From: Saravana Kannan saravanak@google.com
stable inclusion from stable-5.10.75 commit d5f13bbb51046537b2c2b9868177fb8fe8a6a6e9 bugzilla: 182987 https://gitee.com/openeuler/kernel/issues/I4I3MP
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 98e96cf80045a383fcc47c58dd4e87b3ae587b3e upstream.
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, probe these devices using the simple-pm-bus driver.
However, there are instances of devices that are not simple buses (they get probed by their specific drivers) that also list the "simple-bus" (or other bus only compatible strings) in their compatible property to automatically populate their child devices. We still want these devices to get probed by their specific drivers. So, we make sure this driver only probes devices that are only buses.
[1] - https://lore.kernel.org/lkml/CAPDyKFo9Bxremkb1dDrr4OcXSpE0keVze94Cm=zrkOVxHH...
Fixes: c442a0d18744 ("driver core: Set fw_devlink to "permissive" behavior by default") Cc: stable stable@vger.kernel.org Cc: Rob Herring robh+dt@kernel.org Tested-by: Saravana Kannan saravanak@google.com Tested-by: Ulf Hansson ulf.hansson@linaro.org Tested-by: Geert Uytterhoeven geert+renesas@glider.be Tested-by: Damien Le Moal damien.lemoal@wdc.com Signed-off-by: Saravana Kannan saravanak@google.com Link: https://lore.kernel.org/r/20210929000735.585237-2-saravanak@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Chen Jun chenjun102@huawei.com Acked-by: Weilong Chen chenweilong@huawei.com
Signed-off-by: Chen Jun chenjun102@huawei.com --- drivers/bus/simple-pm-bus.c | 39 ++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c index c5eb46cbf388..244b8f3b38b4 100644 --- a/drivers/bus/simple-pm-bus.c +++ b/drivers/bus/simple-pm-bus.c @@ -16,7 +16,33 @@
static int simple_pm_bus_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + const struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + const struct of_device_id *match; + + /* + * Allow user to use driver_override to bind this driver to a + * transparent bus device which has a different compatible string + * that's not listed in simple_pm_bus_of_match. We don't want to do any + * of the simple-pm-bus tasks for these devices, so return early. + */ + if (pdev->driver_override) + return 0; + + match = of_match_device(dev->driver->of_match_table, dev); + /* + * These are transparent bus devices (not simple-pm-bus matches) that + * have their child nodes populated automatically. So, don't need to + * do anything more. We only match with the device if this driver is + * the most specific match because we don't want to incorrectly bind to + * a device that has a more specific driver. + */ + if (match && match->data) { + if (of_property_match_string(np, "compatible", match->compatible) == 0) + return 0; + else + return -ENODEV; + }
dev_dbg(&pdev->dev, "%s\n", __func__);
@@ -30,14 +56,25 @@ static int simple_pm_bus_probe(struct platform_device *pdev)
static int simple_pm_bus_remove(struct platform_device *pdev) { + const void *data = of_device_get_match_data(&pdev->dev); + + if (pdev->driver_override || data) + return 0; + dev_dbg(&pdev->dev, "%s\n", __func__);
pm_runtime_disable(&pdev->dev); return 0; }
+#define ONLY_BUS ((void *) 1) /* Match if the device is only a bus. */ + static const struct of_device_id simple_pm_bus_of_match[] = { { .compatible = "simple-pm-bus", }, + { .compatible = "simple-bus", .data = ONLY_BUS }, + { .compatible = "simple-mfd", .data = ONLY_BUS }, + { .compatible = "isa", .data = ONLY_BUS }, + { .compatible = "arm,amba-bus", .data = ONLY_BUS }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match);