1 // SPDX-License-Identifier: GPL-2.0 2 3 use kernel::{ 4 auxiliary, 5 c_str, 6 device::Core, 7 pci, 8 pci::{ 9 Class, 10 ClassMask, 11 Vendor, // 12 }, 13 prelude::*, 14 sizes::SZ_16M, 15 sync::Arc, // 16 }; 17 18 use crate::gpu::Gpu; 19 20 #[pin_data] 21 pub(crate) struct NovaCore { 22 #[pin] 23 pub(crate) gpu: Gpu, 24 _reg: auxiliary::Registration, 25 } 26 27 const BAR0_SIZE: usize = SZ_16M; 28 pub(crate) type Bar0 = pci::Bar<BAR0_SIZE>; 29 30 kernel::pci_device_table!( 31 PCI_TABLE, 32 MODULE_PCI_TABLE, 33 <NovaCore as pci::Driver>::IdInfo, 34 [ 35 // Modern NVIDIA GPUs will show up as either VGA or 3D controllers. 36 ( 37 pci::DeviceId::from_class_and_vendor( 38 Class::DISPLAY_VGA, 39 ClassMask::ClassSubclass, 40 Vendor::NVIDIA 41 ), 42 () 43 ), 44 ( 45 pci::DeviceId::from_class_and_vendor( 46 Class::DISPLAY_3D, 47 ClassMask::ClassSubclass, 48 Vendor::NVIDIA 49 ), 50 () 51 ), 52 ] 53 ); 54 55 impl pci::Driver for NovaCore { 56 type IdInfo = (); 57 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 58 59 fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 60 dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n"); 61 62 pdev.enable_device_mem()?; 63 pdev.set_master(); 64 65 let devres_bar = Arc::pin_init( 66 pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")), 67 GFP_KERNEL, 68 )?; 69 70 // Used to provided a `&Bar0` to `Gpu::new` without tying it to the lifetime of 71 // `devres_bar`. 72 let bar_clone = Arc::clone(&devres_bar); 73 let bar = bar_clone.access(pdev.as_ref())?; 74 75 let this = KBox::pin_init( 76 try_pin_init!(Self { 77 gpu <- Gpu::new(pdev, devres_bar, bar), 78 _reg: auxiliary::Registration::new( 79 pdev.as_ref(), 80 c_str!("nova-drm"), 81 0, // TODO[XARR]: Once it lands, use XArray; for now we don't use the ID. 82 crate::MODULE_NAME 83 )?, 84 }), 85 GFP_KERNEL, 86 )?; 87 88 Ok(this) 89 } 90 91 fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) { 92 this.gpu.unbind(pdev.as_ref()); 93 } 94 } 95