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