Device / Driver PCI / Platform Rust abstractions
Subsystems (13)
Danilo Krummrich
maintainerv5 cover Device / Driver PCI / Platform Rust abstractions
This patch series implements the necessary Rust abstractions to implement device drivers in Rust.
This includes some basic generalizations for driver registration, handling of ID tables, MMIO operations and device resource handling.
Those generalizations are used to implement device driver support for two busses, the PCI and platform bus (with OF IDs) in order to provide some evidence that the generalizations work as intended.
The patch series also includes two patches adding two driver samples, one PCI driver and one platform driver.
The PCI bits are motivated by the Nova driver project [1], but are used by at least one more OOT driver (rnvme [2]).
The platform bits, besides adding some more evidence to the base abstractions, are required by a few more OOT drivers aiming at going upstream, i.e. rvkms [3], cpufreq-dt [4], asahi [5] and the i2c work from Fabien [6].
The patches of this series can also be [7], [8] and [9].
Changes in v5:
==============
- Opaque:
- add Opaque::pin_init
- Revocable:
- use const generic instead of bool in revoke_internal
- don't open code things with Opaque::try_ffi_init, use Opaque::pin_init instead
- Driver:
- fix DriverOps -> RegistrationOps in commit message
- fix signature of register and unregister to take an Opaque<T::RegType> instead of a mutable reference
- implement generic driver::Adapter
- ID table:
- fix module_device_table! macro, according to commit 054a9cd395a7 (modpost: rename alias symbol for MODULE_DEVICE_TABLE())
- PCI:
- remove pci::DeviceId argument from probe()
- provide vendor_id and device_id accessor functions
- use addr_of_mut! for the device in probe()
- OF:
- move OF IdTable type alias from platform.rs to of.rs
- Platform:
- use addr_of_mut! for the device in probe()
- move generic OF code to driver::Adapter
- MISC:
- rebase onto latest rust-next (-rc2)
Changes in v4:
==============
- Revocable
- convert Revocable::data to Opaque
- introduce revoke_nosync, which does not wait for an RCU grace period
- fix minor typo
- Device ID
- fix ID table export name to always be unique
- remove #![allow(stable_features)]
- move #![allow(const_refs_to_cell)] to the "stable in 1.83" list
- I/O
- split Io<SIZE> in IoRaw<SIZE> and Io<SIZE>
- add rust helper for ioremap() and iounmap() (needed by doctests)
- Devres
- optimze drop by using revoke_nosync (we're guaranteed there are no more concurrent users, hence no need to wait for a full grace period)
- OF
- rename "Open Firmware" -> "Device Tree / Open Firmware" (Rob)
- remove unused C header reference
- add TODO comment to loop in DeviceId::new
- remove DeviceId::compatible; was only used in sample code
- add missing #[repr(transparent)]
- use #[cfg(CONFIG_OF)] for the relevant functions
- PCI
- let Rust helper for pci_resource_len() return resource_size_t
- PCI Sample
- remove unnecessary from_le
- Platform
- fix example compatible string
- add example for platform::Driver
- rename ID_TABLE to OF_ID_TABLE
- don't allow public use of of_match_table; convert to of_id_info to retrieve the of::DeviceId to gather the corresponding IdInfo
- remove wrong example reference in the documentation of platform::Driver
- remove as_dev, as we already implement AsRef for platform::Device
- Platform Sample
- fix compatible string; add corresponding entry to drivers/of/unittest-data/tests-platform.dtsi
- remove usage of of_match_table
- MISC
- fix a few spelling mistakes
- rebase onto rust-next (v6.13-rc1)
Changes in v3:
==============
- add commits for Opaque::try_ffi_init and InPlaceModule
- rename DriverOps to RegistrationOps
- rework device ID abstractions to get rid of almost all macro magic (thanks to Gary Guo for working this out!)
- this is possible due to recently stabilized language features
- add modpost alias generation for device ID tables
- unfortunately, this is the part that still requires some macro magic in the device ID abstractions
- PCI
- represent the driver private data with the driver specific Driver instance and bind it's lifetime to the time of the driver being bound to a device
- this allows us to handle class / subsystem registrations in a cleaner way
- get rid of Driver::remove
- Rust drivers should bind cleanup code to the Drop implementation of the corresponding structure instead and put it into their driver structure for automatic cleanup
- add a sample PCI driver
- add abstractions for struct of_device_id
- add abstractions for the platform bus, including a sample driver
- update the MAINTAINERS file accordingly
- currently this turns out a bit messy, but it should become better once the build system supports a treewide distribution of the kernel crate
- I didn't add myself as maintainer, but (if requested) I'm willing to do so and help with maintenance
Changes in v2:
==============
- statically initialize driver structures (Greg)
- move base device ID abstractions to a separate source file (Greg)
- remove DeviceRemoval trait in favor of using a Devres callback to unregister drivers
- remove device::Data, we don't need this abstraction anymore now that we Devres to revoke resources and registrations
- pass the module name to Module::init and InPlaceModule::init in a separate patch
- rework of Io including compile time boundary checks (Miguel, Wedson)
- adjust PCI abstractions accordingly and implement a module_pci_driver! macro
- rework pci::Bar to support a const SIZE
- increase the total amount of Documentation, rephrase some safety comments and commit messages for less ambiguity
- fix compilation issues with some documentation examples
[1] https://gitlab.freedesktop.org/drm/nova/-/tree/nova-next
[2] https://github.com/metaspace/linux/tree/rnvme
[3] https://lore.kernel.org/all/[email protected]/
[4] https://git.kernel.org/pub/scm/linux/kernel/git/vireshk/linux.git/log/?h=rust/cpufreq-dt
[5] https://github.com/AsahiLinux/linux
[6] https://github.com/Fabo/linux/tree/fparent/rust-i2c
[7] https://github.com/Rust-for-Linux/linux/tree/staging/rust-device
[8] https://github.com/Rust-for-Linux/linux/tree/staging/rust-pci
[9] https://github.com/Rust-for-Linux/linux/tree/staging/dev
Danilo Krummrich (14):
rust: pass module name to Module::init
rust: implement generic driver registration
rust: implement IdArray, IdTable and RawDeviceId
rust: types: add Opaque::pin_init
rust: add io::{Io, IoRaw} base types
rust: add devres abstraction
rust: pci: add basic PCI device / driver abstractions
rust: pci: implement I/O mappable pci::Bar
samples: rust: add Rust PCI sample driver
rust: of: add of::DeviceId abstraction
rust: driver: implement Adapter
rust: platform: add basic platform device / driver abstractions
samples: rust: add Rust platform sample driver
MAINTAINERS: add Danilo to DRIVER CORE
Wedson Almeida Filho (2):
rust: add rcu abstraction
rust: add Revocable type
MAINTAINERS | 9 + drivers/block/rnull.rs | 2 +- drivers/of/unittest-data/tests-platform.dtsi | 5 + rust/bindings/bindings_helper.h | 3 + rust/helpers/device.c | 10 + rust/helpers/helpers.c | 5 + rust/helpers/io.c | 101 +++++ rust/helpers/pci.c | 18 + rust/helpers/platform.c | 13 + rust/helpers/rcu.c | 13 + rust/kernel/device_id.rs | 165 +++++++ rust/kernel/devres.rs | 179 ++++++++ rust/kernel/driver.rs | 173 ++++++++ rust/kernel/io.rs | 260 +++++++++++ rust/kernel/lib.rs | 28 +- rust/kernel/net/phy.rs | 2 +- rust/kernel/of.rs | 60 +++ rust/kernel/pci.rs | 438 +++++++++++++++++++ rust/kernel/platform.rs | 193 ++++++++ rust/kernel/revocable.rs | 223 ++++++++++ rust/kernel/sync.rs | 1 + rust/kernel/sync/lock/global.rs | 6 +- rust/kernel/sync/rcu.rs | 47 ++ rust/kernel/types.rs | 11 + rust/macros/lib.rs | 6 +- rust/macros/module.rs | 7 +- samples/rust/Kconfig | 21 + samples/rust/Makefile | 2 + samples/rust/rust_driver_pci.rs | 110 +++++ samples/rust/rust_driver_platform.rs | 49 +++ samples/rust/rust_minimal.rs | 2 +- samples/rust/rust_print_main.rs | 2 +- 32 files changed, 2150 insertions(+), 14 deletions(-) create mode 100644 rust/helpers/device.c create mode 100644 rust/helpers/io.c create mode 100644 rust/helpers/pci.c create mode 100644 rust/helpers/platform.c create mode 100644 rust/helpers/rcu.c create mode 100644 rust/kernel/device_id.rs create mode 100644 rust/kernel/devres.rs create mode 100644 rust/kernel/driver.rs create mode 100644 rust/kernel/io.rs create mode 100644 rust/kernel/of.rs create mode 100644 rust/kernel/pci.rs create mode 100644 rust/kernel/platform.rs create mode 100644 rust/kernel/revocable.rs create mode 100644 rust/kernel/sync/rcu.rs create mode 100644 samples/rust/rust_driver_pci.rs create mode 100644 samples/rust/rust_driver_platform.rs
base-commit: fac04efc5c793dccbd07e2d59af9f90b7fc0dca4
Signature · 1 line
2.47.0
Danilo Krummrich
maintainerPATCH v5 1/16 rust: pass module name to `Module::init`
In a subsequent patch we introduce the Registration abstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in __pci_register_driver()), hence pass the module name to Module::init.
--- drivers/block/rnull.rs | 2 +- rust/kernel/lib.rs | 14 ++++++++++---- rust/kernel/net/phy.rs | 2 +- rust/kernel/sync/lock/global.rs | 6 ++++-- rust/macros/lib.rs | 6 ++++-- rust/macros/module.rs | 7 +++++-- samples/rust/rust_minimal.rs | 2 +- samples/rust/rust_print_main.rs | 2 +- 8 files changed, 27 insertions(+), 14 deletions(-)
drivers/block/rnull.rs +1 -1
@@ -37,7 +37,7 @@ struct NullBlkModule { }impl kernel::Module for NullBlkModule { -fn init (_module: &'staticThisModule ) ->Result <Self > { +fn init (_name: &'staticCStr , _module: &'staticThisModule ) ->Result <Self > {pr_info! ("Rust null_blk loaded\n" );let tagset =Arc ::pin_init (TagSet ::new (1 ,256 ,1 ), flags::GFP_KERNEL )?;
rust/kernel/lib.rs +10 -4
@@ -90,7 +90,7 @@ pub trait Module: Sized + Sync + Send {/// should do. /// /// Equivalent to the `module_init` macro in the C API. -fn init (module: &'staticThisModule ) -> error::Result <Self >; +fn init (name: &'static str::CStr , module: &'staticThisModule ) -> error::Result <Self >; }/// A module that is pinned and initialised in-place.
@@ -98,13 +98,19 @@ pub trait InPlaceModule: Sync + Send {/// Creates an initialiser for the module. /// /// It is called when the module is loaded. -fn init (module: &'staticThisModule ) ->impl init::PinInit <Self , error::Error >; +fn init ( + name: &'static str::CStr , + module: &'staticThisModule , + ) ->impl init::PinInit <Self , error::Error >; }impl <T :Module >InPlaceModule for T { -fn init (module: &'staticThisModule ) ->impl init::PinInit <Self , error::Error > { +fn init ( + name: &'static str::CStr , + module: &'staticThisModule , + ) ->impl init::PinInit <Self , error::Error > {let initer =move |slot: *mut Self | { -let m = <Self as Module >::init (module)?; +let m = <Self as Module >::init (name, module)?;// SAFETY: `slot` is valid for write per the contract with `pin_init_from_closure`. unsafe { slot.write (m) };
rust/kernel/net/phy.rs +1 -1
@@ -903,7 +903,7 @@ struct Module { [$($crate::net::phy::create_phy_driver::<$driver>()),+];impl $crate::Module for Module { -fn init (module: &'staticThisModule ) ->Result <Self > { +fn init (_name: &'staticCStr , module: &'staticThisModule ) ->Result <Self > {// SAFETY: The anonymous constant guarantees that nobody else can access // the `DRIVERS` static. The array is used only in the C side. let drivers =unsafe { &mut DRIVERS };
rust/kernel/sync/lock/global.rs +4 -2
@@ -187,6 +187,7 @@ pub fn get_mut(&mut self) -> &mut T {/// ``` /// # mod ex { /// # use kernel::prelude::*; +/// # use kernel::str; /// kernel::sync::global_lock! { /// // SAFETY: Initialized in module initializer before first use. /// unsafe(uninit) static MY_COUNTER: Mutex<u32> = 0;
@@ -199,7 +200,7 @@ pub fn get_mut(&mut self) -> &mut T {/// } /// /// impl kernel::Module for MyModule { -/// fn init(_module: &'static ThisModule) -> Result<Self> { +/// fn init(_name: &'static str::CStr, _module: &'static ThisModule) -> Result<Self> { /// // SAFETY: Called exactly once. /// unsafe { MY_COUNTER.init() }; ///
@@ -216,6 +217,7 @@ pub fn get_mut(&mut self) -> &mut T {/// # mod ex { /// # use kernel::prelude::*; /// use kernel::sync::{GlobalGuard, GlobalLockedBy}; +/// # use kernel::str; /// /// kernel::sync::global_lock! { /// // SAFETY: Initialized in module initializer before first use.
@@ -239,7 +241,7 @@ pub fn get_mut(&mut self) -> &mut T {/// } /// /// impl kernel::Module for MyModule { -/// fn init(_module: &'static ThisModule) -> Result<Self> { +/// fn init(_name: &'static str::CStr, _module: &'static ThisModule) -> Result<Self> { /// // SAFETY: Called exactly once. /// unsafe { MY_MUTEX.init() }; ///
rust/macros/lib.rs +4 -2
@@ -32,6 +32,7 @@/// /// ``` /// use kernel::prelude::*; +/// use kernel::str; /// /// module!{ /// type: MyModule,
@@ -45,7 +46,7 @@/// struct MyModule(i32); /// /// impl kernel::Module for MyModule { -/// fn init(_module: &'static ThisModule) -> Result<Self> { +/// fn init(_name: &'static str::CStr, _module: &'static ThisModule) -> Result<Self> { /// let foo: i32 = 42; /// pr_info!("I contain: {}\n", foo); /// Ok(Self(foo))
@@ -65,6 +66,7 @@/// /// ``` /// use kernel::prelude::*; +/// use kernel::str; /// /// module!{ /// type: MyDeviceDriverModule,
@@ -78,7 +80,7 @@/// struct MyDeviceDriverModule; /// /// impl kernel::Module for MyDeviceDriverModule { -/// fn init(_module: &'static ThisModule) -> Result<Self> { +/// fn init(_name: &'static str::CStr, _module: &'static ThisModule) -> Result<Self> { /// Ok(Self) /// } /// }
rust/macros/module.rs +5 -2
@@ -333,8 +333,11 @@ mod __module_init {{/// /// This function must only be called once. unsafe fn __init () -> kernel::ffi::c_int {{ -let initer = - <{type_} as kernel::InPlaceModule>::init(&super::super::THIS_MODULE); + let initer = <{type_} as kernel::InPlaceModule>::init( + kernel::c_str!(\"{name}\"), + &super ::super ::THIS_MODULE + ); +// SAFETY: No data race, since `__MOD` can only be accessed by this module // and there only `__init` and `__exit` access it. These functions are only // called once and `__exit` cannot be called before or during `__init`.
samples/rust/rust_minimal.rs +1 -1
@@ -17,7 +17,7 @@ struct RustMinimal { }impl kernel::Module for RustMinimal { -fn init (_module: &'staticThisModule ) ->Result <Self > { +fn init (_name: &'staticCStr , _module: &'staticThisModule ) ->Result <Self > {pr_info! ("Rust minimal sample (init)\n" );pr_info! ("Am I built-in? {}\n" , !cfg! (MODULE ));
samples/rust/rust_print_main.rs +1 -1
@@ -41,7 +41,7 @@ fn arc_print() -> Result { }impl kernel::Module for RustPrint { -fn init (_module: &'staticThisModule ) ->Result <Self > { +fn init (_name: &'staticCStr , _module: &'staticThisModule ) ->Result <Self > {pr_info! ("Rust printing macros sample (init)\n" );pr_emerg! ("Emergency message (level 0) without args\n" );
Signature · 1 line
2.47.0
Greg KH
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.
Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the register_driver call.
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
thanks,
greg k-h
Greg KH
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 6 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.
Quoted 6 lines
Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use module->name there as well as you have a pointer to a valid module structure that has the name already embedded in it.
still confused,
greg k-h
Greg KH
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.
Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
thanks,
greg k-h
Greg KH
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.
Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the module->name (as I don't think that will be set), but you want KBUILD_MODNAME which the build system sets. You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have KBUILD_MODNAME?
thanks,
greg k-h
Re: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 2 lines · Greg KH
Or does the Rust side not have
KBUILD_MODNAME?
We can definitely give access to it at compile-time with e.g. env!:
pr_info!("{}\n", env!("KBUILD_MODNAME"));Cheers,
Miguel
Alice Ryhl
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 8 lines · Miguel Ojeda
Quoted 2 lines · Greg KH
Or does the Rust side not have
KBUILD_MODNAME?We can definitely give access to it at compile-time with e.g.
env!:pr_info!("{}\n", env!("KBUILD_MODNAME"));
I guess the challenge is that we need that to get evaluated in the driver, rather than inside the rust/kernel/ crate. Perhaps we could have the module! macro emit something that attaches the name to the module type, or something like that.
Alice
Danilo Krummrich
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
In reply to Greg KHQuoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.
That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?
AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access KBUILD_MODNAME conveniently?
Quoted 4 lines
thanks,
greg k-h
Danilo Krummrich
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?
Actually, I now remember there was another reason why I pass it through in Module::init.
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g. rust/kernel/pci.rs. But since this is generic code, it won't get the KBUILD_MODNAME from the module that is using the bus abstraction.
Quoted 5 lines
Quoted 5 lines
thanks,
greg k-h
Greg KH
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 50 lines · Danilo Krummrich
Quoted 49 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
Quoted 8 lines
Quoted 1 line
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.
Rust can't do that in a macro somehow that all pci rust drivers can pull from?
thanks,
greg k-h
Danilo Krummrich
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.
Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional name parameter in Module::init, but it would still need to be the driver resolving env!(KBUILD_MODNAME) passing it into the bus abstraction.
However, similar to what Alice suggested in another thread, we could include this step in the module_*_driver! macros.
Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
Quoted 4 lines
thanks,
greg k-h
Alice Ryhl
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 73 lines · Danilo Krummrich
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional
nameparameter inModule::init, but it would still need to be the driver resolvingenv!(KBUILD_MODNAME)passing it into the bus abstraction.
Quoted 5 lines
However, similar to what Alice suggested in another thread, we could include this step in the
module_*_driver!macros.Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
I think we can do it in the core module! macro that everyone has to use.
Alice
Danilo Krummrich
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 74 lines · Alice Ryhl
Quoted 73 lines · Danilo Krummrich
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional
nameparameter inModule::init, but it would still need to be the driver resolvingenv!(KBUILD_MODNAME)passing it into the bus abstraction.
Quoted 7 lines
Quoted 5 lines
However, similar to what Alice suggested in another thread, we could include this step in the
module_*_driver!macros.Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
I think we can do it in the core
module!macro that everyone has to use.
How? The module! macro does not know about the registration instances within the module structure.
Quoted 2 lines
Alice
Alice Ryhl
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 79 lines · Danilo Krummrich
Quoted 77 lines · Alice Ryhl
Quoted 76 lines · Danilo Krummrich
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional
nameparameter inModule::init, but it would still need to be the driver resolvingenv!(KBUILD_MODNAME)passing it into the bus abstraction.However, similar to what Alice suggested in another thread, we could include this step in the
module_*_driver!macros.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
I think we can do it in the core
module!macro that everyone has to use.How? The
module!macro does not know about the registration instances within the module structure.
You could have the module! macro emit something along these lines:
impl ModuleName for {type_} {
const NAME: &'static CStr = c_str!(env!("KBUILD_MODNAME"));
}Then you can do <Self as ModuleName>::NAME to obtain the name elsewhere.
Alice
Danilo Krummrich
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 88 lines · Alice Ryhl
Quoted 79 lines · Danilo Krummrich
Quoted 77 lines · Alice Ryhl
Quoted 76 lines · Danilo Krummrich
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional
nameparameter inModule::init, but it would still need to be the driver resolvingenv!(KBUILD_MODNAME)passing it into the bus abstraction.However, similar to what Alice suggested in another thread, we could include this step in the
module_*_driver!macros.Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
I think we can do it in the core
module!macro that everyone has to use.How? The
module!macro does not know about the registration instances within the module structure.
Quoted 7 lines
You could have the module! macro emit something along these lines:
impl ModuleName for {type_} { const NAME: &'static CStr = c_str!(env!("KBUILD_MODNAME")); }Then you can do
<Self as ModuleName>::NAMEto obtain the name elsewhere.
Where {type_} would need to be the driver's Driver structure?
We'd then need to define the bus adapter as:
pub struct Adapter<T: Driver + ModuleName>(T)
But the question stands I guess, how would the module macro know {type_}?
Quoted 2 lines
Alice
Alice Ryhl
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 98 lines · Danilo Krummrich
Quoted 88 lines · Alice Ryhl
Quoted 79 lines · Danilo Krummrich
Quoted 77 lines · Alice Ryhl
Quoted 76 lines · Danilo Krummrich
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the `Registration` abstraction used
to register driver structures. Some subsystems require the module name on
driver registration (e.g. PCI in __pci_register_driver()), hence pass
the module name to `Module::init`.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional
nameparameter inModule::init, but it would still need to be the driver resolvingenv!(KBUILD_MODNAME)passing it into the bus abstraction.However, similar to what Alice suggested in another thread, we could include this step in the
module_*_driver!macros.Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
I think we can do it in the core
module!macro that everyone has to use.How? The
module!macro does not know about the registration instances within the module structure.Quoted 7 lines
You could have the module! macro emit something along these lines:
impl ModuleName for {type_} { const NAME: &'static CStr = c_str!(env!("KBUILD_MODNAME")); }Then you can do
<Self as ModuleName>::NAMEto obtain the name elsewhere.
Quoted 7 lines
Where {
type_} would need to be the driver'sDriverstructure?We'd then need to define the bus adapter as:
pub struct Adapter<T: Driver + ModuleName>(T)But the question stands I guess, how would the module macro know {
type_}?
If you look at the macro implementation in rust/macros/module.rs you will find many uses of {type_} throughout the expansion. It's whatever is passed to the macro using the type: argument.
Alice
Danilo Krummrich
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 103 lines · Alice Ryhl
Quoted 102 lines · Danilo Krummrich
Quoted 88 lines · Alice Ryhl
Quoted 79 lines · Danilo Krummrich
Quoted 77 lines · Alice Ryhl
Quoted 76 lines · Danilo Krummrich
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
On Tue, Dec 10, 2024 at 11:46:28PM +0100, Danilo Krummrich wrote:
In a subsequent patch we introduce the `Registration` abstraction used
to register driver structures. Some subsystems require the module name on
driver registration (e.g. PCI in __pci_register_driver()), hence pass
the module name to `Module::init`.Nit, we don't need the NAME of the PCI driver (well, we do like it, but
that's not the real thing), we want the pointer to the module structure
in the register_driver call.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the
"name" that is the issue here.Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional
nameparameter inModule::init, but it would still need to be the driver resolvingenv!(KBUILD_MODNAME)passing it into the bus abstraction.However, similar to what Alice suggested in another thread, we could include this step in the
module_*_driver!macros.Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
I think we can do it in the core
module!macro that everyone has to use.How? The
module!macro does not know about the registration instances within the module structure.Quoted 7 lines
You could have the module! macro emit something along these lines:
impl ModuleName for {type_} { const NAME: &'static CStr = c_str!(env!("KBUILD_MODNAME")); }Then you can do
<Self as ModuleName>::NAMEto obtain the name elsewhere.Where {
type_} would need to be the driver'sDriverstructure?We'd then need to define the bus adapter as:
Quoted 7 lines
Quoted 3 lines
pub struct Adapter<T: Driver + ModuleName>(T)But the question stands I guess, how would the module macro know {
type_}?If you look at the macro implementation in
rust/macros/module.rsyou will find many uses of {type_} throughout the expansion. It's whatever is passed to the macro using thetype:argument.
Oh, I see. So, this means that module / driver author would still need to create the "connection" by listing the correspong driver types in the module! macro, right?
If so, I think it'd be better to do it in the module_*_driver! macro and let people implement the trait by hand for modules with multiple drivers (which should be pretty rare).
The reason is that I think that otherwise we're probably encoding too much semantics into the module! macro that isn't obvious and people need to understand.
Quoted 3 lines
Alice
Alice Ryhl
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 109 lines · Danilo Krummrich
Quoted 107 lines · Alice Ryhl
Quoted 105 lines · Danilo Krummrich
Quoted 88 lines · Alice Ryhl
Quoted 79 lines · Danilo Krummrich
Quoted 77 lines · Alice Ryhl
Quoted 76 lines · Danilo Krummrich
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 19 lines · Greg KH
On Wed, Dec 11, 2024 at 11:45:20AM +0100, Greg KH wrote:
On Tue, Dec 10, 2024 at 11:46:28PM +0100, Danilo Krummrich wrote:
In a subsequent patch we introduce the `Registration` abstraction used
to register driver structures. Some subsystems require the module name on
driver registration (e.g. PCI in __pci_register_driver()), hence pass
the module name to `Module::init`.Nit, we don't need the NAME of the PCI driver (well, we do like it, but
that's not the real thing), we want the pointer to the module structure
in the register_driver call.Does this provide for that? I'm thinking it does, but it's not the
"name" that is the issue here.Wait, no, you really do want the name, don't you. You refer to
"module.0" to get the module structure pointer (if I'm reading the code
right), but as you have that pointer already, why can't you just use
module->name there as well as you have a pointer to a valid module
structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional
nameparameter inModule::init, but it would still need to be the driver resolvingenv!(KBUILD_MODNAME)passing it into the bus abstraction.However, similar to what Alice suggested in another thread, we could include this step in the
module_*_driver!macros.Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
I think we can do it in the core
module!macro that everyone has to use.How? The
module!macro does not know about the registration instances within the module structure.Quoted 7 lines
You could have the module! macro emit something along these lines:
impl ModuleName for {type_} { const NAME: &'static CStr = c_str!(env!("KBUILD_MODNAME")); }Then you can do
<Self as ModuleName>::NAMEto obtain the name elsewhere.Where {
type_} would need to be the driver'sDriverstructure?We'd then need to define the bus adapter as:
pub struct Adapter<T: Driver + ModuleName>(T)But the question stands I guess, how would the module macro know {
type_}?
Quoted 7 lines
Quoted 3 lines
If you look at the macro implementation in
rust/macros/module.rsyou will find many uses of {type_} throughout the expansion. It's whatever is passed to the macro using thetype:argument.Oh, I see. So, this means that module / driver author would still need to create the "connection" by listing the correspong driver types in the module! macro, right?
I'm not sure what you mean. I'm *not* suggesting any changes to the interface of module! or module_*_driver!.
Quoted 11 lines
If so, I think it'd be better to do it in the
module_*_driver!macro and let people implement the trait by hand for modules with multiple drivers (which should be pretty rare).The reason is that I think that otherwise we're probably encoding too much semantics into the
module!macro that isn't obvious and people need to understand.Quoted 3 lines
Alice
Danilo Krummrich
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 114 lines · Alice Ryhl
Quoted 113 lines · Danilo Krummrich
Quoted 110 lines · Alice Ryhl
Quoted 98 lines · Danilo Krummrich
Quoted 88 lines · Alice Ryhl
Quoted 79 lines · Danilo Krummrich
Quoted 77 lines · Alice Ryhl
Quoted 76 lines · Danilo Krummrich
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 29 lines · Greg KH
On Wed, Dec 11, 2024 at 11:48:23AM +0100, Greg KH wrote:
On Wed, Dec 11, 2024 at 11:45:20AM +0100, Greg KH wrote:
On Tue, Dec 10, 2024 at 11:46:28PM +0100, Danilo Krummrich wrote:
In a subsequent patch we introduce the `Registration` abstraction used
to register driver structures. Some subsystems require the module name on
driver registration (e.g. PCI in __pci_register_driver()), hence pass
the module name to `Module::init`.Nit, we don't need the NAME of the PCI driver (well, we do like it, but
that's not the real thing), we want the pointer to the module structure
in the register_driver call.Does this provide for that? I'm thinking it does, but it's not the
"name" that is the issue here.Wait, no, you really do want the name, don't you. You refer to
"module.0" to get the module structure pointer (if I'm reading the code
right), but as you have that pointer already, why can't you just use
module->name there as well as you have a pointer to a valid module
structure that has the name already embedded in it.In digging further, it's used by the pci code to call into lower layers,
but why it's using a different string other than the module name string
is beyond me. Looks like this goes way back before git was around, and
odds are it's my fault for something I wrote a long time ago.I'll see if I can just change the driver core to not need a name at all,
and pull it from the module which would make all of this go away in the
end. Odds are something will break but who knows...Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional
nameparameter inModule::init, but it would still need to be the driver resolvingenv!(KBUILD_MODNAME)passing it into the bus abstraction.However, similar to what Alice suggested in another thread, we could include this step in the
module_*_driver!macros.Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
I think we can do it in the core
module!macro that everyone has to use.How? The
module!macro does not know about the registration instances within the module structure.Quoted 7 lines
You could have the module! macro emit something along these lines:
impl ModuleName for {type_} { const NAME: &'static CStr = c_str!(env!("KBUILD_MODNAME")); }Then you can do
<Self as ModuleName>::NAMEto obtain the name elsewhere.Quoted 7 lines
Where {
type_} would need to be the driver'sDriverstructure?We'd then need to define the bus adapter as:
pub struct Adapter<T: Driver + ModuleName>(T)But the question stands I guess, how would the module macro know {
type_}?If you look at the macro implementation in
rust/macros/module.rsyou will find many uses of {type_} throughout the expansion. It's whatever is passed to the macro using thetype:argument.
Quoted 6 lines
Quoted 3 lines
Oh, I see. So, this means that module / driver author would still need to create the "connection" by listing the correspong driver types in the module! macro, right?
I'm not sure what you mean. I'm *not* suggesting any changes to the interface of module! or module_*_driver!.
Huh! Seems like we're talking past each other than. Maybe we can briefly discuss it in today's call?
Quoted 12 lines
Quoted 12 lines
If so, I think it'd be better to do it in the
module_*_driver!macro and let people implement the trait by hand for modules with multiple drivers (which should be pretty rare).The reason is that I think that otherwise we're probably encoding too much semantics into the
module!macro that isn't obvious and people need to understand.Quoted 3 lines
Alice
Danilo Krummrich
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 119 lines · Danilo Krummrich
Quoted 118 lines · Alice Ryhl
Quoted 116 lines · Danilo Krummrich
Quoted 103 lines · Alice Ryhl
Quoted 102 lines · Danilo Krummrich
Quoted 88 lines · Alice Ryhl
Quoted 79 lines · Danilo Krummrich
Quoted 77 lines · Alice Ryhl
Quoted 76 lines · Danilo Krummrich
Quoted 56 lines · Greg KH
Quoted 55 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 36 lines · Greg KH
On Wed, Dec 11, 2024 at 11:59:54AM +0100, Greg KH wrote:
On Wed, Dec 11, 2024 at 11:48:23AM +0100, Greg KH wrote:
On Wed, Dec 11, 2024 at 11:45:20AM +0100, Greg KH wrote:
On Tue, Dec 10, 2024 at 11:46:28PM +0100, Danilo Krummrich wrote:
In a subsequent patch we introduce the `Registration` abstraction used
to register driver structures. Some subsystems require the module name on
driver registration (e.g. PCI in __pci_register_driver()), hence pass
the module name to `Module::init`.Nit, we don't need the NAME of the PCI driver (well, we do like it, but
that's not the real thing), we want the pointer to the module structure
in the register_driver call.Does this provide for that? I'm thinking it does, but it's not the
"name" that is the issue here.Wait, no, you really do want the name, don't you. You refer to
"module.0" to get the module structure pointer (if I'm reading the code
right), but as you have that pointer already, why can't you just use
module->name there as well as you have a pointer to a valid module
structure that has the name already embedded in it.In digging further, it's used by the pci code to call into lower layers,
but why it's using a different string other than the module name string
is beyond me. Looks like this goes way back before git was around, and
odds are it's my fault for something I wrote a long time ago.I'll see if I can just change the driver core to not need a name at all,
and pull it from the module which would make all of this go away in the
end. Odds are something will break but who knows...Nope, things break, the "name" is there to handle built-in modules (as
the module pointer will be NULL.)So what you really want is not the module->name (as I don't think that
will be set), but you want KBUILD_MODNAME which the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here,
just rely on the build system instead.Or does the Rust side not have KBUILD_MODNAME?
AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Quoted 6 lines
Quoted 3 lines
Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
I think we could avoid having an additional
nameparameter inModule::init, but it would still need to be the driver resolvingenv!(KBUILD_MODNAME)passing it into the bus abstraction.However, similar to what Alice suggested in another thread, we could include this step in the
module_*_driver!macros.Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Modules that don't use this convenience macro would need to do it by hand though. But that's probably not that big a deal.
I think we can do it in the core
module!macro that everyone has to use.How? The
module!macro does not know about the registration instances within the module structure.Quoted 7 lines
You could have the module! macro emit something along these lines:
impl ModuleName for {type_} { const NAME: &'static CStr = c_str!(env!("KBUILD_MODNAME")); }Then you can do
<Self as ModuleName>::NAMEto obtain the name elsewhere.Where {
type_} would need to be the driver'sDriverstructure?We'd then need to define the bus adapter as:
Quoted 7 lines
Quoted 3 lines
pub struct Adapter<T: Driver + ModuleName>(T)But the question stands I guess, how would the module macro know {
type_}?If you look at the macro implementation in
rust/macros/module.rsyou will find many uses of {type_} throughout the expansion. It's whatever is passed to the macro using thetype:argument.Oh, I see. So, this means that module / driver author would still need to create the "connection" by listing the correspong driver types in the module! macro, right?
Quoted 5 lines
Quoted 2 lines
I'm not sure what you mean. I'm *not* suggesting any changes to the interface of module! or module_*_driver!.
Huh! Seems like we're talking past each other than. Maybe we can briefly discuss it in today's call?
I think I figured out the confusion.
The {type_} in the module macro is the thing that implements the Module or InPlaceModule trait. However, that's *not* the driver type that is embedded in the bus adapter.
For instance, what we have is:
```
struct MyDriver;
struct MyModule {
_driver: Registration<pci::Adapter<MyDriver>,
};
impl pci::Driver for MyDriver { ... }
impl InPlaceModule for MyModule { ... }
module! {
type: MyModule,
...
}
```This means module! would generate:
impl ModuleName for MyModule { ... }
But this doesn't help, because pci::Adapter doesn't know about MyModule, but only about MyDriver.
Do I miss anything?
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
If so, I think it'd be better to do it in the
module_*_driver!macro and let people implement the trait by hand for modules with multiple drivers (which should be pretty rare).The reason is that I think that otherwise we're probably encoding too much semantics into the
module!macro that isn't obvious and people need to understand.Quoted 3 lines
Alice
Greg KH
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
In reply to Danilo KrummrichQuoted 61 lines · Danilo Krummrich
Quoted 60 lines · Greg KH
Quoted 58 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.
Quoted 6 lines
Quoted 2 lines
Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
Really? You can't have something in a required "register()" type function? Something for when the driver "instance" is created as part of pci::Driver? You do that today in your sample driver for the id table:
const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
Something else called DRIVER_NAME that you could then set:
const DRIVER_NAME: env!(KBUILD_MODNAME);
Also, I think you will want this for when a single module registers multiple drivers which I think can happen at times, so you could manually override the DRIVER_NAME field.
And if DRIVER_NAME doesn't get set, well, you just don't get the module symlink in sysfs, just like what happens today if you don't provide that field (but for PCI drivers, the .h file does it automatically for you.)
Anyway, this is a driver issue, NOT a module issue, so having to "plumb" the module name all the way down through this really isn't the best abstraction to do here from what I can tell.
thanks,
greg k-h
Danilo Krummrich
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 69 lines · Greg KH
Quoted 61 lines · Danilo Krummrich
Quoted 60 lines · Greg KH
Quoted 58 lines · Danilo Krummrich
Quoted 42 lines · Danilo Krummrich
Quoted 31 lines · Greg KH
Quoted 21 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 10 lines · Greg KH
Quoted 4 lines · Danilo Krummrich
In a subsequent patch we introduce the
Registrationabstraction used to register driver structures. Some subsystems require the module name on driver registration (e.g. PCI in__pci_register_driver()), hence pass the module name toModule::init.Nit, we don't need the NAME of the PCI driver (well, we do like it, but that's not the real thing), we want the pointer to the module structure in the
register_drivercall.Quoted 8 lines
Quoted 2 lines
Does this provide for that? I'm thinking it does, but it's not the "name" that is the issue here.
Wait, no, you really do want the name, don't you. You refer to "module.0" to get the module structure pointer (if I'm reading the code right), but as you have that pointer already, why can't you just use
module->namethere as well as you have a pointer to a valid module structure that has the name already embedded in it.Quoted 8 lines
In digging further, it's used by the pci code to call into lower layers, but why it's using a different string other than the module name string is beyond me. Looks like this goes way back before git was around, and odds are it's my fault for something I wrote a long time ago.
I'll see if I can just change the driver core to not need a name at all, and pull it from the module which would make all of this go away in the end. Odds are something will break but who knows...
Quoted 5 lines
Nope, things break, the "name" is there to handle built-in modules (as the module pointer will be NULL.)
So what you really want is not the
module->name(as I don't think that will be set), but you wantKBUILD_MODNAMEwhich the build system sets.That's correct, and the reason why I pass through this name argument.
Sorry I wasn't able to reply earlier to save you some time.
Quoted 8 lines
Quoted 4 lines
You shouldn't need to pass the name through all of the subsystems here, just rely on the build system instead.
Or does the Rust side not have
KBUILD_MODNAME?AFAIK, it doesn't (or didn't have at the time I wrote the patch).
@Miguel: Can we access
KBUILD_MODNAMEconveniently?Actually, I now remember there was another reason why I pass it through in
Module::init.Even if we had env!(KBUILD_MODNAME) already, I'd want to use it from the bus abstraction code, e.g.
rust/kernel/pci.rs. But since this is generic code, it won't get theKBUILD_MODNAMEfrom the module that is using the bus abstraction.Quoted 6 lines
Quoted 2 lines
Rust can't do that in a macro somehow that all pci rust drivers can pull from?
The problem is that register / unregister is encapsulated within methods of the abstraction types. So the C macro trick (while generally possible) isn't applicable.
Quoted 7 lines
Really? You can't have something in a required "
register()" type function? Something for when the driver "instance" is created as part ofpci::Driver? You do that today in your sample driver for the id table:const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;Something else called
DRIVER_NAMEthat you could then set:const DRIVER_NAME: env!(KBUILD_MODNAME);
Sure, that's possible. But that means that the driver has to set it explicitly -- even when e.g. module_pci_driver! is used.
In C you don't have that, because there it's implicit within the pci_register_driver() macro. (Regardless of whether it's a single module for a single driver or multiple drivers per module.)
Anyways, like I mentioned, given that we have env!(KBUILD_MODNAME) (which we still need to add), there are other options to make it work similarly, e.g. add a parameter to pci::Adapter and bake this into module_pci_driver!.
For this particular option, it would mean that for modules registering multiple drivers a corresponding name would need to be passed explicitly.
Quoted 4 lines
Also, I think you will want this for when a single module registers multiple drivers which I think can happen at times, so you could manually override the
DRIVER_NAMEfield.
My proposal above would provide this option, but do we care? In C no one ever changes the name. There is zero users of __pci_register_driver(), everyone uses pci_register_driver() where the name is just KBUILD_MODNAME. Same for __platform_driver_register().
Quoted 12 lines
And if
DRIVER_NAMEdoesn't get set, well, you just don't get the module symlink in sysfs, just like what happens today if you don't provide that field (but for PCI drivers, the .h file does it automatically for you.)Anyway, this is a driver issue, NOT a module issue, so having to "plumb" the module name all the way down through this really isn't the best abstraction to do here from what I can tell.
thanks,
greg k-h
Greg KH
maintainerRe: [PATCH v5 01/16] rust: pass module name to `Module::init`
Quoted 11 lines · Danilo Krummrich
Quoted 7 lines
Really? You can't have something in a required "
register()" type function? Something for when the driver "instance" is created as part ofpci::Driver? You do that today in your sample driver for the id table:const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;Something else called
DRIVER_NAMEthat you could then set:const DRIVER_NAME: env!(KBUILD_MODNAME);Sure, that's possible. But that means that the driver has to set it explicitly -- even when e.g.
module_pci_driver! is used.
Quoted 7 lines
In C you don't have that, because there it's implicit within the
pci_register_driver()macro. (Regardless of whether it's a single module for a single driver or multiple drivers per module.)Anyways, like I mentioned, given that we have
env!(KBUILD_MODNAME)(which we still need to add), there are other options to make it work similarly, e.g. add a parameter topci::Adapterand bake this intomodule_pci_driver!.
Ok, I'm all for that, just don't modify the module rust functions for it :)
Quoted 2 lines
For this particular option, it would mean that for modules registering multiple drivers a corresponding name would need to be passed explicitly.
True.
Quoted 8 lines
Quoted 3 lines
Also, I think you will want this for when a single module registers multiple drivers which I think can happen at times, so you could manually override the
DRIVER_NAMEfield.My proposal above would provide this option, but do we care? In C no one ever changes the name. There is zero users of
__pci_register_driver(), everyone usespci_register_driver()where the name is justKBUILD_MODNAME. Same for__platform_driver_register().
You are right. But I see other drivers messing with that field, oh no, wait, that's just the EDAC layer doing really odd things (a known issue as that layer does very many odd things.)
So nevermind, multiple drivers per module isn't going to be an issue, if you all can move it to a macro (best yet, like what Alice pointed out), that would be fine with me.
thanks,
greg k-h
Danilo Krummrich
maintainerPATCH v5 2/16 rust: implement generic driver registration
In reply to Danilo KrummrichImplement the generic Registration type and the RegistrationOps trait.
The Registration structure is the common type that represents a driver registration and is typically bound to the lifetime of a module. However, it doesn't implement actual calls to the kernel's driver core to register drivers itself.
Instead the RegistrationOps trait is provided to subsystems, which have to implement RegistrationOps::register and RegistrationOps::unregister. Subsystems have to provide an implementation for both of those methods where the subsystem specific variants to register / unregister a driver have to implemented.
For instance, the PCI subsystem would call __pci_register_driver() from RegistrationOps::register and pci_unregister_driver() from DrvierOps::unregister.
--- MAINTAINERS | 1 + rust/kernel/driver.rs | 116 ++++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 3 files changed, 118 insertions(+) create mode 100644 rust/kernel/driver.rs
MAINTAINERS +1 -0
@@ -7033,6 +7033,7 @@ F: include/linux/kobj* F: include/linux/property.h F: lib/kobj* F: rust/kernel/device.rs +F: rust/kernel/driver.rs DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS) M: Nishanth Menon <[email protected]>
rust/kernel/driver.rs new file +116 -0
116 lines not on this page · raw message
rust/kernel/lib.rs +1 -0
@@ -35,6 +35,7 @@mod build_assert;pub mod cred;pub mod device; +pub mod driver;pub mod error;#[cfg( CONFIG_RUST_FW_LOADER_ABSTRACTIONS )] pub mod firmware;
Signature · 1 line
2.47.0
Danilo Krummrich
maintainerPATCH v5 3/16 rust: implement `IdArray`, `IdTable` and `RawDeviceId`
In reply to Danilo KrummrichMost subsystems use some kind of ID to match devices and drivers. Hence, we have to provide Rust drivers an abstraction to register an ID table for the driver to match.
Generally, those IDs are subsystem specific and hence need to be implemented by the corresponding subsystem. However, the IdArray, IdTable and RawDeviceId types provide a generalized implementation that makes the life of subsystems easier to do so.
--- MAINTAINERS | 1 + rust/kernel/device_id.rs | 165 +++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 6 ++ 3 files changed, 172 insertions(+) create mode 100644 rust/kernel/device_id.rs
MAINTAINERS +1 -0
@@ -7033,6 +7033,7 @@ F: include/linux/kobj* F: include/linux/property.h F: lib/kobj* F: rust/kernel/device.rs +F: rust/kernel/device_id.rs F: rust/kernel/driver.rs DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
rust/kernel/device_id.rs new file +165 -0
165 lines not on this page · raw message
rust/kernel/lib.rs +6 -0
@@ -18,6 +18,11 @@#![feature(inline_const)] #![feature(lint_reasons)] #![feature(unsize)] +// Stable in Rust 1.83 +#![feature(const_maybe_uninit_as_mut_ptr)] +#![feature(const_mut_refs)] +#![feature(const_ptr_write)] +#![feature(const_refs_to_cell)] // Ensure conditional compilation based on the kernel configuration works; // otherwise we may silently break things like initcall handling.
@@ -35,6 +40,7 @@mod build_assert;pub mod cred;pub mod device; +pub mod device_id;pub mod driver;pub mod error;#[cfg( CONFIG_RUST_FW_LOADER_ABSTRACTIONS )]
Signature · 1 line
2.47.0
Danilo Krummrich
maintainerPATCH v5 4/16 rust: add rcu abstraction
In reply to Danilo KrummrichFrom: Wedson Almeida Filho <[email protected]>
Add a simple abstraction to guard critical code sections with an rcu read lock.
--- rust/helpers/helpers.c | 1 + rust/helpers/rcu.c | 13 ++++++++++++ rust/kernel/sync.rs | 1 + rust/kernel/sync/rcu.rs | 47 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 rust/helpers/rcu.c create mode 100644 rust/kernel/sync/rcu.rs
rust/helpers/helpers.c +1 -0
@@ -20,6 +20,7 @@#include "page.c" #include "pid_namespace.c" #include "rbtree.c" +#include "rcu.c" #include "refcount.c" #include "security.c" #include "signal.c"
rust/helpers/rcu.c new file +13 -0
@@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/rcupdate.h> + +void rust_helper_rcu_read_lock (void ) +{ +rcu_read_lock (); +} + +void rust_helper_rcu_read_unlock (void ) +{ +rcu_read_unlock (); +}
rust/kernel/sync.rs +1 -0
@@ -12,6 +12,7 @@pub mod lock;mod locked_by;pub mod poll; +pub mod rcu;pub use arc::{Arc ,ArcBorrow ,UniqueArc };pub use condvar::{new_condvar,CondVar ,CondVarTimeoutResult };
rust/kernel/sync/rcu.rs new file +47 -0
47 lines not on this page · raw message
Signature · 1 line
2.47.0
Re: [PATCH v5 04/16] rust: add rcu abstraction
Hi Danilo,
This looks good so far, could you please Cc RCU maintainers for the next version (if there is one).
A few nits below, with or without, feel free to add:
Quoted 95 lines · Danilo Krummrich
From: Wedson Almeida Filho <[email protected]>
Add a simple abstraction to guard critical code sections with an rcu read lock.
Signed-off-by Wedson Almeida Filho <[email protected]>Co-developed-by Danilo Krummrich <[email protected]>Signed-off-by Danilo Krummrich <[email protected]>--- rust/helpers/helpers.c | 1 + rust/helpers/rcu.c | 13 ++++++++++++ rust/kernel/sync.rs | 1 + rust/kernel/sync/rcu.rs | 47 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 rust/helpers/rcu.c create mode 100644 rust/kernel/sync/rcu.rsrust/helpers/helpers.c +1
-0@@ -20,6 +20,7 @@#include "page.c" #include "pid_namespace.c" #include "rbtree.c" +#include "rcu.c" #include "refcount.c" #include "security.c" #include "signal.c" rust/helpers/rcu.c new file +13
-0@@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/rcupdate.h> + +void rust_helper_rcu_read_lock (void ) +{ +rcu_read_lock (); +} + +void rust_helper_rcu_read_unlock (void ) +{ +rcu_read_unlock (); +}rust/kernel/sync.rs +1
-0@@ -12,6 +12,7 @@pub mod lock;mod locked_by;pub mod poll; +pub mod rcu;pub use arc::{Arc ,ArcBorrow ,UniqueArc };pub use condvar::{new_condvar,CondVar ,CondVarTimeoutResult };rust/kernel/sync/rcu.rs new file +29
-0@@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! RCU support. +//! +//! C header: [`include/linux/rcupdate.h`](srctree/include/linux/rcupdate.h) + +use crate ::{bindings, types::NotThreadSafe }; + +/// Evidence that the RCU read side lock is held on the current thread/CPU. +/// +/// The type is explicitly not `Send` because this property is per-thread/CPU. +/// +/// # Invariants +/// +/// The RCU read side lock is actually held while instances of this guard exist. +pub struct Guard (NotThreadSafe ); + +impl Guard { +/// Acquires the RCU read side lock and returns a guard. +pub fn new () ->Self { +// SAFETY: An FFI call with no additional requirements. +unsafe { bindings::rcu_read_lock () }; +// INVARIANT: The RCU read side lock was just acquired above. +Self (NotThreadSafe ) + } + +/// Explicitly releases the RCU read side lock. +pub fn unlock (self) {} +}
rust/kernel/sync/rcu.rs line 39
Quoted 10 lines
rust/kernel/sync/rcu.rs new file +10
-0+ +impl Default for Guard { +fn default () ->Self { +Self ::new () + } +} + +impl Drop for Guard { +fn drop (&mut self) { +// SAFETY: By the type invariants, the rcu read side is locked, so it is ok to unlock it.
s/rcu/RCU
when referring the RCU mechanism or the subsystem, it makes sense to use the capitalized abbreviation.
Regards,
Boqun
Quoted 11 lines
rust/kernel/sync/rcu.rs new file +8
-0+unsafe { bindings::rcu_read_unlock () }; + } +} + +/// Acquires the RCU read side lock. +pub fn read_lock () ->Guard { +Guard ::new () +}Signature · 1 line
2.47.0
Danilo Krummrich
maintainerPATCH v5 5/16 rust: types: add `Opaque::pin_init`
In reply to Danilo KrummrichAnalogous to Opaque::new add Opaque::pin_init, which instead of a value T takes a PinInit<T> and returns a PinInit<Opaque<T>>.
--- rust/kernel/types.rs | 11 +++++++++++ 1 file changed, 11 insertions(+)
rust/kernel/types.rs +11 -0
@@ -281,6 +281,17 @@ pub const fn uninit() -> Self { } } +/// Create an opaque pin-initializer from the given pin-initializer. +pub fn pin_init (slot:impl PinInit <T >) ->impl PinInit <Self > { +Self ::ffi_init (|ptr: *mut T | { +// SAFETY: +// - `ptr` is a valid pointer to uninitialized memory, +// - `slot` is not accessed on error; the call is infallible, +// - `slot` is pinned in memory. +let _ =unsafe { init::PinInit ::<T >::__pinned_init (slot, ptr) }; + }) + } +/// Creates a pin-initializer from the given initializer closure. /// /// The returned initializer calls the given closure with the pointer to the inner `T` of this
Signature · 1 line
2.47.0
Re: [PATCH v5 05/16] rust: types: add `Opaque::pin_init`
Quoted 6 lines · Danilo Krummrich
Analogous to
Opaque::newaddOpaque::pin_init, which instead of a valueTtakes aPinInit<T>and returns aPinInit<Opaque<T>>.Suggested-by Alice Ryhl <[email protected]>Signed-off-by Danilo Krummrich <[email protected]>
Danilo Krummrich
maintainerPATCH v5 6/16 rust: add `Revocable` type
In reply to Danilo KrummrichFrom: Wedson Almeida Filho <[email protected]>
Revocable allows access to objects to be safely revoked at run time.
This is useful, for example, for resources allocated during device probe; when the device is removed, the driver should stop accessing the device resources even if another state is kept in memory due to existing references (i.e., device context data is ref-counted and has a non-zero refcount after removal of the device).
--- rust/kernel/lib.rs | 1 + rust/kernel/revocable.rs | 223 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 rust/kernel/revocable.rs
rust/kernel/lib.rs +1 -0
@@ -60,6 +60,7 @@pub mod prelude;pub mod print;pub mod rbtree; +pub mod revocable;pub mod security;pub mod seq_file;pub mod sizes;
rust/kernel/revocable.rs new file +223 -0
223 lines not on this page · raw message
Signature · 1 line
2.47.0
Re: [PATCH v5 06/16] rust: add `Revocable` type
Quoted 160 lines · On Tue, 10 Dec 2024 23:46:33 +0100 Danilo Krummrich <[email protected]> wrote:
From: Wedson Almeida Filho <[email protected]>
Revocable allows access to objects to be safely revoked at run time.
This is useful, for example, for resources allocated during device probe; when the device is removed, the driver should stop accessing the device resources even if another state is kept in memory due to existing references (i.e., device context data is ref-counted and has a non-zero refcount after removal of the device).
Signed-off-by Wedson Almeida Filho <[email protected]>Co-developed-by Danilo Krummrich <[email protected]>Signed-off-by Danilo Krummrich <[email protected]>--- rust/kernel/lib.rs | 1 + rust/kernel/revocable.rs | 223 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 rust/kernel/revocable.rsrust/kernel/lib.rs +1
-0@@ -60,6 +60,7 @@pub mod prelude;pub mod print;pub mod rbtree; +pub mod revocable;pub mod security;pub mod seq_file;pub mod sizes;rust/kernel/revocable.rs new file +123
-0@@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Revocable objects. +//! +//! The [`Revocable`] type wraps other types and allows access to them to be revoked. The existence +//! of a [`RevocableGuard`] ensures that objects remain valid. + +use crate ::{bindings, prelude::*, sync::rcu, types::Opaque }; +use core::{ + marker::PhantomData , + ops::Deref , + ptr::drop_in_place, + sync::atomic::{AtomicBool ,Ordering }, +}; + +/// An object that can become inaccessible at runtime. +/// +/// Once access is revoked and all concurrent users complete (i.e., all existing instances of +/// [`RevocableGuard`] are dropped), the wrapped object is also dropped. +/// +/// # Examples +/// +/// ``` +/// # use kernel::revocable::Revocable; +/// +/// struct Example { +/// a: u32, +/// b: u32, +/// } +/// +/// fn add_two(v: &Revocable<Example>) -> Option<u32> { +/// let guard = v.try_access()?; +/// Some(guard.a + guard.b) +/// } +/// +/// let v = KBox::pin_init(Revocable::new(Example { a: 10, b: 20 }), GFP_KERNEL).unwrap(); +/// assert_eq!(add_two(&v), Some(30)); +/// v.revoke(); +/// assert_eq!(add_two(&v), None); +/// ``` +/// +/// Sample example as above, but explicitly using the rcu read side lock. +/// +/// ``` +/// # use kernel::revocable::Revocable; +/// use kernel::sync::rcu; +/// +/// struct Example { +/// a: u32, +/// b: u32, +/// } +/// +/// fn add_two(v: &Revocable<Example>) -> Option<u32> { +/// let guard = rcu::read_lock(); +/// let e = v.try_access_with_guard(&guard)?; +/// Some(e.a + e.b) +/// } +/// +/// let v = KBox::pin_init(Revocable::new(Example { a: 10, b: 20 }), GFP_KERNEL).unwrap(); +/// assert_eq!(add_two(&v), Some(30)); +/// v.revoke(); +/// assert_eq!(add_two(&v), None); +/// ``` +#[pin_data( PinnedDrop )] +pub struct Revocable <T > { + is_available:AtomicBool , +#[pin] + data:Opaque <T >, +} + +// SAFETY: `Revocable` is `Send` if the wrapped object is also `Send`. This is because while the +// functionality exposed by `Revocable` can be accessed from any thread/CPU, it is possible that +// this isn't supported by the wrapped object. +unsafe impl <T :Send >Send for Revocable <T > {} + +// SAFETY: `Revocable` is `Sync` if the wrapped object is both `Send` and `Sync`. We require `Send` +// from the wrapped object as well because of `Revocable::revoke`, which can trigger the `Drop` +// implementation of the wrapped object from an arbitrary thread. +unsafe impl <T :Sync +Send >Sync for Revocable <T > {} + +impl <T >Revocable <T > { +/// Creates a new revocable instance of the given data. +pub fn new (data:impl PinInit <T >) ->impl PinInit <Self > { +pin_init! (Self { + is_available:AtomicBool ::new (true ), + data <-Opaque ::pin_init (data), + }) + } + +/// Tries to access the revocable wrapped object. +/// +/// Returns `None` if the object has been revoked and is therefore no longer accessible. +/// +/// Returns a guard that gives access to the object otherwise; the object is guaranteed to +/// remain accessible while the guard is alive. In such cases, callers are not allowed to sleep +/// because another CPU may be waiting to complete the revocation of this object. +pub fn try_access (&self) ->Option <RevocableGuard <'_,T >> { +let guard = rcu::read_lock (); +if self.is_available.load (Ordering ::Relaxed ) { +// Since `self.is_available` is true, data is initialised and has to remain valid +// because the RCU read side lock prevents it from being dropped. +Some (RevocableGuard ::new (self.data.get (), guard)) + }else { +None + } + } + +/// Tries to access the revocable wrapped object. +/// +/// Returns `None` if the object has been revoked and is therefore no longer accessible. +/// +/// Returns a shared reference to the object otherwise; the object is guaranteed to +/// remain accessible while the rcu read side guard is alive. In such cases, callers are not +/// allowed to sleep because another CPU may be waiting to complete the revocation of this +/// object. +pub fn try_access_with_guard <'a>(&'a self, _guard: &'a rcu::Guard ) ->Option <&'aT > { +if self.is_available.load (Ordering ::Relaxed ) { +// SAFETY: Since `self.is_available` is true, data is initialised and has to remain +// valid because the RCU read side lock prevents it from being dropped. +Some (unsafe { &*self.data.get () }) + }else { +None + }
rust/kernel/revocable.rs line 133
Quoted 10 lines
rust/kernel/revocable.rs new file +10
-0+ } + +/// # Safety +/// +/// Callers must ensure that there are no more concurrent users of the revocable object. +unsafe fn revoke_internal <const SYNC :bool >(&self) { + if self + .is_available + .compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed) + .is_ok()
This can be simplified to if self.is_available.swap(false, Ordering::Relaxed) {
Quoted 60 lines
rust/kernel/revocable.rs new file +60
-0+ { +if SYNC { +// SAFETY: Just an FFI call, there are no further requirements. +unsafe { bindings::synchronize_rcu () }; + } + +// SAFETY: We know `self.data` is valid because only one CPU can succeed the +// `compare_exchange` above that takes `is_available` from `true` to `false`. +unsafe {drop_in_place (self.data.get ()) }; + } + } + +/// Revokes access to and drops the wrapped object. +/// +/// Access to the object is revoked immediately to new callers of [`Revocable::try_access`], +/// expecting that there are no concurrent users of the object. +/// +/// # Safety +/// +/// Callers must ensure that there are no more concurrent users of the revocable object. +pub unsafe fn revoke_nosync (&self) { +// SAFETY: By the safety requirement of this function, the caller ensures that nobody is +// accessing the data anymore and hence we don't have to wait for the grace period to +// finish. +unsafe { self.revoke_internal ::<false >() } + } + +/// Revokes access to and drops the wrapped object. +/// +/// Access to the object is revoked immediately to new callers of [`Revocable::try_access`]. +/// +/// If there are concurrent users of the object (i.e., ones that called +/// [`Revocable::try_access`] beforehand and still haven't dropped the returned guard), this +/// function waits for the concurrent access to complete before dropping the wrapped object. +pub fn revoke (&self) { +// SAFETY: By passing `true` we ask `revoke_internal` to wait for the grace period to +// finish. +unsafe { self.revoke_internal ::<true >() } + } +} + +#[pinned_drop] +impl <T >PinnedDrop for Revocable <T > { +fn drop (self:Pin <&mut Self >) { +// Drop only if the data hasn't been revoked yet (in which case it has already been +// dropped). +// SAFETY: We are not moving out of `p`, only dropping in place +let p =unsafe { self.get_unchecked_mut () }; +if *p.is_available.get_mut () { +// SAFETY: We know `self.data` is valid because no other CPU has changed +// `is_available` to `false` yet, and no other CPU can do it anymore because this CPU +// holds the only reference (mutable) to `self` now. +unsafe {drop_in_place (p.data.get ()) }; + } + } +} + +/// A guard that allows access to a revocable object and keeps it alive. +/// +/// CPUs may not sleep while holding on to [`RevocableGuard`] because it's in atomic context
rust/kernel/revocable.rs line 203
Quoted 10 lines
rust/kernel/revocable.rs new file +10
-0+/// holding the RCU read-side lock. +/// +/// # Invariants +/// +/// The RCU read-side lock is held while the guard is alive. +pub struct RevocableGuard <'a,T > { + data_ref: *const T , + _rcu_guard: rcu::Guard , + _p:PhantomData <&'a ()>, +}
Shouldn't this type hold a &'a T directly instead of a raw pointer ?
Quoted 21 lines
rust/kernel/revocable.rs new file +20
-1+ +impl <T >RevocableGuard <'_,T > { +fn new (data_ref: *const T , rcu_guard: rcu::Guard ) ->Self { +Self { + data_ref, + _rcu_guard: rcu_guard, + _p:PhantomData , + } + } +} + +impl <T >Deref for RevocableGuard <'_,T > { +type Target =T ; + +fn deref (&self) -> &Self ::Target { +// SAFETY: By the type invariants, we hold the rcu read-side lock, so the object is +// guaranteed to remain valid. +unsafe { &*self.data_ref } + } +} --
Quoted 1 line
2.47.0
Benoît du Garreau
Alice Ryhl
maintainerRe: [PATCH v5 06/16] rust: add `Revocable` type
Quoted 17 lines · Benoît du Garreau
rust/kernel/revocable.rs line 203
Quoted 13 lines · On Tue, 10 Dec 2024 23:46:33 +0100 Danilo Krummrich <[email protected]> wrote:
rust/kernel/revocable.rs new file +13
-0+/// A guard that allows access to a revocable object and keeps it alive. +/// +/// CPUs may not sleep while holding on to [`RevocableGuard`] because it's in atomic context +/// holding the RCU read-side lock. +/// +/// # Invariants +/// +/// The RCU read-side lock is held while the guard is alive. +pub struct RevocableGuard <'a,T > { + data_ref: *const T , + _rcu_guard: rcu::Guard , + _p:PhantomData <&'a ()>, +}Shouldn't this type hold a
&'a Tdirectly instead of a raw pointer ?
No, because the value might get destroyed before the end of the lifetime 'a. It's not legal to use references for containers that might free or otherwise invalidate the referent in their destructor.
That said, the PhantomData field should probably be &'a T. It doesn't actually change anything, but it carries the right intent.
Alice
Danilo Krummrich
maintainerPATCH v5 7/16 rust: add `io::{Io, IoRaw}` base types
In reply to Danilo KrummrichI/O memory is typically either mapped through direct calls to ioremap() or subsystem / bus specific ones such as pci_iomap().
Even though subsystem / bus specific functions to map I/O memory are based on ioremap() / iounmap() it is not desirable to re-implement them in Rust.
Instead, implement a base type for I/O mapped memory, which generically provides the corresponding accessors, such as Io::readb or Io:try_readb.
Io supports an optional const generic, such that a driver can indicate the minimal expected and required size of the mapping at compile time. Correspondingly, calls to the 'non-try' accessors, support compile time checks of the I/O memory offset to read / write, while the 'try' accessors, provide boundary checks on runtime.
IoRaw is meant to be embedded into a structure (e.g. pci::Bar or io::IoMem) which creates the actual I/O memory mapping and initializes IoRaw accordingly.
To ensure that I/O mapped memory can't out-live the device it may be bound to, subsystems must embed the corresponding I/O memory type (e.g. pci::Bar) into a Devres container, such that it gets revoked once the device is unbound.
--- rust/helpers/helpers.c | 1 + rust/helpers/io.c | 101 ++++++++++++++++ rust/kernel/io.rs | 260 +++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 4 files changed, 363 insertions(+) create mode 100644 rust/helpers/io.c create mode 100644 rust/kernel/io.rs
rust/helpers/helpers.c +1 -0
@@ -14,6 +14,7 @@#include "cred.c" #include "err.c" #include "fs.c" +#include "io.c" #include "jump_label.c" #include "kunit.c" #include "mutex.c"
rust/helpers/io.c new file +101 -0
101 lines not on this page · raw message
rust/kernel/io.rs new file +260 -0
260 lines not on this page · raw message
rust/kernel/lib.rs +1 -0
@@ -79,6 +79,7 @@#[doc(hidden)] pub use bindings; +pub mod io;pub use macros;pub use uapi;
Signature · 1 line
2.47.0
Danilo Krummrich
maintainerPATCH v5 8/16 rust: add devres abstraction
In reply to Danilo KrummrichAdd a Rust abstraction for the kernel's devres (device resource management) implementation.
The Devres type acts as a container to manage the lifetime and accessibility of device bound resources. Therefore it registers a devres callback and revokes access to the resource on invocation.
Users of the Devres abstraction can simply free the corresponding resources in their Drop implementation, which is invoked when either the Devres instance goes out of scope or the devres callback leads to the resource being revoked, which implies a call to drop_in_place().
--- MAINTAINERS | 1 + rust/helpers/device.c | 10 +++ rust/helpers/helpers.c | 1 + rust/kernel/devres.rs | 179 +++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 5 files changed, 192 insertions(+) create mode 100644 rust/helpers/device.c create mode 100644 rust/kernel/devres.rs
MAINTAINERS +1 -0
@@ -7034,6 +7034,7 @@ F: include/linux/property.h F: lib/kobj* F: rust/kernel/device.rs F: rust/kernel/device_id.rs +F: rust/kernel/devres.rs F: rust/kernel/driver.rs DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
rust/helpers/device.c new file +10 -0
@@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/device.h> + +int rust_helper_devm_add_action (struct device *dev, +void (*action)(void *), +void *data) +{ +return devm_add_action (dev, action, data); +}
rust/helpers/helpers.c +1 -0
@@ -12,6 +12,7 @@#include "build_assert.c" #include "build_bug.c" #include "cred.c" +#include "device.c" #include "err.c" #include "fs.c" #include "io.c"
rust/kernel/devres.rs new file +179 -0
179 lines not on this page · raw message
rust/kernel/lib.rs +1 -0
@@ -41,6 +41,7 @@pub mod cred;pub mod device;pub mod device_id; +pub mod devres;pub mod driver;pub mod error;#[cfg( CONFIG_RUST_FW_LOADER_ABSTRACTIONS )]
Signature · 1 line
2.47.0
Danilo Krummrich
maintainerPATCH v5 9/16 rust: pci: add basic PCI device / driver abstractions
In reply to Danilo KrummrichImplement the basic PCI abstractions required to write a basic PCI driver. This includes the following data structures:
The pci::Driver trait represents the interface to the driver and provides pci::Driver::probe for the driver to implement.
The pci::Device abstraction represents a struct pci_dev and provides abstractions for common functions, such as pci::Device::set_master.
In order to provide the PCI specific parts to a generic driver::Registration the driver::RegistrationOps trait is implemented by pci::Adapter.
pci::DeviceId implements PCI device IDs based on the generic device_id::RawDevceId abstraction.
--- MAINTAINERS | 1 + rust/bindings/bindings_helper.h | 1 + rust/helpers/helpers.c | 1 + rust/helpers/pci.c | 18 ++ rust/kernel/lib.rs | 2 + rust/kernel/pci.rs | 298 ++++++++++++++++++++++++++++++++ 6 files changed, 321 insertions(+) create mode 100644 rust/helpers/pci.c create mode 100644 rust/kernel/pci.rs
MAINTAINERS +1 -0
@@ -18102,6 +18102,7 @@ F: include/asm-generic/pci* F: include/linux/of_pci.h F: include/linux/pci* F: include/uapi/linux/pci* +F: rust/kernel/pci.rs PCIE BANDWIDTH CONTROLLER M: Ilpo Järvinen <[email protected]>
rust/bindings/bindings_helper.h +1 -0
@@ -20,6 +20,7 @@#include <linux/jump_label.h> #include <linux/mdio.h> #include <linux/miscdevice.h> +#include <linux/pci.h> #include <linux/phy.h> #include <linux/pid_namespace.h> #include <linux/poll.h>
rust/helpers/helpers.c +1 -0
@@ -20,6 +20,7 @@#include "kunit.c" #include "mutex.c" #include "page.c" +#include "pci.c" #include "pid_namespace.c" #include "rbtree.c" #include "rcu.c"
rust/helpers/pci.c new file +18 -0
@@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/pci.h> + +void rust_helper_pci_set_drvdata (struct pci_dev *pdev,void *data) +{ +pci_set_drvdata (pdev, data); +} + +void *rust_helper_pci_get_drvdata (struct pci_dev *pdev) +{ +return pci_get_drvdata (pdev); +} + +resource_size_t rust_helper_pci_resource_len (struct pci_dev *pdev,int bar) +{ +return pci_resource_len (pdev, bar); +}
rust/kernel/lib.rs +2 -0
@@ -82,6 +82,8 @@pub use bindings;pub mod io;pub use macros; +#[cfg(all( CONFIG_PCI , CONFIG_PCI_MSI ))] +pub mod pci;pub use uapi;#[doc(hidden)]
rust/kernel/pci.rs new file +298 -0
298 lines not on this page · raw message
Signature · 1 line
2.47.0
Danilo Krummrich
maintainerPATCH v5 10/16 rust: pci: implement I/O mappable `pci::Bar`
In reply to Danilo KrummrichImplement pci::Bar, pci::Device::iomap_region and pci::Device::iomap_region_sized to allow for I/O mappings of PCI BARs.
To ensure that a pci::Bar, and hence the I/O memory mapping, can't out-live the PCI device, the pci::Bar type is always embedded into a Devres container, such that the pci::Bar is revoked once the device is unbound and hence the I/O mapped memory is unmapped.
A pci::Bar can be requested with (pci::Device::iomap_region_sized) or without (pci::Device::iomap_region) a const generic representing the minimal requested size of the I/O mapped memory region. In case of the latter only runtime checked I/O reads / writes are possible.
--- rust/kernel/pci.rs | 140 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+)
rust/kernel/pci.rs +140 -0
@@ -5,10 +5,14 @@//! C header: [`include/linux/pci.h`](srctree/include/linux/pci.h) use crate ::{ + alloc::flags::*, bindings, container_of, device, device_id::RawDeviceId , + devres::Devres , driver, error::{to_result,Result }, + io::Io , + io::IoRaw , str::CStr , types::{ARef ,ForeignOwnable ,Opaque },ThisModule ,
@@ -241,9 +245,115 @@ pub trait Driver {/// /// A PCI device is based on an always reference counted `device:Device` instance. Cloning a PCI /// device, hence, also increments the base device' reference count. +/// +/// # Invariants +/// +/// `Device` hold a valid reference of `ARef<device::Device>` whose underlying `struct device` is a +/// member of a `struct pci_dev`. #[derive( Clone )] pub struct Device (ARef <device::Device >); +/// A PCI BAR to perform I/O-Operations on. +/// +/// # Invariants +/// +/// `Bar` always holds an `IoRaw` inststance that holds a valid pointer to the start of the I/O +/// memory mapped PCI bar and its size. +pub struct Bar <const SIZE :usize =0 > { + pdev:Device , + io:IoRaw <SIZE >, + num:i32 , +} + +impl <const SIZE :usize >Bar <SIZE > { +fn new (pdev:Device , num:u32 , name: &CStr ) ->Result <Self > { +let len = pdev.resource_len (num)?; +if len ==0 { +return Err (ENOMEM ); + } + +// Convert to `i32`, since that's what all the C bindings use. +let num = i32::try_from (num)?; + +// SAFETY: +// `pdev` is valid by the invariants of `Device`. +// `num` is checked for validity by a previous call to `Device::resource_len`. +// `name` is always valid. +let ret =unsafe { bindings::pci_request_region (pdev.as_raw (), num, name.as_char_ptr ()) }; +if ret !=0 { +return Err (EBUSY ); + } + +// SAFETY: +// `pdev` is valid by the invariants of `Device`. +// `num` is checked for validity by a previous call to `Device::resource_len`. +// `name` is always valid. +let ioptr:usize =unsafe { bindings::pci_iomap (pdev.as_raw (), num,0 ) }as usize ; +if ioptr ==0 { +// SAFETY: +// `pdev` valid by the invariants of `Device`. +// `num` is checked for validity by a previous call to `Device::resource_len`. +unsafe { bindings::pci_release_region (pdev.as_raw (), num) }; +return Err (ENOMEM ); + } + +let io =match IoRaw ::new (ioptr, lenas usize ) { +Ok (io) => io, +Err (err) => { +// SAFETY: +// `pdev` is valid by the invariants of `Device`. +// `ioptr` is guaranteed to be the start of a valid I/O mapped memory region. +// `num` is checked for validity by a previous call to `Device::resource_len`. +unsafe {Self ::do_release (&pdev, ioptr, num) }; +return Err (err); + } + }; + +Ok (Bar { pdev, io, num }) + } + +/// # Safety +/// +/// `ioptr` must be a valid pointer to the memory mapped PCI bar number `num`. +unsafe fn do_release (pdev: &Device , ioptr:usize , num:i32 ) { +// SAFETY: +// `pdev` is valid by the invariants of `Device`. +// `ioptr` is valid by the safety requirements. +// `num` is valid by the safety requirements. +unsafe { + bindings::pci_iounmap (pdev.as_raw (), ioptras _ ); + bindings::pci_release_region (pdev.as_raw (), num); + } + } + +fn release (&self) { +// SAFETY: The safety requirements are guaranteed by the type invariant of `self.pdev`. +unsafe {Self ::do_release (&self.pdev, self.io.addr (), self.num) }; + } +} + +impl Bar { +fn index_is_valid (index:u32 ) ->bool { +// A `struct pci_dev` owns an array of resources with at most `PCI_NUM_RESOURCES` entries. + index < bindings::PCI_NUM_RESOURCES + } +} + +impl <const SIZE :usize >Drop for Bar <SIZE > { +fn drop (&mut self) { + self.release (); + } +} + +impl <const SIZE :usize >Deref for Bar <SIZE > { +type Target =Io <SIZE >; + +fn deref (&self) -> &Self ::Target { +// SAFETY: By the type invariant of `Self`, the MMIO range in `self.io` is properly mapped. +unsafe {Io ::from_raw (&self.io) } + } +} +impl Device {/// Create a PCI Device instance from an existing `device::Device`. ///
@@ -289,6 +399,36 @@ pub fn set_master(&self) {// SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. unsafe { bindings::pci_set_master (self.as_raw ()) }; } + +/// Returns the size of the given PCI bar resource. +pub fn resource_len (&self, bar:u32 ) ->Result <bindings::resource_size_t > { +if !Bar ::index_is_valid (bar) { +return Err (EINVAL ); + } + +// SAFETY: +// - `bar` is a valid bar number, as guaranteed by the above call to `Bar::index_is_valid`, +// - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`. +Ok (unsafe { bindings::pci_resource_len (self.as_raw (), bar.try_into ()?) }) + } + +/// Mapps an entire PCI-BAR after performing a region-request on it. I/O operation bound checks +/// can be performed on compile time for offsets (plus the requested type size) < SIZE. +pub fn iomap_region_sized <const SIZE :usize >( + &self, + bar:u32 , + name: &CStr , + ) ->Result <Devres <Bar <SIZE >>> { +let bar =Bar ::<SIZE >::new (self.clone (), bar, name)?; +let devres =Devres ::new (self.as_ref (), bar,GFP_KERNEL )?; + +Ok (devres) + } + +/// Mapps an entire PCI-BAR after performing a region-request on it. +pub fn iomap_region (&self, bar:u32 , name: &CStr ) ->Result <Devres <Bar >> { + self.iomap_region_sized ::<0 >(bar, name) + } }impl AsRef <device::Device >for Device {
Signature · 1 line
2.47.0
Danilo Krummrich
maintainerPATCH v5 11/16 samples: rust: add Rust PCI sample driver
In reply to Danilo KrummrichThis commit adds a sample Rust PCI driver for QEMU's "pci-testdev" device. To enable this device QEMU has to be called with -device pci-testdev.
The same driver shows how to use the PCI device / driver abstractions, as well as how to request and map PCI BARs, including a short sequence of MMIO operations.
--- MAINTAINERS | 1 + samples/rust/Kconfig | 11 ++++ samples/rust/Makefile | 1 + samples/rust/rust_driver_pci.rs | 110 ++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 samples/rust/rust_driver_pci.rs
MAINTAINERS +1 -0
@@ -18103,6 +18103,7 @@ F: include/linux/of_pci.h F: include/linux/pci* F: include/uapi/linux/pci* F: rust/kernel/pci.rs +F: samples/rust/rust_driver_pci.rs PCIE BANDWIDTH CONTROLLER M: Ilpo Järvinen <[email protected]>
samples/rust/Kconfig +11 -0
@@ -30,6 +30,17 @@ config SAMPLE_RUST_PRINT If unsure, say N. +config SAMPLE_RUST_DRIVER_PCI + tristate "PCI Driver" + depends on PCI + help + This option builds the Rust PCI driver sample. + + To compile this as a module, choose M here: + the module will be called driver_pci. + + If unsure, say N. + config SAMPLE_RUST_HOSTPROGS bool "Host programs" help
samples/rust/Makefile +1 -0
@@ -3,6 +3,7 @@ ccflags-y += -I$(src) # needed for trace events obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o rust_print-y := rust_print_main.o rust_print_events.o
samples/rust/rust_driver_pci.rs new file +110 -0
110 lines not on this page · raw message
Signature · 1 line
2.47.0
kernel test robot
build botRe: [PATCH v5 11/16] samples: rust: add Rust PCI sample driver
kernel test robot noticed the following build errors:
Hi Danilo,
kernel test robot noticed the following build errors:
[auto build test ERROR on fac04efc5c793dccbd07e2d59af9f90b7fc0dca4]
url: https://github.com/intel-lab-lkp/linux/commits/Danilo-Krummrich/rust-pass-module-name-to-Module-init/20241211-065809 base: fac04efc5c793dccbd07e2d59af9f90b7fc0dca4 patch link: https://lore.kernel.org/r/20241210224947.23804-12-dakr%40kernel.org patch subject: [PATCH v5 11/16] samples: rust: add Rust PCI sample driver config: x86_64-randconfig-004-20241216 (https://download.01.org/0day-ci/archive/20241216/[email protected]/config) compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241216/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All error/warnings (new ones prefixed by >>):
>> error[E0432]: unresolved import `kernel::pci`
--> samples/rust/rust_driver_pci.rs:7:47
|
7 | use kernel::{bindings, c_str, devres::Devres, pci, prelude::*};
| ^^^ no pci in the root
|
note: found an item that was configured out
--> rust/kernel/lib.rs:86:9
|
86 | pub mod pci;
| ^^^
--
>> error[E0433]: failed to resolve: could not find `pci_device_table` in `kernel`
--> samples/rust/rust_driver_pci.rs:33:9
|
33 | kernel::pci_device_table!(
| ^^^^^^^^^^^^^^^^ could not find pci_device_table in kernel
--
>> error[E0433]: failed to resolve: could not find `module_pci_driver` in `kernel`
--> samples/rust/rust_driver_pci.rs:104:9
|
104 | kernel::module_pci_driver! {
| ^^^^^^^^^^^^^^^^^ could not find module_pci_driver in kernel
--
>> error[E0425]: cannot find value `PCI_TABLE` in this scope
--> samples/rust/rust_driver_pci.rs:63:51
|
63 | const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
| ^^^^^^^^^ not found in this scope
--
>> warning: unused import: `bindings`
--> samples/rust/rust_driver_pci.rs:7:14
|
7 | use kernel::{bindings, c_str, devres::Devres, pci, prelude::*};
| ^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Danilo Krummrich
maintainerPATCH v5 12/16 rust: of: add `of::DeviceId` abstraction
In reply to Danilo Krummrichof::DeviceId is an abstraction around struct of_device_id.
This is used by subsequent patches, in particular the platform bus abstractions, to create OF device ID tables.
--- MAINTAINERS | 1 + rust/kernel/lib.rs | 1 + rust/kernel/of.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 rust/kernel/of.rs
MAINTAINERS +1 -0
@@ -17502,6 +17502,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git F: Documentation/ABI/testing/sysfs-firmware-ofw F: drivers/of/ F: include/linux/of*.h +F: rust/kernel/of.rs F: scripts/dtc/ F: tools/testing/selftests/dt/ K: of_overlay_notifier_
rust/kernel/lib.rs +1 -0
@@ -56,6 +56,7 @@pub mod miscdevice;#[cfg( CONFIG_NET )] pub mod net; +pub mod of;pub mod page;pub mod pid_namespace;pub mod prelude;
rust/kernel/of.rs new file +60 -0
60 lines not on this page · raw message
Signature · 1 line
2.47.0
Danilo Krummrich
maintainerPATCH v5 13/16 rust: driver: implement `Adapter`
In reply to Danilo KrummrichIn order to not duplicate code in bus specific implementations (e.g. platform), implement a generic driver::Adapter to represent the connection of matched drivers and devices.
Bus specific Adapter implementations can simply implement this trait to inherit generic functionality, such as matching OF or ACPI device IDs and ID table entries.
--- rust/kernel/driver.rs | 59 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-)
rust/kernel/driver.rs +58 -1
@@ -6,7 +6,9 @@//! register using the [`Registration`] class. use crate ::error::{Error ,Result }; -use crate ::{init::PinInit , str::CStr , try_pin_init, types::Opaque ,ThisModule }; +use crate ::{ + device, device_id, init::PinInit , of, str::CStr , try_pin_init, types::Opaque ,ThisModule , +};use core::pin::Pin ;use macros::{pin_data, pinned_drop};
@@ -114,3 +116,58 @@ macro_rules! module_driver { } } } + +/// The bus independent adapter to match a drivers and a devices. +/// +/// This trait should be implemented by the bus specific adapter, which represents the connection +/// of a device and a driver. +/// +/// It provides bus independent functions for device / driver interactions. +pub trait Adapter { +/// The type holding driver private data about each device id supported by the driver. +type IdInfo : 'static; + +/// The [`of::IdTable`] of the corresponding driver. +fn of_id_table () -> of::IdTable <Self ::IdInfo >; + +/// Returns the driver's private data from the matching entry in the [`of::IdTable`], if any. +/// +/// If this returns `None`, it means there is no match with an entry in the [`of::IdTable`]. +#[cfg( CONFIG_OF )] +fn of_id_info (dev: &device::Device ) ->Option <&'staticSelf ::IdInfo > { +let table =Self ::of_id_table (); + +// SAFETY: +// - `table` has static lifetime, hence it's valid for read, +// - `dev` is guaranteed to be valid while it's alive, and so is `pdev.as_ref().as_raw()`. +let raw_id =unsafe { bindings::of_match_device (table.as_ptr (), dev.as_raw ()) }; + +if raw_id.is_null () { +None + }else { +// SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct of_device_id` and +// does not add additional invariants, so it's safe to transmute. +let id =unsafe { &*raw_id.cast ::<of::DeviceId >() }; + +Some (table.info (<of::DeviceId as device_id::RawDeviceId >::index (id))) + } + } + +#[cfg(not( CONFIG_OF ))] +fn of_id_info (_dev: &device::Device ) ->Option <&'staticSelf ::IdInfo > { +None + } + +/// Returns the driver's private data from the matching entry of any of the ID tables, if any. +/// +/// If this returns `None`, it means that there is no match in any of the ID tables directly +/// associated with a [`device::Device`]. +fn id_info (dev: &device::Device ) ->Option <&'staticSelf ::IdInfo > { +let id =Self ::of_id_info (dev); +if id.is_some () { +return id; + } + +None + } +}
Signature · 1 line
2.47.0
Re: [PATCH v5 13/16] rust: driver: implement `Adapter`
Hi Danilo,
Quoted 37 lines · Danilo Krummrich
In order to not duplicate code in bus specific implementations (e.g. platform), implement a generic
driver::Adapterto represent the connection of matched drivers and devices.Bus specific
Adapterimplementations can simply implement this trait to inherit generic functionality, such as matching OF or ACPI device IDs and ID table entries.Suggested-by Rob Herring (Arm) <[email protected]>Signed-off-by Danilo Krummrich <[email protected]>--- rust/kernel/driver.rs | 59 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-)rust/kernel/driver.rs +6
-1@@ -6,7 +6,9 @@//! register using the [`Registration`] class. use crate ::error::{Error ,Result }; -use crate ::{init::PinInit , str::CStr , try_pin_init, types::Opaque ,ThisModule }; +use crate ::{ + device, device_id, init::PinInit , of, str::CStr , try_pin_init, types::Opaque ,ThisModule , +};use core::pin::Pin ;use macros::{pin_data, pinned_drop};@@ -114,3 +116,58 @@ macro_rules! module_driver { } } } + +/// The bus independent adapter to match a drivers and a devices. +///
rust/kernel/driver.rs macro_rules! module_driver { · line 131
Quoted 10 lines
rust/kernel/driver.rs +10
-0+/// This trait should be implemented by the bus specific adapter, which represents the connection +/// of a device and a driver. +/// +/// It provides bus independent functions for device / driver interactions. +pub trait Adapter { +/// The type holding driver private data about each device id supported by the driver. +type IdInfo : 'static; + +/// The [`of::IdTable`] of the corresponding driver. +fn of_id_table () -> of::IdTable <Self ::IdInfo >;
I think we may want this to return an Option<of::IdTable<Self::IdInfo>> instead. I don't think we want to force every bus abstraction to have to implement every possible IdTable that this adapter will support.
For instance if your driver only supports ACPI, it will still be required to provide an empty OF table because the bus abstraction needs it for implementing this trait.
Quoted 45 lines
rust/kernel/driver.rs +42
-1+ +/// Returns the driver's private data from the matching entry in the [`of::IdTable`], if any. +/// +/// If this returns `None`, it means there is no match with an entry in the [`of::IdTable`]. +#[cfg( CONFIG_OF )] +fn of_id_info (dev: &device::Device ) ->Option <&'staticSelf ::IdInfo > { +let table =Self ::of_id_table (); + +// SAFETY: +// - `table` has static lifetime, hence it's valid for read, +// - `dev` is guaranteed to be valid while it's alive, and so is `pdev.as_ref().as_raw()`. +let raw_id =unsafe { bindings::of_match_device (table.as_ptr (), dev.as_raw ()) }; + +if raw_id.is_null () { +None + }else { +// SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct of_device_id` and +// does not add additional invariants, so it's safe to transmute. +let id =unsafe { &*raw_id.cast ::<of::DeviceId >() }; + +Some (table.info (<of::DeviceId as device_id::RawDeviceId >::index (id))) + } + } + +#[cfg(not( CONFIG_OF ))] +fn of_id_info (_dev: &device::Device ) ->Option <&'staticSelf ::IdInfo > { +None + } + +/// Returns the driver's private data from the matching entry of any of the ID tables, if any. +/// +/// If this returns `None`, it means that there is no match in any of the ID tables directly +/// associated with a [`device::Device`]. +fn id_info (dev: &device::Device ) ->Option <&'staticSelf ::IdInfo > { +let id =Self ::of_id_info (dev); +if id.is_some () { +return id; + } + +None + } +} --2.47.0
Danilo Krummrich
maintainerPATCH v5 14/16 rust: platform: add basic platform device / driver abstractions
In reply to Danilo KrummrichImplement the basic platform bus abstractions required to write a basic platform driver. This includes the following data structures:
The platform::Driver trait represents the interface to the driver and provides platform::Driver::probe for the driver to implement.
The platform::Device abstraction represents a struct platform_device.
In order to provide the platform bus specific parts to a generic driver::Registration the driver::RegistrationOps trait is implemented by platform::Adapter.
--- MAINTAINERS | 1 + rust/bindings/bindings_helper.h | 2 + rust/helpers/helpers.c | 1 + rust/helpers/platform.c | 13 +++ rust/kernel/lib.rs | 1 + rust/kernel/platform.rs | 193 ++++++++++++++++++++++++++++++++ 6 files changed, 211 insertions(+) create mode 100644 rust/helpers/platform.c create mode 100644 rust/kernel/platform.rs
MAINTAINERS +1 -0
@@ -7036,6 +7036,7 @@ F: rust/kernel/device.rs F: rust/kernel/device_id.rs F: rust/kernel/devres.rs F: rust/kernel/driver.rs +F: rust/kernel/platform.rs DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS) M: Nishanth Menon <[email protected]>
rust/bindings/bindings_helper.h +2 -0
@@ -20,9 +20,11 @@#include <linux/jump_label.h> #include <linux/mdio.h> #include <linux/miscdevice.h> +#include <linux/of_device.h> #include <linux/pci.h> #include <linux/phy.h> #include <linux/pid_namespace.h> +#include <linux/platform_device.h> #include <linux/poll.h> #include <linux/refcount.h> #include <linux/sched.h>
rust/helpers/helpers.c +1 -0
@@ -20,6 +20,7 @@#include "kunit.c" #include "mutex.c" #include "page.c" +#include "platform.c" #include "pci.c" #include "pid_namespace.c" #include "rbtree.c"
rust/helpers/platform.c new file +13 -0
@@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/platform_device.h> + +void *rust_helper_platform_get_drvdata (const struct platform_device *pdev) +{ +return platform_get_drvdata (pdev); +} + +void rust_helper_platform_set_drvdata (struct platform_device *pdev,void *data) +{ +platform_set_drvdata (pdev, data); +}
rust/kernel/lib.rs +1 -0
@@ -59,6 +59,7 @@pub mod of;pub mod page;pub mod pid_namespace; +pub mod platform;pub mod prelude;pub mod print;pub mod rbtree;
rust/kernel/platform.rs new file +193 -0
193 lines not on this page · raw message
Signature · 1 line
2.47.0
Re: [PATCH v5 14/16] rust: platform: add basic platform device / driver abstractions
Quoted 13 lines · Danilo Krummrich
Implement the basic platform bus abstractions required to write a basic platform driver. This includes the following data structures:
The
platform::Drivertrait represents the interface to the driver and providesplatform::Driver::probefor the driver to implement.The
platform::Deviceabstraction represents astruct platform_device.In order to provide the platform bus specific parts to a generic
driver::Registrationthedriver::RegistrationOpstrait is implemented byplatform::Adapter.Signed-off-by Danilo Krummrich <[email protected]>
Quoted 10 lines
--- MAINTAINERS | 1 + rust/bindings/bindings_helper.h | 2 + rust/helpers/helpers.c | 1 + rust/helpers/platform.c | 13 +++ rust/kernel/lib.rs | 1 + rust/kernel/platform.rs | 193 ++++++++++++++++++++++++++++++++ 6 files changed, 211 insertions(+) create mode 100644 rust/helpers/platform.c create mode 100644 rust/kernel/platform.rs
Danilo Krummrich
maintainerPATCH v5 15/16 samples: rust: add Rust platform sample driver
In reply to Danilo KrummrichAdd a sample Rust platform driver illustrating the usage of the platform bus abstractions.
This driver probes through either a match of device / driver name or a match within the OF ID table.
--- MAINTAINERS | 1 + drivers/of/unittest-data/tests-platform.dtsi | 5 ++ samples/rust/Kconfig | 10 ++++ samples/rust/Makefile | 1 + samples/rust/rust_driver_platform.rs | 49 ++++++++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 samples/rust/rust_driver_platform.rs
MAINTAINERS +1 -0
@@ -7037,6 +7037,7 @@ F: rust/kernel/device_id.rs F: rust/kernel/devres.rs F: rust/kernel/driver.rs F: rust/kernel/platform.rs +F: samples/rust/rust_driver_platform.rs DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS) M: Nishanth Menon <[email protected]>
drivers/of/unittest-data/tests-platform.dtsi +5 -0
@@ -33,6 +33,11 @@ dev@100 { reg = <0x100>; }; }; + + test-device@2 { + compatible = "test,rust-device"; + reg = <0x2>; + }; }; }; };
samples/rust/Kconfig +10 -0
@@ -41,6 +41,16 @@ config SAMPLE_RUST_DRIVER_PCI If unsure, say N. +config SAMPLE_RUST_DRIVER_PLATFORM + tristate "Platform Driver" + help + This option builds the Rust Platform driver sample. + + To compile this as a module, choose M here: + the module will be called rust_driver_platform. + + If unsure, say N. + config SAMPLE_RUST_HOSTPROGS bool "Host programs" help
samples/rust/Makefile +1 -0
@@ -4,6 +4,7 @@ ccflags-y += -I$(src) # needed for trace events obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o rust_print-y := rust_print_main.o rust_print_events.o
samples/rust/rust_driver_platform.rs new file +49 -0
49 lines not on this page · raw message
Signature · 1 line
2.47.0
Re: [PATCH v5 15/16] samples: rust: add Rust platform sample driver
Quoted 7 lines · Danilo Krummrich
Add a sample Rust platform driver illustrating the usage of the platform bus abstractions.
This driver probes through either a match of device / driver name or a match within the OF ID table.
Signed-off-by Danilo Krummrich <[email protected]>
Quoted 8 lines
--- MAINTAINERS | 1 + drivers/of/unittest-data/tests-platform.dtsi | 5 ++ samples/rust/Kconfig | 10 ++++ samples/rust/Makefile | 1 + samples/rust/rust_driver_platform.rs | 49 ++++++++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 samples/rust/rust_driver_platform.rs
Danilo Krummrich
maintainerPATCH v5 16/16 MAINTAINERS: add Danilo to DRIVER CORE
In reply to Danilo KrummrichLet's keep an eye on the Rust abstractions; add myself as reviewer to DRIVER CORE.
--- MAINTAINERS | 1 + 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
@@ -7021,6 +7021,7 @@ F: include/linux/component.h DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS M: Greg Kroah-Hartman <[email protected]> R: "Rafael J. Wysocki" <[email protected]> +R: Danilo Krummrich <[email protected]> S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git F: Documentation/core-api/kobject.rst
Signature · 1 line
2.47.0