summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_gpu.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-01 01:06:14 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-01 01:06:14 -0400
commitb9264c40ad9f27f31176a9f8fe718196abde1800 (patch)
tree9739d73b3b4fc6fcb1dd1a8638e1c23f92df3c4e /kernel/gsp_phys_gpu.c
parent8065d67e9a7e2f22490406755e4df429b89136d0 (diff)
downloadopen-iov-b9264c40ad9f27f31176a9f8fe718196abde1800.tar.gz
open-iov-b9264c40ad9f27f31176a9f8fe718196abde1800.zip
gsp-phys: stage 3c FWSEC via VBIOS BIT image plus failure recovery
Diffstat (limited to 'kernel/gsp_phys_gpu.c')
-rw-r--r--kernel/gsp_phys_gpu.c62
1 files changed, 56 insertions, 6 deletions
diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c
index a0f564f..a7c8e57 100644
--- a/kernel/gsp_phys_gpu.c
+++ b/kernel/gsp_phys_gpu.c
@@ -61,6 +61,7 @@
#include "gsp_phys_gpu.h"
#include "gsp_phys_boot.h"
+#include "gsp_phys_fwsec.h"
#define GSP_PHYS_VENDOR 0x10de
#define GSP_PHYS_DEVICE 0x1ed3
@@ -695,11 +696,24 @@ int gsp_phys_gpu_claim(void)
} else {
pr_info("gsp-phys: real GSP firmware staged (backend rung 2)\n");
- if (gsp_phys_layout_enabled() &&
- gsp_phys_boot_layout_init(&phys.boot, phys.pdev, phys.bar0,
- phys.fw_image_size, phys.bar1_len))
- pr_warn("gsp-phys: boot layout/allocation failed; "
- "backend stays at rung 2\n");
+ if (gsp_phys_layout_enabled()) {
+ if (gsp_phys_boot_layout_init(&phys.boot, phys.pdev,
+ phys.bar0,
+ phys.fw_image_size,
+ phys.bar1_len)) {
+ pr_warn("gsp-phys: boot layout/allocation failed; "
+ "backend stays at rung 2\n");
+ } else if (gsp_phys_fwsec_enabled()) {
+ if (gsp_phys_fwsec_run(&phys.boot, phys.pdev,
+ phys.bar0))
+ pr_warn("gsp-phys: stage 3c FWSEC failed "
+ "(see recovery log above)\n");
+ else
+ pr_info("gsp-phys: stage 3c FWSEC complete "
+ "(WPR2 up; release will tear it "
+ "down)\n");
+ }
+ }
}
return 0;
@@ -731,11 +745,30 @@ void gsp_phys_gpu_release(void)
{
struct pci_dev *pdev;
struct device_driver *drv;
- int ret;
+ int ret, wpr2_ret = 0;
if (!phys.drv_registered && !phys.claimed && !phys.nr_locks)
return;
+ /*
+ * WPR2 teardown must run while this module still owns BAR0. A
+ * successful stage 3c leaves WPR2 carved in FB; the distribution
+ * driver refuses to boot against an unexpected WPR2, so it has to be
+ * removed (FWSEC-SB + booter unload) before the hand-back. If the
+ * board stopped answering, skip the teardown (writes to a dead
+ * device are pointless) and let the fail-safe below refuse the
+ * hand-back.
+ */
+ if (phys.pdev) {
+ if (gsp_phys_board_check(phys.pdev, "before WPR2 teardown")) {
+ wpr2_ret = -EIO;
+ } else {
+ wpr2_ret = gsp_phys_fwsec_release(&phys.boot,
+ phys.pdev,
+ phys.bar0);
+ }
+ }
+
if (phys.pdev)
gsp_phys_boot_layout_fini(&phys.boot, phys.pdev);
@@ -751,6 +784,23 @@ void gsp_phys_gpu_release(void)
if (pdev) {
/*
+ * Fail-safe: a WPR2 that survived the teardown makes the
+ * distribution driver's boot path fail (or worse), so never
+ * hand the device back in that state. Keep the D0 locks and
+ * the runtime-PM reference, as with the unresponsive-board
+ * abort.
+ */
+ if (wpr2_ret) {
+ pr_err("gsp-phys: NOT rebinding %s: WPR2 teardown did not complete (WPR2 still up or board unresponsive); do not boot the distribution driver against it; power domain stays LOCKED (reboot with approval; do not retry in this boot)\n",
+ pci_name(pdev));
+ if (phys.runtime_ref_held)
+ pr_debug("gsp-phys: keeping the runtime-PM reference on %s held (WPR2 still up)\n",
+ pci_name(pdev));
+ pci_dev_put(pdev);
+ return;
+ }
+
+ /*
* Abort signal before handing the GPU back: if the board no
* longer answers config reads, do not run the distribution
* driver's power-up path. Keep the D0 locks so that a