diff mbox series

[03/31] dm: core: Allow getting some basic stats

Message ID 20211101011734.1614781-4-sjg@chromium.org
State Superseded
Delegated to: Tom Rini
Headers show
Series passage: Define a standard for firmware data flow | expand

Commit Message

Simon Glass Nov. 1, 2021, 1:17 a.m. UTC
Add a function that returns some basic stats about driver model. For now
we only have two.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device.c        | 11 ++++++++++
 drivers/core/root.c          |  7 ++++++
 drivers/core/uclass.c        | 13 ++++++++++++
 include/dm/device.h          | 11 +++++++++-
 include/dm/root.h            |  8 +++++++
 include/dm/uclass-internal.h |  7 ++++++
 test/dm/core.c               | 41 ++++++++++++++++++++++++++++++++++++
 7 files changed, 97 insertions(+), 1 deletion(-)

Comments

Ilias Apalodimas Nov. 1, 2021, 7:07 a.m. UTC | #1
Hi Simon,

How is this related to the bloblist patchset? Is it required or it can split of?

Regards
/Ilias


On Mon, 1 Nov 2021 at 03:19, Simon Glass <sjg@chromium.org> wrote:
>
> Add a function that returns some basic stats about driver model. For now
> we only have two.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>  drivers/core/device.c        | 11 ++++++++++
>  drivers/core/root.c          |  7 ++++++
>  drivers/core/uclass.c        | 13 ++++++++++++
>  include/dm/device.h          | 11 +++++++++-
>  include/dm/root.h            |  8 +++++++
>  include/dm/uclass-internal.h |  7 ++++++
>  test/dm/core.c               | 41 ++++++++++++++++++++++++++++++++++++
>  7 files changed, 97 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/core/device.c b/drivers/core/device.c
> index d7a778a2413..7d327aba49e 100644
> --- a/drivers/core/device.c
> +++ b/drivers/core/device.c
> @@ -723,6 +723,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 26b8195faa3..815173f86eb 100644
> --- a/drivers/core/root.c
> +++ b/drivers/core/root.c
> @@ -26,6 +26,7 @@
>  #include <dm/read.h>
>  #include <dm/root.h>
>  #include <dm/uclass.h>
> +#include <dm/uclass-internal.h>
>  #include <dm/util.h>
>  #include <linux/list.h>
>
> @@ -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 c5a50952fd0..46b3e85fdbb 100644
> --- a/drivers/core/uclass.c
> +++ b/drivers/core/uclass.c
> @@ -638,6 +638,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 3028d002ab0..68e783ea409 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 42510b106ab..780f269db65 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 57c664c6daa..c71d8b1de45 100644
> --- a/include/dm/uclass-internal.h
> +++ b/include/dm/uclass-internal.h
> @@ -294,6 +294,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 c9a7606666c..c76dfdb1651 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);
> --
> 2.33.1.1089.g2158813163f-goog
>
diff mbox series

Patch

diff --git a/drivers/core/device.c b/drivers/core/device.c
index d7a778a2413..7d327aba49e 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -723,6 +723,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 26b8195faa3..815173f86eb 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -26,6 +26,7 @@ 
 #include <dm/read.h>
 #include <dm/root.h>
 #include <dm/uclass.h>
+#include <dm/uclass-internal.h>
 #include <dm/util.h>
 #include <linux/list.h>
 
@@ -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 c5a50952fd0..46b3e85fdbb 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -638,6 +638,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 3028d002ab0..68e783ea409 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 42510b106ab..780f269db65 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 57c664c6daa..c71d8b1de45 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -294,6 +294,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 c9a7606666c..c76dfdb1651 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);