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,
5 c_str,
6 device::Core,
7 devres::Devres,
8 dma::Device,
9 dma::DmaMask,
10 pci,
11 pci::{
12 Class,
13 ClassMask,
14 Vendor, //
15 },
16 prelude::*,
17 sizes::SZ_16M,
18 sync::Arc, //
19};
20
21use crate::gpu::Gpu;
22
23#[pin_data]
24pub(crate) struct NovaCore {
25 #[pin]
26 pub(crate) gpu: Gpu,
27 #[pin]
28 _reg: Devres<auxiliary::Registration>,
29}
30
31const BAR0_SIZE: usize = SZ_16M;
32
33// For now we only support Ampere which can use up to 47-bit DMA addresses.
34//
35// TODO: Add an abstraction for this to support newer GPUs which may support
36// larger DMA addresses. Limiting these GPUs to smaller address widths won't
37// have any adverse affects, unless installed on systems which require larger
38// DMA addresses. These systems should be quite rare.
39const GPU_DMA_BITS: u32 = 47;
40
41pub(crate) type Bar0 = pci::Bar<BAR0_SIZE>;
42
43kernel::pci_device_table!(
44 PCI_TABLE,
45 MODULE_PCI_TABLE,
46 <NovaCore as pci::Driver>::IdInfo,
47 [
48 // Modern NVIDIA GPUs will show up as either VGA or 3D controllers.
49 (
50 pci::DeviceId::from_class_and_vendor(
51 Class::DISPLAY_VGA,
52 ClassMask::ClassSubclass,
53 Vendor::NVIDIA
54 ),
55 ()
56 ),
57 (
58 pci::DeviceId::from_class_and_vendor(
59 Class::DISPLAY_3D,
60 ClassMask::ClassSubclass,
61 Vendor::NVIDIA
62 ),
63 ()
64 ),
65 ]
66);
67
68impl pci::Driver for NovaCore {
69 type IdInfo = ();
70 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
71
72 fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
73 pin_init::pin_init_scope(move || {
74 dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n");
75
76 pdev.enable_device_mem()?;
77 pdev.set_master();
78
79 // SAFETY: No concurrent DMA allocations or mappings can be made because
80 // the device is still being probed and therefore isn't being used by
81 // other threads of execution.
82 unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::<GPU_DMA_BITS>())? };
83
84 let bar = Arc::pin_init(
85 pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")),
86 GFP_KERNEL,
87 )?;
88
89 Ok(try_pin_init!(Self {
90 gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref())?),
91 _reg <- auxiliary::Registration::new(
92 pdev.as_ref(),
93 c_str!("nova-drm"),
94 0, // TODO[XARR]: Once it lands, use XArray; for now we don't use the ID.
95 crate::MODULE_NAME
96 ),
97 }))
98 })
99 }
100
101 fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {
102 this.gpu.unbind(pdev.as_ref());
103 }
104}