Commit 6e58941c authored by Eric Huang's avatar Eric Huang Committed by Alex Deucher

drm/amd/pm: add a new sysfs entry for default power limit

Driver doesn't keep the default bootup power limit and expose it
to user. As requested we add it in driver.
Signed-off-by: default avatarEric Huang <jinhuieric.huang@amd.com>
Reviewed-by: default avatarEvan Quan <evan.quan@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 616cf23b
...@@ -288,7 +288,8 @@ struct amd_pm_funcs { ...@@ -288,7 +288,8 @@ struct amd_pm_funcs {
uint32_t block_type, bool gate); uint32_t block_type, bool gate);
int (*set_clockgating_by_smu)(void *handle, uint32_t msg_id); int (*set_clockgating_by_smu)(void *handle, uint32_t msg_id);
int (*set_power_limit)(void *handle, uint32_t n); int (*set_power_limit)(void *handle, uint32_t n);
int (*get_power_limit)(void *handle, uint32_t *limit, bool default_limit); int (*get_power_limit)(void *handle, uint32_t *limit, uint32_t *max_limit,
bool default_limit);
int (*get_power_profile_mode)(void *handle, char *buf); int (*get_power_profile_mode)(void *handle, char *buf);
int (*set_power_profile_mode)(void *handle, long *input, uint32_t size); int (*set_power_profile_mode)(void *handle, long *input, uint32_t size);
int (*set_fine_grain_clk_vol)(void *handle, uint32_t type, long *input, uint32_t size); int (*set_fine_grain_clk_vol)(void *handle, uint32_t type, long *input, uint32_t size);
......
...@@ -2613,6 +2613,7 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, ...@@ -2613,6 +2613,7 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev,
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
int limit_type = to_sensor_dev_attr(attr)->index; int limit_type = to_sensor_dev_attr(attr)->index;
uint32_t limit = limit_type << 24; uint32_t limit = limit_type << 24;
uint32_t max_limit = 0;
ssize_t size; ssize_t size;
int r; int r;
...@@ -2629,8 +2630,9 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, ...@@ -2629,8 +2630,9 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev,
smu_get_power_limit(&adev->smu, &limit, SMU_PPT_LIMIT_MAX); smu_get_power_limit(&adev->smu, &limit, SMU_PPT_LIMIT_MAX);
size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000);
} else if (pp_funcs && pp_funcs->get_power_limit) { } else if (pp_funcs && pp_funcs->get_power_limit) {
pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, true); pp_funcs->get_power_limit(adev->powerplay.pp_handle,
size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); &limit, &max_limit, true);
size = snprintf(buf, PAGE_SIZE, "%u\n", max_limit * 1000000);
} else { } else {
size = snprintf(buf, PAGE_SIZE, "\n"); size = snprintf(buf, PAGE_SIZE, "\n");
} }
...@@ -2665,7 +2667,8 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, ...@@ -2665,7 +2667,8 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev,
smu_get_power_limit(&adev->smu, &limit, SMU_PPT_LIMIT_CURRENT); smu_get_power_limit(&adev->smu, &limit, SMU_PPT_LIMIT_CURRENT);
size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000);
} else if (pp_funcs && pp_funcs->get_power_limit) { } else if (pp_funcs && pp_funcs->get_power_limit) {
pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, false); pp_funcs->get_power_limit(adev->powerplay.pp_handle,
&limit, NULL, false);
size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000);
} else { } else {
size = snprintf(buf, PAGE_SIZE, "\n"); size = snprintf(buf, PAGE_SIZE, "\n");
...@@ -2677,6 +2680,42 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, ...@@ -2677,6 +2680,42 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev,
return size; return size;
} }
static ssize_t amdgpu_hwmon_show_power_cap_default(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct amdgpu_device *adev = dev_get_drvdata(dev);
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
int limit_type = to_sensor_dev_attr(attr)->index;
uint32_t limit = limit_type << 24;
ssize_t size;
int r;
if (amdgpu_in_reset(adev))
return -EPERM;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;
}
if (is_support_sw_smu(adev)) {
smu_get_power_limit(&adev->smu, &limit, SMU_PPT_LIMIT_DEFAULT);
size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000);
} else if (pp_funcs && pp_funcs->get_power_limit) {
pp_funcs->get_power_limit(adev->powerplay.pp_handle,
&limit, NULL, true);
size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000);
} else {
size = snprintf(buf, PAGE_SIZE, "\n");
}
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return size;
}
static ssize_t amdgpu_hwmon_show_power_label(struct device *dev, static ssize_t amdgpu_hwmon_show_power_label(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
...@@ -2919,11 +2958,13 @@ static SENSOR_DEVICE_ATTR(power1_average, S_IRUGO, amdgpu_hwmon_show_power_avg, ...@@ -2919,11 +2958,13 @@ static SENSOR_DEVICE_ATTR(power1_average, S_IRUGO, amdgpu_hwmon_show_power_avg,
static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 0); static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 0);
static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 0); static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 0);
static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0); static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0);
static SENSOR_DEVICE_ATTR(power1_cap_default, S_IRUGO, amdgpu_hwmon_show_power_cap_default, NULL, 0);
static SENSOR_DEVICE_ATTR(power1_label, S_IRUGO, amdgpu_hwmon_show_power_label, NULL, 0); static SENSOR_DEVICE_ATTR(power1_label, S_IRUGO, amdgpu_hwmon_show_power_label, NULL, 0);
static SENSOR_DEVICE_ATTR(power2_average, S_IRUGO, amdgpu_hwmon_show_power_avg, NULL, 1); static SENSOR_DEVICE_ATTR(power2_average, S_IRUGO, amdgpu_hwmon_show_power_avg, NULL, 1);
static SENSOR_DEVICE_ATTR(power2_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 1); static SENSOR_DEVICE_ATTR(power2_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 1);
static SENSOR_DEVICE_ATTR(power2_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 1); static SENSOR_DEVICE_ATTR(power2_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 1);
static SENSOR_DEVICE_ATTR(power2_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 1); static SENSOR_DEVICE_ATTR(power2_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 1);
static SENSOR_DEVICE_ATTR(power2_cap_default, S_IRUGO, amdgpu_hwmon_show_power_cap_default, NULL, 1);
static SENSOR_DEVICE_ATTR(power2_label, S_IRUGO, amdgpu_hwmon_show_power_label, NULL, 1); static SENSOR_DEVICE_ATTR(power2_label, S_IRUGO, amdgpu_hwmon_show_power_label, NULL, 1);
static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, amdgpu_hwmon_show_sclk, NULL, 0); static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, amdgpu_hwmon_show_sclk, NULL, 0);
static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, amdgpu_hwmon_show_sclk_label, NULL, 0); static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, amdgpu_hwmon_show_sclk_label, NULL, 0);
...@@ -2963,11 +3004,13 @@ static struct attribute *hwmon_attributes[] = { ...@@ -2963,11 +3004,13 @@ static struct attribute *hwmon_attributes[] = {
&sensor_dev_attr_power1_cap_max.dev_attr.attr, &sensor_dev_attr_power1_cap_max.dev_attr.attr,
&sensor_dev_attr_power1_cap_min.dev_attr.attr, &sensor_dev_attr_power1_cap_min.dev_attr.attr,
&sensor_dev_attr_power1_cap.dev_attr.attr, &sensor_dev_attr_power1_cap.dev_attr.attr,
&sensor_dev_attr_power1_cap_default.dev_attr.attr,
&sensor_dev_attr_power1_label.dev_attr.attr, &sensor_dev_attr_power1_label.dev_attr.attr,
&sensor_dev_attr_power2_average.dev_attr.attr, &sensor_dev_attr_power2_average.dev_attr.attr,
&sensor_dev_attr_power2_cap_max.dev_attr.attr, &sensor_dev_attr_power2_cap_max.dev_attr.attr,
&sensor_dev_attr_power2_cap_min.dev_attr.attr, &sensor_dev_attr_power2_cap_min.dev_attr.attr,
&sensor_dev_attr_power2_cap.dev_attr.attr, &sensor_dev_attr_power2_cap.dev_attr.attr,
&sensor_dev_attr_power2_cap_default.dev_attr.attr,
&sensor_dev_attr_power2_label.dev_attr.attr, &sensor_dev_attr_power2_label.dev_attr.attr,
&sensor_dev_attr_freq1_input.dev_attr.attr, &sensor_dev_attr_freq1_input.dev_attr.attr,
&sensor_dev_attr_freq1_label.dev_attr.attr, &sensor_dev_attr_freq1_label.dev_attr.attr,
...@@ -3066,7 +3109,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, ...@@ -3066,7 +3109,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
(adev->asic_type != CHIP_VANGOGH))) && /* not implemented yet */ (adev->asic_type != CHIP_VANGOGH))) && /* not implemented yet */
(attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr||
attr == &sensor_dev_attr_power1_cap.dev_attr.attr)) attr == &sensor_dev_attr_power1_cap.dev_attr.attr ||
attr == &sensor_dev_attr_power1_cap_default.dev_attr.attr))
return 0; return 0;
if (((adev->family == AMDGPU_FAMILY_SI) || if (((adev->family == AMDGPU_FAMILY_SI) ||
...@@ -3132,6 +3176,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, ...@@ -3132,6 +3176,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
attr == &sensor_dev_attr_power2_cap_max.dev_attr.attr || attr == &sensor_dev_attr_power2_cap_max.dev_attr.attr ||
attr == &sensor_dev_attr_power2_cap_min.dev_attr.attr || attr == &sensor_dev_attr_power2_cap_min.dev_attr.attr ||
attr == &sensor_dev_attr_power2_cap.dev_attr.attr || attr == &sensor_dev_attr_power2_cap.dev_attr.attr ||
attr == &sensor_dev_attr_power2_cap_default.dev_attr.attr ||
attr == &sensor_dev_attr_power2_label.dev_attr.attr || attr == &sensor_dev_attr_power2_label.dev_attr.attr ||
attr == &sensor_dev_attr_power1_label.dev_attr.attr)) attr == &sensor_dev_attr_power1_label.dev_attr.attr))
return 0; return 0;
......
...@@ -171,6 +171,7 @@ enum smu_ppt_limit_level ...@@ -171,6 +171,7 @@ enum smu_ppt_limit_level
{ {
SMU_PPT_LIMIT_MIN = -1, SMU_PPT_LIMIT_MIN = -1,
SMU_PPT_LIMIT_CURRENT, SMU_PPT_LIMIT_CURRENT,
SMU_PPT_LIMIT_DEFAULT,
SMU_PPT_LIMIT_MAX, SMU_PPT_LIMIT_MAX,
}; };
...@@ -446,6 +447,7 @@ struct smu_context ...@@ -446,6 +447,7 @@ struct smu_context
bool od_enabled; bool od_enabled;
uint32_t current_power_limit; uint32_t current_power_limit;
uint32_t default_power_limit;
uint32_t max_power_limit; uint32_t max_power_limit;
/* soft pptable */ /* soft pptable */
......
...@@ -141,6 +141,7 @@ struct smu_11_5_power_context { ...@@ -141,6 +141,7 @@ struct smu_11_5_power_context {
enum smu_11_0_power_state power_state; enum smu_11_0_power_state power_state;
uint32_t current_fast_ppt_limit; uint32_t current_fast_ppt_limit;
uint32_t default_fast_ppt_limit;
uint32_t max_fast_ppt_limit; uint32_t max_fast_ppt_limit;
}; };
......
...@@ -1034,7 +1034,8 @@ static int pp_set_power_limit(void *handle, uint32_t limit) ...@@ -1034,7 +1034,8 @@ static int pp_set_power_limit(void *handle, uint32_t limit)
return 0; return 0;
} }
static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit) static int pp_get_power_limit(void *handle, uint32_t *limit,
uint32_t *max_limit, bool default_limit)
{ {
struct pp_hwmgr *hwmgr = handle; struct pp_hwmgr *hwmgr = handle;
...@@ -1045,9 +1046,12 @@ static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit) ...@@ -1045,9 +1046,12 @@ static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit)
if (default_limit) { if (default_limit) {
*limit = hwmgr->default_power_limit; *limit = hwmgr->default_power_limit;
if (hwmgr->od_enabled) { if (max_limit) {
*limit *= (100 + hwmgr->platform_descriptor.TDPODLimit); *max_limit = *limit;
*limit /= 100; if (hwmgr->od_enabled) {
*max_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);
*max_limit /= 100;
}
} }
} }
else else
......
...@@ -2183,6 +2183,9 @@ int smu_get_power_limit(struct smu_context *smu, ...@@ -2183,6 +2183,9 @@ int smu_get_power_limit(struct smu_context *smu,
case SMU_PPT_LIMIT_CURRENT: case SMU_PPT_LIMIT_CURRENT:
*limit = smu->current_power_limit; *limit = smu->current_power_limit;
break; break;
case SMU_PPT_LIMIT_DEFAULT:
*limit = smu->default_power_limit;
break;
case SMU_PPT_LIMIT_MAX: case SMU_PPT_LIMIT_MAX:
*limit = smu->max_power_limit; *limit = smu->max_power_limit;
break; break;
......
...@@ -1129,7 +1129,7 @@ static int arcturus_get_power_limit(struct smu_context *smu) ...@@ -1129,7 +1129,7 @@ static int arcturus_get_power_limit(struct smu_context *smu)
power_limit = power_limit =
pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
} }
smu->current_power_limit = power_limit; smu->current_power_limit = smu->default_power_limit = power_limit;
if (smu->od_enabled) { if (smu->od_enabled) {
od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
......
...@@ -2111,7 +2111,7 @@ static int navi10_get_power_limit(struct smu_context *smu) ...@@ -2111,7 +2111,7 @@ static int navi10_get_power_limit(struct smu_context *smu)
power_limit = power_limit =
pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
} }
smu->current_power_limit = power_limit; smu->current_power_limit = smu->default_power_limit = power_limit;
if (smu->od_enabled && if (smu->od_enabled &&
navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) { navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
......
...@@ -1736,7 +1736,7 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu) ...@@ -1736,7 +1736,7 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu)
power_limit = power_limit =
pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
} }
smu->current_power_limit = power_limit; smu->current_power_limit = smu->default_power_limit = power_limit;
if (smu->od_enabled) { if (smu->od_enabled) {
od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]); od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
......
...@@ -1756,7 +1756,7 @@ static int vangogh_get_power_limit(struct smu_context *smu) ...@@ -1756,7 +1756,7 @@ static int vangogh_get_power_limit(struct smu_context *smu)
return ret; return ret;
} }
/* convert from milliwatt to watt */ /* convert from milliwatt to watt */
smu->current_power_limit = ppt_limit / 1000; smu->current_power_limit = smu->default_power_limit = ppt_limit / 1000;
smu->max_power_limit = 29; smu->max_power_limit = 29;
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit); ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit);
...@@ -1765,7 +1765,8 @@ static int vangogh_get_power_limit(struct smu_context *smu) ...@@ -1765,7 +1765,8 @@ static int vangogh_get_power_limit(struct smu_context *smu)
return ret; return ret;
} }
/* convert from milliwatt to watt */ /* convert from milliwatt to watt */
power_context->current_fast_ppt_limit = ppt_limit / 1000; power_context->current_fast_ppt_limit =
power_context->default_fast_ppt_limit = ppt_limit / 1000;
power_context->max_fast_ppt_limit = 30; power_context->max_fast_ppt_limit = 30;
return ret; return ret;
...@@ -1790,6 +1791,9 @@ static int vangogh_get_ppt_limit(struct smu_context *smu, ...@@ -1790,6 +1791,9 @@ static int vangogh_get_ppt_limit(struct smu_context *smu,
case SMU_PPT_LIMIT_CURRENT: case SMU_PPT_LIMIT_CURRENT:
*ppt_limit = power_context->current_fast_ppt_limit; *ppt_limit = power_context->current_fast_ppt_limit;
break; break;
case SMU_PPT_LIMIT_DEFAULT:
*ppt_limit = power_context->default_fast_ppt_limit;
break;
default: default:
break; break;
} }
......
...@@ -1088,7 +1088,7 @@ static int aldebaran_get_power_limit(struct smu_context *smu) ...@@ -1088,7 +1088,7 @@ static int aldebaran_get_power_limit(struct smu_context *smu)
power_limit = pptable->PptLimit; power_limit = pptable->PptLimit;
} }
smu->current_power_limit = power_limit; smu->current_power_limit = smu->default_power_limit = power_limit;
if (pptable) if (pptable)
smu->max_power_limit = pptable->PptLimit; smu->max_power_limit = pptable->PptLimit;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment