drm/amd/amdgpu: Update read_sensor calls to have size parameter (v3)
authorTom St Denis <tom.stdenis@amd.com>
Thu, 9 Feb 2017 19:29:01 +0000 (14:29 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 30 Mar 2017 03:52:59 +0000 (23:52 -0400)
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 <tom.stdenis@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h

index 552452a654a52798d34431adac60a2a7d4b2e5b9..f186c20f636b1e83ec932eed9a851241439f6dcc 100644 (file)
@@ -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,
index 5f09893c96745bbc63fcac371cf9fff73d92d45b..5dd9daae9eef35ea585605508ca9264ec01e1357 100644 (file)
@@ -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) \
index 8a9a75a44b626063c1561feba663e46e17ee1868..da877f3c10fc6f74950c0186a9d4b9b0e12cd9ac 100644 (file)
@@ -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);
                }
        }
index 81e6856ffa11426d9ff1204597432ed967b98a76..fde8fcd46b58409187b6d4c4b37e16246818b607 100644 (file)
@@ -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*
index edc3029df785fad83952aa6cfdbe5b1c891dcff4..7aa5ca815a3aadfe95d3b1bff0b625761ee995aa 100644 (file)
@@ -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) {
index 5a4ee43b3d65d837c7a058c0e3ebfbbe52f657e5..13b35be3174c6791421b0fd690f3c2174272345c 100644 (file)
@@ -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;
index ab99013eba77a632c0cc5ef97f241e7b292a2d0d..c0bf3af6846d30c891136d865b82b5fad501b224 100644 (file)
@@ -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);
index fa3bf50eff822909365d889ce2ac8cb9bd6818c4..8cf5aed055b6e0ce18c882af5d8747ef769c44ed 100644 (file)
@@ -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,