mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

The prefix as_* should not be used for a constructor. Constructors usually use the prefix from_* instead. Some prior art in the stdlib: Box::from_raw, CString::from_raw, Rc::from_raw, Arc::from_raw, Waker::from_raw, File::from_raw_fd. There is also prior art in the kernel crate: cpufreq::Policy::from_raw, fs::File::from_raw_file, Kuid::from_raw, ARef::from_raw, SeqFile::from_raw, VmaNew::from_raw, Io::from_raw. Link: https://lore.kernel.org/r/aCd8D5IA0RXZvtcv@pollux Signed-off-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Benno Lossin <lossin@kernel.org> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Link: https://lore.kernel.org/r/20250711-device-as-ref-v2-1-1b16ab6402d7@google.com Signed-off-by: Danilo Krummrich <dakr@kernel.org>
77 lines
3 KiB
Rust
77 lines
3 KiB
Rust
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
//! Abstractions for the faux bus.
|
|
//!
|
|
//! This module provides bindings for working with faux devices in kernel modules.
|
|
//!
|
|
//! C header: [`include/linux/device/faux.h`]
|
|
|
|
use crate::{bindings, device, error::code::*, prelude::*};
|
|
use core::ptr::{addr_of_mut, null, null_mut, NonNull};
|
|
|
|
/// The registration of a faux device.
|
|
///
|
|
/// This type represents the registration of a [`struct faux_device`]. When an instance of this type
|
|
/// is dropped, its respective faux device will be unregistered from the system.
|
|
///
|
|
/// # Invariants
|
|
///
|
|
/// `self.0` always holds a valid pointer to an initialized and registered [`struct faux_device`].
|
|
///
|
|
/// [`struct faux_device`]: srctree/include/linux/device/faux.h
|
|
pub struct Registration(NonNull<bindings::faux_device>);
|
|
|
|
impl Registration {
|
|
/// Create and register a new faux device with the given name.
|
|
#[inline]
|
|
pub fn new(name: &CStr, parent: Option<&device::Device>) -> Result<Self> {
|
|
// SAFETY:
|
|
// - `name` is copied by this function into its own storage
|
|
// - `faux_ops` is safe to leave NULL according to the C API
|
|
// - `parent` can be either NULL or a pointer to a `struct device`, and `faux_device_create`
|
|
// will take a reference to `parent` using `device_add` - ensuring that it remains valid
|
|
// for the lifetime of the faux device.
|
|
let dev = unsafe {
|
|
bindings::faux_device_create(
|
|
name.as_char_ptr(),
|
|
parent.map_or(null_mut(), |p| p.as_raw()),
|
|
null(),
|
|
)
|
|
};
|
|
|
|
// The above function will return either a valid device, or NULL on failure
|
|
// INVARIANT: The device will remain registered until faux_device_destroy() is called, which
|
|
// happens in our Drop implementation.
|
|
Ok(Self(NonNull::new(dev).ok_or(ENODEV)?))
|
|
}
|
|
|
|
fn as_raw(&self) -> *mut bindings::faux_device {
|
|
self.0.as_ptr()
|
|
}
|
|
}
|
|
|
|
impl AsRef<device::Device> for Registration {
|
|
fn as_ref(&self) -> &device::Device {
|
|
// SAFETY: The underlying `device` in `faux_device` is guaranteed by the C API to be
|
|
// a valid initialized `device`.
|
|
unsafe { device::Device::from_raw(addr_of_mut!((*self.as_raw()).dev)) }
|
|
}
|
|
}
|
|
|
|
impl Drop for Registration {
|
|
#[inline]
|
|
fn drop(&mut self) {
|
|
// SAFETY: `self.0` is a valid registered faux_device via our type invariants.
|
|
unsafe { bindings::faux_device_destroy(self.as_raw()) }
|
|
}
|
|
}
|
|
|
|
// SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as
|
|
// faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not
|
|
// having Copy/Clone.
|
|
unsafe impl Send for Registration {}
|
|
|
|
// SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as
|
|
// faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not
|
|
// having Copy/Clone.
|
|
unsafe impl Sync for Registration {}
|