1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Nova Core GPU Driver 4 5 use kernel::{ 6 debugfs, 7 driver::Registration, 8 pci, 9 prelude::*, 10 InPlaceModule, // 11 }; 12 13 pub mod api; 14 mod driver; 15 mod falcon; 16 mod fb; 17 mod firmware; 18 mod fsp; 19 mod gpu; 20 mod gsp; 21 mod irq; 22 mod mctp; 23 mod mm; 24 #[macro_use] 25 mod num; 26 mod regs; 27 mod sbuffer; 28 #[cfg(CONFIG_NOVA_CORE_SELFTESTS)] 29 mod selftest; 30 mod vbios; 31 mod vgpu; 32 33 pub(crate) const MODULE_NAME: &core::ffi::CStr = <LocalModule as kernel::ModuleMetadata>::NAME; 34 35 // TODO: Move this into per-module data once that exists. 36 static mut DEBUGFS_ROOT: Option<debugfs::Dir> = None; 37 38 /// Guard that clears `DEBUGFS_ROOT` when dropped. 39 struct DebugfsRootGuard; 40 41 impl Drop for DebugfsRootGuard { 42 fn drop(&mut self) { 43 // SAFETY: This guard is dropped after `_driver` (due to field order), 44 // so the driver is unregistered and no probe() can be running. 45 unsafe { DEBUGFS_ROOT = None }; 46 } 47 } 48 49 #[pin_data] 50 struct NovaCoreModule { 51 // Fields are dropped in declaration order, so `_driver` is dropped first, 52 // then `_debugfs_guard` clears `DEBUGFS_ROOT`. 53 #[pin] 54 _driver: Registration<pci::Adapter<driver::NovaCoreDriver>>, 55 _debugfs_guard: DebugfsRootGuard, 56 } 57 58 impl InPlaceModule for NovaCoreModule { 59 fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> { 60 let dir = debugfs::Dir::new(c"nova-core"); 61 62 // SAFETY: We are the only driver code running during init, so there 63 // cannot be any concurrent access to `DEBUGFS_ROOT`. 64 unsafe { DEBUGFS_ROOT = Some(dir) }; 65 66 try_pin_init!(Self { 67 _driver <- Registration::new(MODULE_NAME, module), 68 _debugfs_guard: DebugfsRootGuard, 69 }) 70 } 71 } 72 73 module! { 74 type: NovaCoreModule, 75 name: "nova-core", 76 authors: ["Danilo Krummrich"], 77 description: "Nova Core GPU driver", 78 license: "GPL v2", 79 firmware: [], 80 } 81 82 kernel::module_firmware!(firmware::ModInfoBuilder); 83