xref: /linux/drivers/gpu/nova-core/gsp/commands.rs (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
1edcb1342SAlistair Popple // SPDX-License-Identifier: GPL-2.0
2edcb1342SAlistair Popple 
30e7d572bSAlistair Popple use core::{
40e7d572bSAlistair Popple     array,
50e7d572bSAlistair Popple     convert::Infallible, //
60e7d572bSAlistair Popple };
719b0a6e7SAlistair Popple 
8edcb1342SAlistair Popple use kernel::{
9edcb1342SAlistair Popple     device,
10edcb1342SAlistair Popple     pci,
1119b0a6e7SAlistair Popple     prelude::*,
120e7d572bSAlistair Popple     time::Delta,
130e7d572bSAlistair Popple     transmute::{
140e7d572bSAlistair Popple         AsBytes,
150e7d572bSAlistair Popple         FromBytes, //
160e7d572bSAlistair Popple     }, //
17edcb1342SAlistair Popple };
18edcb1342SAlistair Popple 
1919b0a6e7SAlistair Popple use crate::{
20*13f85988SAlistair Popple     driver::Bar0,
2119b0a6e7SAlistair Popple     gsp::{
220e7d572bSAlistair Popple         cmdq::{
230e7d572bSAlistair Popple             Cmdq,
240e7d572bSAlistair Popple             CommandToGsp,
250e7d572bSAlistair Popple             MessageFromGsp, //
260e7d572bSAlistair Popple         },
27edcb1342SAlistair Popple         fw::{
2819b0a6e7SAlistair Popple             commands::*,
29edcb1342SAlistair Popple             MsgFunction, //
30edcb1342SAlistair Popple         },
3119b0a6e7SAlistair Popple     },
3219b0a6e7SAlistair Popple     sbuffer::SBufferIter,
33*13f85988SAlistair Popple     util,
34edcb1342SAlistair Popple };
35edcb1342SAlistair Popple 
36edcb1342SAlistair Popple /// The `GspSetSystemInfo` command.
37edcb1342SAlistair Popple pub(crate) struct SetSystemInfo<'a> {
38edcb1342SAlistair Popple     pdev: &'a pci::Device<device::Bound>,
39edcb1342SAlistair Popple }
40edcb1342SAlistair Popple 
41edcb1342SAlistair Popple impl<'a> SetSystemInfo<'a> {
42edcb1342SAlistair Popple     /// Creates a new `GspSetSystemInfo` command using the parameters of `pdev`.
43edcb1342SAlistair Popple     pub(crate) fn new(pdev: &'a pci::Device<device::Bound>) -> Self {
44edcb1342SAlistair Popple         Self { pdev }
45edcb1342SAlistair Popple     }
46edcb1342SAlistair Popple }
47edcb1342SAlistair Popple 
48edcb1342SAlistair Popple impl<'a> CommandToGsp for SetSystemInfo<'a> {
49edcb1342SAlistair Popple     const FUNCTION: MsgFunction = MsgFunction::GspSetSystemInfo;
50edcb1342SAlistair Popple     type Command = GspSetSystemInfo;
51edcb1342SAlistair Popple     type InitError = Error;
52edcb1342SAlistair Popple 
53edcb1342SAlistair Popple     fn init(&self) -> impl Init<Self::Command, Self::InitError> {
54edcb1342SAlistair Popple         GspSetSystemInfo::init(self.pdev)
55edcb1342SAlistair Popple     }
56edcb1342SAlistair Popple }
5719b0a6e7SAlistair Popple 
5819b0a6e7SAlistair Popple struct RegistryEntry {
5919b0a6e7SAlistair Popple     key: &'static str,
6019b0a6e7SAlistair Popple     value: u32,
6119b0a6e7SAlistair Popple }
6219b0a6e7SAlistair Popple 
6319b0a6e7SAlistair Popple /// The `SetRegistry` command.
6419b0a6e7SAlistair Popple pub(crate) struct SetRegistry {
6519b0a6e7SAlistair Popple     entries: [RegistryEntry; Self::NUM_ENTRIES],
6619b0a6e7SAlistair Popple }
6719b0a6e7SAlistair Popple 
6819b0a6e7SAlistair Popple impl SetRegistry {
6919b0a6e7SAlistair Popple     // For now we hard-code the registry entries. Future work will allow others to
7019b0a6e7SAlistair Popple     // be added as module parameters.
7119b0a6e7SAlistair Popple     const NUM_ENTRIES: usize = 3;
7219b0a6e7SAlistair Popple 
7319b0a6e7SAlistair Popple     /// Creates a new `SetRegistry` command, using a set of hardcoded entries.
7419b0a6e7SAlistair Popple     pub(crate) fn new() -> Self {
7519b0a6e7SAlistair Popple         Self {
7619b0a6e7SAlistair Popple             entries: [
7719b0a6e7SAlistair Popple                 // RMSecBusResetEnable - enables PCI secondary bus reset
7819b0a6e7SAlistair Popple                 RegistryEntry {
7919b0a6e7SAlistair Popple                     key: "RMSecBusResetEnable",
8019b0a6e7SAlistair Popple                     value: 1,
8119b0a6e7SAlistair Popple                 },
8219b0a6e7SAlistair Popple                 // RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration registers on
8319b0a6e7SAlistair Popple                 // any PCI reset.
8419b0a6e7SAlistair Popple                 RegistryEntry {
8519b0a6e7SAlistair Popple                     key: "RMForcePcieConfigSave",
8619b0a6e7SAlistair Popple                     value: 1,
8719b0a6e7SAlistair Popple                 },
8819b0a6e7SAlistair Popple                 // RMDevidCheckIgnore - allows GSP-RM to boot even if the PCI dev ID is not found
8919b0a6e7SAlistair Popple                 // in the internal product name database.
9019b0a6e7SAlistair Popple                 RegistryEntry {
9119b0a6e7SAlistair Popple                     key: "RMDevidCheckIgnore",
9219b0a6e7SAlistair Popple                     value: 1,
9319b0a6e7SAlistair Popple                 },
9419b0a6e7SAlistair Popple             ],
9519b0a6e7SAlistair Popple         }
9619b0a6e7SAlistair Popple     }
9719b0a6e7SAlistair Popple }
9819b0a6e7SAlistair Popple 
9919b0a6e7SAlistair Popple impl CommandToGsp for SetRegistry {
10019b0a6e7SAlistair Popple     const FUNCTION: MsgFunction = MsgFunction::SetRegistry;
10119b0a6e7SAlistair Popple     type Command = PackedRegistryTable;
10219b0a6e7SAlistair Popple     type InitError = Infallible;
10319b0a6e7SAlistair Popple 
10419b0a6e7SAlistair Popple     fn init(&self) -> impl Init<Self::Command, Self::InitError> {
10519b0a6e7SAlistair Popple         PackedRegistryTable::init(Self::NUM_ENTRIES as u32, self.variable_payload_len() as u32)
10619b0a6e7SAlistair Popple     }
10719b0a6e7SAlistair Popple 
10819b0a6e7SAlistair Popple     fn variable_payload_len(&self) -> usize {
10919b0a6e7SAlistair Popple         let mut key_size = 0;
11019b0a6e7SAlistair Popple         for i in 0..Self::NUM_ENTRIES {
11119b0a6e7SAlistair Popple             key_size += self.entries[i].key.len() + 1; // +1 for NULL terminator
11219b0a6e7SAlistair Popple         }
11319b0a6e7SAlistair Popple         Self::NUM_ENTRIES * size_of::<PackedRegistryEntry>() + key_size
11419b0a6e7SAlistair Popple     }
11519b0a6e7SAlistair Popple 
11619b0a6e7SAlistair Popple     fn init_variable_payload(
11719b0a6e7SAlistair Popple         &self,
11819b0a6e7SAlistair Popple         dst: &mut SBufferIter<core::array::IntoIter<&mut [u8], 2>>,
11919b0a6e7SAlistair Popple     ) -> Result {
12019b0a6e7SAlistair Popple         let string_data_start_offset =
12119b0a6e7SAlistair Popple             size_of::<PackedRegistryTable>() + Self::NUM_ENTRIES * size_of::<PackedRegistryEntry>();
12219b0a6e7SAlistair Popple 
12319b0a6e7SAlistair Popple         // Array for string data.
12419b0a6e7SAlistair Popple         let mut string_data = KVec::new();
12519b0a6e7SAlistair Popple 
12619b0a6e7SAlistair Popple         for entry in self.entries.iter().take(Self::NUM_ENTRIES) {
12719b0a6e7SAlistair Popple             dst.write_all(
12819b0a6e7SAlistair Popple                 PackedRegistryEntry::new(
12919b0a6e7SAlistair Popple                     (string_data_start_offset + string_data.len()) as u32,
13019b0a6e7SAlistair Popple                     entry.value,
13119b0a6e7SAlistair Popple                 )
13219b0a6e7SAlistair Popple                 .as_bytes(),
13319b0a6e7SAlistair Popple             )?;
13419b0a6e7SAlistair Popple 
13519b0a6e7SAlistair Popple             let key_bytes = entry.key.as_bytes();
13619b0a6e7SAlistair Popple             string_data.extend_from_slice(key_bytes, GFP_KERNEL)?;
13719b0a6e7SAlistair Popple             string_data.push(0, GFP_KERNEL)?;
13819b0a6e7SAlistair Popple         }
13919b0a6e7SAlistair Popple 
14019b0a6e7SAlistair Popple         dst.write_all(string_data.as_slice())
14119b0a6e7SAlistair Popple     }
14219b0a6e7SAlistair Popple }
1430e7d572bSAlistair Popple 
1440e7d572bSAlistair Popple /// Message type for GSP initialization done notification.
1450e7d572bSAlistair Popple struct GspInitDone {}
1460e7d572bSAlistair Popple 
1470e7d572bSAlistair Popple // SAFETY: `GspInitDone` is a zero-sized type with no bytes, therefore it
1480e7d572bSAlistair Popple // trivially has no uninitialized bytes.
1490e7d572bSAlistair Popple unsafe impl FromBytes for GspInitDone {}
1500e7d572bSAlistair Popple 
1510e7d572bSAlistair Popple impl MessageFromGsp for GspInitDone {
1520e7d572bSAlistair Popple     const FUNCTION: MsgFunction = MsgFunction::GspInitDone;
1530e7d572bSAlistair Popple     type InitError = Infallible;
1540e7d572bSAlistair Popple     type Message = GspInitDone;
1550e7d572bSAlistair Popple 
1560e7d572bSAlistair Popple     fn read(
1570e7d572bSAlistair Popple         _msg: &Self::Message,
1580e7d572bSAlistair Popple         _sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,
1590e7d572bSAlistair Popple     ) -> Result<Self, Self::InitError> {
1600e7d572bSAlistair Popple         Ok(GspInitDone {})
1610e7d572bSAlistair Popple     }
1620e7d572bSAlistair Popple }
1630e7d572bSAlistair Popple 
1640e7d572bSAlistair Popple /// Waits for GSP initialization to complete.
1650e7d572bSAlistair Popple pub(crate) fn wait_gsp_init_done(cmdq: &mut Cmdq) -> Result {
1660e7d572bSAlistair Popple     loop {
1670e7d572bSAlistair Popple         match cmdq.receive_msg::<GspInitDone>(Delta::from_secs(10)) {
1680e7d572bSAlistair Popple             Ok(_) => break Ok(()),
1690e7d572bSAlistair Popple             Err(ERANGE) => continue,
1700e7d572bSAlistair Popple             Err(e) => break Err(e),
1710e7d572bSAlistair Popple         }
1720e7d572bSAlistair Popple     }
1730e7d572bSAlistair Popple }
174*13f85988SAlistair Popple 
175*13f85988SAlistair Popple /// The `GetGspStaticInfo` command.
176*13f85988SAlistair Popple struct GetGspStaticInfo;
177*13f85988SAlistair Popple 
178*13f85988SAlistair Popple impl CommandToGsp for GetGspStaticInfo {
179*13f85988SAlistair Popple     const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
180*13f85988SAlistair Popple     type Command = GspStaticConfigInfo;
181*13f85988SAlistair Popple     type InitError = Infallible;
182*13f85988SAlistair Popple 
183*13f85988SAlistair Popple     fn init(&self) -> impl Init<Self::Command, Self::InitError> {
184*13f85988SAlistair Popple         GspStaticConfigInfo::init_zeroed()
185*13f85988SAlistair Popple     }
186*13f85988SAlistair Popple }
187*13f85988SAlistair Popple 
188*13f85988SAlistair Popple /// The reply from the GSP to the [`GetGspInfo`] command.
189*13f85988SAlistair Popple pub(crate) struct GetGspStaticInfoReply {
190*13f85988SAlistair Popple     gpu_name: [u8; 64],
191*13f85988SAlistair Popple }
192*13f85988SAlistair Popple 
193*13f85988SAlistair Popple impl MessageFromGsp for GetGspStaticInfoReply {
194*13f85988SAlistair Popple     const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
195*13f85988SAlistair Popple     type Message = GspStaticConfigInfo;
196*13f85988SAlistair Popple     type InitError = Infallible;
197*13f85988SAlistair Popple 
198*13f85988SAlistair Popple     fn read(
199*13f85988SAlistair Popple         msg: &Self::Message,
200*13f85988SAlistair Popple         _sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,
201*13f85988SAlistair Popple     ) -> Result<Self, Self::InitError> {
202*13f85988SAlistair Popple         Ok(GetGspStaticInfoReply {
203*13f85988SAlistair Popple             gpu_name: msg.gpu_name_str(),
204*13f85988SAlistair Popple         })
205*13f85988SAlistair Popple     }
206*13f85988SAlistair Popple }
207*13f85988SAlistair Popple 
208*13f85988SAlistair Popple impl GetGspStaticInfoReply {
209*13f85988SAlistair Popple     /// Returns the name of the GPU as a string, or `None` if the string given by the GSP was
210*13f85988SAlistair Popple     /// invalid.
211*13f85988SAlistair Popple     pub(crate) fn gpu_name(&self) -> Option<&str> {
212*13f85988SAlistair Popple         util::str_from_null_terminated(&self.gpu_name)
213*13f85988SAlistair Popple     }
214*13f85988SAlistair Popple }
215*13f85988SAlistair Popple 
216*13f85988SAlistair Popple /// Send the [`GetGspInfo`] command and awaits for its reply.
217*13f85988SAlistair Popple pub(crate) fn get_gsp_info(cmdq: &mut Cmdq, bar: &Bar0) -> Result<GetGspStaticInfoReply> {
218*13f85988SAlistair Popple     cmdq.send_command(bar, GetGspStaticInfo)?;
219*13f85988SAlistair Popple 
220*13f85988SAlistair Popple     loop {
221*13f85988SAlistair Popple         match cmdq.receive_msg::<GetGspStaticInfoReply>(Delta::from_secs(5)) {
222*13f85988SAlistair Popple             Ok(info) => return Ok(info),
223*13f85988SAlistair Popple             Err(ERANGE) => continue,
224*13f85988SAlistair Popple             Err(e) => return Err(e),
225*13f85988SAlistair Popple         }
226*13f85988SAlistair Popple     }
227*13f85988SAlistair Popple }
228