[PATCH RFC 2/2] gpu: nova-core: demonstrate use of BoundedInt

Alexandre Courbot
2025-10-01T15:03:58Z

Augment the register macro with two new bounded setter and getter
methods, and showcase how they can be used in the driver.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
drivers/gpu/nova-core/falcon.rs | 14 +++++++++-----
drivers/gpu/nova-core/regs/macros.rs | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
index 37e6298195e49a9a29e81226abe16cd410c9adbc..2ce2635c86d8cad6e61862d4bd1976d642090c5b 100644
--- a/drivers/gpu/nova-core/falcon.rs
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -6,6 +6,7 @@
use hal::FalconHal;
use kernel::device;
use kernel::dma::DmaAddress;
+use kernel::num::BoundedInt;
use kernel::prelude::*;
use kernel::sync::aref::ARef;
use kernel::time::Delta;
@@ -488,24 +489,27 @@ fn dma_wr<F: FalconFirmware<Target = E>>(
// Set up the base source DMA address.

regs::NV_PFALCON_FALCON_DMATRFBASE::default()
- .set_base((dma_start >> 8) as u32)
+ .set_base_bounded(BoundedInt::new((dma_start >> 8) as u32))
.write(bar, &E::ID);
regs::NV_PFALCON_FALCON_DMATRFBASE1::default()
- .set_base((dma_start >> 40) as u16)
+ .set_base_bounded(BoundedInt::try_from((dma_start >> 40) as u32)?)
.write(bar, &E::ID);

+ let r = regs::NV_PFALCON_FALCON_DMATRFBASE::read(bar, &E::ID).base_bounded();
+ pr_info!("BASE: {:x}\n", r);
+
let cmd = regs::NV_PFALCON_FALCON_DMATRFCMD::default()
.set_size(DmaTrfCmdSize::Size256B)
.set_imem(target_mem == FalconMem::Imem)
- .set_sec(if sec { 1 } else { 0 });
+ .set_sec_bounded(BoundedInt::new(if sec { 1 } else { 0 }));

for pos in (0..num_transfers).map(|i| i * DMA_LEN) {
// Perform a transfer of size `DMA_LEN`.
regs::NV_PFALCON_FALCON_DMATRFMOFFS::default()
- .set_offs(load_offsets.dst_start + pos)
+ .set_offs_bounded(BoundedInt::try_from(load_offsets.dst_start + pos)?)
.write(bar, &E::ID);
regs::NV_PFALCON_FALCON_DMATRFFBOFFS::default()
- .set_offs(src_start + pos)
+ .set_offs_bounded(BoundedInt::new(src_start + pos))
.write(bar, &E::ID);
cmd.write(bar, &E::ID);

diff --git a/drivers/gpu/nova-core/regs/macros.rs b/drivers/gpu/nova-core/regs/macros.rs
index 754c14ee7f401688da51e138db71ccaa58445aa6..03a1830f492fdc1747767ed768ce2239e9ce41ec 100644
--- a/drivers/gpu/nova-core/regs/macros.rs
+++ b/drivers/gpu/nova-core/regs/macros.rs
@@ -565,6 +565,40 @@ pub(crate) fn [<set_ $field>](mut self, value: $to_type) -> Self {
self
}
);
+
+ ::kernel::macros::paste!(
+ pub(crate) fn [<$field _bounded>](self) ->
+ ::kernel::num::BoundedInt<u32, { $hi + 1 - $lo }> {
+ const MASK: u32 = $name::[<$field:upper _MASK>];
+ const SHIFT: u32 = $name::[<$field:upper _SHIFT>];
+ // Ensure the returned type has the same width as the field.
+ ::kernel::static_assert!(
+ MASK >> SHIFT == ::kernel::num::BoundedInt::<u32, { $hi + 1 - $lo }>::MASK
+ );
+
+ let field = ((self.0 & MASK) >> SHIFT);
+
+ ::kernel::num::BoundedInt::<u32, { $hi + 1 - $lo }>::new(field)
+ }
+
+ pub(crate) fn [<set_ $field _bounded>](
+ mut self,
+ value: ::kernel::num::BoundedInt<u32, { $hi + 1 - $lo }>
+ ) -> Self {
+ const MASK: u32 = $name::[<$field:upper _MASK>];
+ const SHIFT: u32 = $name::[<$field:upper _SHIFT>];
+ // Ensure the returned type has the same width as the field.
+ ::kernel::static_assert!(
+ MASK >> SHIFT == ::kernel::num::BoundedInt::<u32, { $hi + 1 - $lo }>::MASK
+ );
+
+ let value = (value.get() << SHIFT) & MASK;
+ self.0 = (self.0 & !MASK) | value;
+
+ self
+ }
+ );
+
};

// Generates the `Debug` implementation for `$name`.

--
2.51.0