To support the maximum vGPUs on devices that support vGPU, a larger
WPR2 heap size is required. On Ada with vGPU supported, the size should
be set to at least 581MB.

When vGPU support is enabled:
  - Reserve a larger WPR2 heap size of 581MB.
  - Set vf_partition_count to MAX_PARTITIONS_WITH_GFID_32VM (32) to
    support the maximum number of virtual functions in the WPR2 meta,
    or MAX_PARTITIONS_WITH_GFID (48) when total VFs exceeds 32.

When vGPU support is not enabled, the original heap size calculation and
partition count of 0 are preserved.

Cc: Alexandre Courbot <[email protected]>
Signed-off-by: Zhi Wang <[email protected]>
---
 drivers/gpu/nova-core/fb.rs                   | 21 +++++++++++++++----
 drivers/gpu/nova-core/gpu.rs                  | 13 +++++++++++-
 drivers/gpu/nova-core/gsp.rs                  |  7 ++++++-
 drivers/gpu/nova-core/gsp/boot.rs             |  2 +-
 drivers/gpu/nova-core/gsp/fw.rs               |  6 ++++++
 .../gpu/nova-core/gsp/fw/r570_144/bindings.rs |  4 ++++
 drivers/gpu/nova-core/vgpu.rs                 |  2 +-
 7 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs
index 1a84a15581a4..2228b6b08699 100644
--- a/drivers/gpu/nova-core/fb.rs
+++ b/drivers/gpu/nova-core/fb.rs
@@ -181,7 +181,15 @@ pub(crate) struct FbLayout {
 
 impl FbLayout {
     /// Computes the FB layout for `chipset` required to run the `gsp_fw` GSP 
firmware.
-    pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> 
Result<Self> {
+    ///
+    /// When `vf_partition_count` is non-zero, a larger WPR2 heap is reserved 
to support
+    /// vGPU virtual functions: 1370 MiB for 48 partitions, 581 MiB for 32 or 
fewer.
+    pub(crate) fn new(
+        chipset: Chipset,
+        bar: &Bar0,
+        gsp_fw: &GspFirmware,
+        vf_partition_count: u8,
+    ) -> Result<Self> {
         let hal = hal::fb_hal(chipset);
 
         let fb = {
@@ -243,8 +251,13 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: 
&GspFirmware) -> Result<
 
         let wpr2_heap = {
             const WPR2_HEAP_DOWN_ALIGN: Alignment = Alignment::new::<SZ_1M>();
-            let wpr2_heap_size =
-                gsp::LibosParams::from_chipset(chipset).wpr_heap_size(chipset, 
fb.end)?;
+            let wpr2_heap_size = if vf_partition_count == 0 {
+                gsp::LibosParams::from_chipset(chipset).wpr_heap_size(chipset, 
fb.end)?
+            } else if vf_partition_count > gsp::MAX_PARTITIONS_WITH_GFID_32VM {
+                gsp::GSP_FW_HEAP_SIZE_VGPU_48VMS
+            } else {
+                gsp::GSP_FW_HEAP_SIZE_VGPU_DEFAULT
+            };
             let wpr2_heap_addr = (elf.start - 
wpr2_heap_size).align_down(WPR2_HEAP_DOWN_ALIGN);
 
             
FbRange(wpr2_heap_addr..(elf.start).align_down(WPR2_HEAP_DOWN_ALIGN))
@@ -272,7 +285,7 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: 
&GspFirmware) -> Result<
             wpr2_heap,
             wpr2,
             heap,
-            vf_partition_count: 0,
+            vf_partition_count,
         })
     }
 }
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index e1c16e1b9ec4..e254ddca0fa4 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -25,7 +25,9 @@
     gfw,
     gsp::{
         Gsp,
-        GspBootContext, //
+        GspBootContext,
+        MAX_PARTITIONS_WITH_GFID,
+        MAX_PARTITIONS_WITH_GFID_32VM, //
     },
     regs,
     vgpu::Vgpu, //
@@ -389,6 +391,15 @@ pub(crate) fn new<'a>(
                         sec2_falcon,
                         fsp_falcon: None,
                         vgpu_requested: vgpu.vgpu_requested,
+                        vf_partition_count: if vgpu.vgpu_requested {
+                            if vgpu.total_vfs > 
u16::from(MAX_PARTITIONS_WITH_GFID_32VM) {
+                                MAX_PARTITIONS_WITH_GFID
+                            } else {
+                                MAX_PARTITIONS_WITH_GFID_32VM
+                            }
+                        } else {
+                            0
+                        },
                     };
                     gsp.boot(&mut ctx)?;
                     vgpu.vgpu_enabled = ctx.vgpu_requested;
diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs
index 9435c7430dfe..528f37e581c7 100644
--- a/drivers/gpu/nova-core/gsp.rs
+++ b/drivers/gpu/nova-core/gsp.rs
@@ -26,8 +26,12 @@
 mod sequencer;
 
 pub(crate) use fw::{
+    GSP_FW_HEAP_SIZE_VGPU_48VMS,
+    GSP_FW_HEAP_SIZE_VGPU_DEFAULT,
     GspFwWprMeta,
-    LibosParams, //
+    LibosParams,
+    MAX_PARTITIONS_WITH_GFID,
+    MAX_PARTITIONS_WITH_GFID_32VM, //
 };
 
 use crate::{
@@ -62,6 +66,7 @@ pub(crate) struct GspBootContext<'a> {
     pub(crate) sec2_falcon: &'a Falcon<Sec2Falcon>,
     pub(crate) fsp_falcon: Option<Falcon<FspFalcon>>,
     pub(crate) vgpu_requested: bool,
+    pub(crate) vf_partition_count: u8,
 }
 
 impl GspBootContext<'_> {
diff --git a/drivers/gpu/nova-core/gsp/boot.rs 
b/drivers/gpu/nova-core/gsp/boot.rs
index ed8729041d46..86b7a7aa8f5a 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -346,7 +346,7 @@ pub(crate) fn boot(
         let dev = ctx.dev();
         let gsp_fw = KBox::pin_init(GspFirmware::new(dev, chipset, 
FIRMWARE_VERSION), GFP_KERNEL)?;
 
-        let fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?;
+        let fb_layout = FbLayout::new(chipset, bar, &gsp_fw, 
ctx.vf_partition_count)?;
         dev_dbg!(dev, "{:#x?}\n", fb_layout);
 
         let wpr_meta = Coherent::<GspFwWprMeta>::zeroed(dev, GFP_KERNEL)?;
diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs
index ca01ac3af9c6..b46ab6b921e3 100644
--- a/drivers/gpu/nova-core/gsp/fw.rs
+++ b/drivers/gpu/nova-core/gsp/fw.rs
@@ -454,6 +454,12 @@ enum GspFwHeapParams {}
 /// Minimum required alignment for the GSP heap.
 const GSP_HEAP_ALIGNMENT: Alignment = Alignment::new::<{ 1 << 20 }>();
 
+// vGPU constants from the bindings, re-exported for use by fb.rs and gpu.rs.
+pub(crate) const GSP_FW_HEAP_SIZE_VGPU_DEFAULT: u64 = 
bindings::GSP_FW_HEAP_SIZE_VGPU_DEFAULT as u64;
+pub(crate) const GSP_FW_HEAP_SIZE_VGPU_48VMS: u64 = 
bindings::GSP_FW_HEAP_SIZE_VGPU_48VMS as u64;
+pub(crate) const MAX_PARTITIONS_WITH_GFID: u8 = 
bindings::MAX_PARTITIONS_WITH_GFID;
+pub(crate) const MAX_PARTITIONS_WITH_GFID_32VM: u8 = 
bindings::MAX_PARTITIONS_WITH_GFID_32VM;
+
 // These constants override the generated bindings for architecture-specific 
heap sizing.
 // See Open RM: kgspCalculateGspFwHeapSize and related functions.
 //
diff --git a/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs 
b/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
index 354ee2cfa295..1273152266ad 100644
--- a/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
+++ b/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
@@ -40,6 +40,10 @@ fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> 
::core::fmt::Result {
 pub const GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS2_MAX_MB: u32 = 256;
 pub const GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MIN_MB: u32 = 88;
 pub const GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MAX_MB: u32 = 280;
+pub const GSP_FW_HEAP_SIZE_VGPU_DEFAULT: u32 = 581 << 20;
+pub const GSP_FW_HEAP_SIZE_VGPU_48VMS: u32 = 1370 << 20;
+pub const MAX_PARTITIONS_WITH_GFID: u8 = 48;
+pub const MAX_PARTITIONS_WITH_GFID_32VM: u8 = 32;
 pub const GSP_FW_WPR_META_REVISION: u32 = 1;
 pub const GSP_FW_WPR_META_MAGIC: i64 = -2577556379034558285;
 pub const REGISTRY_TABLE_ENTRY_TYPE_DWORD: u32 = 1;
diff --git a/drivers/gpu/nova-core/vgpu.rs b/drivers/gpu/nova-core/vgpu.rs
index d35081a088cf..5736eaa79654 100644
--- a/drivers/gpu/nova-core/vgpu.rs
+++ b/drivers/gpu/nova-core/vgpu.rs
@@ -14,7 +14,7 @@
 pub(crate) struct Vgpu {
     pub(crate) vgpu_requested: bool,
     pub(crate) vgpu_enabled: bool,
-    pub total_vfs: u16,
+    pub(crate) total_vfs: u16,
 }
 
 impl Vgpu {
-- 
2.51.0

Reply via email to