rust: driver: let probe() return impl PinInit<Self, Error>
Subsystems (14)
Danilo Krummrich
maintainerPATCH 1/1 rust: driver: let probe() return impl PinInit<Self, Error>
The driver model defines the lifetime of the private data stored in (and owned by) a bus device to be valid from when the driver is bound to a device (i.e. from successful probe()) until the driver is unbound from the device.
This is already taken care of by the Rust implementation of the driver model. However, we still ask drivers to return a Result<Pin<KBox<Self>>> from probe().
Unlike in C, where we do not have the concept of initializers, but rather deal with uninitialized memory, drivers can just return an impl PinInit<Self, Error> instead.
This contributed to more clarity to the fact that a driver returns it's device private data in probe() and the Rust driver model owns the data, manages the lifetime and - considering the lifetime - provides (safe) accessors for the driver.
Hence, let probe() functions return an impl PinInit<Self, Error> instead of Result<Pin<KBox<Self>>>.
---
Depends on a minor pin-init patch [1] (Benno will send it to the list soon). A branch with this patch and the pin-init dependency is available in [2].
[1] https://github.com/Rust-for-Linux/pin-init/pull/86/commits
[2] https://git.kernel.org/pub/scm/linux/kernel/git/dakr/linux.git/log/?h=probe_return
--- drivers/cpufreq/rcpufreq_dt.rs | 4 +- drivers/gpu/drm/nova/driver.rs | 4 +- drivers/gpu/drm/tyr/driver.rs | 4 +- drivers/gpu/nova-core/driver.rs | 34 +++++++---------- rust/kernel/auxiliary.rs | 6 +-- rust/kernel/cpufreq.rs | 4 +- rust/kernel/device.rs | 9 ++++- rust/kernel/driver.rs | 4 +- rust/kernel/io/mem.rs | 8 ++-- rust/kernel/pci.rs | 8 ++-- rust/kernel/platform.rs | 12 +++--- rust/kernel/usb.rs | 4 +- samples/rust/rust_debugfs.rs | 21 ++++++----- samples/rust/rust_dma.rs | 37 +++++++++---------- samples/rust/rust_driver_auxiliary.rs | 25 +++++-------- samples/rust/rust_driver_pci.rs | 53 +++++++++++++-------------- samples/rust/rust_driver_platform.rs | 6 +-- samples/rust/rust_driver_usb.rs | 5 +-- 18 files changed, 117 insertions(+), 131 deletions(-)
drivers/cpufreq/rcpufreq_dt.rs +2 -2
@@ -207,9 +207,9 @@ impl platform::Driver for CPUFreqDTDriver {fn probe ( pdev: &platform::Device <Core >, _id_info:Option <&Self ::IdInfo >, - ) ->Result <Pin <KBox <Self >>> { + ) ->impl PinInit <Self ,Error > { cpufreq::Registration ::<CPUFreqDTDriver >::new_foreign_owned (pdev.as_ref ())?; -Ok (KBox ::new (Self {},GFP_KERNEL )?.into ()) +Ok (Self {}) } }
drivers/gpu/drm/nova/driver.rs +2 -2
@@ -45,13 +45,13 @@ impl auxiliary::Driver for NovaDriver {type IdInfo = ();const ID_TABLE : auxiliary::IdTable <Self ::IdInfo > = &AUX_TABLE ; -fn probe (adev: &auxiliary::Device <Core >, _info: &Self ::IdInfo ) ->Result <Pin <KBox <Self >>> { +fn probe (adev: &auxiliary::Device <Core >, _info: &Self ::IdInfo ) ->impl PinInit <Self ,Error > {let data =try_pin_init! (NovaData { adev: adev.into () });let drm = drm::Device ::<Self >::new (adev.as_ref (), data)?; drm::Registration ::new_foreign_owned (&drm, adev.as_ref (),0 )?; -Ok (KBox ::new (Self { drm },GFP_KERNEL )?.into ()) +Ok (Self { drm }) } }
drivers/gpu/drm/tyr/driver.rs +2 -2
@@ -103,7 +103,7 @@ impl platform::Driver for TyrDriver {fn probe ( pdev: &platform::Device <Core >, _info:Option <&Self ::IdInfo >, - ) ->Result <Pin <KBox <Self >>> { + ) ->impl PinInit <Self ,Error > {let core_clk =Clk ::get (pdev.as_ref (),Some (c_str! ("core" )))?;let stacks_clk =OptionalClk ::get (pdev.as_ref (),Some (c_str! ("stacks" )))?;let coregroup_clk =OptionalClk ::get (pdev.as_ref (),Some (c_str! ("coregroup" )))?;
@@ -143,7 +143,7 @@ fn probe(let tdev:ARef <TyrDevice > = drm::Device ::new (pdev.as_ref (), data)?; drm::driver::Registration ::new_foreign_owned (&tdev, pdev.as_ref (),0 )?; -let driver =KBox ::pin_init (try_pin_init! (TyrDriver { device: tdev }),GFP_KERNEL )?; +let driver =TyrDriver { device: tdev };// We need this to be dev_info!() because dev_dbg!() does not work at // all in Rust for now, and we need to see whether probe succeeded.
drivers/gpu/nova-core/driver.rs +13 -21
@@ -51,36 +51,28 @@ impl pci::Driver for NovaCore {type IdInfo = ();const ID_TABLE : pci::IdTable <Self ::IdInfo > = &PCI_TABLE ; -fn probe (pdev: &pci::Device <Core >, _info: &Self ::IdInfo ) ->Result <Pin <KBox <Self >>> { -dev_dbg! (pdev.as_ref (),"Probe Nova Core GPU driver.\n" ); +fn probe (pdev: &pci::Device <Core >, _info: &Self ::IdInfo ) ->impl PinInit <Self ,Error > { + pin_init::pin_init_scope (move || { +dev_dbg! (pdev.as_ref (),"Probe Nova Core GPU driver.\n" ); - pdev.enable_device_mem ()?; - pdev.set_master (); + pdev.enable_device_mem ()?; + pdev.set_master (); -let devres_bar =Arc ::pin_init ( - pdev.iomap_region_sized ::<BAR0_SIZE >(0 ,c_str! ("nova-core/bar0" )), -GFP_KERNEL , - )?; +let bar =Arc ::pin_init ( + pdev.iomap_region_sized ::<BAR0_SIZE >(0 ,c_str! ("nova-core/bar0" )), +GFP_KERNEL , + )?; -// Used to provided a `&Bar0` to `Gpu::new` without tying it to the lifetime of -// `devres_bar`. -let bar_clone =Arc ::clone (&devres_bar); -let bar = bar_clone.access (pdev.as_ref ())?; - -let this =KBox ::pin_init ( -try_pin_init! (Self { - gpu <-Gpu ::new (pdev, devres_bar, bar), +Ok (try_pin_init! (Self { + gpu <-Gpu ::new (pdev, bar.clone (), bar.access (pdev.as_ref ())?), _reg: auxiliary::Registration ::new ( pdev.as_ref (),c_str! ("nova-drm" ),0 ,// TODO[XARR]: Once it lands, use XArray; for now we don't use the ID. crate ::MODULE_NAME )?, - }), -GFP_KERNEL , - )?; - -Ok (this) + })) + }) }fn unbind (pdev: &pci::Device <Core >, this:Pin <&Self >) {
rust/kernel/auxiliary.rs +3 -3
@@ -68,9 +68,9 @@ extern "C" fn probe_callback(let info =T ::ID_TABLE .info (id.index ());from_result (|| { -let data =T ::probe (adev, info)?; +let data =T ::probe (adev, info); - adev.as_ref ().set_drvdata (data); + adev.as_ref ().set_drvdata (data)?;Ok (0 ) }) }
@@ -184,7 +184,7 @@ pub trait Driver {/// Auxiliary driver probe. /// /// Called when an auxiliary device is matches a corresponding driver. -fn probe (dev: &Device <device::Core >, id_info: &Self ::IdInfo ) ->Result <Pin <KBox <Self >>>; +fn probe (dev: &Device <device::Core >, id_info: &Self ::IdInfo ) ->impl PinInit <Self ,Error >; }/// The auxiliary device representation.
rust/kernel/cpufreq.rs +2 -2
@@ -894,9 +894,9 @@ fn register_em(_policy: &mut Policy) {/// fn probe( /// pdev: &platform::Device<Core>, /// _id_info: Option<&Self::IdInfo>, -/// ) -> Result<Pin<KBox<Self>>> { +/// ) -> impl PinInit<Self, Error> { /// cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?; -/// Ok(KBox::new(Self {}, GFP_KERNEL)?.into()) +/// Ok(Self {}) /// } /// } /// ```
rust/kernel/device.rs +7 -2
@@ -6,6 +6,7 @@use crate ::{ bindings, fmt, + prelude::*, sync::aref::ARef , types::{ForeignOwnable ,Opaque }, };
@@ -198,9 +199,13 @@ pub unsafe fn as_bound(&self) -> &Device<Bound> {impl Device <CoreInternal > {/// Store a pointer to the bound driver's private data. -pub fn set_drvdata (&self, data:impl ForeignOwnable ) { +pub fn set_drvdata <T : 'static>(&self, data:impl PinInit <T ,Error >) ->Result { +let data =KBox ::pin_init (data,GFP_KERNEL )?; +// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. -unsafe { bindings::dev_set_drvdata (self.as_raw (), data.into_foreign ().cast ()) } +unsafe { bindings::dev_set_drvdata (self.as_raw (), data.into_foreign ().cast ()) }; + +Ok (()) }/// Take ownership of the private data stored in this [`Device`].
rust/kernel/driver.rs +2 -2
@@ -24,7 +24,7 @@//! const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None; //! //! /// Driver probe. -//! fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; +//! fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>; //! //! /// Driver unbind (optional). //! fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) {
@@ -35,7 +35,7 @@//! //! For specific examples see [`auxiliary::Driver`], [`pci::Driver`] and [`platform::Driver`]. //! -//! The `probe()` callback should return a `Result<Pin<KBox<Self>>>`, i.e. the driver's private +//! The `probe()` callback should return a `impl PinInit<Self, Error>`, i.e. the driver's private //! data. The bus abstraction should store the pointer in the corresponding bus device. The generic //! [`Device`] infrastructure provides common helpers for this purpose on its //! [`Device<CoreInternal>`] implementation.
rust/kernel/io/mem.rs +4 -4
@@ -53,7 +53,7 @@ pub(crate) unsafe fn new(device: &'a Device<Bound>, resource: &'a Resource) -> S/// fn probe( /// pdev: &platform::Device<Core>, /// info: Option<&Self::IdInfo>, -/// ) -> Result<Pin<KBox<Self>>> { +/// ) -> impl PinInit<Self, Error> { /// let offset = 0; // Some offset. /// /// // If the size is known at compile time, use [`Self::iomap_sized`].
@@ -70,7 +70,7 @@ pub(crate) unsafe fn new(device: &'a Device<Bound>, resource: &'a Resource) -> S/// /// io.write32_relaxed(data, offset); /// -/// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) +/// # Ok(SampleDriver) /// } /// } /// ```
@@ -111,7 +111,7 @@ pub fn iomap_exclusive_sized<const SIZE: usize>(/// fn probe( /// pdev: &platform::Device<Core>, /// info: Option<&Self::IdInfo>, -/// ) -> Result<Pin<KBox<Self>>> { +/// ) -> impl PinInit<Self, Error> { /// let offset = 0; // Some offset. /// /// // Unlike [`Self::iomap_sized`], here the size of the memory region
@@ -128,7 +128,7 @@ pub fn iomap_exclusive_sized<const SIZE: usize>(/// /// io.try_write32_relaxed(data, offset)?; /// -/// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) +/// # Ok(SampleDriver) /// } /// } /// ```
rust/kernel/pci.rs +4 -4
@@ -131,9 +131,9 @@ extern "C" fn probe_callback(let info =T ::ID_TABLE .info (id.index ());from_result (|| { -let data =T ::probe (pdev, info)?; +let data =T ::probe (pdev, info); - pdev.as_ref ().set_drvdata (data); + pdev.as_ref ().set_drvdata (data)?;Ok (0 ) }) }
@@ -302,7 +302,7 @@ macro_rules! pci_device_table {/// fn probe( /// _pdev: &pci::Device<Core>, /// _id_info: &Self::IdInfo, -/// ) -> Result<Pin<KBox<Self>>> { +/// ) -> impl PinInit<Self, Error> { /// Err(ENODEV) /// } /// }
@@ -325,7 +325,7 @@ pub trait Driver: Send {/// /// Called when a new pci device is added or discovered. Implementers should /// attempt to initialize the device here. -fn probe (dev: &Device <device::Core >, id_info: &Self ::IdInfo ) ->Result <Pin <KBox <Self >>>; +fn probe (dev: &Device <device::Core >, id_info: &Self ::IdInfo ) ->impl PinInit <Self ,Error >;/// PCI driver unbind. ///
rust/kernel/platform.rs +7 -5
@@ -74,9 +74,9 @@ extern "C" fn probe_callback(pdev: *mut bindings::platform_device) -> kernel::fflet info = <Self as driver::Adapter >::id_info (pdev.as_ref ());from_result (|| { -let data =T ::probe (pdev, info)?; +let data =T ::probe (pdev, info); - pdev.as_ref ().set_drvdata (data); + pdev.as_ref ().set_drvdata (data)?;Ok (0 ) }) }
@@ -166,7 +166,7 @@ macro_rules! module_platform_driver {/// fn probe( /// _pdev: &platform::Device<Core>, /// _id_info: Option<&Self::IdInfo>, -/// ) -> Result<Pin<KBox<Self>>> { +/// ) -> impl PinInit<Self, Error> { /// Err(ENODEV) /// } /// }
@@ -190,8 +190,10 @@ pub trait Driver: Send {/// /// Called when a new platform device is added or discovered. /// Implementers should attempt to initialize the device here. -fn probe (dev: &Device <device::Core >, id_info:Option <&Self ::IdInfo >) - ->Result <Pin <KBox <Self >>>; +fn probe ( + dev: &Device <device::Core >, + id_info:Option <&Self ::IdInfo >, + ) ->impl PinInit <Self ,Error >;/// Platform driver unbind. ///
rust/kernel/usb.rs +2 -2
@@ -270,7 +270,7 @@ macro_rules! usb_device_table {/// _interface: &usb::Interface<Core>, /// _id: &usb::DeviceId, /// _info: &Self::IdInfo, -/// ) -> Result<Pin<KBox<Self>>> { +/// ) -> impl PinInit<Self, Error> { /// Err(ENODEV) /// } ///
@@ -292,7 +292,7 @@ fn probe( interface: &Interface<device::Core>, id: &DeviceId, id_info: &Self::IdInfo, - ) -> Result<Pin<KBox<Self>>>; + ) -> impl PinInit<Self, Error>;/// USB driver disconnect. ///
samples/rust/rust_debugfs.rs +11 -10
@@ -106,16 +106,17 @@ impl platform::Driver for RustDebugFs {fn probe ( pdev: &platform::Device <Core >, _info:Option <&Self ::IdInfo >, - ) ->Result <Pin <KBox <Self >>> { -let result =KBox ::try_pin_init (RustDebugFs ::new (pdev),GFP_KERNEL )?; -// We can still mutate fields through the files which are atomic or mutexed: - result.counter.store (91 ,Ordering ::Relaxed ); - { -let mut guard = result.inner.lock (); - guard.x = guard.y; - guard.y =42 ; - } -Ok (result) + ) ->impl PinInit <Self ,Error > { +RustDebugFs ::new (pdev).pin_chain (|this| { + this.counter.store (91 ,Ordering ::Relaxed ); + { +let mut guard = this.inner.lock (); + guard.x = guard.y; + guard.y =42 ; + } + +Ok (()) + }) } }
samples/rust/rust_dma.rs +17 -20
@@ -55,36 +55,33 @@ impl pci::Driver for DmaSampleDriver {type IdInfo = ();const ID_TABLE : pci::IdTable <Self ::IdInfo > = &PCI_TABLE ; -fn probe (pdev: &pci::Device <Core >, _info: &Self ::IdInfo ) ->Result <Pin <KBox <Self >>> { -dev_info! (pdev.as_ref (),"Probe DMA test driver.\n" ); +fn probe (pdev: &pci::Device <Core >, _info: &Self ::IdInfo ) ->impl PinInit <Self ,Error > { + pin_init::pin_init_scope (move || { +dev_info! (pdev.as_ref (),"Probe DMA test driver.\n" ); -let mask =DmaMask ::new ::<64 >(); +let mask =DmaMask ::new ::<64 >(); -// SAFETY: There are no concurrent calls to DMA allocation and mapping primitives. -unsafe { pdev.dma_set_mask_and_coherent (mask)? }; +// SAFETY: There are no concurrent calls to DMA allocation and mapping primitives. +unsafe { pdev.dma_set_mask_and_coherent (mask)? }; -let ca:CoherentAllocation <MyStruct > = -CoherentAllocation ::alloc_coherent (pdev.as_ref (),TEST_VALUES .len (),GFP_KERNEL )?; +let ca:CoherentAllocation <MyStruct > = +CoherentAllocation ::alloc_coherent (pdev.as_ref (),TEST_VALUES .len (),GFP_KERNEL )?; -for (i, value)in TEST_VALUES .into_iter ().enumerate () { - kernel::dma_write!(ca[i] =MyStruct ::new (value.0 , value.1 ))?; - } +for (i, value)in TEST_VALUES .into_iter ().enumerate () { + kernel::dma_write!(ca[i] =MyStruct ::new (value.0 , value.1 ))?; + } -let size =4 * page::PAGE_SIZE ; -let pages =VVec ::with_capacity (size,GFP_KERNEL )?; +let size =4 * page::PAGE_SIZE ; +let pages =VVec ::with_capacity (size,GFP_KERNEL )?; -let sgt =SGTable ::new (pdev.as_ref (), pages,DataDirection ::ToDevice ,GFP_KERNEL ); +let sgt =SGTable ::new (pdev.as_ref (), pages,DataDirection ::ToDevice ,GFP_KERNEL ); -let drvdata =KBox ::pin_init ( -try_pin_init! (Self { +Ok (try_pin_init! (Self { pdev: pdev.into (), ca, sgt <- sgt, - }), -GFP_KERNEL , - )?; - -Ok (drvdata) + })) + }) } }
samples/rust/rust_driver_auxiliary.rs +9 -16
@@ -27,7 +27,7 @@ impl auxiliary::Driver for AuxiliaryDriver {const ID_TABLE : auxiliary::IdTable <Self ::IdInfo > = &AUX_TABLE ; -fn probe (adev: &auxiliary::Device <Core >, _info: &Self ::IdInfo ) ->Result <Pin <KBox <Self >>> { +fn probe (adev: &auxiliary::Device <Core >, _info: &Self ::IdInfo ) ->impl PinInit <Self ,Error > {dev_info! ( adev.as_ref (),"Probing auxiliary driver for auxiliary device with id={}\n" ,
@@ -36,9 +36,7 @@ fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBoParentDriver ::connect (adev)?; -let this =KBox ::new (Self ,GFP_KERNEL )?; - -Ok (this.into ()) +Ok (Self ) } }
@@ -58,18 +56,13 @@ impl pci::Driver for ParentDriver {const ID_TABLE : pci::IdTable <Self ::IdInfo > = &PCI_TABLE ; -fn probe (pdev: &pci::Device <Core >, _info: &Self ::IdInfo ) ->Result <Pin <KBox <Self >>> { -let this =KBox ::new ( -Self { - _reg: [ - auxiliary::Registration ::new (pdev.as_ref (),AUXILIARY_NAME ,0 ,MODULE_NAME )?, - auxiliary::Registration ::new (pdev.as_ref (),AUXILIARY_NAME ,1 ,MODULE_NAME )?, - ], - }, -GFP_KERNEL , - )?; - -Ok (this.into ()) +fn probe (pdev: &pci::Device <Core >, _info: &Self ::IdInfo ) ->impl PinInit <Self ,Error > { +Ok (Self { + _reg: [ + auxiliary::Registration ::new (pdev.as_ref (),AUXILIARY_NAME ,0 ,MODULE_NAME )?, + auxiliary::Registration ::new (pdev.as_ref (),AUXILIARY_NAME ,1 ,MODULE_NAME )?, + ], + }) } }
samples/rust/rust_driver_pci.rs +26 -27
61 lines not on this page · raw message
samples/rust/rust_driver_platform.rs +2 -4
@@ -103,7 +103,7 @@ impl platform::Driver for SampleDriver {fn probe ( pdev: &platform::Device <Core >, info:Option <&Self ::IdInfo >, - ) ->Result <Pin <KBox <Self >>> { + ) ->impl PinInit <Self ,Error > {let dev = pdev.as_ref ();dev_dbg! (dev,"Probe Rust Platform driver sample.\n" );
@@ -116,9 +116,7 @@ fn probe(Self ::properties_parse (dev)?; } -let drvdata =KBox ::new (Self { pdev: pdev.into () },GFP_KERNEL )?; - -Ok (drvdata.into ()) +Ok (Self { pdev: pdev.into () }) } }
samples/rust/rust_driver_usb.rs +2 -3
@@ -24,12 +24,11 @@ fn probe( intf: &usb::Interface<Core>, _id: &usb::DeviceId, _info: &Self::IdInfo, - ) -> Result<Pin<KBox<Self>>> { + ) -> impl PinInit<Self, Error> {let dev: &device::Device <Core > = intf.as_ref ();dev_info! (dev,"Rust USB driver sample probed\n" ); -let drvdata =KBox ::new (Self { _intf: intf.into () },GFP_KERNEL )?; -Ok (drvdata.into ()) + Ok(Self { _intf: intf.into() }) }fn disconnect (intf: &usb::Interface <Core >, _data:Pin <&Self >) {
Signature · 1 line
2.51.0
Benno Lossin
reviewerQuoted 18 lines · Danilo Krummrich
The driver model defines the lifetime of the private data stored in (and owned by) a bus device to be valid from when the driver is bound to a device (i.e. from successful
probe()) until the driver is unbound from the device.This is already taken care of by the Rust implementation of the driver model. However, we still ask drivers to return a Result<Pin<KBox<Self>>> from
probe().Unlike in C, where we do not have the concept of initializers, but rather deal with uninitialized memory, drivers can just return an impl PinInit<Self, Error> instead.
This contributed to more clarity to the fact that a driver returns it's device private data in
probe()and the Rust driver model owns the data, manages the lifetime and - considering the lifetime - provides (safe) accessors for the driver.
Quoted 8 lines
Hence, let
probe()functions return an impl PinInit<Self, Error> instead of Result<Pin<KBox<Self>>>.Signed-off-by Danilo Krummrich <[email protected]>---
Depends on a minor pin-init patch [1] (Benno will send it to the list soon). A branch with this patch and the pin-init dependency is available in [2].
I sent the patch to the list:
https://lore.kernel.org/all/[email protected]
---
Cheers,
Benno
Quoted 23 lines
[1] https://github.com/Rust-for-Linux/pin-init/pull/86/commits
[2] https://git.kernel.org/pub/scm/linux/kernel/git/dakr/linux.git/log/?h=probe_return--- drivers/cpufreq/rcpufreq_dt.rs | 4 +- drivers/gpu/drm/nova/driver.rs | 4 +- drivers/gpu/drm/tyr/driver.rs | 4 +- drivers/gpu/nova-core/driver.rs | 34 +++++++---------- rust/kernel/auxiliary.rs | 6 +-- rust/kernel/cpufreq.rs | 4 +- rust/kernel/device.rs | 9 ++++- rust/kernel/driver.rs | 4 +- rust/kernel/io/mem.rs | 8 ++-- rust/kernel/pci.rs | 8 ++-- rust/kernel/platform.rs | 12 +++--- rust/kernel/usb.rs | 4 +- samples/rust/rust_debugfs.rs | 21 ++++++----- samples/rust/rust_dma.rs | 37 +++++++++---------- samples/rust/rust_driver_auxiliary.rs | 25 +++++-------- samples/rust/rust_driver_pci.rs | 53 +++++++++++++-------------- samples/rust/rust_driver_platform.rs | 6 +-- samples/rust/rust_driver_usb.rs | 5 +-- 18 files changed, 117 insertions(+), 131 deletions(-)
Quoted 9 lines · Danilo Krummrich
The driver model defines the lifetime of the private data stored in (and owned by) a bus device to be valid from when the driver is bound to a device (i.e. from successful
probe()) until the driver is unbound from the device.This is already taken care of by the Rust implementation of the driver model. However, we still ask drivers to return a Result<Pin<KBox<Self>>> from
probe().
Quoted 5 lines
Unlike in C, where we do not have the concept of initializers, but rather deal with uninitialized memory, drivers can just return an impl PinInit<Self, Error> instead.
This contributed to more clarity to the fact that a driver returns it's
nit: s/it's/its
Quoted 8 lines
device private data in
probe()and the Rust driver model owns the data, manages the lifetime and - considering the lifetime - provides (safe) accessors for the driver.Hence, let
probe()functions return an impl PinInit<Self, Error> instead of Result<Pin<KBox<Self>>>.Signed-off-by Danilo Krummrich <[email protected]>
Short anecdote: I was curious about measuring the footprint impact of pin initializers, so I did a size vmlinux before and after this patch to compare the size of the text section. This patch removes exactly 60 bytes of binary code, which I guess corresponds to the duplicated KBox allocations that are now gone. It's great to confirm once again how Rust abstractions are indeed zero-overhead! :)
Also, fwiw,
Benno Lossin
reviewerQuoted 26 lines · Alexandre Courbot
Quoted 10 lines · Danilo Krummrich
The driver model defines the lifetime of the private data stored in (and owned by) a bus device to be valid from when the driver is bound to a
device (i.e. from successful
probe()) until the driver is unbound from the device.This is already taken care of by the Rust implementation of the driver model. However, we still ask drivers to return a Result<Pin<KBox<Self>>> from
probe().Quoted 5 lines
Unlike in C, where we do not have the concept of initializers, but rather deal with uninitialized memory, drivers can just return an impl PinInit<Self, Error> instead.
This contributed to more clarity to the fact that a driver returns it's
nit: s/it's/its
Quoted 7 lines
device private data in
probe()and the Rust driver model owns the data, manages the lifetime and - considering the lifetime - provides (safe) accessors for the driver.Hence, let
probe()functions return an impl PinInit<Self, Error> instead of Result<Pin<KBox<Self>>>.
Quoted 8 lines
Quoted 1 line
Signed-off-by Danilo Krummrich <[email protected]>Short anecdote: I was curious about measuring the footprint impact of pin initializers, so I did a
size vmlinuxbefore and after this patch to compare the size of thetextsection. This patch removes exactly 60 bytes of binary code, which I guess corresponds to the duplicatedKBoxallocations that are now gone. It's great to confirm once again how Rust abstractions are indeed zero-overhead! :)
Thanks for the test! If you find that at any point they aren't, let me know, then we can fix that :)
---
Cheers,
Benno
Quoted 2 lines · Danilo Krummrich
drivers/cpufreq/rcpufreq_dt.rs | 4 +- rust/kernel/cpufreq.rs | 4 +-
Signature · 1 line
viresh
Quoted 21 lines · Danilo Krummrich
The driver model defines the lifetime of the private data stored in (and owned by) a bus device to be valid from when the driver is bound to a device (i.e. from successful
probe()) until the driver is unbound from the device.This is already taken care of by the Rust implementation of the driver model. However, we still ask drivers to return a Result<Pin<KBox<Self>>> from
probe().Unlike in C, where we do not have the concept of initializers, but rather deal with uninitialized memory, drivers can just return an impl PinInit<Self, Error> instead.
This contributed to more clarity to the fact that a driver returns it's device private data in
probe()and the Rust driver model owns the data, manages the lifetime and - considering the lifetime - provides (safe) accessors for the driver.Hence, let
probe()functions return an impl PinInit<Self, Error> instead of Result<Pin<KBox<Self>>>.
Quoted 8 lines
Signed-off-by Danilo Krummrich <[email protected]>---
Depends on a minor pin-init patch [1] (Benno will send it to the list soon). A branch with this patch and the pin-init dependency is available in [2].[1] https://github.com/Rust-for-Linux/pin-init/pull/86/commits
[2] https://git.kernel.org/pub/scm/linux/kernel/git/dakr/linux.git/log/?h=probe_return
Overall LGTM.
rust/kernel/device.rs pub unsafe fn as_bound(&self) -> &Device<Bound> { · line 203
Quoted 5 lines
impl Device<CoreInternal> { /// Store a pointer to the bound driver's private data.rust/kernel/device.rs +2
-1-pub fn set_drvdata (&self, data:impl ForeignOwnable ) { +pub fn set_drvdata <T : 'static>(&self, data:impl PinInit <T ,Error >) ->Result { +let data =KBox ::pin_init (data,GFP_KERNEL )?;
Perhaps the gfp flags should be an argument set_drvdata?
Alice
Danilo Krummrich
maintainerQuoted 28 lines · Alice Ryhl
Quoted 27 lines · Danilo Krummrich
The driver model defines the lifetime of the private data stored in (and owned by) a bus device to be valid from when the driver is bound to a device (i.e. from successful
probe()) until the driver is unbound from the device.This is already taken care of by the Rust implementation of the driver model. However, we still ask drivers to return a Result<Pin<KBox<Self>>> from
probe().Unlike in C, where we do not have the concept of initializers, but rather deal with uninitialized memory, drivers can just return an impl PinInit<Self, Error> instead.
This contributed to more clarity to the fact that a driver returns it's device private data in
probe()and the Rust driver model owns the data, manages the lifetime and - considering the lifetime - provides (safe) accessors for the driver.Hence, let
probe()functions return an impl PinInit<Self, Error> instead of Result<Pin<KBox<Self>>>.Signed-off-by Danilo Krummrich <[email protected]>---
Depends on a minor pin-init patch [1] (Benno will send it to the list soon). A branch with this patch and the pin-init dependency is available in [2].
Quoted 5 lines
Quoted 2 lines
[1] https://github.com/Rust-for-Linux/pin-init/pull/86/commits
[2] https://git.kernel.org/pub/scm/linux/kernel/git/dakr/linux.git/log/?h=probe_returnOverall LGTM.
Reviewed-by Alice Ryhl <[email protected]>
Thanks!
Quoted 7 lines
rust/kernel/device.rs pub unsafe fn as_bound(&self) -> &Device<Bound> { · line 203
Quoted 5 lines
impl Device<CoreInternal> { /// Store a pointer to the bound driver's private data.rust/kernel/device.rs +2
-1-pub fn set_drvdata (&self, data:impl ForeignOwnable ) { +pub fn set_drvdata <T : 'static>(&self, data:impl PinInit <T ,Error >) ->Result { +let data =KBox ::pin_init (data,GFP_KERNEL )?;Perhaps the gfp flags should be an argument
set_drvdata?
There shouldn't be a need, so I'd rather do that should we find a valid case.
Quoted 21 lines · Danilo Krummrich
The driver model defines the lifetime of the private data stored in (and owned by) a bus device to be valid from when the driver is bound to a device (i.e. from successful
probe()) until the driver is unbound from the device.This is already taken care of by the Rust implementation of the driver model. However, we still ask drivers to return a Result<Pin<KBox<Self>>> from
probe().Unlike in C, where we do not have the concept of initializers, but rather deal with uninitialized memory, drivers can just return an impl PinInit<Self, Error> instead.
This contributed to more clarity to the fact that a driver returns it's device private data in
probe()and the Rust driver model owns the data, manages the lifetime and - considering the lifetime - provides (safe) accessors for the driver.Hence, let
probe()functions return an impl PinInit<Self, Error> instead of Result<Pin<KBox<Self>>>.
Quoted 8 lines
Signed-off-by Danilo Krummrich <[email protected]>---
Depends on a minor pin-init patch [1] (Benno will send it to the list soon). A branch with this patch and the pin-init dependency is available in [2].[1] https://github.com/Rust-for-Linux/pin-init/pull/86/commits
[2] https://git.kernel.org/pub/scm/linux/kernel/git/dakr/linux.git/log/?h=probe_return
Danilo Krummrich
maintainerQuoted 18 lines · Danilo Krummrich
The driver model defines the lifetime of the private data stored in (and owned by) a bus device to be valid from when the driver is bound to a device (i.e. from successful
probe()) until the driver is unbound from the device.This is already taken care of by the Rust implementation of the driver model. However, we still ask drivers to return a Result<Pin<KBox<Self>>> from
probe().Unlike in C, where we do not have the concept of initializers, but rather deal with uninitialized memory, drivers can just return an impl PinInit<Self, Error> instead.
This contributed to more clarity to the fact that a driver returns it's device private data in
probe()and the Rust driver model owns the data, manages the lifetime and - considering the lifetime - provides (safe) accessors for the driver.
Quoted 4 lines
Hence, let
probe()functions return an impl PinInit<Self, Error> instead of Result<Pin<KBox<Self>>>.Signed-off-by Danilo Krummrich <[email protected]>
Applied to driver-core-testing, thanks!