diff options
-rw-r--r-- | drivers/core/root.c | 53 | ||||
-rw-r--r-- | drivers/core/tag.c | 11 | ||||
-rw-r--r-- | include/dm/root.h | 45 | ||||
-rw-r--r-- | include/dm/tag.h | 11 | ||||
-rw-r--r-- | test/dm/core.c | 11 |
5 files changed, 131 insertions, 0 deletions
diff --git a/drivers/core/root.c b/drivers/core/root.c index 17dd1205a3..f24ddfa521 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 22999193a5..2961725b65 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); + } +} diff --git a/include/dm/root.h b/include/dm/root.h index e888fb993c..382f83c7f5 100644 --- a/include/dm/root.h +++ b/include/dm/root.h @@ -9,12 +9,50 @@ #ifndef _DM_ROOT_H_ #define _DM_ROOT_H_ +#include <dm/tag.h> + struct udevice; /* Head of the uclass list if CONFIG_OF_PLATDATA_INST is enabled */ extern struct list_head uclass_head; /** + * struct dm_stats - Information about driver model memory usage + * + * @total_size: All data + * @dev_count: Number of devices + * @dev_size: Size of all devices (just the struct udevice) + * @dev_name_size: Bytes used by device names + * @uc_count: Number of uclasses + * @uc_size: Size of all uclasses (just the struct uclass) + * @tag_count: Number of tags + * @tag_size: Bytes used by all tags + * @uc_attach_count: Number of uclasses with attached data (priv) + * @uc_attach_size: Total size of that attached data + * @attach_count_total: Total number of attached data items for all udevices and + * uclasses + * @attach_size_total: Total number of bytes of attached data + * @attach_count: Number of devices with attached, for each type + * @attach_size: Total number of bytes of attached data, for each type + */ +struct dm_stats { + int total_size; + int dev_count; + int dev_size; + int dev_name_size; + int uc_count; + int uc_size; + int tag_count; + int tag_size; + int uc_attach_count; + int uc_attach_size; + int attach_count_total; + int attach_size_total; + int attach_count[DM_TAG_ATTACH_COUNT]; + int attach_size[DM_TAG_ATTACH_COUNT]; +}; + +/** * dm_root() - Return pointer to the top of the driver tree * * This function returns pointer to the root node of the driver tree, @@ -141,4 +179,11 @@ static inline int dm_remove_devices_flags(uint flags) { return 0; } */ void dm_get_stats(int *device_countp, int *uclass_countp); +/** + * dm_get_mem() - Get stats on memory usage in driver model + * + * @mem: Place to put the information + */ +void dm_get_mem(struct dm_stats *stats); + #endif diff --git a/include/dm/tag.h b/include/dm/tag.h index 9cb5d68f0a..1ea3c9f7af 100644 --- a/include/dm/tag.h +++ b/include/dm/tag.h @@ -10,6 +10,7 @@ #include <linux/list.h> #include <linux/types.h> +struct dm_stats; struct udevice; enum dm_tag_t { @@ -118,4 +119,14 @@ int dev_tag_del(struct udevice *dev, enum dm_tag_t tag); */ int dev_tag_del_all(struct udevice *dev); +/** + * dev_tag_collect_stats() - Collect information on driver model performance + * + * This collects information on how driver model is performing. For now it only + * includes memory usage + * + * @stats: Place to put the collected information + */ +void dev_tag_collect_stats(struct dm_stats *stats); + #endif /* _DM_TAG_H */ diff --git a/test/dm/core.c b/test/dm/core.c index 26e2fd5661..fd4d756972 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -1355,3 +1355,14 @@ static int dm_test_dev_get_attach_bus(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_dev_get_attach_bus, UT_TESTF_SCAN_FDT); + +/* Test getting information about tags attached to bus devices */ +static int dm_test_dev_get_mem(struct unit_test_state *uts) +{ + struct dm_stats stats; + + dm_get_mem(&stats); + + return 0; +} +DM_TEST(dm_test_dev_get_mem, UT_TESTF_SCAN_FDT); |