Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

samples: rust: add Rust auxiliary driver sample

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 <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/20250414131934.28418-6-dakr@kernel.org
[ Use `ok_or()` when accessing auxiliary::Device::parent(). - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

+134
+1
MAINTAINERS
··· 3874 3874 F: include/linux/auxiliary_bus.h 3875 3875 F: rust/helpers/auxiliary.c 3876 3876 F: rust/kernel/auxiliary.rs 3877 + F: samples/rust/rust_driver_auxiliary.rs 3877 3878 3878 3879 AUXILIARY DISPLAY DRIVERS 3879 3880 M: Andy Shevchenko <andy@kernel.org>
+12
samples/rust/Kconfig
··· 82 82 83 83 If unsure, say N. 84 84 85 + config SAMPLE_RUST_DRIVER_AUXILIARY 86 + tristate "Auxiliary Driver" 87 + depends on AUXILIARY_BUS 88 + depends on PCI 89 + help 90 + This option builds the Rust auxiliary driver sample. 91 + 92 + To compile this as a module, choose M here: 93 + the module will be called rust_driver_auxiliary. 94 + 95 + If unsure, say N. 96 + 85 97 config SAMPLE_RUST_HOSTPROGS 86 98 bool "Host programs" 87 99 help
+1
samples/rust/Makefile
··· 8 8 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o 9 9 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o 10 10 obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o 11 + obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o 11 12 12 13 rust_print-y := rust_print_main.o rust_print_events.o 13 14
+120
samples/rust/rust_driver_auxiliary.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Rust auxiliary driver sample (based on a PCI driver for QEMU's `pci-testdev`). 4 + //! 5 + //! To make this driver probe, QEMU must be run with `-device pci-testdev`. 6 + 7 + use kernel::{ 8 + auxiliary, bindings, c_str, device::Core, driver, error::Error, pci, prelude::*, str::CStr, 9 + InPlaceModule, 10 + }; 11 + 12 + use pin_init::PinInit; 13 + 14 + const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME; 15 + const AUXILIARY_NAME: &CStr = c_str!("auxiliary"); 16 + 17 + struct AuxiliaryDriver; 18 + 19 + kernel::auxiliary_device_table!( 20 + AUX_TABLE, 21 + MODULE_AUX_TABLE, 22 + <AuxiliaryDriver as auxiliary::Driver>::IdInfo, 23 + [(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())] 24 + ); 25 + 26 + impl auxiliary::Driver for AuxiliaryDriver { 27 + type IdInfo = (); 28 + 29 + const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE; 30 + 31 + fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 32 + dev_info!( 33 + adev.as_ref(), 34 + "Probing auxiliary driver for auxiliary device with id={}\n", 35 + adev.id() 36 + ); 37 + 38 + ParentDriver::connect(adev)?; 39 + 40 + let this = KBox::new(Self, GFP_KERNEL)?; 41 + 42 + Ok(this.into()) 43 + } 44 + } 45 + 46 + struct ParentDriver { 47 + _reg: [auxiliary::Registration; 2], 48 + } 49 + 50 + kernel::pci_device_table!( 51 + PCI_TABLE, 52 + MODULE_PCI_TABLE, 53 + <ParentDriver as pci::Driver>::IdInfo, 54 + [( 55 + pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, 0x5), 56 + () 57 + )] 58 + ); 59 + 60 + impl pci::Driver for ParentDriver { 61 + type IdInfo = (); 62 + 63 + const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 64 + 65 + fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 66 + let this = KBox::new( 67 + Self { 68 + _reg: [ 69 + auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME)?, 70 + auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME)?, 71 + ], 72 + }, 73 + GFP_KERNEL, 74 + )?; 75 + 76 + Ok(this.into()) 77 + } 78 + } 79 + 80 + impl ParentDriver { 81 + fn connect(adev: &auxiliary::Device) -> Result<()> { 82 + let parent = adev.parent().ok_or(EINVAL)?; 83 + let pdev: &pci::Device = parent.try_into()?; 84 + 85 + dev_info!( 86 + adev.as_ref(), 87 + "Connect auxiliary {} with parent: VendorID={:#x}, DeviceID={:#x}\n", 88 + adev.id(), 89 + pdev.vendor_id(), 90 + pdev.device_id() 91 + ); 92 + 93 + Ok(()) 94 + } 95 + } 96 + 97 + #[pin_data] 98 + struct SampleModule { 99 + #[pin] 100 + _pci_driver: driver::Registration<pci::Adapter<ParentDriver>>, 101 + #[pin] 102 + _aux_driver: driver::Registration<auxiliary::Adapter<AuxiliaryDriver>>, 103 + } 104 + 105 + impl InPlaceModule for SampleModule { 106 + fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> { 107 + try_pin_init!(Self { 108 + _pci_driver <- driver::Registration::new(MODULE_NAME, module), 109 + _aux_driver <- driver::Registration::new(MODULE_NAME, module), 110 + }) 111 + } 112 + } 113 + 114 + module! { 115 + type: SampleModule, 116 + name: "rust_driver_auxiliary", 117 + author: "Danilo Krummrich", 118 + description: "Rust auxiliary driver", 119 + license: "GPL v2", 120 + }