From 13a8e0f6b01b14b2e28ba144e112c883f03a3db2 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Fri, 19 Aug 2022 15:16:11 -0700 Subject: Revert "driver core: Delete driver_deferred_probe_check_state()" This reverts commit 9cbffc7a59561be950ecc675d19a3d2b45202b2b. There are a few more issues to fix that have been reported in the thread for the original series [1]. We'll need to fix those before this will work. So, revert it for now. [1] - https://lore.kernel.org/lkml/20220601070707.3946847-1-saravanak@google.com/ Fixes: 9cbffc7a5956 ("driver core: Delete driver_deferred_probe_check_state()") Tested-by: Tony Lindgren Tested-by: Peng Fan Tested-by: Douglas Anderson Tested-by: Alexander Stein Reviewed-by: Tony Lindgren Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20220819221616.2107893-2-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 30 ++++++++++++++++++++++++++++++ include/linux/device/driver.h | 1 + 2 files changed, 31 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 70f79fc71539..a8916d1bfdcb 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -274,12 +274,42 @@ static int __init deferred_probe_timeout_setup(char *str) } __setup("deferred_probe_timeout=", deferred_probe_timeout_setup); +/** + * driver_deferred_probe_check_state() - Check deferred probe state + * @dev: device to check + * + * Return: + * * -ENODEV if initcalls have completed and modules are disabled. + * * -ETIMEDOUT if the deferred probe timeout was set and has expired + * and modules are enabled. + * * -EPROBE_DEFER in other cases. + * + * Drivers or subsystems can opt-in to calling this function instead of directly + * returning -EPROBE_DEFER. + */ +int driver_deferred_probe_check_state(struct device *dev) +{ + if (!IS_ENABLED(CONFIG_MODULES) && initcalls_done) { + dev_warn(dev, "ignoring dependency for device, assuming no driver\n"); + return -ENODEV; + } + + if (!driver_deferred_probe_timeout && initcalls_done) { + dev_warn(dev, "deferred probe timeout, ignoring dependency\n"); + return -ETIMEDOUT; + } + + return -EPROBE_DEFER; +} +EXPORT_SYMBOL_GPL(driver_deferred_probe_check_state); + static void deferred_probe_timeout_work_func(struct work_struct *work) { struct device_private *p; fw_devlink_drivers_done(); + driver_deferred_probe_timeout = 0; driver_deferred_probe_trigger(); flush_work(&deferred_probe_work); diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index 7acaabde5396..2114d65b862f 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -242,6 +242,7 @@ driver_find_device_by_acpi_dev(struct device_driver *drv, const void *adev) extern int driver_deferred_probe_timeout; void driver_deferred_probe_add(struct device *dev); +int driver_deferred_probe_check_state(struct device *dev); void driver_init(void); /** -- cgit v1.3-18-gd494 From cffaf9721f755b46370e7be0592dc41168c95019 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Fri, 19 Aug 2022 15:16:12 -0700 Subject: Revert "net: mdio: Delete usage of driver_deferred_probe_check_state()" This reverts commit f8217275b57aa48d98cc42051c2aac34152718d6. There are a few more issues to fix that have been reported in the thread for the original series [1]. We'll need to fix those before this will work. So, revert it for now. [1] - https://lore.kernel.org/lkml/CAMuHMdWo_wRwV-i_iyTxVnEsf3Th9GBAG+wxUQMQGnw1t2ijTg@mail.gmail.com/ Fixes: f8217275b57a ("net: mdio: Delete usage of driver_deferred_probe_check_state()") Reported-by: Geert Uytterhoeven Tested-by: Alexander Stein Reviewed-by: Tony Lindgren Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20220819221616.2107893-3-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/net/mdio/fwnode_mdio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c index 3e79c2c51929..1c1584fca632 100644 --- a/drivers/net/mdio/fwnode_mdio.c +++ b/drivers/net/mdio/fwnode_mdio.c @@ -47,7 +47,9 @@ int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio, * just fall back to poll mode */ if (rc == -EPROBE_DEFER) - rc = -ENODEV; + rc = driver_deferred_probe_check_state(&phy->mdio.dev); + if (rc == -EPROBE_DEFER) + return rc; if (rc > 0) { phy->irq = rc; -- cgit v1.3-18-gd494 From e20813dcdc05aa295ef586b518142d0fab4c5692 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Fri, 19 Aug 2022 15:16:13 -0700 Subject: Revert "PM: domains: Delete usage of driver_deferred_probe_check_state()" This reverts commit 5a46079a96451cfb15e4f5f01f73f7ba24ef851a. Quite a few issues have been reported [1][2][3][4][5][6] on the original commit. While about half of them have been fixed, I'll need to fix the rest before driver_deferred_probe_check_state() can be deleted. So, revert the deletion for now. [1] - https://lore.kernel.org/all/DU0PR04MB941735271F45C716342D0410886B9@DU0PR04MB9417.eurprd04.prod.outlook.com/ [2] - https://lore.kernel.org/all/CM6REZS9Z8AC.2KCR9N3EFLNQR@otso/ [3] - https://lore.kernel.org/all/CAD=FV=XYVwaXZxqUKAuM5c7NiVjFz5C6m6gAHSJ7rBXBF94_Tg@mail.gmail.com/ [4] - https://lore.kernel.org/all/Yvpd2pwUJGp7R+YE@euler/ [5] - https://lore.kernel.org/lkml/20220601070707.3946847-2-saravanak@google.com/ [6] - https://lore.kernel.org/all/CA+G9fYt_cc5SiNv1Vbse=HYY_+uc+9OYPZuJ-x59bROSaLN6fw@mail.gmail.com/ Fixes: 5a46079a9645 ("PM: domains: Delete usage of driver_deferred_probe_check_state()") Reported-by: Peng Fan Reported-by: Luca Weiss Reported-by: Doug Anderson Reported-by: Colin Foster Reported-by: Tony Lindgren Reported-by: Alexander Stein Reported-by: Naresh Kamboju Tested-by: Tony Lindgren Tested-by: Peng Fan Tested-by: Douglas Anderson Tested-by: Alexander Stein Reviewed-by: Tony Lindgren Acked-by: Ulf Hansson Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20220819221616.2107893-4-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/domain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 5a2e0232862e..55a10e6d4e2a 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2733,7 +2733,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev, mutex_unlock(&gpd_list_lock); dev_dbg(dev, "%s() failed to find PM domain: %ld\n", __func__, PTR_ERR(pd)); - return -ENODEV; + return driver_deferred_probe_check_state(base_dev); } dev_dbg(dev, "adding to PM domain %s\n", pd->name); -- cgit v1.3-18-gd494 From a4f124908617553ea3929a17293cea4960c92ba3 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Fri, 19 Aug 2022 15:16:14 -0700 Subject: Revert "iommu/of: Delete usage of driver_deferred_probe_check_state()" This reverts commit b09796d528bbf06e3e10a4a8f78038719da7ebc6. An issue was reported[1] on the original commit. I'll need to address that before I can delete the use of driver_deferred_probe_check_state(). So, bring it back for now. [1] - https://lore.kernel.org/lkml/4799738.LvFx2qVVIh@steina-w/ Fixes: b09796d528bb ("iommu/of: Delete usage of driver_deferred_probe_check_state()") Reported-by: Jean-Philippe Brucker Tested-by: Jean-Philippe Brucker Tested-by: Alexander Stein Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20220819221616.2107893-5-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/of_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 41f4eb005219..5696314ae69e 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -40,7 +40,7 @@ static int of_iommu_xlate(struct device *dev, * a proper probe-ordering dependency mechanism in future. */ if (!ops) - return -ENODEV; + return driver_deferred_probe_check_state(dev); if (!try_module_get(ops->owner)) return -ENODEV; -- cgit v1.3-18-gd494 From 25e9fbf0fd38868a429feabc38abebfc6dbf6542 Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Wed, 17 Aug 2022 11:40:26 -0700 Subject: driver core: Don't probe devices after bus_type.match() probe deferral Both __device_attach_driver() and __driver_attach() check the return code of the bus_type.match() function to see if the device needs to be added to the deferred probe list. After adding the device to the list, the logic attempts to bind the device to the driver anyway, as if the device had matched with the driver, which is not correct. If __device_attach_driver() detects that the device in question is not ready to match with a driver on the bus, then it doesn't make sense for the device to attempt to bind with the current driver or continue attempting to match with any of the other drivers on the bus. So, update the logic in __device_attach_driver() to reflect this. If __driver_attach() detects that a driver tried to match with a device that is not ready to match yet, then the driver should not attempt to bind with the device. However, the driver can still attempt to match and bind with other devices on the bus, as drivers can be bound to multiple devices. So, update the logic in __driver_attach() to reflect this. Fixes: 656b8035b0ee ("ARM: 8524/1: driver cohandle -EPROBE_DEFER from bus_type.match()") Cc: stable@vger.kernel.org Cc: Saravana Kannan Reported-by: Guenter Roeck Tested-by: Guenter Roeck Tested-by: Linus Walleij Reviewed-by: Saravana Kannan Signed-off-by: Isaac J. Manjarres Link: https://lore.kernel.org/r/20220817184026.3468620-1-isaacmanjarres@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index a8916d1bfdcb..ec69b43f926a 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -911,6 +911,11 @@ static int __device_attach_driver(struct device_driver *drv, void *_data) dev_dbg(dev, "Device match requests probe deferral\n"); dev->can_match = true; driver_deferred_probe_add(dev); + /* + * Device can't match with a driver right now, so don't attempt + * to match or bind with other drivers on the bus. + */ + return ret; } else if (ret < 0) { dev_dbg(dev, "Bus failed to match device: %d\n", ret); return ret; @@ -1150,6 +1155,11 @@ static int __driver_attach(struct device *dev, void *data) dev_dbg(dev, "Device match requests probe deferral\n"); dev->can_match = true; driver_deferred_probe_add(dev); + /* + * Driver could not match with device, but may match with + * another device on the bus. + */ + return 0; } else if (ret < 0) { dev_dbg(dev, "Bus failed to match device: %d\n", ret); return ret; -- cgit v1.3-18-gd494 From 9b03e79300100bcd36e77c8ce94ee7f47cd2f528 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 5 Aug 2022 16:07:36 -0700 Subject: arch_topology: Silence early cacheinfo errors when non-existent Architectures which do not have cacheinfo such as ARM 32-bit would spit out the following during boot: Early cacheinfo failed, ret = -2 Treat -ENOENT specifically to silence this error since it means that the platform does not support reporting its cache information. Fixes: 3fcbf1c77d08 ("arch_topology: Fix cache attributes detection in the CPU hotplug path") Tested-by: Geert Uytterhoeven Tested-by: Michael Walle Reviewed-by: Sudeep Holla Reviewed-by: Conor Dooley Signed-off-by: Florian Fainelli Link: https://lore.kernel.org/r/20220805230736.1562801-1-f.fainelli@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/arch_topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 0424b59b695e..eaa1b8d2d39d 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -735,7 +735,7 @@ void update_siblings_masks(unsigned int cpuid) int cpu, ret; ret = detect_cache_attributes(cpuid); - if (ret) + if (ret && ret != -ENOENT) pr_info("Early cacheinfo failed, ret = %d\n", ret); /* update core and thread sibling masks */ -- cgit v1.3-18-gd494 From 8b40c38e37492b5bdf8e95b46b5cca9517a9957a Mon Sep 17 00:00:00 2001 From: Russ Weight Date: Mon, 29 Aug 2022 10:45:57 -0700 Subject: firmware_loader: Fix use-after-free during unregister In the following code within firmware_upload_unregister(), the call to device_unregister() could result in the dev_release function freeing the fw_upload_priv structure before it is dereferenced for the call to module_put(). This bug was found by the kernel test robot using CONFIG_KASAN while running the firmware selftests. device_unregister(&fw_sysfs->dev); module_put(fw_upload_priv->module); The problem is fixed by copying fw_upload_priv->module to a local variable for use when calling device_unregister(). Fixes: 97730bbb242c ("firmware_loader: Add firmware-upload support") Cc: stable Reported-by: kernel test robot Reviewed-by: Matthew Gerlach Signed-off-by: Russ Weight Link: https://lore.kernel.org/r/20220829174557.437047-1-russell.h.weight@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_loader/sysfs_upload.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/base/firmware_loader/sysfs_upload.c b/drivers/base/firmware_loader/sysfs_upload.c index 87044d52322a..63e15bddd80c 100644 --- a/drivers/base/firmware_loader/sysfs_upload.c +++ b/drivers/base/firmware_loader/sysfs_upload.c @@ -377,6 +377,7 @@ void firmware_upload_unregister(struct fw_upload *fw_upload) { struct fw_sysfs *fw_sysfs = fw_upload->priv; struct fw_upload_priv *fw_upload_priv = fw_sysfs->fw_upload_priv; + struct module *module = fw_upload_priv->module; mutex_lock(&fw_upload_priv->lock); if (fw_upload_priv->progress == FW_UPLOAD_PROG_IDLE) { @@ -392,6 +393,6 @@ void firmware_upload_unregister(struct fw_upload *fw_upload) unregister: device_unregister(&fw_sysfs->dev); - module_put(fw_upload_priv->module); + module_put(module); } EXPORT_SYMBOL_GPL(firmware_upload_unregister); -- cgit v1.3-18-gd494 From 789bba82f63c3e81dce426ba457fc7905b30ac6e Mon Sep 17 00:00:00 2001 From: Russ Weight Date: Tue, 30 Aug 2022 17:25:18 -0700 Subject: firmware_loader: Fix memory leak in firmware upload In the case of firmware-upload, an instance of struct fw_upload is allocated in firmware_upload_register(). This data needs to be freed in fw_dev_release(). Create a new fw_upload_free() function in sysfs_upload.c to handle the firmware-upload specific memory frees and incorporate the missing kfree call for the fw_upload structure. Fixes: 97730bbb242c ("firmware_loader: Add firmware-upload support") Cc: stable Signed-off-by: Russ Weight Link: https://lore.kernel.org/r/20220831002518.465274-1-russell.h.weight@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_loader/sysfs.c | 7 +++---- drivers/base/firmware_loader/sysfs.h | 5 +++++ drivers/base/firmware_loader/sysfs_upload.c | 9 +++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/base/firmware_loader/sysfs.c b/drivers/base/firmware_loader/sysfs.c index 77bad32c481a..5b66b3d1fa16 100644 --- a/drivers/base/firmware_loader/sysfs.c +++ b/drivers/base/firmware_loader/sysfs.c @@ -93,10 +93,9 @@ static void fw_dev_release(struct device *dev) { struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); - if (fw_sysfs->fw_upload_priv) { - free_fw_priv(fw_sysfs->fw_priv); - kfree(fw_sysfs->fw_upload_priv); - } + if (fw_sysfs->fw_upload_priv) + fw_upload_free(fw_sysfs); + kfree(fw_sysfs); } diff --git a/drivers/base/firmware_loader/sysfs.h b/drivers/base/firmware_loader/sysfs.h index 5d8ff1675c79..df1d5add698f 100644 --- a/drivers/base/firmware_loader/sysfs.h +++ b/drivers/base/firmware_loader/sysfs.h @@ -106,12 +106,17 @@ extern struct device_attribute dev_attr_cancel; extern struct device_attribute dev_attr_remaining_size; int fw_upload_start(struct fw_sysfs *fw_sysfs); +void fw_upload_free(struct fw_sysfs *fw_sysfs); umode_t fw_upload_is_visible(struct kobject *kobj, struct attribute *attr, int n); #else static inline int fw_upload_start(struct fw_sysfs *fw_sysfs) { return 0; } + +static inline void fw_upload_free(struct fw_sysfs *fw_sysfs) +{ +} #endif #endif /* __FIRMWARE_SYSFS_H */ diff --git a/drivers/base/firmware_loader/sysfs_upload.c b/drivers/base/firmware_loader/sysfs_upload.c index 63e15bddd80c..a0af8f5f13d8 100644 --- a/drivers/base/firmware_loader/sysfs_upload.c +++ b/drivers/base/firmware_loader/sysfs_upload.c @@ -264,6 +264,15 @@ int fw_upload_start(struct fw_sysfs *fw_sysfs) return 0; } +void fw_upload_free(struct fw_sysfs *fw_sysfs) +{ + struct fw_upload_priv *fw_upload_priv = fw_sysfs->fw_upload_priv; + + free_fw_priv(fw_sysfs->fw_priv); + kfree(fw_upload_priv->fw_upload); + kfree(fw_upload_priv); +} + /** * firmware_upload_register() - register for the firmware upload sysfs API * @module: kernel module of this device -- cgit v1.3-18-gd494