Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'topic/device-context-2025-04-17' into driver-core-next

Introduce "Bound" device context

Introduce the "Bound" device context, such that it can be ensured to only
ever pass a bound device to APIs that require this precondition. [1]

This tag exists to share the patches from [1] between multiple trees.

[1] https://lore.kernel.org/lkml/20250413173758.12068-1-dakr@kernel.org/

+121 -65
+88 -2
rust/kernel/device.rs
··· 9 9 str::CStr, 10 10 types::{ARef, Opaque}, 11 11 }; 12 - use core::{fmt, ptr}; 12 + use core::{fmt, marker::PhantomData, ptr}; 13 13 14 14 #[cfg(CONFIG_PRINTK)] 15 15 use crate::c_str; ··· 42 42 /// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be 43 43 /// dropped from any thread. 44 44 #[repr(transparent)] 45 - pub struct Device(Opaque<bindings::device>); 45 + pub struct Device<Ctx: DeviceContext = Normal>(Opaque<bindings::device>, PhantomData<Ctx>); 46 46 47 47 impl Device { 48 48 /// Creates a new reference-counted abstraction instance of an existing `struct device` pointer. ··· 59 59 // SAFETY: By the safety requirements ptr is valid 60 60 unsafe { Self::as_ref(ptr) }.into() 61 61 } 62 + } 62 63 64 + impl<Ctx: DeviceContext> Device<Ctx> { 63 65 /// Obtain the raw `struct device *`. 64 66 pub(crate) fn as_raw(&self) -> *mut bindings::device { 65 67 self.0.get() ··· 191 189 } 192 190 } 193 191 192 + // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic 193 + // argument. 194 + kernel::impl_device_context_deref!(unsafe { Device }); 195 + kernel::impl_device_context_into_aref!(Device); 196 + 194 197 // SAFETY: Instances of `Device` are always reference-counted. 195 198 unsafe impl crate::types::AlwaysRefCounted for Device { 196 199 fn inc_ref(&self) { ··· 232 225 /// any of the bus callbacks, such as `probe()`. 233 226 pub struct Core; 234 227 228 + /// The [`Bound`] context is the context of a bus specific device reference when it is guaranteed to 229 + /// be bound for the duration of its lifetime. 230 + pub struct Bound; 231 + 235 232 mod private { 236 233 pub trait Sealed {} 237 234 235 + impl Sealed for super::Bound {} 238 236 impl Sealed for super::Core {} 239 237 impl Sealed for super::Normal {} 240 238 } 241 239 240 + impl DeviceContext for Bound {} 242 241 impl DeviceContext for Core {} 243 242 impl DeviceContext for Normal {} 243 + 244 + /// # Safety 245 + /// 246 + /// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the 247 + /// generic argument of `$device`. 248 + #[doc(hidden)] 249 + #[macro_export] 250 + macro_rules! __impl_device_context_deref { 251 + (unsafe { $device:ident, $src:ty => $dst:ty }) => { 252 + impl ::core::ops::Deref for $device<$src> { 253 + type Target = $device<$dst>; 254 + 255 + fn deref(&self) -> &Self::Target { 256 + let ptr: *const Self = self; 257 + 258 + // CAST: `$device<$src>` and `$device<$dst>` transparently wrap the same type by the 259 + // safety requirement of the macro. 260 + let ptr = ptr.cast::<Self::Target>(); 261 + 262 + // SAFETY: `ptr` was derived from `&self`. 263 + unsafe { &*ptr } 264 + } 265 + } 266 + }; 267 + } 268 + 269 + /// Implement [`core::ops::Deref`] traits for allowed [`DeviceContext`] conversions of a (bus 270 + /// specific) device. 271 + /// 272 + /// # Safety 273 + /// 274 + /// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the 275 + /// generic argument of `$device`. 276 + #[macro_export] 277 + macro_rules! impl_device_context_deref { 278 + (unsafe { $device:ident }) => { 279 + // SAFETY: This macro has the exact same safety requirement as 280 + // `__impl_device_context_deref!`. 281 + ::kernel::__impl_device_context_deref!(unsafe { 282 + $device, 283 + $crate::device::Core => $crate::device::Bound 284 + }); 285 + 286 + // SAFETY: This macro has the exact same safety requirement as 287 + // `__impl_device_context_deref!`. 288 + ::kernel::__impl_device_context_deref!(unsafe { 289 + $device, 290 + $crate::device::Bound => $crate::device::Normal 291 + }); 292 + }; 293 + } 294 + 295 + #[doc(hidden)] 296 + #[macro_export] 297 + macro_rules! __impl_device_context_into_aref { 298 + ($src:ty, $device:tt) => { 299 + impl ::core::convert::From<&$device<$src>> for $crate::types::ARef<$device> { 300 + fn from(dev: &$device<$src>) -> Self { 301 + (&**dev).into() 302 + } 303 + } 304 + }; 305 + } 306 + 307 + /// Implement [`core::convert::From`], such that all `&Device<Ctx>` can be converted to an 308 + /// `ARef<Device>`. 309 + #[macro_export] 310 + macro_rules! impl_device_context_into_aref { 311 + ($device:tt) => { 312 + ::kernel::__impl_device_context_into_aref!($crate::device::Core, $device); 313 + ::kernel::__impl_device_context_into_aref!($crate::device::Bound, $device); 314 + }; 315 + } 244 316 245 317 #[doc(hidden)] 246 318 #[macro_export]
+7 -10
rust/kernel/devres.rs
··· 8 8 use crate::{ 9 9 alloc::Flags, 10 10 bindings, 11 - device::Device, 11 + device::{Bound, Device}, 12 12 error::{Error, Result}, 13 13 ffi::c_void, 14 14 prelude::*, ··· 45 45 /// # Example 46 46 /// 47 47 /// ```no_run 48 - /// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{Io, IoRaw}}; 48 + /// # use kernel::{bindings, c_str, device::{Bound, Device}, devres::Devres, io::{Io, IoRaw}}; 49 49 /// # use core::ops::Deref; 50 50 /// 51 51 /// // See also [`pci::Bar`] for a real example. ··· 83 83 /// unsafe { Io::from_raw(&self.0) } 84 84 /// } 85 85 /// } 86 - /// # fn no_run() -> Result<(), Error> { 87 - /// # // SAFETY: Invalid usage; just for the example to get an `ARef<Device>` instance. 88 - /// # let dev = unsafe { Device::get_device(core::ptr::null_mut()) }; 89 - /// 86 + /// # fn no_run(dev: &Device<Bound>) -> Result<(), Error> { 90 87 /// // SAFETY: Invalid usage for example purposes. 91 88 /// let iomem = unsafe { IoMem::<{ core::mem::size_of::<u32>() }>::new(0xBAAAAAAD)? }; 92 - /// let devres = Devres::new(&dev, iomem, GFP_KERNEL)?; 89 + /// let devres = Devres::new(dev, iomem, GFP_KERNEL)?; 93 90 /// 94 91 /// let res = devres.try_access().ok_or(ENXIO)?; 95 92 /// res.write8(0x42, 0x0); ··· 96 99 pub struct Devres<T>(Arc<DevresInner<T>>); 97 100 98 101 impl<T> DevresInner<T> { 99 - fn new(dev: &Device, data: T, flags: Flags) -> Result<Arc<DevresInner<T>>> { 102 + fn new(dev: &Device<Bound>, data: T, flags: Flags) -> Result<Arc<DevresInner<T>>> { 100 103 let inner = Arc::pin_init( 101 104 pin_init!( DevresInner { 102 105 dev: dev.into(), ··· 168 171 impl<T> Devres<T> { 169 172 /// Creates a new [`Devres`] instance of the given `data`. The `data` encapsulated within the 170 173 /// returned `Devres` instance' `data` will be revoked once the device is detached. 171 - pub fn new(dev: &Device, data: T, flags: Flags) -> Result<Self> { 174 + pub fn new(dev: &Device<Bound>, data: T, flags: Flags) -> Result<Self> { 172 175 let inner = DevresInner::new(dev, data, flags)?; 173 176 174 177 Ok(Devres(inner)) ··· 176 179 177 180 /// Same as [`Devres::new`], but does not return a `Devres` instance. Instead the given `data` 178 181 /// is owned by devres and will be revoked / dropped, once the device is detached. 179 - pub fn new_foreign_owned(dev: &Device, data: T, flags: Flags) -> Result { 182 + pub fn new_foreign_owned(dev: &Device<Bound>, data: T, flags: Flags) -> Result { 180 183 let _ = DevresInner::new(dev, data, flags)?; 181 184 182 185 Ok(())
+7 -7
rust/kernel/dma.rs
··· 6 6 7 7 use crate::{ 8 8 bindings, build_assert, 9 - device::Device, 9 + device::{Bound, Device}, 10 10 error::code::*, 11 11 error::Result, 12 12 transmute::{AsBytes, FromBytes}, ··· 22 22 /// # Examples 23 23 /// 24 24 /// ``` 25 - /// use kernel::device::Device; 25 + /// # use kernel::device::{Bound, Device}; 26 26 /// use kernel::dma::{attrs::*, CoherentAllocation}; 27 27 /// 28 - /// # fn test(dev: &Device) -> Result { 28 + /// # fn test(dev: &Device<Bound>) -> Result { 29 29 /// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN; 30 30 /// let c: CoherentAllocation<u64> = 31 31 /// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?; ··· 143 143 /// # Examples 144 144 /// 145 145 /// ``` 146 - /// use kernel::device::Device; 146 + /// # use kernel::device::{Bound, Device}; 147 147 /// use kernel::dma::{attrs::*, CoherentAllocation}; 148 148 /// 149 - /// # fn test(dev: &Device) -> Result { 149 + /// # fn test(dev: &Device<Bound>) -> Result { 150 150 /// let c: CoherentAllocation<u64> = 151 151 /// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?; 152 152 /// # Ok::<(), Error>(()) } 153 153 /// ``` 154 154 pub fn alloc_attrs( 155 - dev: &Device, 155 + dev: &Device<Bound>, 156 156 count: usize, 157 157 gfp_flags: kernel::alloc::Flags, 158 158 dma_attrs: Attrs, ··· 194 194 /// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the 195 195 /// `dma_attrs` is 0 by default. 196 196 pub fn alloc_coherent( 197 - dev: &Device, 197 + dev: &Device<Bound>, 198 198 count: usize, 199 199 gfp_flags: kernel::alloc::Flags, 200 200 ) -> Result<CoherentAllocation<T>> {
+11 -22
rust/kernel/pci.rs
··· 360 360 } 361 361 } 362 362 363 - impl Device { 363 + impl<Ctx: device::DeviceContext> Device<Ctx> { 364 364 fn as_raw(&self) -> *mut bindings::pci_dev { 365 365 self.0.get() 366 366 } 367 + } 367 368 369 + impl Device { 368 370 /// Returns the PCI vendor ID. 369 371 pub fn vendor_id(&self) -> u16 { 370 372 // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. ··· 390 388 // - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`. 391 389 Ok(unsafe { bindings::pci_resource_len(self.as_raw(), bar.try_into()?) }) 392 390 } 391 + } 393 392 393 + impl Device<device::Bound> { 394 394 /// Mapps an entire PCI-BAR after performing a region-request on it. I/O operation bound checks 395 395 /// can be performed on compile time for offsets (plus the requested type size) < SIZE. 396 396 pub fn iomap_region_sized<const SIZE: usize>( ··· 426 422 } 427 423 } 428 424 429 - impl Deref for Device<device::Core> { 430 - type Target = Device; 431 - 432 - fn deref(&self) -> &Self::Target { 433 - let ptr: *const Self = self; 434 - 435 - // CAST: `Device<Ctx>` is a transparent wrapper of `Opaque<bindings::pci_dev>`. 436 - let ptr = ptr.cast::<Device>(); 437 - 438 - // SAFETY: `ptr` was derived from `&self`. 439 - unsafe { &*ptr } 440 - } 441 - } 442 - 443 - impl From<&Device<device::Core>> for ARef<Device> { 444 - fn from(dev: &Device<device::Core>) -> Self { 445 - (&**dev).into() 446 - } 447 - } 425 + // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic 426 + // argument. 427 + kernel::impl_device_context_deref!(unsafe { Device }); 428 + kernel::impl_device_context_into_aref!(Device); 448 429 449 430 // SAFETY: Instances of `Device` are always reference-counted. 450 431 unsafe impl crate::types::AlwaysRefCounted for Device { ··· 444 455 } 445 456 } 446 457 447 - impl AsRef<device::Device> for Device { 448 - fn as_ref(&self) -> &device::Device { 458 + impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> { 459 + fn as_ref(&self) -> &device::Device<Ctx> { 449 460 // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid 450 461 // `struct pci_dev`. 451 462 let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) };
+8 -24
rust/kernel/platform.rs
··· 10 10 of, 11 11 prelude::*, 12 12 str::CStr, 13 - types::{ARef, ForeignOwnable, Opaque}, 13 + types::{ForeignOwnable, Opaque}, 14 14 ThisModule, 15 15 }; 16 16 17 17 use core::{ 18 18 marker::PhantomData, 19 - ops::Deref, 20 19 ptr::{addr_of_mut, NonNull}, 21 20 }; 22 21 ··· 183 184 PhantomData<Ctx>, 184 185 ); 185 186 186 - impl Device { 187 + impl<Ctx: device::DeviceContext> Device<Ctx> { 187 188 fn as_raw(&self) -> *mut bindings::platform_device { 188 189 self.0.get() 189 190 } 190 191 } 191 192 192 - impl Deref for Device<device::Core> { 193 - type Target = Device; 194 - 195 - fn deref(&self) -> &Self::Target { 196 - let ptr: *const Self = self; 197 - 198 - // CAST: `Device<Ctx>` is a transparent wrapper of `Opaque<bindings::platform_device>`. 199 - let ptr = ptr.cast::<Device>(); 200 - 201 - // SAFETY: `ptr` was derived from `&self`. 202 - unsafe { &*ptr } 203 - } 204 - } 205 - 206 - impl From<&Device<device::Core>> for ARef<Device> { 207 - fn from(dev: &Device<device::Core>) -> Self { 208 - (&**dev).into() 209 - } 210 - } 193 + // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic 194 + // argument. 195 + kernel::impl_device_context_deref!(unsafe { Device }); 196 + kernel::impl_device_context_into_aref!(Device); 211 197 212 198 // SAFETY: Instances of `Device` are always reference-counted. 213 199 unsafe impl crate::types::AlwaysRefCounted for Device { ··· 207 223 } 208 224 } 209 225 210 - impl AsRef<device::Device> for Device { 211 - fn as_ref(&self) -> &device::Device { 226 + impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> { 227 + fn as_ref(&self) -> &device::Device<Ctx> { 212 228 // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid 213 229 // `struct platform_device`. 214 230 let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) };