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