From nobody Tue Dec 16 21:03:31 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 55C33182D7; Wed, 12 Mar 2025 00:28:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741739282; cv=none; b=IOlsXGl12leptbwedeIEbRAuWVnv8InzL87uz/lSrdP8ageXbs9euQBvQP9wtY7ictEI1Xz+Kgsod9YezJAi2nzlJqRZcWpMPIbEb0IcgrF/qOPymu1jaueVa+dvq1K49f+RTECVPJuQamDjpse9bTvk0LIyS61bQLvJ2Gw6ZmE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741739282; c=relaxed/simple; bh=wKnEotyoBRZGC7QY5ZaBo6U4Ja9/wBUlJsJ/h76VflY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dJLqExFKjZFBbvaCWUyxg4xcD2KJuO9cWu78FB5lJFi5TpYpkOGEwOLYdaHROrKvoygvE96T+5RpyGtTZ4ckO/66LEpG8PHYYUxsF2o4UAfKhab6Ree7hNhtSrBFULryEZnZNZYqki7zCCSKlqsEQQckuBnuYO6bKt5PQpR66zw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CP2xP6FE; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CP2xP6FE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5C1E4C4CEF0; Wed, 12 Mar 2025 00:27:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741739281; bh=wKnEotyoBRZGC7QY5ZaBo6U4Ja9/wBUlJsJ/h76VflY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CP2xP6FEjqAt+FyA8yYLAi8jRtlJirdojff/juCnxpYb/gs1Y8lGLpuGHsoLig8nr pLszn+JR+fJGePgi4EHdSd6DLkNNRFwBbfv+pSK/Z9BjWCxORvSjREKKmvaX10qvj3 VYGyHSyONbXlwySsOzyJDg1AcgignLD6/Tz+OuLKeyCvq2GAgrLxlKeS/BZx0HBNGw 7tm+6nZppyuP7eXZOEm9IiWh7726KOAORBLCYUSc4R65wbX0pA8L2up6eK0zHJzkAI 9EQ32qozo0fSD06JcsvOqZR/PQnAzeATwFMhy2VMhbKB6g+GTlZUVkOToxCnQMTfto u/xvEqFu1Mhvw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, airlied@gmail.com, acourbot@nvidia.com, jhubbard@nvidia.com Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH 1/4] rust: types: add `Opaque::zeroed` Date: Wed, 12 Mar 2025 01:19:07 +0100 Message-ID: <20250312002741.453350-2-dakr@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250312002741.453350-1-dakr@kernel.org> References: <20250312002741.453350-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Analogous to `Opaque::uninit` add `Opaque::zeroed`, which sets the corresponding memory to zero. In contrast to `Opaque::uninit`, the corresponding value, depending on its type, may be initialized. Signed-off-by: Danilo Krummrich --- rust/kernel/types.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 2bbaab83b9d6..f5e7fed903a7 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -326,6 +326,14 @@ pub const fn uninit() -> Self { } } =20 + /// Creates a new zeroed opaque value. + pub const fn zeroed() -> Self { + Self { + value: UnsafeCell::new(MaybeUninit::zeroed()), + _pin: PhantomPinned, + } + } + /// Create an opaque pin-initializer from the given pin-initializer. pub fn pin_init(slot: impl PinInit) -> impl PinInit { Self::ffi_init(|ptr: *mut T| { --=20 2.48.1 From nobody Tue Dec 16 21:03:31 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F4F913AA20; Wed, 12 Mar 2025 00:28:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741739286; cv=none; b=W0HzXVvxafjQiYhePjRnnBk+Ll67ZaFjqyRXq+Ezdfr1ySIQoUOfnTeKkKWqjWs4/T5NkO+CVBhhKXxitCcZFaNj1inIVhIbPhpY5lYpBNtjUjWJPeAkdc0ajGPSrMc9/Ju2VgaQ8xL4YbWFOFH9cBRIFvx5vPFfHURbnkfSvHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741739286; c=relaxed/simple; bh=RJjzuxgfp2+2/N43POniGGcDYY7qjTAZzOe+4ozWkRo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Imzh8sbN2bwnrklQpmdJY6AKDULhnTWJYCKR4sn8GPs9lmiCFyn5VQuW1/rnY3JYD1C+/6uMp3s9MU0Lst31I7ftXY/5qdB+p0YXhbSWNdi6g/9VOAklJZ0KjVk0V2dtxsgx0Z4Zt1e9VH8ZGBq0zSKA4MIIgOLh2MPO3WKvTt8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=h6eJqs8U; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="h6eJqs8U" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3651AC4CEEE; Wed, 12 Mar 2025 00:28:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741739285; bh=RJjzuxgfp2+2/N43POniGGcDYY7qjTAZzOe+4ozWkRo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=h6eJqs8Usu1n3awVAJKJoW1Jkgb5xdzFlzBFlXPCw7LAPFwKQq2J1VypEKeViKJM7 uA6ar4RPprKYwd3iY9B+964rYSC+CD013R5nUiQe6OPHG0tYe8tj4amwSqjOxIlZC7 50T94XniHZDL2L2veXkSWZRhkmnT4K5mT3x0vZBzpkEf/NDU/NF6x5rUM2VnDs78eu fkCySxbgypESvQ6AzD6OHltW1ng0gB7haU4ydExQitUGM4spAsFdzyUZqN2248UubN jJy72LaVjKK+G293OP1tscHgLJFE/FUxnlVbAoFLRIktu3isfzyo5MVLHQozqo34GD PF+3rSmjwo54A== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, airlied@gmail.com, acourbot@nvidia.com, jhubbard@nvidia.com Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH 2/4] rust: auxiliary: add auxiliary driver abstractions Date: Wed, 12 Mar 2025 01:19:08 +0100 Message-ID: <20250312002741.453350-3-dakr@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250312002741.453350-1-dakr@kernel.org> References: <20250312002741.453350-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement the basic auxiliary abstractions required to implement a driver matching an auxiliary device. The design and implementation is analogous to PCI and platform and is based on the generic device / driver abstractions. Signed-off-by: Danilo Krummrich --- MAINTAINERS | 1 + rust/bindings/bindings_helper.h | 1 + rust/helpers/auxiliary.c | 23 ++++ rust/helpers/helpers.c | 1 + rust/kernel/auxiliary.rs | 233 ++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 2 + 6 files changed, 261 insertions(+) create mode 100644 rust/helpers/auxiliary.c create mode 100644 rust/kernel/auxiliary.rs diff --git a/MAINTAINERS b/MAINTAINERS index f5c7022937a7..0a737b28cdfa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7114,6 +7114,7 @@ F: include/linux/kobj* F: include/linux/property.h F: include/linux/sysfs.h F: lib/kobj* +F: rust/kernel/auxiliary.rs F: rust/kernel/device.rs F: rust/kernel/device_id.rs F: rust/kernel/devres.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index f46cf3bb7069..83026b6e53b2 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -7,6 +7,7 @@ */ =20 #include +#include #include #include #include diff --git a/rust/helpers/auxiliary.c b/rust/helpers/auxiliary.c new file mode 100644 index 000000000000..0db3860d774e --- /dev/null +++ b/rust/helpers/auxiliary.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +void rust_helper_auxiliary_set_drvdata(struct auxiliary_device *adev, void= *data) +{ + auxiliary_set_drvdata(adev, data); +} + +void *rust_helper_auxiliary_get_drvdata(struct auxiliary_device *adev) +{ + return auxiliary_get_drvdata(adev); +} + +void rust_helper_auxiliary_device_uninit(struct auxiliary_device *adev) +{ + return auxiliary_device_uninit(adev); +} + +void rust_helper_auxiliary_device_delete(struct auxiliary_device *adev) +{ + return auxiliary_device_delete(adev); +} diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 0640b7e115be..d744af85e3b2 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -7,6 +7,7 @@ * Sorted alphabetically. */ =20 +#include "auxiliary.c" #include "blk.c" #include "bug.c" #include "build_assert.c" diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs new file mode 100644 index 000000000000..3bdd690990aa --- /dev/null +++ b/rust/kernel/auxiliary.rs @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Abstractions for the auxiliary bus. +//! +//! C header: [`include/linux/auxiliary_bus.h`](srctree/include/linux/auxi= liary_bus.h) + +use crate::{ + bindings, container_of, device, + device_id::RawDeviceId, + driver, + error::{to_result, Result}, + prelude::*, + str::CStr, + types::{ARef, ForeignOwnable, Opaque}, + ThisModule, +}; +use core::ptr::addr_of_mut; + +/// An adapter for the registration of auxiliary drivers. +pub struct Adapter(T); + +// SAFETY: A call to `unregister` for a given instance of `RegType` is gua= ranteed to be valid if +// a preceding call to `register` has been successful. +unsafe impl driver::RegistrationOps for Adapter { + type RegType =3D bindings::auxiliary_driver; + + unsafe fn register( + adrv: &Opaque, + name: &'static CStr, + module: &'static ThisModule, + ) -> Result { + // SAFETY: It's safe to set the fields of `struct auxiliary_driver= ` on initialization. + unsafe { + (*adrv.get()).name =3D name.as_char_ptr(); + (*adrv.get()).probe =3D Some(Self::probe_callback); + (*adrv.get()).remove =3D Some(Self::remove_callback); + (*adrv.get()).id_table =3D T::ID_TABLE.as_ptr(); + } + + // SAFETY: `adrv` is guaranteed to be a valid `RegType`. + to_result(unsafe { + bindings::__auxiliary_driver_register(adrv.get(), module.0, na= me.as_char_ptr()) + }) + } + + unsafe fn unregister(adrv: &Opaque) { + // SAFETY: `adrv` is guaranteed to be a valid `RegType`. + unsafe { bindings::auxiliary_driver_unregister(adrv.get()) } + } +} + +impl Adapter { + extern "C" fn probe_callback( + adev: *mut bindings::auxiliary_device, + id: *const bindings::auxiliary_device_id, + ) -> core::ffi::c_int { + // SAFETY: The auxiliary bus only ever calls the probe callback wi= th a valid pointer to a + // `struct auxiliary_device`. + let dev =3D unsafe { device::Device::get_device(addr_of_mut!((*ade= v).dev)) }; + // SAFETY: `dev` is guaranteed to be embedded in a valid `struct a= uxiliary_device` by the + // call above. + let mut adev =3D unsafe { Device::from_dev(dev) }; + + // SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struc= t auxiliary_device_id` and + // does not add additional invariants, so it's safe to transmute. + let id =3D unsafe { &*id.cast::() }; + let info =3D T::ID_TABLE.info(id.index()); + + match T::probe(&mut adev, info) { + Ok(data) =3D> { + // Let the `struct auxiliary_device` own a reference of th= e driver's private data. + // SAFETY: By the type invariant `adev.as_raw` returns a v= alid pointer to a + // `struct auxiliary_device`. + unsafe { bindings::auxiliary_set_drvdata(adev.as_raw(), da= ta.into_foreign()) }; + } + Err(err) =3D> return Error::to_errno(err), + } + + 0 + } + + extern "C" fn remove_callback(adev: *mut bindings::auxiliary_device) { + // SAFETY: The auxiliary bus only ever calls the remove callback w= ith a valid pointer to a + // `struct auxiliary_device`. + let ptr =3D unsafe { bindings::auxiliary_get_drvdata(adev) }; + + // SAFETY: `remove_callback` is only ever called after a successfu= l call to + // `probe_callback`, hence it's guaranteed that `ptr` points to a = valid and initialized + // `KBox` pointer created through `KBox::into_foreign`. + let _ =3D unsafe { KBox::::from_foreign(ptr) }; + } +} + +/// Declares a kernel module that exposes a single auxiliary driver. +#[macro_export] +macro_rules! module_auxiliary_driver { + ($($f:tt)*) =3D> { + $crate::module_driver!(, $crate::auxiliary::Adapter, { $($f)= * }); + }; +} + +/// Abstraction for `bindings::auxiliary_device_id`. +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct DeviceId(bindings::auxiliary_device_id); + +impl DeviceId { + /// Create a new [`DeviceId`] from name. + pub const fn new(modname: &'static CStr, name: &'static CStr) -> Self { + let name =3D name.as_bytes_with_nul(); + let modname =3D modname.as_bytes_with_nul(); + + // TODO: Replace with `bindings::auxiliary_device_id::default()` o= nce stabilized for + // `const`. + // + // SAFETY: FFI type is valid to be zero-initialized. + let mut id: bindings::auxiliary_device_id =3D unsafe { core::mem::= zeroed() }; + + let mut i =3D 0; + while i < modname.len() { + id.name[i] =3D modname[i]; + i +=3D 1; + } + + // Reuse the space of the NULL terminator. + id.name[i - 1] =3D b'.'; + + let mut j =3D 0; + while j < name.len() { + id.name[i] =3D name[j]; + i +=3D 1; + j +=3D 1; + } + + Self(id) + } +} + +// SAFETY: +// * `DeviceId` is a `#[repr(transparent)` wrapper of `auxiliary_device_id= ` and does not add +// additional invariants, so it's safe to transmute to `RawType`. +// * `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. +unsafe impl RawDeviceId for DeviceId { + type RawType =3D bindings::auxiliary_device_id; + + const DRIVER_DATA_OFFSET: usize =3D + core::mem::offset_of!(bindings::auxiliary_device_id, driver_data); + + fn index(&self) -> usize { + self.0.driver_data + } +} + +/// IdTable type for auxiliary drivers. +pub type IdTable =3D &'static dyn kernel::device_id::IdTable; + +/// Create a auxiliary `IdTable` with its alias for modpost. +#[macro_export] +macro_rules! auxiliary_device_table { + ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $tabl= e_data: expr) =3D> { + const $table_name: $crate::device_id::IdArray< + $crate::auxiliary::DeviceId, + $id_info_type, + { $table_data.len() }, + > =3D $crate::device_id::IdArray::new($table_data); + + $crate::module_device_table!("auxiliary", $module_table_name, $tab= le_name); + }; +} + +/// The auxiliary driver trait. +/// +/// Drivers must implement this trait in order to get an auxiliary driver = registered. +pub trait Driver { + /// The type holding information about each device id supported by the= driver. + /// + /// TODO: Use associated_type_defaults once stabilized: + /// + /// type IdInfo: 'static =3D (); + type IdInfo: 'static; + + /// The table of device ids supported by the driver. + const ID_TABLE: IdTable; + + /// Auxiliary driver probe. + /// + /// Called when a new auxiliary device is added or discovered. Impleme= nters should attempt + /// to initialize the device here. + fn probe(dev: &mut Device, id_info: &Self::IdInfo) -> Result>>; +} + +/// The auxiliary device representation. +/// +/// An auxiliary device is based on an always reference counted [`device::= Device`] instance. Cloning +/// an auxiliary device, hence, also increments the base device' reference= count. +/// +/// # Invariants +/// +/// [`Device`] holds a valid reference of `ARef` whose und= erlying `struct device` is +/// a member of a `struct auxiliary_device`. +#[derive(Clone)] +pub struct Device(ARef); + +impl Device { + /// Create an auxiliary [`Device`] instance from an existing [`device:= :Device`]. + /// + /// # Safety + /// + /// `dev` must be an `ARef` whose underlying `bindings= ::device` is a member of + /// a `bindings::auxiliary_device`. + unsafe fn from_dev(dev: ARef) -> Self { + Self(dev) + } + + fn as_raw(&self) -> *mut bindings::auxiliary_device { + // SAFETY: By the type invariant `self.0.as_raw` is a pointer to t= he `struct device` + // embedded in `struct auxiliary_device`. + unsafe { container_of!(self.0.as_raw(), bindings::auxiliary_device= , dev).cast_mut() } + } + + /// Returns the auxiliary device' id. + pub fn id(&self) -> u32 { + // SAFETY: By the type invariant `self.as_raw()` is a valid pointe= r to a + // `struct auxiliary_device`. + unsafe { (*self.as_raw()).id } + } +} + +impl AsRef for Device { + fn as_ref(&self) -> &device::Device { + &self.0 + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 398242f92a96..d9a2ca9d1f20 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -36,6 +36,8 @@ pub use ffi; =20 pub mod alloc; +#[cfg(CONFIG_AUXILIARY_BUS)] +pub mod auxiliary; #[cfg(CONFIG_BLOCK)] pub mod block; #[doc(hidden)] --=20 2.48.1 From nobody Tue Dec 16 21:03:31 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 03ED11482F2; Wed, 12 Mar 2025 00:28:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741739290; cv=none; b=fHmLpdpOe32gD75fyGpHWVy31z3btmr5eeoq/gojIZhohIaMQ+aRu/+715OdoTAUet73KFRX8qamWptJPRLVi9xkvX8J81a5Z1D+v95Src+KNjicAlixwU6C7WiGpVci+3ItJ66vO6HpGcPbcFm/sZEHUa4qvJwzdz34RVSqMsI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741739290; c=relaxed/simple; bh=vSGacgpTJ7Vf5exs6CcFX/ptRjtp9i/3KpX9vrs1jF0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BMC6mdKvnGXTWmtxwESySR8Z2I1soMkNLxN03UXIzYa10xx+Dk0QRBSMxootr/VRkOmL9+wmY8vy3gnEdpzJPFqoXDK/i5GOhPVjwwNnX/tnzS/rK8GuiqGyO3ZD3/3T018G0P4Kzp8BUEbyERhdecgr4UtKChJ04/NBu7HD9zg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VBiBzxNs; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VBiBzxNs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 100B2C4CEEC; Wed, 12 Mar 2025 00:28:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741739289; bh=vSGacgpTJ7Vf5exs6CcFX/ptRjtp9i/3KpX9vrs1jF0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VBiBzxNslj4A62V+LehQs3TBaG2etiX6nUnzx0ddGX3S/qdw427qXKHbJvYfknkqa Vx3fReuhaDIHTSA6zAojqVTi+OfZ//++kzV6LtDtpmEGstr5sY9nLCwjCSOXwB+2zU gP4xRCA/wqVdIHbS7/tUJaaYXx8qVhxLUeSAOQkgXufLDZhTu2HssV7OdjBiDYYXtx 1DLiMtuMHcskGy/i/vUC+EWFOQ4QQ4airtAiq3xM6s8+lDa61LO0ItSfaxwMPouN6H AyZaPfH3v6U77UQJnjGrBpGU6kceXrmxlf/sqzRIN/O/nuWqtfD++nycCRb0jBrDLI NyfP3dZYq+GCw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, airlied@gmail.com, acourbot@nvidia.com, jhubbard@nvidia.com Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH 3/4] rust: auxiliary: add auxiliary registration Date: Wed, 12 Mar 2025 01:19:09 +0100 Message-ID: <20250312002741.453350-4-dakr@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250312002741.453350-1-dakr@kernel.org> References: <20250312002741.453350-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement the `auxiliary::Registration` type, which provides an API to create and register new auxiliary devices in the system. Signed-off-by: Danilo Krummrich --- rust/kernel/auxiliary.rs | 80 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 3bdd690990aa..275dffc64a02 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -14,7 +14,7 @@ types::{ARef, ForeignOwnable, Opaque}, ThisModule, }; -use core::ptr::addr_of_mut; +use core::ptr::{addr_of_mut, NonNull}; =20 /// An adapter for the registration of auxiliary drivers. pub struct Adapter(T); @@ -224,6 +224,16 @@ pub fn id(&self) -> u32 { // `struct auxiliary_device`. unsafe { (*self.as_raw()).id } } + + extern "C" fn release(dev: *mut bindings::device) { + // SAFETY: By the type invariant `self.0.as_raw` is a pointer to t= he `struct device` + // embedded in `struct auxiliary_device`. + let adev =3D unsafe { container_of!(dev, bindings::auxiliary_devic= e, dev) }.cast_mut(); + + // SAFETY: `adev` points to the memory that has been allocated in = `Registration::new`, via + // `KBox::new(Opaque::::zeroed(), GFP_= KERNEL)`. + let _ =3D unsafe { KBox::>::fro= m_raw(adev.cast()) }; + } } =20 impl AsRef for Device { @@ -231,3 +241,71 @@ fn as_ref(&self) -> &device::Device { &self.0 } } + +/// The registration of an auxiliary device. +/// +/// This type represents the registration of a [`struct auxiliary_device`]= . When an instance of this +/// type is dropped, its respective auxiliary device will be unregistered = from the system. +/// +/// # Invariants +/// +/// `self.0` always holds a valid pointer to an initialized and registered +/// [`struct auxiliary_device`]. +pub struct Registration(NonNull); + +impl Registration { + /// Create and register a new auxiliary device. + pub fn new(parent: &device::Device, name: &CStr, id: u32, modname: &CS= tr) -> Result { + let boxed =3D KBox::new(Opaque::::zero= ed(), GFP_KERNEL)?; + let adev =3D boxed.get(); + + // SAFETY: It's safe to set the fields of `struct auxiliary_device= ` on initialization. + unsafe { + (*adev).dev.parent =3D parent.as_raw(); + (*adev).dev.release =3D Some(Device::release); + (*adev).name =3D name.as_char_ptr(); + (*adev).id =3D id; + } + + // SAFETY: `adev` is guaranteed to be a valid pointer to a `struct= auxiliary_device`, + // which has not been initialized yet. + unsafe { bindings::auxiliary_device_init(adev) }; + + // Now that `adev` is initialized, leak the `Box`; the correspondi= ng memory will be freed + // by `Device::release` when the last reference to the `struct aux= iliary_device` is dropped. + let _ =3D KBox::into_raw(boxed); + + // SAFETY: + // - `adev` is guaranteed to be a valid pointer to a `struct auxil= iary_device`, which has + // been initialialized, + // - `modname.as_char_ptr()` is a NULL terminated string. + let ret =3D unsafe { bindings::__auxiliary_device_add(adev, modnam= e.as_char_ptr()) }; + if ret !=3D 0 { + // SAFETY: `adev` is guaranteed to be a valid pointer to a `st= ruct auxiliary_device`, + // which has been initialialized. + unsafe { bindings::auxiliary_device_uninit(adev) }; + + return Err(Error::from_errno(ret)); + } + + // SAFETY: `adev` is guaranteed to be non-null, since the `KBox` w= as allocated successfully. + // + // INVARIANT: The device will remain registered until `auxiliary_d= evice_delete()` is called, + // which happens in `Self::drop()`. + Ok(Self(unsafe { NonNull::new_unchecked(adev) })) + } +} + +impl Drop for Registration { + fn drop(&mut self) { + // SAFETY: By the type invariant of `Self`, `self.0.as_ptr()` is a= valid registered + // `struct auxiliary_device`. + unsafe { bindings::auxiliary_device_delete(self.0.as_ptr()) }; + + // This drops the reference we acquired through `auxiliary_device_= init()`. + // + // SAFETY: By the type invariant of `Self`, `self.0.as_ptr()` is a= valid registered + // `struct auxiliary_device`. + unsafe { bindings::auxiliary_device_uninit(self.0.as_ptr()) }; + } +} --=20 2.48.1 From nobody Tue Dec 16 21:03:31 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C47FA6A009; Wed, 12 Mar 2025 00:28:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741739293; cv=none; b=tztGlhjpfbXmkxQScA3AD932p6hvjsf/bk9UZSR+EWCa3J2ebRpZ22C8eLKu5W43AdQJ7x2hgM8Kwzqu/370Idhe3tSTTBcbG6Wq/RcJDTLXBZ5wDweWEs5oCrw74Rmx/eVfMhf/XsnThD8hbsxZMqV1DzY9Q3Yez61BukEYkZo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741739293; c=relaxed/simple; bh=7HTnlknCHy9BYSUW62VmRoYLTpc62pptmvjdRlu1dmQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XgHbRCs/9udA8CFXXYoXfuPqyxAbfICy26ZfEF0KIlT0Y1VKwhsTvIWdV6ObIqgPr4Xp9Rsn5+BBGBg7vIjH5aPCDZof6qcR//f9OHlDgkTcZexNndkdTbkS5GcCweuhL+hY3rUS+4grDQ/PQp2HL/JuPRHYykGOhGosCf9AZ9g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Lyt/l2Bl; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Lyt/l2Bl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DD55DC4CEF0; Wed, 12 Mar 2025 00:28:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741739293; bh=7HTnlknCHy9BYSUW62VmRoYLTpc62pptmvjdRlu1dmQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Lyt/l2BlQY2M6AnuD2WsOxrp0uIO/vA/X9tmDRm+XzpCi8sdN6WF9ZG8ItxIC6pvv RjsX7lfAE01YZakJMINkjB/hOL8BTLMOjIuoSTqvLfHs/u66NvIUtDAmUagsJWYhyN AED/Nc0eB3keU/jcyL991FVIhfbwqtmt3UeM5nzQ/QO39QI5AnyrypxpQ1vrxWHGM9 v4pPlSyrcM7WcBsUtpeoKy5/vuQ8QQ7aR9E/scet0CWfgZI8fWL1p0T9s6QbBYSz8H 33tXy5crNp+txKFzBl9I0BwDDviZ43ab1dB+O0vRmb7pNwe1WhUOZ2UMooYhETjPUG /LsKpwGLcAjXw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu, airlied@gmail.com, acourbot@nvidia.com, jhubbard@nvidia.com Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH 4/4] samples: rust: add Rust auxiliary driver sample Date: Wed, 12 Mar 2025 01:19:10 +0100 Message-ID: <20250312002741.453350-5-dakr@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250312002741.453350-1-dakr@kernel.org> References: <20250312002741.453350-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a sample Rust auxiliary driver based on a PCI driver for QEMU's "pci-testdev" device. The PCI driver only registers an auxiliary device, in order to make the corresponding auxiliary driver probe. Signed-off-by: Danilo Krummrich --- MAINTAINERS | 1 + samples/rust/Kconfig | 10 +++ samples/rust/Makefile | 1 + samples/rust/rust_driver_auxiliary.rs | 99 +++++++++++++++++++++++++++ 4 files changed, 111 insertions(+) create mode 100644 samples/rust/rust_driver_auxiliary.rs diff --git a/MAINTAINERS b/MAINTAINERS index 0a737b28cdfa..6ec20e4f715d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7121,6 +7121,7 @@ F: rust/kernel/devres.rs F: rust/kernel/driver.rs F: rust/kernel/faux.rs F: rust/kernel/platform.rs +F: samples/rust/rust_driver_auxiliary.rs F: samples/rust/rust_driver_platform.rs F: samples/rust/rust_driver_faux.rs =20 diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index 3b6eae84b297..6679d1f1fd48 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -71,6 +71,16 @@ config SAMPLE_RUST_DRIVER_FAUX =20 If unsure, say N. =20 +config SAMPLE_RUST_DRIVER_AUXILIARY + tristate "Auxiliary Driver" + help + This option builds the Rust auxiliary driver sample. + + To compile this as a module, choose M here: + the module will be called rust_driver_auxiliary. + + If unsure, say N. + config SAMPLE_RUST_HOSTPROGS bool "Host programs" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 0dbc6d90f1ef..30a8809d0a15 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_SAMPLE_RUST_PRINT) +=3D rust_print.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) +=3D rust_driver_pci.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) +=3D rust_driver_platform.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) +=3D rust_driver_faux.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) +=3D rust_driver_auxiliary.o =20 rust_print-y :=3D rust_print_main.o rust_print_events.o =20 diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs new file mode 100644 index 000000000000..f9af7c07a2b7 --- /dev/null +++ b/samples/rust/rust_driver_auxiliary.rs @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust auxiliary driver sample (based on a PCI driver for QEMU's `pci-te= stdev`). +//! +//! To make this driver probe, QEMU must be run with `-device pci-testdev`. + +use kernel::{ + auxiliary, bindings, c_str, driver, error::Error, init, pci, prelude::= *, str::CStr, + InPlaceModule, +}; + +const MODULE_NAME: &CStr =3D ::NAME; +const AUXILIARY_NAME: &CStr =3D c_str!("auxiliary"); + +struct AuxiliaryDriver; + +kernel::auxiliary_device_table!( + AUX_TABLE, + MODULE_AUX_TABLE, + ::IdInfo, + [(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())] +); + +impl auxiliary::Driver for AuxiliaryDriver { + type IdInfo =3D (); + + const ID_TABLE: auxiliary::IdTable =3D &AUX_TABLE; + + fn probe(adev: &mut auxiliary::Device, _info: &Self::IdInfo) -> Result= >> { + dev_info!( + adev.as_ref(), + "Probing auxiliary driver for auxiliary device with id=3D{}\n", + adev.id() + ); + + let this =3D KBox::new(Self, GFP_KERNEL)?; + + Ok(this.into()) + } +} + +struct PciDriver { + _reg: [auxiliary::Registration; 2], +} + +kernel::pci_device_table!( + PCI_TABLE, + MODULE_PCI_TABLE, + ::IdInfo, + [( + pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, 0x5), + () + )] +); + +impl pci::Driver for PciDriver { + type IdInfo =3D (); + + const ID_TABLE: pci::IdTable =3D &PCI_TABLE; + + fn probe(pdev: &mut pci::Device, _info: &Self::IdInfo) -> Result>> { + let this =3D KBox::new( + Self { + _reg: [ + auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_= NAME, 0, MODULE_NAME)?, + auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_= NAME, 1, MODULE_NAME)?, + ], + }, + GFP_KERNEL, + )?; + + Ok(this.into()) + } +} + +#[pin_data] +struct SampleModule { + #[pin] + _pci_driver: driver::Registration>, + #[pin] + _aux_driver: driver::Registration>, +} + +impl InPlaceModule for SampleModule { + fn init(module: &'static kernel::ThisModule) -> impl init::PinInit { + try_pin_init!(Self { + _pci_driver <- driver::Registration::new(MODULE_NAME, module), + _aux_driver <- driver::Registration::new(MODULE_NAME, module), + }) + } +} + +module! { + type: SampleModule, + name: "rust_driver_auxiliary", + author: "Danilo Krummrich", + description: "Rust auxiliary driver", + license: "GPL v2", +} --=20 2.48.1