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

Configure Feed

Select the types of activity you want to include in your feed.

rust: pci: use generic device drvdata accessors

Take advantage of the generic drvdata accessors of the generic Device
type.

While at it, use from_result() instead of match.

Link: https://lore.kernel.org/r/20250621195118.124245-5-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

+14 -27
-10
rust/helpers/pci.c
··· 2 2 3 3 #include <linux/pci.h> 4 4 5 - void rust_helper_pci_set_drvdata(struct pci_dev *pdev, void *data) 6 - { 7 - pci_set_drvdata(pdev, data); 8 - } 9 - 10 - void *rust_helper_pci_get_drvdata(struct pci_dev *pdev) 11 - { 12 - return pci_get_drvdata(pdev); 13 - } 14 - 15 5 resource_size_t rust_helper_pci_resource_len(struct pci_dev *pdev, int bar) 16 6 { 17 7 return pci_resource_len(pdev, bar);
+14 -17
rust/kernel/pci.rs
··· 9 9 device_id::RawDeviceId, 10 10 devres::Devres, 11 11 driver, 12 - error::{to_result, Result}, 12 + error::{from_result, to_result, Result}, 13 13 io::Io, 14 14 io::IoRaw, 15 15 str::CStr, 16 - types::{ARef, ForeignOwnable, Opaque}, 16 + types::{ARef, Opaque}, 17 17 ThisModule, 18 18 }; 19 19 use core::{ ··· 65 65 // `struct pci_dev`. 66 66 // 67 67 // INVARIANT: `pdev` is valid for the duration of `probe_callback()`. 68 - let pdev = unsafe { &*pdev.cast::<Device<device::Core>>() }; 68 + let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() }; 69 69 70 70 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct pci_device_id` and 71 71 // does not add additional invariants, so it's safe to transmute. 72 72 let id = unsafe { &*id.cast::<DeviceId>() }; 73 73 let info = T::ID_TABLE.info(id.index()); 74 74 75 - match T::probe(pdev, info) { 76 - Ok(data) => { 77 - // Let the `struct pci_dev` own a reference of the driver's private data. 78 - // SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a 79 - // `struct pci_dev`. 80 - unsafe { bindings::pci_set_drvdata(pdev.as_raw(), data.into_foreign() as _) }; 81 - } 82 - Err(err) => return Error::to_errno(err), 83 - } 75 + from_result(|| { 76 + let data = T::probe(pdev, info)?; 84 77 85 - 0 78 + pdev.as_ref().set_drvdata(data); 79 + Ok(0) 80 + }) 86 81 } 87 82 88 83 extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) { 89 84 // SAFETY: The PCI bus only ever calls the remove callback with a valid pointer to a 90 85 // `struct pci_dev`. 91 - let ptr = unsafe { bindings::pci_get_drvdata(pdev) }.cast(); 86 + // 87 + // INVARIANT: `pdev` is valid for the duration of `remove_callback()`. 88 + let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() }; 92 89 93 90 // SAFETY: `remove_callback` is only ever called after a successful call to 94 - // `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized 95 - // `KBox<T>` pointer created through `KBox::into_foreign`. 96 - let _ = unsafe { KBox::<T>::from_foreign(ptr) }; 91 + // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 92 + // and stored a `Pin<KBox<T>>`. 93 + let _ = unsafe { pdev.as_ref().drvdata_obtain::<Pin<KBox<T>>>() }; 97 94 } 98 95 } 99 96