Path: blob/master/drivers/gpu/nova-core/gsp/commands.rs
122941 views
// SPDX-License-Identifier: GPL-2.012use core::{3array,4convert::Infallible,5ffi::FromBytesUntilNulError,6str::Utf8Error, //7};89use kernel::{10device,11pci,12prelude::*,13time::Delta,14transmute::{15AsBytes,16FromBytes, //17}, //18};1920use crate::{21driver::Bar0,22gsp::{23cmdq::{24Cmdq,25CommandToGsp,26MessageFromGsp, //27},28fw::{29commands::*,30MsgFunction, //31},32},33sbuffer::SBufferIter,34};3536/// The `GspSetSystemInfo` command.37pub(crate) struct SetSystemInfo<'a> {38pdev: &'a pci::Device<device::Bound>,39}4041impl<'a> SetSystemInfo<'a> {42/// Creates a new `GspSetSystemInfo` command using the parameters of `pdev`.43pub(crate) fn new(pdev: &'a pci::Device<device::Bound>) -> Self {44Self { pdev }45}46}4748impl<'a> CommandToGsp for SetSystemInfo<'a> {49const FUNCTION: MsgFunction = MsgFunction::GspSetSystemInfo;50type Command = GspSetSystemInfo;51type InitError = Error;5253fn init(&self) -> impl Init<Self::Command, Self::InitError> {54GspSetSystemInfo::init(self.pdev)55}56}5758struct RegistryEntry {59key: &'static str,60value: u32,61}6263/// The `SetRegistry` command.64pub(crate) struct SetRegistry {65entries: [RegistryEntry; Self::NUM_ENTRIES],66}6768impl SetRegistry {69// For now we hard-code the registry entries. Future work will allow others to70// be added as module parameters.71const NUM_ENTRIES: usize = 3;7273/// Creates a new `SetRegistry` command, using a set of hardcoded entries.74pub(crate) fn new() -> Self {75Self {76entries: [77// RMSecBusResetEnable - enables PCI secondary bus reset78RegistryEntry {79key: "RMSecBusResetEnable",80value: 1,81},82// RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration registers on83// any PCI reset.84RegistryEntry {85key: "RMForcePcieConfigSave",86value: 1,87},88// RMDevidCheckIgnore - allows GSP-RM to boot even if the PCI dev ID is not found89// in the internal product name database.90RegistryEntry {91key: "RMDevidCheckIgnore",92value: 1,93},94],95}96}97}9899impl CommandToGsp for SetRegistry {100const FUNCTION: MsgFunction = MsgFunction::SetRegistry;101type Command = PackedRegistryTable;102type InitError = Infallible;103104fn init(&self) -> impl Init<Self::Command, Self::InitError> {105PackedRegistryTable::init(Self::NUM_ENTRIES as u32, self.variable_payload_len() as u32)106}107108fn variable_payload_len(&self) -> usize {109let mut key_size = 0;110for i in 0..Self::NUM_ENTRIES {111key_size += self.entries[i].key.len() + 1; // +1 for NULL terminator112}113Self::NUM_ENTRIES * size_of::<PackedRegistryEntry>() + key_size114}115116fn init_variable_payload(117&self,118dst: &mut SBufferIter<core::array::IntoIter<&mut [u8], 2>>,119) -> Result {120let string_data_start_offset =121size_of::<PackedRegistryTable>() + Self::NUM_ENTRIES * size_of::<PackedRegistryEntry>();122123// Array for string data.124let mut string_data = KVec::new();125126for entry in self.entries.iter().take(Self::NUM_ENTRIES) {127dst.write_all(128PackedRegistryEntry::new(129(string_data_start_offset + string_data.len()) as u32,130entry.value,131)132.as_bytes(),133)?;134135let key_bytes = entry.key.as_bytes();136string_data.extend_from_slice(key_bytes, GFP_KERNEL)?;137string_data.push(0, GFP_KERNEL)?;138}139140dst.write_all(string_data.as_slice())141}142}143144/// Message type for GSP initialization done notification.145struct GspInitDone;146147// SAFETY: `GspInitDone` is a zero-sized type with no bytes, therefore it148// trivially has no uninitialized bytes.149unsafe impl FromBytes for GspInitDone {}150151impl MessageFromGsp for GspInitDone {152const FUNCTION: MsgFunction = MsgFunction::GspInitDone;153type InitError = Infallible;154type Message = ();155156fn read(157_msg: &Self::Message,158_sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,159) -> Result<Self, Self::InitError> {160Ok(GspInitDone)161}162}163164/// Waits for GSP initialization to complete.165pub(crate) fn wait_gsp_init_done(cmdq: &mut Cmdq) -> Result {166loop {167match cmdq.receive_msg::<GspInitDone>(Delta::from_secs(10)) {168Ok(_) => break Ok(()),169Err(ERANGE) => continue,170Err(e) => break Err(e),171}172}173}174175/// The `GetGspStaticInfo` command.176struct GetGspStaticInfo;177178impl CommandToGsp for GetGspStaticInfo {179const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;180type Command = GspStaticConfigInfo;181type InitError = Infallible;182183fn init(&self) -> impl Init<Self::Command, Self::InitError> {184GspStaticConfigInfo::init_zeroed()185}186}187188/// The reply from the GSP to the [`GetGspInfo`] command.189pub(crate) struct GetGspStaticInfoReply {190gpu_name: [u8; 64],191}192193impl MessageFromGsp for GetGspStaticInfoReply {194const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;195type Message = GspStaticConfigInfo;196type InitError = Infallible;197198fn read(199msg: &Self::Message,200_sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,201) -> Result<Self, Self::InitError> {202Ok(GetGspStaticInfoReply {203gpu_name: msg.gpu_name_str(),204})205}206}207208/// Error type for [`GetGspStaticInfoReply::gpu_name`].209#[derive(Debug)]210pub(crate) enum GpuNameError {211/// The GPU name string does not contain a null terminator.212NoNullTerminator(FromBytesUntilNulError),213214/// The GPU name string contains invalid UTF-8.215#[expect(dead_code)]216InvalidUtf8(Utf8Error),217}218219impl GetGspStaticInfoReply {220/// Returns the name of the GPU as a string.221///222/// Returns an error if the string given by the GSP does not contain a null terminator or223/// contains invalid UTF-8.224pub(crate) fn gpu_name(&self) -> core::result::Result<&str, GpuNameError> {225CStr::from_bytes_until_nul(&self.gpu_name)226.map_err(GpuNameError::NoNullTerminator)?227.to_str()228.map_err(GpuNameError::InvalidUtf8)229}230}231232/// Send the [`GetGspInfo`] command and awaits for its reply.233pub(crate) fn get_gsp_info(cmdq: &mut Cmdq, bar: &Bar0) -> Result<GetGspStaticInfoReply> {234cmdq.send_command(bar, GetGspStaticInfo)?;235236loop {237match cmdq.receive_msg::<GetGspStaticInfoReply>(Delta::from_secs(5)) {238Ok(info) => return Ok(info),239Err(ERANGE) => continue,240Err(e) => return Err(e),241}242}243}244245246