rust/kernel/auxiliary.rs
Source file repositories/reference/linux-study-clean/rust/kernel/auxiliary.rs
File Facts
- System
- Linux kernel
- Corpus path
rust/kernel/auxiliary.rs- Extension
.rs- Size
- 21094 bytes
- Lines
- 554
- Domain
- Rust Kernel Layer
- Bucket
- Rust API Membrane
- Inferred role
- Rust Kernel Layer: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.
- Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
- No C-style include directives detected by the generator.
Detected Declarations
function to_resultfunction Okfunction Okfunction inc_reffunction dec_reffunction Ok
Annotated Snippet
// - `struct auxiliary_driver` embeds a `struct device_driver`.
// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.
unsafe impl<T: Driver> driver::DriverLayout for Adapter<T> {
type DriverType = bindings::auxiliary_driver;
type DriverData<'bound> = T::Data<'bound>;
const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);
}
// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
// a preceding call to `register` has been successful.
unsafe impl<T: Driver> driver::RegistrationOps for Adapter<T> {
unsafe fn register(
adrv: &Opaque<Self::DriverType>,
name: &'static CStr,
module: &'static ThisModule,
) -> Result {
// SAFETY: It's safe to set the fields of `struct auxiliary_driver` on initialization.
unsafe {
(*adrv.get()).name = name.as_char_ptr();
(*adrv.get()).probe = Some(Self::probe_callback);
(*adrv.get()).remove = Some(Self::remove_callback);
(*adrv.get()).id_table = T::ID_TABLE.as_ptr();
}
// SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
to_result(unsafe {
bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr())
})
}
unsafe fn unregister(adrv: &Opaque<Self::DriverType>) {
// SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
unsafe { bindings::auxiliary_driver_unregister(adrv.get()) }
}
}
impl<T: Driver> Adapter<T> {
extern "C" fn probe_callback(
adev: *mut bindings::auxiliary_device,
id: *const bindings::auxiliary_device_id,
) -> c_int {
// SAFETY: The auxiliary bus only ever calls the probe callback with a valid pointer to a
// `struct auxiliary_device`.
//
// INVARIANT: `adev` is valid for the duration of `probe_callback()`.
let adev = unsafe { &*adev.cast::<Device<device::CoreInternal<'_>>>() };
// SAFETY: `DeviceId` is a `#[repr(transparent)`] wrapper of `struct auxiliary_device_id`
// and does not add additional invariants, so it's safe to transmute.
let id = unsafe { &*id.cast::<DeviceId>() };
let info = T::ID_TABLE.info(id.index());
from_result(|| {
let data = T::probe(adev, info);
adev.as_ref().set_drvdata(data)?;
Ok(0)
})
}
extern "C" fn remove_callback(adev: *mut bindings::auxiliary_device) {
// SAFETY: The auxiliary bus only ever calls the probe callback with a valid pointer to a
// `struct auxiliary_device`.
//
// INVARIANT: `adev` is valid for the duration of `remove_callback()`.
let adev = unsafe { &*adev.cast::<Device<device::CoreInternal<'_>>>() };
// SAFETY: `remove_callback` is only ever called after a successful call to
// `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
// and stored a `Pin<KBox<T::Data<'_>>>`.
let data = unsafe { adev.as_ref().drvdata_borrow::<T::Data<'_>>() };
T::unbind(adev, data);
}
}
/// Declares a kernel module that exposes a single auxiliary driver.
#[macro_export]
macro_rules! module_auxiliary_driver {
($($f:tt)*) => {
$crate::module_driver!(<T>, $crate::auxiliary::Adapter<T>, { $($f)* });
};
}
/// Abstraction for `bindings::auxiliary_device_id`.
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct DeviceId(bindings::auxiliary_device_id);
impl DeviceId {
Annotation
- Detected declarations: `function to_result`, `function Ok`, `function Ok`, `function inc_ref`, `function dec_ref`, `function Ok`.
- Atlas domain: Rust Kernel Layer / Rust API Membrane.
- Implementation status: pattern implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.