From 59e0dd5bef6cda8cbe4abcfab145c562026a86c0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 30 Mar 2023 15:26:13 +0200 Subject: [PATCH] treewide: Fix probing of devices in DT overlays commit 1a50d9403fb90cbe4dea0ec9fd0351d2ecbd8924 upstream. When loading a DT overlay that creates a device, the device is not probed, unless the DT overlay is unloaded and reloaded again. After the recent refactoring to improve fw_devlink, it no longer depends on the "compatible" property to identify which device tree nodes will become struct devices. fw_devlink now picks up dangling consumers (consumers pointing to descendent device tree nodes of a device that aren't converted to child devices) when a device is successfully bound to a driver. See __fw_devlink_pickup_dangling_consumers(). However, during DT overlay, a device's device tree node can have sub-nodes added/removed without unbinding/rebinding the driver. This difference in behavior between the normal device instantiation and probing flow vs. the DT overlay flow has a bunch of implications that are pointed out elsewhere[1]. One of them is that the fw_devlink logic to pick up dangling consumers is never exercised. This patch solves the fw_devlink issue by marking all DT nodes added by DT overlays with FWNODE_FLAG_NOT_DEVICE (fwnode that won't become device), and by clearing the flag when a struct device is actually created for the DT node. This way, fw_devlink knows not to have consumers waiting on these newly added DT nodes, and to propagate the dependency to an ancestor DT node that has the corresponding struct device. Based on a patch by Saravana Kannan, which covered only platform and spi devices. [1] https://lore.kernel.org/r/CAGETcx_bkuFaLCiPrAWCPQz+w79ccDp6=9e881qmK=vx3hBMyg@mail.gmail.com Fixes: 4a032827daa89350 ("of: property: Simplify of_link_to_phandle()") Link: https://lore.kernel.org/r/CAGETcx_+rhHvaC_HJXGrr5_WAd2+k5f=rWYnkCZ6z5bGX-wj4w@mail.gmail.com Signed-off-by: Geert Uytterhoeven Acked-by: Mark Brown Acked-by: Wolfram Sang # for I2C Acked-by: Shawn Guo Acked-by: Saravana Kannan Tested-by: Ivan Bornyakov Link: https://lore.kernel.org/r/e1fa546682ea4c8474ff997ab6244c5e11b6f8bc.1680182615.git.geert+renesas@glider.be Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- drivers/bus/imx-weim.c | 6 ++++++ drivers/i2c/i2c-core-of.c | 5 +++++ drivers/of/dynamic.c | 1 + drivers/of/platform.c | 5 +++++ drivers/spi/spi.c | 5 +++++ 5 files changed, 22 insertions(+) diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c index 55d917bd1f3f..64f9eacd1b38 100644 --- a/drivers/bus/imx-weim.c +++ b/drivers/bus/imx-weim.c @@ -331,6 +331,12 @@ static int of_weim_notify(struct notifier_block *nb, unsigned long action, "Failed to setup timing for '%pOF'\n", rd->dn); if (!of_node_check_flag(rd->dn, OF_POPULATED)) { + /* + * Clear the flag before adding the device so that + * fw_devlink doesn't skip adding consumers to this + * device. + */ + rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE; if (!of_platform_device_create(rd->dn, NULL, &pdev->dev)) { dev_err(&pdev->dev, "Failed to create child device '%pOF'\n", diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index 3ed74aa4b44b..1073f82d5dd4 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -244,6 +244,11 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; } + /* + * Clear the flag before adding the device so that fw_devlink + * doesn't skip adding consumers to this device. + */ + rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE; client = of_i2c_register_device(adap, rd->dn); if (IS_ERR(client)) { dev_err(&adap->dev, "failed to create client for '%pOF'\n", diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 4e436f2d13ae..95501b77ef31 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -225,6 +225,7 @@ static void __of_attach_node(struct device_node *np) np->sibling = np->parent->child; np->parent->child = np; of_node_clear_flag(np, OF_DETACHED); + np->fwnode.flags |= FWNODE_FLAG_NOT_DEVICE; } /** diff --git a/drivers/of/platform.c b/drivers/of/platform.c index e181c3f50f1d..bf96862cb700 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -741,6 +741,11 @@ static int of_platform_notify(struct notifier_block *nb, if (of_node_check_flag(rd->dn, OF_POPULATED)) return NOTIFY_OK; + /* + * Clear the flag before adding the device so that fw_devlink + * doesn't skip adding consumers to this device. + */ + rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE; /* pdev_parent may be NULL when no bus platform device */ pdev_parent = of_find_device_by_node(rd->dn->parent); pdev = of_platform_device_create(rd->dn, NULL, diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5f9aedd1f0b6..151fef199c38 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -4370,6 +4370,11 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; } + /* + * Clear the flag before adding the device so that fw_devlink + * doesn't skip adding consumers to this device. + */ + rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE; spi = of_register_spi_device(ctlr, rd->dn); put_device(&ctlr->dev);