summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_fwsec.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-01 01:21:50 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-01 01:21:50 -0400
commit0055d732c38518bae3a0a58e8d4a6e427317ad8c (patch)
tree33917dd20c82a3003053440305b5aa88204cef5f /kernel/gsp_phys_fwsec.c
parent60afa9a299889e247b0dee1570956b9fbedfbf77 (diff)
downloadopen-iov-0055d732c38518bae3a0a58e8d4a6e427317ad8c.tar.gz
open-iov-0055d732c38518bae3a0a58e8d4a6e427317ad8c.zip
gsp-phys: fix the WPR2-up release hand-back and tighten FWSEC/VBIOS checks
Diffstat (limited to 'kernel/gsp_phys_fwsec.c')
-rw-r--r--kernel/gsp_phys_fwsec.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/kernel/gsp_phys_fwsec.c b/kernel/gsp_phys_fwsec.c
index 93a4208..a6f81e2 100644
--- a/kernel/gsp_phys_fwsec.c
+++ b/kernel/gsp_phys_fwsec.c
@@ -413,22 +413,29 @@ static int gsp_phys_falcon_wait_halt(void __iomem *bar0, u32 base,
}
}
-/* Wait for GFW boot completion: falcon halted and progress 0xff. */
+/* Wait for GFW boot completion: falcon halted, PLM lowered and progress 0xff. */
static int gsp_phys_fwsec_wait_gfw_boot(void __iomem *bar0)
{
unsigned long deadline = jiffies +
msecs_to_jiffies(GSP_PHYS_GFW_BOOT_TIMEOUT_MS);
- u32 cpuctl = 0, progress = 0;
+ u32 cpuctl = 0, progress = 0, plm = 0;
for (;;) {
cpuctl = readl(bar0 + GSP_PHYS_GSP_BASE +
GSP_PHYS_FALCON_CPUCTL);
+ plm = readl(bar0 + GSP_PHYS_GFW_PLM);
progress = readl(bar0 + GSP_PHYS_GFW_BOOT) &
GSP_PHYS_GFW_BOOT_PROGRESS_MASK;
+ /*
+ * FWSEC lowers its read-protection level before GFW posts
+ * progress; level0 must be readable for the progress to be
+ * meaningful.
+ */
if ((cpuctl & GSP_PHYS_CPUCTL_HALTED) &&
+ (plm & GSP_PHYS_GFW_PLM_LEVEL0) &&
progress == GSP_PHYS_GFW_BOOT_COMPLETED) {
- pr_info("gsp-phys-fwsec: GFW boot complete: CPUCTL=0x%08x (halted) progress=0xff\n",
- cpuctl);
+ pr_info("gsp-phys-fwsec: GFW boot complete: CPUCTL=0x%08x (halted) PLM=0x%08x progress=0xff\n",
+ cpuctl, plm);
return 0;
}
if (time_after_eq(jiffies, deadline))
@@ -436,8 +443,8 @@ static int gsp_phys_fwsec_wait_gfw_boot(void __iomem *bar0)
msleep(1);
}
- pr_err("gsp-phys-fwsec: GFW boot not complete (CPUCTL=0x%08x progress=0x%x, timeout %ums); not resetting or kicking the falcon\n",
- cpuctl, progress, GSP_PHYS_GFW_BOOT_TIMEOUT_MS);
+ pr_err("gsp-phys-fwsec: GFW boot not complete (CPUCTL=0x%08x PLM=0x%08x progress=0x%x, timeout %ums); not resetting or kicking the falcon\n",
+ cpuctl, plm, progress, GSP_PHYS_GFW_BOOT_TIMEOUT_MS);
return -ETIMEDOUT;
}
@@ -876,6 +883,13 @@ int gsp_phys_fwsec_run(struct gsp_phys_boot *boot, struct pci_dev *pdev,
return -EINVAL;
}
+ if (boot->frts_size != ((u64)GSP_PHYS_FRTS_REGION_SIZE_4K << 12)) {
+ pr_err("gsp-phys-fwsec: FRTS region size mismatch: boot layout 0x%llx, FWSEC constant 0x%llx; refusing stage 3c\n",
+ boot->frts_size,
+ (u64)GSP_PHYS_FRTS_REGION_SIZE_4K << 12);
+ return -EINVAL;
+ }
+
pr_info("gsp-phys-fwsec: stage 3c FWSEC/FRTS on %s: frtsOffset=0x%llx frtsSize=0x%llx\n",
pci_name(pdev), boot->frts_offset, boot->frts_size);
@@ -991,10 +1005,10 @@ int gsp_phys_fwsec_release(struct gsp_phys_boot *boot, struct pci_dev *pdev,
{
int ret;
- if (!fwsec.touched)
- return 0;
if (!pdev || !bar0)
return -EIO;
+ if (!fwsec.touched && !gsp_phys_fwsec_wpr2_up(bar0))
+ return 0;
if (!gsp_phys_fwsec_wpr2_up(bar0)) {
pr_info("gsp-phys-fwsec: release: WPR2 already down; freeing FWSEC staging and handing back\n");