drm/amdgpu: correct rlc save restore list initialization for v2_1
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / amd / amdgpu / gfx_v9_0.c
index a691534..5e92002 100644 (file)
@@ -648,7 +648,10 @@ static int gfx_v9_0_init_microcode(struct amdgpu_device *adev)
                adev->firmware.fw_size +=
                        ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
 
-               if (adev->gfx.rlc.is_rlc_v2_1) {
+               if (adev->gfx.rlc.is_rlc_v2_1 &&
+                   adev->gfx.rlc.save_restore_list_cntl_size_bytes &&
+                   adev->gfx.rlc.save_restore_list_gpm_size_bytes &&
+                   adev->gfx.rlc.save_restore_list_srm_size_bytes) {
                        info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL];
                        info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL;
                        info->fw = adev->gfx.rlc_fw;
@@ -943,6 +946,7 @@ static int gfx_v9_0_rlc_init(struct amdgpu_device *adev)
                dst_ptr = adev->gfx.rlc.cs_ptr;
                gfx_v9_0_get_csb_buffer(adev, dst_ptr);
                amdgpu_bo_kunmap(adev->gfx.rlc.clear_state_obj);
+               amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
                amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
        }
 
@@ -971,6 +975,39 @@ static int gfx_v9_0_rlc_init(struct amdgpu_device *adev)
        return 0;
 }
 
+static int gfx_v9_0_csb_vram_pin(struct amdgpu_device *adev)
+{
+       int r;
+
+       r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+       if (unlikely(r != 0))
+               return r;
+
+       r = amdgpu_bo_pin(adev->gfx.rlc.clear_state_obj,
+                       AMDGPU_GEM_DOMAIN_VRAM);
+       if (!r)
+               adev->gfx.rlc.clear_state_gpu_addr =
+                       amdgpu_bo_gpu_offset(adev->gfx.rlc.clear_state_obj);
+
+       amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+
+       return r;
+}
+
+static void gfx_v9_0_csb_vram_unpin(struct amdgpu_device *adev)
+{
+       int r;
+
+       if (!adev->gfx.rlc.clear_state_obj)
+               return;
+
+       r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
+       if (likely(r == 0)) {
+               amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
+               amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+       }
+}
+
 static void gfx_v9_0_mec_fini(struct amdgpu_device *adev)
 {
        amdgpu_bo_free_kernel(&adev->gfx.mec.hpd_eop_obj, NULL, NULL);
@@ -2148,8 +2185,16 @@ static void gfx_v9_0_enable_gfx_dynamic_mg_power_gating(struct amdgpu_device *ad
 
 static void gfx_v9_0_init_pg(struct amdgpu_device *adev)
 {
-       if (!adev->gfx.rlc.is_rlc_v2_1)
-               return;
+       gfx_v9_0_init_csb(adev);
+
+       /*
+        * Rlc save restore list is workable since v2_1.
+        * And it's needed by gfxoff feature.
+        */
+       if (adev->gfx.rlc.is_rlc_v2_1) {
+               gfx_v9_1_init_rlc_save_restore_list(adev);
+               gfx_v9_0_enable_save_restore_machine(adev);
+       }
 
        if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG |
                              AMD_PG_SUPPORT_GFX_SMG |
@@ -2157,10 +2202,6 @@ static void gfx_v9_0_init_pg(struct amdgpu_device *adev)
                              AMD_PG_SUPPORT_CP |
                              AMD_PG_SUPPORT_GDS |
                              AMD_PG_SUPPORT_RLC_SMU_HS)) {
-               gfx_v9_0_init_csb(adev);
-               gfx_v9_1_init_rlc_save_restore_list(adev);
-               gfx_v9_0_enable_save_restore_machine(adev);
-
                WREG32(mmRLC_JUMP_TABLE_RESTORE,
                       adev->gfx.rlc.cp_table_gpu_addr >> 8);
                gfx_v9_0_init_gfx_power_gating(adev);
@@ -3116,6 +3157,10 @@ static int gfx_v9_0_hw_init(void *handle)
 
        gfx_v9_0_gpu_init(adev);
 
+       r = gfx_v9_0_csb_vram_pin(adev);
+       if (r)
+               return r;
+
        r = gfx_v9_0_rlc_resume(adev);
        if (r)
                return r;
@@ -3224,6 +3269,8 @@ static int gfx_v9_0_hw_fini(void *handle)
        gfx_v9_0_cp_enable(adev, false);
        gfx_v9_0_rlc_stop(adev);
 
+       gfx_v9_0_csb_vram_unpin(adev);
+
        return 0;
 }
 
@@ -3714,6 +3761,10 @@ static int gfx_v9_0_set_powergating_state(void *handle,
 
                /* update mgcg state */
                gfx_v9_0_update_gfx_mg_power_gating(adev, enable);
+
+               /* set gfx off through smu */
+               if (enable && adev->powerplay.pp_funcs->set_powergating_by_smu)
+                       amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, true);
                break;
        default:
                break;