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: add abstraction for struct device

Add an (always) reference-counted abstraction for a generic C `struct
device`. This abstraction encapsulates existing `struct device` instances
and manages its reference count.

Subsystems may use this abstraction as a base to abstract subsystem
specific device instances based on a generic `struct device`, such as
`struct pci_dev`.

Co-developed-by: Wedson Almeida Filho <wedsonaf@gmail.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@gmail.com>
Signed-off-by: Danilo Krummrich <dakr@redhat.com>
Link: https://lore.kernel.org/r/20240618154841.6716-2-dakr@redhat.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Danilo Krummrich and committed by
Greg Kroah-Hartman
a674fefd fca3eff7

+104
+1
rust/helpers.c
··· 23 23 #include <kunit/test-bug.h> 24 24 #include <linux/bug.h> 25 25 #include <linux/build_bug.h> 26 + #include <linux/device.h> 26 27 #include <linux/err.h> 27 28 #include <linux/errname.h> 28 29 #include <linux/mutex.h>
+102
rust/kernel/device.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Generic devices that are part of the kernel's driver model. 4 + //! 5 + //! C header: [`include/linux/device.h`](srctree/include/linux/device.h) 6 + 7 + use crate::{ 8 + bindings, 9 + types::{ARef, Opaque}, 10 + }; 11 + use core::ptr; 12 + 13 + /// A reference-counted device. 14 + /// 15 + /// This structure represents the Rust abstraction for a C `struct device`. This implementation 16 + /// abstracts the usage of an already existing C `struct device` within Rust code that we get 17 + /// passed from the C side. 18 + /// 19 + /// An instance of this abstraction can be obtained temporarily or permanent. 20 + /// 21 + /// A temporary one is bound to the lifetime of the C `struct device` pointer used for creation. 22 + /// A permanent instance is always reference-counted and hence not restricted by any lifetime 23 + /// boundaries. 24 + /// 25 + /// For subsystems it is recommended to create a permanent instance to wrap into a subsystem 26 + /// specific device structure (e.g. `pci::Device`). This is useful for passing it to drivers in 27 + /// `T::probe()`, such that a driver can store the `ARef<Device>` (equivalent to storing a 28 + /// `struct device` pointer in a C driver) for arbitrary purposes, e.g. allocating DMA coherent 29 + /// memory. 30 + /// 31 + /// # Invariants 32 + /// 33 + /// The pointer stored in `Self` is non-null and valid for the lifetime of the `ARef` instance. In 34 + /// particular, the `ARef` instance owns an increment on the underlying object’s reference count. 35 + /// 36 + /// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be 37 + /// dropped from any thread. 38 + #[repr(transparent)] 39 + pub struct Device(Opaque<bindings::device>); 40 + 41 + impl Device { 42 + /// Creates a new reference-counted abstraction instance of an existing `struct device` pointer. 43 + /// 44 + /// # Safety 45 + /// 46 + /// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count, 47 + /// i.e. it must be ensured that the reference count of the C `struct device` `ptr` points to 48 + /// can't drop to zero, for the duration of this function call. 49 + /// 50 + /// It must also be ensured that `bindings::device::release` can be called from any thread. 51 + /// While not officially documented, this should be the case for any `struct device`. 52 + pub unsafe fn from_raw(ptr: *mut bindings::device) -> ARef<Self> { 53 + // SAFETY: By the safety requirements, ptr is valid. 54 + // Initially increase the reference count by one to compensate for the final decrement once 55 + // this newly created `ARef<Device>` instance is dropped. 56 + unsafe { bindings::get_device(ptr) }; 57 + 58 + // CAST: `Self` is a `repr(transparent)` wrapper around `bindings::device`. 59 + let ptr = ptr.cast::<Self>(); 60 + 61 + // SAFETY: By the safety requirements, ptr is valid. 62 + unsafe { ARef::from_raw(ptr::NonNull::new_unchecked(ptr)) } 63 + } 64 + 65 + /// Obtain the raw `struct device *`. 66 + pub(crate) fn as_raw(&self) -> *mut bindings::device { 67 + self.0.get() 68 + } 69 + 70 + /// Convert a raw C `struct device` pointer to a `&'a Device`. 71 + /// 72 + /// # Safety 73 + /// 74 + /// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count, 75 + /// i.e. it must be ensured that the reference count of the C `struct device` `ptr` points to 76 + /// can't drop to zero, for the duration of this function call and the entire duration when the 77 + /// returned reference exists. 78 + pub unsafe fn as_ref<'a>(ptr: *mut bindings::device) -> &'a Self { 79 + // SAFETY: Guaranteed by the safety requirements of the function. 80 + unsafe { &*ptr.cast() } 81 + } 82 + } 83 + 84 + // SAFETY: Instances of `Device` are always reference-counted. 85 + unsafe impl crate::types::AlwaysRefCounted for Device { 86 + fn inc_ref(&self) { 87 + // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. 88 + unsafe { bindings::get_device(self.as_raw()) }; 89 + } 90 + 91 + unsafe fn dec_ref(obj: ptr::NonNull<Self>) { 92 + // SAFETY: The safety requirements guarantee that the refcount is non-zero. 93 + unsafe { bindings::put_device(obj.cast().as_ptr()) } 94 + } 95 + } 96 + 97 + // SAFETY: As by the type invariant `Device` can be sent to any thread. 98 + unsafe impl Send for Device {} 99 + 100 + // SAFETY: `Device` can be shared among threads because all immutable methods are protected by the 101 + // synchronization in `struct device`. 102 + unsafe impl Sync for Device {}
+1
rust/kernel/lib.rs
··· 28 28 29 29 pub mod alloc; 30 30 mod build_assert; 31 + pub mod device; 31 32 pub mod error; 32 33 pub mod init; 33 34 pub mod ioctl;