drm/nouveau/secboot: add shadow blob argument
authorAlexandre Courbot <acourbot@nvidia.com>
Tue, 15 Nov 2016 07:28:37 +0000 (16:28 +0900)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 7 Mar 2017 07:05:13 +0000 (17:05 +1000)
ACR firmware from r364 on need a shadow region for the ACR to copy the
WPR region into. Add a flag to indicate that a shadow region is required
and manage memory allocations accordingly.

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/acr_r352.h

index 9e64b7c8b0b24baab2ce3d9fc5ebaa42b651c089..814f9f2a17ef89c30004cd3b19d84cf1a8ba6d64 100644 (file)
@@ -491,7 +491,7 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
        struct ls_ucode_img *img, *t;
        unsigned long managed_falcons = acr->base.managed_falcons;
        int managed_count = 0;
-       u32 image_wpr_size;
+       u32 image_wpr_size, ls_blob_size;
        int falcon_id;
        int ret;
 
@@ -542,8 +542,17 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
        image_wpr_size = acr->func->ls_fill_headers(acr, &imgs);
        image_wpr_size = ALIGN(image_wpr_size, WPR_ALIGNMENT);
 
+       ls_blob_size = image_wpr_size;
+
+       /*
+        * If we need a shadow area, allocate twice the size and use the
+        * upper half as WPR
+        */
+       if (wpr_size == 0 && acr->func->shadow_blob)
+               ls_blob_size *= 2;
+
        /* Allocate GPU object that will contain the WPR region */
-       ret = nvkm_gpuobj_new(subdev->device, image_wpr_size, WPR_ALIGNMENT,
+       ret = nvkm_gpuobj_new(subdev->device, ls_blob_size, WPR_ALIGNMENT,
                              false, NULL, &acr->ls_blob);
        if (ret)
                goto cleanup;
@@ -554,6 +563,9 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
        /* If WPR address and size are not fixed, set them to fit the LS blob */
        if (wpr_size == 0) {
                wpr_addr = acr->ls_blob->addr;
+               if (acr->func->shadow_blob)
+                       wpr_addr += acr->ls_blob->size / 2;
+
                wpr_size = image_wpr_size;
        /*
         * But if the WPR region is set by the bootloader, it is illegal for
index 9ca23c1e3aa96ab0164d913637d4d87c10d3bf08..1b9f5c825c8a205cd469f9b207dc49e79f147031 100644 (file)
@@ -104,6 +104,7 @@ struct acr_r352_func {
                                    u64);
        void (*fixup_hs_desc)(struct acr_r352 *, struct nvkm_secboot *, void *);
        u32 hs_bl_desc_size;
+       bool shadow_blob;
 
        struct ls_ucode_img *(*ls_ucode_img_load)(const struct acr_r352 *,
                                                  enum nvkm_secboot_falcon);