| @@ -107,7 +107,6 @@ · 106 unmodified lines |
| 107 | use crate::{ | 107 | use crate::{ |
| 108 | acpi, | 108 | acpi, |
| 109 | device, | 109 | device, |
| 110 | device_id::RawDeviceIdIndex, | | |
| 111 | of, | 110 | of, |
| 112 | prelude::*, | 111 | prelude::*, |
| 113 | types::Opaque, | 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 | /// The bus independent adapter to match a drivers and a devices. | 294 | /// The bus independent adapter to match a drivers and a devices. |
| 316 | /// | 295 | /// |
| 317 | /// This trait should be implemented by the bus specific adapter, which represents the connection | 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 | /// The [`acpi::IdTable`] of the corresponding driver | 304 | /// The [`acpi::IdTable`] of the corresponding driver |
| 326 | fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>>; | 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 | /// The [`of::IdTable`] of the corresponding driver. | 307 | /// The [`of::IdTable`] of the corresponding driver. |
| 361 | fn of_id_table() -> Option<of::IdTable<Self::IdInfo>>; | 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 | /// Returns the driver's private data from the matching entry of any of the ID tables, if any. | 310 | /// Returns the driver's private data from the matching entry of any of the ID tables, if any. |
| 425 | /// | 311 | /// |
| 426 | /// If this returns `None`, it means that there is no match in any of the ID tables directly | 312 | /// If this returns `None`, it means that there is no match in any of the ID tables directly |
| 427 | /// associated with a [`device::Device`]. | 313 | /// associated with a [`device::Device`]. |
| 428 | fn id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> { | 314 | /// |
| 429 | let id = Self::acpi_id_info(dev); | 315 | /// # Safety |
| 430 | if id.is_some() { | 316 | /// |
| 431 | return id; | 317 | /// The caller must ensure that the `dev` matched data is of type `Self::IdInfo`. |
| 432 | } | 318 | #[inline] |
| 433 | | 319 | unsafe fn id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> { |
| 434 | let id = Self::of_id_info(dev); | 320 | // SAFETY: `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`. |
| 435 | if id.is_some() { | 321 | let data = unsafe { bindings::device_get_match_data(dev.as_raw()) }; |
| 436 | return id; | 322 | |
| 437 | } | 323 | // SAFETY: Per safety requirement, `data` is of type `Self::IdInfo`. |
| 438 | | 324 | unsafe { data.cast::<Self::IdInfo>().as_ref() } |
| 439 | None | | |
| 440 | } | 325 | } |
| 441 | } | 326 | } |