Skip to content

Commit ce42dbd

Browse files
committed
platform: move get_id_info from platform.rs to public
Signed-off-by: Li Hongyu <[email protected]>
1 parent f42f82c commit ce42dbd

File tree

3 files changed

+83
-27
lines changed

3 files changed

+83
-27
lines changed

rust/kernel/platform.rs

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::{
1717
types::PointerWrapper,
1818
ThisModule,
1919
};
20+
use macros::get_id_info;
2021

2122
/// A registration of a platform driver.
2223
pub type Registration<T> = driver::Registration<Adapter<T>>;
@@ -61,33 +62,7 @@ impl<T: Driver> driver::DriverOps for Adapter<T> {
6162
}
6263

6364
impl<T: Driver> Adapter<T> {
64-
fn get_id_info(dev: &Device) -> Option<&'static T::IdInfo> {
65-
let table = T::OF_DEVICE_ID_TABLE?;
66-
67-
// SAFETY: `table` has static lifetime, so it is valid for read. `dev` is guaranteed to be
68-
// valid while it's alive, so is the raw device returned by it.
69-
let id = unsafe { bindings::of_match_device(table.as_ref(), dev.raw_device()) };
70-
if id.is_null() {
71-
return None;
72-
}
73-
74-
// SAFETY: `id` is a pointer within the static table, so it's always valid.
75-
let offset = unsafe { (*id).data };
76-
if offset.is_null() {
77-
return None;
78-
}
79-
80-
// SAFETY: The offset comes from a previous call to `offset_from` in `IdArray::new`, which
81-
// guarantees that the resulting pointer is within the table.
82-
let ptr = unsafe {
83-
id.cast::<u8>()
84-
.offset(offset as _)
85-
.cast::<Option<T::IdInfo>>()
86-
};
87-
88-
// SAFETY: The id table has a static lifetime, so `ptr` is guaranteed to be valid for read.
89-
unsafe { (&*ptr).as_ref() }
90-
}
65+
get_id_info!();
9166

9267
extern "C" fn probe_callback(pdev: *mut bindings::platform_device) -> core::ffi::c_int {
9368
from_kernel_result! {

rust/macros/get_id_info.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
use proc_macro::{TokenStream, TokenTree};
4+
5+
pub(crate) fn get_id_info(ts: TokenStream) -> TokenStream {
6+
"fn get_id_info(dev: &Device) -> Option<&'static T::IdInfo> {{
7+
let table = T::OF_DEVICE_ID_TABLE?;
8+
9+
// SAFETY: `table` has static lifetime, so it is valid for read. `dev` is guaranteed to be
10+
// valid while it's alive, so is the raw device returned by it.
11+
let id = unsafe {{ bindings::of_match_device(table.as_ref(), dev.raw_device()) }};
12+
if id.is_null() {{
13+
return None;
14+
}}
15+
16+
// SAFETY: `id` is a pointer within the static table, so it's always valid.
17+
let offset = unsafe {{ (*id).data }};
18+
if offset.is_null() {{
19+
return None;
20+
}}
21+
22+
// SAFETY: The offset comes from a previous call to `offset_from` in `IdArray::new`, which
23+
// guarantees that the resulting pointer is within the table.
24+
let ptr = unsafe {{
25+
id.cast::<u8>()
26+
.offset(offset as _)
27+
.cast::<Option<T::IdInfo>>()
28+
}};
29+
30+
// SAFETY: The id table has a static lifetime, so `ptr` is guaranteed to be valid for read.
31+
unsafe {{ (&*ptr).as_ref() }}
32+
}}"
33+
.parse()
34+
.expect("Error parsing formatted string into token stream.")
35+
}

rust/macros/lib.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! Crate for all kernel procedural macros.
44
55
mod concat_idents;
6+
mod get_id_info;
67
mod helpers;
78
mod module;
89
mod vtable;
@@ -188,3 +189,48 @@ pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream {
188189
pub fn concat_idents(ts: TokenStream) -> TokenStream {
189190
concat_idents::concat_idents(ts)
190191
}
192+
193+
/// Implements a get_id_info function for drivers.
194+
///
195+
/// Some linux drivers, e.g. Platform drivers, need to get info from of_id. This macro helps implements the get_id_info
196+
/// function for those drivers.
197+
///
198+
/// # Examples
199+
///
200+
/// ```ignore
201+
/// use crate::{
202+
/// bindings,
203+
/// device::{self, RawDevice},
204+
/// driver,
205+
/// of,
206+
/// };
207+
///
208+
/// pub trait Driver {
209+
/// type IdInfo: 'static = ();
210+
/// const OF_DEVICE_ID_TABLE: Option<driver::IdTable<'static, of::DeviceId, Self::IdInfo>> = None;
211+
/// }
212+
///
213+
/// pub struct Device {
214+
/// ptr: *mut bindings::bar_device,
215+
/// }
216+
///
217+
/// // SAFETY: The device returned by `raw_device` is the raw bar device.
218+
/// unsafe impl device::RawDevice for Device {
219+
/// fn raw_device(&self) -> *mut bindings::device {
220+
/// // SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
221+
/// unsafe { &mut (*self.ptr).dev }
222+
/// }
223+
/// }
224+
///
225+
/// pub struct Foo<T: Driver>(T);
226+
///
227+
/// impl<T: Driver> Adapter<T> {
228+
/// // Implements a get_id_info function
229+
/// get_id_info!()
230+
///
231+
/// }
232+
/// ```
233+
#[proc_macro]
234+
pub fn get_id_info(ts: TokenStream) -> TokenStream {
235+
get_id_info::get_id_info(ts)
236+
}

0 commit comments

Comments
 (0)