aboutsummaryrefslogtreecommitdiff
path: root/drivers/core
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2022-05-08 04:39:25 -0600
committerSimon Glass <sjg@chromium.org>2022-06-28 03:09:52 +0100
commit0dfda34ca594c701955cfcb71711a7599f97bae3 (patch)
treebc1741d705ae3a62c98477e510535d3193c97802 /drivers/core
parent930a3ddadebf3660cc3163081671de189300afdd (diff)
downloadu-boot-0dfda34ca594c701955cfcb71711a7599f97bae3.zip
u-boot-0dfda34ca594c701955cfcb71711a7599f97bae3.tar.gz
u-boot-0dfda34ca594c701955cfcb71711a7599f97bae3.tar.bz2
dm: core: Add a way to collect memory usage
Add a function for collecting the amount of memory used by driver model, including devices, uclasses and attached data and tags. This information can provide insights into how to reduce the memory required by driver model. Future work may look at execution speed also. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/core')
-rw-r--r--drivers/core/root.c53
-rw-r--r--drivers/core/tag.c11
2 files changed, 64 insertions, 0 deletions
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 17dd120..f24ddfa 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -449,6 +449,59 @@ void dm_get_stats(int *device_countp, int *uclass_countp)
*uclass_countp = uclass_get_count();
}
+void dev_collect_stats(struct dm_stats *stats, const struct udevice *parent)
+{
+ const struct udevice *dev;
+ int i;
+
+ stats->dev_count++;
+ stats->dev_size += sizeof(struct udevice);
+ stats->dev_name_size += strlen(parent->name) + 1;
+ for (i = 0; i < DM_TAG_ATTACH_COUNT; i++) {
+ int size = dev_get_attach_size(parent, i);
+
+ if (size ||
+ (i == DM_TAG_DRIVER_DATA && parent->driver_data)) {
+ stats->attach_count[i]++;
+ stats->attach_size[i] += size;
+ stats->attach_count_total++;
+ stats->attach_size_total += size;
+ }
+ }
+
+ list_for_each_entry(dev, &parent->child_head, sibling_node)
+ dev_collect_stats(stats, dev);
+}
+
+void uclass_collect_stats(struct dm_stats *stats)
+{
+ struct uclass *uc;
+
+ list_for_each_entry(uc, gd->uclass_root, sibling_node) {
+ int size;
+
+ stats->uc_count++;
+ stats->uc_size += sizeof(struct uclass);
+ size = uc->uc_drv->priv_auto;
+ if (size) {
+ stats->uc_attach_count++;
+ stats->uc_attach_size += size;
+ }
+ }
+}
+
+void dm_get_mem(struct dm_stats *stats)
+{
+ memset(stats, '\0', sizeof(*stats));
+ dev_collect_stats(stats, gd->dm_root);
+ uclass_collect_stats(stats);
+ dev_tag_collect_stats(stats);
+
+ stats->total_size = stats->dev_size + stats->uc_size +
+ stats->attach_size_total + stats->uc_attach_size +
+ stats->tag_size;
+}
+
#ifdef CONFIG_ACPIGEN
static int root_acpi_get_name(const struct udevice *dev, char *out_name)
{
diff --git a/drivers/core/tag.c b/drivers/core/tag.c
index 2299919..2961725 100644
--- a/drivers/core/tag.c
+++ b/drivers/core/tag.c
@@ -6,6 +6,7 @@
#include <malloc.h>
#include <asm/global_data.h>
+#include <dm/root.h>
#include <dm/tag.h>
#include <linux/err.h>
#include <linux/list.h>
@@ -137,3 +138,13 @@ int dev_tag_del_all(struct udevice *dev)
return -ENOENT;
}
+
+void dev_tag_collect_stats(struct dm_stats *stats)
+{
+ struct dmtag_node *node;
+
+ list_for_each_entry(node, &gd->dmtag_list, sibling) {
+ stats->tag_count++;
+ stats->tag_size += sizeof(struct dmtag_node);
+ }
+}