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