Re: [PATCH v10 11/28] gpu: nova-core: Hopper/Blackwell: integrate FSP boot path into boot()

From: Alexandre Courbot

Date: Fri Apr 17 2026 - 10:29:06 EST


On Sat Apr 11, 2026 at 11:49 AM JST, John Hubbard wrote:
<snip>
> @@ -166,39 +222,41 @@ pub(crate) fn boot(
> sec2_falcon: &Falcon<Sec2>,
> ) -> Result {
> let dev = pdev.as_ref();
> -
> - let bios = Vbios::new(dev, bar)?;
> + let uses_sec2 = matches!(
> + chipset.arch(),
> + Architecture::Turing | Architecture::Ampere | Architecture::Ada
> + );
>
> let gsp_fw = KBox::pin_init(GspFirmware::new(dev, chipset, FIRMWARE_VERSION), GFP_KERNEL)?;
>
> let fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?;
> dev_dbg!(dev, "{:#x?}\n", fb_layout);
>
> - Self::run_fwsec_frts(dev, chipset, gsp_falcon, bar, &bios, &fb_layout)?;
> -
> let wpr_meta = Coherent::init(dev, GFP_KERNEL, GspFwWprMeta::new(&gsp_fw, &fb_layout))?;
>
> - self.cmdq
> - .send_command_no_wait(bar, commands::SetSystemInfo::new(pdev, chipset))?;
> - self.cmdq
> - .send_command_no_wait(bar, commands::SetRegistry::new())?;
> + // Architecture-specific boot path
> + if uses_sec2 {
> + // SEC2 path: send commands before GSP reset/boot (original order).
> + self.cmdq
> + .send_command_no_wait(bar, commands::SetSystemInfo::new(pdev, chipset))?;
> + self.cmdq
> + .send_command_no_wait(bar, commands::SetRegistry::new())?;
>
> - gsp_falcon.reset(bar)?;
> - let libos_handle = self.libos.dma_handle();
> - let (mbox0, mbox1) = gsp_falcon.boot(
> - bar,
> - Some(libos_handle as u32),
> - Some((libos_handle >> 32) as u32),
> - )?;
> - dev_dbg!(pdev, "GSP MBOX0: {:#x}, MBOX1: {:#x}\n", mbox0, mbox1);
> -
> - dev_dbg!(
> - pdev,
> - "Using SEC2 to load and run the booter_load firmware...\n"
> - );
> -
> - Self::run_booter(dev, bar, chipset, sec2_falcon, &wpr_meta)?;
> + Self::boot_via_sec2(
> + dev,
> + bar,
> + chipset,
> + gsp_falcon,
> + sec2_falcon,
> + &fb_layout,
> + &self.libos,
> + &wpr_meta,
> + )?;
> + } else {
> + Self::boot_via_fsp(dev, bar, chipset, gsp_falcon, &wpr_meta, &self.libos)?;
> + }
>
> + // Common post-boot initialization
> gsp_falcon.write_os_version(bar, gsp_fw.bootloader.app_version);
>
> // Poll for RISC-V to become active before running sequencer
> @@ -209,18 +267,27 @@ pub(crate) fn boot(
> Delta::from_secs(5),
> )?;
>
> - dev_dbg!(pdev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(bar),);
> + dev_dbg!(dev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(bar));
>
> - // Create and run the GSP sequencer.
> - let seq_params = GspSequencerParams {
> - bootloader_app_version: gsp_fw.bootloader.app_version,
> - libos_dma_handle: libos_handle,
> - gsp_falcon,
> - sec2_falcon,
> - dev: pdev.as_ref().into(),
> - bar,
> - };
> - GspSequencer::run(&self.cmdq, seq_params)?;
> + // For FSP path, send commands after GSP becomes active.
> + if !uses_sec2 {
> + self.cmdq
> + .send_command_no_wait(bar, commands::SetSystemInfo::new(pdev, chipset))?;
> + self.cmdq
> + .send_command_no_wait(bar, commands::SetRegistry::new())?;

Do you know why we need to queue these commands at a different time for
the SEC2 and FSP boot methods? I don't see any reason why we couldn't
pre-queue them as we do for SEC2 here, and doing that would simplify the
flow considerably.