aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c62
2 files changed, 39 insertions, 25 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h
index 58eb20a69e9c..580036d623b2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h
@@ -48,6 +48,7 @@ struct nvkm_acr_func {
*
* @boot_falcon: ID of the falcon that will perform secure boot
* @managed_falcons: bitfield of falcons managed by this ACR
+ * @optional_falcons: bitfield of falcons we can live without
* @start_address: virtual start address of the HS bootloader
*/
struct nvkm_acr {
@@ -56,6 +57,7 @@ struct nvkm_acr {
enum nvkm_secboot_falcon boot_falcon;
unsigned long managed_falcons;
+ unsigned long optional_falcons;
u32 start_address;
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
index a5d881438c1f..40c6568bfc31 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
@@ -503,6 +503,12 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
img = acr->func->ls_ucode_img_load(acr, falcon_id);
if (IS_ERR(img)) {
+ if (acr->base.optional_falcons & BIT(falcon_id)) {
+ managed_falcons &= ~BIT(falcon_id);
+ nvkm_info(subdev, "skipping %s falcon...\n",
+ nvkm_secboot_falcon_name[falcon_id]);
+ continue;
+ }
ret = PTR_ERR(img);
goto cleanup;
}
@@ -511,6 +517,24 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
managed_count++;
}
+ /* Commit the actual list of falcons we will manage from now on */
+ acr->base.managed_falcons = managed_falcons;
+
+ /*
+ * If the boot falcon has a firmare, let it manage the bootstrap of other
+ * falcons.
+ */
+ if (acr->func->ls_func[acr->base.boot_falcon] &&
+ (managed_falcons & BIT(acr->base.boot_falcon))) {
+ for_each_set_bit(falcon_id, &managed_falcons,
+ NVKM_SECBOOT_FALCON_END) {
+ if (falcon_id == acr->base.boot_falcon)
+ continue;
+
+ acr->lazy_bootstrap |= BIT(falcon_id);
+ }
+ }
+
/*
* Fill the WPR and LSF headers with the right offsets and compute
* required WPR size
@@ -948,20 +972,25 @@ acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
struct acr_r352 *acr = acr_r352(_acr);
struct nvkm_pmu *pmu = sb->subdev.device->pmu;
const char *fname = nvkm_secboot_falcon_name[falcon];
+ bool wpr_already_set = sb->wpr_set;
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);
-
- /*
- * Otherwise ensure secure boot is done, and command the PMU to reset
- * the desired falcon.
- */
+ /* Make sure secure boot is performed */
ret = acr_r352_bootstrap(acr, sb);
if (ret)
return ret;
+ /* No PMU interface? */
+ if (!nvkm_secboot_is_managed(sb, _acr->boot_falcon)) {
+ /* Redo secure boot entirely if it was already done */
+ if (wpr_already_set)
+ return acr_r352_reset_nopmu(acr, sb, falcon);
+ /* Else return the result of the initial invokation */
+ else
+ return ret;
+ }
+
+ /* Otherwise just ask the PMU to reset the falcon */
nvkm_debug(&sb->subdev, "resetting %s falcon\n", fname);
ret = nvkm_msgqueue_acr_boot_falcon(pmu->queue, falcon);
if (ret) {
@@ -1136,23 +1165,6 @@ acr_r352_new_(const struct acr_r352_func *func,
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_SECBOOT_FALCON_PMU] &&
- (managed_falcons & BIT(NVKM_SECBOOT_FALCON_PMU))) {
- int i;
-
- for (i = 0; i < NVKM_SECBOOT_FALCON_END; i++) {
- if (i == NVKM_SECBOOT_FALCON_PMU)
- continue;
-
- if (func->ls_func[i])
- acr->lazy_bootstrap |= BIT(i);
- }
- }
-
return &acr->base;
}