xref: /linux/samples/rust/rust_driver_auxiliary.rs (revision bfb9e46b5bff33ebaac49cceb27256caceddeee5)
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::{
896609a19SDanilo Krummrich     auxiliary, bindings, c_str, device::Core, driver, error::Error, pci, prelude::*, str::CStr,
996609a19SDanilo Krummrich     InPlaceModule,
1096609a19SDanilo Krummrich };
1196609a19SDanilo Krummrich 
1296609a19SDanilo Krummrich use pin_init::PinInit;
1396609a19SDanilo Krummrich 
1496609a19SDanilo Krummrich const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
1596609a19SDanilo Krummrich const AUXILIARY_NAME: &CStr = c_str!("auxiliary");
1696609a19SDanilo Krummrich 
1796609a19SDanilo Krummrich struct AuxiliaryDriver;
1896609a19SDanilo Krummrich 
1996609a19SDanilo Krummrich kernel::auxiliary_device_table!(
2096609a19SDanilo Krummrich     AUX_TABLE,
2196609a19SDanilo Krummrich     MODULE_AUX_TABLE,
2296609a19SDanilo Krummrich     <AuxiliaryDriver as auxiliary::Driver>::IdInfo,
2396609a19SDanilo Krummrich     [(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())]
2496609a19SDanilo Krummrich );
2596609a19SDanilo Krummrich 
2696609a19SDanilo Krummrich impl auxiliary::Driver for AuxiliaryDriver {
2796609a19SDanilo Krummrich     type IdInfo = ();
2896609a19SDanilo Krummrich 
2996609a19SDanilo Krummrich     const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
3096609a19SDanilo Krummrich 
3196609a19SDanilo Krummrich     fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
3296609a19SDanilo Krummrich         dev_info!(
3396609a19SDanilo Krummrich             adev.as_ref(),
3496609a19SDanilo Krummrich             "Probing auxiliary driver for auxiliary device with id={}\n",
3596609a19SDanilo Krummrich             adev.id()
3696609a19SDanilo Krummrich         );
3796609a19SDanilo Krummrich 
3896609a19SDanilo Krummrich         ParentDriver::connect(adev)?;
3996609a19SDanilo Krummrich 
4096609a19SDanilo Krummrich         let this = KBox::new(Self, GFP_KERNEL)?;
4196609a19SDanilo Krummrich 
4296609a19SDanilo Krummrich         Ok(this.into())
4396609a19SDanilo Krummrich     }
4496609a19SDanilo Krummrich }
4596609a19SDanilo Krummrich 
4696609a19SDanilo Krummrich struct ParentDriver {
4796609a19SDanilo Krummrich     _reg: [auxiliary::Registration; 2],
4896609a19SDanilo Krummrich }
4996609a19SDanilo Krummrich 
5096609a19SDanilo Krummrich kernel::pci_device_table!(
5196609a19SDanilo Krummrich     PCI_TABLE,
5296609a19SDanilo Krummrich     MODULE_PCI_TABLE,
5396609a19SDanilo Krummrich     <ParentDriver as pci::Driver>::IdInfo,
5496609a19SDanilo Krummrich     [(
5596609a19SDanilo Krummrich         pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, 0x5),
5696609a19SDanilo Krummrich         ()
5796609a19SDanilo Krummrich     )]
5896609a19SDanilo Krummrich );
5996609a19SDanilo Krummrich 
6096609a19SDanilo Krummrich impl pci::Driver for ParentDriver {
6196609a19SDanilo Krummrich     type IdInfo = ();
6296609a19SDanilo Krummrich 
6396609a19SDanilo Krummrich     const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
6496609a19SDanilo Krummrich 
6596609a19SDanilo Krummrich     fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
6696609a19SDanilo Krummrich         let this = KBox::new(
6796609a19SDanilo Krummrich             Self {
6896609a19SDanilo Krummrich                 _reg: [
6996609a19SDanilo Krummrich                     auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME)?,
7096609a19SDanilo Krummrich                     auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME)?,
7196609a19SDanilo Krummrich                 ],
7296609a19SDanilo Krummrich             },
7396609a19SDanilo Krummrich             GFP_KERNEL,
7496609a19SDanilo Krummrich         )?;
7596609a19SDanilo Krummrich 
7696609a19SDanilo Krummrich         Ok(this.into())
7796609a19SDanilo Krummrich     }
7896609a19SDanilo Krummrich }
7996609a19SDanilo Krummrich 
8096609a19SDanilo Krummrich impl ParentDriver {
8196609a19SDanilo Krummrich     fn connect(adev: &auxiliary::Device) -> Result<()> {
8296609a19SDanilo Krummrich         let parent = adev.parent().ok_or(EINVAL)?;
8396609a19SDanilo Krummrich         let pdev: &pci::Device = parent.try_into()?;
8496609a19SDanilo Krummrich 
8596609a19SDanilo Krummrich         dev_info!(
8696609a19SDanilo Krummrich             adev.as_ref(),
8796609a19SDanilo Krummrich             "Connect auxiliary {} with parent: VendorID={:#x}, DeviceID={:#x}\n",
8896609a19SDanilo Krummrich             adev.id(),
8996609a19SDanilo Krummrich             pdev.vendor_id(),
9096609a19SDanilo Krummrich             pdev.device_id()
9196609a19SDanilo Krummrich         );
9296609a19SDanilo Krummrich 
9396609a19SDanilo Krummrich         Ok(())
9496609a19SDanilo Krummrich     }
9596609a19SDanilo Krummrich }
9696609a19SDanilo Krummrich 
9796609a19SDanilo Krummrich #[pin_data]
9896609a19SDanilo Krummrich struct SampleModule {
9996609a19SDanilo Krummrich     #[pin]
10096609a19SDanilo Krummrich     _pci_driver: driver::Registration<pci::Adapter<ParentDriver>>,
10196609a19SDanilo Krummrich     #[pin]
10296609a19SDanilo Krummrich     _aux_driver: driver::Registration<auxiliary::Adapter<AuxiliaryDriver>>,
10396609a19SDanilo Krummrich }
10496609a19SDanilo Krummrich 
10596609a19SDanilo Krummrich impl InPlaceModule for SampleModule {
10696609a19SDanilo Krummrich     fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
10796609a19SDanilo Krummrich         try_pin_init!(Self {
10896609a19SDanilo Krummrich             _pci_driver <- driver::Registration::new(MODULE_NAME, module),
10996609a19SDanilo Krummrich             _aux_driver <- driver::Registration::new(MODULE_NAME, module),
11096609a19SDanilo Krummrich         })
11196609a19SDanilo Krummrich     }
11296609a19SDanilo Krummrich }
11396609a19SDanilo Krummrich 
11496609a19SDanilo Krummrich module! {
11596609a19SDanilo Krummrich     type: SampleModule,
11696609a19SDanilo Krummrich     name: "rust_driver_auxiliary",
117*bfb9e46bSGuilherme Giacomo Simoes     authors: ["Danilo Krummrich"],
11896609a19SDanilo Krummrich     description: "Rust auxiliary driver",
11996609a19SDanilo Krummrich     license: "GPL v2",
12096609a19SDanilo Krummrich }
121