Commit 3ae7f509 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'driver-core-6.15-rc4' of...

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

Pull driver core fixes from Greg KH:
 "Here are some small driver core fixes to resolve a number of reported
  problems. Included in here are:

   - driver core sync fix revert to resolve a much reported problem,
     hopefully this is finally resolved

   - MAINTAINERS file update, documenting that the driver-core tree is
     now under a "shared" maintainership model, thanks to Rafael and
     Danilo for offering to do this!

   - auxbus documentation and MAINTAINERS file update

   - MAINTAINERS file update for Rust PCI code

   - firmware rust binding fixup

   - software node link fix

  All of these have been in linux-next for over a week with no reported
  issues"

* tag 'driver-core-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core:
  drivers/base/memory: Avoid overhead from for_each_present_section_nr()
  software node: Prevent link creation failure from causing kobj reference count imbalance
  device property: Add a note to the fwnode.h
  drivers/base: Add myself as auxiliary bus reviewer
  drivers/base: Extend documentation with preferred way to use auxbus
  driver core: fix potential NULL pointer dereference in dev_uevent()
  driver core: introduce device_set_driver() helper
  Revert "drivers: core: synchronize really_probe() and dev_uevent()"
  MAINTAINERS: update the location of the driver-core git tree
  rust: firmware: Use `ffi::c_char` type in `FwFunc`
  MAINTAINERS: pci: add entry for Rust PCI code
parents 882cd652 b9792abb
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -3873,8 +3873,9 @@ AUXILIARY BUS DRIVER
M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
R:	Dave Ertman <david.m.ertman@intel.com>
R:	Ira Weiny <ira.weiny@intel.com>
R:	Leon Romanovsky <leon@kernel.org>
S:	Supported
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
F:	Documentation/driver-api/auxiliary_bus.rst
F:	drivers/base/auxiliary.c
F:	include/linux/auxiliary_bus.h
@@ -7233,7 +7234,7 @@ M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
M:	"Rafael J. Wysocki" <rafael@kernel.org>
M:	Danilo Krummrich <dakr@kernel.org>
S:	Supported
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
F:	Documentation/core-api/kobject.rst
F:	drivers/base/
F:	fs/debugfs/
@@ -13118,7 +13119,7 @@ KERNFS
M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
M:	Tejun Heo <tj@kernel.org>
S:	Supported
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
F:	fs/kernfs/
F:	include/linux/kernfs.h
@@ -18750,6 +18751,16 @@ F: include/asm-generic/pci*
F:	include/linux/of_pci.h
F:	include/linux/pci*
F:	include/uapi/linux/pci*
PCI SUBSYSTEM [RUST]
M:	Danilo Krummrich <dakr@kernel.org>
R:	Bjorn Helgaas <bhelgaas@google.com>
R:	Krzysztof Wilczyński <kwilczynski@kernel.org>
L:	linux-pci@vger.kernel.org
S:	Maintained
C:	irc://irc.oftc.net/linux-pci
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
F:	rust/helpers/pci.c
F:	rust/kernel/pci.rs
F:	samples/rust/rust_driver_pci.rs
+10 −0
Original line number Diff line number Diff line
@@ -156,6 +156,16 @@
 *		},
 *		.ops = my_custom_ops,
 *	};
 *
 * Please note that such custom ops approach is valid, but it is hard to implement
 * it right without global locks per-device to protect from auxiliary_drv removal
 * during call to that ops. In addition, this implementation lacks proper module
 * dependency, which causes to load/unload races between auxiliary parent and devices
 * modules.
 *
 * The most easiest way to provide these ops reliably without needing to
 * have a lock is to EXPORT_SYMBOL*() them and rely on already existing
 * modules infrastructure for validity and correct dependencies chains.
 */

static const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id,
+17 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ static inline void subsys_put(struct subsys_private *sp)
		kset_put(&sp->subsys);
}

struct subsys_private *bus_to_subsys(const struct bus_type *bus);
struct subsys_private *class_to_subsys(const struct class *class);

struct driver_private {
@@ -180,6 +181,22 @@ int driver_add_groups(const struct device_driver *drv, const struct attribute_gr
void driver_remove_groups(const struct device_driver *drv, const struct attribute_group **groups);
void device_driver_detach(struct device *dev);

static inline void device_set_driver(struct device *dev, const struct device_driver *drv)
{
	/*
	 * Majority (all?) read accesses to dev->driver happens either
	 * while holding device lock or in bus/driver code that is only
	 * invoked when the device is bound to a driver and there is no
	 * concern of the pointer being changed while it is being read.
	 * However when reading device's uevent file we read driver pointer
	 * without taking device lock (so we do not block there for
	 * arbitrary amount of time). We use WRITE_ONCE() here to prevent
	 * tearing so that READ_ONCE() can safely be used in uevent code.
	 */
	// FIXME - this cast should not be needed "soon"
	WRITE_ONCE(dev->driver, (struct device_driver *)drv);
}

int devres_release_all(struct device *dev);
void device_block_probing(void);
void device_unblock_probing(void);
+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
 * NULL.  A call to subsys_put() must be done when finished with the pointer in
 * order for it to be properly freed.
 */
static struct subsys_private *bus_to_subsys(const struct bus_type *bus)
struct subsys_private *bus_to_subsys(const struct bus_type *bus)
{
	struct subsys_private *sp = NULL;
	struct kobject *kobj;
+32 −6
Original line number Diff line number Diff line
@@ -2624,6 +2624,35 @@ static const char *dev_uevent_name(const struct kobject *kobj)
	return NULL;
}

/*
 * Try filling "DRIVER=<name>" uevent variable for a device. Because this
 * function may race with binding and unbinding the device from a driver,
 * we need to be careful. Binding is generally safe, at worst we miss the
 * fact that the device is already bound to a driver (but the driver
 * information that is delivered through uevents is best-effort, it may
 * become obsolete as soon as it is generated anyways). Unbinding is more
 * risky as driver pointer is transitioning to NULL, so READ_ONCE() should
 * be used to make sure we are dealing with the same pointer, and to
 * ensure that driver structure is not going to disappear from under us
 * we take bus' drivers klist lock. The assumption that only registered
 * driver can be bound to a device, and to unregister a driver bus code
 * will take the same lock.
 */
static void dev_driver_uevent(const struct device *dev, struct kobj_uevent_env *env)
{
	struct subsys_private *sp = bus_to_subsys(dev->bus);

	if (sp) {
		scoped_guard(spinlock, &sp->klist_drivers.k_lock) {
			struct device_driver *drv = READ_ONCE(dev->driver);
			if (drv)
				add_uevent_var(env, "DRIVER=%s", drv->name);
		}

		subsys_put(sp);
	}
}

static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env)
{
	const struct device *dev = kobj_to_dev(kobj);
@@ -2655,8 +2684,8 @@ static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env)
	if (dev->type && dev->type->name)
		add_uevent_var(env, "DEVTYPE=%s", dev->type->name);

	if (dev->driver)
		add_uevent_var(env, "DRIVER=%s", dev->driver->name);
	/* Add "DRIVER=%s" variable if the device is bound to a driver */
	dev_driver_uevent(dev, env);

	/* Add common DT information about the device */
	of_device_uevent(dev, env);
@@ -2726,11 +2755,8 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
	if (!env)
		return -ENOMEM;

	/* Synchronize with really_probe() */
	device_lock(dev);
	/* let the kset specific function add its keys */
	retval = kset->uevent_ops->uevent(&dev->kobj, env);
	device_unlock(dev);
	if (retval)
		goto out;

@@ -3700,7 +3726,7 @@ int device_add(struct device *dev)
	device_pm_remove(dev);
	dpm_sysfs_remove(dev);
 DPMError:
	dev->driver = NULL;
	device_set_driver(dev, NULL);
	bus_remove_device(dev);
 BusError:
	device_remove_attrs(dev);
Loading