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