summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel')
-rw-r--r--rust/kernel/alloc/allocator_test.rs2
-rw-r--r--rust/kernel/alloc/kvec.rs4
-rw-r--r--rust/kernel/block/mq.rs2
-rw-r--r--rust/kernel/block/mq/operations.rs2
-rw-r--r--rust/kernel/block/mq/request.rs11
-rw-r--r--rust/kernel/clk.rs6
-rw-r--r--rust/kernel/configfs.rs24
-rw-r--r--rust/kernel/cpu.rs125
-rw-r--r--rust/kernel/cpufreq.rs183
-rw-r--r--rust/kernel/cpumask.rs55
-rw-r--r--rust/kernel/device.rs4
-rw-r--r--rust/kernel/device_id.rs4
-rw-r--r--rust/kernel/devres.rs81
-rw-r--r--rust/kernel/dma.rs6
-rw-r--r--rust/kernel/drm/device.rs6
-rw-r--r--rust/kernel/error.rs2
-rw-r--r--rust/kernel/firmware.rs9
-rw-r--r--rust/kernel/fs/file.rs2
-rw-r--r--rust/kernel/io.rs20
-rw-r--r--rust/kernel/kunit.rs13
-rw-r--r--rust/kernel/list.rs38
-rw-r--r--rust/kernel/list/impl_list_item_mod.rs2
-rw-r--r--rust/kernel/miscdevice.rs2
-rw-r--r--rust/kernel/mm/virt.rs52
-rw-r--r--rust/kernel/net/phy.rs4
-rw-r--r--rust/kernel/of.rs6
-rw-r--r--rust/kernel/opp.rs18
-rw-r--r--rust/kernel/pci.rs15
-rw-r--r--rust/kernel/platform.rs6
-rw-r--r--rust/kernel/print.rs6
-rw-r--r--rust/kernel/rbtree.rs6
-rw-r--r--rust/kernel/revocable.rs22
-rw-r--r--rust/kernel/seq_file.rs2
-rw-r--r--rust/kernel/str.rs14
-rw-r--r--rust/kernel/sync.rs4
-rw-r--r--rust/kernel/sync/arc.rs78
-rw-r--r--rust/kernel/sync/completion.rs112
-rw-r--r--rust/kernel/sync/poll.rs2
-rw-r--r--rust/kernel/time/hrtimer.rs2
-rw-r--r--rust/kernel/time/hrtimer/pin.rs2
-rw-r--r--rust/kernel/time/hrtimer/pin_mut.rs2
-rw-r--r--rust/kernel/uaccess.rs4
-rw-r--r--rust/kernel/workqueue.rs10
43 files changed, 719 insertions, 251 deletions
diff --git a/rust/kernel/alloc/allocator_test.rs b/rust/kernel/alloc/allocator_test.rs
index d19c06ef0498..a3074480bd8d 100644
--- a/rust/kernel/alloc/allocator_test.rs
+++ b/rust/kernel/alloc/allocator_test.rs
@@ -82,7 +82,7 @@ unsafe impl Allocator for Cmalloc {
// SAFETY: Returns either NULL or a pointer to a memory allocation that satisfies or
// exceeds the given size and alignment requirements.
- let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) } as *mut u8;
+ let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) }.cast::<u8>();
let dst = NonNull::new(dst).ok_or(AllocError)?;
if flags.contains(__GFP_ZERO) {
diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index 1a0dd852a468..0477041cbc03 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -288,7 +288,7 @@ where
// - `self.len` is smaller than `self.capacity` by the type invariant and hence, the
// resulting pointer is guaranteed to be part of the same allocated object.
// - `self.len` can not overflow `isize`.
- let ptr = unsafe { self.as_mut_ptr().add(self.len) } as *mut MaybeUninit<T>;
+ let ptr = unsafe { self.as_mut_ptr().add(self.len) }.cast::<MaybeUninit<T>>();
// SAFETY: The memory between `self.len` and `self.capacity` is guaranteed to be allocated
// and valid, but uninitialized.
@@ -847,7 +847,7 @@ where
// - `ptr` points to memory with at least a size of `size_of::<T>() * len`,
// - all elements within `b` are initialized values of `T`,
// - `len` does not exceed `isize::MAX`.
- unsafe { Vec::from_raw_parts(ptr as _, len, len) }
+ unsafe { Vec::from_raw_parts(ptr.cast(), len, len) }
}
}
diff --git a/rust/kernel/block/mq.rs b/rust/kernel/block/mq.rs
index fb0f393c1cea..831445d37181 100644
--- a/rust/kernel/block/mq.rs
+++ b/rust/kernel/block/mq.rs
@@ -53,7 +53,7 @@
//! [`GenDiskBuilder`]: gen_disk::GenDiskBuilder
//! [`GenDiskBuilder::build`]: gen_disk::GenDiskBuilder::build
//!
-//! # Example
+//! # Examples
//!
//! ```rust
//! use kernel::{
diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
index 864ff379dc91..c2b98f507bcb 100644
--- a/rust/kernel/block/mq/operations.rs
+++ b/rust/kernel/block/mq/operations.rs
@@ -101,7 +101,7 @@ impl<T: Operations> OperationsVTable<T> {
if let Err(e) = ret {
e.to_blk_status()
} else {
- bindings::BLK_STS_OK as _
+ bindings::BLK_STS_OK as bindings::blk_status_t
}
}
diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
index 4a5b7ec914ef..fefd394f064a 100644
--- a/rust/kernel/block/mq/request.rs
+++ b/rust/kernel/block/mq/request.rs
@@ -69,7 +69,7 @@ impl<T: Operations> Request<T> {
// INVARIANT: By the safety requirements of this function, invariants are upheld.
// SAFETY: By the safety requirement of this function, we own a
// reference count that we can pass to `ARef`.
- unsafe { ARef::from_raw(NonNull::new_unchecked(ptr as *const Self as *mut Self)) }
+ unsafe { ARef::from_raw(NonNull::new_unchecked(ptr.cast())) }
}
/// Notify the block layer that a request is going to be processed now.
@@ -125,7 +125,12 @@ impl<T: Operations> Request<T> {
// success of the call to `try_set_end` guarantees that there are no
// `ARef`s pointing to this request. Therefore it is safe to hand it
// back to the block layer.
- unsafe { bindings::blk_mq_end_request(request_ptr, bindings::BLK_STS_OK as _) };
+ unsafe {
+ bindings::blk_mq_end_request(
+ request_ptr,
+ bindings::BLK_STS_OK as bindings::blk_status_t,
+ )
+ };
Ok(())
}
@@ -155,7 +160,7 @@ impl<T: Operations> Request<T> {
// the private data associated with this request is initialized and
// valid. The existence of `&self` guarantees that the private data is
// valid as a shared reference.
- unsafe { Self::wrapper_ptr(self as *const Self as *mut Self).as_ref() }
+ unsafe { Self::wrapper_ptr(core::ptr::from_ref(self).cast_mut()).as_ref() }
}
}
diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs
index 6041c6d07527..34a19bc99990 100644
--- a/rust/kernel/clk.rs
+++ b/rust/kernel/clk.rs
@@ -12,7 +12,7 @@ use crate::ffi::c_ulong;
///
/// Represents a frequency in hertz, wrapping a [`c_ulong`] value.
///
-/// ## Examples
+/// # Examples
///
/// ```
/// use kernel::clk::Hertz;
@@ -95,7 +95,7 @@ mod common_clk {
/// Instances of this type are reference-counted. Calling [`Clk::get`] ensures that the
/// allocation remains valid for the lifetime of the [`Clk`].
///
- /// ## Examples
+ /// # Examples
///
/// The following example demonstrates how to obtain and configure a clock for a device.
///
@@ -266,7 +266,7 @@ mod common_clk {
/// Instances of this type are reference-counted. Calling [`OptionalClk::get`] ensures that the
/// allocation remains valid for the lifetime of the [`OptionalClk`].
///
- /// ## Examples
+ /// # Examples
///
/// The following example demonstrates how to obtain and configure an optional clock for a
/// device. The code functions correctly whether or not the clock is available.
diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs
index 6d566a8bde74..d287e11e4233 100644
--- a/rust/kernel/configfs.rs
+++ b/rust/kernel/configfs.rs
@@ -17,7 +17,7 @@
//!
//! C header: [`include/linux/configfs.h`](srctree/include/linux/configfs.h)
//!
-//! # Example
+//! # Examples
//!
//! ```ignore
//! use kernel::alloc::flags;
@@ -426,7 +426,7 @@ where
};
const fn vtable_ptr() -> *const bindings::configfs_group_operations {
- &Self::VTABLE as *const bindings::configfs_group_operations
+ &Self::VTABLE
}
}
@@ -464,7 +464,7 @@ where
};
const fn vtable_ptr() -> *const bindings::configfs_item_operations {
- &Self::VTABLE as *const bindings::configfs_item_operations
+ &Self::VTABLE
}
}
@@ -476,7 +476,7 @@ impl<Data> ItemOperationsVTable<Subsystem<Data>, Data> {
};
const fn vtable_ptr() -> *const bindings::configfs_item_operations {
- &Self::VTABLE as *const bindings::configfs_item_operations
+ &Self::VTABLE
}
}
@@ -561,7 +561,7 @@ where
let data: &Data = unsafe { get_group_data(c_group) };
// SAFETY: By function safety requirements, `page` is writable for `PAGE_SIZE`.
- let ret = O::show(data, unsafe { &mut *(page as *mut [u8; PAGE_SIZE]) });
+ let ret = O::show(data, unsafe { &mut *(page.cast::<[u8; PAGE_SIZE]>()) });
match ret {
Ok(size) => size as isize,
@@ -717,11 +717,7 @@ impl<const N: usize, Data> AttributeList<N, Data> {
// SAFETY: By function safety requirements, we have exclusive access to
// `self` and the reference created below will be exclusive.
- unsafe {
- (&mut *self.0.get())[I] = (attribute as *const Attribute<ID, O, Data>)
- .cast_mut()
- .cast()
- };
+ unsafe { (&mut *self.0.get())[I] = core::ptr::from_ref(attribute).cast_mut().cast() };
}
}
@@ -761,9 +757,7 @@ macro_rules! impl_item_type {
ct_owner: owner.as_ptr(),
ct_group_ops: GroupOperationsVTable::<Data, Child>::vtable_ptr().cast_mut(),
ct_item_ops: ItemOperationsVTable::<$tpe, Data>::vtable_ptr().cast_mut(),
- ct_attrs: (attributes as *const AttributeList<N, Data>)
- .cast_mut()
- .cast(),
+ ct_attrs: core::ptr::from_ref(attributes).cast_mut().cast(),
ct_bin_attrs: core::ptr::null_mut(),
}),
_p: PhantomData,
@@ -780,9 +774,7 @@ macro_rules! impl_item_type {
ct_owner: owner.as_ptr(),
ct_group_ops: core::ptr::null_mut(),
ct_item_ops: ItemOperationsVTable::<$tpe, Data>::vtable_ptr().cast_mut(),
- ct_attrs: (attributes as *const AttributeList<N, Data>)
- .cast_mut()
- .cast(),
+ ct_attrs: core::ptr::from_ref(attributes).cast_mut().cast(),
ct_bin_attrs: core::ptr::null_mut(),
}),
_p: PhantomData,
diff --git a/rust/kernel/cpu.rs b/rust/kernel/cpu.rs
index 10c5c3b25873..b75403b0eb56 100644
--- a/rust/kernel/cpu.rs
+++ b/rust/kernel/cpu.rs
@@ -6,6 +6,127 @@
use crate::{bindings, device::Device, error::Result, prelude::ENODEV};
+/// Returns the maximum number of possible CPUs in the current system configuration.
+#[inline]
+pub fn nr_cpu_ids() -> u32 {
+ #[cfg(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS))]
+ {
+ bindings::NR_CPUS
+ }
+
+ #[cfg(not(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS)))]
+ // SAFETY: `nr_cpu_ids` is a valid global provided by the kernel.
+ unsafe {
+ bindings::nr_cpu_ids
+ }
+}
+
+/// The CPU ID.
+///
+/// Represents a CPU identifier as a wrapper around an [`u32`].
+///
+/// # Invariants
+///
+/// The CPU ID lies within the range `[0, nr_cpu_ids())`.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::cpu::CpuId;
+///
+/// let cpu = 0;
+///
+/// // SAFETY: 0 is always a valid CPU number.
+/// let id = unsafe { CpuId::from_u32_unchecked(cpu) };
+///
+/// assert_eq!(id.as_u32(), cpu);
+/// assert!(CpuId::from_i32(0).is_some());
+/// assert!(CpuId::from_i32(-1).is_none());
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub struct CpuId(u32);
+
+impl CpuId {
+ /// Creates a new [`CpuId`] from the given `id` without checking bounds.
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`).
+ #[inline]
+ pub unsafe fn from_i32_unchecked(id: i32) -> Self {
+ debug_assert!(id >= 0);
+ debug_assert!((id as u32) < nr_cpu_ids());
+
+ // INVARIANT: The function safety guarantees `id` is a valid CPU id.
+ Self(id as u32)
+ }
+
+ /// Creates a new [`CpuId`] from the given `id`, checking that it is valid.
+ pub fn from_i32(id: i32) -> Option<Self> {
+ if id < 0 || id as u32 >= nr_cpu_ids() {
+ None
+ } else {
+ // INVARIANT: `id` has just been checked as a valid CPU ID.
+ Some(Self(id as u32))
+ }
+ }
+
+ /// Creates a new [`CpuId`] from the given `id` without checking bounds.
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`).
+ #[inline]
+ pub unsafe fn from_u32_unchecked(id: u32) -> Self {
+ debug_assert!(id < nr_cpu_ids());
+
+ // Ensure the `id` fits in an [`i32`] as it's also representable that way.
+ debug_assert!(id <= i32::MAX as u32);
+
+ // INVARIANT: The function safety guarantees `id` is a valid CPU id.
+ Self(id)
+ }
+
+ /// Creates a new [`CpuId`] from the given `id`, checking that it is valid.
+ pub fn from_u32(id: u32) -> Option<Self> {
+ if id >= nr_cpu_ids() {
+ None
+ } else {
+ // INVARIANT: `id` has just been checked as a valid CPU ID.
+ Some(Self(id))
+ }
+ }
+
+ /// Returns CPU number.
+ #[inline]
+ pub fn as_u32(&self) -> u32 {
+ self.0
+ }
+
+ /// Returns the ID of the CPU the code is currently running on.
+ ///
+ /// The returned value is considered unstable because it may change
+ /// unexpectedly due to preemption or CPU migration. It should only be
+ /// used when the context ensures that the task remains on the same CPU
+ /// or the users could use a stale (yet valid) CPU ID.
+ pub fn current() -> Self {
+ // SAFETY: raw_smp_processor_id() always returns a valid CPU ID.
+ unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()) }
+ }
+}
+
+impl From<CpuId> for u32 {
+ fn from(id: CpuId) -> Self {
+ id.as_u32()
+ }
+}
+
+impl From<CpuId> for i32 {
+ fn from(id: CpuId) -> Self {
+ id.as_u32() as i32
+ }
+}
+
/// Creates a new instance of CPU's device.
///
/// # Safety
@@ -17,9 +138,9 @@ use crate::{bindings, device::Device, error::Result, prelude::ENODEV};
/// Callers must ensure that the CPU device is not used after it has been unregistered.
/// This can be achieved, for example, by registering a CPU hotplug notifier and removing
/// any references to the CPU device within the notifier's callback.
-pub unsafe fn from_cpu(cpu: u32) -> Result<&'static Device> {
+pub unsafe fn from_cpu(cpu: CpuId) -> Result<&'static Device> {
// SAFETY: It is safe to call `get_cpu_device()` for any CPU.
- let ptr = unsafe { bindings::get_cpu_device(cpu) };
+ let ptr = unsafe { bindings::get_cpu_device(u32::from(cpu)) };
if ptr.is_null() {
return Err(ENODEV);
}
diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs
index b0a9c6182aec..e8d231971276 100644
--- a/rust/kernel/cpufreq.rs
+++ b/rust/kernel/cpufreq.rs
@@ -10,6 +10,7 @@
use crate::{
clk::Hertz,
+ cpu::CpuId,
cpumask,
device::{Bound, Device},
devres::Devres,
@@ -201,7 +202,7 @@ impl From<TableIndex> for usize {
/// The callers must ensure that the `struct cpufreq_frequency_table` is valid for access and
/// remains valid for the lifetime of the returned reference.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to read a frequency value from [`Table`].
///
@@ -317,7 +318,7 @@ impl Deref for TableBox {
///
/// This is used by the CPU frequency drivers to build a frequency table dynamically.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to create a CPU frequency table.
///
@@ -394,7 +395,7 @@ impl TableBuilder {
/// The callers must ensure that the `struct cpufreq_policy` is valid for access and remains valid
/// for the lifetime of the returned reference.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to create a CPU frequency table.
///
@@ -465,8 +466,9 @@ impl Policy {
/// Returns the primary CPU for the [`Policy`].
#[inline]
- pub fn cpu(&self) -> u32 {
- self.as_ref().cpu
+ pub fn cpu(&self) -> CpuId {
+ // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
+ unsafe { CpuId::from_u32_unchecked(self.as_ref().cpu) }
}
/// Returns the minimum frequency for the [`Policy`].
@@ -525,7 +527,7 @@ impl Policy {
#[inline]
pub fn generic_get(&self) -> Result<u32> {
// SAFETY: By the type invariant, the pointer stored in `self` is valid.
- Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) })
+ Ok(unsafe { bindings::cpufreq_generic_get(u32::from(self.cpu())) })
}
/// Provides a wrapper to the register with energy model using the OPP core.
@@ -647,7 +649,7 @@ impl Policy {
fn set_data<T: ForeignOwnable>(&mut self, data: T) -> Result {
if self.as_ref().driver_data.is_null() {
// Transfer the ownership of the data to the foreign interface.
- self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data) as _;
+ self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data).cast();
Ok(())
} else {
Err(EBUSY)
@@ -678,9 +680,9 @@ impl Policy {
struct PolicyCpu<'a>(&'a mut Policy);
impl<'a> PolicyCpu<'a> {
- fn from_cpu(cpu: u32) -> Result<Self> {
+ fn from_cpu(cpu: CpuId) -> Result<Self> {
// SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU.
- let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) })?;
+ let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(u32::from(cpu)) })?;
Ok(Self(
// SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of
@@ -832,7 +834,7 @@ pub trait Driver {
/// CPU frequency driver Registration.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to register a cpufreq driver.
///
@@ -1055,8 +1057,11 @@ impl<T: Driver> Registration<T> {
impl<T: Driver> Registration<T> {
/// Driver's `init` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1070,8 +1075,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `exit` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
let policy = unsafe { Policy::from_raw_mut(ptr) };
@@ -1082,8 +1090,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `online` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1094,8 +1105,13 @@ impl<T: Driver> Registration<T> {
/// Driver's `offline` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn offline_callback(
+ ptr: *mut bindings::cpufreq_policy,
+ ) -> kernel::ffi::c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1106,8 +1122,13 @@ impl<T: Driver> Registration<T> {
/// Driver's `suspend` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn suspend_callback(
+ ptr: *mut bindings::cpufreq_policy,
+ ) -> kernel::ffi::c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1118,8 +1139,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `resume` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1130,8 +1154,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `ready` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
let policy = unsafe { Policy::from_raw_mut(ptr) };
@@ -1140,8 +1167,13 @@ impl<T: Driver> Registration<T> {
/// Driver's `verify` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> kernel::ffi::c_int {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn verify_callback(
+ ptr: *mut bindings::cpufreq_policy_data,
+ ) -> kernel::ffi::c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1152,8 +1184,13 @@ impl<T: Driver> Registration<T> {
/// Driver's `setpolicy` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn setpolicy_callback(
+ ptr: *mut bindings::cpufreq_policy,
+ ) -> kernel::ffi::c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1164,8 +1201,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `target` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn target_callback(
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn target_callback(
ptr: *mut bindings::cpufreq_policy,
target_freq: u32,
relation: u32,
@@ -1180,8 +1220,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `target_index` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn target_index_callback(
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn target_index_callback(
ptr: *mut bindings::cpufreq_policy,
index: u32,
) -> kernel::ffi::c_int {
@@ -1200,8 +1243,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `fast_switch` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn fast_switch_callback(
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn fast_switch_callback(
ptr: *mut bindings::cpufreq_policy,
target_freq: u32,
) -> kernel::ffi::c_uint {
@@ -1212,21 +1258,31 @@ impl<T: Driver> Registration<T> {
}
/// Driver's `adjust_perf` callback.
- extern "C" fn adjust_perf_callback(
+ ///
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ unsafe extern "C" fn adjust_perf_callback(
cpu: u32,
min_perf: usize,
target_perf: usize,
capacity: usize,
) {
- if let Ok(mut policy) = PolicyCpu::from_cpu(cpu) {
+ // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
+ let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
+
+ if let Ok(mut policy) = PolicyCpu::from_cpu(cpu_id) {
T::adjust_perf(&mut policy, min_perf, target_perf, capacity);
}
}
/// Driver's `get_intermediate` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn get_intermediate_callback(
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn get_intermediate_callback(
ptr: *mut bindings::cpufreq_policy,
index: u32,
) -> kernel::ffi::c_uint {
@@ -1243,8 +1299,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `target_intermediate` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn target_intermediate_callback(
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn target_intermediate_callback(
ptr: *mut bindings::cpufreq_policy,
index: u32,
) -> kernel::ffi::c_int {
@@ -1262,12 +1321,24 @@ impl<T: Driver> Registration<T> {
}
/// Driver's `get` callback.
- extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint {
- PolicyCpu::from_cpu(cpu).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f))
+ ///
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ unsafe extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint {
+ // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
+ let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
+
+ PolicyCpu::from_cpu(cpu_id).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f))
}
/// Driver's `update_limit` callback.
- extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) {
+ ///
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
let policy = unsafe { Policy::from_raw_mut(ptr) };
@@ -1276,10 +1347,16 @@ impl<T: Driver> Registration<T> {
/// Driver's `bios_limit` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int {
+ // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
+ let cpu_id = unsafe { CpuId::from_i32_unchecked(cpu) };
+
from_result(|| {
- let mut policy = PolicyCpu::from_cpu(cpu as u32)?;
+ let mut policy = PolicyCpu::from_cpu(cpu_id)?;
// SAFETY: `limit` is guaranteed by the C code to be valid.
T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0)
@@ -1288,8 +1365,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `set_boost` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn set_boost_callback(
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn set_boost_callback(
ptr: *mut bindings::cpufreq_policy,
state: i32,
) -> kernel::ffi::c_int {
@@ -1303,8 +1383,11 @@ impl<T: Driver> Registration<T> {
/// Driver's `register_em` callback.
///
- /// SAFETY: Called from C. Inputs must be valid pointers.
- extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) {
+ /// # Safety
+ ///
+ /// - This function may only be called from the cpufreq C infrastructure.
+ /// - The pointer arguments must be valid pointers.
+ unsafe extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
let policy = unsafe { Policy::from_raw_mut(ptr) };
diff --git a/rust/kernel/cpumask.rs b/rust/kernel/cpumask.rs
index c90bfac9346a..4bce230a73b6 100644
--- a/rust/kernel/cpumask.rs
+++ b/rust/kernel/cpumask.rs
@@ -6,6 +6,7 @@
use crate::{
alloc::{AllocError, Flags},
+ cpu::CpuId,
prelude::*,
types::Opaque,
};
@@ -29,15 +30,16 @@ use core::ops::{Deref, DerefMut};
/// The callers must ensure that the `struct cpumask` is valid for access and
/// remains valid for the lifetime of the returned reference.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to update a [`Cpumask`].
///
/// ```
/// use kernel::bindings;
+/// use kernel::cpu::CpuId;
/// use kernel::cpumask::Cpumask;
///
-/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: u32, clear_cpu: i32) {
+/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: CpuId, clear_cpu: CpuId) {
/// // SAFETY: The `ptr` is valid for writing and remains valid for the lifetime of the
/// // returned reference.
/// let mask = unsafe { Cpumask::as_mut_ref(ptr) };
@@ -90,9 +92,9 @@ impl Cpumask {
/// This mismatches kernel naming convention and corresponds to the C
/// function `__cpumask_set_cpu()`.
#[inline]
- pub fn set(&mut self, cpu: u32) {
+ pub fn set(&mut self, cpu: CpuId) {
// SAFETY: By the type invariant, `self.as_raw` is a valid argument to `__cpumask_set_cpu`.
- unsafe { bindings::__cpumask_set_cpu(cpu, self.as_raw()) };
+ unsafe { bindings::__cpumask_set_cpu(u32::from(cpu), self.as_raw()) };
}
/// Clear `cpu` in the cpumask.
@@ -101,19 +103,19 @@ impl Cpumask {
/// This mismatches kernel naming convention and corresponds to the C
/// function `__cpumask_clear_cpu()`.
#[inline]
- pub fn clear(&mut self, cpu: i32) {
+ pub fn clear(&mut self, cpu: CpuId) {
// SAFETY: By the type invariant, `self.as_raw` is a valid argument to
// `__cpumask_clear_cpu`.
- unsafe { bindings::__cpumask_clear_cpu(cpu, self.as_raw()) };
+ unsafe { bindings::__cpumask_clear_cpu(i32::from(cpu), self.as_raw()) };
}
/// Test `cpu` in the cpumask.
///
/// Equivalent to the kernel's `cpumask_test_cpu` API.
#[inline]
- pub fn test(&self, cpu: i32) -> bool {
+ pub fn test(&self, cpu: CpuId) -> bool {
// SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_test_cpu`.
- unsafe { bindings::cpumask_test_cpu(cpu, self.as_raw()) }
+ unsafe { bindings::cpumask_test_cpu(i32::from(cpu), self.as_raw()) }
}
/// Set all CPUs in the cpumask.
@@ -173,26 +175,45 @@ impl Cpumask {
/// The callers must ensure that the `struct cpumask_var_t` is valid for access and remains valid
/// for the lifetime of [`CpumaskVar`].
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to create and update a [`CpumaskVar`].
///
/// ```
+/// use kernel::cpu::CpuId;
/// use kernel::cpumask::CpumaskVar;
///
/// let mut mask = CpumaskVar::new_zero(GFP_KERNEL).unwrap();
///
/// assert!(mask.empty());
-/// mask.set(2);
-/// assert!(mask.test(2));
-/// mask.set(3);
-/// assert!(mask.test(3));
-/// assert_eq!(mask.weight(), 2);
+/// let mut count = 0;
+///
+/// let cpu2 = CpuId::from_u32(2);
+/// if let Some(cpu) = cpu2 {
+/// mask.set(cpu);
+/// assert!(mask.test(cpu));
+/// count += 1;
+/// }
+///
+/// let cpu3 = CpuId::from_u32(3);
+/// if let Some(cpu) = cpu3 {
+/// mask.set(cpu);
+/// assert!(mask.test(cpu));
+/// count += 1;
+/// }
+///
+/// assert_eq!(mask.weight(), count);
///
/// let mask2 = CpumaskVar::try_clone(&mask).unwrap();
-/// assert!(mask2.test(2));
-/// assert!(mask2.test(3));
-/// assert_eq!(mask2.weight(), 2);
+///
+/// if let Some(cpu) = cpu2 {
+/// assert!(mask2.test(cpu));
+/// }
+///
+/// if let Some(cpu) = cpu3 {
+/// assert!(mask2.test(cpu));
+/// }
+/// assert_eq!(mask2.weight(), count);
/// ```
pub struct CpumaskVar {
#[cfg(CONFIG_CPUMASK_OFFSTACK)]
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index dea06b79ecb5..5c946af3a4d5 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -195,10 +195,10 @@ impl<Ctx: DeviceContext> Device<Ctx> {
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_dev_printk(
- klevel as *const _ as *const crate::ffi::c_char,
+ klevel.as_ptr().cast::<crate::ffi::c_char>(),
self.as_raw(),
c_str!("%pA").as_char_ptr(),
- &msg as *const _ as *const crate::ffi::c_void,
+ core::ptr::from_ref(&msg).cast::<crate::ffi::c_void>(),
)
};
}
diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
index 0a4eb56d98f2..3dc72ca8cfc2 100644
--- a/rust/kernel/device_id.rs
+++ b/rust/kernel/device_id.rs
@@ -82,7 +82,7 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
unsafe {
raw_ids[i]
.as_mut_ptr()
- .byte_offset(T::DRIVER_DATA_OFFSET as _)
+ .byte_add(T::DRIVER_DATA_OFFSET)
.cast::<usize>()
.write(i);
}
@@ -136,7 +136,7 @@ impl<T: RawDeviceId, U, const N: usize> IdTable<T, U> for IdArray<T, U, N> {
fn as_ptr(&self) -> *const T::RawType {
// This cannot be `self.ids.as_ptr()`, as the return pointer must have correct provenance
// to access the sentinel.
- (self as *const Self).cast()
+ core::ptr::from_ref(self).cast()
}
fn id(&self, index: usize) -> &T::RawType {
diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
index 0f79a2ec9474..d0e6c6e162c2 100644
--- a/rust/kernel/devres.rs
+++ b/rust/kernel/devres.rs
@@ -12,26 +12,28 @@ use crate::{
error::{Error, Result},
ffi::c_void,
prelude::*,
- revocable::Revocable,
- sync::Arc,
+ revocable::{Revocable, RevocableGuard},
+ sync::{rcu, Arc, Completion},
types::ARef,
};
-use core::ops::Deref;
-
#[pin_data]
struct DevresInner<T> {
dev: ARef<Device>,
callback: unsafe extern "C" fn(*mut c_void),
#[pin]
data: Revocable<T>,
+ #[pin]
+ revoke: Completion,
}
/// This abstraction is meant to be used by subsystems to containerize [`Device`] bound resources to
/// manage their lifetime.
///
/// [`Device`] bound resources should be freed when either the resource goes out of scope or the
-/// [`Device`] is unbound respectively, depending on what happens first.
+/// [`Device`] is unbound respectively, depending on what happens first. In any case, it is always
+/// guaranteed that revoking the device resource is completed before the corresponding [`Device`]
+/// is unbound.
///
/// To achieve that [`Devres`] registers a devres callback on creation, which is called once the
/// [`Device`] is unbound, revoking access to the encapsulated resource (see also [`Revocable`]).
@@ -42,7 +44,7 @@ struct DevresInner<T> {
/// [`Devres`] users should make sure to simply free the corresponding backing resource in `T`'s
/// [`Drop`] implementation.
///
-/// # Example
+/// # Examples
///
/// ```no_run
/// # use kernel::{bindings, c_str, device::{Bound, Device}, devres::Devres, io::{Io, IoRaw}};
@@ -59,19 +61,19 @@ struct DevresInner<T> {
/// unsafe fn new(paddr: usize) -> Result<Self>{
/// // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
/// // valid for `ioremap`.
-/// let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
+/// let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
/// if addr.is_null() {
/// return Err(ENOMEM);
/// }
///
-/// Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
+/// Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
/// }
/// }
///
/// impl<const SIZE: usize> Drop for IoMem<SIZE> {
/// fn drop(&mut self) {
/// // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
-/// unsafe { bindings::iounmap(self.0.addr() as _); };
+/// unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
/// }
/// }
///
@@ -102,6 +104,7 @@ impl<T> DevresInner<T> {
dev: dev.into(),
callback: Self::devres_callback,
data <- Revocable::new(data),
+ revoke <- Completion::new(),
}),
flags,
)?;
@@ -112,8 +115,9 @@ impl<T> DevresInner<T> {
// SAFETY: `devm_add_action` guarantees to call `Self::devres_callback` once `dev` is
// detached.
- let ret =
- unsafe { bindings::devm_add_action(dev.as_raw(), Some(inner.callback), data as _) };
+ let ret = unsafe {
+ bindings::devm_add_action(dev.as_raw(), Some(inner.callback), data.cast_mut().cast())
+ };
if ret != 0 {
// SAFETY: We just created another reference to `inner` in order to pass it to
@@ -127,41 +131,48 @@ impl<T> DevresInner<T> {
}
fn as_ptr(&self) -> *const Self {
- self as _
+ self
}
- fn remove_action(this: &Arc<Self>) {
+ fn remove_action(this: &Arc<Self>) -> bool {
// SAFETY:
// - `self.inner.dev` is a valid `Device`,
// - the `action` and `data` pointers are the exact same ones as given to devm_add_action()
// previously,
// - `self` is always valid, even if the action has been released already.
- let ret = unsafe {
+ let success = unsafe {
bindings::devm_remove_action_nowarn(
this.dev.as_raw(),
Some(this.callback),
- this.as_ptr() as _,
+ this.as_ptr().cast_mut().cast(),
)
- };
+ } == 0;
- if ret == 0 {
+ if success {
// SAFETY: We leaked an `Arc` reference to devm_add_action() in `DevresInner::new`; if
// devm_remove_action_nowarn() was successful we can (and have to) claim back ownership
// of this reference.
let _ = unsafe { Arc::from_raw(this.as_ptr()) };
}
+
+ success
}
#[allow(clippy::missing_safety_doc)]
unsafe extern "C" fn devres_callback(ptr: *mut kernel::ffi::c_void) {
- let ptr = ptr as *mut DevresInner<T>;
+ let ptr = ptr.cast::<DevresInner<T>>();
// Devres owned this memory; now that we received the callback, drop the `Arc` and hence the
// reference.
// SAFETY: Safe, since we leaked an `Arc` reference to devm_add_action() in
// `DevresInner::new`.
let inner = unsafe { Arc::from_raw(ptr) };
- inner.data.revoke();
+ if !inner.data.revoke() {
+ // If `revoke()` returns false, it means that `Devres::drop` already started revoking
+ // `inner.data` for us. Hence we have to wait until `Devres::drop()` signals that it
+ // completed revoking `inner.data`.
+ inner.revoke.wait_for_completion();
+ }
}
}
@@ -192,7 +203,7 @@ impl<T> Devres<T> {
/// An error is returned if `dev` does not match the same [`Device`] this [`Devres`] instance
/// has been created with.
///
- /// # Example
+ /// # Examples
///
/// ```no_run
/// # #![cfg(CONFIG_PCI)]
@@ -218,20 +229,36 @@ impl<T> Devres<T> {
// SAFETY: `dev` being the same device as the device this `Devres` has been created for
// proves that `self.0.data` hasn't been revoked and is guaranteed to not be revoked as
// long as `dev` lives; `dev` lives at least as long as `self`.
- Ok(unsafe { self.deref().access() })
+ Ok(unsafe { self.0.data.access() })
+ }
+
+ /// [`Devres`] accessor for [`Revocable::try_access`].
+ pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> {
+ self.0.data.try_access()
}
-}
-impl<T> Deref for Devres<T> {
- type Target = Revocable<T>;
+ /// [`Devres`] accessor for [`Revocable::try_access_with`].
+ pub fn try_access_with<R, F: FnOnce(&T) -> R>(&self, f: F) -> Option<R> {
+ self.0.data.try_access_with(f)
+ }
- fn deref(&self) -> &Self::Target {
- &self.0.data
+ /// [`Devres`] accessor for [`Revocable::try_access_with_guard`].
+ pub fn try_access_with_guard<'a>(&'a self, guard: &'a rcu::Guard) -> Option<&'a T> {
+ self.0.data.try_access_with_guard(guard)
}
}
impl<T> Drop for Devres<T> {
fn drop(&mut self) {
- DevresInner::remove_action(&self.0);
+ // SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data
+ // anymore, hence it is safe not to wait for the grace period to finish.
+ if unsafe { self.0.data.revoke_nosync() } {
+ // We revoked `self.0.data` before the devres action did, hence try to remove it.
+ if !DevresInner::remove_action(&self.0) {
+ // We could not remove the devres action, which means that it now runs concurrently,
+ // hence signal that `self.0.data` has been revoked successfully.
+ self.0.revoke.complete_all();
+ }
+ }
}
}
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index a33261c62e0c..8e317005decd 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -38,7 +38,7 @@ pub struct Attrs(u32);
impl Attrs {
/// Get the raw representation of this attribute.
pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
- self.0 as _
+ self.0 as crate::ffi::c_ulong
}
/// Check whether `flags` is contained in `self`.
@@ -186,7 +186,7 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
dev: dev.into(),
dma_handle,
count,
- cpu_addr: ret as *mut T,
+ cpu_addr: ret.cast::<T>(),
dma_attrs,
})
}
@@ -293,7 +293,7 @@ impl<T: AsBytes + FromBytes> Drop for CoherentAllocation<T> {
bindings::dma_free_attrs(
self.dev.as_raw(),
size,
- self.cpu_addr as _,
+ self.cpu_addr.cast(),
self.dma_handle,
self.dma_attrs.as_raw(),
)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 624d7a4c83ea..b7ee3c464a12 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -83,13 +83,13 @@ impl<T: drm::Driver> Device<T> {
major: T::INFO.major,
minor: T::INFO.minor,
patchlevel: T::INFO.patchlevel,
- name: T::INFO.name.as_char_ptr() as *mut _,
- desc: T::INFO.desc.as_char_ptr() as *mut _,
+ name: T::INFO.name.as_char_ptr().cast_mut(),
+ desc: T::INFO.desc.as_char_ptr().cast_mut(),
driver_features: drm::driver::FEAT_GEM,
ioctls: T::IOCTLS.as_ptr(),
num_ioctls: T::IOCTLS.len() as i32,
- fops: &Self::GEM_FOPS as _,
+ fops: &Self::GEM_FOPS,
};
const GEM_FOPS: bindings::file_operations = drm::gem::create_fops();
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index 3dee3139fcd4..6277af1c1baa 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -153,7 +153,7 @@ impl Error {
/// Returns the error encoded as a pointer.
pub fn to_ptr<T>(self) -> *mut T {
// SAFETY: `self.0` is a valid error due to its invariant.
- unsafe { bindings::ERR_PTR(self.0.get() as _) as *mut _ }
+ unsafe { bindings::ERR_PTR(self.0.get() as crate::ffi::c_long).cast() }
}
/// Returns a string representing the error, if one exists.
diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs
index 2494c96e105f..be684e860ed2 100644
--- a/rust/kernel/firmware.rs
+++ b/rust/kernel/firmware.rs
@@ -62,10 +62,11 @@ impl Firmware {
fn request_internal(name: &CStr, dev: &Device, func: FwFunc) -> Result<Self> {
let mut fw: *mut bindings::firmware = core::ptr::null_mut();
let pfw: *mut *mut bindings::firmware = &mut fw;
+ let pfw: *mut *const bindings::firmware = pfw.cast();
// SAFETY: `pfw` is a valid pointer to a NULL initialized `bindings::firmware` pointer.
// `name` and `dev` are valid as by their type invariants.
- let ret = unsafe { func.0(pfw as _, name.as_char_ptr(), dev.as_raw()) };
+ let ret = unsafe { func.0(pfw, name.as_char_ptr(), dev.as_raw()) };
if ret != 0 {
return Err(Error::from_errno(ret));
}
@@ -139,7 +140,7 @@ unsafe impl Sync for Firmware {}
/// Typically, such contracts would be enforced by a trait, however traits do not (yet) support
/// const functions.
///
-/// # Example
+/// # Examples
///
/// ```
/// # mod module_firmware_test {
@@ -181,7 +182,7 @@ unsafe impl Sync for Firmware {}
/// module! {
/// type: MyModule,
/// name: "module_firmware_test",
-/// author: "Rust for Linux",
+/// authors: ["Rust for Linux"],
/// description: "module_firmware! test module",
/// license: "GPL",
/// }
@@ -261,7 +262,7 @@ impl<const N: usize> ModInfoBuilder<N> {
/// Append path components to the [`ModInfoBuilder`] instance. Paths need to be separated
/// with [`ModInfoBuilder::new_entry`].
///
- /// # Example
+ /// # Examples
///
/// ```
/// use kernel::firmware::ModInfoBuilder;
diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs
index 72d84fb0e266..35fd5db35c46 100644
--- a/rust/kernel/fs/file.rs
+++ b/rust/kernel/fs/file.rs
@@ -366,7 +366,7 @@ impl core::ops::Deref for File {
//
// By the type invariants, there are no `fdget_pos` calls that did not take the
// `f_pos_lock` mutex.
- unsafe { LocalFile::from_raw_file(self as *const File as *const bindings::file) }
+ unsafe { LocalFile::from_raw_file(core::ptr::from_ref(self).cast()) }
}
}
diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
index 72d80a6f131e..bd4d720be165 100644
--- a/rust/kernel/io.rs
+++ b/rust/kernel/io.rs
@@ -5,7 +5,7 @@
//! C header: [`include/asm-generic/io.h`](srctree/include/asm-generic/io.h)
use crate::error::{code::EINVAL, Result};
-use crate::{bindings, build_assert};
+use crate::{bindings, build_assert, ffi::c_void};
/// Raw representation of an MMIO region.
///
@@ -43,7 +43,7 @@ impl<const SIZE: usize> IoRaw<SIZE> {
}
}
-/// IO-mapped memory, starting at the base address @addr and spanning @maxlen bytes.
+/// IO-mapped memory region.
///
/// The creator (usually a subsystem / bus such as PCI) is responsible for creating the
/// mapping, performing an additional region request etc.
@@ -56,7 +56,7 @@ impl<const SIZE: usize> IoRaw<SIZE> {
/// # Examples
///
/// ```no_run
-/// # use kernel::{bindings, io::{Io, IoRaw}};
+/// # use kernel::{bindings, ffi::c_void, io::{Io, IoRaw}};
/// # use core::ops::Deref;
///
/// // See also [`pci::Bar`] for a real example.
@@ -70,19 +70,19 @@ impl<const SIZE: usize> IoRaw<SIZE> {
/// unsafe fn new(paddr: usize) -> Result<Self>{
/// // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
/// // valid for `ioremap`.
-/// let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
+/// let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
/// if addr.is_null() {
/// return Err(ENOMEM);
/// }
///
-/// Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
+/// Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
/// }
/// }
///
/// impl<const SIZE: usize> Drop for IoMem<SIZE> {
/// fn drop(&mut self) {
/// // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
-/// unsafe { bindings::iounmap(self.0.addr() as _); };
+/// unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
/// }
/// }
///
@@ -119,7 +119,7 @@ macro_rules! define_read {
let addr = self.io_addr_assert::<$type_name>(offset);
// SAFETY: By the type invariant `addr` is a valid address for MMIO operations.
- unsafe { bindings::$c_fn(addr as _) }
+ unsafe { bindings::$c_fn(addr as *const c_void) }
}
/// Read IO data from a given offset.
@@ -131,7 +131,7 @@ macro_rules! define_read {
let addr = self.io_addr::<$type_name>(offset)?;
// SAFETY: By the type invariant `addr` is a valid address for MMIO operations.
- Ok(unsafe { bindings::$c_fn(addr as _) })
+ Ok(unsafe { bindings::$c_fn(addr as *const c_void) })
}
};
}
@@ -148,7 +148,7 @@ macro_rules! define_write {
let addr = self.io_addr_assert::<$type_name>(offset);
// SAFETY: By the type invariant `addr` is a valid address for MMIO operations.
- unsafe { bindings::$c_fn(value, addr as _, ) }
+ unsafe { bindings::$c_fn(value, addr as *mut c_void) }
}
/// Write IO data from a given offset.
@@ -160,7 +160,7 @@ macro_rules! define_write {
let addr = self.io_addr::<$type_name>(offset)?;
// SAFETY: By the type invariant `addr` is a valid address for MMIO operations.
- unsafe { bindings::$c_fn(value, addr as _) }
+ unsafe { bindings::$c_fn(value, addr as *mut c_void) }
Ok(())
}
};
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 4b8cdcb21e77..099a61bbb8f4 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -7,7 +7,10 @@
//! Reference: <https://docs.kernel.org/dev-tools/kunit/index.html>
use crate::prelude::*;
-use core::{ffi::c_void, fmt};
+use core::fmt;
+
+#[cfg(CONFIG_PRINTK)]
+use crate::c_str;
/// Prints a KUnit error-level message.
///
@@ -19,8 +22,8 @@ pub fn err(args: fmt::Arguments<'_>) {
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_printk(
- c"\x013%pA".as_ptr() as _,
- &args as *const _ as *const c_void,
+ c_str!("\x013%pA").as_char_ptr(),
+ core::ptr::from_ref(&args).cast::<c_void>(),
);
}
}
@@ -35,8 +38,8 @@ pub fn info(args: fmt::Arguments<'_>) {
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_printk(
- c"\x016%pA".as_ptr() as _,
- &args as *const _ as *const c_void,
+ c_str!("\x016%pA").as_char_ptr(),
+ core::ptr::from_ref(&args).cast::<c_void>(),
);
}
}
diff --git a/rust/kernel/list.rs b/rust/kernel/list.rs
index c391c30b80f8..fe58a3920e70 100644
--- a/rust/kernel/list.rs
+++ b/rust/kernel/list.rs
@@ -82,9 +82,9 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField};
/// // [15, 10, 30]
/// {
/// let mut iter = list.iter();
-/// assert_eq!(iter.next().unwrap().value, 15);
-/// assert_eq!(iter.next().unwrap().value, 10);
-/// assert_eq!(iter.next().unwrap().value, 30);
+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 15);
+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 10);
+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 30);
/// assert!(iter.next().is_none());
///
/// // Verify the length of the list.
@@ -93,9 +93,9 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField};
///
/// // Pop the items from the list using `pop_back()` and verify the content.
/// {
-/// assert_eq!(list.pop_back().unwrap().value, 30);
-/// assert_eq!(list.pop_back().unwrap().value, 10);
-/// assert_eq!(list.pop_back().unwrap().value, 15);
+/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value, 30);
+/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value, 10);
+/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value, 15);
/// }
///
/// // Insert 3 elements using `push_front()`.
@@ -107,9 +107,9 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField};
/// // [30, 10, 15]
/// {
/// let mut iter = list.iter();
-/// assert_eq!(iter.next().unwrap().value, 30);
-/// assert_eq!(iter.next().unwrap().value, 10);
-/// assert_eq!(iter.next().unwrap().value, 15);
+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 30);
+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 10);
+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 15);
/// assert!(iter.next().is_none());
///
/// // Verify the length of the list.
@@ -118,8 +118,8 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField};
///
/// // Pop the items from the list using `pop_front()` and verify the content.
/// {
-/// assert_eq!(list.pop_front().unwrap().value, 30);
-/// assert_eq!(list.pop_front().unwrap().value, 10);
+/// assert_eq!(list.pop_front().ok_or(EINVAL)?.value, 30);
+/// assert_eq!(list.pop_front().ok_or(EINVAL)?.value, 10);
/// }
///
/// // Push `list2` to `list` through `push_all_back()`.
@@ -135,9 +135,9 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField};
/// // list: [15, 25, 35]
/// // list2: []
/// let mut iter = list.iter();
-/// assert_eq!(iter.next().unwrap().value, 15);
-/// assert_eq!(iter.next().unwrap().value, 25);
-/// assert_eq!(iter.next().unwrap().value, 35);
+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 15);
+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 25);
+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 35);
/// assert!(iter.next().is_none());
/// assert!(list2.is_empty());
/// }
@@ -809,11 +809,11 @@ impl<'a, T: ?Sized + ListItem<ID>, const ID: u64> Iterator for Iter<'a, T, ID> {
/// merge_sorted(&mut list, list2);
///
/// let mut items = list.into_iter();
-/// assert_eq!(items.next().unwrap().value, 10);
-/// assert_eq!(items.next().unwrap().value, 11);
-/// assert_eq!(items.next().unwrap().value, 12);
-/// assert_eq!(items.next().unwrap().value, 13);
-/// assert_eq!(items.next().unwrap().value, 14);
+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 10);
+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 11);
+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 12);
+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 13);
+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 14);
/// assert!(items.next().is_none());
/// # Result::<(), Error>::Ok(())
/// ```
diff --git a/rust/kernel/list/impl_list_item_mod.rs b/rust/kernel/list/impl_list_item_mod.rs
index a0438537cee1..1f9498c1458f 100644
--- a/rust/kernel/list/impl_list_item_mod.rs
+++ b/rust/kernel/list/impl_list_item_mod.rs
@@ -34,7 +34,7 @@ pub unsafe trait HasListLinks<const ID: u64 = 0> {
unsafe fn raw_get_list_links(ptr: *mut Self) -> *mut ListLinks<ID> {
// SAFETY: The caller promises that the pointer is valid. The implementer promises that the
// `OFFSET` constant is correct.
- unsafe { (ptr as *mut u8).add(Self::OFFSET) as *mut ListLinks<ID> }
+ unsafe { ptr.cast::<u8>().add(Self::OFFSET).cast() }
}
}
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index 939278bc7b03..288f40e79906 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -34,7 +34,7 @@ impl MiscDeviceOptions {
pub const fn into_raw<T: MiscDevice>(self) -> bindings::miscdevice {
// SAFETY: All zeros is valid for this C type.
let mut result: bindings::miscdevice = unsafe { MaybeUninit::zeroed().assume_init() };
- result.minor = bindings::MISC_DYNAMIC_MINOR as _;
+ result.minor = bindings::MISC_DYNAMIC_MINOR as ffi::c_int;
result.name = self.name.as_char_ptr();
result.fops = MiscdeviceVTable::<T>::build();
result
diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs
index 31803674aecc..6086ca981b06 100644
--- a/rust/kernel/mm/virt.rs
+++ b/rust/kernel/mm/virt.rs
@@ -392,80 +392,80 @@ pub mod flags {
use crate::bindings;
/// No flags are set.
- pub const NONE: vm_flags_t = bindings::VM_NONE as _;
+ pub const NONE: vm_flags_t = bindings::VM_NONE as vm_flags_t;
/// Mapping allows reads.
- pub const READ: vm_flags_t = bindings::VM_READ as _;
+ pub const READ: vm_flags_t = bindings::VM_READ as vm_flags_t;
/// Mapping allows writes.
- pub const WRITE: vm_flags_t = bindings::VM_WRITE as _;
+ pub const WRITE: vm_flags_t = bindings::VM_WRITE as vm_flags_t;
/// Mapping allows execution.
- pub const EXEC: vm_flags_t = bindings::VM_EXEC as _;
+ pub const EXEC: vm_flags_t = bindings::VM_EXEC as vm_flags_t;
/// Mapping is shared.
- pub const SHARED: vm_flags_t = bindings::VM_SHARED as _;
+ pub const SHARED: vm_flags_t = bindings::VM_SHARED as vm_flags_t;
/// Mapping may be updated to allow reads.
- pub const MAYREAD: vm_flags_t = bindings::VM_MAYREAD as _;
+ pub const MAYREAD: vm_flags_t = bindings::VM_MAYREAD as vm_flags_t;
/// Mapping may be updated to allow writes.
- pub const MAYWRITE: vm_flags_t = bindings::VM_MAYWRITE as _;
+ pub const MAYWRITE: vm_flags_t = bindings::VM_MAYWRITE as vm_flags_t;
/// Mapping may be updated to allow execution.
- pub const MAYEXEC: vm_flags_t = bindings::VM_MAYEXEC as _;
+ pub const MAYEXEC: vm_flags_t = bindings::VM_MAYEXEC as vm_flags_t;
/// Mapping may be updated to be shared.
- pub const MAYSHARE: vm_flags_t = bindings::VM_MAYSHARE as _;
+ pub const MAYSHARE: vm_flags_t = bindings::VM_MAYSHARE as vm_flags_t;
/// Page-ranges managed without `struct page`, just pure PFN.
- pub const PFNMAP: vm_flags_t = bindings::VM_PFNMAP as _;
+ pub const PFNMAP: vm_flags_t = bindings::VM_PFNMAP as vm_flags_t;
/// Memory mapped I/O or similar.
- pub const IO: vm_flags_t = bindings::VM_IO as _;
+ pub const IO: vm_flags_t = bindings::VM_IO as vm_flags_t;
/// Do not copy this vma on fork.
- pub const DONTCOPY: vm_flags_t = bindings::VM_DONTCOPY as _;
+ pub const DONTCOPY: vm_flags_t = bindings::VM_DONTCOPY as vm_flags_t;
/// Cannot expand with mremap().
- pub const DONTEXPAND: vm_flags_t = bindings::VM_DONTEXPAND as _;
+ pub const DONTEXPAND: vm_flags_t = bindings::VM_DONTEXPAND as vm_flags_t;
/// Lock the pages covered when they are faulted in.
- pub const LOCKONFAULT: vm_flags_t = bindings::VM_LOCKONFAULT as _;
+ pub const LOCKONFAULT: vm_flags_t = bindings::VM_LOCKONFAULT as vm_flags_t;
/// Is a VM accounted object.
- pub const ACCOUNT: vm_flags_t = bindings::VM_ACCOUNT as _;
+ pub const ACCOUNT: vm_flags_t = bindings::VM_ACCOUNT as vm_flags_t;
/// Should the VM suppress accounting.
- pub const NORESERVE: vm_flags_t = bindings::VM_NORESERVE as _;
+ pub const NORESERVE: vm_flags_t = bindings::VM_NORESERVE as vm_flags_t;
/// Huge TLB Page VM.
- pub const HUGETLB: vm_flags_t = bindings::VM_HUGETLB as _;
+ pub const HUGETLB: vm_flags_t = bindings::VM_HUGETLB as vm_flags_t;
/// Synchronous page faults. (DAX-specific)
- pub const SYNC: vm_flags_t = bindings::VM_SYNC as _;
+ pub const SYNC: vm_flags_t = bindings::VM_SYNC as vm_flags_t;
/// Architecture-specific flag.
- pub const ARCH_1: vm_flags_t = bindings::VM_ARCH_1 as _;
+ pub const ARCH_1: vm_flags_t = bindings::VM_ARCH_1 as vm_flags_t;
/// Wipe VMA contents in child on fork.
- pub const WIPEONFORK: vm_flags_t = bindings::VM_WIPEONFORK as _;
+ pub const WIPEONFORK: vm_flags_t = bindings::VM_WIPEONFORK as vm_flags_t;
/// Do not include in the core dump.
- pub const DONTDUMP: vm_flags_t = bindings::VM_DONTDUMP as _;
+ pub const DONTDUMP: vm_flags_t = bindings::VM_DONTDUMP as vm_flags_t;
/// Not soft dirty clean area.
- pub const SOFTDIRTY: vm_flags_t = bindings::VM_SOFTDIRTY as _;
+ pub const SOFTDIRTY: vm_flags_t = bindings::VM_SOFTDIRTY as vm_flags_t;
/// Can contain `struct page` and pure PFN pages.
- pub const MIXEDMAP: vm_flags_t = bindings::VM_MIXEDMAP as _;
+ pub const MIXEDMAP: vm_flags_t = bindings::VM_MIXEDMAP as vm_flags_t;
/// MADV_HUGEPAGE marked this vma.
- pub const HUGEPAGE: vm_flags_t = bindings::VM_HUGEPAGE as _;
+ pub const HUGEPAGE: vm_flags_t = bindings::VM_HUGEPAGE as vm_flags_t;
/// MADV_NOHUGEPAGE marked this vma.
- pub const NOHUGEPAGE: vm_flags_t = bindings::VM_NOHUGEPAGE as _;
+ pub const NOHUGEPAGE: vm_flags_t = bindings::VM_NOHUGEPAGE as vm_flags_t;
/// KSM may merge identical pages.
- pub const MERGEABLE: vm_flags_t = bindings::VM_MERGEABLE as _;
+ pub const MERGEABLE: vm_flags_t = bindings::VM_MERGEABLE as vm_flags_t;
}
diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index 32ea43ece646..65ac4d59ad77 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -142,7 +142,7 @@ impl Device {
// SAFETY: The struct invariant ensures that we may access
// this field without additional synchronization.
let bit_field = unsafe { &(*self.0.get())._bitfield_1 };
- bit_field.get(13, 1) == bindings::AUTONEG_ENABLE as u64
+ bit_field.get(13, 1) == u64::from(bindings::AUTONEG_ENABLE)
}
/// Gets the current auto-negotiation state.
@@ -427,7 +427,7 @@ impl<T: Driver> Adapter<T> {
// where we hold `phy_device->lock`, so the accessors on
// `Device` are okay to call.
let dev = unsafe { Device::from_raw(phydev) };
- T::match_phy_device(dev) as i32
+ T::match_phy_device(dev).into()
}
/// # Safety
diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs
index 04f2d8ef29cb..40d1bd13682c 100644
--- a/rust/kernel/of.rs
+++ b/rust/kernel/of.rs
@@ -22,7 +22,7 @@ unsafe impl RawDeviceId for DeviceId {
const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::of_device_id, data);
fn index(&self) -> usize {
- self.0.data as _
+ self.0.data as usize
}
}
@@ -34,10 +34,10 @@ impl DeviceId {
// SAFETY: FFI type is valid to be zero-initialized.
let mut of: bindings::of_device_id = unsafe { core::mem::zeroed() };
- // TODO: Use `clone_from_slice` once the corresponding types do match.
+ // TODO: Use `copy_from_slice` once stabilized for `const`.
let mut i = 0;
while i < src.len() {
- of.compatible[i] = src[i] as _;
+ of.compatible[i] = src[i];
i += 1;
}
diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
index a566fc3e7dcb..0e94cb2703ec 100644
--- a/rust/kernel/opp.rs
+++ b/rust/kernel/opp.rs
@@ -92,7 +92,7 @@ fn to_c_str_array(names: &[CString]) -> Result<KVec<*const u8>> {
let mut list = KVec::with_capacity(names.len() + 1, GFP_KERNEL)?;
for name in names.iter() {
- list.push(name.as_ptr() as _, GFP_KERNEL)?;
+ list.push(name.as_ptr().cast(), GFP_KERNEL)?;
}
list.push(ptr::null(), GFP_KERNEL)?;
@@ -103,7 +103,7 @@ fn to_c_str_array(names: &[CString]) -> Result<KVec<*const u8>> {
///
/// Represents voltage in microvolts, wrapping a [`c_ulong`] value.
///
-/// ## Examples
+/// # Examples
///
/// ```
/// use kernel::opp::MicroVolt;
@@ -128,7 +128,7 @@ impl From<MicroVolt> for c_ulong {
///
/// Represents power in microwatts, wrapping a [`c_ulong`] value.
///
-/// ## Examples
+/// # Examples
///
/// ```
/// use kernel::opp::MicroWatt;
@@ -153,7 +153,7 @@ impl From<MicroWatt> for c_ulong {
///
/// The associated [`OPP`] is automatically removed when the [`Token`] is dropped.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to create an [`OPP`] dynamically.
///
@@ -202,7 +202,7 @@ impl Drop for Token {
/// Rust abstraction for the C `struct dev_pm_opp_data`, used to define operating performance
/// points (OPPs) dynamically.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to create an [`OPP`] with [`Data`].
///
@@ -254,7 +254,7 @@ impl Data {
/// [`OPP`] search options.
///
-/// ## Examples
+/// # Examples
///
/// Defines how to search for an [`OPP`] in a [`Table`] relative to a frequency.
///
@@ -326,7 +326,7 @@ impl Drop for ConfigToken {
///
/// Rust abstraction for the C `struct dev_pm_opp_config`.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to set OPP property-name configuration for a [`Device`].
///
@@ -569,7 +569,7 @@ impl<T: ConfigOps + Default> Config<T> {
///
/// Instances of this type are reference-counted.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to get OPP [`Table`] for a [`Cpumask`] and set its
/// frequency.
@@ -1011,7 +1011,7 @@ impl Drop for Table {
///
/// A reference to the [`OPP`], &[`OPP`], isn't refcounted by the Rust code.
///
-/// ## Examples
+/// # Examples
///
/// The following example demonstrates how to get [`OPP`] corresponding to a frequency value and
/// configure the device with it.
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 8435f8132e38..6b94fd7a3ce9 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -78,7 +78,7 @@ impl<T: Driver + 'static> Adapter<T> {
// Let the `struct pci_dev` own a reference of the driver's private data.
// SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a
// `struct pci_dev`.
- unsafe { bindings::pci_set_drvdata(pdev.as_raw(), data.into_foreign() as _) };
+ unsafe { bindings::pci_set_drvdata(pdev.as_raw(), data.into_foreign().cast()) };
}
Err(err) => return Error::to_errno(err),
}
@@ -100,7 +100,7 @@ impl<T: Driver + 'static> Adapter<T> {
/// Declares a kernel module that exposes a single PCI driver.
///
-/// # Example
+/// # Examples
///
///```ignore
/// kernel::module_pci_driver! {
@@ -171,7 +171,7 @@ unsafe impl RawDeviceId for DeviceId {
const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::pci_device_id, driver_data);
fn index(&self) -> usize {
- self.0.driver_data as _
+ self.0.driver_data
}
}
@@ -194,7 +194,7 @@ macro_rules! pci_device_table {
/// The PCI driver trait.
///
-/// # Example
+/// # Examples
///
///```
/// # use kernel::{bindings, device::Core, pci};
@@ -206,7 +206,10 @@ macro_rules! pci_device_table {
/// MODULE_PCI_TABLE,
/// <MyDriver as pci::Driver>::IdInfo,
/// [
-/// (pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, bindings::PCI_ANY_ID as _), ())
+/// (
+/// pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, bindings::PCI_ANY_ID as u32),
+/// (),
+/// )
/// ]
/// );
///
@@ -330,7 +333,7 @@ impl<const SIZE: usize> Bar<SIZE> {
// `ioptr` is valid by the safety requirements.
// `num` is valid by the safety requirements.
unsafe {
- bindings::pci_iounmap(pdev.as_raw(), ioptr as _);
+ bindings::pci_iounmap(pdev.as_raw(), ioptr as *mut kernel::ffi::c_void);
bindings::pci_release_region(pdev.as_raw(), num);
}
}
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 5b21fa517e55..0a6a6be732b2 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -69,7 +69,9 @@ impl<T: Driver + 'static> Adapter<T> {
// Let the `struct platform_device` own a reference of the driver's private data.
// SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a
// `struct platform_device`.
- unsafe { bindings::platform_set_drvdata(pdev.as_raw(), data.into_foreign() as _) };
+ unsafe {
+ bindings::platform_set_drvdata(pdev.as_raw(), data.into_foreign().cast())
+ };
}
Err(err) => return Error::to_errno(err),
}
@@ -120,7 +122,7 @@ macro_rules! module_platform_driver {
///
/// Drivers must implement this trait in order to get a platform driver registered.
///
-/// # Example
+/// # Examples
///
///```
/// # use kernel::{bindings, c_str, device::Core, of, platform};
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index 9783d960a97a..ecdcee43e5a5 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -25,7 +25,7 @@ unsafe extern "C" fn rust_fmt_argument(
// SAFETY: The C contract guarantees that `buf` is valid if it's less than `end`.
let mut w = unsafe { RawFormatter::from_ptrs(buf.cast(), end.cast()) };
// SAFETY: TODO.
- let _ = w.write_fmt(unsafe { *(ptr as *const fmt::Arguments<'_>) });
+ let _ = w.write_fmt(unsafe { *ptr.cast::<fmt::Arguments<'_>>() });
w.pos().cast()
}
@@ -109,7 +109,7 @@ pub unsafe fn call_printk(
bindings::_printk(
format_string.as_ptr(),
module_name.as_ptr(),
- &args as *const _ as *const c_void,
+ core::ptr::from_ref(&args).cast::<c_void>(),
);
}
}
@@ -129,7 +129,7 @@ pub fn call_printk_cont(args: fmt::Arguments<'_>) {
unsafe {
bindings::_printk(
format_strings::CONT.as_ptr(),
- &args as *const _ as *const c_void,
+ core::ptr::from_ref(&args).cast::<c_void>(),
);
}
}
diff --git a/rust/kernel/rbtree.rs b/rust/kernel/rbtree.rs
index 8d978c896747..9457134eb3af 100644
--- a/rust/kernel/rbtree.rs
+++ b/rust/kernel/rbtree.rs
@@ -191,6 +191,12 @@ impl<K, V> RBTree<K, V> {
}
}
+ /// Returns true if this tree is empty.
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.root.rb_node.is_null()
+ }
+
/// Returns an iterator over the tree nodes, sorted by key.
pub fn iter(&self) -> Iter<'_, K, V> {
Iter {
diff --git a/rust/kernel/revocable.rs b/rust/kernel/revocable.rs
index db4aa46bb121..1cd4511f0260 100644
--- a/rust/kernel/revocable.rs
+++ b/rust/kernel/revocable.rs
@@ -154,8 +154,10 @@ impl<T> Revocable<T> {
/// # Safety
///
/// Callers must ensure that there are no more concurrent users of the revocable object.
- unsafe fn revoke_internal<const SYNC: bool>(&self) {
- if self.is_available.swap(false, Ordering::Relaxed) {
+ unsafe fn revoke_internal<const SYNC: bool>(&self) -> bool {
+ let revoke = self.is_available.swap(false, Ordering::Relaxed);
+
+ if revoke {
if SYNC {
// SAFETY: Just an FFI call, there are no further requirements.
unsafe { bindings::synchronize_rcu() };
@@ -165,6 +167,8 @@ impl<T> Revocable<T> {
// `compare_exchange` above that takes `is_available` from `true` to `false`.
unsafe { drop_in_place(self.data.get()) };
}
+
+ revoke
}
/// Revokes access to and drops the wrapped object.
@@ -172,10 +176,13 @@ impl<T> Revocable<T> {
/// Access to the object is revoked immediately to new callers of [`Revocable::try_access`],
/// expecting that there are no concurrent users of the object.
///
+ /// Returns `true` if `&self` has been revoked with this call, `false` if it was revoked
+ /// already.
+ ///
/// # Safety
///
/// Callers must ensure that there are no more concurrent users of the revocable object.
- pub unsafe fn revoke_nosync(&self) {
+ pub unsafe fn revoke_nosync(&self) -> bool {
// SAFETY: By the safety requirement of this function, the caller ensures that nobody is
// accessing the data anymore and hence we don't have to wait for the grace period to
// finish.
@@ -189,7 +196,10 @@ impl<T> Revocable<T> {
/// If there are concurrent users of the object (i.e., ones that called
/// [`Revocable::try_access`] beforehand and still haven't dropped the returned guard), this
/// function waits for the concurrent access to complete before dropping the wrapped object.
- pub fn revoke(&self) {
+ ///
+ /// Returns `true` if `&self` has been revoked with this call, `false` if it was revoked
+ /// already.
+ pub fn revoke(&self) -> bool {
// SAFETY: By passing `true` we ask `revoke_internal` to wait for the grace period to
// finish.
unsafe { self.revoke_internal::<true>() }
@@ -221,6 +231,10 @@ impl<T> PinnedDrop for Revocable<T> {
///
/// The RCU read-side lock is held while the guard is alive.
pub struct RevocableGuard<'a, T> {
+ // This can't use the `&'a T` type because references that appear in function arguments must
+ // not become dangling during the execution of the function, which can happen if the
+ // `RevocableGuard` is passed as a function argument and then dropped during execution of the
+ // function.
data_ref: *const T,
_rcu_guard: rcu::Guard,
_p: PhantomData<&'a ()>,
diff --git a/rust/kernel/seq_file.rs b/rust/kernel/seq_file.rs
index 7a9403eb6e5b..8f199b1a3bb1 100644
--- a/rust/kernel/seq_file.rs
+++ b/rust/kernel/seq_file.rs
@@ -37,7 +37,7 @@ impl SeqFile {
bindings::seq_printf(
self.inner.get(),
c_str!("%pA").as_char_ptr(),
- &args as *const _ as *const crate::ffi::c_void,
+ core::ptr::from_ref(&args).cast::<crate::ffi::c_void>(),
);
}
}
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index a927db8e079c..cbc8b459ed41 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -29,7 +29,7 @@ impl BStr {
#[inline]
pub const fn from_bytes(bytes: &[u8]) -> &Self {
// SAFETY: `BStr` is transparent to `[u8]`.
- unsafe { &*(bytes as *const [u8] as *const BStr) }
+ unsafe { &*(core::ptr::from_ref(bytes) as *const BStr) }
}
/// Strip a prefix from `self`. Delegates to [`slice::strip_prefix`].
@@ -237,7 +237,7 @@ impl CStr {
// to a `NUL`-terminated C string.
let len = unsafe { bindings::strlen(ptr) } + 1;
// SAFETY: Lifetime guaranteed by the safety precondition.
- let bytes = unsafe { core::slice::from_raw_parts(ptr as _, len) };
+ let bytes = unsafe { core::slice::from_raw_parts(ptr.cast(), len) };
// SAFETY: As `len` is returned by `strlen`, `bytes` does not contain interior `NUL`.
// As we have added 1 to `len`, the last byte is known to be `NUL`.
unsafe { Self::from_bytes_with_nul_unchecked(bytes) }
@@ -290,7 +290,7 @@ impl CStr {
#[inline]
pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &mut [u8]) -> &mut CStr {
// SAFETY: Properties of `bytes` guaranteed by the safety precondition.
- unsafe { &mut *(bytes as *mut [u8] as *mut CStr) }
+ unsafe { &mut *(core::ptr::from_mut(bytes) as *mut CStr) }
}
/// Returns a C pointer to the string.
@@ -728,9 +728,9 @@ impl RawFormatter {
pub(crate) unsafe fn from_ptrs(pos: *mut u8, end: *mut u8) -> Self {
// INVARIANT: The safety requirements guarantee the type invariants.
Self {
- beg: pos as _,
- pos: pos as _,
- end: end as _,
+ beg: pos as usize,
+ pos: pos as usize,
+ end: end as usize,
}
}
@@ -755,7 +755,7 @@ impl RawFormatter {
///
/// N.B. It may point to invalid memory.
pub(crate) fn pos(&self) -> *mut u8 {
- self.pos as _
+ self.pos as *mut u8
}
/// Returns the number of bytes written to the formatter.
diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index 36a719015583..63c99e015ad6 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -10,6 +10,7 @@ use crate::types::Opaque;
use pin_init;
mod arc;
+pub mod completion;
mod condvar;
pub mod lock;
mod locked_by;
@@ -17,6 +18,7 @@ pub mod poll;
pub mod rcu;
pub use arc::{Arc, ArcBorrow, UniqueArc};
+pub use completion::Completion;
pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult};
pub use lock::global::{global_lock, GlobalGuard, GlobalLock, GlobalLockBackend, GlobalLockedBy};
pub use lock::mutex::{new_mutex, Mutex, MutexGuard};
@@ -39,7 +41,7 @@ impl LockClassKey {
/// Initializes a dynamically allocated lock class key. In the common case of using a
/// statically allocated lock class key, the static_lock_class! macro should be used instead.
///
- /// # Example
+ /// # Examples
/// ```
/// # use kernel::c_str;
/// # use kernel::alloc::KBox;
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index c7af0aa48a0a..499175f637a7 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -25,6 +25,7 @@ use crate::{
};
use core::{
alloc::Layout,
+ borrow::{Borrow, BorrowMut},
fmt,
marker::PhantomData,
mem::{ManuallyDrop, MaybeUninit},
@@ -406,7 +407,7 @@ unsafe impl<T: 'static> ForeignOwnable for Arc<T> {
unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> ArcBorrow<'a, T> {
// SAFETY: The safety requirements for `borrow_mut` are a superset of the safety
// requirements for `borrow`.
- unsafe { Self::borrow(ptr) }
+ unsafe { <Self as ForeignOwnable>::borrow(ptr) }
}
}
@@ -426,6 +427,31 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
}
}
+/// # Examples
+///
+/// ```
+/// # use core::borrow::Borrow;
+/// # use kernel::sync::Arc;
+/// struct Foo<B: Borrow<u32>>(B);
+///
+/// // Owned instance.
+/// let owned = Foo(1);
+///
+/// // Shared instance.
+/// let arc = Arc::new(1, GFP_KERNEL)?;
+/// let shared = Foo(arc.clone());
+///
+/// let i = 1;
+/// // Borrowed from `i`.
+/// let borrowed = Foo(&i);
+/// # Ok::<(), Error>(())
+/// ```
+impl<T: ?Sized> Borrow<T> for Arc<T> {
+ fn borrow(&self) -> &T {
+ self.deref()
+ }
+}
+
impl<T: ?Sized> Clone for Arc<T> {
fn clone(&self) -> Self {
// SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
@@ -834,6 +860,56 @@ impl<T: ?Sized> DerefMut for UniqueArc<T> {
}
}
+/// # Examples
+///
+/// ```
+/// # use core::borrow::Borrow;
+/// # use kernel::sync::UniqueArc;
+/// struct Foo<B: Borrow<u32>>(B);
+///
+/// // Owned instance.
+/// let owned = Foo(1);
+///
+/// // Owned instance using `UniqueArc`.
+/// let arc = UniqueArc::new(1, GFP_KERNEL)?;
+/// let shared = Foo(arc);
+///
+/// let i = 1;
+/// // Borrowed from `i`.
+/// let borrowed = Foo(&i);
+/// # Ok::<(), Error>(())
+/// ```
+impl<T: ?Sized> Borrow<T> for UniqueArc<T> {
+ fn borrow(&self) -> &T {
+ self.deref()
+ }
+}
+
+/// # Examples
+///
+/// ```
+/// # use core::borrow::BorrowMut;
+/// # use kernel::sync::UniqueArc;
+/// struct Foo<B: BorrowMut<u32>>(B);
+///
+/// // Owned instance.
+/// let owned = Foo(1);
+///
+/// // Owned instance using `UniqueArc`.
+/// let arc = UniqueArc::new(1, GFP_KERNEL)?;
+/// let shared = Foo(arc);
+///
+/// let mut i = 1;
+/// // Borrowed from `i`.
+/// let borrowed = Foo(&mut i);
+/// # Ok::<(), Error>(())
+/// ```
+impl<T: ?Sized> BorrowMut<T> for UniqueArc<T> {
+ fn borrow_mut(&mut self) -> &mut T {
+ self.deref_mut()
+ }
+}
+
impl<T: fmt::Display + ?Sized> fmt::Display for UniqueArc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.deref(), f)
diff --git a/rust/kernel/sync/completion.rs b/rust/kernel/sync/completion.rs
new file mode 100644
index 000000000000..c50012a940a3
--- /dev/null
+++ b/rust/kernel/sync/completion.rs
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Completion support.
+//!
+//! Reference: <https://docs.kernel.org/scheduler/completion.html>
+//!
+//! C header: [`include/linux/completion.h`](srctree/include/linux/completion.h)
+
+use crate::{bindings, prelude::*, types::Opaque};
+
+/// Synchronization primitive to signal when a certain task has been completed.
+///
+/// The [`Completion`] synchronization primitive signals when a certain task has been completed by
+/// waking up other tasks that have been queued up to wait for the [`Completion`] to be completed.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::sync::{Arc, Completion};
+/// use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};
+///
+/// #[pin_data]
+/// struct MyTask {
+/// #[pin]
+/// work: Work<MyTask>,
+/// #[pin]
+/// done: Completion,
+/// }
+///
+/// impl_has_work! {
+/// impl HasWork<Self> for MyTask { self.work }
+/// }
+///
+/// impl MyTask {
+/// fn new() -> Result<Arc<Self>> {
+/// let this = Arc::pin_init(pin_init!(MyTask {
+/// work <- new_work!("MyTask::work"),
+/// done <- Completion::new(),
+/// }), GFP_KERNEL)?;
+///
+/// let _ = workqueue::system().enqueue(this.clone());
+///
+/// Ok(this)
+/// }
+///
+/// fn wait_for_completion(&self) {
+/// self.done.wait_for_completion();
+///
+/// pr_info!("Completion: task complete\n");
+/// }
+/// }
+///
+/// impl WorkItem for MyTask {
+/// type Pointer = Arc<MyTask>;
+///
+/// fn run(this: Arc<MyTask>) {
+/// // process this task
+/// this.done.complete_all();
+/// }
+/// }
+///
+/// let task = MyTask::new()?;
+/// task.wait_for_completion();
+/// # Ok::<(), Error>(())
+/// ```
+#[pin_data]
+pub struct Completion {
+ #[pin]
+ inner: Opaque<bindings::completion>,
+}
+
+// SAFETY: `Completion` is safe to be send to any task.
+unsafe impl Send for Completion {}
+
+// SAFETY: `Completion` is safe to be accessed concurrently.
+unsafe impl Sync for Completion {}
+
+impl Completion {
+ /// Create an initializer for a new [`Completion`].
+ pub fn new() -> impl PinInit<Self> {
+ pin_init!(Self {
+ inner <- Opaque::ffi_init(|slot: *mut bindings::completion| {
+ // SAFETY: `slot` is a valid pointer to an uninitialized `struct completion`.
+ unsafe { bindings::init_completion(slot) };
+ }),
+ })
+ }
+
+ fn as_raw(&self) -> *mut bindings::completion {
+ self.inner.get()
+ }
+
+ /// Signal all tasks waiting on this completion.
+ ///
+ /// This method wakes up all tasks waiting on this completion; after this operation the
+ /// completion is permanently done, i.e. signals all current and future waiters.
+ pub fn complete_all(&self) {
+ // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
+ unsafe { bindings::complete_all(self.as_raw()) };
+ }
+
+ /// Wait for completion of a task.
+ ///
+ /// This method waits for the completion of a task; it is not interruptible and there is no
+ /// timeout.
+ ///
+ /// See also [`Completion::complete_all`].
+ pub fn wait_for_completion(&self) {
+ // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
+ unsafe { bindings::wait_for_completion(self.as_raw()) };
+ }
+}
diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs
index d7e6e59e124b..339ab6097be7 100644
--- a/rust/kernel/sync/poll.rs
+++ b/rust/kernel/sync/poll.rs
@@ -73,7 +73,7 @@ impl PollTable {
// be destroyed, the destructor must run. That destructor first removes all waiters,
// and then waits for an rcu grace period. Therefore, `cv.wait_queue_head` is valid for
// long enough.
- unsafe { qproc(file.as_ptr() as _, cv.wait_queue_head.get(), self.0.get()) };
+ unsafe { qproc(file.as_ptr().cast(), cv.wait_queue_head.get(), self.0.get()) };
}
}
}
diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 9df3dcd2fa39..36e1290cd079 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -517,7 +517,7 @@ macro_rules! impl_has_hr_timer {
) -> *mut Self {
// SAFETY: As per the safety requirement of this function, `ptr`
// is pointing inside a `$timer_type`.
- unsafe { ::kernel::container_of!(ptr, $timer_type, $field).cast_mut() }
+ unsafe { ::kernel::container_of!(ptr, $timer_type, $field) }
}
}
}
diff --git a/rust/kernel/time/hrtimer/pin.rs b/rust/kernel/time/hrtimer/pin.rs
index 293ca9cf058c..2f29fd75d63a 100644
--- a/rust/kernel/time/hrtimer/pin.rs
+++ b/rust/kernel/time/hrtimer/pin.rs
@@ -79,7 +79,7 @@ where
unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart {
// `HrTimer` is `repr(C)`
- let timer_ptr = ptr as *mut HrTimer<T>;
+ let timer_ptr = ptr.cast::<HrTimer<T>>();
// SAFETY: By the safety requirement of this function, `timer_ptr`
// points to a `HrTimer<T>` contained in an `T`.
diff --git a/rust/kernel/time/hrtimer/pin_mut.rs b/rust/kernel/time/hrtimer/pin_mut.rs
index 6033572d35ad..d05d68be55e9 100644
--- a/rust/kernel/time/hrtimer/pin_mut.rs
+++ b/rust/kernel/time/hrtimer/pin_mut.rs
@@ -83,7 +83,7 @@ where
unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart {
// `HrTimer` is `repr(C)`
- let timer_ptr = ptr as *mut HrTimer<T>;
+ let timer_ptr = ptr.cast::<HrTimer<T>>();
// SAFETY: By the safety requirement of this function, `timer_ptr`
// points to a `HrTimer<T>` contained in an `T`.
diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs
index 6d70edd8086a..4ef13cf13a78 100644
--- a/rust/kernel/uaccess.rs
+++ b/rust/kernel/uaccess.rs
@@ -240,7 +240,7 @@ impl UserSliceReader {
pub fn read_slice(&mut self, out: &mut [u8]) -> Result {
// SAFETY: The types are compatible and `read_raw` doesn't write uninitialized bytes to
// `out`.
- let out = unsafe { &mut *(out as *mut [u8] as *mut [MaybeUninit<u8>]) };
+ let out = unsafe { &mut *(core::ptr::from_mut(out) as *mut [MaybeUninit<u8>]) };
self.read_raw(out)
}
@@ -355,7 +355,7 @@ impl UserSliceWriter {
let res = unsafe {
bindings::_copy_to_user(
self.ptr as *mut c_void,
- (value as *const T).cast::<c_void>(),
+ core::ptr::from_ref(value).cast::<c_void>(),
len,
)
};
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index d092112d843f..cce23684af24 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -26,7 +26,7 @@
//! * The [`WorkItemPointer`] trait is implemented for the pointer type that points at a something
//! that implements [`WorkItem`].
//!
-//! ## Example
+//! ## Examples
//!
//! This example defines a struct that holds an integer and can be scheduled on the workqueue. When
//! the struct is executed, it will print the integer. Since there is only one `work_struct` field,
@@ -170,7 +170,7 @@ impl Queue {
pub unsafe fn from_raw<'a>(ptr: *const bindings::workqueue_struct) -> &'a Queue {
// SAFETY: The `Queue` type is `#[repr(transparent)]`, so the pointer cast is valid. The
// caller promises that the pointer is not dangling.
- unsafe { &*(ptr as *const Queue) }
+ unsafe { &*ptr.cast::<Queue>() }
}
/// Enqueues a work item.
@@ -198,7 +198,7 @@ impl Queue {
unsafe {
w.__enqueue(move |work_ptr| {
bindings::queue_work_on(
- bindings::wq_misc_consts_WORK_CPU_UNBOUND as _,
+ bindings::wq_misc_consts_WORK_CPU_UNBOUND as ffi::c_int,
queue_ptr,
work_ptr,
)
@@ -522,7 +522,7 @@ where
{
unsafe extern "C" fn run(ptr: *mut bindings::work_struct) {
// The `__enqueue` method always uses a `work_struct` stored in a `Work<T, ID>`.
- let ptr = ptr as *mut Work<T, ID>;
+ let ptr = ptr.cast::<Work<T, ID>>();
// SAFETY: This computes the pointer that `__enqueue` got from `Arc::into_raw`.
let ptr = unsafe { T::work_container_of(ptr) };
// SAFETY: This pointer comes from `Arc::into_raw` and we've been given back ownership.
@@ -575,7 +575,7 @@ where
{
unsafe extern "C" fn run(ptr: *mut bindings::work_struct) {
// The `__enqueue` method always uses a `work_struct` stored in a `Work<T, ID>`.
- let ptr = ptr as *mut Work<T, ID>;
+ let ptr = ptr.cast::<Work<T, ID>>();
// SAFETY: This computes the pointer that `__enqueue` got from `Arc::into_raw`.
let ptr = unsafe { T::work_container_of(ptr) };
// SAFETY: This pointer comes from `Arc::into_raw` and we've been given back ownership.