summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2016-11-18 17:47:08 +0900
committerBen Skeggs <bskeggs@redhat.com>2017-03-07 17:05:12 +1000
commit7775d0dcb215ce0eb639940d201fb9f557823bd7 (patch)
treef668fbb1293e8b3635034f303986a5b2b0d12fdf /drivers/gpu/drm/nouveau/nvkm/subdev
parentbb5ec9c9dd1cc71bbae37a31229d72ffab9b6df4 (diff)
downloadop-kernel-dev-7775d0dcb215ce0eb639940d201fb9f557823bd7.zip
op-kernel-dev-7775d0dcb215ce0eb639940d201fb9f557823bd7.tar.gz
drm/nouveau/secboot: support optional falcons
PMU support has been enabled for r352 ACR, but it must remain optional if we want to preserve existing user-space that do not include it. Allow ACR to be instanciated with a list of optional LS falcons, that will not produce a fatal error if their firmware is not loaded. Also change the secure boot bootstrap logic to be able to fall back to legacy behavior if it turns out the boot falcon's LS firmware cannot be loaded. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev')
-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 58eb20a..580036d 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 a5d8814..40c6568 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;
}
OpenPOWER on IntegriCloud