diff options
| author | Benjamin Tissoires <bentiss@kernel.org> | 2025-09-30 16:31:10 +0200 | 
|---|---|---|
| committer | Benjamin Tissoires <bentiss@kernel.org> | 2025-09-30 16:31:10 +0200 | 
| commit | d325efac5938efa3c2a25df72a1bd1af16cd0ed8 (patch) | |
| tree | 6bb0db4f21bd6359bb32f3beeb63231477b09ef3 /rust/kernel/drm | |
| parent | bba920e6f803138587248079de47ad3464a396f6 (diff) | |
| parent | d1dd75c6500c74b91c5286fd3277710371d3e3ca (diff) | |
Merge branch 'for-6.18/core' into for-linus
- allow HID-BPF to rebind a driver to hid-multitouch (Benjamin
  Tissoires)
- Change hid_driver to use a const char* for .name (Rahul Rameshbabu)
Diffstat (limited to 'rust/kernel/drm')
| -rw-r--r-- | rust/kernel/drm/device.rs | 42 | ||||
| -rw-r--r-- | rust/kernel/drm/gem/mod.rs | 4 | 
2 files changed, 30 insertions, 16 deletions
| diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index 32029fde55eb..d29c477e89a8 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -5,6 +5,7 @@  //! C header: [`include/linux/drm/drm_device.h`](srctree/include/linux/drm/drm_device.h)  use crate::{ +    alloc::allocator::Kmalloc,      bindings, device, drm,      drm::driver::AllocImpl,      error::from_err_ptr, @@ -12,7 +13,7 @@ use crate::{      prelude::*,      types::{ARef, AlwaysRefCounted, Opaque},  }; -use core::{mem, ops::Deref, ptr, ptr::NonNull}; +use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull};  #[cfg(CONFIG_DRM_LEGACY)]  macro_rules! drm_legacy_fields { @@ -53,10 +54,8 @@ macro_rules! drm_legacy_fields {  ///  /// `self.dev` is a valid instance of a `struct device`.  #[repr(C)] -#[pin_data]  pub struct Device<T: drm::Driver> {      dev: Opaque<bindings::drm_device>, -    #[pin]      data: T::Data,  } @@ -83,19 +82,23 @@ impl<T: drm::Driver> Device<T> {          major: T::INFO.major,          minor: T::INFO.minor,          patchlevel: T::INFO.patchlevel, -        name: T::INFO.name.as_char_ptr() as *mut _, -        desc: T::INFO.desc.as_char_ptr() as *mut _, +        name: T::INFO.name.as_char_ptr().cast_mut(), +        desc: T::INFO.desc.as_char_ptr().cast_mut(),          driver_features: drm::driver::FEAT_GEM,          ioctls: T::IOCTLS.as_ptr(),          num_ioctls: T::IOCTLS.len() as i32, -        fops: &Self::GEM_FOPS as _, +        fops: &Self::GEM_FOPS,      };      const GEM_FOPS: bindings::file_operations = drm::gem::create_fops();      /// Create a new `drm::Device` for a `drm::Driver`.      pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<ARef<Self>> { +        // `__drm_dev_alloc` uses `kmalloc()` to allocate memory, hence ensure a `kmalloc()` +        // compatible `Layout`. +        let layout = Kmalloc::aligned_layout(Layout::new::<Self>()); +          // SAFETY:          // - `VTABLE`, as a `const` is pinned to the read-only section of the compilation,          // - `dev` is valid by its type invarants, @@ -103,7 +106,7 @@ impl<T: drm::Driver> Device<T> {              bindings::__drm_dev_alloc(                  dev.as_raw(),                  &Self::VTABLE, -                mem::size_of::<Self>(), +                layout.size(),                  mem::offset_of!(Self, dev),              )          } @@ -117,9 +120,13 @@ impl<T: drm::Driver> Device<T> {          // - `raw_data` is a valid pointer to uninitialized memory.          // - `raw_data` will not move until it is dropped.          unsafe { data.__pinned_init(raw_data) }.inspect_err(|_| { -            // SAFETY: `__drm_dev_alloc()` was successful, hence `raw_drm` must be valid and the +            // SAFETY: `raw_drm` is a valid pointer to `Self`, given that `__drm_dev_alloc` was +            // successful. +            let drm_dev = unsafe { Self::into_drm_device(raw_drm) }; + +            // SAFETY: `__drm_dev_alloc()` was successful, hence `drm_dev` must be valid and the              // refcount must be non-zero. -            unsafe { bindings::drm_dev_put(ptr::addr_of_mut!((*raw_drm.as_ptr()).dev).cast()) }; +            unsafe { bindings::drm_dev_put(drm_dev) };          })?;          // SAFETY: The reference count is one, and now we take ownership of that reference as a @@ -135,11 +142,17 @@ impl<T: drm::Driver> Device<T> {      ///      /// `ptr` must be a valid pointer to a `struct device` embedded in `Self`.      unsafe fn from_drm_device(ptr: *const bindings::drm_device) -> *mut Self { -        let ptr: *const Opaque<bindings::drm_device> = ptr.cast(); -          // SAFETY: By the safety requirements of this function `ptr` is a valid pointer to a          // `struct drm_device` embedded in `Self`. -        unsafe { crate::container_of!(ptr, Self, dev) }.cast_mut() +        unsafe { crate::container_of!(Opaque::cast_from(ptr), Self, dev) }.cast_mut() +    } + +    /// # Safety +    /// +    /// `ptr` must be a valid pointer to `Self`. +    unsafe fn into_drm_device(ptr: NonNull<Self>) -> *mut bindings::drm_device { +        // SAFETY: By the safety requirements of this function, `ptr` is a valid pointer to `Self`. +        unsafe { &raw mut (*ptr.as_ptr()).dev }.cast()      }      /// Not intended to be called externally, except via declare_drm_ioctls!() @@ -191,8 +204,11 @@ unsafe impl<T: drm::Driver> AlwaysRefCounted for Device<T> {      }      unsafe fn dec_ref(obj: NonNull<Self>) { +        // SAFETY: `obj` is a valid pointer to `Self`. +        let drm_dev = unsafe { Self::into_drm_device(obj) }; +          // SAFETY: The safety requirements guarantee that the refcount is non-zero. -        unsafe { bindings::drm_dev_put(obj.cast().as_ptr()) }; +        unsafe { bindings::drm_dev_put(drm_dev) };      }  } diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index a24c9a2fc201..b71821cfb5ea 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -125,11 +125,9 @@ impl<T: DriverObject> IntoGEMObject for Object<T> {      }      unsafe fn from_raw<'a>(self_ptr: *mut bindings::drm_gem_object) -> &'a Self { -        let self_ptr: *mut Opaque<bindings::drm_gem_object> = self_ptr.cast(); -          // SAFETY: `obj` is guaranteed to be in an `Object<T>` via the safety contract of this          // function -        unsafe { &*crate::container_of!(self_ptr, Object<T>, obj) } +        unsafe { &*crate::container_of!(Opaque::cast_from(self_ptr), Object<T>, obj) }      }  } | 
