Message ID | 20210902230442.1515531-2-saravanak@google.com |
---|---|
State | New |
Headers | show |
Series | Fix simple-bus issues with fw_devlink | expand |
On Fri, 3 Sept 2021 at 01:04, Saravana Kannan <saravanak@google.com> wrote: > > fw_devlink could end up creating device links for bus only devices. > However, bus only devices don't get probed and can block probe() or > sync_state() [1] call backs of other devices. To avoid this, set up > these devices to get probed by the simple-pm-bus. > > [1] - https://lore.kernel.org/lkml/CAPDyKFo9Bxremkb1dDrr4OcXSpE0keVze94Cm=zrkOVxHHxBmQ@mail.gmail.com/ > Signed-off-by: Saravana Kannan <saravanak@google.com> > Tested-by: Saravana Kannan <saravanak@google.com> Again, this looks like a nice solution to the problem. One question though. The Kconfig SIMPLE_PM_BUS, should probably be "default y" - or something along those lines to make sure fw_devlink works as expected. Kind regards Uffe > --- > drivers/of/platform.c | 45 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 45 insertions(+) > > diff --git a/drivers/of/platform.c b/drivers/of/platform.c > index 74afbb7a4f5e..b010e2310131 100644 > --- a/drivers/of/platform.c > +++ b/drivers/of/platform.c > @@ -97,6 +97,48 @@ static void of_device_make_bus_id(struct device *dev) > } > } > > +/** > + * of_match_only_simple_bus - Check if a device node is only a simple bus > + * @np: device node to check > + * > + * A simple bus in this context is defined as a transparent bus whose child > + * devices are automatically populated but has no hardware specific > + * functionality. > + * > + * Returns true if the device node is only a simple bus and can never match > + * with any other specific driver. Otherwise, returns false. > + */ > +static bool of_match_only_simple_bus(struct device_node *np) > +{ > + /* List of buses that don't have an explicit driver. */ > + static const char * const of_simple_bus_table[] = { > + "simple-bus", > + "simple-mfd", > + "isa", > + "arm,amba-bus", > + }; > + const char *cp; > + struct property *prop; > + int i; > + > + prop = of_find_property(np, "compatible", NULL); > + for (cp = of_prop_next_string(prop, NULL); cp; > + cp = of_prop_next_string(prop, cp)) { > + bool match = false; > + const char *bus = of_simple_bus_table[i]; > + > + for (i = 0; i < ARRAY_SIZE(of_simple_bus_table); i++) > + if (!of_compat_cmp(cp, bus, strlen(bus))) { > + match = true; > + break; > + } > + if (!match) > + return false; > + } > + > + return true; > +} > + > /** > * of_device_alloc - Allocate and initialize an of_device > * @np: device node to assign to device > @@ -143,6 +185,9 @@ struct platform_device *of_device_alloc(struct device_node *np, > dev->dev.fwnode = &np->fwnode; > dev->dev.parent = parent ? : &platform_bus; > > + if (of_match_only_simple_bus(np)) > + dev->driver_override = "simple-pm-bus"; > + > if (bus_id) > dev_set_name(&dev->dev, "%s", bus_id); > else > -- > 2.33.0.153.gba50c8fa24-goog >
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 74afbb7a4f5e..b010e2310131 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -97,6 +97,48 @@ static void of_device_make_bus_id(struct device *dev) } } +/** + * of_match_only_simple_bus - Check if a device node is only a simple bus + * @np: device node to check + * + * A simple bus in this context is defined as a transparent bus whose child + * devices are automatically populated but has no hardware specific + * functionality. + * + * Returns true if the device node is only a simple bus and can never match + * with any other specific driver. Otherwise, returns false. + */ +static bool of_match_only_simple_bus(struct device_node *np) +{ + /* List of buses that don't have an explicit driver. */ + static const char * const of_simple_bus_table[] = { + "simple-bus", + "simple-mfd", + "isa", + "arm,amba-bus", + }; + const char *cp; + struct property *prop; + int i; + + prop = of_find_property(np, "compatible", NULL); + for (cp = of_prop_next_string(prop, NULL); cp; + cp = of_prop_next_string(prop, cp)) { + bool match = false; + const char *bus = of_simple_bus_table[i]; + + for (i = 0; i < ARRAY_SIZE(of_simple_bus_table); i++) + if (!of_compat_cmp(cp, bus, strlen(bus))) { + match = true; + break; + } + if (!match) + return false; + } + + return true; +} + /** * of_device_alloc - Allocate and initialize an of_device * @np: device node to assign to device @@ -143,6 +185,9 @@ struct platform_device *of_device_alloc(struct device_node *np, dev->dev.fwnode = &np->fwnode; dev->dev.parent = parent ? : &platform_bus; + if (of_match_only_simple_bus(np)) + dev->driver_override = "simple-pm-bus"; + if (bus_id) dev_set_name(&dev->dev, "%s", bus_id); else