diff options
| -rw-r--r-- | Documentation/gpu/nova/core/todo.rst | 11 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/falcon.rs | 62 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/falcon/hal/ga102.rs | 16 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/gfw.rs | 36 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/nova_core.rs | 1 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/util.rs | 27 |
6 files changed, 51 insertions, 102 deletions
diff --git a/Documentation/gpu/nova/core/todo.rst b/Documentation/gpu/nova/core/todo.rst index 0972cb905f7a..c55c7bedbfdf 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 e4a4d454941c..fb3561cc9746 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<E: FalconEngine + 'static> Falcon<E> { /// 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<E: FalconEngine + 'static> Falcon<E> { // 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<E: FalconEngine + 'static> Falcon<E> { // 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<E: FalconEngine + 'static> Falcon<E> { } // 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 0b1cbe7853b3..f2ae9537321d 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<E: FalconEngine>(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 8ac1ed187199..23c28c2a3793 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 112277c7921e..e130166c1086 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 = <LocalModule as kernel::ModuleMetadata>::NAME; diff --git a/drivers/gpu/nova-core/util.rs b/drivers/gpu/nova-core/util.rs deleted file mode 100644 index bf35f00cb732..000000000000 --- 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<R, F: Fn() -> Option<R>>(timeout: Delta, cond: F) -> Result<R> { - let start_time = Instant::<Monotonic>::now(); - - loop { - if let Some(ret) = cond() { - return Ok(ret); - } - - if start_time.elapsed().as_nanos() > timeout.as_nanos() { - return Err(ETIMEDOUT); - } - } -} |