xref: /linux/samples/rust/rust_driver_auxiliary.rs (revision 3be458a5a7ed57cb874474aee7929daed0d5d3aa)
196609a19SDanilo Krummrich // SPDX-License-Identifier: GPL-2.0
296609a19SDanilo Krummrich 
396609a19SDanilo Krummrich //! Rust auxiliary driver sample (based on a PCI driver for QEMU's `pci-testdev`).
496609a19SDanilo Krummrich //!
596609a19SDanilo Krummrich //! To make this driver probe, QEMU must be run with `-device pci-testdev`.
696609a19SDanilo Krummrich 
796609a19SDanilo Krummrich use kernel::{
86fc4b5ebSTamir Duberstein     auxiliary,
96506b44eSDanilo Krummrich     device::{
106506b44eSDanilo Krummrich         Bound,
116506b44eSDanilo Krummrich         Core, //
126506b44eSDanilo Krummrich     },
13b0b7301bSDanilo Krummrich     devres::Devres,
14b0b7301bSDanilo Krummrich     driver,
15b0b7301bSDanilo Krummrich     pci,
16b0b7301bSDanilo Krummrich     prelude::*,
176506b44eSDanilo Krummrich     InPlaceModule, //
1896609a19SDanilo Krummrich };
1996609a19SDanilo Krummrich 
20b0b7301bSDanilo Krummrich use core::any::TypeId;
2196609a19SDanilo Krummrich use pin_init::PinInit;
2296609a19SDanilo Krummrich 
2396609a19SDanilo Krummrich const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
246fc4b5ebSTamir Duberstein const AUXILIARY_NAME: &CStr = c"auxiliary";
2596609a19SDanilo Krummrich 
2696609a19SDanilo Krummrich struct AuxiliaryDriver;
2796609a19SDanilo Krummrich 
2896609a19SDanilo Krummrich kernel::auxiliary_device_table!(
2996609a19SDanilo Krummrich     AUX_TABLE,
3096609a19SDanilo Krummrich     MODULE_AUX_TABLE,
3196609a19SDanilo Krummrich     <AuxiliaryDriver as auxiliary::Driver>::IdInfo,
3296609a19SDanilo Krummrich     [(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())]
3396609a19SDanilo Krummrich );
3496609a19SDanilo Krummrich 
3596609a19SDanilo Krummrich impl auxiliary::Driver for AuxiliaryDriver {
3696609a19SDanilo Krummrich     type IdInfo = ();
3796609a19SDanilo Krummrich 
3896609a19SDanilo Krummrich     const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
3996609a19SDanilo Krummrich 
4002426233SDanilo Krummrich     fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
4196609a19SDanilo Krummrich         dev_info!(
42*3be458a5SGary Guo             adev,
4396609a19SDanilo Krummrich             "Probing auxiliary driver for auxiliary device with id={}\n",
4496609a19SDanilo Krummrich             adev.id()
4596609a19SDanilo Krummrich         );
4696609a19SDanilo Krummrich 
4796609a19SDanilo Krummrich         ParentDriver::connect(adev)?;
4896609a19SDanilo Krummrich 
4902426233SDanilo Krummrich         Ok(Self)
5096609a19SDanilo Krummrich     }
5196609a19SDanilo Krummrich }
5296609a19SDanilo Krummrich 
53e4e679c8SDanilo Krummrich #[pin_data]
5496609a19SDanilo Krummrich struct ParentDriver {
55b0b7301bSDanilo Krummrich     private: TypeId,
56e4e679c8SDanilo Krummrich     #[pin]
57e4e679c8SDanilo Krummrich     _reg0: Devres<auxiliary::Registration>,
58e4e679c8SDanilo Krummrich     #[pin]
59e4e679c8SDanilo Krummrich     _reg1: Devres<auxiliary::Registration>,
6096609a19SDanilo Krummrich }
6196609a19SDanilo Krummrich 
6296609a19SDanilo Krummrich kernel::pci_device_table!(
6396609a19SDanilo Krummrich     PCI_TABLE,
6496609a19SDanilo Krummrich     MODULE_PCI_TABLE,
6596609a19SDanilo Krummrich     <ParentDriver as pci::Driver>::IdInfo,
661b8ac376SJohn Hubbard     [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
6796609a19SDanilo Krummrich );
6896609a19SDanilo Krummrich 
6996609a19SDanilo Krummrich impl pci::Driver for ParentDriver {
7096609a19SDanilo Krummrich     type IdInfo = ();
7196609a19SDanilo Krummrich 
7296609a19SDanilo Krummrich     const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
7396609a19SDanilo Krummrich 
7402426233SDanilo Krummrich     fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
75e4e679c8SDanilo Krummrich         try_pin_init!(Self {
76b0b7301bSDanilo Krummrich             private: TypeId::of::<Self>(),
77e4e679c8SDanilo Krummrich             _reg0 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME),
78e4e679c8SDanilo Krummrich             _reg1 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME),
7902426233SDanilo Krummrich         })
8096609a19SDanilo Krummrich     }
8196609a19SDanilo Krummrich }
8296609a19SDanilo Krummrich 
8396609a19SDanilo Krummrich impl ParentDriver {
84b0b7301bSDanilo Krummrich     fn connect(adev: &auxiliary::Device<Bound>) -> Result {
85710ac546SDanilo Krummrich         let dev = adev.parent();
86b0b7301bSDanilo Krummrich         let pdev: &pci::Device<Bound> = dev.try_into()?;
87b0b7301bSDanilo Krummrich         let drvdata = dev.drvdata::<Self>()?;
8896609a19SDanilo Krummrich 
8996609a19SDanilo Krummrich         dev_info!(
90710ac546SDanilo Krummrich             dev,
911b8ac376SJohn Hubbard             "Connect auxiliary {} with parent: VendorID={}, DeviceID={:#x}\n",
9296609a19SDanilo Krummrich             adev.id(),
93710ac546SDanilo Krummrich             pdev.vendor_id(),
9496609a19SDanilo Krummrich             pdev.device_id()
9596609a19SDanilo Krummrich         );
9696609a19SDanilo Krummrich 
97b0b7301bSDanilo Krummrich         dev_info!(
98b0b7301bSDanilo Krummrich             dev,
99b0b7301bSDanilo Krummrich             "We have access to the private data of {:?}.\n",
100b0b7301bSDanilo Krummrich             drvdata.private
101b0b7301bSDanilo Krummrich         );
102b0b7301bSDanilo Krummrich 
10396609a19SDanilo Krummrich         Ok(())
10496609a19SDanilo Krummrich     }
10596609a19SDanilo Krummrich }
10696609a19SDanilo Krummrich 
10796609a19SDanilo Krummrich #[pin_data]
10896609a19SDanilo Krummrich struct SampleModule {
10996609a19SDanilo Krummrich     #[pin]
11096609a19SDanilo Krummrich     _pci_driver: driver::Registration<pci::Adapter<ParentDriver>>,
11196609a19SDanilo Krummrich     #[pin]
11296609a19SDanilo Krummrich     _aux_driver: driver::Registration<auxiliary::Adapter<AuxiliaryDriver>>,
11396609a19SDanilo Krummrich }
11496609a19SDanilo Krummrich 
11596609a19SDanilo Krummrich impl InPlaceModule for SampleModule {
11696609a19SDanilo Krummrich     fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
11796609a19SDanilo Krummrich         try_pin_init!(Self {
11896609a19SDanilo Krummrich             _pci_driver <- driver::Registration::new(MODULE_NAME, module),
11996609a19SDanilo Krummrich             _aux_driver <- driver::Registration::new(MODULE_NAME, module),
12096609a19SDanilo Krummrich         })
12196609a19SDanilo Krummrich     }
12296609a19SDanilo Krummrich }
12396609a19SDanilo Krummrich 
12496609a19SDanilo Krummrich module! {
12596609a19SDanilo Krummrich     type: SampleModule,
12696609a19SDanilo Krummrich     name: "rust_driver_auxiliary",
127bfb9e46bSGuilherme Giacomo Simoes     authors: ["Danilo Krummrich"],
12896609a19SDanilo Krummrich     description: "Rust auxiliary driver",
12996609a19SDanilo Krummrich     license: "GPL v2",
13096609a19SDanilo Krummrich }
131