Skip to content

Commit ca14fdf

Browse files
asahilinaFabo
authored andcommitted
rust: driver,of: Support passing ID tables to modpost for alias generation
In order for modpost to work and correctly generate module aliases from device ID tables, it needs those tables to exist as global symbols with a specific name. Additionally, modpost checks the size of the symbol, so it cannot contain trailing data. To support this, split IdArrayIds out of IdArray. The former contains just the IDs. Then split out the device table definition macro from the macro that defines the device table for a given bus driver, and add another macro to declare a device table as a module device table. Drivers can now define their ID table once, and then specify that it should be used for both the driver and the module: // Generic OF Device ID table. kernel::define_of_id_table! {ASAHI_ID_TABLE, &'static hw::HwConfig, [ (of::DeviceId::Compatible(b"apple,agx-t8103"), Some(&hw::t8103::HWCONFIG)), (of::DeviceId::Compatible(b"apple,agx-t8112"), Some(&hw::t8112::HWCONFIG)), // ... ]} /// Platform Driver implementation for `AsahiDriver`. impl platform::Driver for AsahiDriver { /// Data associated with each hardware ID. type IdInfo = &'static hw::HwConfig; // Assign the above OF ID table to this driver. kernel::driver_of_id_table!(ASAHI_ID_TABLE); // ... } // Export the OF ID table as a module ID table, to make modpost/autoloading work. kernel::module_of_id_table!(MOD_TABLE, ASAHI_ID_TABLE); Signed-off-by: Asahi Lina <[email protected]> (cherry picked from commit 9d4f135) Signed-off-by: Fabien Parent <[email protected]>
1 parent 42bd2b8 commit ca14fdf

File tree

2 files changed

+97
-41
lines changed

2 files changed

+97
-41
lines changed

rust/kernel/driver.rs

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,20 @@ pub unsafe trait RawDeviceId {
140140
fn to_rawid(&self, offset: isize) -> Self::RawType;
141141
}
142142

143-
/// A zero-terminated device id array, followed by context data.
143+
/// A zero-terminated device id array.
144+
#[derive(Copy, Clone)]
144145
#[repr(C)]
145-
pub struct IdArray<T: RawDeviceId, U, const N: usize> {
146+
pub struct IdArrayIds<T: RawDeviceId, const N: usize> {
146147
ids: [T::RawType; N],
147148
sentinel: T::RawType,
149+
}
150+
151+
unsafe impl<T: RawDeviceId, const N: usize> Sync for IdArrayIds<T, N> {}
152+
153+
/// A zero-terminated device id array, followed by context data.
154+
#[repr(C)]
155+
pub struct IdArray<T: RawDeviceId, U, const N: usize> {
156+
ids: IdArrayIds<T, N>,
148157
id_infos: [Option<U>; N],
149158
}
150159

@@ -155,10 +164,13 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
155164
pub const fn new(ids: [T; N], infos: [Option<U>; N]) -> Self
156165
where
157166
T: ~const RawDeviceId + Copy,
167+
T::RawType: Copy + Clone,
158168
{
159169
let mut array = Self {
160-
ids: [T::ZERO; N],
161-
sentinel: T::ZERO,
170+
ids: IdArrayIds {
171+
ids: [T::ZERO; N],
172+
sentinel: T::ZERO,
173+
},
162174
id_infos: infos,
163175
};
164176
let mut i = 0usize;
@@ -168,9 +180,9 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
168180
// so the pointers are necessarily 1-byte aligned.
169181
let offset = unsafe {
170182
(&array.id_infos[i] as *const _ as *const u8)
171-
.offset_from(&array.ids[i] as *const _ as _)
183+
.offset_from(&array.ids.ids[i] as *const _ as _)
172184
};
173-
array.ids[i] = ids[i].to_rawid(offset);
185+
array.ids.ids[i] = ids[i].to_rawid(offset);
174186
i += 1;
175187
}
176188
array
@@ -181,10 +193,23 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
181193
/// This is used to essentially erase the array size.
182194
pub const fn as_table(&self) -> IdTable<'_, T, U> {
183195
IdTable {
184-
first: &self.ids[0],
196+
first: &self.ids.ids[0],
185197
_p: PhantomData,
186198
}
187199
}
200+
201+
/// Returns the number of items in the ID table.
202+
pub const fn count(&self) -> usize {
203+
self.ids.ids.len()
204+
}
205+
206+
/// Returns the inner IdArrayIds array, without the context data.
207+
pub const fn as_ids(&self) -> IdArrayIds<T, N>
208+
where
209+
T: ~const RawDeviceId + Copy,
210+
{
211+
self.ids
212+
}
188213
}
189214

190215
/// A device id table.
@@ -331,6 +356,11 @@ macro_rules! second_item {
331356
/// define_id_array!(A6, Id, &'static [u8], [(Id(10), None), (Id(20), Some(b"id2")), ]);
332357
/// define_id_array!(A7, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), None), ]);
333358
/// define_id_array!(A8, Id, &'static [u8], [(Id(10), None), (Id(20), None), ]);
359+
///
360+
/// // Within a bus driver:
361+
/// driver_id_table!(BUS_ID_TABLE, Id, &'static [u8], A1);
362+
/// // At the top level:
363+
/// module_id_table!(MODULE_ID_TABLE, "mybus", Id, A1);
334364
/// ```
335365
#[macro_export]
336366
macro_rules! define_id_array {
@@ -342,7 +372,7 @@ macro_rules! define_id_array {
342372
};
343373
}
344374

345-
/// Defines a new constant [`IdTable`] with a concise syntax.
375+
/// Declares an [`IdArray`] as an [`IdTable`] for a bus driver with a concise syntax.
346376
///
347377
/// It is meant to be used by buses and subsystems to create a similar macro with their device id
348378
/// type already specified, i.e., with fewer parameters to the end user.
@@ -352,36 +382,38 @@ macro_rules! define_id_array {
352382
// TODO: Exported but not usable by kernel modules (requires `const_trait_impl`).
353383
/// ```ignore
354384
/// #![feature(const_trait_impl)]
355-
/// # use kernel::{define_id_table, driver::RawDeviceId};
385+
/// # use kernel::{driver_id_table};
386+
387+
/// driver_id_table!(BUS_ID_TABLE, Id, &'static [u8], MY_ID_ARRAY);
388+
/// ```
389+
#[macro_export]
390+
macro_rules! driver_id_table {
391+
($table_name:ident, $id_type:ty, $data_type:ty, $target:expr) => {
392+
const $table_name: Option<$crate::driver::IdTable<'static, $id_type, $data_type>> =
393+
Some($target.as_table());
394+
};
395+
}
396+
397+
/// Declares an [`IdArray`] as a module-level ID tablewith a concise syntax.
356398
///
357-
/// #[derive(Copy, Clone)]
358-
/// struct Id(u32);
399+
/// It is meant to be used by buses and subsystems to create a similar macro with their device id
400+
/// type already specified, i.e., with fewer parameters to the end user.
359401
///
360-
/// // SAFETY: `ZERO` is all zeroes and `to_rawid` stores `offset` as the second element of the raw
361-
/// // device id pair.
362-
/// unsafe impl const RawDeviceId for Id {
363-
/// type RawType = (u64, isize);
364-
/// const ZERO: Self::RawType = (0, 0);
365-
/// fn to_rawid(&self, offset: isize) -> Self::RawType {
366-
/// (self.0 as u64 + 1, offset)
367-
/// }
368-
/// }
402+
/// # Examples
369403
///
370-
/// define_id_table!(T1, Id, &'static [u8], [(Id(10), None)]);
371-
/// define_id_table!(T2, Id, &'static [u8], [(Id(10), Some(b"id1")), ]);
372-
/// define_id_table!(T3, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2"))]);
373-
/// define_id_table!(T4, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2")), ]);
374-
/// define_id_table!(T5, Id, &'static [u8], [(Id(10), None), (Id(20), Some(b"id2")), ]);
375-
/// define_id_table!(T6, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), None), ]);
376-
/// define_id_table!(T7, Id, &'static [u8], [(Id(10), None), (Id(20), None), ]);
404+
// TODO: Exported but not usable by kernel modules (requires `const_trait_impl`).
405+
/// ```ignore
406+
/// #![feature(const_trait_impl)]
407+
/// # use kernel::{driver_id_table};
408+
409+
/// driver_id_table!(BUS_ID_TABLE, Id, &'static [u8], MY_ID_ARRAY);
377410
/// ```
378411
#[macro_export]
379-
macro_rules! define_id_table {
380-
($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
381-
const $table_name: Option<$crate::driver::IdTable<'static, $id_type, $data_type>> = {
382-
$crate::define_id_array!(ARRAY, $id_type, $data_type, [ $($t)* ]);
383-
Some(ARRAY.as_table())
384-
};
412+
macro_rules! module_id_table {
413+
($item_name:ident, $table_type:literal, $id_type:ty, $table_name:ident) => {
414+
#[export_name = concat!("__mod_", $table_type, "__", stringify!($table_name), "_device_table")]
415+
static $item_name: $crate::driver::IdArrayIds<$id_type, { $table_name.count() }> =
416+
$table_name.as_ids();
385417
};
386418
}
387419

rust/kernel/of.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,48 @@ pub enum DeviceId {
1515

1616
/// Defines a const open firmware device id table that also carries per-entry data/context/info.
1717
///
18-
/// The name of the const is `OF_DEVICE_ID_TABLE`, which is what buses are expected to name their
19-
/// open firmware tables.
20-
///
21-
/// # Examples
18+
/// # Example
2219
///
2320
/// ```
24-
/// # use kernel::define_of_id_table;
21+
/// # use kernel::{define_of_id_table, module_of_id_table, driver_of_id_table};
2522
/// use kernel::of;
2623
///
27-
/// define_of_id_table! {u32, [
24+
/// define_of_id_table! {MY_ID_TABLE, u32, [
2825
/// (of::DeviceId::Compatible(b"test-device1,test-device2"), Some(0xff)),
2926
/// (of::DeviceId::Compatible(b"test-device3"), None),
3027
/// ]};
28+
///
29+
/// module_of_id_table!(MOD_TABLE, ASAHI_ID_TABLE);
30+
///
31+
/// // Within the `Driver` implementation:
32+
/// driver_of_id_table!(MY_ID_TABLE);
3133
/// ```
3234
#[macro_export]
3335
macro_rules! define_of_id_table {
34-
($data_type:ty, $($t:tt)*) => {
35-
$crate::define_id_table!(OF_DEVICE_ID_TABLE, $crate::of::DeviceId, $data_type, $($t)*);
36+
($name:ident, $data_type:ty, $($t:tt)*) => {
37+
$crate::define_id_array!($name, $crate::of::DeviceId, $data_type, $($t)*);
38+
};
39+
}
40+
41+
/// Convenience macro to declare which device ID table to use for a bus driver.
42+
#[macro_export]
43+
macro_rules! driver_of_id_table {
44+
($name:expr) => {
45+
$crate::driver_id_table!(
46+
OF_DEVICE_ID_TABLE,
47+
$crate::of::DeviceId,
48+
Self::IdInfo,
49+
$name
50+
);
51+
};
52+
}
53+
54+
/// Declare a device ID table as a module-level table. This creates the necessary module alias
55+
/// entries to enable module autoloading.
56+
#[macro_export]
57+
macro_rules! module_of_id_table {
58+
($item_name:ident, $table_name:ident) => {
59+
$crate::module_id_table!($item_name, "of", $crate::of::DeviceId, $table_name);
3660
};
3761
}
3862

0 commit comments

Comments
 (0)