Add `RmControl` which implements CommandToGsp for sending RM control RPCs. Add `RmControlReply` which implements MessageFromGsp for getting the reply back.
Add `send_rm_control` which sends an RM control RPC via the command queue using the above structures. This gives a generic way to send each RM control RPC. Each new RM control RPC can be added by extending RmControlMsgFunction and adding its bindings wrappers and writing a helper function to send it via `send_rm_control`. Signed-off-by: Eliot Courtney <[email protected]> --- drivers/gpu/nova-core/gsp.rs | 1 + drivers/gpu/nova-core/gsp/rm.rs | 3 + drivers/gpu/nova-core/gsp/rm/commands.rs | 111 +++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs index a6f3918c20b1..1a1c4e9808ac 100644 --- a/drivers/gpu/nova-core/gsp.rs +++ b/drivers/gpu/nova-core/gsp.rs @@ -17,6 +17,7 @@ pub(crate) mod cmdq; pub(crate) mod commands; mod fw; +pub(crate) mod rm; mod sequencer; pub(crate) use fw::{ diff --git a/drivers/gpu/nova-core/gsp/rm.rs b/drivers/gpu/nova-core/gsp/rm.rs new file mode 100644 index 000000000000..10e879a3e842 --- /dev/null +++ b/drivers/gpu/nova-core/gsp/rm.rs @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: GPL-2.0 + +pub(crate) mod commands; diff --git a/drivers/gpu/nova-core/gsp/rm/commands.rs b/drivers/gpu/nova-core/gsp/rm/commands.rs new file mode 100644 index 000000000000..16bcf88644db --- /dev/null +++ b/drivers/gpu/nova-core/gsp/rm/commands.rs @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 + +use core::{ + array, + convert::Infallible, // +}; + +use kernel::prelude::*; + +use crate::{ + driver::Bar0, + gsp::{ + cmdq::{ + Cmdq, + CommandToGsp, + MessageFromGsp, // + }, + fw::{ + rm::*, + MsgFunction, + NvStatus, // + }, + }, + sbuffer::SBufferIter, +}; + +/// Command for sending an RM control message to the GSP. +struct RmControl<'a> { + h_client: u32, + h_object: u32, + cmd: RmControlMsgFunction, + params: &'a [u8], +} + +impl<'a> RmControl<'a> { + /// Creates a new RM control command. + fn new(h_client: u32, h_object: u32, cmd: RmControlMsgFunction, params: &'a [u8]) -> Self { + Self { + h_client, + h_object, + cmd, + params, + } + } +} + +impl CommandToGsp for RmControl<'_> { + const FUNCTION: MsgFunction = MsgFunction::GspRmControl; + type Command = GspRmControl; + type Reply = RmControlReply; + type InitError = Infallible; + + fn init(&self) -> impl Init<Self::Command, Self::InitError> { + GspRmControl::new( + self.h_client, + self.h_object, + self.cmd, + self.params.len() as u32, + ) + } + + fn variable_payload_len(&self) -> usize { + self.params.len() + } + + fn init_variable_payload( + &self, + dst: &mut SBufferIter<array::IntoIter<&mut [u8], 2>>, + ) -> Result { + dst.write_all(self.params) + } +} + +/// Response from an RM control message. +pub(crate) struct RmControlReply { + status: NvStatus, + params: KVVec<u8>, +} + +impl MessageFromGsp for RmControlReply { + const FUNCTION: MsgFunction = MsgFunction::GspRmControl; + type Message = GspRmControl; + type InitError = Error; + + fn read( + msg: &Self::Message, + sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>, + ) -> Result<Self, Self::InitError> { + Ok(RmControlReply { + status: msg.status(), + params: sbuffer.flush_into_kvvec(GFP_KERNEL)?, + }) + } +} + +/// Sends an RM control command, checks the reply status, and returns the raw parameter bytes. +#[expect(dead_code)] +fn send_rm_control( + cmdq: &Cmdq, + bar: &Bar0, + h_client: u32, + h_object: u32, + cmd: RmControlMsgFunction, + params: &[u8], +) -> Result<KVVec<u8>> { + let reply = cmdq.send_sync_command(bar, RmControl::new(h_client, h_object, cmd, params))?; + + Result::from(reply.status)?; + + Ok(reply.params) +} -- 2.53.0
