From: Simon Glass Date: Fri, 17 Dec 2021 03:59:32 +0000 (-0700) Subject: dm: core: Allow getting some basic stats X-Git-Url: http://git.dujemihanovic.xyz/login.html?a=commitdiff_plain;h=6476c4d9818beac88610f18ff3c3cb05c7a1f33b;p=u-boot.git dm: core: Allow getting some basic stats Add a function that returns some basic stats about driver model. For now we only have two. Signed-off-by: Simon Glass --- diff --git a/drivers/core/device.c b/drivers/core/device.c index 74374ff881..4873c47d10 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -739,6 +739,17 @@ int device_get_child_count(const struct udevice *parent) return count; } +int device_get_decendent_count(const struct udevice *parent) +{ + const struct udevice *dev; + int count = 1; + + list_for_each_entry(dev, &parent->child_head, sibling_node) + count += device_get_decendent_count(dev); + + return count; +} + int device_find_child_by_seq(const struct udevice *parent, int seq, struct udevice **devp) { diff --git a/drivers/core/root.c b/drivers/core/root.c index 26b8195faa..815173f86e 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -407,6 +408,12 @@ int dm_init_and_scan(bool pre_reloc_only) return 0; } +void dm_get_stats(int *device_countp, int *uclass_countp) +{ + *device_countp = device_get_decendent_count(gd->dm_root); + *uclass_countp = uclass_get_count(); +} + #ifdef CONFIG_ACPIGEN static int root_acpi_get_name(const struct udevice *dev, char *out_name) { diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 2aa2143077..336ea8d243 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -643,6 +643,19 @@ int uclass_next_device_check(struct udevice **devp) return device_probe(*devp); } +int uclass_get_count(void) +{ + const struct uclass *uc; + int count = 0; + + if (gd->dm_root) { + list_for_each_entry(uc, gd->uclass_root, sibling_node) + count++; + } + + return count; +} + int uclass_first_device_drvdata(enum uclass_id id, ulong driver_data, struct udevice **devp) { diff --git a/include/dm/device.h b/include/dm/device.h index 544734ecb3..cf785f7ae2 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -593,7 +593,7 @@ int device_get_child(const struct udevice *parent, int index, struct udevice **devp); /** - * device_get_child_count() - Get the available child count of a device + * device_get_child_count() - Get the child count of a device * * Returns the number of children to a device. * @@ -601,6 +601,15 @@ int device_get_child(const struct udevice *parent, int index, */ int device_get_child_count(const struct udevice *parent); +/** + * device_get_decendent_count() - Get the total number of decendents of a device + * + * Returns the total number of decendents, including all children + * + * @parent: Parent device to check + */ +int device_get_decendent_count(const struct udevice *parent); + /** * device_find_child_by_seq() - Find a child device based on a sequence * diff --git a/include/dm/root.h b/include/dm/root.h index 42510b106a..780f269db6 100644 --- a/include/dm/root.h +++ b/include/dm/root.h @@ -131,4 +131,12 @@ int dm_remove_devices_flags(uint flags); static inline int dm_remove_devices_flags(uint flags) { return 0; } #endif +/** + * dm_get_stats() - Get some stats for driver mode + * + * @device_countp: Returns total number of devices that are bound + * @uclass_countp: Returns total number of uclasses in use + */ +void dm_get_stats(int *device_countp, int *uclass_countp); + #endif diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h index 49808c5c85..fb0edcc296 100644 --- a/include/dm/uclass-internal.h +++ b/include/dm/uclass-internal.h @@ -306,6 +306,13 @@ int uclass_pre_remove_device(struct udevice *dev); static inline int uclass_pre_remove_device(struct udevice *dev) { return 0; } #endif +/** + * uclass_get_count() - Get the number of uclasses + * + * Returns the number of uclasses instantiated in driver model + */ +int uclass_get_count(void); + /** * uclass_find() - Find uclass by its id * diff --git a/test/dm/core.c b/test/dm/core.c index c9a7606666..c76dfdb165 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -307,11 +307,15 @@ static int dm_test_lifecycle(struct unit_test_state *uts) { int op_count[DM_TEST_OP_COUNT]; struct udevice *dev, *test_dev; + int start_dev_count, start_uc_count; + int dev_count, uc_count; int pingret; int ret; memcpy(op_count, dm_testdrv_op_count, sizeof(op_count)); + dm_get_stats(&start_dev_count, &start_uc_count); + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, &dev)); ut_assert(dev); @@ -319,6 +323,11 @@ static int dm_test_lifecycle(struct unit_test_state *uts) == op_count[DM_TEST_OP_BIND] + 1); ut_assert(!dev_get_priv(dev)); + /* We should have one more device */ + dm_get_stats(&dev_count, &uc_count); + ut_asserteq(start_dev_count + 1, dev_count); + ut_asserteq(start_uc_count, uc_count); + /* Probe the device - it should fail allocating private data */ uts->force_fail_alloc = 1; ret = device_probe(dev); @@ -353,6 +362,11 @@ static int dm_test_lifecycle(struct unit_test_state *uts) ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); + /* We should have one less device */ + dm_get_stats(&dev_count, &uc_count); + ut_asserteq(start_dev_count, dev_count); + ut_asserteq(start_uc_count, uc_count); + return 0; } DM_TEST(dm_test_lifecycle, UT_TESTF_SCAN_PDATA | UT_TESTF_PROBE_TEST); @@ -526,17 +540,31 @@ DM_TEST(dm_test_leak, 0); /* Test uclass init/destroy methods */ static int dm_test_uclass(struct unit_test_state *uts) { + int dev_count, uc_count; struct uclass *uc; + /* We should have just the root device and uclass */ + dm_get_stats(&dev_count, &uc_count); + ut_asserteq(1, dev_count); + ut_asserteq(1, uc_count); + ut_assertok(uclass_get(UCLASS_TEST, &uc)); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_DESTROY]); ut_assert(uclass_get_priv(uc)); + dm_get_stats(&dev_count, &uc_count); + ut_asserteq(1, dev_count); + ut_asserteq(2, uc_count); + ut_assertok(uclass_destroy(uc)); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_DESTROY]); + dm_get_stats(&dev_count, &uc_count); + ut_asserteq(1, dev_count); + ut_asserteq(1, uc_count); + return 0; } DM_TEST(dm_test_uclass, 0); @@ -1217,3 +1245,16 @@ static int dm_test_dma_offset(struct unit_test_state *uts) } DM_TEST(dm_test_dma_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); #endif + +/* Test dm_get_stats() */ +static int dm_test_get_stats(struct unit_test_state *uts) +{ + int dev_count, uc_count; + + dm_get_stats(&dev_count, &uc_count); + ut_assert(dev_count > 50); + ut_assert(uc_count > 30); + + return 0; +} +DM_TEST(dm_test_get_stats, UT_TESTF_SCAN_FDT);