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