Skip to content

Commit ce41d4c

Browse files
asahilinaFabo
authored andcommitted
driver, of: Mangle the device ID machinery further to remove const_trait_impl
This unstable feature is broken/gone in 1.73. To work around this without breaking the API, turn IdArray::new() into a macro so that it can use concrete types (which can still have const associated functions) instead of a trait. This is quite ugly... Signed-off-by: Asahi Lina <[email protected]> (cherry picked from commit 71e6c52) Signed-off-by: Fabien Parent <[email protected]>
1 parent 529113f commit ce41d4c

File tree

2 files changed

+83
-46
lines changed

2 files changed

+83
-46
lines changed

rust/kernel/driver.rs

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,6 @@ impl<T: DriverOps> Drop for Registration<T> {
117117
///
118118
/// Implementers must ensure that:
119119
/// - [`RawDeviceId::ZERO`] is actually a zeroed-out version of the raw device id.
120-
/// - [`RawDeviceId::to_rawid`] stores `offset` in the context/data field of the raw device id so
121-
/// that buses can recover the pointer to the data.
122-
#[const_trait]
123120
pub unsafe trait RawDeviceId {
124121
/// The raw type that holds the device id.
125122
///
@@ -131,13 +128,6 @@ pub unsafe trait RawDeviceId {
131128
/// Id tables created from [`Self`] use [`Self::ZERO`] as the sentinel to indicate the end of
132129
/// the table.
133130
const ZERO: Self::RawType;
134-
135-
/// Converts an id into a raw id.
136-
///
137-
/// `offset` is the offset from the memory location where the raw device id is stored to the
138-
/// location where its associated context information is stored. Implementations must store
139-
/// this in the appropriate context/data field of the raw type.
140-
fn to_rawid(&self, offset: isize) -> Self::RawType;
141131
}
142132

143133
/// A zero-terminated device id array.
@@ -158,35 +148,7 @@ pub struct IdArray<T: RawDeviceId, U, const N: usize> {
158148
}
159149

160150
impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
161-
/// Creates a new instance of the array.
162-
///
163-
/// The contents are derived from the given identifiers and context information.
164-
pub const fn new(ids: [T; N], infos: [Option<U>; N]) -> Self
165-
where
166-
T: ~const RawDeviceId + Copy,
167-
T::RawType: Copy + Clone,
168-
{
169-
let mut array = Self {
170-
ids: IdArrayIds {
171-
ids: [T::ZERO; N],
172-
sentinel: T::ZERO,
173-
},
174-
id_infos: infos,
175-
};
176-
let mut i = 0usize;
177-
while i < N {
178-
// SAFETY: Both pointers are within `array` (or one byte beyond), consequently they are
179-
// derived from the same allocated object. We are using a `u8` pointer, whose size 1,
180-
// so the pointers are necessarily 1-byte aligned.
181-
let offset = unsafe {
182-
(&array.id_infos[i] as *const _ as *const u8)
183-
.offset_from(&array.ids.ids[i] as *const _ as _)
184-
};
185-
array.ids.ids[i] = ids[i].to_rawid(offset);
186-
i += 1;
187-
}
188-
array
189-
}
151+
const U_NONE: Option<U> = None;
190152

191153
/// Returns an `IdTable` backed by `self`.
192154
///
@@ -206,10 +168,82 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
206168
/// Returns the inner IdArrayIds array, without the context data.
207169
pub const fn as_ids(&self) -> IdArrayIds<T, N>
208170
where
209-
T: ~const RawDeviceId + Copy,
171+
T: RawDeviceId + Copy,
210172
{
211173
self.ids
212174
}
175+
176+
/// Creates a new instance of the array.
177+
///
178+
/// The contents are derived from the given identifiers and context information.
179+
#[doc(hidden)]
180+
pub const unsafe fn new(raw_ids: [T::RawType; N], infos: [Option<U>; N]) -> Self
181+
where
182+
T: RawDeviceId + Copy,
183+
T::RawType: Copy + Clone,
184+
{
185+
Self {
186+
ids: IdArrayIds {
187+
ids: raw_ids,
188+
sentinel: T::ZERO,
189+
},
190+
id_infos: infos,
191+
}
192+
}
193+
194+
#[doc(hidden)]
195+
pub const fn get_offset(idx: usize) -> isize
196+
where
197+
T: RawDeviceId + Copy,
198+
T::RawType: Copy + Clone,
199+
{
200+
// SAFETY: We are only using this dummy value to get offsets.
201+
let array = unsafe { Self::new([T::ZERO; N], [Self::U_NONE; N]) };
202+
// SAFETY: Both pointers are within `array` (or one byte beyond), consequently they are
203+
// derived from the same allocated object. We are using a `u8` pointer, whose size 1,
204+
// so the pointers are necessarily 1-byte aligned.
205+
let ret = unsafe {
206+
(&array.id_infos[idx] as *const _ as *const u8)
207+
.offset_from(&array.ids.ids[idx] as *const _ as _)
208+
};
209+
core::mem::forget(array);
210+
ret
211+
}
212+
}
213+
214+
// Creates a new ID array. This is a macro so it can take as a parameter the concrete ID type in order
215+
// to call to_rawid() on it, and still remain const. This is necessary until a new const_trait_impl
216+
// implementation lands, since the existing implementation was removed in Rust 1.73.
217+
#[macro_export]
218+
#[doc(hidden)]
219+
macro_rules! _new_id_array {
220+
(($($args:tt)*), $id_type:ty) => {{
221+
/// Creates a new instance of the array.
222+
///
223+
/// The contents are derived from the given identifiers and context information.
224+
const fn new< U, const N: usize>(ids: [$id_type; N], infos: [Option<U>; N])
225+
-> $crate::driver::IdArray<$id_type, U, N>
226+
where
227+
$id_type: $crate::driver::RawDeviceId + Copy,
228+
<$id_type as $crate::driver::RawDeviceId>::RawType: Copy + Clone,
229+
{
230+
let mut raw_ids =
231+
[<$id_type as $crate::driver::RawDeviceId>::ZERO; N];
232+
let mut i = 0usize;
233+
while i < N {
234+
let offset: isize = $crate::driver::IdArray::<$id_type, U, N>::get_offset(i);
235+
raw_ids[i] = ids[i].to_rawid(offset);
236+
i += 1;
237+
}
238+
239+
// SAFETY: We are passing valid arguments computed with the correct offsets.
240+
unsafe {
241+
$crate::driver::IdArray::<$id_type, U, N>::new(raw_ids, infos)
242+
}
243+
}
244+
245+
new($($args)*)
246+
}}
213247
}
214248

215249
/// A device id table.
@@ -367,8 +401,8 @@ macro_rules! define_id_array {
367401
($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
368402
const $table_name:
369403
$crate::driver::IdArray<$id_type, $data_type, { $crate::count_paren_items!($($t)*) }> =
370-
$crate::driver::IdArray::new(
371-
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*));
404+
$crate::_new_id_array!((
405+
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*)), $id_type);
372406
};
373407
}
374408

rust/kernel/of.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
//! C header: [`include/linux/of_*.h`](../../../../include/linux/of_*.h)
66
7-
use crate::{bindings, driver, str::BStr};
7+
use crate::{bindings, driver::RawDeviceId, str::BStr};
88

99
/// An open firmware device id.
1010
#[derive(Clone, Copy)]
@@ -17,7 +17,7 @@ pub enum DeviceId {
1717
///
1818
/// # Example
1919
///
20-
/// ```
20+
/// ```ignore
2121
/// # use kernel::{define_of_id_table, module_of_id_table, driver_of_id_table};
2222
/// use kernel::of;
2323
///
@@ -61,16 +61,19 @@ macro_rules! module_of_id_table {
6161
}
6262

6363
// SAFETY: `ZERO` is all zeroed-out and `to_rawid` stores `offset` in `of_device_id::data`.
64-
unsafe impl const driver::RawDeviceId for DeviceId {
64+
unsafe impl RawDeviceId for DeviceId {
6565
type RawType = bindings::of_device_id;
6666
const ZERO: Self::RawType = bindings::of_device_id {
6767
name: [0; 32],
6868
type_: [0; 32],
6969
compatible: [0; 128],
7070
data: core::ptr::null(),
7171
};
72+
}
7273

73-
fn to_rawid(&self, offset: isize) -> Self::RawType {
74+
impl DeviceId {
75+
#[doc(hidden)]
76+
pub const fn to_rawid(&self, offset: isize) -> <Self as RawDeviceId>::RawType {
7477
let DeviceId::Compatible(compatible) = self;
7578
let mut id = Self::ZERO;
7679
let mut i = 0;

0 commit comments

Comments
 (0)