AMDGPU_INFO_xxx has lots of different queries, and only a small
number of them actually reaches out to the GPU.

This commit extract the amdgpu_info_ioctl implementation to a
helper function, and then wrap it with the runtime pm logic
each query type needs.

Signed-off-by: Pierre-Eric Pelloux-Prayer <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c |  2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 94 ++++++++++++++++++++-----
 2 files changed, 80 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index d21d5af7f187..f51f121d804e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2871,6 +2871,8 @@ long amdgpu_drm_ioctl(struct file *filp,
 
        if (is_driver_ioctl) {
                switch (nr - DRM_COMMAND_BASE) {
+               /* amdgpu_info_ioctl will resume the device if it needs to. */
+               case DRM_AMDGPU_INFO:
                /* These 4 only operate on kernel data structure. */
                case DRM_AMDGPU_VM:
                case DRM_AMDGPU_SCHED:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 260cd0ad286d..b32ff6e1baaf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -543,22 +543,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
        return 0;
 }
 
-/*
- * Userspace get information ioctl
- */
-/**
- * amdgpu_info_ioctl - answer a device specific request.
- *
- * @dev: drm device pointer
- * @data: request object
- * @filp: drm filp
- *
- * This function is used to pass device specific parameters to the userspace
- * drivers.  Examples include: pci device id, pipeline parms, tiling params,
- * etc. (all asics).
- * Returns 0 on success, -EINVAL on failure.
- */
-int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file 
*filp)
+static int amdgpu_info(struct drm_device *dev, void *data, struct drm_file 
*filp)
 {
        struct amdgpu_device *adev = drm_to_adev(dev);
        struct drm_amdgpu_info *info = data;
@@ -1278,6 +1263,83 @@ int amdgpu_info_ioctl(struct drm_device *dev, void 
*data, struct drm_file *filp)
        return 0;
 }
 
+/*
+ * Userspace get information ioctl
+ */
+/**
+ * amdgpu_info_ioctl - answer a device specific request.
+ *
+ * @dev: drm device pointer
+ * @data: request object
+ * @filp: drm filp
+ *
+ * This function is used to pass device specific parameters to the userspace
+ * drivers.  Examples include: pci device id, pipeline parms, tiling params,
+ * etc. (all asics).
+ * Returns 0 on success, -EINVAL on failure.
+ */
+int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file 
*filp)
+{
+       struct drm_amdgpu_info *info = data;
+       bool need_runtime_pm;
+       int ret;
+
+       if (!info->return_size || !info->return_pointer)
+               return -EINVAL;
+
+       switch (info->query) {
+       case AMDGPU_INFO_ACCEL_WORKING:
+       case AMDGPU_INFO_CRTC_FROM_ID:
+       case AMDGPU_INFO_HW_IP_INFO:
+       case AMDGPU_INFO_HW_IP_COUNT:
+       case AMDGPU_INFO_FW_VERSION:
+       case AMDGPU_INFO_NUM_BYTES_MOVED:
+       case AMDGPU_INFO_NUM_EVICTIONS:
+       case AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS:
+       case AMDGPU_INFO_VRAM_USAGE:
+       case AMDGPU_INFO_VIS_VRAM_USAGE:
+       case AMDGPU_INFO_GTT_USAGE:
+       case AMDGPU_INFO_GDS_CONFIG:
+       case AMDGPU_INFO_VRAM_GTT:
+       case AMDGPU_INFO_MEMORY:
+       case AMDGPU_INFO_VCE_CLOCK_TABLE:
+       case AMDGPU_INFO_VBIOS:
+       case AMDGPU_INFO_NUM_HANDLES:
+       case AMDGPU_INFO_VRAM_LOST_COUNTER:
+       case AMDGPU_INFO_RAS_ENABLED_FEATURES:
+       case AMDGPU_INFO_VIDEO_CAPS:
+       case AMDGPU_INFO_MAX_IBS:
+       case AMDGPU_INFO_GPUVM_FAULT:
+               need_runtime_pm = false;
+               break;
+
+       case AMDGPU_INFO_TIMESTAMP:
+       case AMDGPU_INFO_READ_MMR_REG:
+       case AMDGPU_INFO_DEV_INFO:
+       case AMDGPU_INFO_SENSOR:
+               need_runtime_pm = true;
+               break;
+       default:
+               DRM_DEBUG_KMS("Invalid request %d\n", info->query);
+               return -EINVAL;
+       }
+
+       if (need_runtime_pm) {
+               ret = pm_runtime_get_sync(dev->dev);
+               if (ret < 0)
+                       goto put_pm;
+       }
+
+       ret = amdgpu_info(dev, data, filp);
+
+put_pm:
+       if (need_runtime_pm) {
+               pm_runtime_mark_last_busy(dev->dev);
+               pm_runtime_put_autosuspend(dev->dev);
+       }
+
+       return ret;
+}
 
 /*
  * Outdated mess for old drm with Xorg being in charge (void function now).
-- 
2.40.1

Reply via email to