From: Eric Huang <jinhuieric.hu...@amd.com>

Allows you to force multiple levels rather than just one via the new
sysfs interrface.

v2: squash in:
drm/amd/powerplay: ensure clock level set by user is valid.
>From Rex.

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
Signed-off-by: Eric Huang <JinHuiEric.Huang at amd.com>
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c             | 51 +++++++++++++++-------
 drivers/gpu/drm/amd/powerplay/amd_powerplay.c      |  4 +-
 drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c     |  6 +--
 drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c   | 18 ++++++--
 .../gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c  | 16 +++++--
 drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c  | 16 +++++--
 drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h  |  2 +-
 drivers/gpu/drm/amd/powerplay/inc/hwmgr.h          |  2 +-
 8 files changed, 81 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 6d44d4a..589b36e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -362,16 +362,23 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev,
        struct amdgpu_device *adev = ddev->dev_private;
        int ret;
        long level;
+       uint32_t i, mask = 0;
+       char sub_str[2];

-       ret = kstrtol(buf, 0, &level);
+       for (i = 0; i < strlen(buf) - 1; i++) {
+               sub_str[0] = *(buf + i);
+               sub_str[1] = '\0';
+               ret = kstrtol(sub_str, 0, &level);

-       if (ret) {
-               count = -EINVAL;
-               goto fail;
+               if (ret) {
+                       count = -EINVAL;
+                       goto fail;
+               }
+               mask |= 1 << level;
        }

        if (adev->pp_enabled)
-               amdgpu_dpm_force_clock_level(adev, PP_SCLK, level);
+               amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask);
 fail:
        return count;
 }
@@ -399,16 +406,23 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
        struct amdgpu_device *adev = ddev->dev_private;
        int ret;
        long level;
+       uint32_t i, mask = 0;
+       char sub_str[2];

-       ret = kstrtol(buf, 0, &level);
+       for (i = 0; i < strlen(buf) - 1; i++) {
+               sub_str[0] = *(buf + i);
+               sub_str[1] = '\0';
+               ret = kstrtol(sub_str, 0, &level);

-       if (ret) {
-               count = -EINVAL;
-               goto fail;
+               if (ret) {
+                       count = -EINVAL;
+                       goto fail;
+               }
+               mask |= 1 << level;
        }

        if (adev->pp_enabled)
-               amdgpu_dpm_force_clock_level(adev, PP_MCLK, level);
+               amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask);
 fail:
        return count;
 }
@@ -436,16 +450,23 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev,
        struct amdgpu_device *adev = ddev->dev_private;
        int ret;
        long level;
+       uint32_t i, mask = 0;
+       char sub_str[2];

-       ret = kstrtol(buf, 0, &level);
+       for (i = 0; i < strlen(buf) - 1; i++) {
+               sub_str[0] = *(buf + i);
+               sub_str[1] = '\0';
+               ret = kstrtol(sub_str, 0, &level);

-       if (ret) {
-               count = -EINVAL;
-               goto fail;
+               if (ret) {
+                       count = -EINVAL;
+                       goto fail;
+               }
+               mask |= 1 << level;
        }

        if (adev->pp_enabled)
-               amdgpu_dpm_force_clock_level(adev, PP_PCIE, level);
+               amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask);
 fail:
        return count;
 }
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c 
b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index ce8d9bf..0527ae3 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -763,7 +763,7 @@ static int pp_dpm_set_pp_table(void *handle, const char 
*buf, size_t size)
 }

 static int pp_dpm_force_clock_level(void *handle,
-               enum pp_clock_type type, int level)
+               enum pp_clock_type type, uint32_t mask)
 {
        struct pp_hwmgr *hwmgr;

@@ -779,7 +779,7 @@ static int pp_dpm_force_clock_level(void *handle,
                return 0;
        }

-       return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, level);
+       return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
 }

 static int pp_dpm_print_clock_levels(void *handle,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
index 648394f..1f14c47 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
@@ -1729,7 +1729,7 @@ static int cz_get_dal_power_level(struct pp_hwmgr *hwmgr,
 }

 static int cz_force_clock_level(struct pp_hwmgr *hwmgr,
-               enum pp_clock_type type, int level)
+               enum pp_clock_type type, uint32_t mask)
 {
        if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
                return -EINVAL;
@@ -1738,10 +1738,10 @@ static int cz_force_clock_level(struct pp_hwmgr *hwmgr,
        case PP_SCLK:
                smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                PPSMC_MSG_SetSclkSoftMin,
-                               (1 << level));
+                               mask);
                smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                PPSMC_MSG_SetSclkSoftMax,
-                               (1 << level));
+                               mask);
                break;
        default:
                break;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
index dc836d3..f8d49f1 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
@@ -5113,7 +5113,7 @@ static int fiji_set_pp_table(struct pp_hwmgr *hwmgr, 
const char *buf, size_t siz
 }

 static int fiji_force_clock_level(struct pp_hwmgr *hwmgr,
-               enum pp_clock_type type, int level)
+               enum pp_clock_type type, uint32_t mask)
 {
        struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);

@@ -5125,20 +5125,30 @@ static int fiji_force_clock_level(struct pp_hwmgr 
*hwmgr,
                if (!data->sclk_dpm_key_disabled)
                        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                        PPSMC_MSG_SCLKDPM_SetEnabledMask,
-                                       (1 << level));
+                                       
data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
                break;
+
        case PP_MCLK:
                if (!data->mclk_dpm_key_disabled)
                        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                        PPSMC_MSG_MCLKDPM_SetEnabledMask,
-                                       (1 << level));
+                                       
data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
                break;
+
        case PP_PCIE:
+       {
+               uint32_t tmp = mask & 
data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+               uint32_t level = 0;
+
+               while (tmp >>= 1)
+                       level++;
+
                if (!data->pcie_dpm_key_disabled)
                        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                        PPSMC_MSG_PCIeDPM_ForceLevel,
-                                       (1 << level));
+                                       level);
                break;
+       }
        default:
                break;
        }
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c
index 2ab3bb2..79192c3 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c
@@ -4767,7 +4767,7 @@ static int polaris10_set_pp_table(struct pp_hwmgr *hwmgr, 
const char *buf, size_
 }

 static int polaris10_force_clock_level(struct pp_hwmgr *hwmgr,
-               enum pp_clock_type type, int level)
+               enum pp_clock_type type, uint32_t mask)
 {
        struct polaris10_hwmgr *data = (struct polaris10_hwmgr 
*)(hwmgr->backend);

@@ -4779,20 +4779,28 @@ static int polaris10_force_clock_level(struct pp_hwmgr 
*hwmgr,
                if (!data->sclk_dpm_key_disabled)
                        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                        PPSMC_MSG_SCLKDPM_SetEnabledMask,
-                                       (1 << level));
+                                       
data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
                break;
        case PP_MCLK:
                if (!data->mclk_dpm_key_disabled)
                        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                        PPSMC_MSG_MCLKDPM_SetEnabledMask,
-                                       (1 << level));
+                                       
data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
                break;
        case PP_PCIE:
+       {
+               uint32_t tmp = mask & 
data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+               uint32_t level = 0;
+
+               while (tmp >>= 1)
+                       level++;
+
                if (!data->pcie_dpm_key_disabled)
                        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                        PPSMC_MSG_PCIeDPM_ForceLevel,
-                                       (1 << level));
+                                       level);
                break;
+       }
        default:
                break;
        }
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
index 0242e34..9040225 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
@@ -6075,7 +6075,7 @@ static int tonga_set_pp_table(struct pp_hwmgr *hwmgr, 
const char *buf, size_t si
 }

 static int tonga_force_clock_level(struct pp_hwmgr *hwmgr,
-               enum pp_clock_type type, int level)
+               enum pp_clock_type type, uint32_t mask)
 {
        struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);

@@ -6087,20 +6087,28 @@ static int tonga_force_clock_level(struct pp_hwmgr 
*hwmgr,
                if (!data->sclk_dpm_key_disabled)
                        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                        PPSMC_MSG_SCLKDPM_SetEnabledMask,
-                                       (1 << level));
+                                       
data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
                break;
        case PP_MCLK:
                if (!data->mclk_dpm_key_disabled)
                        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                        PPSMC_MSG_MCLKDPM_SetEnabledMask,
-                                       (1 << level));
+                                       
data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
                break;
        case PP_PCIE:
+       {
+               uint32_t tmp = mask & 
data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+               uint32_t level = 0;
+
+               while (tmp >>= 1)
+                       level++;
+
                if (!data->pcie_dpm_key_disabled)
                        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                                        PPSMC_MSG_PCIeDPM_ForceLevel,
-                                       (1 << level));
+                                       level);
                break;
+       }
        default:
                break;
        }
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h 
b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
index e5f2ee7..50b367d 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
@@ -340,7 +340,7 @@ struct amd_powerplay_funcs {
        int (*get_pp_num_states)(void *handle, struct pp_states_info *data);
        int (*get_pp_table)(void *handle, char **table);
        int (*set_pp_table)(void *handle, const char *buf, size_t size);
-       int (*force_clock_level)(void *handle, enum pp_clock_type type, int 
level);
+       int (*force_clock_level)(void *handle, enum pp_clock_type type, 
uint32_t mask);
        int (*print_clock_levels)(void *handle, enum pp_clock_type type, char 
*buf);
 };

diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h 
b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index 12285a9..b1a9ae5 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -335,7 +335,7 @@ struct pp_hwmgr_func {
        int (*power_off_asic)(struct pp_hwmgr *hwmgr);
        int (*get_pp_table)(struct pp_hwmgr *hwmgr, char **table);
        int (*set_pp_table)(struct pp_hwmgr *hwmgr, const char *buf, size_t 
size);
-       int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type 
type, int level);
+       int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type 
type, uint32_t mask);
        int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type 
type, char *buf);
        int (*enable_per_cu_power_gating)(struct pp_hwmgr *hwmgr, bool enable);
 };
-- 
2.5.5

Reply via email to