summaryrefslogtreecommitdiff
path: root/drivers/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/core')
-rw-r--r--drivers/core/Kconfig11
-rw-r--r--drivers/core/dump.c73
-rw-r--r--drivers/core/tag.c18
3 files changed, 102 insertions, 0 deletions
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 9b9a7148a1..97dc699e96 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -75,6 +75,17 @@ config DM_DEBUG
help
Say Y here if you want to compile in debug messages in DM core.
+config DM_STATS
+ bool "Collect and show driver model stats"
+ depends on DM
+ default y if SANDBOX
+ help
+ Enable this to collect and display memory statistics about driver
+ model. This can help to figure out where all the memory is going and
+ to find optimisations.
+
+ To display the memory stats, use the 'dm mem' command.
+
config DM_DEVICE_REMOVE
bool "Support device removal"
depends on DM
diff --git a/drivers/core/dump.c b/drivers/core/dump.c
index e434fe0472..1c1f7e4d30 100644
--- a/drivers/core/dump.c
+++ b/drivers/core/dump.c
@@ -172,3 +172,76 @@ void dm_dump_static_driver_info(void)
for (entry = drv; entry != drv + n_ents; entry++)
printf("%-25.25s %p\n", entry->name, entry->plat);
}
+
+void dm_dump_mem(struct dm_stats *stats)
+{
+ int total, total_delta;
+ int i;
+
+ /* Support SPL printf() */
+ printf("Struct sizes: udevice %x, driver %x, uclass %x, uc_driver %x\n",
+ (int)sizeof(struct udevice), (int)sizeof(struct driver),
+ (int)sizeof(struct uclass), (int)sizeof(struct uclass_driver));
+ printf("Memory: device %x:%x, device names %x, uclass %x:%x\n",
+ stats->dev_count, stats->dev_size, stats->dev_name_size,
+ stats->uc_count, stats->uc_size);
+ printf("\n");
+ printf("%-15s %5s %5s %5s %5s %5s\n", "Attached type", "Count",
+ "Size", "Cur", "Tags", "Save");
+ printf("%-15s %5s %5s %5s %5s %5s\n", "---------------", "-----",
+ "-----", "-----", "-----", "-----");
+ total_delta = 0;
+ for (i = 0; i < DM_TAG_ATTACH_COUNT; i++) {
+ int cur_size, new_size, delta;
+
+ cur_size = stats->dev_count * sizeof(struct udevice);
+ new_size = stats->dev_count * (sizeof(struct udevice) -
+ sizeof(void *));
+ /*
+ * Let's assume we can fit each dmtag_node into 32 bits. We can
+ * limit the 'tiny tags' feature to SPL with
+ * CONFIG_SPL_SYS_MALLOC_F_LEN <= 64KB, so needing 14 bits to
+ * point to anything in that region (with 4-byte alignment).
+ * So:
+ * 4 bits for tag
+ * 14 bits for offset of dev
+ * 14 bits for offset of data
+ */
+ new_size += stats->attach_count[i] * sizeof(u32);
+ delta = cur_size - new_size;
+ total_delta += delta;
+ printf("%-16s %5x %6x %6x %6x %6x (%d)\n", tag_get_name(i),
+ stats->attach_count[i], stats->attach_size[i],
+ cur_size, new_size, delta > 0 ? delta : 0, delta);
+ }
+ printf("%-16s %5x %6x\n", "uclass", stats->uc_attach_count,
+ stats->uc_attach_size);
+ printf("%-16s %5x %6x %5s %5s %6x (%d)\n", "Attached total",
+ stats->attach_count_total + stats->uc_attach_count,
+ stats->attach_size_total + stats->uc_attach_size, "", "",
+ total_delta > 0 ? total_delta : 0, total_delta);
+ printf("%-16s %5x %6x\n", "tags", stats->tag_count, stats->tag_size);
+ printf("\n");
+ printf("Total size: %x (%d)\n", stats->total_size, stats->total_size);
+ printf("\n");
+
+ total = stats->total_size;
+ total -= total_delta;
+ printf("With tags: %x (%d)\n", total, total);
+
+ /* Use singly linked lists in struct udevice (3 nodes in each) */
+ total -= sizeof(void *) * 3 * stats->dev_count;
+ printf("- singly-linked: %x (%d)\n", total, total);
+
+ /* Use an index into the struct_driver list instead of a pointer */
+ total = total + stats->dev_count * (1 - sizeof(void *));
+ printf("- driver index: %x (%d)\n", total, total);
+
+ /* Same with the uclass */
+ total = total + stats->dev_count * (1 - sizeof(void *));
+ printf("- uclass index: %x (%d)\n", total, total);
+
+ /* Drop the device name */
+ printf("Drop device name (not SRAM): %x (%d)\n", stats->dev_name_size,
+ stats->dev_name_size);
+}
diff --git a/drivers/core/tag.c b/drivers/core/tag.c
index 2961725b65..a3c5cb7e57 100644
--- a/drivers/core/tag.c
+++ b/drivers/core/tag.c
@@ -16,6 +16,24 @@ struct udevice;
DECLARE_GLOBAL_DATA_PTR;
+static const char *const tag_name[] = {
+ [DM_TAG_PLAT] = "plat",
+ [DM_TAG_PARENT_PLAT] = "parent_plat",
+ [DM_TAG_UC_PLAT] = "uclass_plat",
+
+ [DM_TAG_PRIV] = "priv",
+ [DM_TAG_PARENT_PRIV] = "parent_priv",
+ [DM_TAG_UC_PRIV] = "uclass_priv",
+ [DM_TAG_DRIVER_DATA] = "driver_data",
+
+ [DM_TAG_EFI] = "efi",
+};
+
+const char *tag_get_name(enum dm_tag_t tag)
+{
+ return tag_name[tag];
+}
+
int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr)
{
struct dmtag_node *node;