From nobody Wed Dec 17 05:26:26 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 222871EC013; Wed, 19 Mar 2025 20:35:04 +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=1742416505; cv=none; b=Wmq9pNbN3XFxAWqHJEmO9Jz+VTTPhkm9FU8a10zDOwb0y4BkYfHTe3/QUI/ol8Z0mHMhiFmY/RJkU1ILraZatcJcSAWfuQSBg88LtoInRlz2nhwZ0zm3U1LlDwg7RrPXtMLera5tAtfaEBLhvzme7yV9FfeqT2zxz/h7D2OJ7h8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742416505; c=relaxed/simple; bh=p+JzsKxEduL9/McaTlczwZmdMpIxti9MNodikeaTpCo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XNHHE8CfTuMMlJfVOLR2bEvHUfl1u5+SImiAElWnwjufcCgZHsTGlC3uZdapE4w00jIZwJxe9aYi5tErzhnCTl/KnazmRGXg/ULWeE73t/79qsMSx4OJvFXeE8fCnKyyqmWSNBGw1YYWu6+Vn0dwFw1vsfbutOtWCKuuItrgIPA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=piiCKYLA; 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="piiCKYLA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5DC42C4CEEA; Wed, 19 Mar 2025 20:35:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1742416504; bh=p+JzsKxEduL9/McaTlczwZmdMpIxti9MNodikeaTpCo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=piiCKYLAoPZay/O2lCRAJ1F1jcxQeKqCBVS4IQ8nl+9HxElBNKeeF1NAoOSmTVF5x kdezQBl/HuWsO0A+fApsnAi4SQ9+BfObMsRup98lFV1zxZAyWB5B/dqQ1guJbACu+v Gldi3g6b0Y8GB3c9YsVXSxfX08npDXqBSpWVftFVxGAKU/3lYKtWHpXp4H6ygxNA8N U7DDh9+Mcc2yLx6SjSwivjdaSIBVXgoaDUzV77ObnxbPnT1Nhdc0TY1GxtAyR3GwEt LuVdlNrapESdKWCzkgTAcuma23EznMHj8YkMmk0yCCluoX35hzyWogxA4me7go4zh/ 8dwftjvCX8uBg== 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 v3 1/5] rust: types: add `Opaque::zeroed` Date: Wed, 19 Mar 2025 21:33:53 +0100 Message-ID: <20250319203455.132539-2-dakr@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250319203455.132539-1-dakr@kernel.org> References: <20250319203455.132539-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. Acked-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich Reviewed-by: Alice Ryhl --- 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 Wed Dec 17 05:26:26 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 6E65F1EC013; Wed, 19 Mar 2025 20:35:08 +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=1742416508; cv=none; b=hIOJHC4mt7GSGcOHt/u10YztXA2BimxjiIfE3gIc1AspRVZKW3yWlyJD8cRs6ryMu8y+30cRZE58NuvKEMVEKkwDdRXMT0o9zuY51IScsGzOICzqDKnblWdt6z6SgahP8XaPtq2x277m2BXxv8uf+OJsHhcOrrTuxK6rqvmlpzs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742416508; c=relaxed/simple; bh=E96WYj6OXwZvjyqYORmOiFImfPx6kL3Y08R1UPDGqt4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=o6yp4XIV7GpuO9SrFssgsh8TB8ZHWiu0iJjH4FYEVtUTVqa1ePo+l6RvnarC8ywbLVU/VjtBSXWXQSzQW3rvgD2rd9rD/fA1v7da71aeS+Io2E/fgkYRtAVjywLEZeTuKk3vv5Mpdv6nAgp+kj8uW5hWx+X/Mx4A0LsBwi2/VDo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LaWeIQj3; 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="LaWeIQj3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0D220C4CEE4; Wed, 19 Mar 2025 20:35:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1742416508; bh=E96WYj6OXwZvjyqYORmOiFImfPx6kL3Y08R1UPDGqt4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LaWeIQj3AeL5SM8wu56XFOjEqUMOUmsJSS1mysMKNTEA2mvY9AYOnWY+ofWN3tVIC cc14bhtC5iQeqfQZsB8usWy21qyBgJKkB1EBZ7mLvbnCJGqmeorz4ZRz1Cd4URcI7O SBX/o3mESJG5DWvvaoWwQUyr2ljFr3KoY4/o5RhTR69xQ0mihSpMM95d54ULanay3W lgCE1okM3VngqlcijMe2lheiGyCkzCabB52WSQvv0MXs0JxIo2wNUHWl3AU+fKXtLk SrJd9i+LZSRxLJ11Jx28jJgKEin0fAwL3RnG0JEoWu+ecqAF7vvyIlmnDK+q8jvbyw 5xX4jUNrl/zzg== 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 v3 2/5] driver: core: auxiliary: export auxiliary_bus_type Date: Wed, 19 Mar 2025 21:33:54 +0100 Message-ID: <20250319203455.132539-3-dakr@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250319203455.132539-1-dakr@kernel.org> References: <20250319203455.132539-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" In Rust we can safely derive a struct auxiliary_device pointer from a generic struct device pointer by checking dev->bus =3D=3D auxiliary_bus_type hence, export auxiliary_bus_type. Signed-off-by: Danilo Krummrich --- drivers/base/auxiliary.c | 3 ++- include/linux/auxiliary_bus.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c index afa4df4c5a3f..213e26c2747d 100644 --- a/drivers/base/auxiliary.c +++ b/drivers/base/auxiliary.c @@ -244,7 +244,7 @@ static void auxiliary_bus_shutdown(struct device *dev) auxdrv->shutdown(auxdev); } =20 -static const struct bus_type auxiliary_bus_type =3D { +const struct bus_type auxiliary_bus_type =3D { .name =3D "auxiliary", .probe =3D auxiliary_bus_probe, .remove =3D auxiliary_bus_remove, @@ -253,6 +253,7 @@ static const struct bus_type auxiliary_bus_type =3D { .uevent =3D auxiliary_uevent, .pm =3D &auxiliary_dev_pm_ops, }; +EXPORT_SYMBOL_GPL(auxiliary_bus_type); =20 /** * auxiliary_device_init - check auxiliary_device and initialize diff --git a/include/linux/auxiliary_bus.h b/include/linux/auxiliary_bus.h index 65dd7f154374..d4ad9233bfd0 100644 --- a/include/linux/auxiliary_bus.h +++ b/include/linux/auxiliary_bus.h @@ -197,6 +197,8 @@ struct auxiliary_driver { const struct auxiliary_device_id *id_table; }; =20 +extern const struct bus_type auxiliary_bus_type; + static inline void *auxiliary_get_drvdata(struct auxiliary_device *auxdev) { return dev_get_drvdata(&auxdev->dev); --=20 2.48.1 From nobody Wed Dec 17 05:26:26 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 4993D1EC013; Wed, 19 Mar 2025 20:35:12 +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=1742416512; cv=none; b=IhT6li2QoKQSd7rx2TKgzuGl8TWw0lwZQlX5CkYQbtfvYOiNjZRfHoMSFfwvIQNUbtlAi8gggID0ggjONtUoF2kxaj+PS4V1EWFtcMHhBGd1pc32NQLQMddLmYHxXah+sCyuDuhSnyrzapjIiNT0CfckbIqOKcSLIHLV5wrSUOg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742416512; c=relaxed/simple; bh=ievfoTl3jyU3x62kz5hsaDxDJP+Kedl4LbqRU180iqw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JvLB40OFiB5ERyCAWtDbYU5AWVHW+6xWlUKneQnMn3taNspGrN/oSt2EvZt16xUGm8kX8cHxQbGBzq3xO7tLuoOoeacq3ouGpuAYFEne3uUSSltm0JMldtS13cUNj8VT8NM7QfsD1c0ujJ5XKYOHVoTPso/14xUXcqBXmdIl9fA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fZ8RAw1N; 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="fZ8RAw1N" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B03C3C4CEE4; Wed, 19 Mar 2025 20:35:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1742416512; bh=ievfoTl3jyU3x62kz5hsaDxDJP+Kedl4LbqRU180iqw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fZ8RAw1NWANlnSuSGTQd+lqLKIvA1N/Nwi4T+agbzWiBmZrajv1uOP5Sgj/RHJAr1 hcUqycNxbsiWCbgLeg15N4fnm+9M5Qfs7ERHWBEFViDQePAOXrsCwiFk7znowmqZRS x9NAsMZXWACwIyr1qOU2cm7/UVSr75X8A/N8Z4nNW42QTzWjsrYCLpX36rqH1hGg5k aAQR3Y+ht5i+shn0RPKIcps0oLOp23Ho4Zq/2yUfZuQkDZkDCyn9iFfawmnk7Bqy89 Kj9a+dR5PKb6Eu5hL5iB+SODigtxJVOkkkTmmO5XVw/dUO3XLI3vBtV/XW8fVN6NA6 w3bUBXmi8hN0w== 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 v3 3/5] rust: auxiliary: add auxiliary device / driver abstractions Date: Wed, 19 Mar 2025 21:33:55 +0100 Message-ID: <20250319203455.132539-4-dakr@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250319203455.132539-1-dakr@kernel.org> References: <20250319203455.132539-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. Acked-by: Greg Kroah-Hartman 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 | 299 ++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 2 + 6 files changed, 327 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..1b8015bfca3e --- /dev/null +++ b/rust/kernel/auxiliary.rs @@ -0,0 +1,299 @@ +// 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::{ + convert::TryFrom, + marker::PhantomData, + ops::Deref, + ptr::{addr_of, addr_of_mut, NonNull}, +}; + +/// 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`. + // + // INVARIANT: `adev` is valid for the duration of `probe_callback(= )`. + let adev =3D unsafe { &*adev.cast::>() }; + + // 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(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: &Device, id_info: &Self::IdInfo) -> Result= >>; +} + +/// The auxiliary device representation. +/// +/// This structure represents the Rust abstraction for a C `struct auxilia= ry_device`. The +/// implementation abstracts the usage of an already existing C `struct au= xiliary_device` within +/// Rust code that we get passed from the C side. +/// +/// # Invariants +/// +/// A [`Device`] instance represents a valid `struct auxiliary_device` cre= ated by the C portion of +/// the kernel. +#[repr(transparent)] +pub struct Device( + Opaque, + PhantomData, +); + +impl Device { + fn as_raw(&self) -> *mut bindings::auxiliary_device { + self.0.get() + } + + /// 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 Deref for Device { + type Target =3D Device; + + fn deref(&self) -> &Self::Target { + let ptr: *const Self =3D self; + + // CAST: `Device` is a transparent wrapper of `Opaque`. + let ptr =3D ptr.cast::(); + + // SAFETY: `ptr` was derived from `&self`. + unsafe { &*ptr } + } +} + +impl From<&Device> for ARef { + fn from(dev: &Device) -> Self { + (&**dev).into() + } +} + +// SAFETY: Instances of `Device` are always reference-counted. +unsafe impl crate::types::AlwaysRefCounted for Device { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference guarantees that the= refcount is non-zero. + unsafe { bindings::get_device(self.as_ref().as_raw()) }; + } + + unsafe fn dec_ref(obj: NonNull) { + // CAST: `Self` a transparent wrapper of `bindings::auxiliary_devi= ce`. + let adev: *mut bindings::auxiliary_device =3D obj.cast().as_ptr(); + + // SAFETY: By the type invariant of `Self`, `adev` is a pointer to= a valid + // `struct auxiliary_device`. + let dev =3D unsafe { addr_of_mut!((*adev).dev) }; + + // SAFETY: The safety requirements guarantee that the refcount is = non-zero. + unsafe { bindings::put_device(dev) } + } +} + +impl AsRef for Device { + fn as_ref(&self) -> &device::Device { + // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a p= ointer to a valid + // `struct auxiliary_device`. + let dev =3D unsafe { addr_of_mut!((*self.as_raw()).dev) }; + + // SAFETY: `dev` points to a valid `struct device`. + unsafe { device::Device::as_ref(dev) } + } +} + +impl TryFrom<&device::Device> for &Device { + type Error =3D kernel::error::Error; + + fn try_from(dev: &device::Device) -> Result { + if dev.bus_type_raw() !=3D addr_of!(bindings::auxiliary_bus_type) { + return Err(EINVAL); + } + + // SAFETY: We've just verified that the bus type of `dev` equals + // `bindings::auxiliary_bus_type`, hence `dev` must be embedded in= a valid + // `struct auxiliary_device`. + let adev =3D unsafe { container_of!(dev.as_raw(), bindings::auxili= ary_device, dev) }; + + // SAFETY: `adev` is a valid pointer to a `struct auxiliary_device= `. + Ok(unsafe { &*adev.cast() }) + } +} + +// SAFETY: A `Device` is always reference-counted and can be released from= any thread. +unsafe impl Send for Device {} + +// SAFETY: `Device` can be shared among threads because all methods of `De= vice` +// (i.e. `Device) are thread safe. +unsafe impl Sync for Device {} 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 Wed Dec 17 05:26:26 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 56CCF219E93; Wed, 19 Mar 2025 20:35:15 +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=1742416516; cv=none; b=Lo0DF3ZhlIPFNkR0qDEIS3LZYvapLNDK+6XIskWbOFC5YwiTQXAQX9joX0iAPL+UFruJXdSmhlyVuq1GCy7rDrnCjBYcWrBjIC6L56e4wFDYfC4obh+ZKgCF6McylIIM6gRM21xoce1EESbj4oz5+2Tyeo9ALx+k6HTTDTu1xRE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742416516; c=relaxed/simple; bh=q6o/iQcyfsiCVyTovpMftSB8oe4JG/TbhOJ0ASGnH1c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CaeMqG3JFVVaOqeiI3LrNz3rezLFOle+ZziVSLqHDeVWXLZH4Ty3p+gqGDVJ6qz9TckqZx7To5/qRHeFwJfzGoY8LIYKvR6sMlt9I45RSwDqp5TDBdfhEftIJTe7glGDHZDyXqhOnh5lYGEMBE48//xmZZWJ6RSAAuPwtTyK67c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jD/7F8qb; 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="jD/7F8qb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 926E8C4CEEC; Wed, 19 Mar 2025 20:35:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1742416515; bh=q6o/iQcyfsiCVyTovpMftSB8oe4JG/TbhOJ0ASGnH1c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jD/7F8qbLouHwfN1DpcYjZIvdUQBNzK1sg2zzgAS0VOdP9bsU2Nbvu7/8W0inYuyM D0K4CMBIbLggC8A3qjjqYxJnvNfNxRIcxoVsnN3k/1d3n6WupE7to+kPevDg+Zkd4U NvHE6DF68LVeqp8P7Ru+Iq+h4AU+kNpa16f8l9djuWykDlxtW6jE77EnduXvWnXYKq AaMDnD6fY4w5MNMc6ErmhC/K5p39RxlBgsONa1EPo2XodwcjUtjrNZCEALD6ssRFXt s00FjLfwmx4cT88pP8SvMcEeq8pDuba3DpldgDleSFNO9Pb0y3GRIGWSofT2MjnILu DWSoWZlDhjW/A== 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 v3 4/5] rust: auxiliary: add auxiliary registration Date: Wed, 19 Mar 2025 21:33:56 +0100 Message-ID: <20250319203455.132539-5-dakr@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250319203455.132539-1-dakr@kernel.org> References: <20250319203455.132539-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. Acked-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- rust/kernel/auxiliary.rs | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 1b8015bfca3e..ff69fde760d8 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -220,6 +220,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 Deref for Device { @@ -297,3 +307,77 @@ unsafe impl Send for Device {} // SAFETY: `Device` can be shared among threads because all methods of `De= vice` // (i.e. `Device) are thread safe. unsafe impl Sync for Device {} + +/// 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()) }; + } +} + +// SAFETY: A `Registration` of a `struct auxiliary_device` can be released= from any thread. +unsafe impl Send for Registration {} + +// SAFETY: `Registration` does not expose any methods or fields that need = synchronization. +unsafe impl Sync for Registration {} --=20 2.48.1 From nobody Wed Dec 17 05:26:26 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 9996621ABA8; Wed, 19 Mar 2025 20:35:19 +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=1742416519; cv=none; b=Sva61KQZIY2y0IrAX13z5x1G2hkiTlUgrcZb3FStxhz4JO1L1K91AwQp8lhhwnhImE29tDKihGjvthNtxapFo5NC/WIAcIU512i7mUWBTUiSJ4eIK+q3kEa3MrW2at1C3Y2FNUwqtkXWpiQVWw1ohDRq/JkH0fbCx26G6U+Jx+g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742416519; c=relaxed/simple; bh=sxOTX+2LPaZPARYN028bSE2ifTHGymdjHAmVElZ1zEY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jvJtBET+A9nsIQraj2mUIPsAioyjbM45ZIalEdK5fMGqRTL4X5mDAgAqAHRmyzspCCKW/06jvMI9CilRjYZVhlPrdpbM9ATsxM1w4hZ9DkTYxv497lRm4yKHi7c2Cl6RtT2GpZIYpdFIdORYBhFHTEaqjOSJMH+GK6fnyy50oV8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ABegs/Al; 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="ABegs/Al" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 41F19C4CEE7; Wed, 19 Mar 2025 20:35:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1742416519; bh=sxOTX+2LPaZPARYN028bSE2ifTHGymdjHAmVElZ1zEY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ABegs/AlFYCG9R5Yo9jXFsVgXDDfvLKxJFt/Mfemd4yYGw0mcBJEMKz0nE+D8dUJC LnILQ4WBdgge+pFhoat0aHmwTnEe16q4GiSC464WfZgd4u4WTdrSRyEzNOrMk0r9yK ye9AFX49ZDjBm1AvNOchFjufsYyAvwBicaktgU+tG4YlVz1WnCDhQ/jzeKYw6vj2G1 BFrrOizRYdpquEJPt50McY6vZohoe559ojN8+DvpMVszy0I7KRKLiDYNTd0+jM6kd5 DTTKBat7nhpks+3+Jgm47CAYjTRoHBCPAOP/k2iEDabqcIUHA4UlZMHl3AmE5e+m9A 5bt9U1AXrVBhA== 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 v3 5/5] samples: rust: add Rust auxiliary driver sample Date: Wed, 19 Mar 2025 21:33:57 +0100 Message-ID: <20250319203455.132539-6-dakr@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250319203455.132539-1-dakr@kernel.org> References: <20250319203455.132539-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. Acked-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- MAINTAINERS | 1 + samples/rust/Kconfig | 12 +++ samples/rust/Makefile | 1 + samples/rust/rust_driver_auxiliary.rs | 110 ++++++++++++++++++++++++++ 4 files changed, 124 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..413216da1b70 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -71,6 +71,18 @@ config SAMPLE_RUST_DRIVER_FAUX =20 If unsure, say N. =20 +config SAMPLE_RUST_DRIVER_AUXILIARY + tristate "Auxiliary Driver" + depends on AUXILIARY_BUS + depends on PCI + 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..0f03d1d2181e --- /dev/null +++ b/samples/rust/rust_driver_auxiliary.rs @@ -0,0 +1,110 @@ +// 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, device::Core, 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: &auxiliary::Device, _info: &Self::IdInfo) -> Resu= lt>> { + dev_info!( + adev.as_ref(), + "Probing auxiliary driver for auxiliary device with id=3D{}\n", + adev.id() + ); + + if let Some(parent) =3D adev.as_ref().parent() { + let pdev: &pci::Device =3D parent.try_into()?; + + dev_info!( + adev.as_ref(), + "Parent: VendorID=3D{:#x}, DeviceID=3D{:#x}\n", + pdev.vendor_id(), + pdev.device_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: &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