From: "Alexandre Courbot" <acourbot@nvidia.com>
To: "Zhi Wang" <zhiw@nvidia.com>
Cc: <dakr@kernel.org>, <airlied@gmail.com>, <simona@ffwll.ch>,
<ojeda@kernel.org>, <alex.gaynor@gmail.com>,
<boqun.feng@gmail.com>, <gary@garyguo.net>,
<bjorn3_gh@protonmail.com>, <lossin@kernel.org>,
<a.hindborg@kernel.org>, <aliceryhl@google.com>,
<tmgross@umich.edu>, <jhubbard@nvidia.com>,
<ecourtney@nvidia.com>, <joelagnelf@nvidia.com>,
<apopple@nvidia.com>, <cjia@nvidia.com>, <smitra@nvidia.com>,
<kjaju@nvidia.com>, <alkumar@nvidia.com>, <ankita@nvidia.com>,
<aniketa@nvidia.com>, <kwankhede@nvidia.com>,
<targupta@nvidia.com>, <nova-gpu@lists.linux.dev>,
<linux-kernel@vger.kernel.org>, <zhiwang@kernel.org>
Subject: Re: [PATCH 4/9] gpu: nova-core: read vGPU mode from FSP via PRC protocol
Date: Tue, 16 Jun 2026 17:35:27 +0900 [thread overview]
Message-ID: <DJAC408HKZTR.20UBUA67YKT3O@nvidia.com> (raw)
In-Reply-To: <20260604114339.1565660-5-zhiw@nvidia.com>
On Thu Jun 4, 2026 at 8:43 PM JST, Zhi Wang wrote:
> Add support for querying the vGPU mode configuration from FSP using
> the PRC (Product Reconfiguration Control) protocol. PRC is an API
> system exposed through FSP's Management Partition that allows querying
> device configuration "knobs" without firmware updates.
>
> Add a VgpuMode enum that validates the raw PRC response value,
> returning an error for unexpected values.
>
> Signed-off-by: Zhi Wang <zhiw@nvidia.com>
> ---
> drivers/gpu/nova-core/fsp.rs | 145 ++++++++++++++++++++++++++++++++++
> drivers/gpu/nova-core/mctp.rs | 3 +
> 2 files changed, 148 insertions(+)
>
> diff --git a/drivers/gpu/nova-core/fsp.rs b/drivers/gpu/nova-core/fsp.rs
> index 5fd2e9e277b1..ce11efeba37e 100644
> --- a/drivers/gpu/nova-core/fsp.rs
> +++ b/drivers/gpu/nova-core/fsp.rs
> @@ -48,6 +48,44 @@
>
> mod hal;
>
> +/// PRC (Product Reconfiguration Control) protocol constants.
> +///
> +/// PRC is an API system exposed through FSP's Management Partition that allows
> +/// querying and modifying device configuration "knobs" without firmware updates.
> +/// Each knob is identified by a unique object ID and controls a specific device
> +/// behavior (e.g., vGPU mode, ECC, confidential computing).
> +mod prc {
> + /// Sub-command to read a PRC knob value.
> + pub(super) const SUBCMD_READ: u8 = 0x0c;
> +
> + /// PRC object ID for vGPU mode configuration (knob ID 41).
> + pub(super) const OBJECT_VGPU_MODE: u8 = 0x29;
> +
> + /// Request the active knob value (currently effective this boot).
> + pub(super) const FLAG_ACTIVE: u8 = 1 << 1;
> +}
These 3 should be defined as their own enum types, to make sure we
cannot mix them. For instance:
enum PrcMessageSubcmd {
Read = 0x0c,
}
enum PrcObjectId {
VgpuMode = 0x29,
}
(for the flags I guess you will want to use `kernel::impl_flags!`?)
Then, `NvdmPayloadPrc` can have a constructor that takes these 3 as
parameters and returns the constructed value - that way no risk of, say,
using the subcmd as an object identifier.
Btw, is there a public source for these values?
I like the idea of using a `prc` sub-module - to the point where I'd
suggest moving all PRC-related types to it, and all CoT messages to a
`cot` sub-module. But doing it in this series would distract from the
goal, and the `fsp` module is not that large, so let's keep everything
in it for now and do this as a follow-up.
> +
> +/// vGPU operating mode as reported by FSP via the PRC protocol.
> +#[derive(Debug, Clone, Copy, PartialEq, Eq)]
> +pub(crate) enum VgpuMode {
> + /// vGPU support is disabled on this GPU.
> + Disabled = 0,
> + /// vGPU support is enabled on this GPU.
> + Enabled = 1,
> +}
> +
> +impl TryFrom<u16> for VgpuMode {
> + type Error = kernel::error::Error;
> +
> + fn try_from(value: u16) -> Result<Self> {
> + match value {
> + 0 => Ok(VgpuMode::Disabled),
> + 1 => Ok(VgpuMode::Enabled),
> + _ => Err(EINVAL),
> + }
> + }
> +}
You can even do `TryFrom<NvdmPayloadPrcResponse> for VgpuMode` for a
better fit.
> +
> /// FSP command response payload (`NVDM_PAYLOAD_COMMAND_RESPONSE`).
> #[repr(C, packed)]
> #[derive(Clone, Copy)]
> @@ -57,6 +95,39 @@ struct NvdmPayloadCommandResponse {
> error_code: u32,
> }
>
> +// SAFETY: NvdmPayloadCommandResponse is a packed C struct with only integral fields.
> +unsafe impl FromBytes for NvdmPayloadCommandResponse {}
> +
> +/// PRC message payload.
> +///
> +/// Sent to FSP to query or modify a device configuration knob.
> +/// The response includes the common FSP response header followed by
> +/// a [`NvdmPayloadPrcResponse`] with the knob's current state value.
> +#[repr(C, packed)]
> +#[derive(Clone, Copy)]
> +struct NvdmPayloadPrc {
> + sub_message_id: u8,
> + flags: u8,
> + object_id: u8,
> + reserved: u8,
> +}
> +
> +// SAFETY: NvdmPayloadPrc is a packed C struct with only integral fields.
> +unsafe impl AsBytes for NvdmPayloadPrc {}
> +
> +/// PRC response payload containing the knob state value.
> +#[repr(C, packed)]
> +#[derive(Clone, Copy)]
> +struct NvdmPayloadPrcResponse {
> + value_low: u8,
> + value_high: u8,
> + reserved1: u8,
> + reserved2: u8,
> +}
> +
> +// SAFETY: NvdmPayloadPrcResponse is a packed C struct with only integral fields.
> +unsafe impl FromBytes for NvdmPayloadPrcResponse {}
> +
> /// Common MCTP and NVDM headers shared by all FSP messages.
> #[repr(C, packed)]
> #[derive(Clone, Copy)]
> @@ -92,6 +163,18 @@ struct FspResponse {
> // SAFETY: FspResponse is a packed C struct with only integral fields.
> unsafe impl FromBytes for FspResponse {}
>
> +/// Complete FSP PRC response including the knob state payload.
> +#[repr(C, packed)]
> +#[derive(Clone, Copy)]
> +struct FspPrcResponse {
> + header: FspMessageHeader,
> + response: NvdmPayloadCommandResponse,
Since you introduced `FspMessageHeader` to factor out `mctp_header`
and `nvdm_header`, can you do the same for the reponse? I guess in our
case this is as simple as renaming `FspResponse` to `FspResponseHeader`
and using it in `FspPrcResponse`.
> + prc_data: NvdmPayloadPrcResponse,
> +}
> +
> +// SAFETY: FspPrcResponse is a packed C struct with only integral fields.
> +unsafe impl FromBytes for FspPrcResponse {}
> +
> /// Trait implemented by types representing a message to send to FSP.
> ///
> /// This provides [`Fsp::send_sync_fsp`] with the information it needs to send
> @@ -178,10 +261,25 @@ fn new<'a>(
> // bytes are initialized.
> unsafe impl AsBytes for FspCotMessage {}
>
> +/// Complete FSP PRC message.
> +#[repr(C, packed)]
> +#[derive(Clone, Copy)]
> +struct FspPrcMessage {
> + header: FspMessageHeader,
> + prc: NvdmPayloadPrc,
> +}
> +
> +// SAFETY: FspPrcMessage is a packed C struct with only integral fields.
> +unsafe impl AsBytes for FspPrcMessage {}
> +
> impl MessageToFsp for FspCotMessage {
> const NVDM_TYPE: NvdmType = NvdmType::Cot;
> }
>
> +impl MessageToFsp for FspPrcMessage {
> + const NVDM_TYPE: NvdmType = NvdmType::Prc;
> +}
> +
> /// Bundled arguments for FMC boot via FSP Chain of Trust.
> pub(crate) struct FmcBootArgs {
> chipset: Chipset,
> @@ -226,6 +324,53 @@ pub(crate) struct Fsp {
> }
>
> impl Fsp {
> + /// Read vGPU mode from FSP using the PRC protocol.
> + ///
> + /// Queries FSP's Management Partition for the active vGPU mode knob value.
> + /// Returns [`VgpuMode::Enabled`] if vGPU support is active on this GPU,
> + /// [`VgpuMode::Disabled`] otherwise.
> + #[expect(dead_code)]
> + pub(crate) fn read_vgpu_mode(
> + &mut self,
> + dev: &device::Device<device::Bound>,
> + bar: Bar0<'_>,
> + ) -> Result<VgpuMode> {
> + let msg = KBox::new(
> + FspPrcMessage {
> + header: FspMessageHeader::new(NvdmType::Prc),
> + prc: NvdmPayloadPrc {
> + sub_message_id: prc::SUBCMD_READ,
> + flags: prc::FLAG_ACTIVE,
> + object_id: prc::OBJECT_VGPU_MODE,
> + reserved: 0,
> + },
> + },
> + GFP_KERNEL,
> + )?;
> +
> + let response_buf = self.send_sync_fsp(dev, bar, &*msg)?;
> +
> + let prc_resp_size = core::mem::size_of::<FspPrcResponse>();
> + if response_buf.len() < prc_resp_size {
> + dev_err!(
> + dev,
> + "PRC response too small: {} bytes (expected {})\n",
> + response_buf.len(),
> + prc_resp_size
> + );
> + return Err(EIO);
> + }
IIUC `from_bytes_prefix` takes care of checking the size, so this check
looks redundant.
next prev parent reply other threads:[~2026-06-16 8:35 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-04 11:43 [PATCH 0/9] gpu: nova-core: boot GSP with vGPU enabled on Zhi Wang
2026-06-04 11:43 ` [PATCH 1/9] rust: pci: expose sriov_get_totalvfs() helper Zhi Wang
2026-06-05 14:08 ` Alexandre Courbot
2026-06-04 11:43 ` [PATCH 2/9] gpu: nova-core: factor out common FSP message header Zhi Wang
2026-06-05 13:21 ` Alexandre Courbot
2026-06-04 11:43 ` [PATCH 3/9] gpu: nova-core: return FSP response buffer to caller Zhi Wang
2026-06-05 13:25 ` Alexandre Courbot
2026-06-05 16:04 ` Zhi Wang
2026-06-09 6:07 ` Alexandre Courbot
2026-06-04 11:43 ` [PATCH 4/9] gpu: nova-core: read vGPU mode from FSP via PRC protocol Zhi Wang
2026-06-16 8:35 ` Alexandre Courbot [this message]
2026-06-04 11:43 ` [PATCH 5/9] gpu: nova-core: add FSP and PRC protocol documentation Zhi Wang
2026-06-16 8:17 ` Alexandre Courbot
2026-06-04 11:43 ` [PATCH 6/9] gpu: nova-core: consolidate GSP boot parameters into GspBootContext Zhi Wang
2026-06-16 14:13 ` Alexandre Courbot
2026-06-04 11:43 ` [PATCH 7/9] gpu: nova-core: add vGPU preludes Zhi Wang
2026-06-04 11:43 ` [PATCH 8/9] gpu: nova-core: set RMSetSriovMode when NVIDIA vGPU is enabled Zhi Wang
2026-06-04 11:43 ` [PATCH] gpu: nova-core: reserve a larger GSP WPR2 heap when " Zhi Wang
2026-06-16 14:20 ` Alexandre Courbot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DJAC408HKZTR.20UBUA67YKT3O@nvidia.com \
--to=acourbot@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=airlied@gmail.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=alkumar@nvidia.com \
--cc=aniketa@nvidia.com \
--cc=ankita@nvidia.com \
--cc=apopple@nvidia.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=cjia@nvidia.com \
--cc=dakr@kernel.org \
--cc=ecourtney@nvidia.com \
--cc=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=joelagnelf@nvidia.com \
--cc=kjaju@nvidia.com \
--cc=kwankhede@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=simona@ffwll.ch \
--cc=smitra@nvidia.com \
--cc=targupta@nvidia.com \
--cc=tmgross@umich.edu \
--cc=zhiw@nvidia.com \
--cc=zhiwang@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.