Here is the big set of driver core and debugfs updates for 6.14-rc1. It's coming late in the merge cycle as there are a number of merge conflicts with your tree now, and I wanted to make sure they were working properly. To resolve them, look in linux-next, and I will send the "fixup" patch as a response to the pull request. Included in here is a bunch of driver core, PCI, OF, and platform rust bindings (all acked by the different subsystem maintainers), hence the merge conflict with the rust tree, and some driver core api updates to mark things as const, which will also require some fixups due to new stuff coming in through other trees in this merge window. There are also a bunch of debugfs updates from Al, and there is at least one user that does have a regression with these, but Al is working on tracking down the fix for it. In my use (and everyone else's linux-next use), it does not seem like a big issue at the moment. Here's a short list of the things in here: - driver core bindings for PCI, platform, OF, and some i/o functions. We are almost at the "write a real driver in rust" stage now, depending on what you want to do. - misc device rust bindings and a sample driver to show how to use them - debugfs cleanups in the fs as well as the users of the fs api for places where drivers got it wrong or were unnecessarily doing things in complex ways. - driver core const work, making more of the api take const * for different parameters to make the rust bindings easier overall. - other small fixes and updates All of these have been in linux-next with all of the aforementioned merge conflicts, and the one debugfs issue, which looks to be resolved "soon". Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZ5koPA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ymFHACfT5acDKf2Bov2Lc/5u3vBW/R6ChsAnj+LmgVI hcDSPodj4szR40RRnzBd =u5Ey -----END PGP SIGNATURE----- Merge tag 'driver-core-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core Pull driver core and debugfs updates from Greg KH: "Here is the big set of driver core and debugfs updates for 6.14-rc1. Included in here is a bunch of driver core, PCI, OF, and platform rust bindings (all acked by the different subsystem maintainers), hence the merge conflict with the rust tree, and some driver core api updates to mark things as const, which will also require some fixups due to new stuff coming in through other trees in this merge window. There are also a bunch of debugfs updates from Al, and there is at least one user that does have a regression with these, but Al is working on tracking down the fix for it. In my use (and everyone else's linux-next use), it does not seem like a big issue at the moment. Here's a short list of the things in here: - driver core rust bindings for PCI, platform, OF, and some i/o functions. We are almost at the "write a real driver in rust" stage now, depending on what you want to do. - misc device rust bindings and a sample driver to show how to use them - debugfs cleanups in the fs as well as the users of the fs api for places where drivers got it wrong or were unnecessarily doing things in complex ways. - driver core const work, making more of the api take const * for different parameters to make the rust bindings easier overall. - other small fixes and updates All of these have been in linux-next with all of the aforementioned merge conflicts, and the one debugfs issue, which looks to be resolved "soon"" * tag 'driver-core-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (95 commits) rust: device: Use as_char_ptr() to avoid explicit cast rust: device: Replace CString with CStr in property_present() devcoredump: Constify 'struct bin_attribute' devcoredump: Define 'struct bin_attribute' through macro rust: device: Add property_present() saner replacement for debugfs_rename() orangefs-debugfs: don't mess with ->d_name octeontx2: don't mess with ->d_parent or ->d_parent->d_name arm_scmi: don't mess with ->d_parent->d_name slub: don't mess with ->d_name sof-client-ipc-flood-test: don't mess with ->d_name qat: don't mess with ->d_name xhci: don't mess with ->d_iname mtu3: don't mess wiht ->d_iname greybus/camera - stop messing with ->d_iname mediatek: stop messing with ->d_iname netdevsim: don't embed file_operations into your structs b43legacy: make use of debugfs_get_aux() b43: stop embedding struct file_operations into their objects carl9170: stop embedding file_operations into their objects ...
420 lines
14 KiB
Rust
420 lines
14 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,
|
|
str::CStr,
|
|
types::{ARef, Opaque},
|
|
};
|
|
use core::{fmt, ptr};
|
|
|
|
#[cfg(CONFIG_PRINTK)]
|
|
use crate::c_str;
|
|
|
|
/// 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(Opaque<bindings::device>);
|
|
|
|
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::as_ref(ptr) }.into()
|
|
}
|
|
|
|
/// Obtain the raw `struct device *`.
|
|
pub(crate) fn as_raw(&self) -> *mut bindings::device {
|
|
self.0.get()
|
|
}
|
|
|
|
/// 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 as_ref<'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 *const _ as *const crate::ffi::c_char,
|
|
self.as_raw(),
|
|
c_str!("%pA").as_char_ptr(),
|
|
&msg as *const _ as *const crate::ffi::c_void,
|
|
)
|
|
};
|
|
}
|
|
|
|
/// Checks if property is present or not.
|
|
pub fn property_present(&self, name: &CStr) -> bool {
|
|
// SAFETY: By the invariant of `CStr`, `name` is null-terminated.
|
|
unsafe { bindings::device_property_present(self.as_raw().cast_const(), name.as_char_ptr()) }
|
|
}
|
|
}
|
|
|
|
// 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 {}
|
|
|
|
#[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 `alloc::format!`.
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.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 `alloc::format!`.
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.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 `alloc::format!`.
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.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 `alloc::format!`.
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.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 `alloc::format!`.
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.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 `alloc::format!`.
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.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 `alloc::format!`.
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.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 `alloc::format!`.
|
|
///
|
|
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.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)*); }
|
|
}
|