Export a few items from nova-core and use them from nova-drm in order to print the chipset of the GPU being probed.
Some documentation items are added to make Clippy happy. This is only meant for demonstration purposes, and won't be merged. Signed-off-by: Alexandre Courbot <[email protected]> --- drivers/gpu/drm/nova/driver.rs | 9 +++++- drivers/gpu/nova-core/driver.rs | 59 +++++++++++++++++++++++++++++--------- drivers/gpu/nova-core/gpu.rs | 9 ++++-- drivers/gpu/nova-core/gsp/hal.rs | 2 +- drivers/gpu/nova-core/nova_core.rs | 4 +-- 5 files changed, 62 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs index 48933d86ddda..de1ad7032b6c 100644 --- a/drivers/gpu/drm/nova/driver.rs +++ b/drivers/gpu/drm/nova/driver.rs @@ -9,12 +9,15 @@ ioctl, // }, prelude::*, - sync::aref::ARef, // + sync::aref::ARef, + types::ForLt, // }; use crate::file::File; use crate::gem::NovaObject; +use nova_core::driver::AuxData; + pub(crate) struct NovaDriver; pub(crate) struct Nova { @@ -60,6 +63,10 @@ fn probe<'bound>( adev: &'bound auxiliary::Device<Core<'_>>, _info: &'bound Self::IdInfo, ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound { + let aux_data = adev.registration_data::<ForLt!(AuxData<'_>)>()?; + + pr_info!("Chipset from nova-core: {}\n", aux_data.chipset()); + let data = try_pin_init!(NovaData { adev: adev.into() }); let drm = drm::UnregisteredDevice::<Self>::new(adev.as_ref(), data)?; diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs index 5738d4ac521b..a214860f20de 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 +//! Main driver module. + use kernel::{ auxiliary, device::Core, @@ -18,18 +20,36 @@ types::ForLt, }; -use crate::gpu::Gpu; +use crate::gpu::{ + Chipset, + Gpu, // +}; /// Counter for generating unique auxiliary device IDs. static AUXILIARY_ID_COUNTER: Atomic<u32> = Atomic::new(0); +/// Data passed to the auxiliary device registration, for the sibling driver to use. +pub struct AuxData<'bound> { + gpu: &'bound Gpu<'bound>, +} + +impl AuxData<'_> { + /// Returns the chipset of this GPU. + pub fn chipset(&self) -> Chipset { + self.gpu.spec.chipset + } +} + +/// Driver-associated data. #[pin_data] -pub(crate) struct NovaCore<'bound> { +pub struct NovaCore<'bound> { + // Fields are dropped in declaration order: unregister the auxiliary device before dropping + // `gpu`, and drop `gpu` before `bar` because `AuxData` borrows `gpu` and `Gpu` borrows `bar`. + #[allow(clippy::type_complexity)] + _reg: auxiliary::Registration<'bound, ForLt!(AuxData<'_>)>, #[pin] pub(crate) gpu: Gpu<'bound>, bar: pci::Bar<'bound, BAR0_SIZE>, - #[allow(clippy::type_complexity)] - _reg: auxiliary::Registration<'bound, ForLt!(())>, } pub(crate) struct NovaCoreDriver; @@ -78,7 +98,7 @@ fn probe<'bound>( pdev.enable_device_mem()?; pdev.set_master(); - Ok(try_pin_init!(NovaCore { + Ok(try_pin_init!(&this in NovaCore { bar: pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0")?, // TODO: Use `&bar` self-referential pin-init syntax once available. // @@ -86,15 +106,26 @@ fn probe<'bound>( // (`try_pin_init!()` initializes fields in declaration order), lives at a pinned // stable address, and is dropped after `gpu` (struct field drop order). gpu <- Gpu::new(pdev, unsafe { &*core::ptr::from_ref(bar) }), - _reg: auxiliary::Registration::new( - pdev.as_ref(), - c"nova-drm", - // TODO[XARR]: Use XArray or perhaps IDA for proper ID allocation/recycling. For - // now, use a simple atomic counter that never recycles IDs. - AUXILIARY_ID_COUNTER.fetch_add(1, Relaxed), - crate::MODULE_NAME, - (), - )?, + // SAFETY: `NovaCore` is dropped when the device is unbound; i.e. `mem::forget()` is + // never called on it. + _reg: unsafe { + auxiliary::Registration::new_with_lt( + pdev.as_ref(), + c"nova-drm", + // TODO[XARR]: Use XArray or perhaps IDA for proper ID allocation/recycling. + // For now, use a simple atomic counter that never recycles IDs. + AUXILIARY_ID_COUNTER.fetch_add(1, Relaxed), + crate::MODULE_NAME, + AuxData { + // TODO: Use `&gpu` self-referential pin-init syntax once available. + // + // SAFETY: `this.gpu` is initialized before this expression is + // evaluated, lives at a pinned stable address, and is dropped after + // `_reg` (struct field drop order). + gpu: &(*this.as_ptr()).gpu, + }, + )? + }, })) }) } diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index b3c91731db45..bceed4652508 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 +//! Core types for the driver. + use core::ops::Range; use kernel::{ @@ -35,7 +37,8 @@ macro_rules! define_chipset { { /// Enum representation of the GPU chipset. #[derive(fmt::Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)] - pub(crate) enum Chipset { + #[allow(missing_docs)] + pub enum Chipset { $($variant = $value),*, } @@ -203,7 +206,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// Structure holding a basic description of the GPU: `Chipset` and `Revision`. #[derive(Clone, Copy)] pub(crate) struct Spec { - chipset: Chipset, + pub(crate) chipset: Chipset, revision: Revision, } @@ -267,7 +270,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { pub(crate) struct Gpu<'gpu> { /// Device owning the GPU. device: &'gpu device::Device<device::Bound>, - spec: Spec, + pub(crate) spec: Spec, /// MMIO mapping of PCI BAR 0. bar: Bar0<'gpu>, /// System memory page required for flushing all pending GPU-side memory writes done through diff --git a/drivers/gpu/nova-core/gsp/hal.rs b/drivers/gpu/nova-core/gsp/hal.rs index 04f004856c60..5f2d4a0c25cc 100644 --- a/drivers/gpu/nova-core/gsp/hal.rs +++ b/drivers/gpu/nova-core/gsp/hal.rs @@ -36,7 +36,7 @@ /// The GSP unload code might run in a situation where we cannot load firmware dynamically (e.g. /// because we are in shutdown and the file system is not accessible anymore). Thus, the firmware /// required for unloading is prepared at load time, and stored here until it needs to be run. -pub(super) trait UnloadBundle: Send { +pub(super) trait UnloadBundle: Send + Sync { /// Performs the steps required to properly reset the GSP after it has been stopped. fn run( &self, diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs index 9f0199f7b38c..77f647b8862a 100644 --- a/drivers/gpu/nova-core/nova_core.rs +++ b/drivers/gpu/nova-core/nova_core.rs @@ -13,12 +13,12 @@ #[macro_use] mod bitfield; -mod driver; +pub mod driver; mod falcon; mod fb; mod firmware; mod fsp; -mod gpu; +pub mod gpu; mod gsp; mod mctp; #[macro_use] -- 2.54.0
