1 // SPDX-License-Identifier: GPL-2.0 2 // SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 4 use kernel::{ 5 bits, 6 device, 7 dma::Coherent, 8 io::poll::read_poll_timeout, 9 prelude::*, 10 time::Delta, 11 types::ScopeGuard, // 12 }; 13 14 use crate::{ 15 driver::Bar0, 16 falcon::{ 17 gsp::Gsp, 18 sec2::Sec2, 19 Falcon, // 20 }, 21 fb::FbLayout, 22 firmware::{ 23 gsp::GspFirmware, 24 FIRMWARE_VERSION, // 25 }, 26 gsp::{ 27 cmdq::Cmdq, 28 commands, 29 GspFwWprMeta, // 30 }, 31 }; 32 33 impl super::Gsp { 34 /// Attempt to boot the GSP. 35 /// 36 /// This is a GPU-dependent and complex procedure that involves loading firmware files from 37 /// user-space, patching them with signatures, and building firmware-specific intricate data 38 /// structures that the GSP will use at runtime. 39 /// 40 /// Upon return, the GSP is up and running, and its unload bundle (to be given as argument to 41 /// [`Self::unload`]) returned. 42 pub(crate) fn boot( 43 self: Pin<&mut Self>, 44 ctx: super::GspBootContext<'_>, 45 ) -> Result<Option<super::UnloadBundle>> { 46 let pdev = ctx.pdev; 47 let bar = ctx.bar; 48 let chipset = ctx.chipset; 49 let gsp_falcon = ctx.gsp_falcon; 50 let sec2_falcon = ctx.sec2_falcon; 51 let dev = pdev.as_ref(); 52 let hal = super::hal::gsp_hal(chipset); 53 54 let gsp_fw = KBox::pin_init(GspFirmware::new(dev, chipset, FIRMWARE_VERSION), GFP_KERNEL)?; 55 56 let fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?; 57 dev_dbg!(dev, "{:#x?}\n", fb_layout); 58 59 let wpr_meta = Coherent::init(dev, GFP_KERNEL, GspFwWprMeta::new(&gsp_fw, &fb_layout))?; 60 61 // Perform the chipset-specific boot sequence, and retrieve the unload bundle. 62 let unload_bundle = hal.boot(&self, &ctx, &fb_layout, &wpr_meta)?; 63 64 let unload_guard = ScopeGuard::new_with_data(unload_bundle, |unload_bundle| { 65 let _ = self.unload(dev, bar, gsp_falcon, sec2_falcon, unload_bundle); 66 }); 67 68 gsp_falcon.write_os_version(gsp_fw.bootloader.app_version); 69 70 // Poll for RISC-V to become active before continuing. 71 read_poll_timeout( 72 || Ok(gsp_falcon.is_riscv_active()), 73 |val: &bool| *val, 74 Delta::from_millis(10), 75 Delta::from_secs(5), 76 )?; 77 78 dev_dbg!(pdev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(),); 79 80 self.cmdq 81 .send_command_no_wait(bar, commands::SetSystemInfo::new(pdev, chipset))?; 82 self.cmdq 83 .send_command_no_wait(bar, commands::SetRegistry::new()?)?; 84 85 hal.post_boot(&self, &ctx, &gsp_fw)?; 86 87 // Wait until GSP is fully initialized. 88 commands::wait_gsp_init_done(&self.cmdq)?; 89 90 Ok(unload_guard.dismiss()) 91 } 92 93 /// Shut down the GSP and wait until it is offline. 94 fn shutdown_gsp( 95 cmdq: &Cmdq, 96 bar: Bar0<'_>, 97 gsp_falcon: &Falcon<'_, Gsp>, 98 mode: commands::PowerStateLevel, 99 ) -> Result { 100 // Command to shut the GSP down. 101 cmdq.send_command(bar, commands::UnloadingGuestDriver::new(mode))?; 102 103 // Wait until GSP signals it is suspended. 104 const LIBOS_INTERRUPT_PROCESSOR_SUSPENDED: u32 = bits::bit_u32(31); 105 read_poll_timeout( 106 || Ok(gsp_falcon.read_mailbox0()), 107 |&mb0| mb0 & LIBOS_INTERRUPT_PROCESSOR_SUSPENDED != 0, 108 Delta::from_millis(10), 109 Delta::from_secs(5), 110 ) 111 .map(|_| ()) 112 } 113 114 /// Attempts to unload the GSP firmware. 115 /// 116 /// This stops all activity on the GSP. 117 pub(crate) fn unload( 118 &self, 119 dev: &device::Device<device::Bound>, 120 bar: Bar0<'_>, 121 gsp_falcon: &Falcon<'_, Gsp>, 122 sec2_falcon: &Falcon<'_, Sec2>, 123 unload_bundle: Option<super::UnloadBundle>, 124 ) -> Result { 125 // Shut down the GSP. Keep going even in case of error. 126 let mut res = Self::shutdown_gsp( 127 &self.cmdq, 128 bar, 129 gsp_falcon, 130 commands::PowerStateLevel::Level0, 131 ) 132 .inspect_err(|e| dev_err!(dev, "GSP shutdown failed: {:?}\n", e)); 133 134 // Run the unload bundle to reset the GSP so it can be booted again. 135 if let Some(unload_bundle) = unload_bundle { 136 res = res.and( 137 unload_bundle 138 .0 139 .run(dev, bar, gsp_falcon, sec2_falcon) 140 .inspect_err(|e| dev_err!(dev, "Unload bundle failed: {:?}\n", e)), 141 ); 142 } else { 143 dev_warn!( 144 dev, 145 "Unload bundle is missing, GSP won't be properly reset.\n" 146 ); 147 148 res = Err(EAGAIN); 149 } 150 151 res.inspect(|()| dev_info!(dev, "GSP successfully unloaded\n")) 152 } 153 } 154