Commit 0b3acd1c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'driver-core-6.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core fixes from Greg KH:
 "Here are some small driver core fixes for some oft-reported problems
  in 6.0-rc1.  They include:

   - a bunch of reverts to handle driver_deferred_probe_check_state()
     problems that were part of the 6.0-rc1 merge.

   - firmware_loader bugfixes now that the code is being properly tested
     and used by others

   - arch_topology fix

   - deferred driver probe bugfix to solve a long-suffering amba bus
     problem that many people have reported.

  All of these have been in linux-next for a while with no reported
  problems"

* tag 'driver-core-6.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
  firmware_loader: Fix memory leak in firmware upload
  firmware_loader: Fix use-after-free during unregister
  arch_topology: Silence early cacheinfo errors when non-existent
  driver core: Don't probe devices after bus_type.match() probe deferral
  Revert "iommu/of: Delete usage of driver_deferred_probe_check_state()"
  Revert "PM: domains: Delete usage of driver_deferred_probe_check_state()"
  Revert "net: mdio: Delete usage of driver_deferred_probe_check_state()"
  Revert "driver core: Delete driver_deferred_probe_check_state()"
parents ffb384c2 789bba82
...@@ -735,7 +735,7 @@ void update_siblings_masks(unsigned int cpuid) ...@@ -735,7 +735,7 @@ void update_siblings_masks(unsigned int cpuid)
int cpu, ret; int cpu, ret;
ret = detect_cache_attributes(cpuid); ret = detect_cache_attributes(cpuid);
if (ret) if (ret && ret != -ENOENT)
pr_info("Early cacheinfo failed, ret = %d\n", ret); pr_info("Early cacheinfo failed, ret = %d\n", ret);
/* update core and thread sibling masks */ /* update core and thread sibling masks */
......
...@@ -274,12 +274,42 @@ static int __init deferred_probe_timeout_setup(char *str) ...@@ -274,12 +274,42 @@ static int __init deferred_probe_timeout_setup(char *str)
} }
__setup("deferred_probe_timeout=", deferred_probe_timeout_setup); __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) static void deferred_probe_timeout_work_func(struct work_struct *work)
{ {
struct device_private *p; struct device_private *p;
fw_devlink_drivers_done(); fw_devlink_drivers_done();
driver_deferred_probe_timeout = 0;
driver_deferred_probe_trigger(); driver_deferred_probe_trigger();
flush_work(&deferred_probe_work); flush_work(&deferred_probe_work);
...@@ -881,6 +911,11 @@ static int __device_attach_driver(struct device_driver *drv, void *_data) ...@@ -881,6 +911,11 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
dev_dbg(dev, "Device match requests probe deferral\n"); dev_dbg(dev, "Device match requests probe deferral\n");
dev->can_match = true; dev->can_match = true;
driver_deferred_probe_add(dev); 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) { } else if (ret < 0) {
dev_dbg(dev, "Bus failed to match device: %d\n", ret); dev_dbg(dev, "Bus failed to match device: %d\n", ret);
return ret; return ret;
...@@ -1120,6 +1155,11 @@ static int __driver_attach(struct device *dev, void *data) ...@@ -1120,6 +1155,11 @@ static int __driver_attach(struct device *dev, void *data)
dev_dbg(dev, "Device match requests probe deferral\n"); dev_dbg(dev, "Device match requests probe deferral\n");
dev->can_match = true; dev->can_match = true;
driver_deferred_probe_add(dev); 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) { } else if (ret < 0) {
dev_dbg(dev, "Bus failed to match device: %d\n", ret); dev_dbg(dev, "Bus failed to match device: %d\n", ret);
return ret; return ret;
......
...@@ -93,10 +93,9 @@ static void fw_dev_release(struct device *dev) ...@@ -93,10 +93,9 @@ static void fw_dev_release(struct device *dev)
{ {
struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev);
if (fw_sysfs->fw_upload_priv) { if (fw_sysfs->fw_upload_priv)
free_fw_priv(fw_sysfs->fw_priv); fw_upload_free(fw_sysfs);
kfree(fw_sysfs->fw_upload_priv);
}
kfree(fw_sysfs); kfree(fw_sysfs);
} }
......
...@@ -106,12 +106,17 @@ extern struct device_attribute dev_attr_cancel; ...@@ -106,12 +106,17 @@ extern struct device_attribute dev_attr_cancel;
extern struct device_attribute dev_attr_remaining_size; extern struct device_attribute dev_attr_remaining_size;
int fw_upload_start(struct fw_sysfs *fw_sysfs); 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); umode_t fw_upload_is_visible(struct kobject *kobj, struct attribute *attr, int n);
#else #else
static inline int fw_upload_start(struct fw_sysfs *fw_sysfs) static inline int fw_upload_start(struct fw_sysfs *fw_sysfs)
{ {
return 0; return 0;
} }
static inline void fw_upload_free(struct fw_sysfs *fw_sysfs)
{
}
#endif #endif
#endif /* __FIRMWARE_SYSFS_H */ #endif /* __FIRMWARE_SYSFS_H */
...@@ -264,6 +264,15 @@ int fw_upload_start(struct fw_sysfs *fw_sysfs) ...@@ -264,6 +264,15 @@ int fw_upload_start(struct fw_sysfs *fw_sysfs)
return 0; 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 * firmware_upload_register() - register for the firmware upload sysfs API
* @module: kernel module of this device * @module: kernel module of this device
...@@ -377,6 +386,7 @@ void firmware_upload_unregister(struct fw_upload *fw_upload) ...@@ -377,6 +386,7 @@ void firmware_upload_unregister(struct fw_upload *fw_upload)
{ {
struct fw_sysfs *fw_sysfs = fw_upload->priv; struct fw_sysfs *fw_sysfs = fw_upload->priv;
struct fw_upload_priv *fw_upload_priv = 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); mutex_lock(&fw_upload_priv->lock);
if (fw_upload_priv->progress == FW_UPLOAD_PROG_IDLE) { if (fw_upload_priv->progress == FW_UPLOAD_PROG_IDLE) {
...@@ -392,6 +402,6 @@ void firmware_upload_unregister(struct fw_upload *fw_upload) ...@@ -392,6 +402,6 @@ void firmware_upload_unregister(struct fw_upload *fw_upload)
unregister: unregister:
device_unregister(&fw_sysfs->dev); device_unregister(&fw_sysfs->dev);
module_put(fw_upload_priv->module); module_put(module);
} }
EXPORT_SYMBOL_GPL(firmware_upload_unregister); EXPORT_SYMBOL_GPL(firmware_upload_unregister);
...@@ -2733,7 +2733,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev, ...@@ -2733,7 +2733,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
mutex_unlock(&gpd_list_lock); mutex_unlock(&gpd_list_lock);
dev_dbg(dev, "%s() failed to find PM domain: %ld\n", dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
__func__, PTR_ERR(pd)); __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); dev_dbg(dev, "adding to PM domain %s\n", pd->name);
......
...@@ -40,7 +40,7 @@ static int of_iommu_xlate(struct device *dev, ...@@ -40,7 +40,7 @@ static int of_iommu_xlate(struct device *dev,
* a proper probe-ordering dependency mechanism in future. * a proper probe-ordering dependency mechanism in future.
*/ */
if (!ops) if (!ops)
return -ENODEV; return driver_deferred_probe_check_state(dev);
if (!try_module_get(ops->owner)) if (!try_module_get(ops->owner))
return -ENODEV; return -ENODEV;
......
...@@ -47,7 +47,9 @@ int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio, ...@@ -47,7 +47,9 @@ int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
* just fall back to poll mode * just fall back to poll mode
*/ */
if (rc == -EPROBE_DEFER) if (rc == -EPROBE_DEFER)
rc = -ENODEV; rc = driver_deferred_probe_check_state(&phy->mdio.dev);
if (rc == -EPROBE_DEFER)
return rc;
if (rc > 0) { if (rc > 0) {
phy->irq = rc; phy->irq = rc;
......
...@@ -242,6 +242,7 @@ driver_find_device_by_acpi_dev(struct device_driver *drv, const void *adev) ...@@ -242,6 +242,7 @@ driver_find_device_by_acpi_dev(struct device_driver *drv, const void *adev)
extern int driver_deferred_probe_timeout; extern int driver_deferred_probe_timeout;
void driver_deferred_probe_add(struct device *dev); void driver_deferred_probe_add(struct device *dev);
int driver_deferred_probe_check_state(struct device *dev);
void driver_init(void); void driver_init(void);
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment