From 34bb2734d1bc3c72e4739234481c0efab0941d14 Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Mon, 12 Sep 2016 16:17:44 -0400 Subject: drm/amd/amdgpu: add power profile sysfs entry Add the sysfs entries pp_gfx_power_profile and pp_compute_power_profile which give user a way to set power profile through parameters minimum sclk, minimum mclk, activity threshold, up hysteresis and down hysteresis only when the entry power_dpm_force_performance_level is in default value "auto". It is read and write. Example: echo 500 800 20 0 5 > /sys/class/drm/card0/device/pp_*_power_profile cat /sys/class/drm/card0/device/pp_*_power_profile 500 800 20 0 5 Note: first parameter is sclk in MHz, second is mclk in MHz, third is activity threshold in percentage, fourth is up hysteresis in ms and fifth is down hysteresis in ms. echo set > /sys/class/drm/card0/device/pp_*_power_profile To set power profile state if it exists. echo reset > /sys/class/drm/card0/device/pp_*_power_profile To restore default state and clear previous setting. Signed-off-by: Eric Huang Acked-by: Rex Zhu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 192 +++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 346e80a7119b..fd45212c4b98 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -610,6 +610,174 @@ fail: return count; } +static ssize_t amdgpu_get_pp_power_profile(struct device *dev, + char *buf, struct amd_pp_profile *query) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret = 0; + + if (adev->pp_enabled) + ret = amdgpu_dpm_get_power_profile_state( + adev, query); + else if (adev->pm.funcs->get_power_profile_state) + ret = adev->pm.funcs->get_power_profile_state( + adev, query); + + if (ret) + return ret; + + return snprintf(buf, PAGE_SIZE, + "%d %d %d %d %d\n", + query->min_sclk / 100, + query->min_mclk / 100, + query->activity_threshold, + query->up_hyst, + query->down_hyst); +} + +static ssize_t amdgpu_get_pp_gfx_power_profile(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amd_pp_profile query = {0}; + + query.type = AMD_PP_GFX_PROFILE; + + return amdgpu_get_pp_power_profile(dev, buf, &query); +} + +static ssize_t amdgpu_get_pp_compute_power_profile(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amd_pp_profile query = {0}; + + query.type = AMD_PP_COMPUTE_PROFILE; + + return amdgpu_get_pp_power_profile(dev, buf, &query); +} + +static ssize_t amdgpu_set_pp_power_profile(struct device *dev, + const char *buf, + size_t count, + struct amd_pp_profile *request) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + uint32_t loop = 0; + char *sub_str, buf_cpy[128], *tmp_str; + const char delimiter[3] = {' ', '\n', '\0'}; + long int value; + int ret = 0; + + if (strncmp("reset", buf, strlen("reset")) == 0) { + if (adev->pp_enabled) + ret = amdgpu_dpm_reset_power_profile_state( + adev, request); + else if (adev->pm.funcs->reset_power_profile_state) + ret = adev->pm.funcs->reset_power_profile_state( + adev, request); + if (ret) { + count = -EINVAL; + goto fail; + } + return count; + } + + if (strncmp("set", buf, strlen("set")) == 0) { + if (adev->pp_enabled) + ret = amdgpu_dpm_set_power_profile_state( + adev, request); + else if (adev->pm.funcs->set_power_profile_state) + ret = adev->pm.funcs->set_power_profile_state( + adev, request); + if (ret) { + count = -EINVAL; + goto fail; + } + return count; + } + + if (count + 1 >= 128) { + count = -EINVAL; + goto fail; + } + + memcpy(buf_cpy, buf, count + 1); + tmp_str = buf_cpy; + + while (tmp_str[0]) { + sub_str = strsep(&tmp_str, delimiter); + ret = kstrtol(sub_str, 0, &value); + if (ret) { + count = -EINVAL; + goto fail; + } + + switch (loop) { + case 0: + /* input unit MHz convert to dpm table unit 10KHz*/ + request->min_sclk = (uint32_t)value * 100; + break; + case 1: + /* input unit MHz convert to dpm table unit 10KHz*/ + request->min_mclk = (uint32_t)value * 100; + break; + case 2: + request->activity_threshold = (uint16_t)value; + break; + case 3: + request->up_hyst = (uint8_t)value; + break; + case 4: + request->down_hyst = (uint8_t)value; + break; + default: + break; + } + + loop++; + } + + if (adev->pp_enabled) + ret = amdgpu_dpm_set_power_profile_state( + adev, request); + else if (adev->pm.funcs->set_power_profile_state) + ret = adev->pm.funcs->set_power_profile_state( + adev, request); + + if (ret) + count = -EINVAL; + +fail: + return count; +} + +static ssize_t amdgpu_set_pp_gfx_power_profile(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct amd_pp_profile request = {0}; + + request.type = AMD_PP_GFX_PROFILE; + + return amdgpu_set_pp_power_profile(dev, buf, count, &request); +} + +static ssize_t amdgpu_set_pp_compute_power_profile(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct amd_pp_profile request = {0}; + + request.type = AMD_PP_COMPUTE_PROFILE; + + return amdgpu_set_pp_power_profile(dev, buf, count, &request); +} + static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state); static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR, amdgpu_get_dpm_forced_performance_level, @@ -637,6 +805,12 @@ static DEVICE_ATTR(pp_sclk_od, S_IRUGO | S_IWUSR, static DEVICE_ATTR(pp_mclk_od, S_IRUGO | S_IWUSR, amdgpu_get_pp_mclk_od, amdgpu_set_pp_mclk_od); +static DEVICE_ATTR(pp_gfx_power_profile, S_IRUGO | S_IWUSR, + amdgpu_get_pp_gfx_power_profile, + amdgpu_set_pp_gfx_power_profile); +static DEVICE_ATTR(pp_compute_power_profile, S_IRUGO | S_IWUSR, + amdgpu_get_pp_compute_power_profile, + amdgpu_set_pp_compute_power_profile); static ssize_t amdgpu_hwmon_show_temp(struct device *dev, struct device_attribute *attr, @@ -1255,6 +1429,20 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) DRM_ERROR("failed to create device file pp_mclk_od\n"); return ret; } + ret = device_create_file(adev->dev, + &dev_attr_pp_gfx_power_profile); + if (ret) { + DRM_ERROR("failed to create device file " + "pp_gfx_power_profile\n"); + return ret; + } + ret = device_create_file(adev->dev, + &dev_attr_pp_compute_power_profile); + if (ret) { + DRM_ERROR("failed to create device file " + "pp_compute_power_profile\n"); + return ret; + } ret = amdgpu_debugfs_pm_init(adev); if (ret) { @@ -1284,6 +1472,10 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie); device_remove_file(adev->dev, &dev_attr_pp_sclk_od); device_remove_file(adev->dev, &dev_attr_pp_mclk_od); + device_remove_file(adev->dev, + &dev_attr_pp_gfx_power_profile); + device_remove_file(adev->dev, + &dev_attr_pp_compute_power_profile); } void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) -- cgit v1.2.3-59-g8ed1b From cd7b0c66ce35e8693a0018b4ce0bc59f46f97bd1 Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Tue, 7 Feb 2017 16:37:48 -0500 Subject: drm/amd/powerplay: change parameter type pointer from int32_t to void in read sensor As well as fix print format for uint32_t type. Signed-off-by: Eric Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 24 +++++++++---------- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 2 +- drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 28 +++++++++++------------ drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 14 ++++++------ drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 2 +- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 2 +- 6 files changed, 36 insertions(+), 36 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index fd45212c4b98..fc4d61cf34c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1532,7 +1532,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *adev) { - int32_t value; + uint32_t value; /* sanity check PP is enabled */ if (!(adev->powerplay.pp_funcs && @@ -1541,46 +1541,46 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a /* GPU Clocks */ seq_printf(m, "GFX Clocks and Power:\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, &value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&value)) seq_printf(m, "\t%u MHz (MCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, &value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&value)) seq_printf(m, "\t%u MHz (SCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, &value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&value)) seq_printf(m, "\t%u mV (VDDGFX)\n", value); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, &value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&value)) seq_printf(m, "\t%u mV (VDDNB)\n", value); seq_printf(m, "\n"); /* GPU Temp */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, &value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, (void *)&value)) seq_printf(m, "GPU Temperature: %u C\n", value/1000); /* GPU Load */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, &value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, (void *)&value)) seq_printf(m, "GPU Load: %u %%\n", value); seq_printf(m, "\n"); /* UVD clocks */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, &value)) { + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, (void *)&value)) { if (!value) { seq_printf(m, "UVD: Disabled\n"); } else { seq_printf(m, "UVD: Enabled\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, &value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value)) seq_printf(m, "\t%u MHz (DCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, &value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value)) seq_printf(m, "\t%u MHz (VCLK)\n", value/100); } } seq_printf(m, "\n"); /* VCE clocks */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, &value)) { + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, (void *)&value)) { if (!value) { seq_printf(m, "VCE: Disabled\n"); } else { seq_printf(m, "VCE: Enabled\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, &value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, (void *)&value)) seq_printf(m, "\t%u MHz (ECCLK)\n", value/100); } } diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 8074386da36f..81e6856ffa11 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -880,7 +880,7 @@ static int pp_dpm_set_mclk_od(void *handle, uint32_t value) return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); } -static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value) +static int pp_dpm_read_sensor(void *handle, int idx, void *value) { struct pp_hwmgr *hwmgr; struct pp_instance *pp_handle = (struct pp_instance *)handle; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index a4cde3d778b8..edc3029df785 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -1813,7 +1813,7 @@ static int cz_thermal_get_temperature(struct pp_hwmgr *hwmgr) return actual_temp; } -static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) +static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, void *value) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -1841,7 +1841,7 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) case AMDGPU_PP_SENSOR_GFX_SCLK: if (sclk_index < NUM_SCLK_LEVELS) { sclk = table->entries[sclk_index].clk; - *value = sclk; + *((uint32_t *)value) = sclk; return 0; } return -EINVAL; @@ -1849,13 +1849,13 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) & CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; vddnb = cz_convert_8Bit_index_to_voltage(hwmgr, tmp); - *value = vddnb; + *((uint32_t *)value) = vddnb; return 0; case AMDGPU_PP_SENSOR_VDDGFX: tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) & CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; vddgfx = cz_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp); - *value = vddgfx; + *((uint32_t *)value) = vddgfx; return 0; case AMDGPU_PP_SENSOR_UVD_VCLK: if (!cz_hwmgr->uvd_power_gated) { @@ -1863,11 +1863,11 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) return -EINVAL; } else { vclk = uvd_table->entries[uvd_index].vclk; - *value = vclk; + *((uint32_t *)value) = vclk; return 0; } } - *value = 0; + *((uint32_t *)value) = 0; return 0; case AMDGPU_PP_SENSOR_UVD_DCLK: if (!cz_hwmgr->uvd_power_gated) { @@ -1875,11 +1875,11 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) return -EINVAL; } else { dclk = uvd_table->entries[uvd_index].dclk; - *value = dclk; + *((uint32_t *)value) = dclk; return 0; } } - *value = 0; + *((uint32_t *)value) = 0; return 0; case AMDGPU_PP_SENSOR_VCE_ECCLK: if (!cz_hwmgr->vce_power_gated) { @@ -1887,11 +1887,11 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) return -EINVAL; } else { ecclk = vce_table->entries[vce_index].ecclk; - *value = ecclk; + *((uint32_t *)value) = ecclk; return 0; } } - *value = 0; + *((uint32_t *)value) = 0; return 0; case AMDGPU_PP_SENSOR_GPU_LOAD: result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity); @@ -1901,16 +1901,16 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) } else { activity_percent = 50; } - *value = activity_percent; + *((uint32_t *)value) = activity_percent; return 0; case AMDGPU_PP_SENSOR_UVD_POWER: - *value = cz_hwmgr->uvd_power_gated ? 0 : 1; + *((uint32_t *)value) = cz_hwmgr->uvd_power_gated ? 0 : 1; return 0; case AMDGPU_PP_SENSOR_VCE_POWER: - *value = cz_hwmgr->vce_power_gated ? 0 : 1; + *((uint32_t *)value) = cz_hwmgr->vce_power_gated ? 0 : 1; return 0; case AMDGPU_PP_SENSOR_GPU_TEMP: - *value = cz_thermal_get_temperature(hwmgr); + *((uint32_t *)value) = cz_thermal_get_temperature(hwmgr); return 0; default: return -EINVAL; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 31289a8d5cec..c3f8e9d56563 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -3289,7 +3289,7 @@ static int smu7_get_pp_table_entry(struct pp_hwmgr *hwmgr, return 0; } -static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) +static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, void *value) { uint32_t sclk, mclk, activity_percent; uint32_t offset; @@ -3299,12 +3299,12 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) case AMDGPU_PP_SENSOR_GFX_SCLK: smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency); sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); - *value = sclk; + *((uint32_t *)value) = sclk; return 0; case AMDGPU_PP_SENSOR_GFX_MCLK: smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency); mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); - *value = mclk; + *((uint32_t *)value) = mclk; return 0; case AMDGPU_PP_SENSOR_GPU_LOAD: offset = data->soft_regs_start + smum_get_offsetof(hwmgr->smumgr, @@ -3314,16 +3314,16 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); activity_percent += 0x80; activity_percent >>= 8; - *value = activity_percent > 100 ? 100 : activity_percent; + *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; return 0; case AMDGPU_PP_SENSOR_GPU_TEMP: - *value = smu7_thermal_get_temperature(hwmgr); + *((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr); return 0; case AMDGPU_PP_SENSOR_UVD_POWER: - *value = data->uvd_power_gated ? 0 : 1; + *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; return 0; case AMDGPU_PP_SENSOR_VCE_POWER: - *value = data->vce_power_gated ? 0 : 1; + *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; return 0; default: return -EINVAL; diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 4b4f5ff2f039..97009110e011 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -359,7 +359,7 @@ struct amd_powerplay_funcs { int (*set_sclk_od)(void *handle, uint32_t value); int (*get_mclk_od)(void *handle); int (*set_mclk_od)(void *handle, uint32_t value); - int (*read_sensor)(void *handle, int idx, int32_t *value); + int (*read_sensor)(void *handle, int idx, void *value); struct amd_vce_state* (*get_vce_clock_state)(void *handle, unsigned idx); int (*reset_power_profile_state)(void *handle, struct amd_pp_profile *request); diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 768f81f365ca..fa3bf50eff82 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -355,7 +355,7 @@ struct pp_hwmgr_func { int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); int (*get_mclk_od)(struct pp_hwmgr *hwmgr); int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); - int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, int32_t *value); + int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, void *value); int (*request_firmware)(struct pp_hwmgr *hwmgr); int (*release_firmware)(struct pp_hwmgr *hwmgr); int (*set_power_profile_state)(struct pp_hwmgr *hwmgr, -- cgit v1.2.3-59-g8ed1b From 4f9afc9bd23fce85f2022af50d0127a64121bb37 Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Tue, 24 Jan 2017 16:59:27 -0500 Subject: drm/amd/powerplay: add power consumption display support in debugfs The additional output are: vddc power in Watt; vddci power in Watt; max gpu power in Watt; average gpu power in Watt. Signed-off-by: Eric Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 11 +++++++++++ drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 8 ++++++++ 2 files changed, 19 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index fc4d61cf34c1..8a9a75a44b62 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1533,6 +1533,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *adev) { uint32_t value; + struct pp_gpu_power query = {0}; /* sanity check PP is enabled */ if (!(adev->powerplay.pp_funcs && @@ -1549,6 +1550,16 @@ 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)) seq_printf(m, "\t%u mV (VDDNB)\n", value); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query)) { + seq_printf(m, "\t%u.%u W (VDDC)\n", query.vddc_power >> 8, + query.vddc_power & 0xff); + seq_printf(m, "\t%u.%u W (VDDCI)\n", query.vddci_power >> 8, + query.vddci_power & 0xff); + seq_printf(m, "\t%u.%u W (max GPU)\n", query.max_gpu_power >> 8, + query.max_gpu_power & 0xff); + seq_printf(m, "\t%u.%u W (average GPU)\n", query.average_gpu_power >> 8, + query.average_gpu_power & 0xff); + } seq_printf(m, "\n"); /* GPU Temp */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 97009110e011..ab99013eba77 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -46,6 +46,7 @@ enum amd_pp_sensors { AMDGPU_PP_SENSOR_GPU_TEMP, AMDGPU_PP_SENSOR_VCE_POWER, AMDGPU_PP_SENSOR_UVD_POWER, + AMDGPU_PP_SENSOR_GPU_POWER, }; enum amd_pp_event { @@ -295,6 +296,13 @@ struct pp_states_info { uint32_t states[16]; }; +struct pp_gpu_power { + uint32_t vddc_power; + uint32_t vddci_power; + uint32_t max_gpu_power; + uint32_t average_gpu_power; +}; + #define PP_GROUP_MASK 0xF0000000 #define PP_GROUP_SHIFT 28 -- cgit v1.2.3-59-g8ed1b From 9f8df7d71e382c9afa808a08c11a990e90ac7df4 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 9 Feb 2017 14:29:01 -0500 Subject: drm/amd/amdgpu: Update read_sensor calls to have size parameter (v3) This update allows sensors to return more than 1 value and indicates to the caller how many bytes are written. The debugfs interface has been updated to handle reading all of the values. Simply seek to the enum value (multiplied by 4) and then read as many bytes as the sensor provides. (v2): Don't set size to 4 before reading GPU_POWER (v3): agd: rebase Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 26 +++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 28 +++++++++++++---------- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 5 ++-- drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 8 ++++++- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_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, 64 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 552452a654a5..f186c20f636b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3106,24 +3106,36 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { struct amdgpu_device *adev = file_inode(f)->i_private; - int idx, r; - int32_t value; + int idx, x, outsize, r, valuesize; + uint32_t values[16]; - if (size != 4 || *pos & 0x3) + if (size & 3 || *pos & 0x3) return -EINVAL; /* convert offset to sensor number */ idx = *pos >> 2; + valuesize = sizeof(values); if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) - r = adev->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, idx, &value); + r = adev->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, idx, &values[0], &valuesize); else return -EINVAL; - if (!r) - r = put_user(value, (int32_t *)buf); + if (size > valuesize) + return -EINVAL; + + outsize = 0; + x = 0; + if (!r) { + while (size) { + r = put_user(values[x++], (int32_t *)buf); + buf += 4; + size -= 4; + outsize += 4; + } + } - return !r ? 4 : r; + return !r ? outsize : r; } static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 5f09893c9674..5dd9daae9eef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -290,9 +290,9 @@ struct amdgpu_dpm_funcs { #define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev)) #define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e)) -#define amdgpu_dpm_read_sensor(adev, idx, value) \ +#define amdgpu_dpm_read_sensor(adev, idx, value, size) \ ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value)) : \ + (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value), (size)) : \ -EINVAL) #define amdgpu_dpm_get_temperature(adev) \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 8a9a75a44b62..da877f3c10fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1534,6 +1534,7 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a { uint32_t value; struct pp_gpu_power query = {0}; + int size; /* sanity check PP is enabled */ if (!(adev->powerplay.pp_funcs && @@ -1541,16 +1542,18 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a return -EINVAL; /* GPU Clocks */ + size = sizeof(value); seq_printf(m, "GFX Clocks and Power:\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&value, &size)) seq_printf(m, "\t%u MHz (MCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&value, &size)) seq_printf(m, "\t%u MHz (SCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&value, &size)) seq_printf(m, "\t%u mV (VDDGFX)\n", value); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&value, &size)) seq_printf(m, "\t%u mV (VDDNB)\n", value); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query)) { + size = sizeof(query); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size)) { seq_printf(m, "\t%u.%u W (VDDC)\n", query.vddc_power >> 8, query.vddc_power & 0xff); seq_printf(m, "\t%u.%u W (VDDCI)\n", query.vddci_power >> 8, @@ -1560,38 +1563,39 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a seq_printf(m, "\t%u.%u W (average GPU)\n", query.average_gpu_power >> 8, query.average_gpu_power & 0xff); } + size = sizeof(value); seq_printf(m, "\n"); /* GPU Temp */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, (void *)&value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, (void *)&value, &size)) seq_printf(m, "GPU Temperature: %u C\n", value/1000); /* GPU Load */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, (void *)&value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, (void *)&value, &size)) seq_printf(m, "GPU Load: %u %%\n", value); seq_printf(m, "\n"); /* UVD clocks */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, (void *)&value)) { + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, (void *)&value, &size)) { if (!value) { seq_printf(m, "UVD: Disabled\n"); } else { seq_printf(m, "UVD: Enabled\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size)) seq_printf(m, "\t%u MHz (DCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size)) seq_printf(m, "\t%u MHz (VCLK)\n", value/100); } } seq_printf(m, "\n"); /* VCE clocks */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, (void *)&value)) { + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, (void *)&value, &size)) { if (!value) { seq_printf(m, "VCE: Disabled\n"); } else { seq_printf(m, "VCE: Enabled\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, (void *)&value)) + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, (void *)&value, &size)) seq_printf(m, "\t%u MHz (ECCLK)\n", value/100); } } diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 81e6856ffa11..fde8fcd46b58 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -880,7 +880,8 @@ static int pp_dpm_set_mclk_od(void *handle, uint32_t value) return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); } -static int pp_dpm_read_sensor(void *handle, int idx, void *value) +static int pp_dpm_read_sensor(void *handle, int idx, + void *value, int *size) { struct pp_hwmgr *hwmgr; struct pp_instance *pp_handle = (struct pp_instance *)handle; @@ -898,7 +899,7 @@ static int pp_dpm_read_sensor(void *handle, int idx, void *value) return 0; } - return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value); + return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size); } static struct amd_vce_state* diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index edc3029df785..7aa5ca815a3a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -1813,7 +1813,8 @@ static int cz_thermal_get_temperature(struct pp_hwmgr *hwmgr) return actual_temp; } -static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, void *value) +static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, + void *value, int *size) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -1837,6 +1838,11 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, void *value) uint16_t vddnb, vddgfx; int result; + /* size must be at least 4 bytes for all sensors */ + if (*size < 4) + return -EINVAL; + *size = 4; + switch (idx) { case AMDGPU_PP_SENSOR_GFX_SCLK: if (sclk_index < NUM_SCLK_LEVELS) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 5a4ee43b3d65..13b35be3174c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -3320,22 +3320,29 @@ static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, return 0; } -static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, void *value) +static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, + void *value, int *size) { uint32_t sclk, mclk, activity_percent; uint32_t offset; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + /* size must be at least 4 bytes for all sensors */ + if (*size < 4) + return -EINVAL; + switch (idx) { case AMDGPU_PP_SENSOR_GFX_SCLK: smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency); sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); *((uint32_t *)value) = sclk; + *size = 4; return 0; case AMDGPU_PP_SENSOR_GFX_MCLK: smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency); mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); *((uint32_t *)value) = mclk; + *size = 4; return 0; case AMDGPU_PP_SENSOR_GPU_LOAD: offset = data->soft_regs_start + smum_get_offsetof(hwmgr->smumgr, @@ -3346,17 +3353,24 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, void *value) activity_percent += 0x80; activity_percent >>= 8; *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; + *size = 4; return 0; case AMDGPU_PP_SENSOR_GPU_TEMP: *((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr); + *size = 4; return 0; case AMDGPU_PP_SENSOR_UVD_POWER: *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; + *size = 4; return 0; case AMDGPU_PP_SENSOR_VCE_POWER: *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; + *size = 4; return 0; case AMDGPU_PP_SENSOR_GPU_POWER: + if (*size < sizeof(struct pp_gpu_power)) + return -EINVAL; + *size = sizeof(struct pp_gpu_power); return smu7_get_gpu_power(hwmgr, (struct pp_gpu_power *)value); default: return -EINVAL; diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index ab99013eba77..c0bf3af6846d 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -367,7 +367,7 @@ struct amd_powerplay_funcs { int (*set_sclk_od)(void *handle, uint32_t value); int (*get_mclk_od)(void *handle); int (*set_mclk_od)(void *handle, uint32_t value); - int (*read_sensor)(void *handle, int idx, void *value); + int (*read_sensor)(void *handle, int idx, void *value, int *size); struct amd_vce_state* (*get_vce_clock_state)(void *handle, unsigned idx); int (*reset_power_profile_state)(void *handle, struct amd_pp_profile *request); diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index fa3bf50eff82..8cf5aed055b6 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -355,7 +355,7 @@ struct pp_hwmgr_func { int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); int (*get_mclk_od)(struct pp_hwmgr *hwmgr); int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); - int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, void *value); + int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, void *value, int *size); int (*request_firmware)(struct pp_hwmgr *hwmgr); int (*release_firmware)(struct pp_hwmgr *hwmgr); int (*set_power_profile_state)(struct pp_hwmgr *hwmgr, -- cgit v1.2.3-59-g8ed1b From 03a5f1df5bc3329efd3f8306c20f9b094cbbb08e Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 6 Mar 2017 11:29:26 +0800 Subject: drm/amdgpu: refine vce2.0 dpm sequence start vce first then enable vce dpm. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index da877f3c10fc..b69f8274d81a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1316,11 +1316,11 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) /* XXX select vce level based on ring/task */ adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; mutex_unlock(&adev->pm.mutex); - amdgpu_pm_compute_clocks(adev); - amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_UNGATE); amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, AMD_CG_STATE_UNGATE); + amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_UNGATE); + amdgpu_pm_compute_clocks(adev); } else { amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, AMD_PG_STATE_GATE); -- cgit v1.2.3-59-g8ed1b From 12ad27faa81e47875bd5a6daa43f33bddf12e6b6 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Fri, 24 Mar 2017 09:58:11 +0800 Subject: drm/amdgpu: add get_clockgating callback for gfx v9 Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 2 ++ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index b69f8274d81a..f0094a312be9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -43,6 +43,8 @@ static const struct cg_flag_name clocks[] = { {AMD_CG_SUPPORT_GFX_CGTS_LS, "Graphics Coarse Grain Tree Shader Light Sleep"}, {AMD_CG_SUPPORT_GFX_CP_LS, "Graphics Command Processor Light Sleep"}, {AMD_CG_SUPPORT_GFX_RLC_LS, "Graphics Run List Controller Light Sleep"}, + {AMD_CG_SUPPORT_GFX_3D_CGCG, "Graphics 3D Coarse Grain Clock Gating"}, + {AMD_CG_SUPPORT_GFX_3D_CGLS, "Graphics 3D Coarse Grain memory Light Sleep"}, {AMD_CG_SUPPORT_MC_LS, "Memory Controller Light Sleep"}, {AMD_CG_SUPPORT_MC_MGCG, "Memory Controller Medium Grain Clock Gating"}, {AMD_CG_SUPPORT_SDMA_LS, "System Direct Memory Access Light Sleep"}, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 07800c91878d..69fa15678817 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2946,6 +2946,48 @@ static int gfx_v9_0_set_clockgating_state(void *handle, return 0; } +static void gfx_v9_0_get_clockgating_state(void *handle, u32 *flags) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int data; + + if (amdgpu_sriov_vf(adev)) + *flags = 0; + + /* AMD_CG_SUPPORT_GFX_MGCG */ + data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE)); + if (!(data & RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK)) + *flags |= AMD_CG_SUPPORT_GFX_MGCG; + + /* AMD_CG_SUPPORT_GFX_CGCG */ + data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL)); + if (data & RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK) + *flags |= AMD_CG_SUPPORT_GFX_CGCG; + + /* AMD_CG_SUPPORT_GFX_CGLS */ + if (data & RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK) + *flags |= AMD_CG_SUPPORT_GFX_CGLS; + + /* AMD_CG_SUPPORT_GFX_RLC_LS */ + data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL)); + if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK) + *flags |= AMD_CG_SUPPORT_GFX_RLC_LS | AMD_CG_SUPPORT_GFX_MGLS; + + /* AMD_CG_SUPPORT_GFX_CP_LS */ + data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL)); + if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) + *flags |= AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_MGLS; + + /* AMD_CG_SUPPORT_GFX_3D_CGCG */ + data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D)); + if (data & RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK) + *flags |= AMD_CG_SUPPORT_GFX_3D_CGCG; + + /* AMD_CG_SUPPORT_GFX_3D_CGLS */ + if (data & RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK) + *flags |= AMD_CG_SUPPORT_GFX_3D_CGLS; +} + static u64 gfx_v9_0_ring_get_rptr_gfx(struct amdgpu_ring *ring) { return ring->adev->wb.wb[ring->rptr_offs]; /* gfx9 is 32bit rptr*/ @@ -3626,6 +3668,7 @@ const struct amd_ip_funcs gfx_v9_0_ip_funcs = { .soft_reset = gfx_v9_0_soft_reset, .set_clockgating_state = gfx_v9_0_set_clockgating_state, .set_powergating_state = gfx_v9_0_set_powergating_state, + .get_clockgating_state = gfx_v9_0_get_clockgating_state, }; static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = { -- cgit v1.2.3-59-g8ed1b From e96487a6a7288b46e6b8c0ec5b659bb4e59fbdab Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Fri, 24 Mar 2017 10:12:32 +0800 Subject: drm/amdgpu: add get_clockgating callback for nbio v6.1 Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 1 + drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c | 15 +++++++++++++++ drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h | 1 + 3 files changed, 17 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index f0094a312be9..67f4a5afdac3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -49,6 +49,7 @@ static const struct cg_flag_name clocks[] = { {AMD_CG_SUPPORT_MC_MGCG, "Memory Controller Medium Grain Clock Gating"}, {AMD_CG_SUPPORT_SDMA_LS, "System Direct Memory Access Light Sleep"}, {AMD_CG_SUPPORT_SDMA_MGCG, "System Direct Memory Access Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_BIF_MGCG, "Bus Interface Medium Grain Clock Gating"}, {AMD_CG_SUPPORT_BIF_LS, "Bus Interface Light Sleep"}, {AMD_CG_SUPPORT_UVD_MGCG, "Unified Video Decoder Medium Grain Clock Gating"}, {AMD_CG_SUPPORT_VCE_MGCG, "Video Compression Engine Medium Grain Clock Gating"}, diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c index 902187206c86..97057f4a10de 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c @@ -206,6 +206,21 @@ void nbio_v6_1_update_medium_grain_light_sleep(struct amdgpu_device *adev, WREG32_PCIE(smnPCIE_CNTL2, data); } +void nbio_v6_1_get_clockgating_state(struct amdgpu_device *adev, u32 *flags) +{ + int data; + + /* AMD_CG_SUPPORT_BIF_MGCG */ + data = RREG32_PCIE(smnCPM_CONTROL); + if (data & CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK) + *flags |= AMD_CG_SUPPORT_BIF_MGCG; + + /* AMD_CG_SUPPORT_BIF_LS */ + data = RREG32_PCIE(smnPCIE_CNTL2); + if (data & PCIE_CNTL2__SLV_MEM_LS_EN_MASK) + *flags |= AMD_CG_SUPPORT_BIF_LS; +} + struct nbio_hdp_flush_reg nbio_v6_1_hdp_flush_reg; struct nbio_pcie_index_data nbio_v6_1_pcie_index_data; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h index 3e04093539f5..f6f8bc045518 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h @@ -48,6 +48,7 @@ void nbio_v6_1_ih_control(struct amdgpu_device *adev); u32 nbio_v6_1_get_rev_id(struct amdgpu_device *adev); void nbio_v6_1_update_medium_grain_clock_gating(struct amdgpu_device *adev, bool enable); void nbio_v6_1_update_medium_grain_light_sleep(struct amdgpu_device *adev, bool enable); +void nbio_v6_1_get_clockgating_state(struct amdgpu_device *adev, u32 *flags); void nbio_v6_1_detect_hw_virt(struct amdgpu_device *adev); #endif -- cgit v1.2.3-59-g8ed1b From f9abe35c307e26c16d4eade33b2904d9ff665116 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Fri, 24 Mar 2017 10:46:16 +0800 Subject: drm/amdgpu: add get_clockgating callback for soc15 (v3) v2: squash register typo fix from Ray v3: fix spelling Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 3 +++ drivers/gpu/drm/amd/amdgpu/soc15.c | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 67f4a5afdac3..990fde2cf4fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -55,7 +55,10 @@ static const struct cg_flag_name clocks[] = { {AMD_CG_SUPPORT_VCE_MGCG, "Video Compression Engine Medium Grain Clock Gating"}, {AMD_CG_SUPPORT_HDP_LS, "Host Data Path Light Sleep"}, {AMD_CG_SUPPORT_HDP_MGCG, "Host Data Path Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_DRM_MGCG, "Digital Right Management Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_DRM_LS, "Digital Right Management Light Sleep"}, {AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_DF_MGCG, "Data Fabric Medium Grain Clock Gating"}, {0, NULL}, }; diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 6286573ae513..3c77b59adbc7 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -792,6 +792,42 @@ static int soc15_common_set_clockgating_state(void *handle, return 0; } +static void soc15_common_get_clockgating_state(void *handle, u32 *flags) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int data; + + if (amdgpu_sriov_vf(adev)) + *flags = 0; + + nbio_v6_1_get_clockgating_state(adev, flags); + + /* AMD_CG_SUPPORT_HDP_LS */ + data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS)); + if (data & HDP_MEM_POWER_LS__LS_ENABLE_MASK) + *flags |= AMD_CG_SUPPORT_HDP_LS; + + /* AMD_CG_SUPPORT_DRM_MGCG */ + data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_CGTT_CTRL0)); + if (!(data & 0x01000000)) + *flags |= AMD_CG_SUPPORT_DRM_MGCG; + + /* AMD_CG_SUPPORT_DRM_LS */ + data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_LIGHT_SLEEP_CTRL)); + if (data & 0x1) + *flags |= AMD_CG_SUPPORT_DRM_LS; + + /* AMD_CG_SUPPORT_ROM_MGCG */ + data = RREG32(SOC15_REG_OFFSET(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0)); + if (!(data & CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK)) + *flags |= AMD_CG_SUPPORT_ROM_MGCG; + + /* AMD_CG_SUPPORT_DF_MGCG */ + data = RREG32(SOC15_REG_OFFSET(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater)); + if (data & DF_MGCG_ENABLE_15_CYCLE_DELAY) + *flags |= AMD_CG_SUPPORT_DF_MGCG; +} + static int soc15_common_set_powergating_state(void *handle, enum amd_powergating_state state) { @@ -814,4 +850,5 @@ const struct amd_ip_funcs soc15_common_ip_funcs = { .soft_reset = soc15_common_soft_reset, .set_clockgating_state = soc15_common_set_clockgating_state, .set_powergating_state = soc15_common_set_powergating_state, + .get_clockgating_state= soc15_common_get_clockgating_state, }; -- cgit v1.2.3-59-g8ed1b