Add `RawRmControl` which implements CommandToGsp for sending RM control RPCs. Add `RmControlReply` which implements MessageFromGsp for getting the reply back. Add the `RmControlCommand` trait for defining an RM control message.
Add `RmControl` 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, adding its bindings wrappers and writing an implementation of `RmControlCommand` that can be sent using `RmControl`. Signed-off-by: Eliot Courtney <[email protected]> --- drivers/gpu/nova-core/gsp.rs | 1 + drivers/gpu/nova-core/gsp/fw/rm.rs | 1 - drivers/gpu/nova-core/gsp/rm.rs | 3 + drivers/gpu/nova-core/gsp/rm/commands.rs | 141 +++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs index 04e3976127cc..09d6e673aa65 100644 --- a/drivers/gpu/nova-core/gsp.rs +++ b/drivers/gpu/nova-core/gsp.rs @@ -21,6 +21,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/fw/rm.rs b/drivers/gpu/nova-core/gsp/fw/rm.rs index 4a4f97d88ecf..1c6e8b4c4865 100644 --- a/drivers/gpu/nova-core/gsp/fw/rm.rs +++ b/drivers/gpu/nova-core/gsp/fw/rm.rs @@ -53,7 +53,6 @@ pub(crate) struct GspRmControl { inner: bindings::rpc_gsp_rm_control_v03_00, } -#[expect(dead_code)] impl GspRmControl { /// Creates a new RM control command. pub(crate) fn new<T>( 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..8845ca0a0225 --- /dev/null +++ b/drivers/gpu/nova-core/gsp/rm/commands.rs @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 + +use core::array; + +use kernel::prelude::*; + +use crate::{ + driver::Bar0, + gsp::{ + cmdq::{ + Cmdq, + CommandToGsp, + MessageFromGsp, // + }, + commands::{ + Client, + Handle, // + }, + fw::{ + rm::*, + MsgFunction, + NvStatus, // + }, + }, + sbuffer::SBufferIter, // +}; + +/// Wraps a [`RmControl`] command to provide the infrastructure for sending it on the command queue. +struct RawRmControl<'a, T>(&'a RmControl<T>) +where + T: RmControlCommand; + +impl<'a, T: RmControlCommand> CommandToGsp for RawRmControl<'a, T> { + const FUNCTION: MsgFunction = MsgFunction::GspRmControl; + type Command = GspRmControl; + type Reply = RmControlReply; + type InitError = Error; + + fn init(&self) -> impl Init<Self::Command, Self::InitError> { + let params_size: u32 = T::LEN.try_into()?; + Ok(GspRmControl::new( + self.0.client, + self.0.object, + T::FUNCTION, + params_size, + )) + } + + fn variable_payload_len(&self) -> usize { + T::LEN + } + + fn init_variable_payload( + &self, + dst: &mut SBufferIter<array::IntoIter<&mut [u8], 2>>, + ) -> Result { + self.0.cmd.write_payload(dst) + } +} + +/// Command for sending an RM control message to the GSP. +/// +/// RM control messages are used to query or control RM objects (see [`Handle`] for more info on RM +/// objects). It takes a client handle and an RM object handle identifying the target of the +/// message, within the given client. +pub(crate) struct RmControl<T> +where + T: RmControlCommand, +{ + /// The client handle under which `object` is allocated. + client: Handle<Client>, + /// The RM object handle to query or control. + object: Handle<T::Target>, + /// The specific RM control command to send. + cmd: T, +} + +#[expect(unused)] +impl<T: RmControlCommand> RmControl<T> { + /// Creates a new RM control command. + pub(crate) fn new(client: Handle<Client>, object: Handle<T::Target>, cmd: T) -> Self { + Self { + client, + object, + cmd, + } + } + + /// Sends an RM control command, checks the reply status, and returns the reply. + pub(crate) fn send(self, cmdq: &Cmdq, bar: &Bar0) -> Result<T::Reply> { + let reply = cmdq.send_command(bar, RawRmControl(&self))?; + + Result::from(reply.status)?; + + self.cmd.parse_reply(&reply.params) + } +} + +/// Response from an RM control message. +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.read_to_vec(GFP_KERNEL)?, + }) + } +} + +/// Trait for RM control commands that can be sent using [`RmControl`]. +pub(crate) trait RmControlCommand { + /// The specific RM control message kind to send. + const FUNCTION: RmControlMsgFunction; + + /// Length of the command-specific payload to send with the RM control message. + const LEN: usize; + + /// The type of the reply after parsing the raw bytes from the RM control reply message. + type Reply; + + /// The type of the RM object that this command targets. + type Target; + + /// Writes the payload of the command into `dst`. + fn write_payload(&self, dst: &mut SBufferIter<array::IntoIter<&mut [u8], 2>>) -> Result; + + /// Parses the reply bytes from an RM control reply message into the command-specific + /// reply type. + fn parse_reply(&self, params: &[u8]) -> Result<Self::Reply>; +} -- 2.53.0
