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

Toolchain and infrastructure: - Enable a set of Clippy lints: 'ptr_as_ptr', 'ptr_cast_constness', 'as_ptr_cast_mut', 'as_underscore', 'cast_lossless' and 'ref_as_ptr'. These are intended to avoid type casts with the 'as' operator, which are quite powerful, into restricted variants that are less powerful and thus should help to avoid mistakes. - Remove the 'author' key now that most instances were moved to the plural one in the previous cycle. 'kernel' crate: - New 'bug' module: add 'warn_on!' macro which reuses the existing 'BUG'/'WARN' infrastructure, i.e. it respects the usual sysctls and kernel parameters: warn_on!(value == 42); To avoid duplicating the assembly code, the same strategy is followed as for the static branch code in order to share the assembly between both C and Rust. This required a few rearrangements on C arch headers -- the existing C macros should still generate the same outputs, thus no functional change expected there. - 'workqueue' module: add delayed work items, including a 'DelayedWork' struct, a 'impl_has_delayed_work!' macro and an 'enqueue_delayed' method, e.g.: /// Enqueue the struct for execution on the system workqueue, /// where its value will be printed 42 jiffies later. fn print_later(value: Arc<MyStruct>) { let _ = workqueue::system().enqueue_delayed(value, 42); } - New 'bits' module: add support for 'bit' and 'genmask' functions, with runtime- and compile-time variants, e.g.: static_assert!(0b00010000 == bit_u8(4)); static_assert!(0b00011110 == genmask_u8(1..=4)); assert!(checked_bit_u32(u32::BITS).is_none()); - 'uaccess' module: add 'UserSliceReader::strcpy_into_buf', which reads NUL-terminated strings from userspace into a '&CStr'. Introduce 'UserPtr' newtype, similar in purpose to '__user' in C, to minimize mistakes handling userspace pointers, including mixing them up with integers and leaking them via the 'Debug' trait. Add it to the prelude, too. - Start preparations for the replacement of our custom 'CStr' type with the analogous type in the 'core' standard library. This will take place across several cycles to make it easier. For this one, it includes a new 'fmt' module, using upstream method names and some other cleanups. Replace 'fmt!' with a re-export, which helps Clippy lint properly, and clean up the found 'uninlined-format-args' instances. - 'dma' module: - Clarify wording and be consistent in 'coherent' nomenclature. - Convert the 'read!()' and 'write!()' macros to return a 'Result'. - Add 'as_slice()', 'write()' methods in 'CoherentAllocation'. - Expose 'count()' and 'size()' in 'CoherentAllocation' and add the corresponding type invariants. - Implement 'CoherentAllocation::dma_handle_with_offset()'. - 'time' module: - Make 'Instant' generic over clock source. This allows the compiler to assert that arithmetic expressions involving the 'Instant' use 'Instants' based on the same clock source. - Make 'HrTimer' generic over the timer mode. 'HrTimer' timers take a 'Duration' or an 'Instant' when setting the expiry time, depending on the timer mode. With this change, the compiler can check the type matches the timer mode. - Add an abstraction for 'fsleep'. 'fsleep' is a flexible sleep function that will select an appropriate sleep method depending on the requested sleep time. - Avoid 64-bit divisions on 32-bit hardware when calculating timestamps. - Seal the 'HrTimerMode' trait. This prevents users of the 'HrTimerMode' from implementing the trait on their own types. - Pass the correct timer mode ID to 'hrtimer_start_range_ns()'. - 'list' module: remove 'OFFSET' constants, allowing to remove pointer arithmetic; now 'impl_list_item!' invokes 'impl_has_list_links!' or 'impl_has_list_links_self_ptr!'. Other simplifications too. - 'types' module: remove 'ForeignOwnable::PointedTo' in favor of a constant, which avoids exposing the type of the opaque pointer, and require 'into_foreign' to return non-null. Remove the 'Either<L, R>' type as well. It is unused, and we want to encourage the use of custom enums for concrete use cases. - 'sync' module: implement 'Borrow' and 'BorrowMut' for 'Arc' types to allow them to be used in generic APIs. - 'alloc' module: implement 'Borrow' and 'BorrowMut' for 'Box<T, A>'; and 'Borrow', 'BorrowMut' and 'Default' for 'Vec<T, A>'. - 'Opaque' type: add 'cast_from' method to perform a restricted cast that cannot change the inner type and use it in callers of 'container_of!'. Rename 'raw_get' to 'cast_into' to match it. - 'rbtree' module: add 'is_empty' method. - 'sync' module: new 'aref' submodule to hold 'AlwaysRefCounted' and 'ARef', which are moved from the too general 'types' module which we want to reduce or eventually remove. Also fix a safety comment in 'static_lock_class'. 'pin-init' crate: - Add 'impl<T, E> [Pin]Init<T, E> for Result<T, E>', so results are now (pin-)initializers. - Add 'Zeroable::init_zeroed()' that delegates to 'init_zeroed()'. - New 'zeroed()', a safe version of 'mem::zeroed()' and also provide it via 'Zeroable::zeroed()'. - Implement 'Zeroable' for 'Option<&T>', 'Option<&mut T>' and for 'Option<[unsafe] [extern "abi"] fn(...args...) -> ret>' for '"Rust"' and '"C"' ABIs and up to 20 arguments. - Changed blanket impls of 'Init' and 'PinInit' from 'impl<T, E> [Pin]Init<T, E> for T' to 'impl<T> [Pin]Init<T> for T'. - Renamed 'zeroed()' to 'init_zeroed()'. - Upstream dev news: improve CI more to deny warnings, use '--all-targets'. Check the synchronization status of the two '-next' branches in upstream and the kernel. MAINTAINERS: - Add Vlastimil Babka, Liam R. Howlett, Uladzislau Rezki and Lorenzo Stoakes as reviewers (thanks everyone). And a few other cleanups and improvements. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEPjU5OPd5QIZ9jqqOGXyLc2htIW0FAmiOWREACgkQGXyLc2ht IW39Ig/9E0ExSiBgNKdkCOaULMq31wAxnu3iWoVVisFndlh/Inv+JlaLrmA57BCi xXgBwVZ1GoMsG8Fzt6gT+gyhGYi8waNd+5KXr/WJZVTaJ9v1KpdvxuCnSz0DjCbk GaKfAfxvJ5GAOEwiIIX8X0TFu6kx911DCJY387/VrqZQ7Msh1QSM3tcZeir/EV4w lPjUdlOh1FnLJLI9CGuW20d1IhQUP7K3pdoywgJPpCZV0I8QCyMlMqCEael8Tw2S r/PzRaQtiIzk5HTx06V8paK+nEn0K2vQXqW2kV56Y6TNm1Zcv6dES/8hCITsISs2 nwney3vXEwvoZX+YkQRffZddY4i6YenWMrtLgVxZzdshBL3bn6eHqBL04Nfix+p7 pQe3qMH3G8UBtX1lugBE7RrWGWcz9ARN8sK12ClmpAUnKJOwTpo97kpqXP7pDme8 Buh/oV3voAMsqwooSbVBzuUUWnbGaQ5Oj6CiiosSadfNh6AxJLYLKHtRLKJHZEw3 0Ob/1HhoWS6JSvYKVjMyD19qcH7O8ThZE+83CfMAkI4KphXJarWhpSmN4cHkFn/v 0clQ7Y5m+up9v1XWTaEq0Biqa6CaxLQwm/qW5WU0Y/TiovmvxAFdCwsQqDkRoJNx 9kNfMJRvNl78KQxrjEDz9gl7/ajgqX1KkqP8CQbGjv29cGzFlVE= =5Wt9 -----END PGP SIGNATURE----- Merge tag 'rust-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux Pull Rust updates from Miguel Ojeda: "Toolchain and infrastructure: - Enable a set of Clippy lints: 'ptr_as_ptr', 'ptr_cast_constness', 'as_ptr_cast_mut', 'as_underscore', 'cast_lossless' and 'ref_as_ptr' These are intended to avoid type casts with the 'as' operator, which are quite powerful, into restricted variants that are less powerful and thus should help to avoid mistakes - Remove the 'author' key now that most instances were moved to the plural one in the previous cycle 'kernel' crate: - New 'bug' module: add 'warn_on!' macro which reuses the existing 'BUG'/'WARN' infrastructure, i.e. it respects the usual sysctls and kernel parameters: warn_on!(value == 42); To avoid duplicating the assembly code, the same strategy is followed as for the static branch code in order to share the assembly between both C and Rust This required a few rearrangements on C arch headers -- the existing C macros should still generate the same outputs, thus no functional change expected there - 'workqueue' module: add delayed work items, including a 'DelayedWork' struct, a 'impl_has_delayed_work!' macro and an 'enqueue_delayed' method, e.g.: /// Enqueue the struct for execution on the system workqueue, /// where its value will be printed 42 jiffies later. fn print_later(value: Arc<MyStruct>) { let _ = workqueue::system().enqueue_delayed(value, 42); } - New 'bits' module: add support for 'bit' and 'genmask' functions, with runtime- and compile-time variants, e.g.: static_assert!(0b00010000 == bit_u8(4)); static_assert!(0b00011110 == genmask_u8(1..=4)); assert!(checked_bit_u32(u32::BITS).is_none()); - 'uaccess' module: add 'UserSliceReader::strcpy_into_buf', which reads NUL-terminated strings from userspace into a '&CStr' Introduce 'UserPtr' newtype, similar in purpose to '__user' in C, to minimize mistakes handling userspace pointers, including mixing them up with integers and leaking them via the 'Debug' trait. Add it to the prelude, too - Start preparations for the replacement of our custom 'CStr' type with the analogous type in the 'core' standard library. This will take place across several cycles to make it easier. For this one, it includes a new 'fmt' module, using upstream method names and some other cleanups Replace 'fmt!' with a re-export, which helps Clippy lint properly, and clean up the found 'uninlined-format-args' instances - 'dma' module: - Clarify wording and be consistent in 'coherent' nomenclature - Convert the 'read!()' and 'write!()' macros to return a 'Result' - Add 'as_slice()', 'write()' methods in 'CoherentAllocation' - Expose 'count()' and 'size()' in 'CoherentAllocation' and add the corresponding type invariants - Implement 'CoherentAllocation::dma_handle_with_offset()' - 'time' module: - Make 'Instant' generic over clock source. This allows the compiler to assert that arithmetic expressions involving the 'Instant' use 'Instants' based on the same clock source - Make 'HrTimer' generic over the timer mode. 'HrTimer' timers take a 'Duration' or an 'Instant' when setting the expiry time, depending on the timer mode. With this change, the compiler can check the type matches the timer mode - Add an abstraction for 'fsleep'. 'fsleep' is a flexible sleep function that will select an appropriate sleep method depending on the requested sleep time - Avoid 64-bit divisions on 32-bit hardware when calculating timestamps - Seal the 'HrTimerMode' trait. This prevents users of the 'HrTimerMode' from implementing the trait on their own types - Pass the correct timer mode ID to 'hrtimer_start_range_ns()' - 'list' module: remove 'OFFSET' constants, allowing to remove pointer arithmetic; now 'impl_list_item!' invokes 'impl_has_list_links!' or 'impl_has_list_links_self_ptr!'. Other simplifications too - 'types' module: remove 'ForeignOwnable::PointedTo' in favor of a constant, which avoids exposing the type of the opaque pointer, and require 'into_foreign' to return non-null Remove the 'Either<L, R>' type as well. It is unused, and we want to encourage the use of custom enums for concrete use cases - 'sync' module: implement 'Borrow' and 'BorrowMut' for 'Arc' types to allow them to be used in generic APIs - 'alloc' module: implement 'Borrow' and 'BorrowMut' for 'Box<T, A>'; and 'Borrow', 'BorrowMut' and 'Default' for 'Vec<T, A>' - 'Opaque' type: add 'cast_from' method to perform a restricted cast that cannot change the inner type and use it in callers of 'container_of!'. Rename 'raw_get' to 'cast_into' to match it - 'rbtree' module: add 'is_empty' method - 'sync' module: new 'aref' submodule to hold 'AlwaysRefCounted' and 'ARef', which are moved from the too general 'types' module which we want to reduce or eventually remove. Also fix a safety comment in 'static_lock_class' 'pin-init' crate: - Add 'impl<T, E> [Pin]Init<T, E> for Result<T, E>', so results are now (pin-)initializers - Add 'Zeroable::init_zeroed()' that delegates to 'init_zeroed()' - New 'zeroed()', a safe version of 'mem::zeroed()' and also provide it via 'Zeroable::zeroed()' - Implement 'Zeroable' for 'Option<&T>', 'Option<&mut T>' and for 'Option<[unsafe] [extern "abi"] fn(...args...) -> ret>' for '"Rust"' and '"C"' ABIs and up to 20 arguments - Changed blanket impls of 'Init' and 'PinInit' from 'impl<T, E> [Pin]Init<T, E> for T' to 'impl<T> [Pin]Init<T> for T' - Renamed 'zeroed()' to 'init_zeroed()' - Upstream dev news: improve CI more to deny warnings, use '--all-targets'. Check the synchronization status of the two '-next' branches in upstream and the kernel MAINTAINERS: - Add Vlastimil Babka, Liam R. Howlett, Uladzislau Rezki and Lorenzo Stoakes as reviewers (thanks everyone) And a few other cleanups and improvements" * tag 'rust-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux: (76 commits) rust: Add warn_on macro arm64/bug: Add ARCH_WARN_ASM macro for BUG/WARN asm code sharing with Rust riscv/bug: Add ARCH_WARN_ASM macro for BUG/WARN asm code sharing with Rust x86/bug: Add ARCH_WARN_ASM macro for BUG/WARN asm code sharing with Rust rust: kernel: move ARef and AlwaysRefCounted to sync::aref rust: sync: fix safety comment for `static_lock_class` rust: types: remove `Either<L, R>` rust: kernel: use `core::ffi::CStr` method names rust: str: add `CStr` methods matching `core::ffi::CStr` rust: str: remove unnecessary qualification rust: use `kernel::{fmt,prelude::fmt!}` rust: kernel: add `fmt` module rust: kernel: remove `fmt!`, fix clippy::uninlined-format-args scripts: rust: emit path candidates in panic message scripts: rust: replace length checks with match rust: list: remove nonexistent generic parameter in link rust: bits: add support for bits/genmask macros rust: list: remove OFFSET constants rust: list: add `impl_list_item!` examples rust: list: use fully qualified path ...
649 lines
23 KiB
Rust
649 lines
23 KiB
Rust
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
//! Generic devices that are part of the kernel's driver model.
|
|
//!
|
|
//! C header: [`include/linux/device.h`](srctree/include/linux/device.h)
|
|
|
|
use crate::{
|
|
bindings,
|
|
types::{ARef, ForeignOwnable, Opaque},
|
|
};
|
|
use core::{fmt, marker::PhantomData, ptr};
|
|
|
|
#[cfg(CONFIG_PRINTK)]
|
|
use crate::c_str;
|
|
|
|
pub mod property;
|
|
|
|
/// A reference-counted device.
|
|
///
|
|
/// This structure represents the Rust abstraction for a C `struct device`. This implementation
|
|
/// abstracts the usage of an already existing C `struct device` within Rust code that we get
|
|
/// passed from the C side.
|
|
///
|
|
/// An instance of this abstraction can be obtained temporarily or permanent.
|
|
///
|
|
/// A temporary one is bound to the lifetime of the C `struct device` pointer used for creation.
|
|
/// A permanent instance is always reference-counted and hence not restricted by any lifetime
|
|
/// boundaries.
|
|
///
|
|
/// For subsystems it is recommended to create a permanent instance to wrap into a subsystem
|
|
/// specific device structure (e.g. `pci::Device`). This is useful for passing it to drivers in
|
|
/// `T::probe()`, such that a driver can store the `ARef<Device>` (equivalent to storing a
|
|
/// `struct device` pointer in a C driver) for arbitrary purposes, e.g. allocating DMA coherent
|
|
/// memory.
|
|
///
|
|
/// # Invariants
|
|
///
|
|
/// A `Device` instance represents a valid `struct device` created by the C portion of the kernel.
|
|
///
|
|
/// Instances of this type are always reference-counted, that is, a call to `get_device` ensures
|
|
/// that the allocation remains valid at least until the matching call to `put_device`.
|
|
///
|
|
/// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be
|
|
/// dropped from any thread.
|
|
#[repr(transparent)]
|
|
pub struct Device<Ctx: DeviceContext = Normal>(Opaque<bindings::device>, PhantomData<Ctx>);
|
|
|
|
impl Device {
|
|
/// Creates a new reference-counted abstraction instance of an existing `struct device` pointer.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count,
|
|
/// i.e. it must be ensured that the reference count of the C `struct device` `ptr` points to
|
|
/// can't drop to zero, for the duration of this function call.
|
|
///
|
|
/// It must also be ensured that `bindings::device::release` can be called from any thread.
|
|
/// While not officially documented, this should be the case for any `struct device`.
|
|
pub unsafe fn get_device(ptr: *mut bindings::device) -> ARef<Self> {
|
|
// SAFETY: By the safety requirements ptr is valid
|
|
unsafe { Self::from_raw(ptr) }.into()
|
|
}
|
|
|
|
/// Convert a [`&Device`](Device) into a [`&Device<Bound>`](Device<Bound>).
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// The caller is responsible to ensure that the returned [`&Device<Bound>`](Device<Bound>)
|
|
/// only lives as long as it can be guaranteed that the [`Device`] is actually bound.
|
|
pub unsafe fn as_bound(&self) -> &Device<Bound> {
|
|
let ptr = core::ptr::from_ref(self);
|
|
|
|
// CAST: By the safety requirements the caller is responsible to guarantee that the
|
|
// returned reference only lives as long as the device is actually bound.
|
|
let ptr = ptr.cast();
|
|
|
|
// SAFETY:
|
|
// - `ptr` comes from `from_ref(self)` above, hence it's guaranteed to be valid.
|
|
// - Any valid `Device` pointer is also a valid pointer for `Device<Bound>`.
|
|
unsafe { &*ptr }
|
|
}
|
|
}
|
|
|
|
impl Device<CoreInternal> {
|
|
/// Store a pointer to the bound driver's private data.
|
|
pub fn set_drvdata(&self, data: impl ForeignOwnable) {
|
|
// 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()) }
|
|
}
|
|
|
|
/// Take ownership of the private data stored in this [`Device`].
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// - Must only be called once after a preceding call to [`Device::set_drvdata`].
|
|
/// - The type `T` must match the type of the `ForeignOwnable` previously stored by
|
|
/// [`Device::set_drvdata`].
|
|
pub unsafe fn drvdata_obtain<T: ForeignOwnable>(&self) -> T {
|
|
// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
|
|
let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };
|
|
|
|
// SAFETY:
|
|
// - By the safety requirements of this function, `ptr` comes from a previous call to
|
|
// `into_foreign()`.
|
|
// - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()`
|
|
// in `into_foreign()`.
|
|
unsafe { T::from_foreign(ptr.cast()) }
|
|
}
|
|
|
|
/// Borrow the driver's private data bound to this [`Device`].
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// - Must only be called after a preceding call to [`Device::set_drvdata`] and before
|
|
/// [`Device::drvdata_obtain`].
|
|
/// - The type `T` must match the type of the `ForeignOwnable` previously stored by
|
|
/// [`Device::set_drvdata`].
|
|
pub unsafe fn drvdata_borrow<T: ForeignOwnable>(&self) -> T::Borrowed<'_> {
|
|
// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
|
|
let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };
|
|
|
|
// SAFETY:
|
|
// - By the safety requirements of this function, `ptr` comes from a previous call to
|
|
// `into_foreign()`.
|
|
// - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()`
|
|
// in `into_foreign()`.
|
|
unsafe { T::borrow(ptr.cast()) }
|
|
}
|
|
}
|
|
|
|
impl<Ctx: DeviceContext> Device<Ctx> {
|
|
/// Obtain the raw `struct device *`.
|
|
pub(crate) fn as_raw(&self) -> *mut bindings::device {
|
|
self.0.get()
|
|
}
|
|
|
|
/// Returns a reference to the parent device, if any.
|
|
#[cfg_attr(not(CONFIG_AUXILIARY_BUS), expect(dead_code))]
|
|
pub(crate) fn parent(&self) -> Option<&Self> {
|
|
// SAFETY:
|
|
// - By the type invariant `self.as_raw()` is always valid.
|
|
// - The parent device is only ever set at device creation.
|
|
let parent = unsafe { (*self.as_raw()).parent };
|
|
|
|
if parent.is_null() {
|
|
None
|
|
} else {
|
|
// SAFETY:
|
|
// - Since `parent` is not NULL, it must be a valid pointer to a `struct device`.
|
|
// - `parent` is valid for the lifetime of `self`, since a `struct device` holds a
|
|
// reference count of its parent.
|
|
Some(unsafe { Self::from_raw(parent) })
|
|
}
|
|
}
|
|
|
|
/// Convert a raw C `struct device` pointer to a `&'a Device`.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count,
|
|
/// i.e. it must be ensured that the reference count of the C `struct device` `ptr` points to
|
|
/// can't drop to zero, for the duration of this function call and the entire duration when the
|
|
/// returned reference exists.
|
|
pub unsafe fn from_raw<'a>(ptr: *mut bindings::device) -> &'a Self {
|
|
// SAFETY: Guaranteed by the safety requirements of the function.
|
|
unsafe { &*ptr.cast() }
|
|
}
|
|
|
|
/// Prints an emergency-level message (level 0) prefixed with device information.
|
|
///
|
|
/// More details are available from [`dev_emerg`].
|
|
///
|
|
/// [`dev_emerg`]: crate::dev_emerg
|
|
pub fn pr_emerg(&self, args: fmt::Arguments<'_>) {
|
|
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
|
|
unsafe { self.printk(bindings::KERN_EMERG, args) };
|
|
}
|
|
|
|
/// Prints an alert-level message (level 1) prefixed with device information.
|
|
///
|
|
/// More details are available from [`dev_alert`].
|
|
///
|
|
/// [`dev_alert`]: crate::dev_alert
|
|
pub fn pr_alert(&self, args: fmt::Arguments<'_>) {
|
|
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
|
|
unsafe { self.printk(bindings::KERN_ALERT, args) };
|
|
}
|
|
|
|
/// Prints a critical-level message (level 2) prefixed with device information.
|
|
///
|
|
/// More details are available from [`dev_crit`].
|
|
///
|
|
/// [`dev_crit`]: crate::dev_crit
|
|
pub fn pr_crit(&self, args: fmt::Arguments<'_>) {
|
|
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
|
|
unsafe { self.printk(bindings::KERN_CRIT, args) };
|
|
}
|
|
|
|
/// Prints an error-level message (level 3) prefixed with device information.
|
|
///
|
|
/// More details are available from [`dev_err`].
|
|
///
|
|
/// [`dev_err`]: crate::dev_err
|
|
pub fn pr_err(&self, args: fmt::Arguments<'_>) {
|
|
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
|
|
unsafe { self.printk(bindings::KERN_ERR, args) };
|
|
}
|
|
|
|
/// Prints a warning-level message (level 4) prefixed with device information.
|
|
///
|
|
/// More details are available from [`dev_warn`].
|
|
///
|
|
/// [`dev_warn`]: crate::dev_warn
|
|
pub fn pr_warn(&self, args: fmt::Arguments<'_>) {
|
|
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
|
|
unsafe { self.printk(bindings::KERN_WARNING, args) };
|
|
}
|
|
|
|
/// Prints a notice-level message (level 5) prefixed with device information.
|
|
///
|
|
/// More details are available from [`dev_notice`].
|
|
///
|
|
/// [`dev_notice`]: crate::dev_notice
|
|
pub fn pr_notice(&self, args: fmt::Arguments<'_>) {
|
|
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
|
|
unsafe { self.printk(bindings::KERN_NOTICE, args) };
|
|
}
|
|
|
|
/// Prints an info-level message (level 6) prefixed with device information.
|
|
///
|
|
/// More details are available from [`dev_info`].
|
|
///
|
|
/// [`dev_info`]: crate::dev_info
|
|
pub fn pr_info(&self, args: fmt::Arguments<'_>) {
|
|
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
|
|
unsafe { self.printk(bindings::KERN_INFO, args) };
|
|
}
|
|
|
|
/// Prints a debug-level message (level 7) prefixed with device information.
|
|
///
|
|
/// More details are available from [`dev_dbg`].
|
|
///
|
|
/// [`dev_dbg`]: crate::dev_dbg
|
|
pub fn pr_dbg(&self, args: fmt::Arguments<'_>) {
|
|
if cfg!(debug_assertions) {
|
|
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
|
|
unsafe { self.printk(bindings::KERN_DEBUG, args) };
|
|
}
|
|
}
|
|
|
|
/// Prints the provided message to the console.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// Callers must ensure that `klevel` is null-terminated; in particular, one of the
|
|
/// `KERN_*`constants, for example, `KERN_CRIT`, `KERN_ALERT`, etc.
|
|
#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
|
|
unsafe fn printk(&self, klevel: &[u8], msg: fmt::Arguments<'_>) {
|
|
// SAFETY: `klevel` is null-terminated and one of the kernel constants. `self.as_raw`
|
|
// is valid because `self` is valid. The "%pA" format string expects a pointer to
|
|
// `fmt::Arguments`, which is what we're passing as the last argument.
|
|
#[cfg(CONFIG_PRINTK)]
|
|
unsafe {
|
|
bindings::_dev_printk(
|
|
klevel.as_ptr().cast::<crate::ffi::c_char>(),
|
|
self.as_raw(),
|
|
c_str!("%pA").as_char_ptr(),
|
|
core::ptr::from_ref(&msg).cast::<crate::ffi::c_void>(),
|
|
)
|
|
};
|
|
}
|
|
|
|
/// Obtain the [`FwNode`](property::FwNode) corresponding to this [`Device`].
|
|
pub fn fwnode(&self) -> Option<&property::FwNode> {
|
|
// SAFETY: `self` is valid.
|
|
let fwnode_handle = unsafe { bindings::__dev_fwnode(self.as_raw()) };
|
|
if fwnode_handle.is_null() {
|
|
return None;
|
|
}
|
|
// SAFETY: `fwnode_handle` is valid. Its lifetime is tied to `&self`. We
|
|
// return a reference instead of an `ARef<FwNode>` because `dev_fwnode()`
|
|
// doesn't increment the refcount. It is safe to cast from a
|
|
// `struct fwnode_handle*` to a `*const FwNode` because `FwNode` is
|
|
// defined as a `#[repr(transparent)]` wrapper around `fwnode_handle`.
|
|
Some(unsafe { &*fwnode_handle.cast() })
|
|
}
|
|
}
|
|
|
|
// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
|
|
// argument.
|
|
kernel::impl_device_context_deref!(unsafe { Device });
|
|
kernel::impl_device_context_into_aref!(Device);
|
|
|
|
// SAFETY: Instances of `Device` are always reference-counted.
|
|
unsafe impl crate::types::AlwaysRefCounted for Device {
|
|
fn inc_ref(&self) {
|
|
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
|
|
unsafe { bindings::get_device(self.as_raw()) };
|
|
}
|
|
|
|
unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
|
|
// SAFETY: The safety requirements guarantee that the refcount is non-zero.
|
|
unsafe { bindings::put_device(obj.cast().as_ptr()) }
|
|
}
|
|
}
|
|
|
|
// SAFETY: As by the type invariant `Device` can be sent to any thread.
|
|
unsafe impl Send for Device {}
|
|
|
|
// SAFETY: `Device` can be shared among threads because all immutable methods are protected by the
|
|
// synchronization in `struct device`.
|
|
unsafe impl Sync for Device {}
|
|
|
|
/// Marker trait for the context of a bus specific device.
|
|
///
|
|
/// Some functions of a bus specific device should only be called from a certain context, i.e. bus
|
|
/// callbacks, such as `probe()`.
|
|
///
|
|
/// This is the marker trait for structures representing the context of a bus specific device.
|
|
pub trait DeviceContext: private::Sealed {}
|
|
|
|
/// The [`Normal`] context is the context of a bus specific device when it is not an argument of
|
|
/// any bus callback.
|
|
pub struct Normal;
|
|
|
|
/// The [`Core`] context is the context of a bus specific device when it is supplied as argument of
|
|
/// any of the bus callbacks, such as `probe()`.
|
|
pub struct Core;
|
|
|
|
/// Semantically the same as [`Core`] but reserved for internal usage of the corresponding bus
|
|
/// abstraction.
|
|
pub struct CoreInternal;
|
|
|
|
/// The [`Bound`] context is the context of a bus specific device reference when it is guaranteed to
|
|
/// be bound for the duration of its lifetime.
|
|
pub struct Bound;
|
|
|
|
mod private {
|
|
pub trait Sealed {}
|
|
|
|
impl Sealed for super::Bound {}
|
|
impl Sealed for super::Core {}
|
|
impl Sealed for super::CoreInternal {}
|
|
impl Sealed for super::Normal {}
|
|
}
|
|
|
|
impl DeviceContext for Bound {}
|
|
impl DeviceContext for Core {}
|
|
impl DeviceContext for CoreInternal {}
|
|
impl DeviceContext for Normal {}
|
|
|
|
/// # Safety
|
|
///
|
|
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
|
|
/// generic argument of `$device`.
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __impl_device_context_deref {
|
|
(unsafe { $device:ident, $src:ty => $dst:ty }) => {
|
|
impl ::core::ops::Deref for $device<$src> {
|
|
type Target = $device<$dst>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
let ptr: *const Self = self;
|
|
|
|
// CAST: `$device<$src>` and `$device<$dst>` transparently wrap the same type by the
|
|
// safety requirement of the macro.
|
|
let ptr = ptr.cast::<Self::Target>();
|
|
|
|
// SAFETY: `ptr` was derived from `&self`.
|
|
unsafe { &*ptr }
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Implement [`core::ops::Deref`] traits for allowed [`DeviceContext`] conversions of a (bus
|
|
/// specific) device.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
|
|
/// generic argument of `$device`.
|
|
#[macro_export]
|
|
macro_rules! impl_device_context_deref {
|
|
(unsafe { $device:ident }) => {
|
|
// SAFETY: This macro has the exact same safety requirement as
|
|
// `__impl_device_context_deref!`.
|
|
::kernel::__impl_device_context_deref!(unsafe {
|
|
$device,
|
|
$crate::device::CoreInternal => $crate::device::Core
|
|
});
|
|
|
|
// SAFETY: This macro has the exact same safety requirement as
|
|
// `__impl_device_context_deref!`.
|
|
::kernel::__impl_device_context_deref!(unsafe {
|
|
$device,
|
|
$crate::device::Core => $crate::device::Bound
|
|
});
|
|
|
|
// SAFETY: This macro has the exact same safety requirement as
|
|
// `__impl_device_context_deref!`.
|
|
::kernel::__impl_device_context_deref!(unsafe {
|
|
$device,
|
|
$crate::device::Bound => $crate::device::Normal
|
|
});
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __impl_device_context_into_aref {
|
|
($src:ty, $device:tt) => {
|
|
impl ::core::convert::From<&$device<$src>> for $crate::types::ARef<$device> {
|
|
fn from(dev: &$device<$src>) -> Self {
|
|
(&**dev).into()
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Implement [`core::convert::From`], such that all `&Device<Ctx>` can be converted to an
|
|
/// `ARef<Device>`.
|
|
#[macro_export]
|
|
macro_rules! impl_device_context_into_aref {
|
|
($device:tt) => {
|
|
::kernel::__impl_device_context_into_aref!($crate::device::CoreInternal, $device);
|
|
::kernel::__impl_device_context_into_aref!($crate::device::Core, $device);
|
|
::kernel::__impl_device_context_into_aref!($crate::device::Bound, $device);
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! dev_printk {
|
|
($method:ident, $dev:expr, $($f:tt)*) => {
|
|
{
|
|
($dev).$method(::core::format_args!($($f)*));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Prints an emergency-level message (level 0) prefixed with device information.
|
|
///
|
|
/// This level should be used if the system is unusable.
|
|
///
|
|
/// Equivalent to the kernel's `dev_emerg` macro.
|
|
///
|
|
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
|
|
/// [`core::fmt`] and [`std::format!`].
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
|
|
/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use kernel::device::Device;
|
|
///
|
|
/// fn example(dev: &Device) {
|
|
/// dev_emerg!(dev, "hello {}\n", "there");
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! dev_emerg {
|
|
($($f:tt)*) => { $crate::dev_printk!(pr_emerg, $($f)*); }
|
|
}
|
|
|
|
/// Prints an alert-level message (level 1) prefixed with device information.
|
|
///
|
|
/// This level should be used if action must be taken immediately.
|
|
///
|
|
/// Equivalent to the kernel's `dev_alert` macro.
|
|
///
|
|
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
|
|
/// [`core::fmt`] and [`std::format!`].
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
|
|
/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use kernel::device::Device;
|
|
///
|
|
/// fn example(dev: &Device) {
|
|
/// dev_alert!(dev, "hello {}\n", "there");
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! dev_alert {
|
|
($($f:tt)*) => { $crate::dev_printk!(pr_alert, $($f)*); }
|
|
}
|
|
|
|
/// Prints a critical-level message (level 2) prefixed with device information.
|
|
///
|
|
/// This level should be used in critical conditions.
|
|
///
|
|
/// Equivalent to the kernel's `dev_crit` macro.
|
|
///
|
|
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
|
|
/// [`core::fmt`] and [`std::format!`].
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
|
|
/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use kernel::device::Device;
|
|
///
|
|
/// fn example(dev: &Device) {
|
|
/// dev_crit!(dev, "hello {}\n", "there");
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! dev_crit {
|
|
($($f:tt)*) => { $crate::dev_printk!(pr_crit, $($f)*); }
|
|
}
|
|
|
|
/// Prints an error-level message (level 3) prefixed with device information.
|
|
///
|
|
/// This level should be used in error conditions.
|
|
///
|
|
/// Equivalent to the kernel's `dev_err` macro.
|
|
///
|
|
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
|
|
/// [`core::fmt`] and [`std::format!`].
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
|
|
/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use kernel::device::Device;
|
|
///
|
|
/// fn example(dev: &Device) {
|
|
/// dev_err!(dev, "hello {}\n", "there");
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! dev_err {
|
|
($($f:tt)*) => { $crate::dev_printk!(pr_err, $($f)*); }
|
|
}
|
|
|
|
/// Prints a warning-level message (level 4) prefixed with device information.
|
|
///
|
|
/// This level should be used in warning conditions.
|
|
///
|
|
/// Equivalent to the kernel's `dev_warn` macro.
|
|
///
|
|
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
|
|
/// [`core::fmt`] and [`std::format!`].
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
|
|
/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use kernel::device::Device;
|
|
///
|
|
/// fn example(dev: &Device) {
|
|
/// dev_warn!(dev, "hello {}\n", "there");
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! dev_warn {
|
|
($($f:tt)*) => { $crate::dev_printk!(pr_warn, $($f)*); }
|
|
}
|
|
|
|
/// Prints a notice-level message (level 5) prefixed with device information.
|
|
///
|
|
/// This level should be used in normal but significant conditions.
|
|
///
|
|
/// Equivalent to the kernel's `dev_notice` macro.
|
|
///
|
|
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
|
|
/// [`core::fmt`] and [`std::format!`].
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
|
|
/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use kernel::device::Device;
|
|
///
|
|
/// fn example(dev: &Device) {
|
|
/// dev_notice!(dev, "hello {}\n", "there");
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! dev_notice {
|
|
($($f:tt)*) => { $crate::dev_printk!(pr_notice, $($f)*); }
|
|
}
|
|
|
|
/// Prints an info-level message (level 6) prefixed with device information.
|
|
///
|
|
/// This level should be used for informational messages.
|
|
///
|
|
/// Equivalent to the kernel's `dev_info` macro.
|
|
///
|
|
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
|
|
/// [`core::fmt`] and [`std::format!`].
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
|
|
/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use kernel::device::Device;
|
|
///
|
|
/// fn example(dev: &Device) {
|
|
/// dev_info!(dev, "hello {}\n", "there");
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! dev_info {
|
|
($($f:tt)*) => { $crate::dev_printk!(pr_info, $($f)*); }
|
|
}
|
|
|
|
/// Prints a debug-level message (level 7) prefixed with device information.
|
|
///
|
|
/// This level should be used for debug messages.
|
|
///
|
|
/// Equivalent to the kernel's `dev_dbg` macro, except that it doesn't support dynamic debug yet.
|
|
///
|
|
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
|
|
/// [`core::fmt`] and [`std::format!`].
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
|
|
/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use kernel::device::Device;
|
|
///
|
|
/// fn example(dev: &Device) {
|
|
/// dev_dbg!(dev, "hello {}\n", "there");
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! dev_dbg {
|
|
($($f:tt)*) => { $crate::dev_printk!(pr_dbg, $($f)*); }
|
|
}
|