drm/amd/powerplay: properly set mp1 state for SW SMU suspend/reset routine
authorEvan Quan <evan.quan@amd.com>
Wed, 11 Sep 2019 11:35:45 +0000 (19:35 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 16 Sep 2019 15:10:58 +0000 (10:10 -0500)
Set mp1 state properly for SW SMU suspend/reset routine.

Signed-off-by: Evan Quan <evan.quan@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_device.c
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h

index 1affaa4ee1eecc78a5351777e2e737fa60bf4942..d3524f19d79a45dc6f57c0841b6195d66c25c833 100644 (file)
@@ -2233,17 +2233,17 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
                /* handle putting the SMC in the appropriate state */
                if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
                        if (is_support_sw_smu(adev)) {
-                               /* todo */
+                               r = smu_set_mp1_state(&adev->smu, adev->mp1_state);
                        } else if (adev->powerplay.pp_funcs &&
                                           adev->powerplay.pp_funcs->set_mp1_state) {
                                r = adev->powerplay.pp_funcs->set_mp1_state(
                                        adev->powerplay.pp_handle,
                                        adev->mp1_state);
-                               if (r) {
-                                       DRM_ERROR("SMC failed to set mp1 state %d, %d\n",
-                                                 adev->mp1_state, r);
-                                       return r;
-                               }
+                       }
+                       if (r) {
+                               DRM_ERROR("SMC failed to set mp1 state %d, %d\n",
+                                         adev->mp1_state, r);
+                               return r;
                        }
                }
 
index 03896e667c1425474cb8c6f7444e35fdac5a0457..be01b88db3ec7444ff453a87cf70dbec1875ae8f 100644 (file)
@@ -1788,6 +1788,46 @@ int smu_force_clk_levels(struct smu_context *smu,
        return ret;
 }
 
+int smu_set_mp1_state(struct smu_context *smu,
+                     enum pp_mp1_state mp1_state)
+{
+       uint16_t msg;
+       int ret;
+
+       /*
+        * The SMC is not fully ready. That may be
+        * expected as the IP may be masked.
+        * So, just return without error.
+        */
+       if (!smu->pm_enabled)
+               return 0;
+
+       switch (mp1_state) {
+       case PP_MP1_STATE_SHUTDOWN:
+               msg = SMU_MSG_PrepareMp1ForShutdown;
+               break;
+       case PP_MP1_STATE_UNLOAD:
+               msg = SMU_MSG_PrepareMp1ForUnload;
+               break;
+       case PP_MP1_STATE_RESET:
+               msg = SMU_MSG_PrepareMp1ForReset;
+               break;
+       case PP_MP1_STATE_NONE:
+       default:
+               return 0;
+       }
+
+       /* some asics may not support those messages */
+       if (smu_msg_get_index(smu, msg) < 0)
+               return 0;
+
+       ret = smu_send_smc_msg(smu, msg);
+       if (ret)
+               pr_err("[PrepareMp1] Failed!\n");
+
+       return ret;
+}
+
 const struct amd_ip_funcs smu_ip_funcs = {
        .name = "smu",
        .early_init = smu_early_init,
index 88f1ee9a2f1d9e525f1f1461a7abb5efce209538..45da21dc2356c3aaf8e8de1ebaa3f89e1a47f35b 100644 (file)
@@ -836,5 +836,7 @@ int smu_sys_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask);
 int smu_force_clk_levels(struct smu_context *smu,
                         enum smu_clk_type clk_type,
                         uint32_t mask);
+int smu_set_mp1_state(struct smu_context *smu,
+                     enum pp_mp1_state mp1_state);
 
 #endif