lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251231214727.448776-1-jhubbard@nvidia.com>
Date: Wed, 31 Dec 2025 13:47:27 -0800
From: John Hubbard <jhubbard@...dia.com>
To: Danilo Krummrich <dakr@...nel.org>
Cc: Alexandre Courbot <acourbot@...dia.com>,
	Joel Fernandes <joelagnelf@...dia.com>,
	Timur Tabi <ttabi@...dia.com>,
	Alistair Popple <apopple@...dia.com>,
	Edwin Peer <epeer@...dia.com>,
	Zhi Wang <zhiw@...dia.com>,
	David Airlie <airlied@...il.com>,
	Simona Vetter <simona@...ll.ch>,
	Bjorn Helgaas <bhelgaas@...gle.com>,
	Miguel Ojeda <ojeda@...nel.org>,
	Alex Gaynor <alex.gaynor@...il.com>,
	Boqun Feng <boqun.feng@...il.com>,
	Gary Guo <gary@...yguo.net>,
	Björn Roy Baron <bjorn3_gh@...tonmail.com>,
	Benno Lossin <lossin@...nel.org>,
	Andreas Hindborg <a.hindborg@...nel.org>,
	Alice Ryhl <aliceryhl@...gle.com>,
	Trevor Gross <tmgross@...ch.edu>,
	nouveau@...ts.freedesktop.org,
	rust-for-linux@...r.kernel.org,
	LKML <linux-kernel@...r.kernel.org>,
	John Hubbard <jhubbard@...dia.com>
Subject: [PATCH] gpu: nova-core: bitfield: use &mut self setters instead of builder pattern

The builder-pattern setters (self -> Self) enabled method chaining like:

    reg.set_foo(x).set_sec(y).write(bar);

This made separate operations appear as a single expression, obscuring
that each setter is a distinct mutation. These setters are infallible,
so the chaining provides no error-propagation benefit—it just obscures
what are simple, independent assignments.

Change the bitfield!() macro to generate `&mut self` setters, so each
operation is a distinct statement:

    reg.set_foo(x);
    reg.set_sec(y);
    reg.write(bar);

Update all call sites and change update() closures to take `&mut Self`.

Signed-off-by: John Hubbard <jhubbard@...dia.com>
---
 drivers/gpu/nova-core/bitfield.rs         |  4 +-
 drivers/gpu/nova-core/falcon.rs           | 98 ++++++++++++-----------
 drivers/gpu/nova-core/falcon/gsp.rs       |  6 +-
 drivers/gpu/nova-core/falcon/hal/ga102.rs | 33 ++++----
 drivers/gpu/nova-core/fb/hal/ga100.rs     | 21 ++---
 drivers/gpu/nova-core/fb/hal/tu102.rs     |  6 +-
 drivers/gpu/nova-core/gsp/cmdq.rs         |  6 +-
 drivers/gpu/nova-core/gsp/fw.rs           |  7 +-
 drivers/gpu/nova-core/regs/macros.rs      | 41 ++++++----
 9 files changed, 120 insertions(+), 102 deletions(-)

diff --git a/drivers/gpu/nova-core/bitfield.rs b/drivers/gpu/nova-core/bitfield.rs
index 16e143658c51..be152d1e08e0 100644
--- a/drivers/gpu/nova-core/bitfield.rs
+++ b/drivers/gpu/nova-core/bitfield.rs
@@ -284,13 +284,11 @@ impl $name {
         #[doc=$comment]
         )?
         #[inline(always)]
-        $vis fn [<set_ $field>](mut self, value: $to_type) -> Self {
+        $vis fn [<set_ $field>](&mut self, value: $to_type) {
             const MASK: $storage = $name::[<$field:upper _MASK>];
             const SHIFT: u32 = $name::[<$field:upper _SHIFT>];
             let value = ($storage::from($prim_type::from(value)) << SHIFT) & MASK;
             self.0 = (self.0 & !MASK) | value;
-
-            self
         }
         );
     };
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
index 82c661aef594..66fd37c73a3a 100644
--- a/drivers/gpu/nova-core/falcon.rs
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -413,12 +413,12 @@ fn reset_eng(&self, bar: &Bar0) -> Result {
             Delta::from_micros(150),
         );
 
-        regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_reset(true));
+        regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| { v.set_reset(true); });
 
         // TIMEOUT: falcon engine should not take more than 10us to reset.
         fsleep(Delta::from_micros(10));
 
-        regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_reset(false));
+        regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| { v.set_reset(false); });
 
         self.reset_wait_mem_scrubbing(bar)?;
 
@@ -431,9 +431,9 @@ pub(crate) fn reset(&self, bar: &Bar0) -> Result {
         self.hal.select_core(self, bar)?;
         self.reset_wait_mem_scrubbing(bar)?;
 
-        regs::NV_PFALCON_FALCON_RM::default()
-            .set_value(regs::NV_PMC_BOOT_0::read(bar).into())
-            .write(bar, &E::ID);
+        let mut reg = regs::NV_PFALCON_FALCON_RM::default();
+        reg.set_value(regs::NV_PMC_BOOT_0::read(bar).into());
+        reg.write(bar, &E::ID);
 
         Ok(())
     }
@@ -495,30 +495,32 @@ fn dma_wr<F: FalconFirmware<Target = E>>(
 
         // Set up the base source DMA address.
 
-        regs::NV_PFALCON_FALCON_DMATRFBASE::default()
-            // CAST: `as u32` is used on purpose since we do want to strip the upper bits, which
-            // will be written to `NV_PFALCON_FALCON_DMATRFBASE1`.
-            .set_base((dma_start >> 8) as u32)
-            .write(bar, &E::ID);
-        regs::NV_PFALCON_FALCON_DMATRFBASE1::default()
-            // CAST: `as u16` is used on purpose since the remaining bits are guaranteed to fit
-            // within a `u16`.
-            .set_base((dma_start >> 40) as u16)
-            .write(bar, &E::ID);
-
-        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 });
+        // CAST: `as u32` is used on purpose since we do want to strip the upper bits, which
+        // will be written to `NV_PFALCON_FALCON_DMATRFBASE1`.
+        let mut reg = regs::NV_PFALCON_FALCON_DMATRFBASE::default();
+        reg.set_base((dma_start >> 8) as u32);
+        reg.write(bar, &E::ID);
+
+        // CAST: `as u16` is used on purpose since the remaining bits are guaranteed to fit
+        // within a `u16`.
+        let mut reg = regs::NV_PFALCON_FALCON_DMATRFBASE1::default();
+        reg.set_base((dma_start >> 40) as u16);
+        reg.write(bar, &E::ID);
+
+        let mut cmd = regs::NV_PFALCON_FALCON_DMATRFCMD::default();
+        cmd.set_size(DmaTrfCmdSize::Size256B);
+        cmd.set_imem(target_mem == FalconMem::Imem);
+        cmd.set_sec(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)
-                .write(bar, &E::ID);
-            regs::NV_PFALCON_FALCON_DMATRFFBOFFS::default()
-                .set_offs(src_start + pos)
-                .write(bar, &E::ID);
+            let mut reg = regs::NV_PFALCON_FALCON_DMATRFMOFFS::default();
+            reg.set_offs(load_offsets.dst_start + pos);
+            reg.write(bar, &E::ID);
+
+            let mut reg = regs::NV_PFALCON_FALCON_DMATRFFBOFFS::default();
+            reg.set_offs(src_start + pos);
+            reg.write(bar, &E::ID);
             cmd.write(bar, &E::ID);
 
             // Wait for the transfer to complete.
@@ -539,8 +541,8 @@ fn dma_wr<F: FalconFirmware<Target = E>>(
     pub(crate) fn dma_load<F: FalconFirmware<Target = E>>(&self, bar: &Bar0, fw: &F) -> Result {
         self.dma_reset(bar);
         regs::NV_PFALCON_FBIF_TRANSCFG::update(bar, &E::ID, 0, |v| {
-            v.set_target(FalconFbifTarget::CoherentSysmem)
-                .set_mem_type(FalconFbifMemType::Physical)
+            v.set_target(FalconFbifTarget::CoherentSysmem);
+            v.set_mem_type(FalconFbifMemType::Physical);
         });
 
         self.dma_wr(bar, fw, FalconMem::Imem, fw.imem_load_params(), true)?;
@@ -549,9 +551,9 @@ pub(crate) fn dma_load<F: FalconFirmware<Target = E>>(&self, bar: &Bar0, fw: &F)
         self.hal.program_brom(self, bar, &fw.brom_params())?;
 
         // Set `BootVec` to start of non-secure code.
-        regs::NV_PFALCON_FALCON_BOOTVEC::default()
-            .set_value(fw.boot_addr())
-            .write(bar, &E::ID);
+        let mut reg = regs::NV_PFALCON_FALCON_BOOTVEC::default();
+        reg.set_value(fw.boot_addr());
+        reg.write(bar, &E::ID);
 
         Ok(())
     }
@@ -572,12 +574,16 @@ pub(crate) fn wait_till_halted(&self, bar: &Bar0) -> Result<()> {
     /// Start the falcon CPU.
     pub(crate) fn start(&self, bar: &Bar0) -> Result<()> {
         match regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID).alias_en() {
-            true => regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::default()
-                .set_startcpu(true)
-                .write(bar, &E::ID),
-            false => regs::NV_PFALCON_FALCON_CPUCTL::default()
-                .set_startcpu(true)
-                .write(bar, &E::ID),
+            true => {
+                let mut reg = regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::default();
+                reg.set_startcpu(true);
+                reg.write(bar, &E::ID);
+            }
+            false => {
+                let mut reg = regs::NV_PFALCON_FALCON_CPUCTL::default();
+                reg.set_startcpu(true);
+                reg.write(bar, &E::ID);
+            }
         }
 
         Ok(())
@@ -586,15 +592,15 @@ pub(crate) fn start(&self, bar: &Bar0) -> Result<()> {
     /// Writes values to the mailbox registers if provided.
     pub(crate) fn write_mailboxes(&self, bar: &Bar0, mbox0: Option<u32>, mbox1: Option<u32>) {
         if let Some(mbox0) = mbox0 {
-            regs::NV_PFALCON_FALCON_MAILBOX0::default()
-                .set_value(mbox0)
-                .write(bar, &E::ID);
+            let mut reg = regs::NV_PFALCON_FALCON_MAILBOX0::default();
+            reg.set_value(mbox0);
+            reg.write(bar, &E::ID);
         }
 
         if let Some(mbox1) = mbox1 {
-            regs::NV_PFALCON_FALCON_MAILBOX1::default()
-                .set_value(mbox1)
-                .write(bar, &E::ID);
+            let mut reg = regs::NV_PFALCON_FALCON_MAILBOX1::default();
+            reg.set_value(mbox1);
+            reg.write(bar, &E::ID);
         }
     }
 
@@ -657,8 +663,8 @@ pub(crate) fn is_riscv_active(&self, bar: &Bar0) -> bool {
 
     /// Write the application version to the OS register.
     pub(crate) fn write_os_version(&self, bar: &Bar0, app_version: u32) {
-        regs::NV_PFALCON_FALCON_OS::default()
-            .set_value(app_version)
-            .write(bar, &E::ID);
+        let mut reg = regs::NV_PFALCON_FALCON_OS::default();
+        reg.set_value(app_version);
+        reg.write(bar, &E::ID);
     }
 }
diff --git a/drivers/gpu/nova-core/falcon/gsp.rs b/drivers/gpu/nova-core/falcon/gsp.rs
index 67edef3636c1..ce76c75cfdc6 100644
--- a/drivers/gpu/nova-core/falcon/gsp.rs
+++ b/drivers/gpu/nova-core/falcon/gsp.rs
@@ -39,9 +39,9 @@ impl Falcon<Gsp> {
     /// Clears the SWGEN0 bit in the Falcon's IRQ status clear register to
     /// allow GSP to signal CPU for processing new messages in message queue.
     pub(crate) fn clear_swgen0_intr(&self, bar: &Bar0) {
-        regs::NV_PFALCON_FALCON_IRQSCLR::default()
-            .set_swgen0(true)
-            .write(bar, &Gsp::ID);
+        let mut reg = regs::NV_PFALCON_FALCON_IRQSCLR::default();
+        reg.set_swgen0(true);
+        reg.write(bar, &Gsp::ID);
     }
 
     /// Checks if GSP reload/resume has completed during the boot process.
diff --git a/drivers/gpu/nova-core/falcon/hal/ga102.rs b/drivers/gpu/nova-core/falcon/hal/ga102.rs
index 69a7a95cac16..4fb94c727b65 100644
--- a/drivers/gpu/nova-core/falcon/hal/ga102.rs
+++ b/drivers/gpu/nova-core/falcon/hal/ga102.rs
@@ -26,9 +26,9 @@
 fn select_core_ga102<E: FalconEngine>(bar: &Bar0) -> Result {
     let bcr_ctrl = regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID);
     if bcr_ctrl.core_select() != PeregrineCoreSelect::Falcon {
-        regs::NV_PRISCV_RISCV_BCR_CTRL::default()
-            .set_core_select(PeregrineCoreSelect::Falcon)
-            .write(bar, &E::ID);
+        let mut reg = regs::NV_PRISCV_RISCV_BCR_CTRL::default();
+        reg.set_core_select(PeregrineCoreSelect::Falcon);
+        reg.write(bar, &E::ID);
 
         // TIMEOUT: falcon core should take less than 10ms to report being enabled.
         read_poll_timeout(
@@ -75,18 +75,21 @@ fn signature_reg_fuse_version_ga102(
 }
 
 fn program_brom_ga102<E: FalconEngine>(bar: &Bar0, params: &FalconBromParams) -> Result {
-    regs::NV_PFALCON2_FALCON_BROM_PARAADDR::default()
-        .set_value(params.pkc_data_offset)
-        .write(bar, &E::ID, 0);
-    regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default()
-        .set_value(u32::from(params.engine_id_mask))
-        .write(bar, &E::ID);
-    regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default()
-        .set_ucode_id(params.ucode_id)
-        .write(bar, &E::ID);
-    regs::NV_PFALCON2_FALCON_MOD_SEL::default()
-        .set_algo(FalconModSelAlgo::Rsa3k)
-        .write(bar, &E::ID);
+    let mut reg = regs::NV_PFALCON2_FALCON_BROM_PARAADDR::default();
+    reg.set_value(params.pkc_data_offset);
+    reg.write(bar, &E::ID, 0);
+
+    let mut reg = regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default();
+    reg.set_value(u32::from(params.engine_id_mask));
+    reg.write(bar, &E::ID);
+
+    let mut reg = regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default();
+    reg.set_ucode_id(params.ucode_id);
+    reg.write(bar, &E::ID);
+
+    let mut reg = regs::NV_PFALCON2_FALCON_MOD_SEL::default();
+    reg.set_algo(FalconModSelAlgo::Rsa3k);
+    reg.write(bar, &E::ID);
 
     Ok(())
 }
diff --git a/drivers/gpu/nova-core/fb/hal/ga100.rs b/drivers/gpu/nova-core/fb/hal/ga100.rs
index e0acc41aa7cd..027f2f59614f 100644
--- a/drivers/gpu/nova-core/fb/hal/ga100.rs
+++ b/drivers/gpu/nova-core/fb/hal/ga100.rs
@@ -19,16 +19,17 @@ pub(super) fn read_sysmem_flush_page_ga100(bar: &Bar0) -> u64 {
 }
 
 pub(super) fn write_sysmem_flush_page_ga100(bar: &Bar0, addr: u64) {
-    regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::default()
-        // CAST: `as u32` is used on purpose since the remaining bits are guaranteed to fit within
-        // a `u32`.
-        .set_adr_63_40((addr >> FLUSH_SYSMEM_ADDR_SHIFT_HI) as u32)
-        .write(bar);
-    regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default()
-        // CAST: `as u32` is used on purpose since we want to strip the upper bits that have been
-        // written to `NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI`.
-        .set_adr_39_08((addr >> FLUSH_SYSMEM_ADDR_SHIFT) as u32)
-        .write(bar);
+    // CAST: `as u32` is used on purpose since the remaining bits are guaranteed to fit within
+    // a `u32`.
+    let mut reg = regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::default();
+    reg.set_adr_63_40((addr >> FLUSH_SYSMEM_ADDR_SHIFT_HI) as u32);
+    reg.write(bar);
+
+    // CAST: `as u32` is used on purpose since we want to strip the upper bits that have been
+    // written to `NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI`.
+    let mut reg = regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default();
+    reg.set_adr_39_08((addr >> FLUSH_SYSMEM_ADDR_SHIFT) as u32);
+    reg.write(bar);
 }
 
 pub(super) fn display_enabled_ga100(bar: &Bar0) -> bool {
diff --git a/drivers/gpu/nova-core/fb/hal/tu102.rs b/drivers/gpu/nova-core/fb/hal/tu102.rs
index eec984f4e816..994a173dc6f4 100644
--- a/drivers/gpu/nova-core/fb/hal/tu102.rs
+++ b/drivers/gpu/nova-core/fb/hal/tu102.rs
@@ -21,9 +21,9 @@ pub(super) fn write_sysmem_flush_page_gm107(bar: &Bar0, addr: u64) -> Result {
     u32::try_from(addr >> FLUSH_SYSMEM_ADDR_SHIFT)
         .map_err(|_| EINVAL)
         .map(|addr| {
-            regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default()
-                .set_adr_39_08(addr)
-                .write(bar)
+            let mut reg = regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default();
+            reg.set_adr_39_08(addr);
+            reg.write(bar);
         })
 }
 
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 6f946d14868a..358c97b96e9a 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -475,9 +475,9 @@ fn calculate_checksum<T: Iterator<Item = u8>>(it: T) -> u32 {
 
     /// Notifies the GSP that we have updated the command queue pointers.
     fn notify_gsp(bar: &Bar0) {
-        regs::NV_PGSP_QUEUE_HEAD::default()
-            .set_address(0)
-            .write(bar);
+        let mut reg = regs::NV_PGSP_QUEUE_HEAD::default();
+        reg.set_address(0);
+        reg.write(bar);
     }
 
     /// Sends `command` to the GSP.
diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs
index abffd6beec65..2436933ac8cd 100644
--- a/drivers/gpu/nova-core/gsp/fw.rs
+++ b/drivers/gpu/nova-core/gsp/fw.rs
@@ -772,9 +772,10 @@ impl MsgHeaderVersion {
     const MINOR_TOT: u8 = 0;
 
     fn new() -> Self {
-        Self::default()
-            .set_major(Self::MAJOR_TOT)
-            .set_minor(Self::MINOR_TOT)
+        let mut v = Self::default();
+        v.set_major(Self::MAJOR_TOT);
+        v.set_minor(Self::MINOR_TOT);
+        v
     }
 }
 
diff --git a/drivers/gpu/nova-core/regs/macros.rs b/drivers/gpu/nova-core/regs/macros.rs
index fd1a815fa57d..6ab20e960399 100644
--- a/drivers/gpu/nova-core/regs/macros.rs
+++ b/drivers/gpu/nova-core/regs/macros.rs
@@ -49,10 +49,15 @@ pub(crate) trait RegisterBase<T> {
 /// let chipset = boot0.chipset()?;
 ///
 /// // Update some fields and write the value back.
-/// boot0.set_major_revision(3).set_minor_revision(10).write(&bar);
+/// boot0.set_major_revision(3);
+/// boot0.set_minor_revision(10);
+/// boot0.write(&bar);
 ///
 /// // Or, just read and update the register in a single step:
-/// BOOT_0::update(&bar, |r| r.set_major_revision(3).set_minor_revision(10));
+/// BOOT_0::update(&bar, |r| {
+///     r.set_major_revision(3);
+///     r.set_minor_revision(10);
+/// });
 /// ```
 ///
 /// The documentation strings are optional. If present, they will be added to the type's
@@ -388,12 +393,13 @@ pub(crate) fn write<const SIZE: usize, T>(self, io: &T) where
             #[inline(always)]
             pub(crate) fn update<const SIZE: usize, T, F>(
                 io: &T,
-                f: F,
+                mut f: F,
             ) where
                 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>,
-                F: ::core::ops::FnOnce(Self) -> Self,
+                F: ::core::ops::FnMut(&mut Self),
             {
-                let reg = f(Self::read(io));
+                let mut reg = Self::read(io);
+                f(&mut reg);
                 reg.write(io);
             }
         }
@@ -452,13 +458,14 @@ pub(crate) fn write<const SIZE: usize, T, B>(
             pub(crate) fn update<const SIZE: usize, T, B, F>(
                 io: &T,
                 base: &B,
-                f: F,
+                mut f: F,
             ) where
                 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>,
                 B: crate::regs::macros::RegisterBase<$base>,
-                F: ::core::ops::FnOnce(Self) -> Self,
+                F: ::core::ops::FnMut(&mut Self),
             {
-                let reg = f(Self::read(io, base));
+                let mut reg = Self::read(io, base);
+                f(&mut reg);
                 reg.write(io, base);
             }
         }
@@ -510,12 +517,13 @@ pub(crate) fn write<const SIZE: usize, T>(
             pub(crate) fn update<const SIZE: usize, T, F>(
                 io: &T,
                 idx: usize,
-                f: F,
+                mut f: F,
             ) where
                 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>,
-                F: ::core::ops::FnOnce(Self) -> Self,
+                F: ::core::ops::FnMut(&mut Self),
             {
-                let reg = f(Self::read(io, idx));
+                let mut reg = Self::read(io, idx);
+                f(&mut reg);
                 reg.write(io, idx);
             }
 
@@ -568,7 +576,7 @@ pub(crate) fn try_update<const SIZE: usize, T, F>(
                 f: F,
             ) -> ::kernel::error::Result where
                 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>,
-                F: ::core::ops::FnOnce(Self) -> Self,
+                F: ::core::ops::FnMut(&mut Self),
             {
                 if idx < Self::SIZE {
                     Ok(Self::update(io, idx, f))
@@ -640,13 +648,14 @@ pub(crate) fn update<const SIZE: usize, T, B, F>(
                 io: &T,
                 base: &B,
                 idx: usize,
-                f: F,
+                mut f: F,
             ) where
                 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>,
                 B: crate::regs::macros::RegisterBase<$base>,
-                F: ::core::ops::FnOnce(Self) -> Self,
+                F: ::core::ops::FnMut(&mut Self),
             {
-                let reg = f(Self::read(io, base, idx));
+                let mut reg = Self::read(io, base, idx);
+                f(&mut reg);
                 reg.write(io, base, idx);
             }
 
@@ -708,7 +717,7 @@ pub(crate) fn try_update<const SIZE: usize, T, B, F>(
             ) -> ::kernel::error::Result where
                 T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>,
                 B: crate::regs::macros::RegisterBase<$base>,
-                F: ::core::ops::FnOnce(Self) -> Self,
+                F: ::core::ops::FnMut(&mut Self),
             {
                 if idx < Self::SIZE {
                     Ok(Self::update(io, base, idx, f))

base-commit: 7acc70476f14661149774ab88d3fe23d83ba4249
-- 
2.52.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ