dm: core: Allow the uclass list to move

At present the uclass list head is in global_data. This is convenient
but with the new of-platdata we need the list head to be declared by
the generated code.

Change this over to be a pointer. Provide a 'static' version in
global_data to retain the current behaviour.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2020-12-19 10:40:17 -07:00
parent 49bbe6eab5
commit 8a715530bb
6 changed files with 19 additions and 11 deletions

View file

@ -613,7 +613,7 @@ static int device_find_by_ofnode(ofnode node, struct udevice **devp)
struct udevice *dev;
int ret;
list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
list_for_each_entry(uc, gd->uclass_root, sibling_node) {
ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node,
&dev);
if (!ret || dev) {
@ -1032,7 +1032,7 @@ int dev_disable_by_path(const char *path)
if (!of_live_active())
return -ENOSYS;
list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
list_for_each_entry(uc, gd->uclass_root, sibling_node) {
ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node, &dev);
if (!ret)
break;

View file

@ -45,8 +45,8 @@ void dm_fixup_for_gd_move(struct global_data *new_gd)
{
/* The sentinel node has moved, so update things that point to it */
if (gd->dm_root) {
new_gd->uclass_root.next->prev = &new_gd->uclass_root;
new_gd->uclass_root.prev->next = &new_gd->uclass_root;
new_gd->uclass_root->next->prev = new_gd->uclass_root;
new_gd->uclass_root->prev->next = new_gd->uclass_root;
}
}
@ -136,7 +136,8 @@ int dm_init(bool of_live)
dm_warn("Virtual root driver already exists!\n");
return -EINVAL;
}
INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) {
fix_drivers();

View file

@ -33,7 +33,7 @@ struct uclass *uclass_find(enum uclass_id key)
* node to the start of the list, or creating a linear array mapping
* id to node.
*/
list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
list_for_each_entry(uc, gd->uclass_root, sibling_node) {
if (uc->uc_drv->id == key)
return uc;
}
@ -84,7 +84,7 @@ static int uclass_add(enum uclass_id id, struct uclass **ucp)
uc->uc_drv = uc_drv;
INIT_LIST_HEAD(&uc->sibling_node);
INIT_LIST_HEAD(&uc->dev_head);
list_add(&uc->sibling_node, &DM_UCLASS_ROOT_NON_CONST);
list_add(&uc->sibling_node, DM_UCLASS_ROOT_NON_CONST);
if (uc_drv->init) {
ret = uc_drv->init(uc);

View file

@ -194,7 +194,13 @@ struct global_data {
/**
* @uclass_root: head of core tree
*/
struct list_head uclass_root;
struct list_head uclass_root_s;
/**
* @uclass_root: pointer to head of core tree, if uclasses are in
* read-only memory and cannot be adjusted to use @uclass_root as a
* list head.
*/
struct list_head *uclass_root;
# if CONFIG_IS_ENABLED(OF_PLATDATA)
/** Dynamic info about the driver */
struct driver_rt *dm_driver_rt;

View file

@ -288,6 +288,7 @@ fdt_addr_t simple_bus_translate(struct udevice *dev, fdt_addr_t addr);
/* Cast away any volatile pointer */
#define DM_ROOT_NON_CONST (((gd_t *)gd)->dm_root)
#define DM_UCLASS_ROOT_NON_CONST (((gd_t *)gd)->uclass_root)
#define DM_UCLASS_ROOT_S_NON_CONST (((gd_t *)gd)->uclass_root_s)
/* device resource management */
#ifdef CONFIG_DEVRES

View file

@ -116,14 +116,14 @@ static int dm_test_autobind(struct unit_test_state *uts)
* device with no children.
*/
ut_assert(dms->root);
ut_asserteq(1, list_count_items(&gd->uclass_root));
ut_asserteq(1, list_count_items(gd->uclass_root));
ut_asserteq(0, list_count_items(&gd->dm_root->child_head));
ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]);
ut_assertok(dm_scan_plat(false));
/* We should have our test class now at least, plus more children */
ut_assert(1 < list_count_items(&gd->uclass_root));
ut_assert(1 < list_count_items(gd->uclass_root));
ut_assert(0 < list_count_items(&gd->dm_root->child_head));
/* Our 3 dm_test_infox children should be bound to the test uclass */
@ -1073,7 +1073,7 @@ static int dm_test_all_have_seq(struct unit_test_state *uts)
struct udevice *dev;
struct uclass *uc;
list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
list_for_each_entry(uc, gd->uclass_root, sibling_node) {
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
if (dev->seq_ == -1)
printf("Device '%s' has no seq (%d)\n",