mirror-linux/drivers/base
Danilo Krummrich 6f61a2637a rust: device: introduce Device::drvdata()
In C dev_get_drvdata() has specific requirements under which it is valid
to access the returned pointer. That is, drivers have to ensure that

  (1) for the duration the returned pointer is accessed the driver is
      bound and remains to be bound to the corresponding device,

  (2) the returned void * is treated according to the driver's private
      data type, i.e. according to what has been passed to
      dev_set_drvdata().

In Rust, (1) can be ensured by simply requiring the Bound device
context, i.e. provide the drvdata() method for Device<Bound> only.

For (2) we would usually make the device type generic over the driver
type, e.g. Device<T: Driver>, where <T as Driver>::Data is the type of
the driver's private data.

However, a device does not have a driver type known at compile time and
may be bound to multiple drivers throughout its lifetime.

Hence, in order to be able to provide a safe accessor for the driver's
device private data, we have to do the type check on runtime.

This is achieved by letting a driver assert the expected type, which is
then compared to a type hash stored in struct device_private when
dev_set_drvdata() is called.

Example:

	// `dev` is a `&Device<Bound>`.
	let data = dev.drvdata::<SampleDriver>()?;

There are two aspects to note:

  (1) Technically, the same check could be achieved by comparing the
      struct device_driver pointer of struct device with the struct
      device_driver pointer of the driver struct (e.g. struct
      pci_driver).

      However, this would - in addition the pointer comparison - require
      to tie back the private driver data type to the struct
      device_driver pointer of the driver struct to prove correctness.

      Besides that, accessing the driver struct (stored in the module
      structure) isn't trivial and would result into horrible code and
      API ergonomics.

  (2) Having a direct accessor to the driver's private data is not
      commonly required (at least in Rust): Bus callback methods already
      provide access to the driver's device private data through a &self
      argument, while other driver entry points such as IRQs,
      workqueues, timers, IOCTLs, etc. have their own private data with
      separate ownership and lifetime.

      In other words, a driver's device private data is only relevant
      for driver model contexts (such a file private is only relevant
      for file contexts).

Having that said, the motivation for accessing the driver's device
private data with Device<Bound>::drvdata() are interactions between
drivers. For instance, when an auxiliary driver calls back into its
parent, the parent has to be capable to derive its private data from the
corresponding device (i.e. the parent of the auxiliary device).

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ * Remove unnecessary `const _: ()` block,
  * rename type_id_{store,match}() to {set,match}_type_id(),
  * assert size_of::<bindings::driver_type>() >= size_of::<TypeId>(),
  * add missing check in case Device::drvdata() is called from probe().

  - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-29 18:18:02 +01:00
..
firmware_loader firmware_loader: Replace simple_strtol() with kstrtoint() 2025-10-22 08:09:25 +02:00
power Merge branches 'pm-core' and 'pm-runtime' 2025-10-07 12:20:36 +02:00
regmap regmap: use int type to store negative error codes 2025-08-28 17:18:40 +02:00
test drivers: base: test: Add ...find_device_by...(... NULL) tests 2024-12-24 09:48:09 +01:00
Kconfig PM: runtime: Add basic kunit tests for API contracts 2025-09-27 13:41:47 +02:00
Makefile driver core: add a faux bus for use when a simple device/bus is needed 2025-02-13 16:58:51 +01:00
arch_numa.c arch_numa: Restore nid checks before registering a memblock with a node 2024-12-01 22:04:52 +02:00
arch_topology.c Merge 6.18-rc3 into driver-core-next 2025-10-27 08:02:50 +01:00
attribute_container.c driver core: attribute_container: Remove unused functions 2024-09-13 15:41:42 +02:00
auxiliary.c driver core: auxiliary bus: Optimize logic of auxiliary_match_id() 2025-09-06 20:12:36 +02:00
auxiliary_sysfs.c driver core: auxiliary bus: show auxiliary device IRQs 2024-07-11 14:17:03 -07:00
base.h rust: device: introduce Device::drvdata() 2025-10-29 18:18:02 +01:00
bus.c driver core: fix potential NULL pointer dereference in dev_uevent() 2025-04-15 17:04:35 +02:00
cacheinfo.c cacheinfo: Add arch hook to compress CPU h/w id into 32 bits for cache-id 2025-07-16 15:04:27 +02:00
class.c drivers: core: remove device_link argument from class_compat_[create|remove]_link 2025-01-10 15:42:20 +01:00
component.c component: do not try to unbind unbound components 2025-04-15 18:05:40 +02:00
container.c
core.c driver core: fw_devlink: Don't warn about sync_state() pending 2025-10-17 09:47:40 +02:00
cpu.c Merge 6.17-rc6 into driver-core-next 2025-09-15 08:26:05 +02:00
dd.c PM: domains: Detach on device_unbind_cleanup() 2025-07-07 20:41:21 +02:00
devcoredump.c devcoredump: Fix circular locking dependency with devcd->mutex. 2025-10-17 09:47:40 +02:00
devres.c devres: provide devm_kmemdup_const() 2025-09-08 14:21:23 +02:00
devtmpfs.c VFS: rename kern_path_locked() and related functions. 2025-09-23 12:37:36 +02:00
driver.c driver core: Introduce device_iter_t for device iterating APIs 2025-01-10 15:26:12 +01:00
faux.c driver core: faux: Set power.no_pm for faux devices 2025-09-06 13:58:00 +02:00
firmware.c
hypervisor.c
init.c driver core: add a faux bus for use when a simple device/bus is needed 2025-02-13 16:58:51 +01:00
isa.c
map.c
memory.c drivers/base: move memory_block_add_nid() into the caller 2025-10-03 16:42:43 -07:00
module.c drivers: base: handle module_kobject creation 2025-04-16 15:10:55 +02:00
node.c Only two patch series in this pull request: 2025-10-05 12:11:07 -07:00
physical_location.c driver core: location: Use str_yes_no() helper function 2025-02-21 09:20:30 +01:00
physical_location.h
pinctrl.c
platform-msi.c platform-msi: Add msi_remove_device_irq_domain() in platform_device_msi_free_irqs_all() 2025-05-07 17:49:00 +02:00
platform.c driver core: platform: Drop dev_pm_domain_detach() call 2025-07-07 20:41:21 +02:00
property.c ACPI: Add support for nargs_prop in acpi_fwnode_get_reference_args() 2025-09-25 19:48:47 -06:00
soc.c
swnode.c software node: Constify node_group in registration functions 2025-08-17 13:18:07 +02:00
syscore.c
topology.c sysfs: treewide: switch back to attribute_group::bin_attrs 2025-06-17 10:44:15 +02:00
trace.c
trace.h devres: Fix page faults when tracing devres from unloaded modules 2024-10-14 08:21:09 +02:00
transport_class.c