From: Alexandre Courbot Date: Mon, 20 Oct 2025 06:09:25 +0000 (+0900) Subject: gpu: nova-core: replace wait_on with kernel equivalents X-Git-Tag: v6.19-rc1~157^2~8^2~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76544ef6a01b2d8fa86f92ff17940b6ff534696e;p=thirdparty%2Fkernel%2Flinux.git gpu: nova-core: replace wait_on with kernel equivalents wait_on was a temporary helper function waiting for a kernel crate equivalent. Now that read_poll_timeout and fsleep are available, use them and remove wait_on. Acked-by: Danilo Krummrich Signed-off-by: Alexandre Courbot Message-ID: <20251020-nova_wait_on-v1-1-2eb87fb38d14@nvidia.com> --- diff --git a/Documentation/gpu/nova/core/todo.rst b/Documentation/gpu/nova/core/todo.rst index 0972cb905f7ae..c55c7bedbfdfa 100644 --- a/Documentation/gpu/nova/core/todo.rst +++ b/Documentation/gpu/nova/core/todo.rst @@ -153,17 +153,6 @@ A `num` core kernel module is being designed to provide these operations. | Complexity: Intermediate | Contact: Alexandre Courbot -Delay / Sleep abstractions [DLAY] ---------------------------------- - -Rust abstractions for the kernel's delay() and sleep() functions. - -FUJITA Tomonori plans to work on abstractions for read_poll_timeout_atomic() -(and friends) [1]. - -| Complexity: Beginner -| Link: https://lore.kernel.org/netdev/20250228.080550.354359820929821928.fujita.tomonori@gmail.com/ [1] - IRQ abstractions ---------------- diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs index e4a4d454941c3..fb3561cc97460 100644 --- a/drivers/gpu/nova-core/falcon.rs +++ b/drivers/gpu/nova-core/falcon.rs @@ -6,8 +6,10 @@ use core::ops::Deref; use hal::FalconHal; use kernel::device; use kernel::dma::DmaAddress; +use kernel::io::poll::read_poll_timeout; use kernel::prelude::*; use kernel::sync::aref::ARef; +use kernel::time::delay::fsleep; use kernel::time::Delta; use crate::dma::DmaObject; @@ -15,7 +17,6 @@ use crate::driver::Bar0; use crate::gpu::Chipset; use crate::regs; use crate::regs::macros::RegisterBase; -use crate::util; pub(crate) mod gsp; mod hal; @@ -372,13 +373,13 @@ impl Falcon { /// Wait for memory scrubbing to complete. fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Result { // TIMEOUT: memory scrubbing should complete in less than 20ms. - util::wait_on(Delta::from_millis(20), || { - if regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID).mem_scrubbing_done() { - Some(()) - } else { - None - } - }) + read_poll_timeout( + || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)), + |r| r.mem_scrubbing_done(), + Delta::ZERO, + Delta::from_millis(20), + ) + .map(|_| ()) } /// Reset the falcon engine. @@ -387,20 +388,17 @@ impl Falcon { // According to OpenRM's `kflcnPreResetWait_GA102` documentation, HW sometimes does not set // RESET_READY so a non-failing timeout is used. - let _ = util::wait_on(Delta::from_micros(150), || { - let r = regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID); - if r.reset_ready() { - Some(()) - } else { - None - } - }); + let _ = read_poll_timeout( + || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)), + |r| r.reset_ready(), + Delta::ZERO, + Delta::from_micros(150), + ); regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_reset(true)); - // TODO[DLAY]: replace with udelay() or equivalent once available. // TIMEOUT: falcon engine should not take more than 10us to reset. - let _: Result = util::wait_on(Delta::from_micros(10), || None); + fsleep(Delta::from_micros(10)); regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_reset(false)); @@ -504,14 +502,12 @@ impl Falcon { // Wait for the transfer to complete. // TIMEOUT: arbitrarily large value, no DMA transfer to the falcon's small memories // should ever take that long. - util::wait_on(Delta::from_secs(2), || { - let r = regs::NV_PFALCON_FALCON_DMATRFCMD::read(bar, &E::ID); - if r.idle() { - Some(()) - } else { - None - } - })?; + read_poll_timeout( + || Ok(regs::NV_PFALCON_FALCON_DMATRFCMD::read(bar, &E::ID)), + |r| r.idle(), + Delta::ZERO, + Delta::from_secs(2), + )?; } Ok(()) @@ -574,14 +570,12 @@ impl Falcon { } // TIMEOUT: arbitrarily large value, firmwares should complete in less than 2 seconds. - util::wait_on(Delta::from_secs(2), || { - let r = regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID); - if r.halted() { - Some(()) - } else { - None - } - })?; + read_poll_timeout( + || Ok(regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID)), + |r| r.halted(), + Delta::ZERO, + Delta::from_secs(2), + )?; let (mbox0, mbox1) = ( regs::NV_PFALCON_FALCON_MAILBOX0::read(bar, &E::ID).value(), diff --git a/drivers/gpu/nova-core/falcon/hal/ga102.rs b/drivers/gpu/nova-core/falcon/hal/ga102.rs index 0b1cbe7853b3e..f2ae9537321d0 100644 --- a/drivers/gpu/nova-core/falcon/hal/ga102.rs +++ b/drivers/gpu/nova-core/falcon/hal/ga102.rs @@ -3,6 +3,7 @@ use core::marker::PhantomData; use kernel::device; +use kernel::io::poll::read_poll_timeout; use kernel::prelude::*; use kernel::time::Delta; @@ -11,7 +12,6 @@ use crate::falcon::{ Falcon, FalconBromParams, FalconEngine, FalconModSelAlgo, PeregrineCoreSelect, }; use crate::regs; -use crate::util; use super::FalconHal; @@ -23,14 +23,12 @@ fn select_core_ga102(bar: &Bar0) -> Result { .write(bar, &E::ID); // TIMEOUT: falcon core should take less than 10ms to report being enabled. - util::wait_on(Delta::from_millis(10), || { - let r = regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID); - if r.valid() { - Some(()) - } else { - None - } - })?; + read_poll_timeout( + || Ok(regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID)), + |r| r.valid(), + Delta::ZERO, + Delta::from_millis(10), + )?; } Ok(()) diff --git a/drivers/gpu/nova-core/gfw.rs b/drivers/gpu/nova-core/gfw.rs index 8ac1ed1871992..23c28c2a3793a 100644 --- a/drivers/gpu/nova-core/gfw.rs +++ b/drivers/gpu/nova-core/gfw.rs @@ -18,13 +18,12 @@ //! //! Note that the devinit sequence also needs to run during suspend/resume. -use kernel::bindings; +use kernel::io::poll::read_poll_timeout; use kernel::prelude::*; use kernel::time::Delta; use crate::driver::Bar0; use crate::regs; -use crate::util; /// Wait for the `GFW` (GPU firmware) boot completion signal (`GFW_BOOT`), or a 4 seconds timeout. /// @@ -50,22 +49,19 @@ pub(crate) fn wait_gfw_boot_completion(bar: &Bar0) -> Result { // // TIMEOUT: arbitrarily large value. GFW starts running immediately after the GPU is put out of // reset, and should complete in less time than that. - util::wait_on(Delta::from_secs(4), || { - // Check that FWSEC has lowered its protection level before reading the GFW_BOOT status. - let gfw_booted = regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK::read(bar) - .read_protection_level0() - && regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT::read(bar).completed(); - - if gfw_booted { - Some(()) - } else { - // TODO[DLAY]: replace with [1] once it merges. - // [1] https://lore.kernel.org/rust-for-linux/20250423192857.199712-6-fujita.tomonori@gmail.com/ - // - // SAFETY: `msleep()` is safe to call with any parameter. - unsafe { bindings::msleep(1) }; - - None - } - }) + read_poll_timeout( + || { + Ok( + // Check that FWSEC has lowered its protection level before reading the GFW_BOOT + // status. + regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK::read(bar) + .read_protection_level0() + && regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT::read(bar).completed(), + ) + }, + |&gfw_booted| gfw_booted, + Delta::from_millis(1), + Delta::from_secs(4), + ) + .map(|_| ()) } diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs index 112277c7921eb..e130166c1086f 100644 --- a/drivers/gpu/nova-core/nova_core.rs +++ b/drivers/gpu/nova-core/nova_core.rs @@ -14,7 +14,6 @@ mod gfw; mod gpu; mod gsp; mod regs; -mod util; mod vbios; pub(crate) const MODULE_NAME: &kernel::str::CStr = ::NAME; diff --git a/drivers/gpu/nova-core/util.rs b/drivers/gpu/nova-core/util.rs deleted file mode 100644 index bf35f00cb732e..0000000000000 --- a/drivers/gpu/nova-core/util.rs +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -use kernel::prelude::*; -use kernel::time::{Delta, Instant, Monotonic}; - -/// Wait until `cond` is true or `timeout` elapsed. -/// -/// When `cond` evaluates to `Some`, its return value is returned. -/// -/// `Err(ETIMEDOUT)` is returned if `timeout` has been reached without `cond` evaluating to -/// `Some`. -/// -/// TODO[DLAY]: replace with `read_poll_timeout` once it is available. -/// (https://lore.kernel.org/lkml/20250220070611.214262-8-fujita.tomonori@gmail.com/) -pub(crate) fn wait_on Option>(timeout: Delta, cond: F) -> Result { - let start_time = Instant::::now(); - - loop { - if let Some(ret) = cond() { - return Ok(ret); - } - - if start_time.elapsed().as_nanos() > timeout.as_nanos() { - return Err(ETIMEDOUT); - } - } -}