Add `total_fb_end()` to `GspStaticConfigInfo` that computes the exclusive end
address of the highest valid FB region covering both usable and GSP-reserved
areas.

This allows callers to know the full physical VRAM extent, not just the
allocatable portion.

Signed-off-by: Joel Fernandes <[email protected]>
---
 drivers/gpu/nova-core/gsp/commands.rs    |  6 ++++++
 drivers/gpu/nova-core/gsp/fw/commands.rs | 19 +++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/drivers/gpu/nova-core/gsp/commands.rs 
b/drivers/gpu/nova-core/gsp/commands.rs
index 8d5780d9cace..389d215098c6 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -193,6 +193,9 @@ pub(crate) struct GetGspStaticInfoReply {
     /// Usable FB (VRAM) region for driver memory allocation.
     #[expect(dead_code)]
     pub(crate) usable_fb_region: Range<u64>,
+    /// End of VRAM.
+    #[expect(dead_code)]
+    pub(crate) total_fb_end: u64,
 }
 
 impl MessageFromGsp for GetGspStaticInfoReply {
@@ -206,9 +209,12 @@ fn read(
     ) -> Result<Self, Self::InitError> {
         let (base, size) = msg.first_usable_fb_region().ok_or(ENODEV)?;
 
+        let total_fb_end = msg.total_fb_end().ok_or(ENODEV)?;
+
         Ok(GetGspStaticInfoReply {
             gpu_name: msg.gpu_name_str(),
             usable_fb_region: base..base.saturating_add(size),
+            total_fb_end,
         })
     }
 }
diff --git a/drivers/gpu/nova-core/gsp/fw/commands.rs 
b/drivers/gpu/nova-core/gsp/fw/commands.rs
index cef86cab8a12..acaf92cd6735 100644
--- a/drivers/gpu/nova-core/gsp/fw/commands.rs
+++ b/drivers/gpu/nova-core/gsp/fw/commands.rs
@@ -147,6 +147,25 @@ pub(crate) fn first_usable_fb_region(&self) -> 
Option<(u64, u64)> {
         }
         None
     }
+
+    /// Compute the end of physical VRAM from all FB regions.
+    pub(crate) fn total_fb_end(&self) -> Option<u64> {
+        let fb_info = &self.0.fbRegionInfoParams;
+        let mut max_end: Option<u64> = None;
+        for i in 0..fb_info.numFBRegions.into_safe_cast() {
+            if let Some(reg) = fb_info.fbRegion.get(i) {
+                if reg.limit < reg.base {
+                    continue;
+                }
+                let end = reg.limit.saturating_add(1);
+                max_end = Some(match max_end {
+                    None => end,
+                    Some(prev) => prev.max(end),
+                });
+            }
+        }
+        max_end
+    }
 }
 
 // SAFETY: Padding is explicit and will not contain uninitialized data.
-- 
2.34.1

Reply via email to