drm/nouveau/secboot: let callers interpret return value of blobs
authorAlexandre Courbot <acourbot@nvidia.com>
Thu, 23 Feb 2017 04:05:27 +0000 (13:05 +0900)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 7 Mar 2017 07:05:13 +0000 (17:05 +1000)
Since the HS blobs are provided and signed by NVIDIA, we cannot expect
always-consistent behavior. In this case, on GP10x the unload blob may
return 0x1d even though things have run perfectly well. This behavior
has been confirmed by NVIDIA.

So let the callers of the run_blob() hook receive the blob return's
value (a positive integer) and decide what it means. This allows us to
workaround the 0x1d code instead of issuing an error.

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

index 613ed363a6bf34d364fe9c9426a3c39e12d61162..413275d0594bcbcb06d3f0e3d32c7de65631f6a4 100644 (file)
@@ -865,17 +865,26 @@ acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon,
 static int
 acr_r352_shutdown(struct acr_r352 *acr, struct nvkm_secboot *sb)
 {
+       struct nvkm_subdev *subdev = &sb->subdev;
        int i;
 
        /* Run the unload blob to unprotect the WPR region */
        if (acr->unload_blob && sb->wpr_set) {
                int ret;
 
-               nvkm_debug(&sb->subdev, "running HS unload blob\n");
+               nvkm_debug(subdev, "running HS unload blob\n");
                ret = sb->func->run_blob(sb, acr->unload_blob, sb->halt_falcon);
-               if (ret)
+               if (ret < 0)
                        return ret;
-               nvkm_debug(&sb->subdev, "HS unload blob completed\n");
+               /*
+                * Unload blob will return this error code - it is not an error
+                * and the expected behavior on RM as well
+                */
+               if (ret && ret != 0x1d) {
+                       nvkm_error(subdev, "HS unload failed, ret 0x%08x", ret);
+                       return -EINVAL;
+               }
+               nvkm_debug(subdev, "HS unload blob completed\n");
        }
 
        for (i = 0; i < NVKM_SECBOOT_FALCON_END; i++)
@@ -938,11 +947,13 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb)
        /* clear halt interrupt */
        nvkm_falcon_clear_interrupt(sb->boot_falcon, 0x10);
        sb->wpr_set = acr_r352_wpr_is_set(acr, sb);
-       if (ret)
+       if (ret < 0) {
                return ret;
+       } else if (ret > 0) {
+               nvkm_error(subdev, "HS load failed, ret 0x%08x", ret);
+               return -EINVAL;
+       }
        nvkm_debug(subdev, "HS load blob completed\n");
-       if (ret)
-               return ret;
        /* WPR must be set at this point */
        if (!sb->wpr_set) {
                nvkm_error(subdev, "ACR blob completed but WPR not set!\n");
index 2c8dec9fda9a686c9d24959a85107a996c04faf9..73ca1203281d65737062fa46e65c2aeaa79498c2 100644 (file)
@@ -80,13 +80,11 @@ gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob,
        if (ret)
                goto end;
 
-       /* If mailbox register contains an error code, then ACR has failed */
+       /*
+        * The mailbox register contains the (positive) error code - return this
+        * to the caller
+        */
        ret = nvkm_falcon_rd32(falcon, 0x040);
-       if (ret) {
-               nvkm_error(subdev, "HS blob failed, ret 0x%08x", ret);
-               ret = -EINVAL;
-               goto end;
-       }
 
 end:
        /* Reenable interrupts */