]> Git Repo - linux.git/commitdiff
drm/amd/pm: correct the workload setting
authorKenneth Feng <[email protected]>
Wed, 30 Oct 2024 05:22:44 +0000 (13:22 +0800)
committerAlex Deucher <[email protected]>
Mon, 4 Nov 2024 17:06:23 +0000 (12:06 -0500)
Correct the workload setting in order not to mix the setting
with the end user. Update the workload mask accordingly.

v2: changes as below:
1. the end user can not erase the workload from driver except default workload.
2. always shows the real highest priority workoad to the end user.
3. the real workload mask is combined with driver workload mask and end user workload mask.

v3: apply this to the other ASICs as well.
v4: simplify the code
v5: refine the code based on the review comments.

Signed-off-by: Kenneth Feng <[email protected]>
Acked-by: Alex Deucher <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
12 files changed:
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h

index ba97070acf9f71c844bb091bf464f05cbe914cd8..aa7c57b587650eb8e1bc698d21fcbd6fb7c4ac1f 100644 (file)
@@ -1261,26 +1261,33 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block)
        smu->watermarks_bitmap = 0;
        smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
        smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       smu->user_dpm_profile.user_workload_mask = 0;
 
        atomic_set(&smu->smu_power.power_gate.vcn_gated, 1);
        atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1);
        atomic_set(&smu->smu_power.power_gate.vpe_gated, 1);
        atomic_set(&smu->smu_power.power_gate.umsch_mm_gated, 1);
 
-       smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
-       smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
-       smu->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
-       smu->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
-       smu->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
-       smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
-       smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
+       smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
+       smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
+       smu->workload_priority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
+       smu->workload_priority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
+       smu->workload_priority[PP_SMC_POWER_PROFILE_VR] = 4;
+       smu->workload_priority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
+       smu->workload_priority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
 
        if (smu->is_apu ||
-           !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D))
-               smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
-       else
-               smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
+           !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) {
+               smu->driver_workload_mask =
+                       1 << smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+       } else {
+               smu->driver_workload_mask =
+                       1 << smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
+               smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+       }
 
+       smu->workload_mask = smu->driver_workload_mask |
+                                                       smu->user_dpm_profile.user_workload_mask;
        smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
        smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
        smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
@@ -2355,17 +2362,20 @@ static int smu_switch_power_profile(void *handle,
                return -EINVAL;
 
        if (!en) {
-               smu->workload_mask &= ~(1 << smu->workload_prority[type]);
+               smu->driver_workload_mask &= ~(1 << smu->workload_priority[type]);
                index = fls(smu->workload_mask);
                index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
                workload[0] = smu->workload_setting[index];
        } else {
-               smu->workload_mask |= (1 << smu->workload_prority[type]);
+               smu->driver_workload_mask |= (1 << smu->workload_priority[type]);
                index = fls(smu->workload_mask);
                index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
                workload[0] = smu->workload_setting[index];
        }
 
+       smu->workload_mask = smu->driver_workload_mask |
+                                                smu->user_dpm_profile.user_workload_mask;
+
        if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
                smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
                smu_bump_power_profile_mode(smu, workload, 0);
@@ -3056,12 +3066,23 @@ static int smu_set_power_profile_mode(void *handle,
                                      uint32_t param_size)
 {
        struct smu_context *smu = handle;
+       int ret;
 
        if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled ||
            !smu->ppt_funcs->set_power_profile_mode)
                return -EOPNOTSUPP;
 
-       return smu_bump_power_profile_mode(smu, param, param_size);
+       if (smu->user_dpm_profile.user_workload_mask &
+          (1 << smu->workload_priority[param[param_size]]))
+          return 0;
+
+       smu->user_dpm_profile.user_workload_mask =
+               (1 << smu->workload_priority[param[param_size]]);
+       smu->workload_mask = smu->user_dpm_profile.user_workload_mask |
+               smu->driver_workload_mask;
+       ret = smu_bump_power_profile_mode(smu, param, param_size);
+
+       return ret;
 }
 
 static int smu_get_fan_control_mode(void *handle, u32 *fan_mode)
index 4ebcc1e53ea2f63565f26f05e0dba6c2e287a9f7..d665c47f19b77b654a2ae79f3ca6a4d41300fa4d 100644 (file)
@@ -240,6 +240,7 @@ struct smu_user_dpm_profile {
        /* user clock state information */
        uint32_t clk_mask[SMU_CLK_COUNT];
        uint32_t clk_dependency;
+       uint32_t user_workload_mask;
 };
 
 #define SMU_TABLE_INIT(tables, table_id, s, a, d)      \
@@ -557,7 +558,8 @@ struct smu_context {
        bool disable_uclk_switch;
 
        uint32_t workload_mask;
-       uint32_t workload_prority[WORKLOAD_POLICY_MAX];
+       uint32_t driver_workload_mask;
+       uint32_t workload_priority[WORKLOAD_POLICY_MAX];
        uint32_t workload_setting[WORKLOAD_POLICY_MAX];
        uint32_t power_profile_mode;
        uint32_t default_power_profile_mode;
index 6c8e80f6b592d0d4d6a1fadc5b68c6d21dda178d..4b36c230e43a0928d7d640f9c94091724b946893 100644 (file)
@@ -1455,7 +1455,6 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
                return -EINVAL;
        }
 
-
        if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
             (smu->smc_fw_version >= 0x360d00)) {
                if (size != 10)
@@ -1523,14 +1522,14 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
 
        ret = smu_cmn_send_smc_msg_with_param(smu,
                                          SMU_MSG_SetWorkloadMask,
-                                         1 << workload_type,
+                                         smu->workload_mask,
                                          NULL);
        if (ret) {
                dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
                return ret;
        }
 
-       smu->power_profile_mode = profile_mode;
+       smu_cmn_assign_power_profile(smu);
 
        return 0;
 }
index faa8e7d9c3c6285cbf812bb03ce20fb9b1be93d5..211635dabed851ffb0e3963e5a0155c42742a004 100644 (file)
@@ -2083,10 +2083,13 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u
                                                       smu->power_profile_mode);
        if (workload_type < 0)
                return -EINVAL;
+
        ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
-                                   1 << workload_type, NULL);
+                                   smu->workload_mask, NULL);
        if (ret)
                dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
+       else
+               smu_cmn_assign_power_profile(smu);
 
        return ret;
 }
index a9cb28ce21337586eb0a3b583162a79a9b48e4e8..d0ed0d060a8a3af587f37a45422aa73714095a4c 100644 (file)
@@ -1788,10 +1788,13 @@ static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *
                                                       smu->power_profile_mode);
        if (workload_type < 0)
                return -EINVAL;
+
        ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
-                                   1 << workload_type, NULL);
+                                   smu->workload_mask, NULL);
        if (ret)
                dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
+       else
+               smu_cmn_assign_power_profile(smu);
 
        return ret;
 }
index cd3e9ba3eff442ac03ebcb011506f89b8c8d2828..f89c487dce723d15488c5f66570e22f4f13d0fe5 100644 (file)
@@ -1081,7 +1081,7 @@ static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,
        }
 
        ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
-                                   1 << workload_type,
+                                   smu->workload_mask,
                                    NULL);
        if (ret) {
                dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
@@ -1089,7 +1089,7 @@ static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,
                return ret;
        }
 
-       smu->power_profile_mode = profile_mode;
+       smu_cmn_assign_power_profile(smu);
 
        return 0;
 }
index a34797f3576bf562029d56bacf7d167b49c93996..75a9ea87f419af8bbdfecbb99941b21dcd9f5185 100644 (file)
@@ -892,14 +892,14 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u
        }
 
        ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
-                                   1 << workload_type,
+                                   smu->workload_mask,
                                    NULL);
        if (ret) {
                dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
                return ret;
        }
 
-       smu->power_profile_mode = profile_mode;
+       smu_cmn_assign_power_profile(smu);
 
        return 0;
 }
index 8d25cc1f218f10d4644393c9252fc47416e628be..1d29e99d7955779c64790bb7a0c13a6c6921ad2c 100644 (file)
@@ -2473,7 +2473,7 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
        DpmActivityMonitorCoeffInt_t *activity_monitor =
                &(activity_monitor_external.DpmActivityMonitorCoeffInt);
        int workload_type, ret = 0;
-       u32 workload_mask, selected_workload_mask;
+       u32 workload_mask;
 
        smu->power_profile_mode = input[size];
 
@@ -2540,7 +2540,7 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
        if (workload_type < 0)
                return -EINVAL;
 
-       selected_workload_mask = workload_mask = 1 << workload_type;
+       workload_mask = 1 << workload_type;
 
        /* Add optimizations for SMU13.0.0/10.  Reuse the power saving profile */
        if ((amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 0) &&
@@ -2555,12 +2555,22 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
                        workload_mask |= 1 << workload_type;
        }
 
+       smu->workload_mask |= workload_mask;
        ret = smu_cmn_send_smc_msg_with_param(smu,
                                               SMU_MSG_SetWorkloadMask,
-                                              workload_mask,
+                                              smu->workload_mask,
                                               NULL);
-       if (!ret)
-               smu->workload_mask = selected_workload_mask;
+       if (!ret) {
+               smu_cmn_assign_power_profile(smu);
+               if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING) {
+                       workload_type = smu_cmn_to_asic_specific_index(smu,
+                                                              CMN2ASIC_MAPPING_WORKLOAD,
+                                                              PP_SMC_POWER_PROFILE_FULLSCREEN3D);
+                       smu->power_profile_mode = smu->workload_mask & (1 << workload_type)
+                                                                               ? PP_SMC_POWER_PROFILE_FULLSCREEN3D
+                                                                               : PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+               }
+       }
 
        return ret;
 }
index 23f13388455fe499559c6be45440af8e70ff7f06..12d622d4aceb00d17fc0ad96f2147d5aa9dfe8bc 100644 (file)
@@ -2487,13 +2487,14 @@ static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *inp
                                                       smu->power_profile_mode);
        if (workload_type < 0)
                return -EINVAL;
+
        ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
-                                   1 << workload_type, NULL);
+                                   smu->workload_mask, NULL);
 
        if (ret)
                dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
        else
-               smu->workload_mask = (1 << workload_type);
+               smu_cmn_assign_power_profile(smu);
 
        return ret;
 }
index 884938d69fcae9825dfb144f6d8e171ffa3fec73..59b369eff30fb806f1e717dcde66b7f78a5d53cf 100644 (file)
@@ -1795,12 +1795,11 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
        if (workload_type < 0)
                return -EINVAL;
 
-       ret = smu_cmn_send_smc_msg_with_param(smu,
-                                              SMU_MSG_SetWorkloadMask,
-                                              1 << workload_type,
-                                              NULL);
+       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
+                                                                                 smu->workload_mask, NULL);
+
        if (!ret)
-               smu->workload_mask = 1 << workload_type;
+               smu_cmn_assign_power_profile(smu);
 
        return ret;
 }
index 843f00c9e4075c06f6508faf999630ce2ee42d78..f1ab1a6bb46703a6a970e8b6cec6f2adb9019a3c 100644 (file)
@@ -1141,6 +1141,14 @@ int smu_cmn_set_mp1_state(struct smu_context *smu,
        return ret;
 }
 
+void smu_cmn_assign_power_profile(struct smu_context *smu)
+{
+       uint32_t index;
+       index = fls(smu->workload_mask);
+       index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+       smu->power_profile_mode = smu->workload_setting[index];
+}
+
 bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev)
 {
        struct pci_dev *p = NULL;
index 1de685defe85b19e3d2895ec33a2e95101c8ded8..8a801e389659d1b6f7bc162a93de43761e7739bd 100644 (file)
@@ -130,6 +130,8 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev);
 int smu_cmn_set_mp1_state(struct smu_context *smu,
                          enum pp_mp1_state mp1_state);
 
+void smu_cmn_assign_power_profile(struct smu_context *smu);
+
 /*
  * Helper function to make sysfs_emit_at() happy. Align buf to
  * the current page boundary and record the offset.
This page took 0.09331 seconds and 4 git commands to generate.