for f in $FILES
do
echo === $f === >> $LOGFILE
cat $HWMON_DIR/device/$f >> $LOGFILE
done
cat $LOGFILE
Signed-off-by: Darren Powell <darren.powell@xxxxxxx>
---
.../gpu/drm/amd/include/kgd_pp_interface.h | 2 +
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 41 +++++++-
drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 9 ++
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 53 +++++++++-
.../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 96 +++++++++++++++++++
5 files changed, 192 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index bac15c466733..fbe045811e60 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -310,6 +310,8 @@ struct amd_pm_funcs {
int (*get_fan_speed_pwm)(void *handle, u32 *speed);
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);
+ int (*get_clock_levels)(void *handle, enum pp_clock_type type,
+ uint32_t *clock_list, uint max_list_length);
int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level);
int (*get_sclk_od)(void *handle);
int (*set_sclk_od)(void *handle, uint32_t value);
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index 41472ed99253..ca7a6779e59b 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -1020,6 +1020,23 @@ static ssize_t amdgpu_get_pp_features(struct device *dev,
return size;
}
+static int amdgpu_dpm_print_clock_array(enum pp_clock_type type,
+ char *buf,
+ uint32_t *clock_list, uint list_length) {
+
+ uint i;
+ int size = 0;
+
+ for (i = 1; i < list_length; i++) {
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, clock_list[i],
+ clock_list[i] == clock_list[0] ? "*" : "");
+ }
+
+
+ return size;
+}
+
+
/**
* DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_pcie
*
@@ -1058,6 +1075,7 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct device *dev,
struct amdgpu_device *adev = drm_to_adev(ddev);
ssize_t size;
int ret;
+ uint32_t clock_list[8];
if (amdgpu_in_reset(adev))
return -EPERM;
@@ -1070,10 +1088,24 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct device *dev,
return ret;
}
- if (adev->powerplay.pp_funcs->print_clock_levels)
- size = amdgpu_dpm_print_clock_levels(adev, type, buf);
- else
- size = sysfs_emit(buf, "\n");
+ if (adev->powerplay.pp_funcs->get_clock_levels) {
+ ret = adev->powerplay.pp_funcs->get_clock_levels(
+ adev->powerplay.pp_handle, type, clock_list, 8);
+
+ if (ret > 0)
+ size = amdgpu_dpm_print_clock_array(type, buf, clock_list, ret);
+ }
+ else {
+ ret = -EOPNOTSUPP;
+ }
+
+ if (ret == -EOPNOTSUPP) {
+ if (adev->powerplay.pp_funcs->print_clock_levels) {
+ size = amdgpu_dpm_print_clock_levels(adev, type, buf);
+ }
+ else
+ size = sysfs_emit(buf, "\n");
+ }
pm_runtime_mark_last_busy(ddev->dev);
pm_runtime_put_autosuspend(ddev->dev);
@@ -1159,6 +1191,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
struct device_attribute *attr,
char *buf)
{
+ dev_warn(dev, " %s ENTRY", __func__);
return amdgpu_get_pp_dpm_clock(dev, PP_SCLK, buf);
}
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
index 3557f4e7fc30..d8c20a134475 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
@@ -610,6 +610,15 @@ struct pptable_funcs {
*/
int (*print_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf);
+ /**
+ * @get_clk_levels: Get array DPM clock levels for a clock domain
+ * to array clock_list. current level is first element.
+ *
+ * Used for sysfs interfaces.
+ */
+ int (*get_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type,
+ uint32_t *clock_list, uint max_list_length);
+
/**
* @force_clk_levels: Set a range of allowed DPM levels for a clock
* domain.
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 01168b8955bf..2de566118422 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -2395,11 +2395,8 @@ static int smu_print_smuclk_levels(struct smu_context *smu, enum smu_clk_type cl
return ret;
}
-static int smu_print_ppclk_levels(void *handle,
- enum pp_clock_type type,
- char *buf)
+static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type)
{
- struct smu_context *smu = handle;
enum smu_clk_type clk_type;
switch (type) {
@@ -2432,12 +2429,57 @@ static int smu_print_ppclk_levels(void *handle,
case OD_CCLK:
clk_type = SMU_OD_CCLK; break;
default:
- return -EINVAL;
+ clk_type = SMU_CLK_COUNT; break;
}
+ return clk_type;
+}
+
+static int smu_print_ppclk_levels(void *handle,
+ enum pp_clock_type type,
+ char *buf)
+{
+ struct smu_context *smu = handle;
+ enum smu_clk_type clk_type;
+
+ clk_type = smu_convert_to_smuclk(type);
+ if (clk_type == SMU_CLK_COUNT)
+ return -EINVAL;
+
return smu_print_smuclk_levels(smu, clk_type, buf);
}
+static int smu_get_ppclk_levels(void *handle,
+ enum pp_clock_type type,
+ uint32_t *clock_list, uint max_list_length)
+{
+ struct smu_context *smu = handle;
+ enum smu_clk_type clk_type;
+ int ret = 0;
+
+ clk_type = smu_convert_to_smuclk(type);
+ if (clk_type == SMU_CLK_COUNT)
+ return -EINVAL;
+
+
+ if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
+ return -EOPNOTSUPP;
+
+
+ if (smu->ppt_funcs->get_clk_levels) {
+
+ mutex_lock(&smu->mutex);
+ ret = smu->ppt_funcs->get_clk_levels(smu, clk_type, clock_list, max_list_length);
+ mutex_unlock(&smu->mutex);
+ }
+ else {
+ ret = -EOPNOTSUPP;
+ }
+
+
+ return ret;
+}
+
static int smu_od_edit_dpm_table(void *handle,
enum PP_OD_DPM_TABLE_COMMAND type,
long *input, uint32_t size)
@@ -3100,6 +3142,7 @@ static const struct amd_pm_funcs swsmu_pm_funcs = {
.set_fan_speed_pwm = smu_set_fan_speed_pwm,
.get_fan_speed_pwm = smu_get_fan_speed_pwm,
.force_clock_level = smu_force_ppclk_levels,
+ .get_clock_levels = smu_get_ppclk_levels,
.print_clock_levels = smu_print_ppclk_levels,
.force_performance_level = smu_force_performance_level,
.read_sensor = smu_read_sensor,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 71161f6b78fe..55e6880c2964 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -1261,6 +1261,101 @@ static void navi10_od_setting_get_range(struct smu_11_0_overdrive_table *od_tabl
*max = od_table->max[setting];
}
+static int navi10_get_clk_levels(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *clock_list, uint max_list_length)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int size = 0, ret = 0;
+ uint32_t cur_value = 0, value = 0, count = 0, i;
+ uint32_t freq_values[3] = {0};
+ uint32_t mark_index = 0;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ case SMU_SOCCLK:
+ case SMU_MCLK:
+ case SMU_UCLK:
+ case SMU_FCLK:
+ case SMU_VCLK:
+ case SMU_DCEFCLK:
+ case SMU_DCLK:
+ ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value);
+ if (ret) {
+ dev_err(adev->dev, " %s Unable to retrieve clk freq : %u", __func__, clk_type);
+ return -EIO;
+ }
+
+ ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count);
+ if (ret) {
+ dev_err(adev->dev, " %s Unable to retrieve clk count : %u", __func__, clk_type);
+ return -EIO;
+ }
+
+ if (count > max_list_length-1) {
+ dev_err(adev->dev, " %s Too many clock values", __func__);
+ return -EPERM;
+ }
+
+
+ clock_list[0] = cur_value;
+ if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) {
+ for (i = 0; i < count; i++) {
+ ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value);
+ if (ret) {
+ dev_err(adev->dev, " %s Unable to retrieve clk freq : %u", __func__, clk_type);
+ return -EIO;
+ }
+
+ clock_list[i+1] = value;
+ }
+ size = count+1;
+ } else {
+ // for fine-grained dpm, display cur_value as average of max and min
+ ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]);
+ if (ret) {
+ dev_err(adev->dev, " %s Unable to retrieve clk freq : %u", __func__, clk_type);
+ return -EIO;
+ }
+ ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]);
+ if (ret) {
+ dev_err(adev->dev, " %s Unable to retrieve clk freq : %u", __func__, clk_type);
+ return -EIO;
+ }
+
+ freq_values[1] = cur_value;
+ mark_index = cur_value == freq_values[0] ? 0 :
+ cur_value == freq_values[2] ? 2 : 1;
+ if (mark_index != 1)
+ freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
+
+ clock_list[0] = freq_values[1];
+ for (i = 0; i < 3; i++) {
+ clock_list[i+1] = freq_values[i];
+ }
+
+ size = 3+1;
+ }
+ break;
+ case SMU_PCIE:
+ case SMU_OD_SCLK:
+ case SMU_OD_MCLK:
+ case SMU_OD_VDDC_CURVE:
+ case SMU_OD_RANGE:
+ dev_warn(adev->dev, " %s Unhandled clk_type : %u", __func__, clk_type);
+ size = -EOPNOTSUPP;
+ break;
+
+ default:
+ dev_err(adev->dev, " %s Unknown clk_type : %u", __func__, clk_type);
+ size = -EINVAL;
+ break;
+ }
+
+ return size;
+}
+
static int navi10_print_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type, char *buf)
{
@@ -3241,6 +3336,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable,
.i2c_init = navi10_i2c_control_init,
.i2c_fini = navi10_i2c_control_fini,
+ .get_clk_levels = navi10_get_clk_levels,
.print_clk_levels = navi10_print_clk_levels,
.force_clk_levels = navi10_force_clk_levels,
.populate_umd_state_clk = navi10_populate_umd_state_clk,
base-commit: eabeb4f20a0786188fba07a2dd1b0a614c4e15f6