diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-01 01:21:50 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-01 01:21:50 -0400 |
| commit | 12db41d77c899400fffc0486b64ebd057a1e95fa (patch) | |
| tree | 726093bf0948a6eb8aa764e0b1ed38a520ea589e /kernel/gsp_phys_fwsec.c | |
| parent | 55a8591fb503c3924f5037c39479ca811e00514b (diff) | |
| download | open-iov-12db41d77c899400fffc0486b64ebd057a1e95fa.tar.gz open-iov-12db41d77c899400fffc0486b64ebd057a1e95fa.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.c | 30 |
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"); |
