History

rust: driver: remove open-coded matching logic

With device ID info now including pointers instead of indices, the open-coded ACPI/OF matching is no longer needed and can be replaced with `device_get_match_data`. With the removal of open-coded matching, the exposed functions and helpers are also removed; this effectively reverts most of commit 2690d071584e ("rust: ACPI: fix missing match data for PRP0001").

Gary Guo committed 4 months ago

Commit 2c5d17c1 parent 0b763359 files · +22 −162Browse files

Showing the changes to rust/kernel (4 of 9 files). Show all

Unified · Split

4 files
  1. rust/kernel/driver.rs +11 −126
  2. rust/kernel/i2c.rs +4 −2
  3. rust/kernel/platform.rs +2 −1
  4. rust/kernel/serdev.rs +2 −1
rust/kernel/driver.rs+11−126
@@ -107,7 +107,6 @@ · 106 unmodified lines
107107 use crate::{
108108 acpi,
109109 device,
110− device_id::RawDeviceIdIndex,
111110 of,
112111 prelude::*,
113112 types::Opaque,
@@ -292,26 +291,6 @@ macro_rules! module_driver { · 178 unmodified lines
292291 }
293292 }
294293
295−// Calling the FFI function directly from the `Adapter` impl may result in it being called
296−// directly from driver modules. This happens since the Rust compiler will use monomorphisation, so
297−// it might happen that functions are instantiated within the calling driver module. For now, work
298−// around this with `#[inline(never)]` helpers.
299−//
300−// TODO: Remove once a more generic solution has been implemented. For instance, we may be able to
301−// leverage `bindgen` to take care of this depending on whether a symbol is (already) exported.
302−#[inline(never)]
303−#[allow(clippy::missing_safety_doc)]
304−#[allow(dead_code)]
305−#[must_use]
306−unsafe fn acpi_of_match_device(
307− adev: *const bindings::acpi_device,
308− of_match_table: *const bindings::of_device_id,
309− of_id: *mut *const bindings::of_device_id,
310−) -> bool {
311− // SAFETY: Safety requirements are the same as `bindings::acpi_of_match_device`.
312− unsafe { bindings::acpi_of_match_device(adev, of_match_table, of_id) }
313−}
314−
315294 /// The bus independent adapter to match a drivers and a devices.
316295 ///
317296 /// This trait should be implemented by the bus specific adapter, which represents the connection
@@ -325,117 +304,23 @@ pub trait Adapter { · 7 unmodified lines
325304 /// The [`acpi::IdTable`] of the corresponding driver
326305 fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>>;
327306
328− /// Returns the driver's private data from the matching entry in the [`acpi::IdTable`], if any.
329− ///
330− /// If this returns `None`, it means there is no match with an entry in the [`acpi::IdTable`].
331− fn acpi_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {
332− #[cfg(not(CONFIG_ACPI))]
333− {
334− let _ = dev;
335− None
336− }
337−
338− #[cfg(CONFIG_ACPI)]
339− {
340− let table = Self::acpi_id_table()?;
341−
342− // SAFETY:
343− // - `table` has static lifetime, hence it's valid for read,
344− // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.
345− let raw_id = unsafe { bindings::acpi_match_device(table.as_ptr(), dev.as_raw()) };
346−
347− if raw_id.is_null() {
348− None
349− } else {
350− // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct acpi_device_id`
351− // and does not add additional invariants, so it's safe to transmute.
352− let id = unsafe { &*raw_id.cast::<acpi::DeviceId>() };
353−
354− // SAFETY: `id` comes from `table` which is of type `IdArray<_, Self::IdInfo>`.
355− Some(unsafe { id.info_unchecked::<Self::IdInfo>() })
356− }
357− }
358− }
359−
360307 /// The [`of::IdTable`] of the corresponding driver.
361308 fn of_id_table() -> Option<of::IdTable<Self::IdInfo>>;
362309
363− /// Returns the driver's private data from the matching entry in the [`of::IdTable`], if any.
364− ///
365− /// If this returns `None`, it means there is no match with an entry in the [`of::IdTable`].
366− fn of_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {
367− let table = Self::of_id_table()?;
368−
369− #[cfg(not(any(CONFIG_OF, CONFIG_ACPI)))]
370− {
371− let _ = (dev, table);
372− }
373−
374− #[cfg(CONFIG_OF)]
375− {
376− // SAFETY:
377− // - `table` has static lifetime, hence it's valid for read,
378− // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.
379− let raw_id = unsafe { bindings::of_match_device(table.as_ptr(), dev.as_raw()) };
380−
381− if !raw_id.is_null() {
382− // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id`
383− // and does not add additional invariants, so it's safe to transmute.
384− let id = unsafe { &*raw_id.cast::<of::DeviceId>() };
385−
386− // SAFETY: `id` comes from `table` which is of type `IdArray<_, Self::IdInfo>`.
387− return Some(unsafe { id.info_unchecked::<Self::IdInfo>() });
388− }
389− }
390−
391− #[cfg(CONFIG_ACPI)]
392− {
393− use core::ptr;
394− use device::property::FwNode;
395−
396− let mut raw_id = ptr::null();
397−
398− let fwnode = dev.fwnode().map_or(ptr::null_mut(), FwNode::as_raw);
399−
400− // SAFETY: `fwnode` is a pointer to a valid `fwnode_handle`. A null pointer will be
401− // passed through the function.
402− let adev = unsafe { bindings::to_acpi_device_node(fwnode) };
403−
404− // SAFETY:
405− // - `adev` is a valid pointer to `acpi_device` or is null. It is guaranteed to be
406− // valid as long as `dev` is alive.
407− // - `table` has static lifetime, hence it's valid for read.
408− if unsafe { acpi_of_match_device(adev, table.as_ptr(), &raw mut raw_id) } {
409− // SAFETY:
410− // - the function returns true, therefore `raw_id` has been set to a pointer to a
411− // valid `of_device_id`.
412− // - `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id`
413− // and does not add additional invariants, so it's safe to transmute.
414− let id = unsafe { &*raw_id.cast::<of::DeviceId>() };
415−
416− // SAFETY: `id` comes from `table` which is of type `IdArray<_, Self::IdInfo>`.
417− return Some(unsafe { id.info_unchecked::<Self::IdInfo>() });
418− }
419− }
420−
421− None
422− }
423−
424310 /// Returns the driver's private data from the matching entry of any of the ID tables, if any.
425311 ///
426312 /// If this returns `None`, it means that there is no match in any of the ID tables directly
427313 /// associated with a [`device::Device`].
428− fn id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {
429− let id = Self::acpi_id_info(dev);
430− if id.is_some() {
431− return id;
432− }
433−
434− let id = Self::of_id_info(dev);
435− if id.is_some() {
436− return id;
437− }
438−
439− None
314+ ///
315+ /// # Safety
316+ ///
317+ /// The caller must ensure that the `dev` matched data is of type `Self::IdInfo`.
318+ #[inline]
319+ unsafe fn id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {
320+ // SAFETY: `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.
321+ let data = unsafe { bindings::device_get_match_data(dev.as_raw()) };
322+
323+ // SAFETY: Per safety requirement, `data` is of type `Self::IdInfo`.
324+ unsafe { data.cast::<Self::IdInfo>().as_ref() }
440325 }
441326 }
rust/kernel/i2c.rs+4−2
@@ -149,8 +149,10 @@ impl<T: Driver> Adapter<T> { · 148 unmodified lines
149149 // INVARIANT: `idev` is valid for the duration of `probe_callback()`.
150150 let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal<'_>>>() };
151151
152− let info =
153− Self::i2c_id_info(idev).or_else(|| <Self as driver::Adapter>::id_info(idev.as_ref()));
152+ let info = Self::i2c_id_info(idev).or_else(|| {
153+ // SAFETY: `idev` matched data is of type `Self::IdInfo`.
154+ unsafe { <Self as driver::Adapter>::id_info(idev.as_ref()) }
155+ });
154156
155157 from_result(|| {
156158 let data = T::probe(idev, info);
rust/kernel/platform.rs+2−1
@@ -100,7 +100,8 @@ impl<T: Driver> Adapter<T> { · 99 unmodified lines
100100 //
101101 // INVARIANT: `pdev` is valid for the duration of `probe_callback()`.
102102 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal<'_>>>() };
103− let info = <Self as driver::Adapter>::id_info(pdev.as_ref());
103+ // SAFETY: `pdev` matched data is of type `Self::IdInfo`.
104+ let info = unsafe { <Self as driver::Adapter>::id_info(pdev.as_ref()) };
104105
105106 from_result(|| {
106107 let data = T::probe(pdev, info);
rust/kernel/serdev.rs+2−1
@@ -162,7 +162,8 @@ impl<T: Driver> Adapter<T> { · 161 unmodified lines
162162 //
163163 // INVARIANT: `sdev` is valid for the duration of `probe_callback()`.
164164 let sdev = unsafe { &*sdev.cast::<Device<device::CoreInternal<'_>>>() };
165− let info = <Self as driver::Adapter>::id_info(sdev.as_ref());
165+ // SAFETY: `sdev` matched data is of type `Self::IdInfo`.
166+ let info = unsafe { <Self as driver::Adapter>::id_info(sdev.as_ref()) };
166167
167168 from_result(|| {
168169 sdev.as_ref().set_drvdata(try_pin_init!(PrivateData::<T> {