| @@ -107,7 +107,6 @@ · 106 unmodified lines |
| 107 | 107 | use crate::{ |
| 108 | 108 | acpi, |
| 109 | 109 | device, |
| 110 | | − device_id::RawDeviceIdIndex, |
| 111 | 110 | of, |
| 112 | 111 | prelude::*, |
| 113 | 112 | types::Opaque, |
| @@ -292,26 +291,6 @@ macro_rules! module_driver { · 178 unmodified lines |
| 292 | 291 | } |
| 293 | 292 | } |
| 294 | 293 | |
| 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 | | − |
| 315 | 294 | /// The bus independent adapter to match a drivers and a devices. |
| 316 | 295 | /// |
| 317 | 296 | /// This trait should be implemented by the bus specific adapter, which represents the connection |
| @@ -325,117 +304,23 @@ pub trait Adapter { · 7 unmodified lines |
| 325 | 304 | /// The [`acpi::IdTable`] of the corresponding driver |
| 326 | 305 | fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>>; |
| 327 | 306 | |
| 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 | | − |
| 360 | 307 | /// The [`of::IdTable`] of the corresponding driver. |
| 361 | 308 | fn of_id_table() -> Option<of::IdTable<Self::IdInfo>>; |
| 362 | 309 | |
| 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 | | − |
| 424 | 310 | /// Returns the driver's private data from the matching entry of any of the ID tables, if any. |
| 425 | 311 | /// |
| 426 | 312 | /// If this returns `None`, it means that there is no match in any of the ID tables directly |
| 427 | 313 | /// 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() } |
| 440 | 325 | } |
| 441 | 326 | } |