Add first_usable_fb_region() to GspStaticConfigInfo to extract the first usable FB region from GSP's fbRegionInfoParams. Usable regions are those that are not reserved or protected.
The extracted region is stored in GetGspStaticInfoReply and exposed via usable_fb_region() API for use by the memory subsystem. Signed-off-by: Joel Fernandes <[email protected]> --- drivers/gpu/nova-core/gsp/commands.rs | 13 +++++++++- drivers/gpu/nova-core/gsp/fw/commands.rs | 30 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs index 311f65f8367b..d619cf294b9c 100644 --- a/drivers/gpu/nova-core/gsp/commands.rs +++ b/drivers/gpu/nova-core/gsp/commands.rs @@ -186,10 +186,13 @@ fn init(&self) -> impl Init<Self::Command, Self::InitError> { } } -/// The reply from the GSP to the [`GetGspInfo`] command. +/// The reply from the GSP to the [`GetGspStaticInfo`] command. pub(crate) struct GetGspStaticInfoReply { gpu_name: [u8; 64], bar1_pde_base: u64, + /// First usable FB region (base, size) for memory allocation. + #[expect(dead_code)] + usable_fb_region: Option<(u64, u64)>, } impl MessageFromGsp for GetGspStaticInfoReply { @@ -204,6 +207,7 @@ fn read( Ok(GetGspStaticInfoReply { gpu_name: msg.gpu_name_str(), bar1_pde_base: msg.bar1_pde_base(), + usable_fb_region: msg.first_usable_fb_region(), }) } } @@ -235,6 +239,13 @@ pub(crate) fn gpu_name(&self) -> core::result::Result<&str, GpuNameError> { pub(crate) fn bar1_pde_base(&self) -> u64 { self.bar1_pde_base } + + /// Returns the usable FB region (base, size) for driver allocation which is + /// already retrieved from the GSP. + #[expect(dead_code)] + pub(crate) fn usable_fb_region(&self) -> Option<(u64, u64)> { + self.usable_fb_region + } } /// Send the [`GetGspInfo`] command and awaits for its reply. diff --git a/drivers/gpu/nova-core/gsp/fw/commands.rs b/drivers/gpu/nova-core/gsp/fw/commands.rs index f069f4092911..cc1cf4bd52ea 100644 --- a/drivers/gpu/nova-core/gsp/fw/commands.rs +++ b/drivers/gpu/nova-core/gsp/fw/commands.rs @@ -122,6 +122,36 @@ impl GspStaticConfigInfo { pub(crate) fn bar1_pde_base(&self) -> u64 { self.0.bar1PdeBase } + + /// Extract the first usable FB region from GSP firmware data. + /// + /// Returns the first region suitable for driver memory allocation as a base,size tuple. + /// Usable regions are those that: + /// - Are not reserved for firmware internal use. + /// - Are not protected (hardware-enforced access restrictions). + /// - Support compression (can use GPU memory compression for bandwidth). + /// - Support ISO (isochronous memory for display requiring guaranteed bandwidth). + pub(crate) fn first_usable_fb_region(&self) -> Option<(u64, u64)> { + let fb_info = &self.0.fbRegionInfoParams; + for i in 0..fb_info.numFBRegions as usize { + if let Some(reg) = fb_info.fbRegion.get(i) { + // Skip malformed regions where limit < base. + if reg.limit < reg.base { + continue; + } + // Filter: not reserved, not protected, supports compression and ISO. + if reg.reserved == 0 + && reg.bProtected == 0 + && reg.supportCompressed != 0 + && reg.supportISO != 0 + { + let size = reg.limit - reg.base + 1; + return Some((reg.base, size)); + } + } + } + None + } } // SAFETY: Padding is explicit and will not contain uninitialized data. -- 2.34.1
