drm/amdgpu: expose GPU sensor related information
authorAlex Deucher <alexander.deucher@amd.com>
Wed, 8 Mar 2017 23:25:15 +0000 (18:25 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 30 Mar 2017 03:53:05 +0000 (23:53 -0400)
This includes shader/memory clocks, temperature, GPU load, etc.

v2: - add sub-queries for AMDPGU_INFO_GPU_SENSOR_*
    - do not break the ABI
v3: - return -ENOENT when amdgpu_dpm == 0
    - expose more sensor queries
v4: - s/GPU_POWER/GPU_AVG_POWER/
    - improve VDDNB/VDDGFX query description
    - fix amdgpu_dpm check
v5: - agd: fix warning
v6: - agd: bump version

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
include/uapi/drm/amdgpu_drm.h

index b76cd699eb0d7357d79d68f9da4fd9bd02f3e132..6d5d0a74ad2c8487a0d6df60313dcf5065c26958 100644 (file)
  * - 3.8.0 - Add support raster config init in the kernel
  * - 3.9.0 - Add support for memory query info about VRAM and GTT.
  * - 3.10.0 - Add support for new fences ioctl, new gem ioctl flags
+ * - 3.11.0 - Add support for sensor query info (clocks, temp, etc).
  */
 #define KMS_DRIVER_MAJOR       3
-#define KMS_DRIVER_MINOR       10
+#define KMS_DRIVER_MINOR       11
 #define KMS_DRIVER_PATCHLEVEL  0
 
 int amdgpu_vram_limit = 0;
index 49f93ee019e310617fd84d50fa8aaf73e0ca51e6..027692bf8457dbfaf478ce829d8380d11b22a2ad 100644 (file)
@@ -240,6 +240,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
        uint32_t ui32 = 0;
        uint64_t ui64 = 0;
        int i, found;
+       int ui32_size = sizeof(ui32);
 
        if (!info->return_size || !info->return_pointer)
                return -EINVAL;
@@ -596,6 +597,80 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                        return -EINVAL;
                }
        }
+       case AMDGPU_INFO_SENSOR: {
+               struct pp_gpu_power query = {0};
+               int query_size = sizeof(query);
+
+               if (amdgpu_dpm == 0)
+                       return -ENOENT;
+
+               switch (info->sensor_info.type) {
+               case AMDGPU_INFO_SENSOR_GFX_SCLK:
+                       /* get sclk in Mhz */
+                       if (amdgpu_dpm_read_sensor(adev,
+                                                  AMDGPU_PP_SENSOR_GFX_SCLK,
+                                                  (void *)&ui32, &ui32_size)) {
+                               return -EINVAL;
+                       }
+                       ui32 /= 100;
+                       break;
+               case AMDGPU_INFO_SENSOR_GFX_MCLK:
+                       /* get mclk in Mhz */
+                       if (amdgpu_dpm_read_sensor(adev,
+                                                  AMDGPU_PP_SENSOR_GFX_MCLK,
+                                                  (void *)&ui32, &ui32_size)) {
+                               return -EINVAL;
+                       }
+                       ui32 /= 100;
+                       break;
+               case AMDGPU_INFO_SENSOR_GPU_TEMP:
+                       /* get temperature in millidegrees C */
+                       if (amdgpu_dpm_read_sensor(adev,
+                                                  AMDGPU_PP_SENSOR_GPU_TEMP,
+                                                  (void *)&ui32, &ui32_size)) {
+                               return -EINVAL;
+                       }
+                       break;
+               case AMDGPU_INFO_SENSOR_GPU_LOAD:
+                       /* get GPU load */
+                       if (amdgpu_dpm_read_sensor(adev,
+                                                  AMDGPU_PP_SENSOR_GPU_LOAD,
+                                                  (void *)&ui32, &ui32_size)) {
+                               return -EINVAL;
+                       }
+                       break;
+               case AMDGPU_INFO_SENSOR_GPU_AVG_POWER:
+                       /* get average GPU power */
+                       if (amdgpu_dpm_read_sensor(adev,
+                                                  AMDGPU_PP_SENSOR_GPU_POWER,
+                                                  (void *)&query, &query_size)) {
+                               return -EINVAL;
+                       }
+                       ui32 = query.average_gpu_power >> 8;
+                       break;
+               case AMDGPU_INFO_SENSOR_VDDNB:
+                       /* get VDDNB in millivolts */
+                       if (amdgpu_dpm_read_sensor(adev,
+                                                  AMDGPU_PP_SENSOR_VDDNB,
+                                                  (void *)&ui32, &ui32_size)) {
+                               return -EINVAL;
+                       }
+                       break;
+               case AMDGPU_INFO_SENSOR_VDDGFX:
+                       /* get VDDGFX in millivolts */
+                       if (amdgpu_dpm_read_sensor(adev,
+                                                  AMDGPU_PP_SENSOR_VDDGFX,
+                                                  (void *)&ui32, &ui32_size)) {
+                               return -EINVAL;
+                       }
+                       break;
+               default:
+                       DRM_DEBUG_KMS("Invalid request %d\n",
+                                     info->sensor_info.type);
+                       return -EINVAL;
+               }
+               return copy_to_user(out, &ui32, min(size, 4u)) ? -EFAULT : 0;
+       }
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->query);
                return -EINVAL;
index 1c0ddf71193e562a89e647e7da101b8290c362f1..a30fe693175fb3a6f2ed4865ba786600f8ffcc85 100644 (file)
@@ -532,6 +532,22 @@ struct drm_amdgpu_cs_chunk_data {
        #define AMDGPU_INFO_VBIOS_IMAGE         0x2
 /* Query UVD handles */
 #define AMDGPU_INFO_NUM_HANDLES                        0x1C
+/* Query sensor related information */
+#define AMDGPU_INFO_SENSOR                     0x1D
+       /* Subquery id: Query GPU shader clock */
+       #define AMDGPU_INFO_SENSOR_GFX_SCLK             0x1
+       /* Subquery id: Query GPU memory clock */
+       #define AMDGPU_INFO_SENSOR_GFX_MCLK             0x2
+       /* Subquery id: Query GPU temperature */
+       #define AMDGPU_INFO_SENSOR_GPU_TEMP             0x3
+       /* Subquery id: Query GPU load */
+       #define AMDGPU_INFO_SENSOR_GPU_LOAD             0x4
+       /* Subquery id: Query average GPU power */
+       #define AMDGPU_INFO_SENSOR_GPU_AVG_POWER        0x5
+       /* Subquery id: Query northbridge voltage */
+       #define AMDGPU_INFO_SENSOR_VDDNB                0x6
+       /* Subquery id: Query graphics voltage */
+       #define AMDGPU_INFO_SENSOR_VDDGFX               0x7
 
 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
 #define AMDGPU_INFO_MMR_SE_INDEX_MASK  0xff
@@ -595,6 +611,10 @@ struct drm_amdgpu_info {
                        __u32 type;
                        __u32 offset;
                } vbios_info;
+
+               struct {
+                       __u32 type;
+               } sensor_info;
        };
 };