summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/pm/amdgpu_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c')
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c151
1 files changed, 66 insertions, 85 deletions
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index 85b089a3dc41..c0e677328af5 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -34,6 +34,7 @@
#include <linux/nospec.h>
#include <linux/pm_runtime.h>
#include <linux/string_choices.h>
+#include <linux/units.h>
#include <asm/processor.h>
#define MAX_NUM_OF_FEATURES_PER_SUBSET 8
@@ -98,6 +99,37 @@ const char * const amdgpu_pp_profile_name[] = {
"UNCAPPED",
};
+static int amdgpu_pm_parse_long_params(char *str, long *params,
+ uint32_t max_params,
+ uint32_t *num_params)
+{
+ const char delimiter[] = { ' ', '\n', '\0' };
+ uint32_t count = 0;
+ char *sub_str;
+ int ret;
+
+ if (!params || !num_params)
+ return -EINVAL;
+
+ while ((sub_str = strsep(&str, delimiter)) != NULL) {
+ if (strlen(sub_str) == 0)
+ continue;
+ if (count >= max_params)
+ return -EINVAL;
+ ret = kstrtol(sub_str, 0, &params[count]);
+ if (ret)
+ return -EINVAL;
+ count++;
+ if (!str)
+ break;
+ while (isspace(*str))
+ str++;
+ }
+ *num_params = count;
+
+ return 0;
+}
+
/**
* amdgpu_pm_dev_state_check - Check if device can be accessed.
* @adev: Target device.
@@ -761,8 +793,6 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
long parameter[64];
char buf_cpy[128];
char *tmp_str;
- char *sub_str;
- const char delimiter[3] = {' ', '\n', '\0'};
uint32_t type;
if (count > 127 || count == 0)
@@ -797,22 +827,10 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
tmp_str++;
while (isspace(*++tmp_str));
- while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) {
- if (strlen(sub_str) == 0)
- continue;
- if (parameter_size >= ARRAY_SIZE(parameter))
- return -EINVAL;
- ret = kstrtol(sub_str, 0, &parameter[parameter_size]);
- if (ret)
- return -EINVAL;
- parameter_size++;
-
- if (!tmp_str)
- break;
-
- while (isspace(*tmp_str))
- tmp_str++;
- }
+ ret = amdgpu_pm_parse_long_params(
+ tmp_str, parameter, ARRAY_SIZE(parameter), &parameter_size);
+ if (ret)
+ return ret;
ret = amdgpu_pm_get_access(adev);
if (ret < 0)
@@ -1385,11 +1403,9 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,
struct amdgpu_device *adev = drm_to_adev(ddev);
uint32_t parameter_size = 0;
long parameter[64];
- char *sub_str, buf_cpy[128];
- char *tmp_str;
+ char buf_cpy[128];
char tmp[2];
long int profile_mode = 0;
- const char delimiter[3] = {' ', '\n', '\0'};
/* Reject empty/whitespace strings - fuzzing found this is not validated */
if (count == 0 || sysfs_streq(buf, ""))
@@ -1407,19 +1423,11 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,
while (isspace(*buf))
buf++;
strscpy(buf_cpy, buf, sizeof(buf_cpy));
- tmp_str = buf_cpy;
- while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) {
- if (strlen(sub_str) == 0)
- continue;
- ret = kstrtol(sub_str, 0, &parameter[parameter_size]);
- if (ret)
- return -EINVAL;
- parameter_size++;
- if (!tmp_str)
- break;
- while (isspace(*tmp_str))
- tmp_str++;
- }
+ ret = amdgpu_pm_parse_long_params(buf_cpy, parameter,
+ ARRAY_SIZE(parameter) - 1,
+ &parameter_size);
+ if (ret)
+ return ret;
}
parameter[parameter_size] = profile_mode;
@@ -2015,6 +2023,7 @@ static int pp_dpm_clk_default_attr_update(struct amdgpu_device *adev, struct amd
gc_ver == IP_VERSION(11, 0, 1) ||
gc_ver == IP_VERSION(11, 0, 4) ||
gc_ver == IP_VERSION(11, 5, 0) ||
+ gc_ver == IP_VERSION(11, 5, 1) ||
gc_ver == IP_VERSION(11, 0, 2) ||
gc_ver == IP_VERSION(11, 0, 3) ||
amdgpu_is_multi_aid(adev)))
@@ -2023,7 +2032,8 @@ static int pp_dpm_clk_default_attr_update(struct amdgpu_device *adev, struct amd
if (!((gc_ver == IP_VERSION(10, 3, 1) ||
gc_ver == IP_VERSION(10, 3, 0) ||
gc_ver == IP_VERSION(11, 0, 2) ||
- gc_ver == IP_VERSION(11, 0, 3)) && adev->vcn.num_vcn_inst >= 2))
+ gc_ver == IP_VERSION(11, 0, 3) ||
+ gc_ver == IP_VERSION(11, 5, 1)) && adev->vcn.num_vcn_inst >= 2))
*states = ATTR_STATE_UNSUPPORTED;
} else if (DEVICE_ATTR_IS(pp_dpm_dclk)) {
if (!(gc_ver == IP_VERSION(10, 3, 1) ||
@@ -2036,6 +2046,7 @@ static int pp_dpm_clk_default_attr_update(struct amdgpu_device *adev, struct amd
gc_ver == IP_VERSION(11, 0, 1) ||
gc_ver == IP_VERSION(11, 0, 4) ||
gc_ver == IP_VERSION(11, 5, 0) ||
+ gc_ver == IP_VERSION(11, 5, 1) ||
gc_ver == IP_VERSION(11, 0, 2) ||
gc_ver == IP_VERSION(11, 0, 3) ||
amdgpu_is_multi_aid(adev)))
@@ -2044,7 +2055,8 @@ static int pp_dpm_clk_default_attr_update(struct amdgpu_device *adev, struct amd
if (!((gc_ver == IP_VERSION(10, 3, 1) ||
gc_ver == IP_VERSION(10, 3, 0) ||
gc_ver == IP_VERSION(11, 0, 2) ||
- gc_ver == IP_VERSION(11, 0, 3)) && adev->vcn.num_vcn_inst >= 2))
+ gc_ver == IP_VERSION(11, 0, 3) ||
+ gc_ver == IP_VERSION(11, 5, 1)) && adev->vcn.num_vcn_inst >= 2))
*states = ATTR_STATE_UNSUPPORTED;
} else if (DEVICE_ATTR_IS(pp_dpm_pcie)) {
if (amdgpu_is_multi_aid(adev))
@@ -3943,18 +3955,14 @@ out_pm_put:
return size;
}
-static int parse_input_od_command_lines(const char *buf,
- size_t count,
- u32 *type,
- long *params,
- size_t params_max,
+static int parse_input_od_command_lines(const char *buf, size_t count,
+ u32 *type, long *params,
+ uint32_t max_params,
uint32_t *num_of_params)
{
- const char delimiter[3] = {' ', '\n', '\0'};
uint32_t parameter_size = 0;
char buf_cpy[128] = {0};
- char *tmp_str, *sub_str;
- int ret;
+ char *tmp_str;
if (count > sizeof(buf_cpy) - 1)
return -EINVAL;
@@ -3979,28 +3987,8 @@ static int parse_input_od_command_lines(const char *buf,
break;
}
- while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) {
- if (strlen(sub_str) == 0)
- continue;
-
- if (parameter_size >= params_max)
- return -EINVAL;
-
- ret = kstrtol(sub_str, 0, &params[parameter_size]);
- if (ret)
- return -EINVAL;
- parameter_size++;
-
- if (!tmp_str)
- break;
-
- while (isspace(*tmp_str))
- tmp_str++;
- }
-
- *num_of_params = parameter_size;
-
- return 0;
+ return amdgpu_pm_parse_long_params(tmp_str, params, max_params,
+ num_of_params);
}
static int
@@ -4013,10 +4001,7 @@ amdgpu_distribute_custom_od_settings(struct amdgpu_device *adev,
long parameter[64];
int ret;
- ret = parse_input_od_command_lines(in_buf,
- count,
- &cmd_type,
- parameter,
+ ret = parse_input_od_command_lines(in_buf, count, &cmd_type, parameter,
ARRAY_SIZE(parameter),
&parameter_size);
if (ret)
@@ -4892,9 +4877,8 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
{
uint32_t mp1_ver = amdgpu_ip_version(adev, MP1_HWIP, 0);
uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0);
- uint32_t value, mwatt, centiwatt;
uint64_t value64 = 0;
- uint32_t query = 0;
+ uint32_t value;
int size;
/* GPU Clocks */
@@ -4915,25 +4899,22 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
seq_printf(m, "\t%u mV (VDDGFX)\n", value);
if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&value, &size))
seq_printf(m, "\t%u mV (VDDNB)\n", value);
- size = sizeof(uint32_t);
- if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_AVG_POWER, (void *)&query, &size)) {
- mwatt = query;
- centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_AVG_POWER, (void *)&value, &size)) {
if (adev->flags & AMD_IS_APU)
- seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
+ seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n",
+ (u32)(value / MILLIWATT_PER_WATT), (u32)(value % MILLIWATT_PER_WATT) / 10);
else
- seq_printf(m, "\t%u.%02u W (average SoC)\n", centiwatt / 100, centiwatt % 100);
+ seq_printf(m, "\t%u.%02u W (average SoC)\n",
+ (u32)(value / MILLIWATT_PER_WATT), (u32)(value % MILLIWATT_PER_WATT) / 10);
}
- size = sizeof(uint32_t);
- if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_INPUT_POWER, (void *)&query, &size)) {
- mwatt = query;
- centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
+ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_INPUT_POWER, (void *)&value, &size)) {
if (adev->flags & AMD_IS_APU)
- seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
+ seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n",
+ (u32)(value / MILLIWATT_PER_WATT), (u32)(value % MILLIWATT_PER_WATT) / 10);
else
- seq_printf(m, "\t%u.%02u W (current SoC)\n", centiwatt / 100, centiwatt % 100);
+ seq_printf(m, "\t%u.%02u W (current SoC)\n",
+ (u32)(value / MILLIWATT_PER_WATT), (u32)(value % MILLIWATT_PER_WATT) / 10);
}
- size = sizeof(value);
seq_printf(m, "\n");
/* GPU Temp */