[PATCH v2 08/21] gpu: nova-core: introduce helper macro for register access

Alexandre Courbot
2025-05-01T12:59:19Z

Acquiring the BAR temporarily to access is going to be a very common
pattern, that typically takes two lines of code and introduces a
short-lived local variable.

Add the Nova-local convenience with_bar!() macro, which uses
Revocable::try_access_with() and converts its returned Option into the
proper error as needed.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
drivers/gpu/nova-core/gpu.rs | 3 +--
drivers/gpu/nova-core/nova_core.rs | 18 ++++++++++++++++++
drivers/gpu/nova-core/regs/macros.rs | 1 +
3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 64c38425098c19360a7c938f2b86a55ca3c48880..275b005d262e0a01a9ef1498836ef3c3019cb497 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -148,8 +148,7 @@ pub(crate) struct Spec {

impl Spec {
fn new(bar: &Devres<Bar0>) -> Result<Spec> {
- let bar = bar.try_access().ok_or(ENXIO)?;
- let boot0 = regs::NV_PMC_BOOT_0::read(&*bar);
+ let boot0 = with_bar!(bar, regs::NV_PMC_BOOT_0::read)?;

Ok(Self {
chipset: boot0.chipset()?,
diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs
index a91cd924054b49966937a8db6aab9cd0614f10de..0eecd612e34efc046dad852e6239de6ffa5fdd62 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -2,6 +2,24 @@

//! Nova Core GPU Driver

+#[macro_use]
+mod macros {
+ /// Convenience macro to run a closure while holding [`crate::driver::Bar0`].
+ ///
+ /// If the bar cannot be acquired, then `ENXIO` is returned.
+ ///
+ /// If a `?` is present before the `bar` argument, then the `Result` returned by the closure is
+ /// merged into the `Result` of the macro itself to avoid having a `Result<Result<>>`.
+ macro_rules! with_bar {
+ ($bar:expr, $closure:expr) => {
+ $bar.try_access_with($closure).ok_or(ENXIO)
+ };
+ (? $bar:expr, $closure:expr) => {
+ with_bar!($bar, $closure).and_then(|r| r)
+ };
+ }
+}
+
mod driver;
mod firmware;
mod gpu;
diff --git a/drivers/gpu/nova-core/regs/macros.rs b/drivers/gpu/nova-core/regs/macros.rs
index a08d4f2aa0a32b00e80dae4e6b2c79d072241734..7ecc70efb3cd723b673cd72915e72b8a4a009f06 100644
--- a/drivers/gpu/nova-core/regs/macros.rs
+++ b/drivers/gpu/nova-core/regs/macros.rs
@@ -68,6 +68,7 @@
///
/// // Flip the `start` switch for the CPU core which base address is at `CPU_BASE`.
/// let cpuctl = CPU_CTL::read(&bar, CPU_BASE);
+/// pr_info!("CPU CTL: {:#x}", cpuctl);
/// cpuctl.set_start(true).write(&bar, CPU_BASE);
/// ```
macro_rules! register {

--
2.49.0