1 // SPDX-License-Identifier: GPL-2.0 2 3 use kernel::{ 4 auxiliary, 5 device::Core, 6 pci, 7 pci::{ 8 Class, 9 ClassMask, 10 Vendor, // 11 }, 12 prelude::*, 13 sizes::SZ_16M, 14 sync::atomic::{ 15 Atomic, 16 Relaxed, // 17 }, 18 types::CovariantForLt, 19 }; 20 21 use crate::gpu::Gpu; 22 23 /// Counter for generating unique auxiliary device IDs. 24 static AUXILIARY_ID_COUNTER: Atomic<u32> = Atomic::new(0); 25 26 #[pin_data] 27 pub(crate) struct NovaCore<'bound> { 28 #[pin] 29 pub(crate) gpu: Gpu<'bound>, 30 bar: pci::Bar<'bound, BAR0_SIZE>, 31 #[allow(clippy::type_complexity)] 32 _reg: auxiliary::Registration<'bound, CovariantForLt!(())>, 33 } 34 35 pub(crate) struct NovaCoreDriver; 36 37 const BAR0_SIZE: usize = SZ_16M; 38 39 pub(crate) type Bar0<'a> = &'a pci::Bar<'a, BAR0_SIZE>; 40 41 kernel::pci_device_table!( 42 PCI_TABLE, 43 <NovaCoreDriver as pci::Driver>::IdInfo, 44 [ 45 // Modern NVIDIA GPUs will show up as either VGA or 3D controllers. 46 ( 47 pci::DeviceId::from_class_and_vendor( 48 Class::DISPLAY_VGA, 49 ClassMask::ClassSubclass, 50 Vendor::NVIDIA 51 ), 52 () 53 ), 54 ( 55 pci::DeviceId::from_class_and_vendor( 56 Class::DISPLAY_3D, 57 ClassMask::ClassSubclass, 58 Vendor::NVIDIA 59 ), 60 () 61 ), 62 ] 63 ); 64 65 impl pci::Driver for NovaCoreDriver { 66 type IdInfo = (); 67 type Data<'bound> = NovaCore<'bound>; 68 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 69 70 fn probe<'bound>( 71 pdev: &'bound pci::Device<Core<'_>>, 72 _info: Option<&'bound Self::IdInfo>, 73 ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound { 74 pin_init::pin_init_scope(move || { 75 dev_dbg!(pdev, "Probe Nova Core GPU driver.\n"); 76 77 pdev.enable_device_mem()?; 78 pdev.set_master(); 79 80 Ok(try_pin_init!(NovaCore { 81 bar: pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0")?, 82 // TODO: Use `&bar` self-referential pin-init syntax once available. 83 // 84 // SAFETY: `bar` is initialized before this expression is evaluated 85 // (`try_pin_init!()` initializes fields in declaration order), lives at a pinned 86 // stable address, and is dropped after `gpu` (struct field drop order). 87 gpu <- Gpu::new(pdev, unsafe { &*core::ptr::from_ref(bar) }), 88 _reg: auxiliary::Registration::new( 89 pdev.as_ref(), 90 c"nova-drm", 91 // TODO[XARR]: Use XArray or perhaps IDA for proper ID allocation/recycling. For 92 // now, use a simple atomic counter that never recycles IDs. 93 AUXILIARY_ID_COUNTER.fetch_add(1, Relaxed), 94 crate::MODULE_NAME, 95 (), 96 )?, 97 })) 98 }) 99 } 100 } 101