[PATCH 6/9] dm: core: Support accessing core tags

AKASHI Takahiro takahiro.akashi at linaro.org
Mon May 9 06:52:26 CEST 2022


Hi Simon,

On Sun, May 08, 2022 at 04:39:24AM -0600, Simon Glass wrote:
> At present tag numbers are only allocated for non-core data, meaning that
> the 'core' data, like priv and plat, are accessed through dedicated
> functions.
> 
> For debugging and consistency it is convenient to use tags for this 'core'
> data too. Add support for this, with new tag numbers and functions to
> access the pointer and size for each.
> 
> Update one of the test drivers so that the uclass-private data can be
> tested here.
> 
> There is some code duplication with functions like device_alloc_priv() but
> this is not addressed for now. At some point, some rationalisation may
> help to reduce code size, but more thought it needed on that.
> 
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
> 
>  drivers/core/device.c   | 65 +++++++++++++++++++++++++++++++++
>  drivers/misc/test_drv.c |  4 ++-
>  include/dm/device.h     | 25 +++++++++++++
>  include/dm/tag.h        | 13 ++++++-
>  test/dm/core.c          | 80 +++++++++++++++++++++++++++++++++++++++++
>  tools/dtoc/test_dtoc.py |  4 +++
>  6 files changed, 189 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/core/device.c b/drivers/core/device.c
> index 3ab2583df38..d7936a46732 100644
> --- a/drivers/core/device.c
> +++ b/drivers/core/device.c
> @@ -680,6 +680,71 @@ void *dev_get_parent_priv(const struct udevice *dev)
>  	return dm_priv_to_rw(dev->parent_priv_);
>  }
>  
> +void *dev_get_attach_ptr(const struct udevice *dev, enum dm_tag_t tag)

Why not (enhance and) re-use dev_tag_get_ptr()?
Both functions, at least, share the syntax and even the semantics
from user's viewpoint.

> +{
> +	switch (tag) {
> +	case DM_TAG_PLAT:
> +		return dev_get_plat(dev);
> +	case DM_TAG_PARENT_PLAT:
> +		return dev_get_parent_plat(dev);
> +	case DM_TAG_UC_PLAT:
> +		return dev_get_uclass_plat(dev);
> +	case DM_TAG_PRIV:
> +		return dev_get_priv(dev);
> +	case DM_TAG_PARENT_PRIV:
> +		return dev_get_parent_priv(dev);
> +	case DM_TAG_UC_PRIV:
> +		return dev_get_uclass_priv(dev);
> +	default:
> +		return NULL;
> +	}
> +}
> +
> +int dev_get_attach_size(const struct udevice *dev, enum dm_tag_t tag)
> +{
> +	const struct udevice *parent = dev_get_parent(dev);
> +	const struct uclass *uc = dev->uclass;
> +	const struct uclass_driver *uc_drv = uc->uc_drv;
> +	const struct driver *parent_drv = NULL;
> +	int size = 0;
> +
> +	if (parent)
> +		parent_drv = parent->driver;
> +
> +	switch (tag) {
> +	case DM_TAG_PLAT:
> +		size = dev->driver->plat_auto;
> +		break;
> +	case DM_TAG_PARENT_PLAT:
> +		if (parent) {
> +			size = parent_drv->per_child_plat_auto;
> +			if (!size)
> +				size = parent->uclass->uc_drv->per_child_plat_auto;
> +		}
> +		break;
> +	case DM_TAG_UC_PLAT:
> +		size = uc_drv->per_device_plat_auto;
> +		break;
> +	case DM_TAG_PRIV:
> +		size = dev->driver->priv_auto;
> +		break;
> +	case DM_TAG_PARENT_PRIV:
> +		if (parent) {
> +			size = parent_drv->per_child_auto;
> +			if (!size)
> +				size = parent->uclass->uc_drv->per_child_auto;
> +		}
> +		break;
> +	case DM_TAG_UC_PRIV:
> +		size = uc_drv->per_device_auto;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return size;
> +}
> +
>  static int device_get_device_tail(struct udevice *dev, int ret,
>  				  struct udevice **devp)
>  {
> diff --git a/drivers/misc/test_drv.c b/drivers/misc/test_drv.c
> index b6df1189032..927618256f0 100644
> --- a/drivers/misc/test_drv.c
> +++ b/drivers/misc/test_drv.c
> @@ -108,7 +108,9 @@ UCLASS_DRIVER(testbus) = {
>  	.child_pre_probe = testbus_child_pre_probe_uclass,
>  	.child_post_probe = testbus_child_post_probe_uclass,
>  
> -	/* This is for dtoc testing only */
> +	.per_device_auto   = sizeof(struct dm_test_uclass_priv),
> +
> +	/* Note: this is for dtoc testing as well as tags*/
>  	.per_device_plat_auto   = sizeof(struct dm_test_uclass_plat),
>  };
>  
> diff --git a/include/dm/device.h b/include/dm/device.h
> index 5bdb10653f8..12c6ba37ff3 100644
> --- a/include/dm/device.h
> +++ b/include/dm/device.h
> @@ -11,6 +11,7 @@
>  #define _DM_DEVICE_H
>  
>  #include <dm/ofnode.h>
> +#include <dm/tag.h>
>  #include <dm/uclass-id.h>
>  #include <fdtdec.h>
>  #include <linker_lists.h>
> @@ -546,6 +547,30 @@ void *dev_get_parent_priv(const struct udevice *dev);
>   */
>  void *dev_get_uclass_priv(const struct udevice *dev);
>  
> +/**
> + * dev_get_attach_ptr() - Get the value of an attached pointed tag
> + *
> + * The tag is assumed to hold a pointer, if it exists
> + *
> + * @dev: Device to look at
> + * @tag: Tag to access
> + * @return value of tag, or NULL if there is no tag of this type
> + */
> +void *dev_get_attach_ptr(const struct udevice *dev, enum dm_tag_t tag);
> +
> +/**
> + * dev_get_attach_size() - Get the size of an attached tag
> + *
> + * Core tags have an automatic-allocation mechanism where the allocated size is
> + * defined by the device, parent or uclass. This returns the size associated
> + * with a particular tag
> + *
> + * @dev: Device to look at
> + * @tag: Tag to access
> + * @return size of auto-allocated data, 0 if none
> + */
> +int dev_get_attach_size(const struct udevice *dev, enum dm_tag_t tag);
> +
>  /**
>   * dev_get_parent() - Get the parent of a device
>   *
> diff --git a/include/dm/tag.h b/include/dm/tag.h
> index 54fc31eb153..9cb5d68f0a3 100644
> --- a/include/dm/tag.h
> +++ b/include/dm/tag.h
> @@ -13,8 +13,19 @@
>  struct udevice;
>  
>  enum dm_tag_t {
> +	/* Types of core tags that can be attached to devices */
> +	DM_TAG_PLAT,
> +	DM_TAG_PARENT_PLAT,
> +	DM_TAG_UC_PLAT,
> +
> +	DM_TAG_PRIV,
> +	DM_TAG_PARENT_PRIV,
> +	DM_TAG_UC_PRIV,
> +	DM_TAG_DRIVER_DATA,
> +	DM_TAG_ATTACH_COUNT,
> +
>  	/* EFI_LOADER */
> -	DM_TAG_EFI = 0,
> +	DM_TAG_EFI = DM_TAG_ATTACH_COUNT,

What does DM_TAG_ATTACH_COUNT mean?

-Takahiro Akashi

>  
>  	DM_TAG_COUNT,
>  };
> diff --git a/test/dm/core.c b/test/dm/core.c
> index ebd504427d1..26e2fd56619 100644
> --- a/test/dm/core.c
> +++ b/test/dm/core.c
> @@ -1275,3 +1275,83 @@ static int dm_test_uclass_find_device(struct unit_test_state *uts)
>  	return 0;
>  }
>  DM_TEST(dm_test_uclass_find_device, UT_TESTF_SCAN_FDT);
> +
> +/* Test getting information about tags attached to devices */
> +static int dm_test_dev_get_attach(struct unit_test_state *uts)
> +{
> +	struct udevice *dev;
> +
> +	ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev));
> +	ut_asserteq_str("a-test", dev->name);
> +
> +	ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_PLAT));
> +	ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_PRIV));
> +	ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_UC_PRIV));
> +	ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_UC_PLAT));
> +	ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_PARENT_PLAT));
> +	ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_PARENT_PRIV));
> +
> +	ut_asserteq(sizeof(struct dm_test_pdata),
> +		    dev_get_attach_size(dev, DM_TAG_PLAT));
> +	ut_asserteq(sizeof(struct dm_test_priv),
> +		    dev_get_attach_size(dev, DM_TAG_PRIV));
> +	ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_UC_PRIV));
> +	ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_UC_PLAT));
> +	ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_PARENT_PLAT));
> +	ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_PARENT_PRIV));
> +
> +	return 0;
> +}
> +DM_TEST(dm_test_dev_get_attach, UT_TESTF_SCAN_FDT);
> +
> +/* Test getting information about tags attached to bus devices */
> +static int dm_test_dev_get_attach_bus(struct unit_test_state *uts)
> +{
> +	struct udevice *dev, *child;
> +
> +	ut_assertok(uclass_first_device_err(UCLASS_TEST_BUS, &dev));
> +	ut_asserteq_str("some-bus", dev->name);
> +
> +	ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_PLAT));
> +	ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_PRIV));
> +	ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_UC_PRIV));
> +	ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_UC_PLAT));
> +	ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_PARENT_PLAT));
> +	ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_PARENT_PRIV));
> +
> +	ut_asserteq(sizeof(struct dm_test_pdata),
> +		    dev_get_attach_size(dev, DM_TAG_PLAT));
> +	ut_asserteq(sizeof(struct dm_test_priv),
> +		    dev_get_attach_size(dev, DM_TAG_PRIV));
> +	ut_asserteq(sizeof(struct dm_test_uclass_priv),
> +		    dev_get_attach_size(dev, DM_TAG_UC_PRIV));
> +	ut_asserteq(sizeof(struct dm_test_uclass_plat),
> +		    dev_get_attach_size(dev, DM_TAG_UC_PLAT));
> +	ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_PARENT_PLAT));
> +	ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_PARENT_PRIV));
> +
> +	/* Now try the child of the bus */
> +	ut_assertok(device_first_child_err(dev, &child));
> +	ut_asserteq_str("c-test at 5", child->name);
> +
> +	ut_assertnonnull(dev_get_attach_ptr(child, DM_TAG_PLAT));
> +	ut_assertnonnull(dev_get_attach_ptr(child, DM_TAG_PRIV));
> +	ut_assertnull(dev_get_attach_ptr(child, DM_TAG_UC_PRIV));
> +	ut_assertnull(dev_get_attach_ptr(child, DM_TAG_UC_PLAT));
> +	ut_assertnonnull(dev_get_attach_ptr(child, DM_TAG_PARENT_PLAT));
> +	ut_assertnonnull(dev_get_attach_ptr(child, DM_TAG_PARENT_PRIV));
> +
> +	ut_asserteq(sizeof(struct dm_test_pdata),
> +		    dev_get_attach_size(child, DM_TAG_PLAT));
> +	ut_asserteq(sizeof(struct dm_test_priv),
> +		    dev_get_attach_size(child, DM_TAG_PRIV));
> +	ut_asserteq(0, dev_get_attach_size(child, DM_TAG_UC_PRIV));
> +	ut_asserteq(0, dev_get_attach_size(child, DM_TAG_UC_PLAT));
> +	ut_asserteq(sizeof(struct dm_test_parent_plat),
> +		    dev_get_attach_size(child, DM_TAG_PARENT_PLAT));
> +	ut_asserteq(sizeof(struct dm_test_parent_data),
> +		    dev_get_attach_size(child, DM_TAG_PARENT_PRIV));
> +
> +	return 0;
> +}
> +DM_TEST(dm_test_dev_get_attach_bus, UT_TESTF_SCAN_FDT);
> diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
> index 8bac2076214..879ca2ab2bf 100755
> --- a/tools/dtoc/test_dtoc.py
> +++ b/tools/dtoc/test_dtoc.py
> @@ -618,6 +618,9 @@ u8 _denx_u_boot_test_bus_priv_some_bus[sizeof(struct dm_test_priv)]
>  #include <dm/test.h>
>  u8 _denx_u_boot_test_bus_ucplat_some_bus[sizeof(struct dm_test_uclass_plat)]
>  \t__attribute__ ((section (".priv_data")));
> +#include <dm/test.h>
> +u8 _denx_u_boot_test_bus_uc_priv_some_bus[sizeof(struct dm_test_uclass_priv)]
> +	__attribute__ ((section (".priv_data")));
>  #include <test.h>
>  
>  DM_DEVICE_INST(some_bus) = {
> @@ -628,6 +631,7 @@ DM_DEVICE_INST(some_bus) = {
>  \t.driver_data\t= DM_TEST_TYPE_FIRST,
>  \t.priv_\t\t= _denx_u_boot_test_bus_priv_some_bus,
>  \t.uclass\t\t= DM_UCLASS_REF(testbus),
> +\t.uclass_priv_ = _denx_u_boot_test_bus_uc_priv_some_bus,
>  \t.uclass_node\t= {
>  \t\t.prev = &DM_UCLASS_REF(testbus)->dev_head,
>  \t\t.next = &DM_UCLASS_REF(testbus)->dev_head,
> -- 
> 2.36.0.512.ge40c2bad7a-goog
> 


More information about the U-Boot mailing list