public inbox for linux-usb@vger.kernel.org
 help / color / mirror / Atom feed
From: Danilo Krummrich <dakr@kernel.org>
To: gregkh@linuxfoundation.org, rafael@kernel.org,
	igor.korotin.linux@gmail.com, ojeda@kernel.org,
	boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com,
	lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com,
	tmgross@umich.edu, david.m.ertman@intel.com, ira.weiny@intel.com,
	leon@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org,
	wsa+renesas@sang-engineering.com
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	linux-pci@vger.kernel.org, linux-usb@vger.kernel.org,
	linux-i2c@vger.kernel.org, Danilo Krummrich <dakr@kernel.org>
Subject: [PATCH 3/6] rust: driver: introduce a common Driver trait
Date: Wed,  7 Jan 2026 11:35:02 +0100	[thread overview]
Message-ID: <20260107103511.570525-4-dakr@kernel.org> (raw)
In-Reply-To: <20260107103511.570525-1-dakr@kernel.org>

The Driver trait describes the layout of a specific driver structure,
such as `struct pci_driver` or `struct platform_driver`.

In a first step, this replaces the associated type RegType of the
RegistrationOps with the Driver::DriverType associated type.

Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
 rust/kernel/auxiliary.rs | 18 +++++++++++-------
 rust/kernel/driver.rs    | 40 +++++++++++++++++++++++++---------------
 rust/kernel/i2c.rs       | 18 +++++++++++-------
 rust/kernel/pci.rs       | 18 +++++++++++-------
 rust/kernel/platform.rs  | 18 +++++++++++-------
 rust/kernel/usb.rs       | 18 +++++++++++-------
 6 files changed, 80 insertions(+), 50 deletions(-)

diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index 6931f8a4267f..4636b6f41195 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -23,13 +23,17 @@
 /// An adapter for the registration of auxiliary drivers.
 pub struct Adapter<T: Driver>(T);
 
-// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
+// SAFETY:
+// - `bindings::auxiliary_driver` is a C type declared as `repr(C)`.
+unsafe impl<T: Driver + 'static> driver::Driver for Adapter<T> {
+    type DriverType = bindings::auxiliary_driver;
+}
+
+// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
 // a preceding call to `register` has been successful.
 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
-    type RegType = bindings::auxiliary_driver;
-
     unsafe fn register(
-        adrv: &Opaque<Self::RegType>,
+        adrv: &Opaque<Self::DriverType>,
         name: &'static CStr,
         module: &'static ThisModule,
     ) -> Result {
@@ -41,14 +45,14 @@ unsafe fn register(
             (*adrv.get()).id_table = T::ID_TABLE.as_ptr();
         }
 
-        // SAFETY: `adrv` is guaranteed to be a valid `RegType`.
+        // SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
         to_result(unsafe {
             bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr())
         })
     }
 
-    unsafe fn unregister(adrv: &Opaque<Self::RegType>) {
-        // SAFETY: `adrv` is guaranteed to be a valid `RegType`.
+    unsafe fn unregister(adrv: &Opaque<Self::DriverType>) {
+        // SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
         unsafe { bindings::auxiliary_driver_unregister(adrv.get()) }
     }
 }
diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
index 649d06468f41..cd1d36c313e1 100644
--- a/rust/kernel/driver.rs
+++ b/rust/kernel/driver.rs
@@ -99,23 +99,33 @@
 use core::pin::Pin;
 use pin_init::{pin_data, pinned_drop, PinInit};
 
+/// Trait describing the layout of a specific device driver.
+///
+/// This trait describes the layout of a specific driver structure, such as `struct pci_driver` or
+/// `struct platform_driver`.
+///
+/// # Safety
+///
+/// Implementors must guarantee that:
+/// - `DriverType` is `repr(C)`.
+pub unsafe trait Driver {
+    /// The specific driver type embedding a `struct device_driver`.
+    type DriverType: Default;
+}
+
 /// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform,
 /// Amba, etc.) to provide the corresponding subsystem specific implementation to register /
-/// unregister a driver of the particular type (`RegType`).
+/// unregister a driver of the particular type (`DriverType`).
 ///
-/// For instance, the PCI subsystem would set `RegType` to `bindings::pci_driver` and call
+/// For instance, the PCI subsystem would set `DriverType` to `bindings::pci_driver` and call
 /// `bindings::__pci_register_driver` from `RegistrationOps::register` and
 /// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`.
 ///
 /// # Safety
 ///
-/// A call to [`RegistrationOps::unregister`] for a given instance of `RegType` is only valid if a
-/// preceding call to [`RegistrationOps::register`] has been successful.
-pub unsafe trait RegistrationOps {
-    /// The type that holds information about the registration. This is typically a struct defined
-    /// by the C portion of the kernel.
-    type RegType: Default;
-
+/// A call to [`RegistrationOps::unregister`] for a given instance of `DriverType` is only valid if
+/// a preceding call to [`RegistrationOps::register`] has been successful.
+pub unsafe trait RegistrationOps: Driver {
     /// Registers a driver.
     ///
     /// # Safety
@@ -123,7 +133,7 @@ pub unsafe trait RegistrationOps {
     /// On success, `reg` must remain pinned and valid until the matching call to
     /// [`RegistrationOps::unregister`].
     unsafe fn register(
-        reg: &Opaque<Self::RegType>,
+        reg: &Opaque<Self::DriverType>,
         name: &'static CStr,
         module: &'static ThisModule,
     ) -> Result;
@@ -134,7 +144,7 @@ unsafe fn register(
     ///
     /// Must only be called after a preceding successful call to [`RegistrationOps::register`] for
     /// the same `reg`.
-    unsafe fn unregister(reg: &Opaque<Self::RegType>);
+    unsafe fn unregister(reg: &Opaque<Self::DriverType>);
 }
 
 /// A [`Registration`] is a generic type that represents the registration of some driver type (e.g.
@@ -146,7 +156,7 @@ unsafe fn register(
 #[pin_data(PinnedDrop)]
 pub struct Registration<T: RegistrationOps> {
     #[pin]
-    reg: Opaque<T::RegType>,
+    reg: Opaque<T::DriverType>,
 }
 
 // SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to
@@ -161,13 +171,13 @@ impl<T: RegistrationOps> Registration<T> {
     /// Creates a new instance of the registration object.
     pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> {
         try_pin_init!(Self {
-            reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| {
+            reg <- Opaque::try_ffi_init(|ptr: *mut T::DriverType| {
                 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
-                unsafe { ptr.write(T::RegType::default()) };
+                unsafe { ptr.write(T::DriverType::default()) };
 
                 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has
                 // just been initialised above, so it's also valid for read.
-                let drv = unsafe { &*(ptr as *const Opaque<T::RegType>) };
+                let drv = unsafe { &*(ptr as *const Opaque<T::DriverType>) };
 
                 // SAFETY: `drv` is guaranteed to be pinned until `T::unregister`.
                 unsafe { T::register(drv, name, module) }
diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs
index 35b678b78d91..de35961c6903 100644
--- a/rust/kernel/i2c.rs
+++ b/rust/kernel/i2c.rs
@@ -92,13 +92,17 @@ macro_rules! i2c_device_table {
 /// An adapter for the registration of I2C drivers.
 pub struct Adapter<T: Driver>(T);
 
-// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
+// SAFETY:
+// - `bindings::i2c_driver` is a C type declared as `repr(C)`.
+unsafe impl<T: Driver + 'static> driver::Driver for Adapter<T> {
+    type DriverType = bindings::i2c_driver;
+}
+
+// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
 // a preceding call to `register` has been successful.
 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
-    type RegType = bindings::i2c_driver;
-
     unsafe fn register(
-        idrv: &Opaque<Self::RegType>,
+        idrv: &Opaque<Self::DriverType>,
         name: &'static CStr,
         module: &'static ThisModule,
     ) -> Result {
@@ -133,12 +137,12 @@ unsafe fn register(
             (*idrv.get()).driver.acpi_match_table = acpi_table;
         }
 
-        // SAFETY: `idrv` is guaranteed to be a valid `RegType`.
+        // SAFETY: `idrv` is guaranteed to be a valid `DriverType`.
         to_result(unsafe { bindings::i2c_register_driver(module.0, idrv.get()) })
     }
 
-    unsafe fn unregister(idrv: &Opaque<Self::RegType>) {
-        // SAFETY: `idrv` is guaranteed to be a valid `RegType`.
+    unsafe fn unregister(idrv: &Opaque<Self::DriverType>) {
+        // SAFETY: `idrv` is guaranteed to be a valid `DriverType`.
         unsafe { bindings::i2c_del_driver(idrv.get()) }
     }
 }
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 82e128431f08..f58ce35d9c60 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -50,13 +50,17 @@
 /// An adapter for the registration of PCI drivers.
 pub struct Adapter<T: Driver>(T);
 
-// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
+// SAFETY:
+// - `bindings::pci_driver` is a C type declared as `repr(C)`.
+unsafe impl<T: Driver + 'static> driver::Driver for Adapter<T> {
+    type DriverType = bindings::pci_driver;
+}
+
+// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
 // a preceding call to `register` has been successful.
 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
-    type RegType = bindings::pci_driver;
-
     unsafe fn register(
-        pdrv: &Opaque<Self::RegType>,
+        pdrv: &Opaque<Self::DriverType>,
         name: &'static CStr,
         module: &'static ThisModule,
     ) -> Result {
@@ -68,14 +72,14 @@ unsafe fn register(
             (*pdrv.get()).id_table = T::ID_TABLE.as_ptr();
         }
 
-        // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
+        // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
         to_result(unsafe {
             bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr())
         })
     }
 
-    unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
-        // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
+    unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {
+        // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
         unsafe { bindings::pci_unregister_driver(pdrv.get()) }
     }
 }
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index ed889f079cab..e48d055fdc8a 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -26,13 +26,17 @@
 /// An adapter for the registration of platform drivers.
 pub struct Adapter<T: Driver>(T);
 
-// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
+// SAFETY:
+// - `bindings::platform_driver` is a C type declared as `repr(C)`.
+unsafe impl<T: Driver + 'static> driver::Driver for Adapter<T> {
+    type DriverType = bindings::platform_driver;
+}
+
+// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
 // a preceding call to `register` has been successful.
 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
-    type RegType = bindings::platform_driver;
-
     unsafe fn register(
-        pdrv: &Opaque<Self::RegType>,
+        pdrv: &Opaque<Self::DriverType>,
         name: &'static CStr,
         module: &'static ThisModule,
     ) -> Result {
@@ -55,12 +59,12 @@ unsafe fn register(
             (*pdrv.get()).driver.acpi_match_table = acpi_table;
         }
 
-        // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
+        // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
         to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) })
     }
 
-    unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
-        // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
+    unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {
+        // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
         unsafe { bindings::platform_driver_unregister(pdrv.get()) };
     }
 }
diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs
index d10b65e9fb6a..32f4b2d55dfb 100644
--- a/rust/kernel/usb.rs
+++ b/rust/kernel/usb.rs
@@ -27,13 +27,17 @@
 /// An adapter for the registration of USB drivers.
 pub struct Adapter<T: Driver>(T);
 
-// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
+// SAFETY:
+// - `bindings::usb_driver` is a C type declared as `repr(C)`.
+unsafe impl<T: Driver + 'static> driver::Driver for Adapter<T> {
+    type DriverType = bindings::usb_driver;
+}
+
+// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
 // a preceding call to `register` has been successful.
 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
-    type RegType = bindings::usb_driver;
-
     unsafe fn register(
-        udrv: &Opaque<Self::RegType>,
+        udrv: &Opaque<Self::DriverType>,
         name: &'static CStr,
         module: &'static ThisModule,
     ) -> Result {
@@ -45,14 +49,14 @@ unsafe fn register(
             (*udrv.get()).id_table = T::ID_TABLE.as_ptr();
         }
 
-        // SAFETY: `udrv` is guaranteed to be a valid `RegType`.
+        // SAFETY: `udrv` is guaranteed to be a valid `DriverType`.
         to_result(unsafe {
             bindings::usb_register_driver(udrv.get(), module.0, name.as_char_ptr())
         })
     }
 
-    unsafe fn unregister(udrv: &Opaque<Self::RegType>) {
-        // SAFETY: `udrv` is guaranteed to be a valid `RegType`.
+    unsafe fn unregister(udrv: &Opaque<Self::DriverType>) {
+        // SAFETY: `udrv` is guaranteed to be a valid `DriverType`.
         unsafe { bindings::usb_deregister(udrv.get()) };
     }
 }
-- 
2.52.0


  parent reply	other threads:[~2026-01-07 10:35 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-07 10:34 [PATCH 0/6] Address race condition with Device::drvdata() Danilo Krummrich
2026-01-07 10:35 ` [PATCH 1/6] rust: i2c: do not drop device private data on shutdown() Danilo Krummrich
2026-01-07 10:35 ` [PATCH 2/6] rust: auxiliary: add Driver::unbind() callback Danilo Krummrich
2026-01-07 10:35 ` Danilo Krummrich [this message]
2026-01-14 19:40   ` [PATCH 3/6] rust: driver: introduce a common Driver trait Igor Korotin
2026-01-07 10:35 ` [PATCH 4/6] rust: driver: add DEVICE_DRIVER_OFFSET to the " Danilo Krummrich
2026-01-07 10:35 ` [PATCH 5/6] rust: driver: add DriverData type to the generic " Danilo Krummrich
2026-01-07 10:35 ` [PATCH 6/6] rust: driver: drop device private data post unbind Danilo Krummrich
2026-01-07 12:22   ` Greg KH
2026-01-07 12:50     ` Danilo Krummrich
2026-01-07 14:54       ` Greg KH
2026-01-12 14:27         ` Danilo Krummrich
2026-01-12 15:03           ` Greg KH
2026-01-07 15:51 ` [PATCH 0/6] Address race condition with Device::drvdata() Alice Ryhl
2026-01-07 16:40   ` Danilo Krummrich
2026-01-12 15:34     ` Alice Ryhl
2026-01-12 15:47       ` Danilo Krummrich
2026-01-14 19:50 ` Igor Korotin
2026-01-16  0:23 ` Danilo Krummrich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260107103511.570525-4-dakr@kernel.org \
    --to=dakr@kernel.org \
    --cc=a.hindborg@kernel.org \
    --cc=aliceryhl@google.com \
    --cc=bhelgaas@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=david.m.ertman@intel.com \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=igor.korotin.linux@gmail.com \
    --cc=ira.weiny@intel.com \
    --cc=kwilczynski@kernel.org \
    --cc=leon@kernel.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rafael@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    --cc=wsa+renesas@sang-engineering.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox