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