On Wed, May 07, 2025 at 10:52:36PM +0900, Alexandre Courbot wrote:
> Upon reset, the GPU executes the GFW_BOOT firmware in order to
> initialize its base parameters such as clocks. The driver must ensure
> that this step is completed before using the hardware.
> 
> Signed-off-by: Alexandre Courbot <acour...@nvidia.com>
> ---
>  drivers/gpu/nova-core/devinit.rs   | 38 
> ++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/nova-core/driver.rs    |  2 +-
>  drivers/gpu/nova-core/gpu.rs       |  5 +++++
>  drivers/gpu/nova-core/nova_core.rs |  1 +
>  drivers/gpu/nova-core/regs.rs      | 11 +++++++++++
>  5 files changed, 56 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/nova-core/devinit.rs 
> b/drivers/gpu/nova-core/devinit.rs
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..5be2e0344fb651e5e53c9223aefeb5b2d95b8de1
> --- /dev/null
> +++ b/drivers/gpu/nova-core/devinit.rs
> @@ -0,0 +1,38 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Methods for device initialization.
> +
> +use kernel::bindings;
> +use kernel::prelude::*;
> +
> +use crate::driver::Bar0;
> +use crate::regs;
> +
> +/// Wait for devinit FW completion.
> +///
> +/// Upon reset, the GPU runs some firmware code to setup its core 
> parameters. Most of the GPU is
> +/// considered unusable until this step is completed, so it must be waited 
> on very early during
> +/// driver initialization.
> +pub(crate) fn wait_gfw_boot_completion(bar: &Bar0) -> Result<()> {
> +    let mut timeout = 2000;
> +
> +    loop {
> +        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::read(bar).value() 
> & 0xff) == 0xff;

What does it mean when the first 8 bits are set? Why don't we have a mask and
value to compare for that?

> +
> +        if gfw_booted {
> +            return Ok(());
> +        }
> +
> +        if timeout == 0 {
> +            return Err(ETIMEDOUT);
> +        }
> +        timeout -= 1;

NIT: This means the timeout is ~4s; can we start with timeout == 4000 and 
decrement
with the number of ms passed to msleep()?

Anyways, this should go away with read_poll_timeout() anyways.

> +
> +        // TODO: use `read_poll_timeout` once it is available.
> +        // 
> (https://lore.kernel.org/lkml/20250220070611.214262-8-fujita.tomon...@gmail.com/)
> +        // SAFETY: msleep should be safe to call with any parameter.
> +        unsafe { bindings::msleep(2) };
> +    }
> +}
> diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs
> index 
> a08fb6599267a960f0e07b6efd0e3b6cdc296aa4..752ba4b0fcfe8d835d366570bb2f807840a196da
>  100644
> --- a/drivers/gpu/nova-core/driver.rs
> +++ b/drivers/gpu/nova-core/driver.rs
> @@ -10,7 +10,7 @@ pub(crate) struct NovaCore {
>      pub(crate) gpu: Gpu,
>  }
>  
> -const BAR0_SIZE: usize = 8;
> +const BAR0_SIZE: usize = 0x1000000;

This means that we'll fail probing the card if BAR0 is not at least 16MiB.
AFAIK, that should be fine. However, can you make this a separate patch please?

Reply via email to