Commit 0b3acd1c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 */
+40 −0
Original line number Diff line number Diff line
@@ -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);

@@ -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->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;
@@ -1120,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;
+3 −4
Original line number Diff line number Diff line
@@ -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);
}

+5 −0
Original line number Diff line number Diff line
@@ -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 */
+11 −1
Original line number Diff line number Diff line
@@ -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
@@ -377,6 +386,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 +402,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);
Loading