1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Devres abstraction 4 //! 5 //! [`Devres`] represents an abstraction for the kernel devres (device resource management) 6 //! implementation. 7 8 use crate::{ 9 alloc::Flags, 10 bindings, 11 device::{ 12 Bound, 13 Device, // 14 }, 15 error::to_result, 16 prelude::*, 17 revocable::{ 18 Revocable, 19 RevocableGuard, // 20 }, 21 sync::{ 22 aref::ARef, 23 rcu, 24 Arc, 25 Completion, // 26 }, 27 types::{ 28 CovariantForLt, 29 ForLt, 30 ForeignOwnable, 31 Opaque, // 32 }, 33 }; 34 35 /// Inner type that embeds a `struct devres_node` and the `Revocable<T>`. 36 #[repr(C)] 37 #[pin_data] 38 struct Inner<T> { 39 #[pin] 40 node: Opaque<bindings::devres_node>, 41 #[pin] 42 data: Revocable<T>, 43 #[pin] 44 revocation: Completion, 45 } 46 47 /// This abstraction is meant to be used by subsystems to containerize [`Device`] bound resources to 48 /// manage their lifetime. 49 /// 50 /// [`Device`] bound resources should be freed when either the resource goes out of scope or the 51 /// [`Device`] is unbound respectively, depending on what happens first. In any case, it is always 52 /// guaranteed that revoking the device resource is completed before the corresponding [`Device`] 53 /// is unbound. 54 /// 55 /// To achieve that [`Devres`] registers a devres callback on creation, which is called once the 56 /// [`Device`] is unbound, revoking access to the encapsulated resource (see also [`Revocable`]). 57 /// 58 /// After the [`Devres`] has been unbound it is not possible to access the encapsulated resource 59 /// anymore. 60 /// 61 /// When a [`Devres`] is dropped, it is guaranteed that `T` has been fully dropped by the time 62 /// [`Devres::drop`] returns, even if a concurrent revocation through the release callback is in 63 /// progress. 64 /// 65 /// [`Devres`] users should make sure to simply free the corresponding backing resource in `T`'s 66 /// [`Drop`] implementation. 67 /// 68 /// # Examples 69 /// 70 /// ```no_run 71 /// # #![cfg(CONFIG_HAS_IOMEM)] 72 /// use kernel::{ 73 /// bindings, 74 /// device::{ 75 /// Bound, 76 /// Device, 77 /// }, 78 /// devres::Devres, 79 /// io::{ 80 /// Io, 81 /// IoBase, 82 /// Mmio, 83 /// MmioRaw, 84 /// MmioBackend, 85 /// PhysAddr, 86 /// Region, // 87 /// }, 88 /// prelude::*, 89 /// }; 90 /// use core::ops::Deref; 91 /// 92 /// // See also [`pci::Bar`] for a real example. 93 /// struct IoMem<const SIZE: usize>(MmioRaw<Region<SIZE>>); 94 /// 95 /// impl<const SIZE: usize> IoMem<SIZE> { 96 /// /// # Safety 97 /// /// 98 /// /// [`paddr`, `paddr` + `SIZE`) must be a valid MMIO region that is mappable into the CPUs 99 /// /// virtual address space. 100 /// unsafe fn new(paddr: usize) -> Result<Self>{ 101 /// // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is 102 /// // valid for `ioremap`. 103 /// let addr = unsafe { bindings::ioremap(paddr as PhysAddr, SIZE) }; 104 /// if addr.is_null() { 105 /// return Err(ENOMEM); 106 /// } 107 /// 108 /// Ok(IoMem(MmioRaw::new_region(addr as usize, SIZE)?)) 109 /// } 110 /// } 111 /// 112 /// impl<const SIZE: usize> Drop for IoMem<SIZE> { 113 /// fn drop(&mut self) { 114 /// // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`. 115 /// unsafe { bindings::iounmap(self.0.addr() as *mut c_void); }; 116 /// } 117 /// } 118 /// 119 /// impl<'a, const SIZE: usize> IoBase<'a> for &'a IoMem<SIZE> { 120 /// type Backend = MmioBackend; 121 /// type Target = Region<SIZE>; 122 /// 123 /// fn as_view(self) -> Mmio<'a, Region<SIZE>> { 124 /// // SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`. 125 /// unsafe { Mmio::from_raw(self.0) } 126 /// } 127 /// } 128 /// # fn no_run(dev: &Device<Bound>) -> Result<(), Error> { 129 /// // SAFETY: Invalid usage for example purposes. 130 /// let iomem = unsafe { IoMem::<{ core::mem::size_of::<u32>() }>::new(0xBAAAAAAD)? }; 131 /// let devres = Devres::new(dev, iomem)?; 132 /// 133 /// let res = devres.try_access().ok_or(ENXIO)?; 134 /// res.write8(0x42, 0x0); 135 /// # Ok(()) 136 /// # } 137 /// ``` 138 pub struct Devres<T: Send + 'static> { 139 dev: ARef<Device>, 140 inner: Arc<Inner<T>>, 141 } 142 143 // Calling the FFI functions from the `base` module directly from the `Devres<T>` impl may result in 144 // them being called directly from driver modules. This happens since the Rust compiler will use 145 // monomorphisation, so it might happen that functions are instantiated within the calling driver 146 // module. For now, work around this with `#[inline(never)]` helpers. 147 // 148 // TODO: Remove once a more generic solution has been implemented. For instance, we may be able to 149 // leverage `bindgen` to take care of this depending on whether a symbol is (already) exported. 150 mod base { 151 use kernel::{ 152 bindings, 153 prelude::*, // 154 }; 155 156 #[inline(never)] 157 #[allow(clippy::missing_safety_doc)] 158 pub(super) unsafe fn devres_node_init( 159 node: *mut bindings::devres_node, 160 release: bindings::dr_node_release_t, 161 free: bindings::dr_node_free_t, 162 ) { 163 // SAFETY: Safety requirements are the same as `bindings::devres_node_init`. 164 unsafe { bindings::devres_node_init(node, release, free) } 165 } 166 167 #[inline(never)] 168 #[allow(clippy::missing_safety_doc)] 169 pub(super) unsafe fn devres_set_node_dbginfo( 170 node: *mut bindings::devres_node, 171 name: *const c_char, 172 size: usize, 173 ) { 174 // SAFETY: Safety requirements are the same as `bindings::devres_set_node_dbginfo`. 175 unsafe { bindings::devres_set_node_dbginfo(node, name, size) } 176 } 177 178 #[inline(never)] 179 #[allow(clippy::missing_safety_doc)] 180 pub(super) unsafe fn devres_node_add( 181 dev: *mut bindings::device, 182 node: *mut bindings::devres_node, 183 ) { 184 // SAFETY: Safety requirements are the same as `bindings::devres_node_add`. 185 unsafe { bindings::devres_node_add(dev, node) } 186 } 187 188 #[must_use] 189 #[inline(never)] 190 #[allow(clippy::missing_safety_doc)] 191 pub(super) unsafe fn devres_node_remove( 192 dev: *mut bindings::device, 193 node: *mut bindings::devres_node, 194 ) -> bool { 195 // SAFETY: Safety requirements are the same as `bindings::devres_node_remove`. 196 unsafe { bindings::devres_node_remove(dev, node) } 197 } 198 } 199 200 impl<T: Send + 'static> Devres<T> { 201 /// Creates a new [`Devres`] instance of the given `data`. 202 /// 203 /// The `data` encapsulated within the returned `Devres` instance' `data` will be 204 /// (revoked)[`Revocable`] once the device is detached. 205 pub fn new<E>(dev: &Device<Bound>, data: impl PinInit<T, E>) -> Result<Self> 206 where 207 Error: From<E>, 208 { 209 let inner = Arc::pin_init::<Error>( 210 try_pin_init!(Inner { 211 node <- Opaque::ffi_init(|node: *mut bindings::devres_node| { 212 // SAFETY: `node` is a valid pointer to an uninitialized `struct devres_node`. 213 unsafe { 214 base::devres_node_init( 215 node, 216 Some(Self::devres_node_release), 217 Some(Self::devres_node_free_node), 218 ) 219 }; 220 221 // SAFETY: `node` is a valid pointer to an uninitialized `struct devres_node`. 222 unsafe { 223 base::devres_set_node_dbginfo( 224 node, 225 // TODO: Use `core::any::type_name::<T>()` once it is a `const fn`, 226 // such that we can convert the `&str` to a `&CStr` at compile-time. 227 c"Devres<T>".as_char_ptr(), 228 core::mem::size_of::<Revocable<T>>(), 229 ) 230 }; 231 }), 232 data <- Revocable::new(data), 233 revocation <- Completion::new(), 234 }), 235 GFP_KERNEL, 236 )?; 237 238 // SAFETY: 239 // - `dev` is a valid pointer to a bound `struct device`. 240 // - `node` is a valid pointer to a `struct devres_node`. 241 // - `devres_node_add()` is guaranteed not to call `devres_node_release()` for the entire 242 // lifetime of `dev`. 243 unsafe { base::devres_node_add(dev.as_raw(), inner.node.get()) }; 244 245 // Take additional reference count for `devres_node_add()`. 246 core::mem::forget(inner.clone()); 247 248 Ok(Self { 249 dev: dev.into(), 250 inner, 251 }) 252 } 253 254 fn data(&self) -> &Revocable<T> { 255 &self.inner.data 256 } 257 258 #[allow(clippy::missing_safety_doc)] 259 unsafe extern "C" fn devres_node_release( 260 _dev: *mut bindings::device, 261 node: *mut bindings::devres_node, 262 ) { 263 let node = Opaque::cast_from(node); 264 265 // SAFETY: `node` is in the same allocation as its container. 266 let inner = unsafe { kernel::container_of!(node, Inner<T>, node) }; 267 268 // SAFETY: `inner` is a valid `Inner<T>` pointer. 269 let inner = unsafe { &*inner }; 270 271 if inner.data.revoke() { 272 inner.revocation.complete_all(); 273 } else { 274 // Devres::drop() is concurrently revoking; wait for it to finish `drop_in_place()` 275 // before returning to `devres_release_all()`, ensuring `T` is fully torn down before 276 // the device finishes unbinding. 277 inner.revocation.wait_for_completion(); 278 } 279 } 280 281 #[allow(clippy::missing_safety_doc)] 282 unsafe extern "C" fn devres_node_free_node(node: *mut bindings::devres_node) { 283 let node = Opaque::cast_from(node); 284 285 // SAFETY: `node` is in the same allocation as its container. 286 let inner = unsafe { kernel::container_of!(node, Inner<T>, node) }; 287 288 // SAFETY: `inner` points to the entire `Inner<T>` allocation. 289 drop(unsafe { Arc::from_raw(inner) }); 290 } 291 292 fn remove_node(&self) -> bool { 293 // SAFETY: 294 // - `self.device().as_raw()` is a valid pointer to a bound `struct device`. 295 // - `self.inner.node.get()` is a valid pointer to a `struct devres_node`. 296 unsafe { base::devres_node_remove(self.device().as_raw(), self.inner.node.get()) } 297 } 298 299 /// Return a reference of the [`Device`] this [`Devres`] instance has been created with. 300 pub fn device(&self) -> &Device { 301 &self.dev 302 } 303 304 /// Obtain `&'a T`, bypassing the [`Revocable`]. 305 /// 306 /// This method allows to directly obtain a `&'a T`, bypassing the [`Revocable`], by presenting 307 /// a `&'a Device<Bound>` of the same [`Device`] this [`Devres`] instance has been created with. 308 /// 309 /// # Errors 310 /// 311 /// An error is returned if `dev` does not match the same [`Device`] this [`Devres`] instance 312 /// has been created with. 313 /// 314 /// # Examples 315 /// 316 /// ```no_run 317 /// #![cfg(CONFIG_PCI)] 318 /// use kernel::{ 319 /// device::Core, 320 /// devres::Devres, 321 /// io::Io, 322 /// pci, // 323 /// }; 324 /// 325 /// fn from_core(dev: &pci::Device<Core<'_>>, devres: Devres<pci::Bar<'_, 0x4>>) -> Result { 326 /// let bar = devres.access(dev.as_ref())?; 327 /// 328 /// let _ = bar.read32(0x0); 329 /// 330 /// // might_sleep() 331 /// 332 /// bar.write32(0x42, 0x0); 333 /// 334 /// Ok(()) 335 /// } 336 /// ``` 337 pub fn access<'a>(&'a self, dev: &'a Device<Bound>) -> Result<&'a T> { 338 if self.dev.as_raw() != dev.as_raw() { 339 return Err(EINVAL); 340 } 341 342 // SAFETY: `dev` being the same device as the device this `Devres` has been created for 343 // proves that `self.data` hasn't been revoked and is guaranteed to not be revoked as long 344 // as `dev` lives; `dev` lives at least as long as `self`. 345 Ok(unsafe { self.data().access() }) 346 } 347 348 /// [`Devres`] accessor for [`Revocable::try_access`]. 349 pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> { 350 self.data().try_access() 351 } 352 353 /// [`Devres`] accessor for [`Revocable::try_access_with`]. 354 pub fn try_access_with<R, F: FnOnce(&T) -> R>(&self, f: F) -> Option<R> { 355 self.data().try_access_with(f) 356 } 357 358 /// [`Devres`] accessor for [`Revocable::try_access_with_guard`]. 359 pub fn try_access_with_guard<'a>(&'a self, guard: &'a rcu::Guard) -> Option<&'a T> { 360 self.data().try_access_with_guard(guard) 361 } 362 } 363 364 // SAFETY: `Devres` can be send to any task, if `T: Send`. 365 unsafe impl<T: Send> Send for Devres<T> {} 366 367 // SAFETY: `Devres` can be shared with any task, if `T: Sync`. 368 unsafe impl<T: Send + Sync> Sync for Devres<T> {} 369 370 impl<T: Send + 'static> Drop for Devres<T> { 371 fn drop(&mut self) { 372 // SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data 373 // anymore, hence it is safe not to wait for the grace period to finish. 374 if unsafe { self.data().revoke_nosync() } { 375 self.inner.revocation.complete_all(); 376 377 // We revoked `self.data` before devres did, hence try to remove it. 378 if self.remove_node() { 379 // SAFETY: In `Self::new` we have taken an additional reference count of `self.data` 380 // for `devres_node_add()`. Since `remove_node()` was successful, we have to drop 381 // this additional reference count. 382 drop(unsafe { Arc::from_raw(Arc::as_ptr(&self.inner)) }); 383 } 384 } else { 385 // The release callback is concurrently revoking; wait for it to finish 386 // `drop_in_place()` of the wrapped object before returning. 387 self.inner.revocation.wait_for_completion(); 388 } 389 } 390 } 391 392 /// Guard returned by [`DevresLt::try_access`]. 393 /// 394 /// Dereferences to `F::Of<'a>`, shortening the lifetime of the stored data to the guard's borrow 395 /// lifetime. 396 pub struct DevresGuard<'a, F: CovariantForLt>(RevocableGuard<'a, F::Of<'static>>); 397 398 impl<'a, F: CovariantForLt> core::ops::Deref for DevresGuard<'a, F> { 399 type Target = F::Of<'a>; 400 401 #[inline] 402 fn deref(&self) -> &Self::Target { 403 F::cast_ref(&*self.0) 404 } 405 } 406 407 /// Device-managed resource with [`ForLt`](trait@ForLt)-aware access. 408 /// 409 /// `DevresLt` wraps [`Devres`] and shortens the stored `'static` lifetime to the caller's borrow 410 /// lifetime in all access methods. 411 /// 412 /// Types that implement [`trait@CovariantForLt`] get direct-reference accessors ([`Self::access`], 413 /// [`Self::try_access`]). Plain [`ForLt`](trait@ForLt) types use closure-based accessors 414 /// ([`Self::access_with`], [`Self::try_access_with`]). 415 pub struct DevresLt<F: ForLt>(Devres<F::Of<'static>>) 416 where 417 for<'a> F::Of<'a>: Send; 418 419 impl<F: ForLt> DevresLt<F> 420 where 421 for<'a> F::Of<'a>: Send, 422 { 423 /// Creates a new [`DevresLt`] instance of the given `data`. 424 /// 425 /// # Safety 426 /// 427 /// The data must remain valid for the device's full bound scope. [`DevresLt`] allows 428 /// access until the device is unbound, which may outlast `'a`. 429 pub unsafe fn new<'a, E>( 430 dev: &'a Device<Bound>, 431 data: impl PinInit<F::Of<'a>, E>, 432 ) -> Result<Self> 433 where 434 Error: From<E>, 435 { 436 // SAFETY: The caller guarantees the data is valid for the device's full bound scope. 437 // Lifetimes do not affect layout, so F::Of<'a> and F::Of<'static> have identical 438 // representation; casting the slot pointer is sound. 439 let data = unsafe { pin_init::cast_pin_init(data) }; 440 441 Ok(Self(Devres::new(dev, data)?)) 442 } 443 444 /// Return a reference of the [`Device`] this [`DevresLt`] instance has been created with. 445 #[inline] 446 pub fn device(&self) -> &Device { 447 self.0.device() 448 } 449 450 /// Obtain `&F::Of<'_>`, bypassing the [`Revocable`], through a closure. 451 /// 452 /// This method works like [`DevresLt::access`](DevresLt::access) but accepts any 453 /// [`trait@ForLt`] type, not just [`trait@CovariantForLt`]. 454 #[inline] 455 pub fn access_with<R, G>(&self, dev: &Device<Bound>, f: G) -> Result<R> 456 where 457 G: for<'a> FnOnce(&F::Of<'a>) -> R, 458 { 459 self.0.access(dev).map(f) 460 } 461 462 /// [`DevresLt`] accessor for [`Revocable::try_access_with`]. 463 #[inline] 464 pub fn try_access_with<R, G>(&self, f: G) -> Option<R> 465 where 466 G: for<'a> FnOnce(&F::Of<'a>) -> R, 467 { 468 self.0.data().try_access_with(f) 469 } 470 } 471 472 impl<F: CovariantForLt> DevresLt<F> 473 where 474 for<'a> F::Of<'a>: Send, 475 { 476 /// Obtain `&'a F::Of<'a>`, bypassing the [`Revocable`]. 477 /// 478 /// This method works like [`Devres::access`], but shortens the returned reference's lifetime 479 /// from `'static` to `'a` via [`CovariantForLt::cast_ref`]. 480 #[inline] 481 pub fn access<'a>(&'a self, dev: &'a Device<Bound>) -> Result<&'a F::Of<'a>> { 482 self.0.access(dev).map(F::cast_ref) 483 } 484 485 /// [`DevresLt`] accessor for [`Revocable::try_access`]. 486 #[inline] 487 pub fn try_access(&self) -> Option<DevresGuard<'_, F>> { 488 self.0.data().try_access().map(DevresGuard) 489 } 490 } 491 492 /// Consume `data` and [`Drop::drop`] `data` once `dev` is unbound. 493 fn register_foreign<P>(dev: &Device<Bound>, data: P) -> Result 494 where 495 P: ForeignOwnable + Send + 'static, 496 { 497 let ptr = data.into_foreign(); 498 499 #[allow(clippy::missing_safety_doc)] 500 unsafe extern "C" fn callback<P: ForeignOwnable>(ptr: *mut kernel::ffi::c_void) { 501 // SAFETY: `ptr` is the pointer to the `ForeignOwnable` leaked above and hence valid. 502 drop(unsafe { P::from_foreign(ptr.cast()) }); 503 } 504 505 // SAFETY: 506 // - `dev.as_raw()` is a pointer to a valid and bound device. 507 // - `ptr` is a valid pointer the `ForeignOwnable` devres takes ownership of. 508 to_result(unsafe { 509 // `devm_add_action_or_reset()` also calls `callback` on failure, such that the 510 // `ForeignOwnable` is released eventually. 511 bindings::devm_add_action_or_reset(dev.as_raw(), Some(callback::<P>), ptr.cast()) 512 }) 513 } 514 515 /// Encapsulate `data` in a [`KBox`] and [`Drop::drop`] `data` once `dev` is unbound. 516 /// 517 /// # Examples 518 /// 519 /// ```no_run 520 /// use kernel::{ 521 /// device::{ 522 /// Bound, 523 /// Device, // 524 /// }, 525 /// devres, // 526 /// }; 527 /// 528 /// /// Registration of e.g. a class device, IRQ, etc. 529 /// struct Registration; 530 /// 531 /// impl Registration { 532 /// fn new() -> Self { 533 /// // register 534 /// 535 /// Self 536 /// } 537 /// } 538 /// 539 /// impl Drop for Registration { 540 /// fn drop(&mut self) { 541 /// // unregister 542 /// } 543 /// } 544 /// 545 /// fn from_bound_context(dev: &Device<Bound>) -> Result { 546 /// devres::register(dev, Registration::new(), GFP_KERNEL) 547 /// } 548 /// ``` 549 pub fn register<T, E>(dev: &Device<Bound>, data: impl PinInit<T, E>, flags: Flags) -> Result 550 where 551 T: Send + 'static, 552 Error: From<E>, 553 { 554 let data = KBox::pin_init(data, flags)?; 555 556 register_foreign(dev, data) 557 } 558