Commit 4793dae0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

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

Pull driver core updates from Danilo Krummrich:
 "debugfs:
   - Fix NULL pointer dereference in debugfs_create_str()
   - Fix misplaced EXPORT_SYMBOL_GPL for debugfs_create_str()
   - Fix soundwire debugfs NULL pointer dereference from uninitialized
     firmware_file

  device property:
   - Make fwnode flags modifications thread safe; widen the field to
     unsigned long and use set_bit() / clear_bit() based accessors
   - Document how to check for the property presence

  devres:
   - Separate struct devres_node from its "subclasses" (struct devres,
     struct devres_group); give struct devres_node its own release and
     free callbacks for per-type dispatch
   - Introduce struct devres_action for devres actions, avoiding the
     ARCH_DMA_MINALIGN alignment overhead of struct devres
   - Export struct devres_node and its init/add/remove/dbginfo
     primitives for use by Rust Devres<T>
   - Fix missing node debug info in devm_krealloc()
   - Use guard(spinlock_irqsave) where applicable; consolidate unlock
     paths in devres_release_group()

  driver_override:
   - Convert PCI, WMI, vdpa, s390/cio, s390/ap, and fsl-mc to the
     generic driver_override infrastructure, replacing per-bus
     driver_override strings, sysfs attributes, and match logic; fixes a
     potential UAF from unsynchronized access to driver_override in bus
     match() callbacks
   - Simplify __device_set_driver_override() logic

  kernfs:
   - Send IN_DELETE_SELF and IN_IGNORED inotify events on kernfs file
     and directory removal
   - Add corresponding selftests for memcg

  platform:
   - Allow attaching software nodes when creating platform devices via a
     new 'swnode' field in struct platform_device_info
   - Add kerneldoc for struct platform_device_info

  software node:
   - Move software node initialization from postcore_initcall() to
     driver_init(), making it available early in the boot process
   - Move kernel_kobj initialization (ksysfs_init) earlier to support
     the above
   - Remove software_node_exit(); dead code in a built-in unit

  SoC:
   - Introduce of_machine_read_compatible() and of_machine_read_model()
     OF helpers and export soc_attr_read_machine() to replace direct
     accesses to of_root from SoC drivers; also enables
     CONFIG_COMPILE_TEST coverage for these drivers

  sysfs:
   - Constify attribute group array pointers to
     'const struct attribute_group *const *' in sysfs functions,
     device_add_groups() / device_remove_groups(), and struct class

  Rust:
   - Devres:
      - Embed struct devres_node directly in Devres<T> instead of going
        through devm_add_action(), avoiding the extra allocation and the
        unnecessary ARCH_DMA_MINALIGN alignment

   - I/O:
      - Turn IoCapable from a marker trait into a functional trait
        carrying the raw I/O accessor implementation (io_read /
        io_write), providing working defaults for the per-type Io
        methods
      - Add RelaxedMmio wrapper type, making relaxed accessors usable in
        code generic over the Io trait
      - Remove overloaded per-type Io methods and per-backend macros
        from Mmio and PCI ConfigSpace

   - I/O (Register):
      - Add IoLoc trait and generic read/write/update methods to the Io
        trait, making I/O operations parameterizable by typed locations
      - Add register! macro for defining hardware register types with
        typed bitfield accessors backed by Bounded values; supports
        direct, relative, and array register addressing
      - Add write_reg() / try_write_reg() and LocatedRegister trait
      - Update PCI sample driver to demonstrate the register! macro

         Example:

         ```
             register! {
                 /// UART control register.
                 CTRL(u32) @ 0x18 {
                     /// Receiver enable.
                     19:19   rx_enable => bool;
                     /// Parity configuration.
                     14:13   parity ?=> Parity;
                 }

                 /// FIFO watermark and counter register.
                 WATER(u32) @ 0x2c {
                     /// Number of datawords in the receive FIFO.
                     26:24   rx_count;
                     /// RX interrupt threshold.
                     17:16   rx_water;
                 }
             }

             impl WATER {
                 fn rx_above_watermark(&self) -> bool {
                     self.rx_count() > self.rx_water()
                 }
             }

             fn init(bar: &pci::Bar<BAR0_SIZE>) {
                 let water = WATER::zeroed()
                     .with_const_rx_water::<1>(); // > 3 would not compile
                 bar.write_reg(water);

                 let ctrl = CTRL::zeroed()
                     .with_parity(Parity::Even)
                     .with_rx_enable(true);
                 bar.write_reg(ctrl);
             }

             fn handle_rx(bar: &pci::Bar<BAR0_SIZE>) {
                 if bar.read(WATER).rx_above_watermark() {
                     // drain the FIFO
                 }
             }

             fn set_parity(bar: &pci::Bar<BAR0_SIZE>, parity: Parity) {
                 bar.update(CTRL, |r| r.with_parity(parity));
             }
         ```

   - IRQ:
      - Move 'static bounds from where clauses to trait declarations for
        IRQ handler traits

   - Misc:
      - Enable the generic_arg_infer Rust feature
      - Extend Bounded with shift operations, single-bit bool
        conversion, and const get()

  Misc:
   - Make deferred_probe_timeout default a Kconfig option
   - Drop auxiliary_dev_pm_ops; the PM core falls back to driver PM
     callbacks when no bus type PM ops are set
   - Add conditional guard support for device_lock()
   - Add ksysfs.c to the DRIVER CORE MAINTAINERS entry
   - Fix kernel-doc warnings in base.h
   - Fix stale reference to memory_block_add_nid() in documentation"

* tag 'driver-core-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: (67 commits)
  bus: fsl-mc: use generic driver_override infrastructure
  s390/ap: use generic driver_override infrastructure
  s390/cio: use generic driver_override infrastructure
  vdpa: use generic driver_override infrastructure
  platform/wmi: use generic driver_override infrastructure
  PCI: use generic driver_override infrastructure
  driver core: make software nodes available earlier
  software node: remove software_node_exit()
  kernel: ksysfs: initialize kernel_kobj earlier
  MAINTAINERS: add ksysfs.c to the DRIVER CORE entry
  drivers/base/memory: fix stale reference to memory_block_add_nid()
  device property: Document how to check for the property presence
  soundwire: debugfs: initialize firmware_file to empty string
  debugfs: fix placement of EXPORT_SYMBOL_GPL for debugfs_create_str()
  debugfs: check for NULL pointer in debugfs_create_str()
  driver core: Make deferred_probe_timeout default a Kconfig option
  driver core: simplify __device_set_driver_override() clearing logic
  driver core: auxiliary bus: Drop auxiliary_dev_pm_ops
  device property: Make modifications of fwnode "flags" thread safe
  rust: devres: embed struct devres_node directly
  ...
parents d568788b 6c8dfb03
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -7807,8 +7807,10 @@ F: include/linux/debugfs.h
F:	include/linux/device.h
F:	include/linux/fwnode.h
F:	include/linux/kobj*
F:	include/linux/ksysfs.h
F:	include/linux/property.h
F:	include/linux/sysfs.h
F:	kernel/ksysfs.c
F:	lib/kobj*
F:	rust/kernel/debugfs.rs
F:	rust/kernel/debugfs/
+9 −0
Original line number Diff line number Diff line
@@ -73,6 +73,15 @@ config DEVTMPFS_SAFE
	  with the PROT_EXEC flag. This can break, for example, non-KMS
	  video drivers.

config DRIVER_DEFERRED_PROBE_TIMEOUT
	int "Default value for deferred_probe_timeout"
	default 0 if !MODULES
	default 10 if MODULES
	help
	  Set the default value for the deferred_probe_timeout kernel parameter.
	  See Documentation/admin-guide/kernel-parameters.txt for a description
	  of the deferred_probe_timeout kernel parameter.

config STANDALONE
	bool "Select only drivers that don't need compile-time external firmware"
	default y
+0 −6
Original line number Diff line number Diff line
@@ -207,11 +207,6 @@ static int auxiliary_uevent(const struct device *dev, struct kobj_uevent_env *en
			      (int)(p - name), name);
}

static const struct dev_pm_ops auxiliary_dev_pm_ops = {
	SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL)
	SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
};

static int auxiliary_bus_probe(struct device *dev)
{
	const struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver);
@@ -258,7 +253,6 @@ static const struct bus_type auxiliary_bus_type = {
	.shutdown = auxiliary_bus_shutdown,
	.match = auxiliary_match,
	.uevent = auxiliary_uevent,
	.pm = &auxiliary_dev_pm_ops,
};

/**
+60 −38
Original line number Diff line number Diff line
@@ -13,25 +13,26 @@
#include <linux/notifier.h>

/**
 * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
 *
 * @subsys - the struct kset that defines this subsystem
 * @devices_kset - the subsystem's 'devices' directory
 * @interfaces - list of subsystem interfaces associated
 * @mutex - protect the devices, and interfaces lists.
 *
 * @drivers_kset - the list of drivers associated
 * @klist_devices - the klist to iterate over the @devices_kset
 * @klist_drivers - the klist to iterate over the @drivers_kset
 * @bus_notifier - the bus notifier list for anything that cares about things
 * struct subsys_private - structure to hold the private to the driver core
 *			   portions of the bus_type/class structure.
 * @subsys: the struct kset that defines this subsystem
 * @devices_kset: the subsystem's 'devices' directory
 * @interfaces: list of subsystem interfaces associated
 * @mutex: protect the devices, and interfaces lists.
 * @drivers_kset: the list of drivers associated
 * @klist_devices: the klist to iterate over the @devices_kset
 * @klist_drivers: the klist to iterate over the @drivers_kset
 * @bus_notifier: the bus notifier list for anything that cares about things
 *		  on this bus.
 * @bus - pointer back to the struct bus_type that this structure is associated
 * @drivers_autoprobe: gate whether new devices are automatically attached to
 *		       registered drivers, or new drivers automatically attach
 *		       to existing devices.
 * @bus: pointer back to the struct bus_type that this structure is associated
 *	 with.
 * @dev_root: Default device to use as the parent.
 *
 * @glue_dirs - "glue" directory to put in-between the parent device to
 * @glue_dirs: "glue" directory to put in-between the parent device to
 *	       avoid namespace conflicts
 * @class - pointer back to the struct class that this structure is associated
 * @class: pointer back to the struct class that this structure is associated
 *	   with.
 * @lock_key: Lock class key for use by the lock validator
 *
@@ -98,22 +99,24 @@ struct driver_type {
#endif

/**
 * struct device_private - structure to hold the private to the driver core portions of the device structure.
 *
 * @klist_children - klist containing all children of this device
 * @knode_parent - node in sibling list
 * @knode_driver - node in driver list
 * @knode_bus - node in bus list
 * @knode_class - node in class list
 * @deferred_probe - entry in deferred_probe_list which is used to retry the
 *	binding of drivers which were unable to get all the resources needed by
 *	the device; typically because it depends on another driver getting
 *	probed first.
 * @async_driver - pointer to device driver awaiting probe via async_probe
 * @device - pointer back to the struct device that this structure is
 * struct device_private - structure to hold the private to the driver core
 *			   portions of the device structure.
 * @klist_children: klist containing all children of this device
 * @knode_parent: node in sibling list
 * @knode_driver: node in driver list
 * @knode_bus: node in bus list
 * @knode_class: node in class list
 * @deferred_probe: entry in deferred_probe_list which is used to retry the
 *		    binding of drivers which were unable to get all the
 *		    resources needed by the device; typically because it depends
 *		    on another driver getting probed first.
 * @async_driver: pointer to device driver awaiting probe via async_probe
 * @deferred_probe_reason: capture the -EPROBE_DEFER message emitted with
 *			   dev_err_probe() for later retrieval via debugfs
 * @device: pointer back to the struct device that this structure is
 *	    associated with.
 * @driver_type - The type of the bound Rust driver.
 * @dead - This device is currently either in the process of or has been
 * @driver_type: The type of the bound Rust driver.
 * @dead: This device is currently either in the process of or has been
 *	  removed from the system. Any asynchronous events scheduled for this
 *	  device should exit without taking any action.
 *
@@ -213,6 +216,24 @@ static inline void device_set_driver(struct device *dev, const struct device_dri
	WRITE_ONCE(dev->driver, (struct device_driver *)drv);
}

struct devres_node;
typedef void (*dr_node_release_t)(struct device *dev, struct devres_node *node);
typedef void (*dr_node_free_t)(struct devres_node *node);

struct devres_node {
	struct list_head		entry;
	dr_node_release_t		release;
	dr_node_free_t			free_node;
	const char			*name;
	size_t				size;
};

void devres_node_init(struct devres_node *node, dr_node_release_t release,
		      dr_node_free_t free_node);
void devres_node_add(struct device *dev, struct devres_node *node);
bool devres_node_remove(struct device *dev, struct devres_node *node);
void devres_set_node_dbginfo(struct devres_node *node, const char *name,
			     size_t size);
void devres_for_each_res(struct device *dev, dr_release_t release,
			 dr_match_t match, void *match_data,
			 void (*fn)(struct device *, void *, void *),
@@ -291,6 +312,7 @@ static inline int devtmpfs_create_node(struct device *dev) { return 0; }
static inline int devtmpfs_delete_node(struct device *dev) { return 0; }
#endif

void software_node_init(void);
void software_node_notify(struct device *dev);
void software_node_notify_remove(struct device *dev);

+15 −14
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ void fw_devlink_purge_absent_suppliers(struct fwnode_handle *fwnode)
	if (fwnode->dev)
		return;

	fwnode->flags |= FWNODE_FLAG_NOT_DEVICE;
	fwnode_set_flag(fwnode, FWNODE_FLAG_NOT_DEVICE);
	fwnode_links_purge_consumers(fwnode);

	fwnode_for_each_available_child_node(fwnode, child)
@@ -228,7 +228,7 @@ static void __fw_devlink_pickup_dangling_consumers(struct fwnode_handle *fwnode,
	if (fwnode->dev && fwnode->dev->bus)
		return;

	fwnode->flags |= FWNODE_FLAG_NOT_DEVICE;
	fwnode_set_flag(fwnode, FWNODE_FLAG_NOT_DEVICE);
	__fwnode_links_move_consumers(fwnode, new_sup);

	fwnode_for_each_available_child_node(fwnode, child)
@@ -1012,7 +1012,7 @@ static void device_links_missing_supplier(struct device *dev)
static bool dev_is_best_effort(struct device *dev)
{
	return (fw_devlink_best_effort && dev->can_match) ||
		(dev->fwnode && (dev->fwnode->flags & FWNODE_FLAG_BEST_EFFORT));
		(dev->fwnode && fwnode_test_flag(dev->fwnode, FWNODE_FLAG_BEST_EFFORT));
}

static struct fwnode_handle *fwnode_links_check_suppliers(
@@ -1723,11 +1723,11 @@ bool fw_devlink_is_strict(void)

static void fw_devlink_parse_fwnode(struct fwnode_handle *fwnode)
{
	if (fwnode->flags & FWNODE_FLAG_LINKS_ADDED)
	if (fwnode_test_flag(fwnode, FWNODE_FLAG_LINKS_ADDED))
		return;

	fwnode_call_int_op(fwnode, add_links);
	fwnode->flags |= FWNODE_FLAG_LINKS_ADDED;
	fwnode_set_flag(fwnode, FWNODE_FLAG_LINKS_ADDED);
}

static void fw_devlink_parse_fwtree(struct fwnode_handle *fwnode)
@@ -1885,7 +1885,7 @@ static bool fwnode_init_without_drv(struct fwnode_handle *fwnode)
	struct device *dev;
	bool ret;

	if (!(fwnode->flags & FWNODE_FLAG_INITIALIZED))
	if (!fwnode_test_flag(fwnode, FWNODE_FLAG_INITIALIZED))
		return false;

	dev = get_dev_from_fwnode(fwnode);
@@ -2001,10 +2001,10 @@ static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
	 * We aren't trying to find all cycles. Just a cycle between con and
	 * sup_handle.
	 */
	if (sup_handle->flags & FWNODE_FLAG_VISITED)
	if (fwnode_test_flag(sup_handle, FWNODE_FLAG_VISITED))
		return false;

	sup_handle->flags |= FWNODE_FLAG_VISITED;
	fwnode_set_flag(sup_handle, FWNODE_FLAG_VISITED);

	/* Termination condition. */
	if (sup_handle == con_handle) {
@@ -2074,7 +2074,7 @@ static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
	}

out:
	sup_handle->flags &= ~FWNODE_FLAG_VISITED;
	fwnode_clear_flag(sup_handle, FWNODE_FLAG_VISITED);
	put_device(sup_dev);
	put_device(con_dev);
	put_device(par_dev);
@@ -2127,7 +2127,7 @@ static int fw_devlink_create_devlink(struct device *con,
	 * When such a flag is set, we can't create device links where P is the
	 * supplier of C as that would delay the probe of C.
	 */
	if (sup_handle->flags & FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD &&
	if (fwnode_test_flag(sup_handle, FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD) &&
	    fwnode_is_ancestor_of(sup_handle, con->fwnode))
		return -EINVAL;

@@ -2150,7 +2150,7 @@ static int fw_devlink_create_devlink(struct device *con,
	else
		flags = FW_DEVLINK_FLAGS_PERMISSIVE;

	if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE)
	if (fwnode_test_flag(sup_handle, FWNODE_FLAG_NOT_DEVICE))
		sup_dev = fwnode_get_next_parent_dev(sup_handle);
	else
		sup_dev = get_dev_from_fwnode(sup_handle);
@@ -2162,7 +2162,7 @@ static int fw_devlink_create_devlink(struct device *con,
		 * supplier device indefinitely.
		 */
		if (sup_dev->links.status == DL_DEV_NO_DRIVER &&
		    sup_handle->flags & FWNODE_FLAG_INITIALIZED) {
		    fwnode_test_flag(sup_handle, FWNODE_FLAG_INITIALIZED)) {
			dev_dbg(con,
				"Not linking %pfwf - dev might never probe\n",
				sup_handle);
@@ -2831,14 +2831,15 @@ static ssize_t removable_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(removable);

int device_add_groups(struct device *dev, const struct attribute_group **groups)
int device_add_groups(struct device *dev,
		      const struct attribute_group *const *groups)
{
	return sysfs_create_groups(&dev->kobj, groups);
}
EXPORT_SYMBOL_GPL(device_add_groups);

void device_remove_groups(struct device *dev,
			  const struct attribute_group **groups)
			  const struct attribute_group *const *groups)
{
	sysfs_remove_groups(&dev->kobj, groups);
}
Loading