From d3195c112354ffa9e25651057b491623d760d1a2 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 3 Mar 2017 18:16:06 +0100 Subject: [f] revise DM_ALLOW_MULTIPLE_DRIVERS for SJG-comments --- drivers/core/Kconfig | 1 - drivers/core/lists.c | 87 +++++++++++++++++++++++++++++----------------------- include/dm/lists.h | 6 ++++ 3 files changed, 55 insertions(+), 39 deletions(-) diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index 913101ce87..4af8505695 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -34,7 +34,6 @@ config DM_WARN config DM_ALLOW_MULTIPLE_DRIVERS bool "Allow multiple drivers to bind for one node" depends on DM - default n help The driver model in U-Boot originally did not allow multiple drivers to bind for a single device node. diff --git a/drivers/core/lists.c b/drivers/core/lists.c index 912469381b..af1657c6e2 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -126,15 +126,55 @@ static int driver_check_compatible(const struct udevice_id *of_match, return -ENOENT; } -int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, - struct udevice **devp) +static bool driver_bind_next(struct driver **entryp, struct udevice *parent, + const char *name, int offset, const char *compat, + struct udevice **devp) { struct driver *driver = ll_entry_start(struct driver, driver); const int n_ents = ll_entry_count(struct driver, driver); + struct driver *entry = *entryp; + struct udevice *dev; const struct udevice_id *id; + bool found = false; + int ret; + + for (; entry != driver + n_ents; entry++) { + ret = driver_check_compatible(entry->of_match, &id, + compat); + if (!ret) + break; + } + + if (entry == driver + n_ents) { + *entryp = NULL; + return false; + } + + dm_dbg(" - found match at '%s'\n", entry->name); + ret = device_bind_with_driver_data(parent, entry, name, + id->data, offset, &dev); + if (ret == -ENODEV) + dm_dbg("Driver '%s' refuses to bind\n", entry->name); + + if (ret) { + dm_warn("Error binding driver '%s': %d\n", entry->name, ret); + } else { + found = true; + if (devp) + *devp = dev; + } + + *entryp = entry + 1; /* advance onto the next element */ + return found; +} + +int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, + struct udevice **devp) +{ + struct driver *driver = ll_entry_start(struct driver, driver); struct driver *entry; - struct udevice *dev; bool found = false; + bool allow_multiple = CONFIG_IS_ENABLED(DM_ALLOW_MULTIPLE_DRIVERS); const char *name, *compat_list, *compat; int compat_length, i; int result = 0; @@ -166,42 +206,13 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, dm_dbg(" - attempt to match compatible string '%s'\n", compat); - entry = driver; -#if defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS) -allow_more_matches: -#endif - for (; entry != driver + n_ents; entry++) { - ret = driver_check_compatible(entry->of_match, &id, - compat); - if (!ret) - break; - } - if (entry == driver + n_ents) - continue; - - dm_dbg(" - found match at '%s'\n", entry->name); - ret = device_bind_with_driver_data(parent, entry, name, - id->data, offset, &dev); - if (ret == -ENODEV) { - dm_dbg("Driver '%s' refuses to bind\n", entry->name); - continue; - } - if (ret) { - dm_warn("Error binding driver '%s': %d\n", entry->name, - ret); - return ret; - } else { - found = true; - if (devp) - *devp = dev; -#if defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS) - else { - entry++; - goto allow_more_matches; - } -#endif + for (entry = driver; entry;) { + found = driver_bind_next(&entry, parent, name, + offset, compat, devp); + + if (found && (devp || !allow_multiple)) + return 0; } - break; } if (!found && !result && ret != -ENODEV) diff --git a/include/dm/lists.h b/include/dm/lists.h index 4513d6a311..e300f4f4c9 100644 --- a/include/dm/lists.h +++ b/include/dm/lists.h @@ -65,6 +65,12 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, * * This binds a new device to a driver. * + * If DM_ALLOW_MULTIPLE_DRIVERS is configured and devp is NULL, it + * will continue through the list of drivers and bind all drivers that + * match the compatible string. If not configured or devp is + * non-NULL, it will stop after the first driver that successfully + * binds. + * * @parent: Parent device * @drv_name: Name of driver to attach to this parent * @dev_name: Name of the new device thus created -- cgit v1.2.3