return -EINVAL;
                }
        }
+       case AMDGPU_INFO_NUM_HANDLES: {
+               struct drm_amdgpu_info_num_handles handle;
+
+               switch (info->query_hw_ip.type) {
+               case AMDGPU_HW_IP_UVD:
+                       /* Starting Polaris, we support unlimited UVD handles */
+                       if (adev->asic_type < CHIP_POLARIS10) {
+                               handle.uvd_max_handles = adev->uvd.max_handles;
+                               handle.uvd_used_handles = amdgpu_uvd_used_handles(adev);
+
+                               return copy_to_user(out, &handle,
+                                       min((size_t)size, sizeof(handle))) ? -EFAULT : 0;
+                       } else {
+                               return -ENODATA;
+                       }
+
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->query);
                return -EINVAL;
 
 error:
        return r;
 }
+
+/**
+ * amdgpu_uvd_used_handles - returns used UVD handles
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Returns the number of UVD handles in use
+ */
+uint32_t amdgpu_uvd_used_handles(struct amdgpu_device *adev)
+{
+       unsigned i;
+       uint32_t used_handles = 0;
+
+       for (i = 0; i < adev->uvd.max_handles; ++i) {
+               /*
+                * Handles can be freed in any order, and not
+                * necessarily linear. So we need to count
+                * all non-zero handles.
+                */
+               if (atomic_read(&adev->uvd.handles[i]))
+                       used_handles++;
+       }
+
+       return used_handles;
+}
 
 void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring);
 void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring);
 int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout);
+uint32_t amdgpu_uvd_used_handles(struct amdgpu_device *adev);
 
 #endif
 
        #define AMDGPU_INFO_VBIOS_SIZE          0x1
        /* Subquery id: Query vbios image */
        #define AMDGPU_INFO_VBIOS_IMAGE         0x2
+/* Query UVD handles */
+#define AMDGPU_INFO_NUM_HANDLES                        0x1C
 
 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
 #define AMDGPU_INFO_MMR_SE_INDEX_MASK  0xff
        __u32  _pad;
 };
 
+struct drm_amdgpu_info_num_handles {
+       /** Max handles as supported by firmware for UVD */
+       __u32  uvd_max_handles;
+       /** Handles currently in use for UVD */
+       __u32  uvd_used_handles;
+};
+
 #define AMDGPU_VCE_CLOCK_TABLE_ENTRIES         6
 
 struct drm_amdgpu_info_vce_clock_table_entry {