Merge tag 'driver-core-6.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core api addition from Greg KH:
"Here is a driver core new api for 6.14-rc3 that is being added to
allow platform devices from stop being abused.

It adds a new 'faux_device' structure and bus and api to allow almost
a straight or simpler conversion from platform devices that were not
really a platform device. It also comes with a binding for rust, with
an example driver in rust showing how it's used.

I'm adding this now so that the patches that convert the different
drivers and subsystems can all start flowing into linux-next now
through their different development trees, in time for 6.15-rc1.

We have a number that are already reviewed and tested, but adding
those conversions now doesn't seem right. For now, no one is using
this, and it passes all build tests from 0-day and linux-next, so all
should be good"

* tag 'driver-core-6.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
rust/kernel: Add faux device bindings
driver core: add a faux bus for use when a simple device/bus is needed

Changed files
+421 -1
Documentation
driver-api
drivers
include
linux
device
rust
bindings
kernel
samples
+6
Documentation/driver-api/infrastructure.rst
··· 41 41 .. kernel-doc:: drivers/base/class.c 42 42 :export: 43 43 44 + .. kernel-doc:: include/linux/device/faux.h 45 + :internal: 46 + 47 + .. kernel-doc:: drivers/base/faux.c 48 + :export: 49 + 44 50 .. kernel-doc:: drivers/base/node.c 45 51 :internal: 46 52
+2
MAINTAINERS
··· 7108 7108 F: rust/kernel/device_id.rs 7109 7109 F: rust/kernel/devres.rs 7110 7110 F: rust/kernel/driver.rs 7111 + F: rust/kernel/faux.rs 7111 7112 F: rust/kernel/platform.rs 7112 7113 F: samples/rust/rust_driver_platform.rs 7114 + F: samples/rust/rust_driver_faux.rs 7113 7115 7114 7116 DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS) 7115 7117 M: Nishanth Menon <nm@ti.com>
+1 -1
drivers/base/Makefile
··· 6 6 cpu.o firmware.o init.o map.o devres.o \ 7 7 attribute_container.o transport_class.o \ 8 8 topology.o container.o property.o cacheinfo.o \ 9 - swnode.o 9 + swnode.o faux.o 10 10 obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o 11 11 obj-$(CONFIG_DEVTMPFS) += devtmpfs.o 12 12 obj-y += power/
+1
drivers/base/base.h
··· 137 137 static inline int hypervisor_init(void) { return 0; } 138 138 #endif 139 139 int platform_bus_init(void); 140 + int faux_bus_init(void); 140 141 void cpu_dev_init(void); 141 142 void container_dev_init(void); 142 143 #ifdef CONFIG_AUXILIARY_BUS
+232
drivers/base/faux.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2025 Greg Kroah-Hartman <gregkh@linuxfoundation.org> 4 + * Copyright (c) 2025 The Linux Foundation 5 + * 6 + * A "simple" faux bus that allows devices to be created and added 7 + * automatically to it. This is to be used whenever you need to create a 8 + * device that is not associated with any "real" system resources, and do 9 + * not want to have to deal with a bus/driver binding logic. It is 10 + * intended to be very simple, with only a create and a destroy function 11 + * available. 12 + */ 13 + #include <linux/err.h> 14 + #include <linux/init.h> 15 + #include <linux/slab.h> 16 + #include <linux/string.h> 17 + #include <linux/container_of.h> 18 + #include <linux/device/faux.h> 19 + #include "base.h" 20 + 21 + /* 22 + * Internal wrapper structure so we can hold a pointer to the 23 + * faux_device_ops for this device. 24 + */ 25 + struct faux_object { 26 + struct faux_device faux_dev; 27 + const struct faux_device_ops *faux_ops; 28 + }; 29 + #define to_faux_object(dev) container_of_const(dev, struct faux_object, faux_dev.dev) 30 + 31 + static struct device faux_bus_root = { 32 + .init_name = "faux", 33 + }; 34 + 35 + static int faux_match(struct device *dev, const struct device_driver *drv) 36 + { 37 + /* Match always succeeds, we only have one driver */ 38 + return 1; 39 + } 40 + 41 + static int faux_probe(struct device *dev) 42 + { 43 + struct faux_object *faux_obj = to_faux_object(dev); 44 + struct faux_device *faux_dev = &faux_obj->faux_dev; 45 + const struct faux_device_ops *faux_ops = faux_obj->faux_ops; 46 + int ret = 0; 47 + 48 + if (faux_ops && faux_ops->probe) 49 + ret = faux_ops->probe(faux_dev); 50 + 51 + return ret; 52 + } 53 + 54 + static void faux_remove(struct device *dev) 55 + { 56 + struct faux_object *faux_obj = to_faux_object(dev); 57 + struct faux_device *faux_dev = &faux_obj->faux_dev; 58 + const struct faux_device_ops *faux_ops = faux_obj->faux_ops; 59 + 60 + if (faux_ops && faux_ops->remove) 61 + faux_ops->remove(faux_dev); 62 + } 63 + 64 + static const struct bus_type faux_bus_type = { 65 + .name = "faux", 66 + .match = faux_match, 67 + .probe = faux_probe, 68 + .remove = faux_remove, 69 + }; 70 + 71 + static struct device_driver faux_driver = { 72 + .name = "faux_driver", 73 + .bus = &faux_bus_type, 74 + .probe_type = PROBE_FORCE_SYNCHRONOUS, 75 + }; 76 + 77 + static void faux_device_release(struct device *dev) 78 + { 79 + struct faux_object *faux_obj = to_faux_object(dev); 80 + 81 + kfree(faux_obj); 82 + } 83 + 84 + /** 85 + * faux_device_create_with_groups - Create and register with the driver 86 + * core a faux device and populate the device with an initial 87 + * set of sysfs attributes. 88 + * @name: The name of the device we are adding, must be unique for 89 + * all faux devices. 90 + * @parent: Pointer to a potential parent struct device. If set to 91 + * NULL, the device will be created in the "root" of the faux 92 + * device tree in sysfs. 93 + * @faux_ops: struct faux_device_ops that the new device will call back 94 + * into, can be NULL. 95 + * @groups: The set of sysfs attributes that will be created for this 96 + * device when it is registered with the driver core. 97 + * 98 + * Create a new faux device and register it in the driver core properly. 99 + * If present, callbacks in @faux_ops will be called with the device that 100 + * for the caller to do something with at the proper time given the 101 + * device's lifecycle. 102 + * 103 + * Note, when this function is called, the functions specified in struct 104 + * faux_ops can be called before the function returns, so be prepared for 105 + * everything to be properly initialized before that point in time. 106 + * 107 + * Return: 108 + * * NULL if an error happened with creating the device 109 + * * pointer to a valid struct faux_device that is registered with sysfs 110 + */ 111 + struct faux_device *faux_device_create_with_groups(const char *name, 112 + struct device *parent, 113 + const struct faux_device_ops *faux_ops, 114 + const struct attribute_group **groups) 115 + { 116 + struct faux_object *faux_obj; 117 + struct faux_device *faux_dev; 118 + struct device *dev; 119 + int ret; 120 + 121 + faux_obj = kzalloc(sizeof(*faux_obj), GFP_KERNEL); 122 + if (!faux_obj) 123 + return NULL; 124 + 125 + /* Save off the callbacks so we can use them in the future */ 126 + faux_obj->faux_ops = faux_ops; 127 + 128 + /* Initialize the device portion and register it with the driver core */ 129 + faux_dev = &faux_obj->faux_dev; 130 + dev = &faux_dev->dev; 131 + 132 + device_initialize(dev); 133 + dev->release = faux_device_release; 134 + if (parent) 135 + dev->parent = parent; 136 + else 137 + dev->parent = &faux_bus_root; 138 + dev->bus = &faux_bus_type; 139 + dev->groups = groups; 140 + dev_set_name(dev, "%s", name); 141 + 142 + ret = device_add(dev); 143 + if (ret) { 144 + pr_err("%s: device_add for faux device '%s' failed with %d\n", 145 + __func__, name, ret); 146 + put_device(dev); 147 + return NULL; 148 + } 149 + 150 + return faux_dev; 151 + } 152 + EXPORT_SYMBOL_GPL(faux_device_create_with_groups); 153 + 154 + /** 155 + * faux_device_create - create and register with the driver core a faux device 156 + * @name: The name of the device we are adding, must be unique for all 157 + * faux devices. 158 + * @parent: Pointer to a potential parent struct device. If set to 159 + * NULL, the device will be created in the "root" of the faux 160 + * device tree in sysfs. 161 + * @faux_ops: struct faux_device_ops that the new device will call back 162 + * into, can be NULL. 163 + * 164 + * Create a new faux device and register it in the driver core properly. 165 + * If present, callbacks in @faux_ops will be called with the device that 166 + * for the caller to do something with at the proper time given the 167 + * device's lifecycle. 168 + * 169 + * Note, when this function is called, the functions specified in struct 170 + * faux_ops can be called before the function returns, so be prepared for 171 + * everything to be properly initialized before that point in time. 172 + * 173 + * Return: 174 + * * NULL if an error happened with creating the device 175 + * * pointer to a valid struct faux_device that is registered with sysfs 176 + */ 177 + struct faux_device *faux_device_create(const char *name, 178 + struct device *parent, 179 + const struct faux_device_ops *faux_ops) 180 + { 181 + return faux_device_create_with_groups(name, parent, faux_ops, NULL); 182 + } 183 + EXPORT_SYMBOL_GPL(faux_device_create); 184 + 185 + /** 186 + * faux_device_destroy - destroy a faux device 187 + * @faux_dev: faux device to destroy 188 + * 189 + * Unregisters and cleans up a device that was created with a call to 190 + * faux_device_create() 191 + */ 192 + void faux_device_destroy(struct faux_device *faux_dev) 193 + { 194 + struct device *dev = &faux_dev->dev; 195 + 196 + if (!faux_dev) 197 + return; 198 + 199 + device_del(dev); 200 + 201 + /* The final put_device() will clean up the memory we allocated for this device. */ 202 + put_device(dev); 203 + } 204 + EXPORT_SYMBOL_GPL(faux_device_destroy); 205 + 206 + int __init faux_bus_init(void) 207 + { 208 + int ret; 209 + 210 + ret = device_register(&faux_bus_root); 211 + if (ret) { 212 + put_device(&faux_bus_root); 213 + return ret; 214 + } 215 + 216 + ret = bus_register(&faux_bus_type); 217 + if (ret) 218 + goto error_bus; 219 + 220 + ret = driver_register(&faux_driver); 221 + if (ret) 222 + goto error_driver; 223 + 224 + return ret; 225 + 226 + error_driver: 227 + bus_unregister(&faux_bus_type); 228 + 229 + error_bus: 230 + device_unregister(&faux_bus_root); 231 + return ret; 232 + }
+1
drivers/base/init.c
··· 32 32 /* These are also core pieces, but must come after the 33 33 * core core pieces. 34 34 */ 35 + faux_bus_init(); 35 36 of_core_init(); 36 37 platform_bus_init(); 37 38 auxiliary_bus_init();
+69
include/linux/device/faux.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2025 Greg Kroah-Hartman <gregkh@linuxfoundation.org> 4 + * Copyright (c) 2025 The Linux Foundation 5 + * 6 + * A "simple" faux bus that allows devices to be created and added 7 + * automatically to it. This is to be used whenever you need to create a 8 + * device that is not associated with any "real" system resources, and do 9 + * not want to have to deal with a bus/driver binding logic. It is 10 + * intended to be very simple, with only a create and a destroy function 11 + * available. 12 + */ 13 + #ifndef _FAUX_DEVICE_H_ 14 + #define _FAUX_DEVICE_H_ 15 + 16 + #include <linux/container_of.h> 17 + #include <linux/device.h> 18 + 19 + /** 20 + * struct faux_device - a "faux" device 21 + * @dev: internal struct device of the object 22 + * 23 + * A simple faux device that can be created/destroyed. To be used when a 24 + * driver only needs to have a device to "hang" something off. This can be 25 + * used for downloading firmware or other basic tasks. Use this instead of 26 + * a struct platform_device if the device has no resources assigned to 27 + * it at all. 28 + */ 29 + struct faux_device { 30 + struct device dev; 31 + }; 32 + #define to_faux_device(x) container_of_const((x), struct faux_device, dev) 33 + 34 + /** 35 + * struct faux_device_ops - a set of callbacks for a struct faux_device 36 + * @probe: called when a faux device is probed by the driver core 37 + * before the device is fully bound to the internal faux bus 38 + * code. If probe succeeds, return 0, otherwise return a 39 + * negative error number to stop the probe sequence from 40 + * succeeding. 41 + * @remove: called when a faux device is removed from the system 42 + * 43 + * Both @probe and @remove are optional, if not needed, set to NULL. 44 + */ 45 + struct faux_device_ops { 46 + int (*probe)(struct faux_device *faux_dev); 47 + void (*remove)(struct faux_device *faux_dev); 48 + }; 49 + 50 + struct faux_device *faux_device_create(const char *name, 51 + struct device *parent, 52 + const struct faux_device_ops *faux_ops); 53 + struct faux_device *faux_device_create_with_groups(const char *name, 54 + struct device *parent, 55 + const struct faux_device_ops *faux_ops, 56 + const struct attribute_group **groups); 57 + void faux_device_destroy(struct faux_device *faux_dev); 58 + 59 + static inline void *faux_device_get_drvdata(const struct faux_device *faux_dev) 60 + { 61 + return dev_get_drvdata(&faux_dev->dev); 62 + } 63 + 64 + static inline void faux_device_set_drvdata(struct faux_device *faux_dev, void *data) 65 + { 66 + dev_set_drvdata(&faux_dev->dev, data); 67 + } 68 + 69 + #endif /* _FAUX_DEVICE_H_ */
+1
rust/bindings/bindings_helper.h
··· 11 11 #include <linux/blk_types.h> 12 12 #include <linux/blkdev.h> 13 13 #include <linux/cred.h> 14 + #include <linux/device/faux.h> 14 15 #include <linux/errname.h> 15 16 #include <linux/ethtool.h> 16 17 #include <linux/file.h>
+67
rust/kernel/faux.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + //! Abstractions for the faux bus. 4 + //! 5 + //! This module provides bindings for working with faux devices in kernel modules. 6 + //! 7 + //! C header: [`include/linux/device/faux.h`] 8 + 9 + use crate::{bindings, device, error::code::*, prelude::*}; 10 + use core::ptr::{addr_of_mut, null, null_mut, NonNull}; 11 + 12 + /// The registration of a faux device. 13 + /// 14 + /// This type represents the registration of a [`struct faux_device`]. When an instance of this type 15 + /// is dropped, its respective faux device will be unregistered from the system. 16 + /// 17 + /// # Invariants 18 + /// 19 + /// `self.0` always holds a valid pointer to an initialized and registered [`struct faux_device`]. 20 + /// 21 + /// [`struct faux_device`]: srctree/include/linux/device/faux.h 22 + #[repr(transparent)] 23 + pub struct Registration(NonNull<bindings::faux_device>); 24 + 25 + impl Registration { 26 + /// Create and register a new faux device with the given name. 27 + pub fn new(name: &CStr) -> Result<Self> { 28 + // SAFETY: 29 + // - `name` is copied by this function into its own storage 30 + // - `faux_ops` is safe to leave NULL according to the C API 31 + let dev = unsafe { bindings::faux_device_create(name.as_char_ptr(), null_mut(), null()) }; 32 + 33 + // The above function will return either a valid device, or NULL on failure 34 + // INVARIANT: The device will remain registered until faux_device_destroy() is called, which 35 + // happens in our Drop implementation. 36 + Ok(Self(NonNull::new(dev).ok_or(ENODEV)?)) 37 + } 38 + 39 + fn as_raw(&self) -> *mut bindings::faux_device { 40 + self.0.as_ptr() 41 + } 42 + } 43 + 44 + impl AsRef<device::Device> for Registration { 45 + fn as_ref(&self) -> &device::Device { 46 + // SAFETY: The underlying `device` in `faux_device` is guaranteed by the C API to be 47 + // a valid initialized `device`. 48 + unsafe { device::Device::as_ref(addr_of_mut!((*self.as_raw()).dev)) } 49 + } 50 + } 51 + 52 + impl Drop for Registration { 53 + fn drop(&mut self) { 54 + // SAFETY: `self.0` is a valid registered faux_device via our type invariants. 55 + unsafe { bindings::faux_device_destroy(self.as_raw()) } 56 + } 57 + } 58 + 59 + // SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as 60 + // faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not 61 + // having Copy/Clone. 62 + unsafe impl Send for Registration {} 63 + 64 + // SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as 65 + // faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not 66 + // having Copy/Clone. 67 + unsafe impl Sync for Registration {}
+1
rust/kernel/lib.rs
··· 46 46 pub mod devres; 47 47 pub mod driver; 48 48 pub mod error; 49 + pub mod faux; 49 50 #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)] 50 51 pub mod firmware; 51 52 pub mod fs;
+10
samples/rust/Kconfig
··· 61 61 62 62 If unsure, say N. 63 63 64 + config SAMPLE_RUST_DRIVER_FAUX 65 + tristate "Faux Driver" 66 + help 67 + This option builds the Rust Faux driver sample. 68 + 69 + To compile this as a module, choose M here: 70 + the module will be called rust_driver_faux. 71 + 72 + If unsure, say N. 73 + 64 74 config SAMPLE_RUST_HOSTPROGS 65 75 bool "Host programs" 66 76 help
+1
samples/rust/Makefile
··· 6 6 obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o 7 7 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o 8 8 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o 9 + obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o 9 10 10 11 rust_print-y := rust_print_main.o rust_print_events.o 11 12
+29
samples/rust/rust_driver_faux.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + //! Rust faux device sample. 4 + 5 + use kernel::{c_str, faux, prelude::*, Module}; 6 + 7 + module! { 8 + type: SampleModule, 9 + name: "rust_faux_driver", 10 + author: "Lyude Paul", 11 + description: "Rust faux device sample", 12 + license: "GPL", 13 + } 14 + 15 + struct SampleModule { 16 + _reg: faux::Registration, 17 + } 18 + 19 + impl Module for SampleModule { 20 + fn init(_module: &'static ThisModule) -> Result<Self> { 21 + pr_info!("Initialising Rust Faux Device Sample\n"); 22 + 23 + let reg = faux::Registration::new(c_str!("rust-faux-sample-device"))?; 24 + 25 + dev_info!(reg.as_ref(), "Hello from faux device!\n"); 26 + 27 + Ok(Self { _reg: reg }) 28 + } 29 + }