Commit 8c2bf4a2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'driver-core-7.1-rc1-2' of...

Merge tag 'driver-core-7.1-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core

Pull driver core fixes from Danilo Krummrich:

 - Prevent a device from being probed before device_add() has finished
   initializing it; gate probe with a "ready_to_probe" device flag to
   avoid races with concurrent driver_register() calls

 - Fix a kernel-doc warning for DEV_FLAG_COUNT introduced by the above

 - Return -ENOTCONN from software_node_get_reference_args() when a
   referenced software node is known but not yet registered, allowing
   callers to defer probe

 - In sysfs_group_attrs_change_owner(), also check is_visible_const();
   missed when the const variant was introduced

* tag 'driver-core-7.1-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core:
  driver core: Add kernel-doc for DEV_FLAG_COUNT enum value
  sysfs: attribute_group: Respect is_visible_const() when changing owner
  software node: return -ENOTCONN when referenced swnode is not registered yet
  driver core: Don't let a device probe until it's ready
parents bea8d77e 5b484311
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -3688,6 +3688,21 @@ int device_add(struct device *dev)
		fw_devlink_link_device(dev);
	}

	/*
	 * The moment the device was linked into the bus's "klist_devices" in
	 * bus_add_device() then it's possible that probe could have been
	 * attempted in a different thread via userspace loading a driver
	 * matching the device. "ready_to_probe" being unset would have
	 * blocked those attempts. Now that all of the above initialization has
	 * happened, unblock probe. If probe happens through another thread
	 * after this point but before bus_probe_device() runs then it's fine.
	 * bus_probe_device() -> device_initial_probe() -> __device_attach()
	 * will notice (under device_lock) that the device is already bound.
	 */
	device_lock(dev);
	dev_set_ready_to_probe(dev);
	device_unlock(dev);

	bus_probe_device(dev);

	/*
+20 −0
Original line number Diff line number Diff line
@@ -836,6 +836,26 @@ static int __driver_probe_device(const struct device_driver *drv, struct device
	if (dev->driver)
		return -EBUSY;

	/*
	 * In device_add(), the "struct device" gets linked into the subsystem's
	 * list of devices and broadcast to userspace (via uevent) before we're
	 * quite ready to probe. Those open pathways to driver probe before
	 * we've finished enough of device_add() to reliably support probe.
	 * Detect this and tell other pathways to try again later. device_add()
	 * itself will also try to probe immediately after setting
	 * "ready_to_probe".
	 */
	if (!dev_ready_to_probe(dev))
		return dev_err_probe(dev, -EPROBE_DEFER, "Device not ready to probe\n");

	/*
	 * Set can_match = true after calling dev_ready_to_probe(), so
	 * driver_deferred_probe_add() won't actually add the device to the
	 * deferred probe list when dev_ready_to_probe() returns false.
	 *
	 * When dev_ready_to_probe() returns false, it means that device_add()
	 * will do another probe() attempt for us.
	 */
	dev->can_match = true;
	dev_dbg(dev, "bus: '%s': %s: matched device with driver %s\n",
		drv->bus->name, __func__, drv->name);
+2 −0
Original line number Diff line number Diff line
@@ -602,6 +602,8 @@ EXPORT_SYMBOL_GPL(fwnode_property_match_property_string);
 *	    %-ENOENT when the index is out of bounds, the index has an empty
 *		     reference or the property was not found
 *	    %-EINVAL on parse error
 *	    %-ENOTCONN when the remote firmware node exists but has not been
 *		       registered yet
 */
int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode,
				       const char *prop, const char *nargs_prop,
+1 −1
Original line number Diff line number Diff line
@@ -554,7 +554,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
		return -EINVAL;

	if (!refnode)
		return -ENOENT;
		return -ENOTCONN;

	if (nargs_prop) {
		error = fwnode_property_read_u32(refnode, nargs_prop, &nargs_prop_val);
+5 −2
Original line number Diff line number Diff line
@@ -517,8 +517,11 @@ static int sysfs_group_attrs_change_owner(struct kobject *kobj,
		struct attribute *const *attr;

		for (i = 0, attr = grp->attrs; *attr; i++, attr++) {
			if (grp->is_visible) {
			if (grp->is_visible || grp->is_visible_const) {
				if (grp->is_visible)
					mode = grp->is_visible(kobj, *attr, i);
				else
					mode = grp->is_visible_const(kobj, *attr, i);
				if (mode & SYSFS_GROUP_INVISIBLE)
					break;
				if (!mode)
Loading