[Nouveau] [PATCH v4 29/33] secboot: base support for PMU falcon

Alexandre Courbot acourbot at nvidia.com
Mon Nov 21 08:29:26 UTC 2016


Adapt secboot's behavior if a PMU firmware is present, in particular
the way LS falcons are reset. Without PMU firmware, secboot needs to be
performed again from scratch so all LS falcons are reset. With PMU
firmware, we can ask the PMU's ACR unit to reset a specific falcon
through a PMU message.

As we must preserve the old behavior to avoid breaking user-space, add a
few conditionals to the way falcons are reset.

Signed-off-by: Alexandre Courbot <acourbot at nvidia.com>
---
 drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 97 +++++++++++++++++++----
 1 file changed, 82 insertions(+), 15 deletions(-)

diff --git a/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
index fd316bd2f0a4..bfcfb647f4ad 100644
--- a/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
+++ b/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
@@ -24,6 +24,8 @@
 
 #include <core/gpuobj.h>
 #include <core/firmware.h>
+#include <subdev/mc.h>
+#include <subdev/pmu.h>
 
 /**
  * struct hsf_fw_header - HS firmware descriptor
@@ -780,7 +782,7 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb)
 	if (ret)
 		return ret;
 
-	nvkm_debug(&sb->subdev, "running HS load blob\n");
+	nvkm_debug(subdev, "running HS load blob\n");
 	ret = sb->func->run_blob(sb, acr->load_blob);
 	nvkm_secboot_falcon_clear_halt_interrupt(device, sb->base);
 	if (ret)
@@ -798,6 +800,50 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb)
 			func->post_run(&acr->base, sb);
 	}
 
+	/* Re-start ourselves if we are managed */
+	if (!nvkm_secboot_is_managed(sb, acr->base.boot_falcon))
+		return 0;
+
+	/* Enable interrupts */
+	nvkm_wr32(device, sb->base + 0x10, 0xff);
+	nvkm_mc_intr_mask(device, sb->devidx, true);
+
+	/* Start PMU */
+	nvkm_secboot_start(sb, acr->base.boot_falcon);
+	nvkm_debug(subdev, "PMU started\n");
+
+	return 0;
+}
+
+/**
+ * acr_r352_reset_nopmu - dummy reset method when no PMU firmware is loaded
+ *
+ * Reset is done by re-executing secure boot from scratch, with lazy bootstrap
+ * disabled. This has the effect of making all managed falcons ready-to-run.
+ */
+static int
+acr_r352_reset_nopmu(struct acr_r352 *acr, struct nvkm_secboot *sb,
+		     enum nvkm_falconidx falcon)
+{
+	int ret;
+
+	/*
+	 * Perform secure boot each time we are called on FECS. Since only FECS
+	 * and GPCCS are managed and started together, this ought to be safe.
+	 */
+	if (falcon != NVKM_FALCON_FECS)
+		goto end;
+
+	ret = acr_r352_shutdown(acr, sb);
+	if (ret)
+		return ret;
+
+	ret = acr_r352_bootstrap(acr, sb);
+	if (ret)
+		return ret;
+
+end:
+	acr->falcon_state[falcon] = RESET;
 	return 0;
 }
 
@@ -813,29 +859,30 @@ acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
 	       enum nvkm_falconidx falcon)
 {
 	struct acr_r352 *acr = acr_r352(_acr);
+	struct nvkm_pmu *pmu = sb->subdev.device->pmu;
+	const char *fname = nvkm_falcon_name[falcon];
 	int ret;
 
+	/* Not self-managed? Redo secure boot entirely */
+	if (!nvkm_secboot_is_managed(sb, _acr->boot_falcon))
+		return acr_r352_reset_nopmu(acr, sb, falcon);
+
 	/*
-	 * Dummy GM200 implementation: perform secure boot each time we are
-	 * called on FECS. Since only FECS and GPCCS are managed and started
-	 * together, this ought to be safe.
-	 *
-	 * Once we have proper PMU firmware and support, this will be changed
-	 * to a proper call to the PMU method.
+	 * Otherwise ensure secure boot is done, and command the PMU to reset
+	 * the desired falcon.
 	 */
-	if (falcon != NVKM_FALCON_FECS)
-		goto end;
-
-	ret = acr_r352_shutdown(acr, sb);
+	ret = acr_r352_bootstrap(acr, sb);
 	if (ret)
 		return ret;
 
-	acr_r352_bootstrap(acr, sb);
-	if (ret)
+	nvkm_debug(&sb->subdev, "resetting %s falcon\n", fname);
+	ret = nvkm_pmu_acr_boot_falcon(pmu, falcon);
+	if (ret) {
+		nvkm_error(&sb->subdev, "cannot boot %s falcon\n", fname);
 		return ret;
+	}
+	nvkm_debug(&sb->subdev, "falcon %s reset\n", fname);
 
-end:
-	acr->falcon_state[falcon] = RESET;
 	return 0;
 }
 
@@ -854,6 +901,9 @@ acr_r352_start(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
 	case NVKM_FALCON_GPCCS:
 		base = 0x41a000;
 		break;
+	case NVKM_FALCON_PMU:
+		base = 0x10a000;
+		break;
 	default:
 		nvkm_error(subdev, "cannot start unhandled falcon!\n");
 		return -EINVAL;
@@ -940,6 +990,23 @@ acr_r352_new_(const struct acr_r352_func *func, enum nvkm_falconidx boot_falcon,
 	acr->base.func = &acr_r352_base_func;
 	acr->func = func;
 
+	/*
+	 * If we have a PMU firmware, let it manage the bootstrap of other
+	 * falcons.
+	 */
+	if (func->ls_func[NVKM_FALCON_PMU] &&
+	    (managed_falcons & BIT(NVKM_FALCON_PMU))) {
+		int i;
+
+		for (i = 0; i < NVKM_FALCON_END; i++) {
+			if (i == NVKM_FALCON_PMU)
+				continue;
+
+			if (func->ls_func[i])
+				acr->lazy_bootstrap |= BIT(i);
+		}
+	}
+
 	return &acr->base;
 }
 
-- 
git-series 0.8.10


More information about the Nouveau mailing list