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