
On 2/2/22 02:08, AKASHI Takahiro wrote:
With dm-tag feature, any U-Boot subsystem is allowed to associate arbitrary number of data with a particular udevice. This can been see as expanding "struct udevice" without modifying the definition.
As a first user, UEFI subsystem makes use of tags to associate an efi_disk object with a block device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/core/Makefile | 2 +- drivers/core/root.c | 2 + drivers/core/tag.c | 139 ++++++++++++++++++++++++++++++ include/asm-generic/global_data.h | 1 + include/dm/tag.h | 110 +++++++++++++++++++++++ 5 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 drivers/core/tag.c create mode 100644 include/dm/tag.h
diff --git a/drivers/core/Makefile b/drivers/core/Makefile index 5edd4e413576..3742e7574525 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -2,7 +2,7 @@ # # Copyright (c) 2013 Google, Inc
-obj-y += device.o fdtaddr.o lists.o root.o uclass.o util.o +obj-y += device.o fdtaddr.o lists.o root.o uclass.o util.o tag.o obj-$(CONFIG_$(SPL_TPL_)ACPIGEN) += acpi.o obj-$(CONFIG_DEVRES) += devres.o obj-$(CONFIG_$(SPL_)DM_DEVICE_REMOVE) += device-remove.o diff --git a/drivers/core/root.c b/drivers/core/root.c index e3f87956d866..1aa4819ceb6c 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -199,6 +199,8 @@ int dm_init(bool of_live) return ret; }
- INIT_LIST_HEAD((struct list_head *)&gd->dmtag_list);
- return 0; }
diff --git a/drivers/core/tag.c b/drivers/core/tag.c new file mode 100644 index 000000000000..6829bcd8806c --- /dev/null +++ b/drivers/core/tag.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2021 Linaro Limited
Author: AKASHI Takahiro
- */
+#include <malloc.h> +#include <asm/global_data.h> +#include <dm/tag.h> +#include <linux/err.h> +#include <linux/list.h> +#include <linux/types.h>
+struct udevice;
+DECLARE_GLOBAL_DATA_PTR;
+int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr) +{
- struct dmtag_node *node;
- if (!dev || tag >= DM_TAG_COUNT)
return -EINVAL;
- list_for_each_entry(node, &gd->dmtag_list, sibling) {
if (node->dev == dev && node->tag == tag)
return -EEXIST;
- }
- node = calloc(sizeof(*node), 1);
- if (!node)
return -ENOSPC;
- node->dev = dev;
- node->tag = tag;
- node->ptr = ptr;
- list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list);
- return 0;
+}
+int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val) +{
- struct dmtag_node *node;
- if (!dev || tag >= DM_TAG_COUNT)
return -EINVAL;
- list_for_each_entry(node, &gd->dmtag_list, sibling) {
if (node->dev == dev && node->tag == tag)
return -EEXIST;
- }
- node = calloc(sizeof(*node), 1);
- if (!node)
return -ENOSPC;
- node->dev = dev;
- node->tag = tag;
- node->val = val;
- list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list);
- return 0;
+}
+int dev_tag_get_ptr(struct udevice *dev, enum dm_tag_t tag, void **ptrp) +{
- struct dmtag_node *node;
- if (!dev || tag >= DM_TAG_COUNT)
return -EINVAL;
- list_for_each_entry(node, &gd->dmtag_list, sibling) {
if (node->dev == dev && node->tag == tag) {
*ptrp = node->ptr;
return 0;
}
- }
- return -ENOENT;
+}
+int dev_tag_get_val(struct udevice *dev, enum dm_tag_t tag, ulong *valp) +{
- struct dmtag_node *node;
- if (!dev || tag >= DM_TAG_COUNT)
return -EINVAL;
- list_for_each_entry(node, &gd->dmtag_list, sibling) {
if (node->dev == dev && node->tag == tag) {
*valp = node->val;
return 0;
}
- }
- return -ENOENT;
+}
+int dev_tag_del(struct udevice *dev, enum dm_tag_t tag) +{
- struct dmtag_node *node, *tmp;
- if (!dev || tag >= DM_TAG_COUNT)
return -EINVAL;
- list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) {
if (node->dev == dev && node->tag == tag) {
list_del(&node->sibling);
free(node);
return 0;
}
- }
- return -ENOENT;
+}
+int dev_tag_del_all(struct udevice *dev) +{
- struct dmtag_node *node, *tmp;
- bool found = false;
- if (!dev)
return -EINVAL;
- list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) {
if (node->dev == dev) {
list_del(&node->sibling);
free(node);
found = true;
}
- }
- if (found)
return 0;
- return -ENOENT;
+} diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 9f4598f09ee5..b887bef6deef 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -470,6 +470,7 @@ struct global_data { #if CONFIG_IS_ENABLED(EVENT) struct event_state *event_state; #endif
- struct list_head dmtag_list;
This breaks 'make htmldocs'. You have to describe the new element.
Best regards
Heinrich
}; #ifndef DO_DEPS_ONLY static_assert(sizeof(struct global_data) == GD_SIZE); diff --git a/include/dm/tag.h b/include/dm/tag.h new file mode 100644 index 000000000000..54fc31eb1539 --- /dev/null +++ b/include/dm/tag.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2021 Linaro Limited
Author: AKASHI Takahiro
- */
+#ifndef _DM_TAG_H +#define _DM_TAG_H
+#include <linux/list.h> +#include <linux/types.h>
+struct udevice;
+enum dm_tag_t {
- /* EFI_LOADER */
- DM_TAG_EFI = 0,
- DM_TAG_COUNT,
+};
+/**
- dmtag_node
- @sibling: List of dm-tag nodes
- @dev: Associated udevice
- @tag: Tag type
- @ptr: Pointer as a value
- @val: Value
- */
+struct dmtag_node {
- struct list_head sibling;
- struct udevice *dev;
- enum dm_tag_t tag;
- union {
void *ptr;
ulong val;
- };
+};
+/**
- dev_tag_set_ptr() - set a tag's value as a pointer
- @dev: Device to operate
- @tag: Tag type
- @ptr: Pointer to set
- Set the value, @ptr, as of @tag associated with the device, @dev
- Return: 0 on success, -ve on error
- */
+int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr);
+/**
- dev_tag_set_val() set a tag's value as an integer
- @dev: Device to operate
- @tag: Tag type
- @val: Value to set
- Set the value, @val, as of @tag associated with the device, @dev
- Return: on success, -ve on error
- */
+int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val);
+/**
- dev_tag_get_ptr() - get a tag's value as a pointer
- @dev: Device to operate
- @tag: Tag type
- @ptrp: Pointer to tag's value (pointer)
- Get a tag's value as a pointer
- Return: on success, -ve on error
- */
+int dev_tag_get_ptr(struct udevice *dev, enum dm_tag_t tag, void **ptrp);
+/**
- dev_tag_get_val() - get a tag's value as an integer
- @dev: Device to operate
- @tag: Tag type
- @valp: Pointer to tag's value (ulong)
- Get a tag's value as an integer
- Return: 0 on success, -ve on error
- */
+int dev_tag_get_val(struct udevice *dev, enum dm_tag_t tag, ulong *valp);
+/**
- dev_tag_del() - delete a tag
- @dev: Device to operate
- @tag: Tag type
- Delete a tag of @tag associated with the device, @dev
- Return: 0 on success, -ve on error
- */
+int dev_tag_del(struct udevice *dev, enum dm_tag_t tag);
+/**
- dev_tag_del_all() - delete all tags
- @dev: Device to operate
- Delete all the tags associated with the device, @dev
- Return: 0 on success, -ve on error
- */
+int dev_tag_del_all(struct udevice *dev);
+#endif /* _DM_TAG_H */