Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
7use kernel::{
8 auxiliary,
9 device::{
10 Bound,
11 Core, //
12 },
13 devres::Devres,
14 driver,
15 pci,
16 prelude::*,
17 InPlaceModule, //
18};
19
20use core::any::TypeId;
21
22const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
23const AUXILIARY_NAME: &CStr = c"auxiliary";
24
25struct AuxiliaryDriver;
26
27kernel::auxiliary_device_table!(
28 AUX_TABLE,
29 MODULE_AUX_TABLE,
30 <AuxiliaryDriver as auxiliary::Driver>::IdInfo,
31 [(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())]
32);
33
34impl auxiliary::Driver for AuxiliaryDriver {
35 type IdInfo = ();
36
37 const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
38
39 fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
40 dev_info!(
41 adev,
42 "Probing auxiliary driver for auxiliary device with id={}\n",
43 adev.id()
44 );
45
46 ParentDriver::connect(adev)?;
47
48 Ok(Self)
49 }
50}
51
52#[pin_data]
53struct ParentDriver {
54 private: TypeId,
55 #[pin]
56 _reg0: Devres<auxiliary::Registration>,
57 #[pin]
58 _reg1: Devres<auxiliary::Registration>,
59}
60
61kernel::pci_device_table!(
62 PCI_TABLE,
63 MODULE_PCI_TABLE,
64 <ParentDriver as pci::Driver>::IdInfo,
65 [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
66);
67
68impl pci::Driver for ParentDriver {
69 type IdInfo = ();
70
71 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
72
73 fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
74 try_pin_init!(Self {
75 private: TypeId::of::<Self>(),
76 _reg0 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME),
77 _reg1 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME),
78 })
79 }
80}
81
82impl ParentDriver {
83 fn connect(adev: &auxiliary::Device<Bound>) -> Result {
84 let dev = adev.parent();
85 let pdev: &pci::Device<Bound> = dev.try_into()?;
86 let drvdata = dev.drvdata::<Self>()?;
87
88 dev_info!(
89 dev,
90 "Connect auxiliary {} with parent: VendorID={}, DeviceID={:#x}\n",
91 adev.id(),
92 pdev.vendor_id(),
93 pdev.device_id()
94 );
95
96 dev_info!(
97 dev,
98 "We have access to the private data of {:?}.\n",
99 drvdata.private
100 );
101
102 Ok(())
103 }
104}
105
106#[pin_data]
107struct SampleModule {
108 #[pin]
109 _pci_driver: driver::Registration<pci::Adapter<ParentDriver>>,
110 #[pin]
111 _aux_driver: driver::Registration<auxiliary::Adapter<AuxiliaryDriver>>,
112}
113
114impl InPlaceModule for SampleModule {
115 fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
116 try_pin_init!(Self {
117 _pci_driver <- driver::Registration::new(MODULE_NAME, module),
118 _aux_driver <- driver::Registration::new(MODULE_NAME, module),
119 })
120 }
121}
122
123module! {
124 type: SampleModule,
125 name: "rust_driver_auxiliary",
126 authors: ["Danilo Krummrich"],
127 description: "Rust auxiliary driver",
128 license: "GPL v2",
129}