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