@@ -184,6 +184,85 @@ impl PinnedDrop for Gpu {
184184}
185185
186186impl Gpu {
187+ /// Helper function to load and run the FWSEC-FRTS firmware and confirm that it has properly
188+ /// created the WPR2 region.
189+ ///
190+ /// TODO: this needs to be moved into a larger type responsible for booting the whole GSP
191+ /// (`GspBooter`?).
192+ fn run_fwsec_frts (
193+ dev : & device:: Device < device:: Bound > ,
194+ falcon : & Falcon < Gsp > ,
195+ bar : & Bar0 ,
196+ bios : & Vbios ,
197+ fb_layout : & FbLayout ,
198+ ) -> Result < ( ) > {
199+ // Check that the WPR2 region does not already exists - if it does, we cannot run
200+ // FWSEC-FRTS until the GPU is reset.
201+ if regs:: NV_PFB_PRI_MMU_WPR2_ADDR_HI :: read ( bar) . higher_bound ( ) != 0 {
202+ dev_err ! (
203+ dev,
204+ "WPR2 region already exists - GPU needs to be reset to proceed\n "
205+ ) ;
206+ return Err ( EBUSY ) ;
207+ }
208+
209+ let fwsec_frts = FwsecFirmware :: new (
210+ dev,
211+ falcon,
212+ bar,
213+ bios,
214+ FwsecCommand :: Frts {
215+ frts_addr : fb_layout. frts . start ,
216+ frts_size : fb_layout. frts . end - fb_layout. frts . start ,
217+ } ,
218+ ) ?;
219+
220+ // Run FWSEC-FRTS to create the WPR2 region.
221+ fwsec_frts. run ( dev, falcon, bar) ?;
222+
223+ // SCRATCH_E contains the error code for FWSEC-FRTS.
224+ let frts_status = regs:: NV_PBUS_SW_SCRATCH_0E :: read ( bar) . frts_err_code ( ) ;
225+ if frts_status != 0 {
226+ dev_err ! (
227+ dev,
228+ "FWSEC-FRTS returned with error code {:#x}" ,
229+ frts_status
230+ ) ;
231+
232+ return Err ( EIO ) ;
233+ }
234+
235+ // Check that the WPR2 region has been created as we requested.
236+ let ( wpr2_lo, wpr2_hi) = (
237+ regs:: NV_PFB_PRI_MMU_WPR2_ADDR_LO :: read ( bar) . lower_bound ( ) ,
238+ regs:: NV_PFB_PRI_MMU_WPR2_ADDR_HI :: read ( bar) . higher_bound ( ) ,
239+ ) ;
240+
241+ match ( wpr2_lo, wpr2_hi) {
242+ ( _, 0 ) => {
243+ dev_err ! ( dev, "WPR2 region not created after running FWSEC-FRTS\n " ) ;
244+
245+ Err ( EIO )
246+ }
247+ ( wpr2_lo, _) if wpr2_lo != fb_layout. frts . start => {
248+ dev_err ! (
249+ dev,
250+ "WPR2 region created at unexpected address {:#x}; expected {:#x}\n " ,
251+ wpr2_lo,
252+ fb_layout. frts. start,
253+ ) ;
254+
255+ Err ( EIO )
256+ }
257+ ( wpr2_lo, wpr2_hi) => {
258+ dev_dbg ! ( dev, "WPR2: {:#x}-{:#x}\n " , wpr2_lo, wpr2_hi) ;
259+ dev_dbg ! ( dev, "GPU instance built\n " ) ;
260+
261+ Ok ( ( ) )
262+ }
263+ }
264+ }
265+
187266 pub ( crate ) fn new (
188267 pdev : & pci:: Device < device:: Bound > ,
189268 devres_bar : Devres < Bar0 > ,
@@ -222,16 +301,7 @@ impl Gpu {
222301
223302 let bios = Vbios :: new ( pdev, bar) ?;
224303
225- let _fwsec_frts = FwsecFirmware :: new (
226- pdev. as_ref ( ) ,
227- & gsp_falcon,
228- bar,
229- & bios,
230- FwsecCommand :: Frts {
231- frts_addr : fb_layout. frts . start ,
232- frts_size : fb_layout. frts . end - fb_layout. frts . start ,
233- } ,
234- ) ?;
304+ Self :: run_fwsec_frts ( pdev. as_ref ( ) , & gsp_falcon, bar, & bios, & fb_layout) ?;
235305
236306 Ok ( pin_init ! ( Self {
237307 spec,
0 commit comments