[PATCH 1/2] lib: utils/fdt: Respect compatible string fallback priority
Anup Patel
anup at brainfault.org
Wed Feb 19 21:59:52 PST 2025
On Thu, Feb 20, 2025 at 2:13 AM Samuel Holland
<samuel.holland at sifive.com> wrote:
>
> When matching drivers to DT nodes, always match all drivers against the
> first compatible string before considering fallback compatible strings.
> This ensures the most specific match is always selected, regardless of
> the order of the drivers or match structures, as long as no compatible
> string appears in multiple match structures.
>
> Fixes: 1ccc52c427f3 ("lib: utils/fdt: Add helpers for generic driver initialization")
> Signed-off-by: Samuel Holland <samuel.holland at sifive.com>
LGTM.
Reviewed-by: Anup Patel <anup at brainfault.org>
Regards,
Anup
> ---
>
> lib/utils/fdt/fdt_driver.c | 46 +++++++++++++++++++++-----------------
> 1 file changed, 25 insertions(+), 21 deletions(-)
>
> diff --git a/lib/utils/fdt/fdt_driver.c b/lib/utils/fdt/fdt_driver.c
> index f6707c0e..39385ce9 100644
> --- a/lib/utils/fdt/fdt_driver.c
> +++ b/lib/utils/fdt/fdt_driver.c
> @@ -15,39 +15,43 @@ int fdt_driver_init_by_offset(const void *fdt, int nodeoff,
> {
> const struct fdt_driver *driver;
> const struct fdt_match *match;
> - const void *prop;
> - int len, rc;
> + int compat_len, prop_len, rc;
> + const char *compat_str;
>
> if (!fdt_node_is_enabled(fdt, nodeoff))
> return SBI_ENODEV;
>
> - prop = fdt_getprop(fdt, nodeoff, "compatible", &len);
> - if (!prop)
> + compat_str = fdt_getprop(fdt, nodeoff, "compatible", &prop_len);
> + if (!compat_str)
> return SBI_ENODEV;
>
> - while ((driver = *drivers++)) {
> - for (match = driver->match_table; match->compatible; match++) {
> - if (!fdt_stringlist_contains(prop, len, match->compatible))
> - continue;
> + while ((compat_len = strnlen(compat_str, prop_len) + 1) <= prop_len) {
> + for (int i = 0; (driver = drivers[i]); i++)
> + for (match = driver->match_table; match->compatible; match++)
> + if (!memcmp(match->compatible, compat_str, compat_len))
> + goto found;
>
> - if (driver->experimental)
> - sbi_printf("WARNING: %s driver is experimental and may change\n",
> - match->compatible);
> + compat_str += compat_len;
> + prop_len -= compat_len;
> + }
>
> - rc = driver->init(fdt, nodeoff, match);
> - if (rc < 0) {
> - const char *name;
> + return SBI_ENODEV;
>
> - name = fdt_get_name(fdt, nodeoff, NULL);
> - sbi_printf("%s: %s (%s) init failed: %d\n",
> - __func__, name, match->compatible, rc);
> - }
> +found:
> + if (driver->experimental)
> + sbi_printf("WARNING: %s driver is experimental and may change\n",
> + match->compatible);
>
> - return rc;
> - }
> + rc = driver->init(fdt, nodeoff, match);
> + if (rc < 0) {
> + const char *name;
> +
> + name = fdt_get_name(fdt, nodeoff, NULL);
> + sbi_printf("%s: %s (%s) init failed: %d\n",
> + __func__, name, match->compatible, rc);
> }
>
> - return SBI_ENODEV;
> + return rc;
> }
>
> static int fdt_driver_init_scan(const void *fdt,
> --
> 2.47.2
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
More information about the opensbi
mailing list