Skip to content

Commit 816c8af

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 ca14fdf commit 816c8af

File tree

2 files changed

+82
-43
lines changed

2 files changed

+82
-43
lines changed

rust/kernel/driver.rs

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ impl<T: DriverOps> Drop for Registration<T> {
119119
/// - [`RawDeviceId::ZERO`] is actually a zeroed-out version of the raw device id.
120120
/// - [`RawDeviceId::to_rawid`] stores `offset` in the context/data field of the raw device id so
121121
/// that buses can recover the pointer to the data.
122-
#[const_trait]
123122
pub unsafe trait RawDeviceId {
124123
/// The raw type that holds the device id.
125124
///
@@ -131,13 +130,6 @@ pub unsafe trait RawDeviceId {
131130
/// Id tables created from [`Self`] use [`Self::ZERO`] as the sentinel to indicate the end of
132131
/// the table.
133132
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;
141133
}
142134

143135
/// A zero-terminated device id array.
@@ -158,35 +150,7 @@ pub struct IdArray<T: RawDeviceId, U, const N: usize> {
158150
}
159151

160152
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-
}
153+
const U_NONE: Option<U> = None;
190154

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

215251
/// A device id table.
@@ -367,8 +403,8 @@ macro_rules! define_id_array {
367403
($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
368404
const $table_name:
369405
$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)*));
406+
$crate::_new_id_array!((
407+
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*)), $id_type);
372408
};
373409
}
374410

rust/kernel/of.rs

Lines changed: 6 additions & 3 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)]
@@ -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)