Commit 9f8df7d7 authored by Tom St Denis's avatar Tom St Denis Committed by Alex Deucher

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: default avatarTom St Denis <tom.stdenis@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 603adfe8
...@@ -3106,24 +3106,36 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, ...@@ -3106,24 +3106,36 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf,
size_t size, loff_t *pos) size_t size, loff_t *pos)
{ {
struct amdgpu_device *adev = file_inode(f)->i_private; struct amdgpu_device *adev = file_inode(f)->i_private;
int idx, r; int idx, x, outsize, r, valuesize;
int32_t value; uint32_t values[16];
if (size != 4 || *pos & 0x3) if (size & 3 || *pos & 0x3)
return -EINVAL; return -EINVAL;
/* convert offset to sensor number */ /* convert offset to sensor number */
idx = *pos >> 2; idx = *pos >> 2;
valuesize = sizeof(values);
if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) 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 else
return -EINVAL; return -EINVAL;
if (!r) if (size > valuesize)
r = put_user(value, (int32_t *)buf); 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, static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf,
......
...@@ -290,9 +290,9 @@ struct amdgpu_dpm_funcs { ...@@ -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_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_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)->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) -EINVAL)
#define amdgpu_dpm_get_temperature(adev) \ #define amdgpu_dpm_get_temperature(adev) \
......
...@@ -1534,6 +1534,7 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a ...@@ -1534,6 +1534,7 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
{ {
uint32_t value; uint32_t value;
struct pp_gpu_power query = {0}; struct pp_gpu_power query = {0};
int size;
/* sanity check PP is enabled */ /* sanity check PP is enabled */
if (!(adev->powerplay.pp_funcs && if (!(adev->powerplay.pp_funcs &&
...@@ -1541,16 +1542,18 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a ...@@ -1541,16 +1542,18 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
return -EINVAL; return -EINVAL;
/* GPU Clocks */ /* GPU Clocks */
size = sizeof(value);
seq_printf(m, "GFX Clocks and Power:\n"); 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); 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); 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); 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); 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, seq_printf(m, "\t%u.%u W (VDDC)\n", query.vddc_power >> 8,
query.vddc_power & 0xff); query.vddc_power & 0xff);
seq_printf(m, "\t%u.%u W (VDDCI)\n", query.vddci_power >> 8, 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 ...@@ -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, seq_printf(m, "\t%u.%u W (average GPU)\n", query.average_gpu_power >> 8,
query.average_gpu_power & 0xff); query.average_gpu_power & 0xff);
} }
size = sizeof(value);
seq_printf(m, "\n"); seq_printf(m, "\n");
/* GPU Temp */ /* 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); seq_printf(m, "GPU Temperature: %u C\n", value/1000);
/* GPU Load */ /* 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, "GPU Load: %u %%\n", value);
seq_printf(m, "\n"); seq_printf(m, "\n");
/* UVD clocks */ /* 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) { if (!value) {
seq_printf(m, "UVD: Disabled\n"); seq_printf(m, "UVD: Disabled\n");
} else { } else {
seq_printf(m, "UVD: Enabled\n"); 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); 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, "\t%u MHz (VCLK)\n", value/100);
} }
} }
seq_printf(m, "\n"); seq_printf(m, "\n");
/* VCE clocks */ /* 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) { if (!value) {
seq_printf(m, "VCE: Disabled\n"); seq_printf(m, "VCE: Disabled\n");
} else { } else {
seq_printf(m, "VCE: Enabled\n"); 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); seq_printf(m, "\t%u MHz (ECCLK)\n", value/100);
} }
} }
......
...@@ -880,7 +880,8 @@ static int pp_dpm_set_mclk_od(void *handle, uint32_t value) ...@@ -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); 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_hwmgr *hwmgr;
struct pp_instance *pp_handle = (struct pp_instance *)handle; 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) ...@@ -898,7 +899,7 @@ static int pp_dpm_read_sensor(void *handle, int idx, void *value)
return 0; 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* static struct amd_vce_state*
......
...@@ -1813,7 +1813,8 @@ static int cz_thermal_get_temperature(struct pp_hwmgr *hwmgr) ...@@ -1813,7 +1813,8 @@ static int cz_thermal_get_temperature(struct pp_hwmgr *hwmgr)
return actual_temp; 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); 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) ...@@ -1837,6 +1838,11 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, void *value)
uint16_t vddnb, vddgfx; uint16_t vddnb, vddgfx;
int result; int result;
/* size must be at least 4 bytes for all sensors */
if (*size < 4)
return -EINVAL;
*size = 4;
switch (idx) { switch (idx) {
case AMDGPU_PP_SENSOR_GFX_SCLK: case AMDGPU_PP_SENSOR_GFX_SCLK:
if (sclk_index < NUM_SCLK_LEVELS) { if (sclk_index < NUM_SCLK_LEVELS) {
......
...@@ -3320,22 +3320,29 @@ static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, ...@@ -3320,22 +3320,29 @@ static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr,
return 0; 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 sclk, mclk, activity_percent;
uint32_t offset; uint32_t offset;
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 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) { switch (idx) {
case AMDGPU_PP_SENSOR_GFX_SCLK: case AMDGPU_PP_SENSOR_GFX_SCLK:
smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency); smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency);
sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
*((uint32_t *)value) = sclk; *((uint32_t *)value) = sclk;
*size = 4;
return 0; return 0;
case AMDGPU_PP_SENSOR_GFX_MCLK: case AMDGPU_PP_SENSOR_GFX_MCLK:
smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency); smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency);
mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
*((uint32_t *)value) = mclk; *((uint32_t *)value) = mclk;
*size = 4;
return 0; return 0;
case AMDGPU_PP_SENSOR_GPU_LOAD: case AMDGPU_PP_SENSOR_GPU_LOAD:
offset = data->soft_regs_start + smum_get_offsetof(hwmgr->smumgr, 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) ...@@ -3346,17 +3353,24 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, void *value)
activity_percent += 0x80; activity_percent += 0x80;
activity_percent >>= 8; activity_percent >>= 8;
*((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
*size = 4;
return 0; return 0;
case AMDGPU_PP_SENSOR_GPU_TEMP: case AMDGPU_PP_SENSOR_GPU_TEMP:
*((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr); *((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr);
*size = 4;
return 0; return 0;
case AMDGPU_PP_SENSOR_UVD_POWER: case AMDGPU_PP_SENSOR_UVD_POWER:
*((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
*size = 4;
return 0; return 0;
case AMDGPU_PP_SENSOR_VCE_POWER: case AMDGPU_PP_SENSOR_VCE_POWER:
*((uint32_t *)value) = data->vce_power_gated ? 0 : 1; *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
*size = 4;
return 0; return 0;
case AMDGPU_PP_SENSOR_GPU_POWER: 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); return smu7_get_gpu_power(hwmgr, (struct pp_gpu_power *)value);
default: default:
return -EINVAL; return -EINVAL;
......
...@@ -367,7 +367,7 @@ struct amd_powerplay_funcs { ...@@ -367,7 +367,7 @@ struct amd_powerplay_funcs {
int (*set_sclk_od)(void *handle, uint32_t value); int (*set_sclk_od)(void *handle, uint32_t value);
int (*get_mclk_od)(void *handle); int (*get_mclk_od)(void *handle);
int (*set_mclk_od)(void *handle, uint32_t value); 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); struct amd_vce_state* (*get_vce_clock_state)(void *handle, unsigned idx);
int (*reset_power_profile_state)(void *handle, int (*reset_power_profile_state)(void *handle,
struct amd_pp_profile *request); struct amd_pp_profile *request);
......
...@@ -355,7 +355,7 @@ struct pp_hwmgr_func { ...@@ -355,7 +355,7 @@ struct pp_hwmgr_func {
int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
int (*get_mclk_od)(struct pp_hwmgr *hwmgr); int (*get_mclk_od)(struct pp_hwmgr *hwmgr);
int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); 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 (*request_firmware)(struct pp_hwmgr *hwmgr);
int (*release_firmware)(struct pp_hwmgr *hwmgr); int (*release_firmware)(struct pp_hwmgr *hwmgr);
int (*set_power_profile_state)(struct pp_hwmgr *hwmgr, int (*set_power_profile_state)(struct pp_hwmgr *hwmgr,
......
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