Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 contributes 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>>>.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

+116 -130
+2 -2
drivers/cpufreq/rcpufreq_dt.rs
··· 207 207 fn probe( 208 208 pdev: &platform::Device<Core>, 209 209 _id_info: Option<&Self::IdInfo>, 210 - ) -> Result<Pin<KBox<Self>>> { 210 + ) -> impl PinInit<Self, Error> { 211 211 cpufreq::Registration::<CPUFreqDTDriver>::new_foreign_owned(pdev.as_ref())?; 212 - Ok(KBox::new(Self {}, GFP_KERNEL)?.into()) 212 + Ok(Self {}) 213 213 } 214 214 } 215 215
+2 -2
drivers/gpu/drm/nova/driver.rs
··· 45 45 type IdInfo = (); 46 46 const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE; 47 47 48 - fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 48 + fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 49 49 let data = try_pin_init!(NovaData { adev: adev.into() }); 50 50 51 51 let drm = drm::Device::<Self>::new(adev.as_ref(), data)?; 52 52 drm::Registration::new_foreign_owned(&drm, adev.as_ref(), 0)?; 53 53 54 - Ok(KBox::new(Self { drm }, GFP_KERNEL)?.into()) 54 + Ok(Self { drm }) 55 55 } 56 56 } 57 57
+2 -2
drivers/gpu/drm/tyr/driver.rs
··· 103 103 fn probe( 104 104 pdev: &platform::Device<Core>, 105 105 _info: Option<&Self::IdInfo>, 106 - ) -> Result<Pin<KBox<Self>>> { 106 + ) -> impl PinInit<Self, Error> { 107 107 let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?; 108 108 let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?; 109 109 let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?; ··· 143 143 let tdev: ARef<TyrDevice> = drm::Device::new(pdev.as_ref(), data)?; 144 144 drm::driver::Registration::new_foreign_owned(&tdev, pdev.as_ref(), 0)?; 145 145 146 - let driver = KBox::pin_init(try_pin_init!(TyrDriver { device: tdev }), GFP_KERNEL)?; 146 + let driver = TyrDriver { device: tdev }; 147 147 148 148 // We need this to be dev_info!() because dev_dbg!() does not work at 149 149 // all in Rust for now, and we need to see whether probe succeeded.
+13 -21
drivers/gpu/nova-core/driver.rs
··· 51 51 type IdInfo = (); 52 52 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 53 53 54 - fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 55 - dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n"); 54 + fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 55 + pin_init::pin_init_scope(move || { 56 + dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n"); 56 57 57 - pdev.enable_device_mem()?; 58 - pdev.set_master(); 58 + pdev.enable_device_mem()?; 59 + pdev.set_master(); 59 60 60 - let devres_bar = Arc::pin_init( 61 - pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")), 62 - GFP_KERNEL, 63 - )?; 61 + let bar = Arc::pin_init( 62 + pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")), 63 + GFP_KERNEL, 64 + )?; 64 65 65 - // Used to provided a `&Bar0` to `Gpu::new` without tying it to the lifetime of 66 - // `devres_bar`. 67 - let bar_clone = Arc::clone(&devres_bar); 68 - let bar = bar_clone.access(pdev.as_ref())?; 69 - 70 - let this = KBox::pin_init( 71 - try_pin_init!(Self { 72 - gpu <- Gpu::new(pdev, devres_bar, bar), 66 + Ok(try_pin_init!(Self { 67 + gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref())?), 73 68 _reg: auxiliary::Registration::new( 74 69 pdev.as_ref(), 75 70 c_str!("nova-drm"), 76 71 0, // TODO[XARR]: Once it lands, use XArray; for now we don't use the ID. 77 72 crate::MODULE_NAME 78 73 )?, 79 - }), 80 - GFP_KERNEL, 81 - )?; 82 - 83 - Ok(this) 74 + })) 75 + }) 84 76 } 85 77 86 78 fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {
+3 -3
rust/kernel/auxiliary.rs
··· 68 68 let info = T::ID_TABLE.info(id.index()); 69 69 70 70 from_result(|| { 71 - let data = T::probe(adev, info)?; 71 + let data = T::probe(adev, info); 72 72 73 - adev.as_ref().set_drvdata(data); 73 + adev.as_ref().set_drvdata(data)?; 74 74 Ok(0) 75 75 }) 76 76 } ··· 184 184 /// Auxiliary driver probe. 185 185 /// 186 186 /// Called when an auxiliary device is matches a corresponding driver. 187 - fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; 187 + fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>; 188 188 } 189 189 190 190 /// The auxiliary device representation.
+2 -2
rust/kernel/cpufreq.rs
··· 894 894 /// fn probe( 895 895 /// pdev: &platform::Device<Core>, 896 896 /// _id_info: Option<&Self::IdInfo>, 897 - /// ) -> Result<Pin<KBox<Self>>> { 897 + /// ) -> impl PinInit<Self, Error> { 898 898 /// cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?; 899 - /// Ok(KBox::new(Self {}, GFP_KERNEL)?.into()) 899 + /// Ok(Self {}) 900 900 /// } 901 901 /// } 902 902 /// ```
+7 -2
rust/kernel/device.rs
··· 6 6 7 7 use crate::{ 8 8 bindings, fmt, 9 + prelude::*, 9 10 sync::aref::ARef, 10 11 types::{ForeignOwnable, Opaque}, 11 12 }; ··· 199 198 200 199 impl Device<CoreInternal> { 201 200 /// Store a pointer to the bound driver's private data. 202 - pub fn set_drvdata(&self, data: impl ForeignOwnable) { 201 + pub fn set_drvdata<T: 'static>(&self, data: impl PinInit<T, Error>) -> Result { 202 + let data = KBox::pin_init(data, GFP_KERNEL)?; 203 + 203 204 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 204 - unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) } 205 + unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) }; 206 + 207 + Ok(()) 205 208 } 206 209 207 210 /// Take ownership of the private data stored in this [`Device`].
+2 -2
rust/kernel/driver.rs
··· 24 24 //! const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None; 25 25 //! 26 26 //! /// Driver probe. 27 - //! fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; 27 + //! fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>; 28 28 //! 29 29 //! /// Driver unbind (optional). 30 30 //! fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) { ··· 35 35 //! 36 36 //! For specific examples see [`auxiliary::Driver`], [`pci::Driver`] and [`platform::Driver`]. 37 37 //! 38 - //! The `probe()` callback should return a `Result<Pin<KBox<Self>>>`, i.e. the driver's private 38 + //! The `probe()` callback should return a `impl PinInit<Self, Error>`, i.e. the driver's private 39 39 //! data. The bus abstraction should store the pointer in the corresponding bus device. The generic 40 40 //! [`Device`] infrastructure provides common helpers for this purpose on its 41 41 //! [`Device<CoreInternal>`] implementation.
+4 -4
rust/kernel/io/mem.rs
··· 53 53 /// fn probe( 54 54 /// pdev: &platform::Device<Core>, 55 55 /// info: Option<&Self::IdInfo>, 56 - /// ) -> Result<Pin<KBox<Self>>> { 56 + /// ) -> impl PinInit<Self, Error> { 57 57 /// let offset = 0; // Some offset. 58 58 /// 59 59 /// // If the size is known at compile time, use [`Self::iomap_sized`]. ··· 70 70 /// 71 71 /// io.write32_relaxed(data, offset); 72 72 /// 73 - /// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) 73 + /// # Ok(SampleDriver) 74 74 /// } 75 75 /// } 76 76 /// ``` ··· 111 111 /// fn probe( 112 112 /// pdev: &platform::Device<Core>, 113 113 /// info: Option<&Self::IdInfo>, 114 - /// ) -> Result<Pin<KBox<Self>>> { 114 + /// ) -> impl PinInit<Self, Error> { 115 115 /// let offset = 0; // Some offset. 116 116 /// 117 117 /// // Unlike [`Self::iomap_sized`], here the size of the memory region ··· 128 128 /// 129 129 /// io.try_write32_relaxed(data, offset)?; 130 130 /// 131 - /// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) 131 + /// # Ok(SampleDriver) 132 132 /// } 133 133 /// } 134 134 /// ```
+4 -4
rust/kernel/pci.rs
··· 77 77 let info = T::ID_TABLE.info(id.index()); 78 78 79 79 from_result(|| { 80 - let data = T::probe(pdev, info)?; 80 + let data = T::probe(pdev, info); 81 81 82 - pdev.as_ref().set_drvdata(data); 82 + pdev.as_ref().set_drvdata(data)?; 83 83 Ok(0) 84 84 }) 85 85 } ··· 248 248 /// fn probe( 249 249 /// _pdev: &pci::Device<Core>, 250 250 /// _id_info: &Self::IdInfo, 251 - /// ) -> Result<Pin<KBox<Self>>> { 251 + /// ) -> impl PinInit<Self, Error> { 252 252 /// Err(ENODEV) 253 253 /// } 254 254 /// } ··· 271 271 /// 272 272 /// Called when a new pci device is added or discovered. Implementers should 273 273 /// attempt to initialize the device here. 274 - fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; 274 + fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>; 275 275 276 276 /// PCI driver unbind. 277 277 ///
+7 -5
rust/kernel/platform.rs
··· 74 74 let info = <Self as driver::Adapter>::id_info(pdev.as_ref()); 75 75 76 76 from_result(|| { 77 - let data = T::probe(pdev, info)?; 77 + let data = T::probe(pdev, info); 78 78 79 - pdev.as_ref().set_drvdata(data); 79 + pdev.as_ref().set_drvdata(data)?; 80 80 Ok(0) 81 81 }) 82 82 } ··· 166 166 /// fn probe( 167 167 /// _pdev: &platform::Device<Core>, 168 168 /// _id_info: Option<&Self::IdInfo>, 169 - /// ) -> Result<Pin<KBox<Self>>> { 169 + /// ) -> impl PinInit<Self, Error> { 170 170 /// Err(ENODEV) 171 171 /// } 172 172 /// } ··· 190 190 /// 191 191 /// Called when a new platform device is added or discovered. 192 192 /// Implementers should attempt to initialize the device here. 193 - fn probe(dev: &Device<device::Core>, id_info: Option<&Self::IdInfo>) 194 - -> Result<Pin<KBox<Self>>>; 193 + fn probe( 194 + dev: &Device<device::Core>, 195 + id_info: Option<&Self::IdInfo>, 196 + ) -> impl PinInit<Self, Error>; 195 197 196 198 /// Platform driver unbind. 197 199 ///
+4 -4
rust/kernel/usb.rs
··· 67 67 let id = unsafe { &*id.cast::<DeviceId>() }; 68 68 69 69 let info = T::ID_TABLE.info(id.index()); 70 - let data = T::probe(intf, id, info)?; 70 + let data = T::probe(intf, id, info); 71 71 72 72 let dev: &device::Device<device::CoreInternal> = intf.as_ref(); 73 - dev.set_drvdata(data); 73 + dev.set_drvdata(data)?; 74 74 Ok(0) 75 75 }) 76 76 } ··· 270 270 /// _interface: &usb::Interface<Core>, 271 271 /// _id: &usb::DeviceId, 272 272 /// _info: &Self::IdInfo, 273 - /// ) -> Result<Pin<KBox<Self>>> { 273 + /// ) -> impl PinInit<Self, Error> { 274 274 /// Err(ENODEV) 275 275 /// } 276 276 /// ··· 292 292 interface: &Interface<device::Core>, 293 293 id: &DeviceId, 294 294 id_info: &Self::IdInfo, 295 - ) -> Result<Pin<KBox<Self>>>; 295 + ) -> impl PinInit<Self, Error>; 296 296 297 297 /// USB driver disconnect. 298 298 ///
+11 -10
samples/rust/rust_debugfs.rs
··· 106 106 fn probe( 107 107 pdev: &platform::Device<Core>, 108 108 _info: Option<&Self::IdInfo>, 109 - ) -> Result<Pin<KBox<Self>>> { 110 - let result = KBox::try_pin_init(RustDebugFs::new(pdev), GFP_KERNEL)?; 111 - // We can still mutate fields through the files which are atomic or mutexed: 112 - result.counter.store(91, Ordering::Relaxed); 113 - { 114 - let mut guard = result.inner.lock(); 115 - guard.x = guard.y; 116 - guard.y = 42; 117 - } 118 - Ok(result) 109 + ) -> impl PinInit<Self, Error> { 110 + RustDebugFs::new(pdev).pin_chain(|this| { 111 + this.counter.store(91, Ordering::Relaxed); 112 + { 113 + let mut guard = this.inner.lock(); 114 + guard.x = guard.y; 115 + guard.y = 42; 116 + } 117 + 118 + Ok(()) 119 + }) 119 120 } 120 121 } 121 122
+17 -20
samples/rust/rust_dma.rs
··· 55 55 type IdInfo = (); 56 56 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 57 57 58 - fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 59 - dev_info!(pdev.as_ref(), "Probe DMA test driver.\n"); 58 + fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 59 + pin_init::pin_init_scope(move || { 60 + dev_info!(pdev.as_ref(), "Probe DMA test driver.\n"); 60 61 61 - let mask = DmaMask::new::<64>(); 62 + let mask = DmaMask::new::<64>(); 62 63 63 - // SAFETY: There are no concurrent calls to DMA allocation and mapping primitives. 64 - unsafe { pdev.dma_set_mask_and_coherent(mask)? }; 64 + // SAFETY: There are no concurrent calls to DMA allocation and mapping primitives. 65 + unsafe { pdev.dma_set_mask_and_coherent(mask)? }; 65 66 66 - let ca: CoherentAllocation<MyStruct> = 67 - CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; 67 + let ca: CoherentAllocation<MyStruct> = 68 + CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; 68 69 69 - for (i, value) in TEST_VALUES.into_iter().enumerate() { 70 - kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1))?; 71 - } 70 + for (i, value) in TEST_VALUES.into_iter().enumerate() { 71 + kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1))?; 72 + } 72 73 73 - let size = 4 * page::PAGE_SIZE; 74 - let pages = VVec::with_capacity(size, GFP_KERNEL)?; 74 + let size = 4 * page::PAGE_SIZE; 75 + let pages = VVec::with_capacity(size, GFP_KERNEL)?; 75 76 76 - let sgt = SGTable::new(pdev.as_ref(), pages, DataDirection::ToDevice, GFP_KERNEL); 77 + let sgt = SGTable::new(pdev.as_ref(), pages, DataDirection::ToDevice, GFP_KERNEL); 77 78 78 - let drvdata = KBox::pin_init( 79 - try_pin_init!(Self { 79 + Ok(try_pin_init!(Self { 80 80 pdev: pdev.into(), 81 81 ca, 82 82 sgt <- sgt, 83 - }), 84 - GFP_KERNEL, 85 - )?; 86 - 87 - Ok(drvdata) 83 + })) 84 + }) 88 85 } 89 86 } 90 87
+9 -16
samples/rust/rust_driver_auxiliary.rs
··· 27 27 28 28 const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE; 29 29 30 - fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 30 + fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 31 31 dev_info!( 32 32 adev.as_ref(), 33 33 "Probing auxiliary driver for auxiliary device with id={}\n", ··· 36 36 37 37 ParentDriver::connect(adev)?; 38 38 39 - let this = KBox::new(Self, GFP_KERNEL)?; 40 - 41 - Ok(this.into()) 39 + Ok(Self) 42 40 } 43 41 } 44 42 ··· 56 58 57 59 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 58 60 59 - fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 60 - let this = KBox::new( 61 - Self { 62 - _reg: [ 63 - auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME)?, 64 - auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME)?, 65 - ], 66 - }, 67 - GFP_KERNEL, 68 - )?; 69 - 70 - Ok(this.into()) 61 + fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 62 + Ok(Self { 63 + _reg: [ 64 + auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME)?, 65 + auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME)?, 66 + ], 67 + }) 71 68 } 72 69 } 73 70
+23 -24
samples/rust/rust_driver_pci.rs
··· 65 65 66 66 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 67 67 68 - fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 69 - let vendor = pdev.vendor_id(); 70 - dev_dbg!( 71 - pdev.as_ref(), 72 - "Probe Rust PCI driver sample (PCI ID: {}, 0x{:x}).\n", 73 - vendor, 74 - pdev.device_id() 75 - ); 68 + fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> { 69 + pin_init::pin_init_scope(move || { 70 + let vendor = pdev.vendor_id(); 71 + dev_dbg!( 72 + pdev.as_ref(), 73 + "Probe Rust PCI driver sample (PCI ID: {}, 0x{:x}).\n", 74 + vendor, 75 + pdev.device_id() 76 + ); 76 77 77 - pdev.enable_device_mem()?; 78 - pdev.set_master(); 78 + pdev.enable_device_mem()?; 79 + pdev.set_master(); 79 80 80 - let drvdata = KBox::pin_init( 81 - try_pin_init!(Self { 81 + Ok(try_pin_init!(Self { 82 82 bar <- pdev.iomap_region_sized::<{ Regs::END }>(0, c_str!("rust_driver_pci")), 83 - pdev: pdev.into(), 84 83 index: *info, 85 - }), 86 - GFP_KERNEL, 87 - )?; 84 + _: { 85 + let bar = bar.access(pdev.as_ref())?; 88 86 89 - let bar = drvdata.bar.access(pdev.as_ref())?; 90 - dev_info!( 91 - pdev.as_ref(), 92 - "pci-testdev data-match count: {}\n", 93 - Self::testdev(info, bar)? 94 - ); 95 - 96 - Ok(drvdata) 87 + dev_info!( 88 + pdev.as_ref(), 89 + "pci-testdev data-match count: {}\n", 90 + Self::testdev(info, bar)? 91 + ); 92 + }, 93 + pdev: pdev.into(), 94 + })) 95 + }) 97 96 } 98 97 99 98 fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {
+2 -4
samples/rust/rust_driver_platform.rs
··· 103 103 fn probe( 104 104 pdev: &platform::Device<Core>, 105 105 info: Option<&Self::IdInfo>, 106 - ) -> Result<Pin<KBox<Self>>> { 106 + ) -> impl PinInit<Self, Error> { 107 107 let dev = pdev.as_ref(); 108 108 109 109 dev_dbg!(dev, "Probe Rust Platform driver sample.\n"); ··· 116 116 Self::properties_parse(dev)?; 117 117 } 118 118 119 - let drvdata = KBox::new(Self { pdev: pdev.into() }, GFP_KERNEL)?; 120 - 121 - Ok(drvdata.into()) 119 + Ok(Self { pdev: pdev.into() }) 122 120 } 123 121 } 124 122
+2 -3
samples/rust/rust_driver_usb.rs
··· 24 24 intf: &usb::Interface<Core>, 25 25 _id: &usb::DeviceId, 26 26 _info: &Self::IdInfo, 27 - ) -> Result<Pin<KBox<Self>>> { 27 + ) -> impl PinInit<Self, Error> { 28 28 let dev: &device::Device<Core> = intf.as_ref(); 29 29 dev_info!(dev, "Rust USB driver sample probed\n"); 30 30 31 - let drvdata = KBox::new(Self { _intf: intf.into() }, GFP_KERNEL)?; 32 - Ok(drvdata.into()) 31 + Ok(Self { _intf: intf.into() }) 33 32 } 34 33 35 34 fn disconnect(intf: &usb::Interface<Core>, _data: Pin<&Self>) {