drm/amdgpu:properly fix some JumpTable issues
authorMonk Liu <Monk.Liu@amd.com>
Tue, 27 Sep 2016 08:39:58 +0000 (16:39 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 25 Oct 2016 18:38:23 +0000 (14:38 -0400)
we found some MEC ucode leads to IB test fail or even
ring test fail if Jump Table of it is not start in
FW bo with page aligned address, fixed by always make
JT address page aligned.

we don't need to patch JT2 for MEC2, because for VI,
MEC2 is a copy of MEC1, thus when converting fw_type
for MEC_JT2 we just return MEC1,hw can use the same
JT for both MEC1 & MEC2.

above two change fixed some ring/ib test failure issue
for some version of MEC ucode.

Signed-off-by: Frank Min <Frank.Min@amd.com>
Signed-off-by: Monk Liu <Monk.Liu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c

index e6b1bf3dc29204fdd5a82f5ec745b87243184609..34049d67a0d82a3d40047a912bde9597c36fa3b1 100644 (file)
@@ -687,11 +687,14 @@ static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
                result = AMDGPU_UCODE_ID_CP_MEC1;
                break;
        case CGS_UCODE_ID_CP_MEC_JT2:
-               if (adev->asic_type == CHIP_TONGA || adev->asic_type == CHIP_POLARIS11
-                 || adev->asic_type == CHIP_POLARIS10)
-                       result = AMDGPU_UCODE_ID_CP_MEC2;
-               else
+               /* for VI. JT2 should be the same as JT1, because:
+                       1, MEC2 and MEC1 use exactly same FW.
+                       2, JT2 is not pached but JT1 is.
+               */
+               if (adev->asic_type >= CHIP_TOPAZ)
                        result = AMDGPU_UCODE_ID_CP_MEC1;
+               else
+                       result = AMDGPU_UCODE_ID_CP_MEC2;
                break;
        case CGS_UCODE_ID_RLC_G:
                result = AMDGPU_UCODE_ID_RLC_G;
@@ -781,12 +784,18 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
 
                if ((type == CGS_UCODE_ID_CP_MEC_JT1) ||
                    (type == CGS_UCODE_ID_CP_MEC_JT2)) {
-                       gpu_addr += le32_to_cpu(header->jt_offset) << 2;
+                       gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE);
                        data_size = le32_to_cpu(header->jt_size) << 2;
                }
-               info->mc_addr = gpu_addr;
+
+               info->kptr = ucode->kaddr;
                info->image_size = data_size;
+               info->mc_addr = gpu_addr;
                info->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
+
+               if (CGS_UCODE_ID_CP_MEC == type)
+                       info->image_size = (header->jt_offset) << 2;
+
                info->fw_version = amdgpu_get_firmware_version(cgs_device, type);
                info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version);
        } else {
index 5d3f6ca742a4aa6ebfd80d0f085951e0d7031ef7..0f0b38191fac899f90592c107fca8eee826b5448 100644 (file)
@@ -239,6 +239,31 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_firmware_info *ucode,
        return 0;
 }
 
+static int amdgpu_ucode_patch_jt(struct amdgpu_firmware_info *ucode,
+                               uint64_t mc_addr, void *kptr)
+{
+       const struct gfx_firmware_header_v1_0 *header = NULL;
+       const struct common_firmware_header *comm_hdr = NULL;
+       uint8_t* src_addr = NULL;
+       uint8_t* dst_addr = NULL;
+
+       if (NULL == ucode->fw)
+               return 0;
+
+       comm_hdr = (const struct common_firmware_header *)ucode->fw->data;
+       header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
+       dst_addr = ucode->kaddr +
+                          ALIGN(le32_to_cpu(comm_hdr->ucode_size_bytes),
+                          PAGE_SIZE);
+       src_addr = (uint8_t *)ucode->fw->data +
+                          le32_to_cpu(comm_hdr->ucode_array_offset_bytes) +
+                          (le32_to_cpu(header->jt_offset) * 4);
+       memcpy(dst_addr, src_addr, le32_to_cpu(header->jt_size) * 4);
+
+       return 0;
+}
+
+
 int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
 {
        struct amdgpu_bo **bo = &adev->firmware.fw_buf;
@@ -284,6 +309,13 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
                        header = (const struct common_firmware_header *)ucode->fw->data;
                        amdgpu_ucode_init_single_fw(ucode, fw_mc_addr + fw_offset,
                                                    fw_buf_ptr + fw_offset);
+                       if (i == AMDGPU_UCODE_ID_CP_MEC1) {
+                               const struct gfx_firmware_header_v1_0 *cp_hdr;
+                               cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
+                               amdgpu_ucode_patch_jt(ucode, fw_mc_addr + fw_offset,
+                                                   fw_buf_ptr + fw_offset);
+                               fw_offset += ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE);
+                       }
                        fw_offset += ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
                }
        }
index 45d194a58c57ab3a737a979cddaa6462036995f0..0637349f9b656e865638e54b4ba2a52e808c96ea 100644 (file)
@@ -1058,6 +1058,11 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
                adev->firmware.fw_size +=
                        ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
 
+               /* we need account JT in */
+               cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
+               adev->firmware.fw_size +=
+                       ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE);
+
                if (amdgpu_sriov_vf(adev)) {
                        info = &adev->firmware.ucode[AMDGPU_UCODE_ID_STORAGE];
                        info->ucode_id = AMDGPU_UCODE_ID_STORAGE;