From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D216349B1D for ; Wed, 14 Jan 2026 19:40:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.48 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768419640; cv=none; b=qPGOtwvA03ZFxFzmZgNHyt0NS/p37l9dhX15yuww4X8RfaFukFNI1ryXrrYuP+jceG33Gs1sas3sEt+tK3becet6zGU5s1Po6jrgQBNSIfKIjUgU4vUEufZdsng/Wg+bKdGmBCQLJ+9DPOxUTxFMDT/CFKfBYx2LONMlIdGfn0k= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768419640; c=relaxed/simple; bh=ykLH2MgbCvBBlz1nfxnm2nxGWsprbZ68o9/wmnQtSQg=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=BzW4Ex8XGy9QwuN7nNiFj70GgdlFE2Gd6hKcSxa5UCTFTlldnEm6R/ATXZFNn7o+NLq/Sj8y8SD7Q9lYV9wQPyVrIi67z9hX96Wsw1bnZov2iHD05whuVitZlHZNYnZjV7c1wgMFlULz6WqAYYVT+0mm6o46eXyl98Yp2Hawtww= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ZmBYlfI5; arc=none smtp.client-ip=209.85.221.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZmBYlfI5" Received: by mail-wr1-f48.google.com with SMTP id ffacd0b85a97d-4327555464cso101951f8f.1 for ; Wed, 14 Jan 2026 11:40:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768419636; x=1769024436; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=Scpe9pFl2VETM92or+Eva19ojkvY4Xd+w6SP7ONyFrE=; b=ZmBYlfI51rt514x4jVU2s6nzIWHbuR43vHtcq+biRQMlpYpBCloeOyyme5NmOATh7f 4eOGfT8J39lVkXBg5dmDCu5eWCwly3b3pGPU3h0xYnln/hUN5ApbGGKsymxNHETfuzP+ mWsRJgCiEtAvCcFwaHx0BjvbCjF92XQs2LYHMCai0ptmbxmzoDuXhx1C533s2ATg8cKp HHJgx3U08ABQEUa8KM4N1CtFO1ZHbdqHE8lXKUc3pftbpmcuvhBs+Qke30KbCHjkDqxd fea20GF4JC05brbPuLg46oIqIN2yN/H5sbgL7QXZ3Q5Ydu6HB8FHZv6Plh4cFUy/owJE 5LXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768419636; x=1769024436; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Scpe9pFl2VETM92or+Eva19ojkvY4Xd+w6SP7ONyFrE=; b=sTGknbXjl4MbGk0+A/IvgpEoa2ZO8d8n99cbiR4iEoBosYmyMyFRLjFOQpWXGDv0MY cbJMXTYfNOTcYGN7MCIhB4b7OAWP1VOb/j79Cl5zlMDCRXhqF8fb2EOwGNULbCct26PK kJh/34htb7df/cTE8LrDD66CL8N+MyU4/GUZU8F8Y9mc1cR/sqLgs6ZrZHgcRf17qcWX QQk3QkpeViiYXJ3/hUJxRFDSU2GCysEGh84atBiI0bI4W9UqpkXz/h5e0/g6EZsyqWoS Qv86oa0IDkR3OCi6GgX9mW/VBIwAqyVjyDgrekUWK2v6S/THbjQx8GRDnrW+atQkq8wU uKxw== X-Gm-Message-State: AOJu0YwkrA3LBKA4j/vtRHkwlJyVEPXXagBOmdSE8n3pdDmd9W/QzhXk 1oYew3DZWN7gcFSlRrqlFj9V8849x/ZpO3bLmN/lE77ZZDzGosXhUCGU X-Gm-Gg: AY/fxX7685TQZVg/1alHJLWJRaQYn/2YhRIUCi8ccIzOieH9fDUtc8nKVo+3WHzPBqM mUaUCMHMmirwyuy4YO5/1aMXkvacZ1U8ixpHAHGgqer8WL0cbv/HzFkQACt/77ffQaZs38VNGRG yfnYZ1tX3QZI1Zlh/gqsS8GO6YHfkgdR53rXEE+hmzrF/57UTMZDgAd7+Cy+d5UYvbtZoC0iutl c62EoJ6UzuiID1IxcCz46DypsioBlr40r16xqN5xtclDragNEGxw2yg9ZIOTCGGJ7knNH5y4azR FYp8w0FYC6pe9DoYpGZBMqVMoHaP/k0Rq1nnFsLyT279hniocEv36WlvEJRYD+aCcCmCnDIb2pR JJK8ACSMlvi/k2MlS4RZVE3YcvgUJpyJ3BOi5aiCAKKUxkR/WeSueRq9huO3ZrHVWOQAqWTs6Gs ZVVbRmY0bqxyDXtCMMd/vTiyWJOQR9xpLtUp1aWS2esYOYM5Z6LnV23AHeX1lJEVNFCscZYtim2 avwIA== X-Received: by 2002:a5d:5d0a:0:b0:430:fd84:3175 with SMTP id ffacd0b85a97d-4342c535d4cmr5459711f8f.38.1768419635614; Wed, 14 Jan 2026 11:40:35 -0800 (PST) Received: from ?IPV6:2a06:5906:2639:e200:7139:7167:2ab3:2206? ([2a06:5906:2639:e200:7139:7167:2ab3:2206]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-434af64a778sm1065645f8f.3.2026.01.14.11.40.34 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Jan 2026 11:40:35 -0800 (PST) Message-ID: Date: Wed, 14 Jan 2026 19:40:34 +0000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH 3/6] rust: driver: introduce a common Driver trait To: Danilo Krummrich , gregkh@linuxfoundation.org, rafael@kernel.org, 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 References: <20260107103511.570525-1-dakr@kernel.org> <20260107103511.570525-4-dakr@kernel.org> Content-Language: en-US From: Igor Korotin In-Reply-To: <20260107103511.570525-4-dakr@kernel.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 1/7/2026 10:35 AM, Danilo Krummrich wrote: > 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 > --- > 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); > > -// 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 driver::Driver for Adapter { > + 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 driver::RegistrationOps for Adapter { > - type RegType = bindings::auxiliary_driver; > - > unsafe fn register( > - adrv: &Opaque, > + adrv: &Opaque, > 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) { > - // SAFETY: `adrv` is guaranteed to be a valid `RegType`. > + unsafe fn unregister(adrv: &Opaque) { > + // 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, > + reg: &Opaque, > 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); > + unsafe fn unregister(reg: &Opaque); > } > > /// 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 { > #[pin] > - reg: Opaque, > + reg: Opaque, > } > > // SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to > @@ -161,13 +171,13 @@ impl Registration { > /// Creates a new instance of the registration object. > pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit { > 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) }; > + let drv = unsafe { &*(ptr as *const Opaque) }; > > // 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); > > -// 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 driver::Driver for Adapter { > + 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 driver::RegistrationOps for Adapter { > - type RegType = bindings::i2c_driver; > - > unsafe fn register( > - idrv: &Opaque, > + idrv: &Opaque, > 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) { > - // SAFETY: `idrv` is guaranteed to be a valid `RegType`. > + unsafe fn unregister(idrv: &Opaque) { > + // 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); > > -// 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 driver::Driver for Adapter { > + 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 driver::RegistrationOps for Adapter { > - type RegType = bindings::pci_driver; > - > unsafe fn register( > - pdrv: &Opaque, > + pdrv: &Opaque, > 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) { > - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. > + unsafe fn unregister(pdrv: &Opaque) { > + // 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); > > -// 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 driver::Driver for Adapter { > + 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 driver::RegistrationOps for Adapter { > - type RegType = bindings::platform_driver; > - > unsafe fn register( > - pdrv: &Opaque, > + pdrv: &Opaque, > 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) { > - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. > + unsafe fn unregister(pdrv: &Opaque) { > + // 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); > > -// 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 driver::Driver for Adapter { > + 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 driver::RegistrationOps for Adapter { > - type RegType = bindings::usb_driver; > - > unsafe fn register( > - udrv: &Opaque, > + udrv: &Opaque, > 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) { > - // SAFETY: `udrv` is guaranteed to be a valid `RegType`. > + unsafe fn unregister(udrv: &Opaque) { > + // SAFETY: `udrv` is guaranteed to be a valid `DriverType`. > unsafe { bindings::usb_deregister(udrv.get()) }; > } > } Acked-by: Igor Korotin Cheers Igor