diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs index d62bab07e861..0845d0906ca1 100644 --- a/drivers/gpu/nova-core/gsp/boot.rs +++ b/drivers/gpu/nova-core/gsp/boot.rs @@ -236,6 +236,9 @@ pub(crate) fn boot( }; GspSequencer::run(&mut self.cmdq, seq_params)?; + // Wait until GSP is fully initialized. + commands::wait_gsp_init_done(&mut self.cmdq)?; + Ok(()) } } diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs index d5be3bf10684..b544603703d3 100644 --- a/drivers/gpu/nova-core/gsp/commands.rs +++ b/drivers/gpu/nova-core/gsp/commands.rs @@ -1,17 +1,28 @@ // SPDX-License-Identifier: GPL-2.0 -use core::convert::Infallible; +use core::{ + array, + convert::Infallible, // +}; use kernel::{ device, pci, prelude::*, - transmute::AsBytes, // + time::Delta, + transmute::{ + AsBytes, + FromBytes, // + }, // }; use crate::{ gsp::{ - cmdq::CommandToGsp, + cmdq::{ + Cmdq, + CommandToGsp, + MessageFromGsp, // + }, fw::{ commands::*, MsgFunction, // @@ -127,3 +138,34 @@ fn init_variable_payload( dst.write_all(string_data.as_slice()) } } + +/// Message type for GSP initialization done notification. +struct GspInitDone {} + +// SAFETY: `GspInitDone` is a zero-sized type with no bytes, therefore it +// trivially has no uninitialized bytes. +unsafe impl FromBytes for GspInitDone {} + +impl MessageFromGsp for GspInitDone { + const FUNCTION: MsgFunction = MsgFunction::GspInitDone; + type InitError = Infallible; + type Message = GspInitDone; + + fn read( + _msg: &Self::Message, + _sbuffer: &mut SBufferIter>, + ) -> Result { + Ok(GspInitDone {}) + } +} + +/// Waits for GSP initialization to complete. +pub(crate) fn wait_gsp_init_done(cmdq: &mut Cmdq) -> Result { + loop { + match cmdq.receive_msg::(Delta::from_secs(10)) { + Ok(_) => break Ok(()), + Err(ERANGE) => continue, + Err(e) => break Err(e), + } + } +}