[PATCH v3 25/31] gpu: nova-core: vgpu: negotiate the GSP plugin RPC version

From: Zhi Wang

Date: Mon Sep 28 2026 - 06:39:45 EST


The host must negotiate the RPC protocol with the booted GSP plugin
before sending instance configuration.

After observing the plugin's ready marker, initialize the shared RPC
buffers and submit the existing typed version-negotiation request
through the instance's PluginRpc channel.

Co-developed-by: Eliot Courtney <ecourtney@xxxxxxxxxx>
Signed-off-by: Eliot Courtney <ecourtney@xxxxxxxxxx>
Signed-off-by: Zhi Wang <zhiw@xxxxxxxxxx>
---
drivers/gpu/nova-core/vgpu/commands.rs | 12 +++++++++++-
drivers/gpu/nova-core/vgpu/fw.rs | 4 ++--
drivers/gpu/nova-core/vgpu/fw/commands.rs | 1 -
drivers/gpu/nova-core/vgpu/gsp_plugin_rpc.rs | 2 --
drivers/gpu/nova-core/vgpu/instance.rs | 3 +++
5 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/nova-core/vgpu/commands.rs b/drivers/gpu/nova-core/vgpu/commands.rs
index 52c6fc0ee335..268c3043d88b 100644
--- a/drivers/gpu/nova-core/vgpu/commands.rs
+++ b/drivers/gpu/nova-core/vgpu/commands.rs
@@ -27,13 +27,15 @@
commands::{
VgpuPropertiesSchema, //
},
+ RpcMessage, //
GMCAPI_CMD_BOOTLOAD_GSP_VGPU_PLUGIN_TASK,
GMCAPI_CMD_CLEANUP_GSP_VGPU_PLUGIN_RESOURCES,
GMCAPI_CMD_QUERY_ASSIGNED_VF_VGPU_TYPE,
GMCAPI_CMD_QUERY_VGPU_PROPERTIES,
GMCAPI_CMD_SHUTDOWN_GSP_VGPU_PLUGIN_TASK,
- GMCAPI_CMD_SHUTDOWN_GSP_VGPU_PLUGIN_TASK_COMPLETE, //
+ GMCAPI_CMD_SHUTDOWN_GSP_VGPU_PLUGIN_TASK_COMPLETE,
},
+ gsp_plugin_rpc::PluginRpc,
instance::Gfid, //
};

@@ -159,3 +161,11 @@ pub(super) fn send_cleanup(
dev_dbg!(dev, "cleanup: gfid={} done\n", gfid.get());
Ok(())
}
+
+/// Negotiate the host protocol with a bootloaded GSP plugin.
+pub(super) fn negotiate_plugin_version(
+ dev: &device::Device<device::Bound>,
+ rpc: &mut PluginRpc<'_, '_>,
+) -> Result {
+ rpc.rpc_call(dev, RpcMessage::VersionNegotiation, &[])
+}
diff --git a/drivers/gpu/nova-core/vgpu/fw.rs b/drivers/gpu/nova-core/vgpu/fw.rs
index d80f36465296..6cec92c9b505 100644
--- a/drivers/gpu/nova-core/vgpu/fw.rs
+++ b/drivers/gpu/nova-core/vgpu/fw.rs
@@ -10,8 +10,6 @@

use crate::gsp::bindings;

-pub(super) use commands::RpcMessage;
-
pub(super) use bindings::{
GSP_PLUGIN_BOOTLOADED,
VGPU_CPU_GSP_COMMUNICATION_BUFF_TOTAL_SIZE,
@@ -29,6 +27,8 @@
VGPU_CPU_GSP_VGPU_TASK_LOG_BUFF_REGION_SIZE, //
};

+pub(super) use commands::RpcMessage;
+
pub(super) const GMCAPI_CMD_QUERY_ASSIGNED_VF_VGPU_TYPE: u32 =
bindings::GMCAPI_COMMANDS_GMCAPI_CMD_QUERY_ASSIGNED_VF_VGPU_TYPE;

diff --git a/drivers/gpu/nova-core/vgpu/fw/commands.rs b/drivers/gpu/nova-core/vgpu/fw/commands.rs
index 91d43cf6dd85..915585706174 100644
--- a/drivers/gpu/nova-core/vgpu/fw/commands.rs
+++ b/drivers/gpu/nova-core/vgpu/fw/commands.rs
@@ -31,7 +31,6 @@
use super::bindings;

/// Message types supported by the nova-core plugin RPC channel.
-#[expect(dead_code)]
#[derive(Clone, Copy)]
#[repr(u32)]
pub(crate) enum RpcMessage {
diff --git a/drivers/gpu/nova-core/vgpu/gsp_plugin_rpc.rs b/drivers/gpu/nova-core/vgpu/gsp_plugin_rpc.rs
index 0ee32f011f63..696127c7169f 100644
--- a/drivers/gpu/nova-core/vgpu/gsp_plugin_rpc.rs
+++ b/drivers/gpu/nova-core/vgpu/gsp_plugin_rpc.rs
@@ -65,7 +65,6 @@ pub(super) fn comm(&self) -> &CommBufferRegion<'map, 'gpu> {
}

/// Initialize the control and response buffers for the first RPC.
- #[expect(dead_code)]
pub(super) fn init_rpc(&mut self) -> Result {
self.comm.initialize()?;
self.message_sequence = 0;
@@ -82,7 +81,6 @@ fn next_sequence(&self) -> u32 {
}

/// Write one RPC message, ring the VF doorbell, and wait for its response.
- #[expect(dead_code)]
pub(super) fn rpc_call(
&mut self,
dev: &device::Device<device::Bound>,
diff --git a/drivers/gpu/nova-core/vgpu/instance.rs b/drivers/gpu/nova-core/vgpu/instance.rs
index 8a2d8e3970a3..445d7f513fdc 100644
--- a/drivers/gpu/nova-core/vgpu/instance.rs
+++ b/drivers/gpu/nova-core/vgpu/instance.rs
@@ -31,6 +31,7 @@

use super::{
commands::{
+ negotiate_plugin_version,
send_bootload,
send_cleanup,
send_shutdown,
@@ -156,6 +157,8 @@ impl<'gpu> VgpuInstance<'gpu> {
fn activate(&mut self, vgpu: &VgpuManager<'gpu>) -> Result {
let dev = vgpu.dev;
self.bootload(dev, vgpu.cmdq, &vgpu.fifo_engine_list)?;
+ self.plugin_rpc.init_rpc()?;
+ negotiate_plugin_version(dev, &mut self.plugin_rpc)?;

Ok(())
}