mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
Driver core fixes for 6.16-rc3
- Fix swapped handling of lru_gen and lru_gen_full debugfs files in vmscan. - Fix debugfs mount options (uid, gid, mode) being silently ignored. - Fix leak of devres action in the unwind path of Devres::new(). - Documentation - Expand and fix documentation of (outdated) Device, DeviceContext and generic driver infrastructure. - Fix C header link of faux device abstractions. - Clarify expected interaction with the security team. - Smooth text flow in the security bug reporting process documentation. -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQS2q/xV6QjXAdC7k+1FlHeO1qrKLgUCaKmYLgAKCRBFlHeO1qrK LuUiAQDMA7wZCdzvU8kZazpVpiN5t4Y/EeCztbZJlTG1b0F66QEAgKfgBbdKdgvu LNSXY0Mo6/t6RbFbW5+wR4R+sGn6PwQ= =wBy0 -----END PGP SIGNATURE----- Merge tag 'driver-core-6.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core Pull driver core fixes from Danilo Krummrich: - Fix swapped handling of lru_gen and lru_gen_full debugfs files in vmscan - Fix debugfs mount options (uid, gid, mode) being silently ignored - Fix leak of devres action in the unwind path of Devres::new() - Documentation: - Expand and fix documentation of (outdated) Device, DeviceContext and generic driver infrastructure - Fix C header link of faux device abstractions - Clarify expected interaction with the security team - Smooth text flow in the security bug reporting process documentation * tag 'driver-core-6.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: Documentation: smooth the text flow in the security bug reporting process Documentation: clarify the expected collaboration with security bugs reporters debugfs: fix mount options not being applied rust: devres: fix leaking call to devm_add_action() rust: faux: fix C header link driver: rust: expand documentation for driver infrastructure device: rust: expand documentation for Device device: rust: expand documentation for DeviceContext mm/vmscan: fix inverted polarity in lru_gen_seq_show()
This commit is contained in:
commit
52025b8fc9
@ -8,8 +8,22 @@ like to know when a security bug is found so that it can be fixed and
|
|||||||
disclosed as quickly as possible. Please report security bugs to the
|
disclosed as quickly as possible. Please report security bugs to the
|
||||||
Linux kernel security team.
|
Linux kernel security team.
|
||||||
|
|
||||||
Contact
|
The security team and maintainers almost always require additional
|
||||||
-------
|
information beyond what was initially provided in a report and rely on
|
||||||
|
active and efficient collaboration with the reporter to perform further
|
||||||
|
testing (e.g., verifying versions, configuration options, mitigations, or
|
||||||
|
patches). Before contacting the security team, the reporter must ensure
|
||||||
|
they are available to explain their findings, engage in discussions, and
|
||||||
|
run additional tests. Reports where the reporter does not respond promptly
|
||||||
|
or cannot effectively discuss their findings may be abandoned if the
|
||||||
|
communication does not quickly improve.
|
||||||
|
|
||||||
|
As it is with any bug, the more information provided the easier it
|
||||||
|
will be to diagnose and fix. Please review the procedure outlined in
|
||||||
|
'Documentation/admin-guide/reporting-issues.rst' if you are unclear about what
|
||||||
|
information is helpful. Any exploit code is very helpful and will not
|
||||||
|
be released without consent from the reporter unless it has already been
|
||||||
|
made public.
|
||||||
|
|
||||||
The Linux kernel security team can be contacted by email at
|
The Linux kernel security team can be contacted by email at
|
||||||
<security@kernel.org>. This is a private list of security officers
|
<security@kernel.org>. This is a private list of security officers
|
||||||
@ -19,13 +33,6 @@ that can speed up the process considerably. It is possible that the
|
|||||||
security team will bring in extra help from area maintainers to
|
security team will bring in extra help from area maintainers to
|
||||||
understand and fix the security vulnerability.
|
understand and fix the security vulnerability.
|
||||||
|
|
||||||
As it is with any bug, the more information provided the easier it
|
|
||||||
will be to diagnose and fix. Please review the procedure outlined in
|
|
||||||
'Documentation/admin-guide/reporting-issues.rst' if you are unclear about what
|
|
||||||
information is helpful. Any exploit code is very helpful and will not
|
|
||||||
be released without consent from the reporter unless it has already been
|
|
||||||
made public.
|
|
||||||
|
|
||||||
Please send plain text emails without attachments where possible.
|
Please send plain text emails without attachments where possible.
|
||||||
It is much harder to have a context-quoted discussion about a complex
|
It is much harder to have a context-quoted discussion about a complex
|
||||||
issue if all the details are hidden away in attachments. Think of it like a
|
issue if all the details are hidden away in attachments. Think of it like a
|
||||||
|
@ -183,6 +183,9 @@ static int debugfs_reconfigure(struct fs_context *fc)
|
|||||||
struct debugfs_fs_info *sb_opts = sb->s_fs_info;
|
struct debugfs_fs_info *sb_opts = sb->s_fs_info;
|
||||||
struct debugfs_fs_info *new_opts = fc->s_fs_info;
|
struct debugfs_fs_info *new_opts = fc->s_fs_info;
|
||||||
|
|
||||||
|
if (!new_opts)
|
||||||
|
return 0;
|
||||||
|
|
||||||
sync_filesystem(sb);
|
sync_filesystem(sb);
|
||||||
|
|
||||||
/* structure copy of new mount options to sb */
|
/* structure copy of new mount options to sb */
|
||||||
@ -282,10 +285,16 @@ static int debugfs_fill_super(struct super_block *sb, struct fs_context *fc)
|
|||||||
|
|
||||||
static int debugfs_get_tree(struct fs_context *fc)
|
static int debugfs_get_tree(struct fs_context *fc)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
if (!(debugfs_allow & DEBUGFS_ALLOW_API))
|
if (!(debugfs_allow & DEBUGFS_ALLOW_API))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
return get_tree_single(fc, debugfs_fill_super);
|
err = get_tree_single(fc, debugfs_fill_super);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return debugfs_reconfigure(fc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debugfs_free_fc(struct fs_context *fc)
|
static void debugfs_free_fc(struct fs_context *fc)
|
||||||
|
@ -5772,9 +5772,9 @@ static int __init init_lru_gen(void)
|
|||||||
if (sysfs_create_group(mm_kobj, &lru_gen_attr_group))
|
if (sysfs_create_group(mm_kobj, &lru_gen_attr_group))
|
||||||
pr_err("lru_gen: failed to create sysfs group\n");
|
pr_err("lru_gen: failed to create sysfs group\n");
|
||||||
|
|
||||||
debugfs_create_file_aux_num("lru_gen", 0644, NULL, NULL, 1,
|
debugfs_create_file_aux_num("lru_gen", 0644, NULL, NULL, false,
|
||||||
&lru_gen_rw_fops);
|
&lru_gen_rw_fops);
|
||||||
debugfs_create_file_aux_num("lru_gen_full", 0444, NULL, NULL, 0,
|
debugfs_create_file_aux_num("lru_gen_full", 0444, NULL, NULL, true,
|
||||||
&lru_gen_ro_fops);
|
&lru_gen_ro_fops);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -15,23 +15,130 @@ use crate::c_str;
|
|||||||
|
|
||||||
pub mod property;
|
pub mod property;
|
||||||
|
|
||||||
/// A reference-counted device.
|
/// The core representation of a device in the kernel's driver model.
|
||||||
///
|
///
|
||||||
/// This structure represents the Rust abstraction for a C `struct device`. This implementation
|
/// This structure represents the Rust abstraction for a C `struct device`. A [`Device`] can either
|
||||||
/// abstracts the usage of an already existing C `struct device` within Rust code that we get
|
/// exist as temporary reference (see also [`Device::from_raw`]), which is only valid within a
|
||||||
/// passed from the C side.
|
/// certain scope or as [`ARef<Device>`], owning a dedicated reference count.
|
||||||
///
|
///
|
||||||
/// An instance of this abstraction can be obtained temporarily or permanent.
|
/// # Device Types
|
||||||
///
|
///
|
||||||
/// A temporary one is bound to the lifetime of the C `struct device` pointer used for creation.
|
/// A [`Device`] can represent either a bus device or a class device.
|
||||||
/// 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
|
/// ## Bus Devices
|
||||||
/// 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
|
/// A bus device is a [`Device`] that is associated with a physical or virtual bus. Examples of
|
||||||
/// `struct device` pointer in a C driver) for arbitrary purposes, e.g. allocating DMA coherent
|
/// buses include PCI, USB, I2C, and SPI. Devices attached to a bus are registered with a specific
|
||||||
/// memory.
|
/// bus type, which facilitates matching devices with appropriate drivers based on IDs or other
|
||||||
|
/// identifying information. Bus devices are visible in sysfs under `/sys/bus/<bus-name>/devices/`.
|
||||||
|
///
|
||||||
|
/// ## Class Devices
|
||||||
|
///
|
||||||
|
/// A class device is a [`Device`] that is associated with a logical category of functionality
|
||||||
|
/// rather than a physical bus. Examples of classes include block devices, network interfaces, sound
|
||||||
|
/// cards, and input devices. Class devices are grouped under a common class and exposed to
|
||||||
|
/// userspace via entries in `/sys/class/<class-name>/`.
|
||||||
|
///
|
||||||
|
/// # Device Context
|
||||||
|
///
|
||||||
|
/// [`Device`] references are generic over a [`DeviceContext`], which represents the type state of
|
||||||
|
/// a [`Device`].
|
||||||
|
///
|
||||||
|
/// As the name indicates, this type state represents the context of the scope the [`Device`]
|
||||||
|
/// reference is valid in. For instance, the [`Bound`] context guarantees that the [`Device`] is
|
||||||
|
/// bound to a driver for the entire duration of the existence of a [`Device<Bound>`] reference.
|
||||||
|
///
|
||||||
|
/// Other [`DeviceContext`] types besides [`Bound`] are [`Normal`], [`Core`] and [`CoreInternal`].
|
||||||
|
///
|
||||||
|
/// Unless selected otherwise [`Device`] defaults to the [`Normal`] [`DeviceContext`], which by
|
||||||
|
/// itself has no additional requirements.
|
||||||
|
///
|
||||||
|
/// It is always up to the caller of [`Device::from_raw`] to select the correct [`DeviceContext`]
|
||||||
|
/// type for the corresponding scope the [`Device`] reference is created in.
|
||||||
|
///
|
||||||
|
/// All [`DeviceContext`] types other than [`Normal`] are intended to be used with
|
||||||
|
/// [bus devices](#bus-devices) only.
|
||||||
|
///
|
||||||
|
/// # Implementing Bus Devices
|
||||||
|
///
|
||||||
|
/// This section provides a guideline to implement bus specific devices, such as [`pci::Device`] or
|
||||||
|
/// [`platform::Device`].
|
||||||
|
///
|
||||||
|
/// A bus specific device should be defined as follows.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// #[repr(transparent)]
|
||||||
|
/// pub struct Device<Ctx: device::DeviceContext = device::Normal>(
|
||||||
|
/// Opaque<bindings::bus_device_type>,
|
||||||
|
/// PhantomData<Ctx>,
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Since devices are reference counted, [`AlwaysRefCounted`] should be implemented for `Device`
|
||||||
|
/// (i.e. `Device<Normal>`). Note that [`AlwaysRefCounted`] must not be implemented for any other
|
||||||
|
/// [`DeviceContext`], since all other device context types are only valid within a certain scope.
|
||||||
|
///
|
||||||
|
/// In order to be able to implement the [`DeviceContext`] dereference hierarchy, bus device
|
||||||
|
/// implementations should call the [`impl_device_context_deref`] macro as shown below.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// // 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 });
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// In order to convert from a any [`Device<Ctx>`] to [`ARef<Device>`], bus devices can implement
|
||||||
|
/// the following macro call.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// kernel::impl_device_context_into_aref!(Device);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Bus devices should also implement the following [`AsRef`] implementation, such that users can
|
||||||
|
/// easily derive a generic [`Device`] reference.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
|
||||||
|
/// fn as_ref(&self) -> &device::Device<Ctx> {
|
||||||
|
/// ...
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Implementing Class Devices
|
||||||
|
///
|
||||||
|
/// Class device implementations require less infrastructure and depend slightly more on the
|
||||||
|
/// specific subsystem.
|
||||||
|
///
|
||||||
|
/// An example implementation for a class device could look like this.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// #[repr(C)]
|
||||||
|
/// pub struct Device<T: class::Driver> {
|
||||||
|
/// dev: Opaque<bindings::class_device_type>,
|
||||||
|
/// data: T::Data,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This class device uses the sub-classing pattern to embed the driver's private data within the
|
||||||
|
/// allocation of the class device. For this to be possible the class device is generic over the
|
||||||
|
/// class specific `Driver` trait implementation.
|
||||||
|
///
|
||||||
|
/// Just like any device, class devices are reference counted and should hence implement
|
||||||
|
/// [`AlwaysRefCounted`] for `Device`.
|
||||||
|
///
|
||||||
|
/// Class devices should also implement the following [`AsRef`] implementation, such that users can
|
||||||
|
/// easily derive a generic [`Device`] reference.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// impl<T: class::Driver> AsRef<device::Device> for Device<T> {
|
||||||
|
/// fn as_ref(&self) -> &device::Device {
|
||||||
|
/// ...
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// An example for a class device implementation is [`drm::Device`].
|
||||||
///
|
///
|
||||||
/// # Invariants
|
/// # Invariants
|
||||||
///
|
///
|
||||||
@ -42,6 +149,12 @@ pub mod property;
|
|||||||
///
|
///
|
||||||
/// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be
|
/// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be
|
||||||
/// dropped from any thread.
|
/// dropped from any thread.
|
||||||
|
///
|
||||||
|
/// [`AlwaysRefCounted`]: kernel::types::AlwaysRefCounted
|
||||||
|
/// [`drm::Device`]: kernel::drm::Device
|
||||||
|
/// [`impl_device_context_deref`]: kernel::impl_device_context_deref
|
||||||
|
/// [`pci::Device`]: kernel::pci::Device
|
||||||
|
/// [`platform::Device`]: kernel::platform::Device
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Device<Ctx: DeviceContext = Normal>(Opaque<bindings::device>, PhantomData<Ctx>);
|
pub struct Device<Ctx: DeviceContext = Normal>(Opaque<bindings::device>, PhantomData<Ctx>);
|
||||||
|
|
||||||
@ -311,28 +424,75 @@ unsafe impl Send for Device {}
|
|||||||
// synchronization in `struct device`.
|
// synchronization in `struct device`.
|
||||||
unsafe impl Sync for Device {}
|
unsafe impl Sync for Device {}
|
||||||
|
|
||||||
/// Marker trait for the context of a bus specific device.
|
/// Marker trait for the context or scope of a bus specific device.
|
||||||
///
|
///
|
||||||
/// Some functions of a bus specific device should only be called from a certain context, i.e. bus
|
/// [`DeviceContext`] is a marker trait for types representing the context of a bus specific
|
||||||
/// callbacks, such as `probe()`.
|
/// [`Device`].
|
||||||
///
|
///
|
||||||
/// This is the marker trait for structures representing the context of a bus specific device.
|
/// The specific device context types are: [`CoreInternal`], [`Core`], [`Bound`] and [`Normal`].
|
||||||
|
///
|
||||||
|
/// [`DeviceContext`] types are hierarchical, which means that there is a strict hierarchy that
|
||||||
|
/// defines which [`DeviceContext`] type can be derived from another. For instance, any
|
||||||
|
/// [`Device<Core>`] can dereference to a [`Device<Bound>`].
|
||||||
|
///
|
||||||
|
/// The following enumeration illustrates the dereference hierarchy of [`DeviceContext`] types.
|
||||||
|
///
|
||||||
|
/// - [`CoreInternal`] => [`Core`] => [`Bound`] => [`Normal`]
|
||||||
|
///
|
||||||
|
/// Bus devices can automatically implement the dereference hierarchy by using
|
||||||
|
/// [`impl_device_context_deref`].
|
||||||
|
///
|
||||||
|
/// Note that the guarantee for a [`Device`] reference to have a certain [`DeviceContext`] comes
|
||||||
|
/// from the specific scope the [`Device`] reference is valid in.
|
||||||
|
///
|
||||||
|
/// [`impl_device_context_deref`]: kernel::impl_device_context_deref
|
||||||
pub trait DeviceContext: private::Sealed {}
|
pub trait DeviceContext: private::Sealed {}
|
||||||
|
|
||||||
/// The [`Normal`] context is the context of a bus specific device when it is not an argument of
|
/// The [`Normal`] context is the default [`DeviceContext`] of any [`Device`].
|
||||||
/// any bus callback.
|
///
|
||||||
|
/// The normal context does not indicate any specific context. Any `Device<Ctx>` is also a valid
|
||||||
|
/// [`Device<Normal>`]. It is the only [`DeviceContext`] for which it is valid to implement
|
||||||
|
/// [`AlwaysRefCounted`] for.
|
||||||
|
///
|
||||||
|
/// [`AlwaysRefCounted`]: kernel::types::AlwaysRefCounted
|
||||||
pub struct Normal;
|
pub struct Normal;
|
||||||
|
|
||||||
/// The [`Core`] context is the context of a bus specific device when it is supplied as argument of
|
/// The [`Core`] context is the context of a bus specific device when it appears as argument of
|
||||||
/// any of the bus callbacks, such as `probe()`.
|
/// any bus specific callback, such as `probe()`.
|
||||||
|
///
|
||||||
|
/// The core context indicates that the [`Device<Core>`] reference's scope is limited to the bus
|
||||||
|
/// callback it appears in. It is intended to be used for synchronization purposes. Bus device
|
||||||
|
/// implementations can implement methods for [`Device<Core>`], such that they can only be called
|
||||||
|
/// from bus callbacks.
|
||||||
pub struct Core;
|
pub struct Core;
|
||||||
|
|
||||||
/// Semantically the same as [`Core`] but reserved for internal usage of the corresponding bus
|
/// Semantically the same as [`Core`], but reserved for internal usage of the corresponding bus
|
||||||
/// abstraction.
|
/// abstraction.
|
||||||
|
///
|
||||||
|
/// The internal core context is intended to be used in exactly the same way as the [`Core`]
|
||||||
|
/// context, with the difference that this [`DeviceContext`] is internal to the corresponding bus
|
||||||
|
/// abstraction.
|
||||||
|
///
|
||||||
|
/// This context mainly exists to share generic [`Device`] infrastructure that should only be called
|
||||||
|
/// from bus callbacks with bus abstractions, but without making them accessible for drivers.
|
||||||
pub struct CoreInternal;
|
pub struct CoreInternal;
|
||||||
|
|
||||||
/// The [`Bound`] context is the context of a bus specific device reference when it is guaranteed to
|
/// The [`Bound`] context is the [`DeviceContext`] of a bus specific device when it is guaranteed to
|
||||||
/// be bound for the duration of its lifetime.
|
/// be bound to a driver.
|
||||||
|
///
|
||||||
|
/// The bound context indicates that for the entire duration of the lifetime of a [`Device<Bound>`]
|
||||||
|
/// reference, the [`Device`] is guaranteed to be bound to a driver.
|
||||||
|
///
|
||||||
|
/// Some APIs, such as [`dma::CoherentAllocation`] or [`Devres`] rely on the [`Device`] to be bound,
|
||||||
|
/// which can be proven with the [`Bound`] device context.
|
||||||
|
///
|
||||||
|
/// Any abstraction that can guarantee a scope where the corresponding bus device is bound, should
|
||||||
|
/// provide a [`Device<Bound>`] reference to its users for this scope. This allows users to benefit
|
||||||
|
/// from optimizations for accessing device resources, see also [`Devres::access`].
|
||||||
|
///
|
||||||
|
/// [`Devres`]: kernel::devres::Devres
|
||||||
|
/// [`Devres::access`]: kernel::devres::Devres::access
|
||||||
|
/// [`dma::CoherentAllocation`]: kernel::dma::CoherentAllocation
|
||||||
pub struct Bound;
|
pub struct Bound;
|
||||||
|
|
||||||
mod private {
|
mod private {
|
||||||
|
@ -115,10 +115,11 @@ pub struct Devres<T: Send> {
|
|||||||
/// Contains all the fields shared with [`Self::callback`].
|
/// Contains all the fields shared with [`Self::callback`].
|
||||||
// TODO: Replace with `UnsafePinned`, once available.
|
// TODO: Replace with `UnsafePinned`, once available.
|
||||||
//
|
//
|
||||||
// Subsequently, the `drop_in_place()` in `Devres::drop` and the explicit `Send` and `Sync'
|
// Subsequently, the `drop_in_place()` in `Devres::drop` and `Devres::new` as well as the
|
||||||
// impls can be removed.
|
// explicit `Send` and `Sync' impls can be removed.
|
||||||
#[pin]
|
#[pin]
|
||||||
inner: Opaque<Inner<T>>,
|
inner: Opaque<Inner<T>>,
|
||||||
|
_add_action: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send> Devres<T> {
|
impl<T: Send> Devres<T> {
|
||||||
@ -140,7 +141,15 @@ impl<T: Send> Devres<T> {
|
|||||||
dev: dev.into(),
|
dev: dev.into(),
|
||||||
callback,
|
callback,
|
||||||
// INVARIANT: `inner` is properly initialized.
|
// INVARIANT: `inner` is properly initialized.
|
||||||
inner <- {
|
inner <- Opaque::pin_init(try_pin_init!(Inner {
|
||||||
|
devm <- Completion::new(),
|
||||||
|
revoke <- Completion::new(),
|
||||||
|
data <- Revocable::new(data),
|
||||||
|
})),
|
||||||
|
// TODO: Replace with "initializer code blocks" [1] once available.
|
||||||
|
//
|
||||||
|
// [1] https://github.com/Rust-for-Linux/pin-init/pull/69
|
||||||
|
_add_action: {
|
||||||
// SAFETY: `this` is a valid pointer to uninitialized memory.
|
// SAFETY: `this` is a valid pointer to uninitialized memory.
|
||||||
let inner = unsafe { &raw mut (*this.as_ptr()).inner };
|
let inner = unsafe { &raw mut (*this.as_ptr()).inner };
|
||||||
|
|
||||||
@ -152,13 +161,13 @@ impl<T: Send> Devres<T> {
|
|||||||
// live at least as long as the returned `impl PinInit<Self, Error>`.
|
// live at least as long as the returned `impl PinInit<Self, Error>`.
|
||||||
to_result(unsafe {
|
to_result(unsafe {
|
||||||
bindings::devm_add_action(dev.as_raw(), Some(callback), inner.cast())
|
bindings::devm_add_action(dev.as_raw(), Some(callback), inner.cast())
|
||||||
})?;
|
}).inspect_err(|_| {
|
||||||
|
let inner = Opaque::cast_into(inner);
|
||||||
|
|
||||||
Opaque::pin_init(try_pin_init!(Inner {
|
// SAFETY: `inner` is a valid pointer to an `Inner<T>` and valid for both reads
|
||||||
devm <- Completion::new(),
|
// and writes.
|
||||||
revoke <- Completion::new(),
|
unsafe { core::ptr::drop_in_place(inner) };
|
||||||
data <- Revocable::new(data),
|
})?;
|
||||||
}))
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,93 @@
|
|||||||
|
|
||||||
//! Generic support for drivers of different buses (e.g., PCI, Platform, Amba, etc.).
|
//! Generic support for drivers of different buses (e.g., PCI, Platform, Amba, etc.).
|
||||||
//!
|
//!
|
||||||
//! Each bus / subsystem is expected to implement [`RegistrationOps`], which allows drivers to
|
//! This documentation describes how to implement a bus specific driver API and how to align it with
|
||||||
//! register using the [`Registration`] class.
|
//! the design of (bus specific) devices.
|
||||||
|
//!
|
||||||
|
//! Note: Readers are expected to know the content of the documentation of [`Device`] and
|
||||||
|
//! [`DeviceContext`].
|
||||||
|
//!
|
||||||
|
//! # Driver Trait
|
||||||
|
//!
|
||||||
|
//! The main driver interface is defined by a bus specific driver trait. For instance:
|
||||||
|
//!
|
||||||
|
//! ```ignore
|
||||||
|
//! pub trait Driver: Send {
|
||||||
|
//! /// The type holding information about each device ID supported by the driver.
|
||||||
|
//! type IdInfo: 'static;
|
||||||
|
//!
|
||||||
|
//! /// The table of OF device ids supported by the driver.
|
||||||
|
//! const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
|
||||||
|
//!
|
||||||
|
//! /// The table of ACPI device ids supported by the driver.
|
||||||
|
//! const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None;
|
||||||
|
//!
|
||||||
|
//! /// Driver probe.
|
||||||
|
//! fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>;
|
||||||
|
//!
|
||||||
|
//! /// Driver unbind (optional).
|
||||||
|
//! fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) {
|
||||||
|
//! let _ = (dev, this);
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! For specific examples see [`auxiliary::Driver`], [`pci::Driver`] and [`platform::Driver`].
|
||||||
|
//!
|
||||||
|
//! The `probe()` callback should return a `Result<Pin<KBox<Self>>>`, i.e. the driver's private
|
||||||
|
//! data. The bus abstraction should store the pointer in the corresponding bus device. The generic
|
||||||
|
//! [`Device`] infrastructure provides common helpers for this purpose on its
|
||||||
|
//! [`Device<CoreInternal>`] implementation.
|
||||||
|
//!
|
||||||
|
//! All driver callbacks should provide a reference to the driver's private data. Once the driver
|
||||||
|
//! is unbound from the device, the bus abstraction should take back the ownership of the driver's
|
||||||
|
//! private data from the corresponding [`Device`] and [`drop`] it.
|
||||||
|
//!
|
||||||
|
//! All driver callbacks should provide a [`Device<Core>`] reference (see also [`device::Core`]).
|
||||||
|
//!
|
||||||
|
//! # Adapter
|
||||||
|
//!
|
||||||
|
//! The adapter implementation of a bus represents the abstraction layer between the C bus
|
||||||
|
//! callbacks and the Rust bus callbacks. It therefore has to be generic over an implementation of
|
||||||
|
//! the [driver trait](#driver-trait).
|
||||||
|
//!
|
||||||
|
//! ```ignore
|
||||||
|
//! pub struct Adapter<T: Driver>;
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! There's a common [`Adapter`] trait that can be implemented to inherit common driver
|
||||||
|
//! infrastructure, such as finding the ID info from an [`of::IdTable`] or [`acpi::IdTable`].
|
||||||
|
//!
|
||||||
|
//! # Driver Registration
|
||||||
|
//!
|
||||||
|
//! In order to register C driver types (such as `struct platform_driver`) the [adapter](#adapter)
|
||||||
|
//! should implement the [`RegistrationOps`] trait.
|
||||||
|
//!
|
||||||
|
//! This trait implementation can be used to create the actual registration with the common
|
||||||
|
//! [`Registration`] type.
|
||||||
|
//!
|
||||||
|
//! Typically, bus abstractions want to provide a bus specific `module_bus_driver!` macro, which
|
||||||
|
//! creates a kernel module with exactly one [`Registration`] for the bus specific adapter.
|
||||||
|
//!
|
||||||
|
//! The generic driver infrastructure provides a helper for this with the [`module_driver`] macro.
|
||||||
|
//!
|
||||||
|
//! # Device IDs
|
||||||
|
//!
|
||||||
|
//! Besides the common device ID types, such as [`of::DeviceId`] and [`acpi::DeviceId`], most buses
|
||||||
|
//! may need to implement their own device ID types.
|
||||||
|
//!
|
||||||
|
//! For this purpose the generic infrastructure in [`device_id`] should be used.
|
||||||
|
//!
|
||||||
|
//! [`auxiliary::Driver`]: kernel::auxiliary::Driver
|
||||||
|
//! [`Core`]: device::Core
|
||||||
|
//! [`Device`]: device::Device
|
||||||
|
//! [`Device<Core>`]: device::Device<device::Core>
|
||||||
|
//! [`Device<CoreInternal>`]: device::Device<device::CoreInternal>
|
||||||
|
//! [`DeviceContext`]: device::DeviceContext
|
||||||
|
//! [`device_id`]: kernel::device_id
|
||||||
|
//! [`module_driver`]: kernel::module_driver
|
||||||
|
//! [`pci::Driver`]: kernel::pci::Driver
|
||||||
|
//! [`platform::Driver`]: kernel::platform::Driver
|
||||||
|
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::{acpi, device, of, str::CStr, try_pin_init, types::Opaque, ThisModule};
|
use crate::{acpi, device, of, str::CStr, try_pin_init, types::Opaque, ThisModule};
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! This module provides bindings for working with faux devices in kernel modules.
|
//! This module provides bindings for working with faux devices in kernel modules.
|
||||||
//!
|
//!
|
||||||
//! C header: [`include/linux/device/faux.h`]
|
//! C header: [`include/linux/device/faux.h`](srctree/include/linux/device/faux.h)
|
||||||
|
|
||||||
use crate::{bindings, device, error::code::*, prelude::*};
|
use crate::{bindings, device, error::code::*, prelude::*};
|
||||||
use core::ptr::{addr_of_mut, null, null_mut, NonNull};
|
use core::ptr::{addr_of_mut, null, null_mut, NonNull};
|
||||||
|
Loading…
Reference in New Issue
Block a user