diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 62 |
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; } |