drm/nouveau/secboot: support for different load and unload falcons
authorAlexandre Courbot <acourbot@nvidia.com>
Thu, 26 Jan 2017 08:18:49 +0000 (17:18 +0900)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 7 Mar 2017 07:05:13 +0000 (17:05 +1000)
On some secure boot instances (e.g. gp10x) the load and unload blobs do
not run on the same falcon. Support this case by introducing a new
member to the ACR structure and making related functions take the falcon
to use as an argument instead of assuming the boot falcon is to be used.

The rule is that the load blob can be run on either the SEC or PMU
falcons, but the unload blob must be always run on PMU.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/secboot.h
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h

index eb46fbf26df68f37779cce40ca4b733b24672033..03da24e2c22943a08d46cfa23829bc68026d7003 100644 (file)
@@ -45,6 +45,7 @@ struct nvkm_secboot {
        struct nvkm_acr *acr;
        struct nvkm_subdev subdev;
        struct nvkm_falcon *boot_falcon;
+       struct nvkm_falcon *halt_falcon;
 
        u64 wpr_addr;
        u32 wpr_size;
index 9738340d33a16ed9570e835453d485b8ae5230a9..15aa443658ad232c9cc982222d5a0954abdda500 100644 (file)
@@ -37,7 +37,7 @@ struct nvkm_acr_func {
        void (*dtor)(struct nvkm_acr *);
        int (*oneinit)(struct nvkm_acr *, struct nvkm_secboot *);
        int (*fini)(struct nvkm_acr *, struct nvkm_secboot *, bool);
-       int (*load)(struct nvkm_acr *, struct nvkm_secboot *,
+       int (*load)(struct nvkm_acr *, struct nvkm_falcon *,
                    struct nvkm_gpuobj *, u64);
        int (*reset)(struct nvkm_acr *, struct nvkm_secboot *,
                     enum nvkm_secboot_falcon);
index 0b563bc9daf833f5d06b36e4c636b300ccc8b295..613ed363a6bf34d364fe9c9426a3c39e12d61162 100644 (file)
@@ -816,11 +816,10 @@ acr_r352_load_blobs(struct acr_r352 *acr, struct nvkm_secboot *sb)
  * Returns the start address to use, or a negative error value.
  */
 static int
-acr_r352_load(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
+acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon,
              struct nvkm_gpuobj *blob, u64 offset)
 {
        struct acr_r352 *acr = acr_r352(_acr);
-       struct nvkm_falcon *falcon = sb->boot_falcon;
        struct fw_bin_header *hdr = acr->hsbl_blob;
        struct fw_bl_desc *hsbl_desc = acr->hsbl_blob + hdr->header_offset;
        void *blob_data = acr->hsbl_blob + hdr->data_offset;
@@ -873,7 +872,7 @@ acr_r352_shutdown(struct acr_r352 *acr, struct nvkm_secboot *sb)
                int ret;
 
                nvkm_debug(&sb->subdev, "running HS unload blob\n");
-               ret = sb->func->run_blob(sb, acr->unload_blob);
+               ret = sb->func->run_blob(sb, acr->unload_blob, sb->halt_falcon);
                if (ret)
                        return ret;
                nvkm_debug(&sb->subdev, "HS unload blob completed\n");
@@ -935,7 +934,7 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb)
                return ret;
 
        nvkm_debug(subdev, "running HS load blob\n");
-       ret = sb->func->run_blob(sb, acr->load_blob);
+       ret = sb->func->run_blob(sb, acr->load_blob, sb->boot_falcon);
        /* clear halt interrupt */
        nvkm_falcon_clear_interrupt(sb->boot_falcon, 0x10);
        sb->wpr_set = acr_r352_wpr_is_set(acr, sb);
@@ -967,9 +966,10 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb)
        nvkm_falcon_wr32(sb->boot_falcon, 0x10, 0xff);
        nvkm_mc_intr_mask(subdev->device, sb->boot_falcon->owner->index, true);
 
-       /* Start PMU */
+       /* Start LS firmware on boot falcon */
        nvkm_falcon_start(sb->boot_falcon);
-       nvkm_debug(subdev, "PMU started\n");
+       nvkm_debug(subdev, "%s started\n",
+                  nvkm_secboot_falcon_name[acr->base.boot_falcon]);
 
        return 0;
 }
index faf94a457670031cfb097d80ff5f37dc65cd3e9a..5c11e8c5096483d21d31314a99e3041f850f0625 100644 (file)
@@ -133,12 +133,13 @@ nvkm_secboot_oneinit(struct nvkm_subdev *subdev)
 
        switch (sb->acr->boot_falcon) {
        case NVKM_SECBOOT_FALCON_PMU:
-               sb->boot_falcon = subdev->device->pmu->falcon;
+               sb->halt_falcon = sb->boot_falcon = subdev->device->pmu->falcon;
                break;
        case NVKM_SECBOOT_FALCON_SEC2:
                /* we must keep SEC2 alive forever since ACR will run on it */
                nvkm_engine_ref(&subdev->device->sec2->engine);
                sb->boot_falcon = subdev->device->sec2->falcon;
+               sb->halt_falcon = subdev->device->pmu->falcon;
                break;
        default:
                nvkm_error(subdev, "Unmanaged boot falcon %s!\n",
index b21e91778f86077545829c6394ed2798c353acff..2c8dec9fda9a686c9d24959a85107a996c04faf9 100644 (file)
  *
  */
 int
-gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob)
+gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob,
+                      struct nvkm_falcon *falcon)
 {
        struct gm200_secboot *gsb = gm200_secboot(sb);
        struct nvkm_subdev *subdev = &gsb->base.subdev;
-       struct nvkm_falcon *falcon = gsb->base.boot_falcon;
        struct nvkm_vma vma;
        u32 start_address;
        int ret;
@@ -61,7 +61,7 @@ gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob)
        nvkm_falcon_bind_context(falcon, gsb->inst);
 
        /* Load the HS bootloader into the falcon's IMEM/DMEM */
-       ret = sb->acr->func->load(sb->acr, &gsb->base, blob, vma.offset);
+       ret = sb->acr->func->load(sb->acr, falcon, blob, vma.offset);
        if (ret < 0)
                goto end;
 
@@ -83,7 +83,7 @@ gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob)
        /* If mailbox register contains an error code, then ACR has failed */
        ret = nvkm_falcon_rd32(falcon, 0x040);
        if (ret) {
-               nvkm_error(subdev, "ACR boot failed, ret 0x%08x", ret);
+               nvkm_error(subdev, "HS blob failed, ret 0x%08x", ret);
                ret = -EINVAL;
                goto end;
        }
index 45adf1a3bc206c6bc456bcb13e01d748dab160c7..6dc9fc384f244ea39d5c823cbe673d7b819a0e85 100644 (file)
@@ -38,6 +38,7 @@ struct gm200_secboot {
 int gm200_secboot_oneinit(struct nvkm_secboot *);
 int gm200_secboot_fini(struct nvkm_secboot *, bool);
 void *gm200_secboot_dtor(struct nvkm_secboot *);
-int gm200_secboot_run_blob(struct nvkm_secboot *, struct nvkm_gpuobj *);
+int gm200_secboot_run_blob(struct nvkm_secboot *, struct nvkm_gpuobj *,
+                          struct nvkm_falcon *);
 
 #endif
index 430b88ec74cf68ab575e4cc058e60796ad43bb24..885e919a87205a7df01a141c5499af1344ae5c98 100644 (file)
@@ -30,7 +30,8 @@ struct nvkm_secboot_func {
        int (*oneinit)(struct nvkm_secboot *);
        int (*fini)(struct nvkm_secboot *, bool suspend);
        void *(*dtor)(struct nvkm_secboot *);
-       int (*run_blob)(struct nvkm_secboot *, struct nvkm_gpuobj *);
+       int (*run_blob)(struct nvkm_secboot *, struct nvkm_gpuobj *,
+                       struct nvkm_falcon *);
 };
 
 int nvkm_secboot_ctor(const struct nvkm_secboot_func *, struct nvkm_acr *,