[PATCH] iommu/amd: flush IOTLB for specific domains only (v3)

2017-05-22 Thread arindam . nath
From: Arindam Nath <arindam.n...@amd.com>

Change History
--

v3:
- add Fixes and CC tags
- add link to Bugzilla

v2: changes suggested by Joerg
- add flush flag to improve efficiency of flush operation

v1:
- The idea behind flush queues is to defer the IOTLB flushing
  for domains for which the mappings are no longer valid. We
  add such domains in queue_add(), and when the queue size
  reaches FLUSH_QUEUE_SIZE, we perform __queue_flush().

  Since we have already taken lock before __queue_flush()
  is called, we need to make sure the IOTLB flushing is
  performed as quickly as possible.

  In the current implementation, we perform IOTLB flushing
  for all domains irrespective of which ones were actually
  added in the flush queue initially. This can be quite
  expensive especially for domains for which unmapping is
  not required at this point of time.

  This patch makes use of domain information in
  'struct flush_queue_entry' to make sure we only flush
  IOTLBs for domains who need it, skipping others.

Bugzilla: https://bugs.freedesktop.org/101029
Fixes: b1516a14657a ("iommu/amd: Implement flush queue")
Cc: sta...@vger.kernel.org
Suggested-by: Joerg Roedel <j...@8bytes.org>
Signed-off-by: Arindam Nath <arindam.n...@amd.com>
---
 drivers/iommu/amd_iommu.c   | 27 ---
 drivers/iommu/amd_iommu_types.h |  2 ++
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 63cacf5..1edeebec 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2227,15 +2227,26 @@ static struct iommu_group 
*amd_iommu_device_group(struct device *dev)
 
 static void __queue_flush(struct flush_queue *queue)
 {
-   struct protection_domain *domain;
-   unsigned long flags;
int idx;
 
-   /* First flush TLB of all known domains */
-   spin_lock_irqsave(_iommu_pd_lock, flags);
-   list_for_each_entry(domain, _iommu_pd_list, list)
-   domain_flush_tlb(domain);
-   spin_unlock_irqrestore(_iommu_pd_lock, flags);
+   /* First flush TLB of all domains which were added to flush queue */
+   for (idx = 0; idx < queue->next; ++idx) {
+   struct flush_queue_entry *entry;
+
+   entry = queue->entries + idx;
+
+   /*
+* There might be cases where multiple IOVA entries for the
+* same domain are queued in the flush queue. To avoid
+* flushing the same domain again, we check whether the
+* flag is set or not. This improves the efficiency of
+* flush operation.
+*/
+   if (!entry->dma_dom->domain.already_flushed) {
+   entry->dma_dom->domain.already_flushed = true;
+   domain_flush_tlb(>dma_dom->domain);
+   }
+   }
 
/* Wait until flushes have completed */
domain_flush_complete(NULL);
@@ -2289,6 +2300,8 @@ static void queue_add(struct dma_ops_domain *dma_dom,
pages = __roundup_pow_of_two(pages);
address >>= PAGE_SHIFT;
 
+   dma_dom->domain.already_flushed = false;
+
queue = get_cpu_ptr(_queue);
spin_lock_irqsave(>lock, flags);
 
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 4de8f41..4f5519d 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -454,6 +454,8 @@ struct protection_domain {
bool updated;   /* complete domain flush required */
unsigned dev_cnt;   /* devices assigned to this domain */
unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
+   bool already_flushed;   /* flag to avoid flushing the same domain again
+  in a single invocation of __queue_flush() */
 };
 
 /*
-- 
2.7.4

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] iommu/amd: flush IOTLB for specific domains only (v2)

2017-05-19 Thread arindam . nath
From: Arindam Nath <arindam.n...@amd.com>

Change History
--

v2: changes suggested by Joerg
- add flush flag to improve efficiency of flush operation

v1:
- The idea behind flush queues is to defer the IOTLB flushing
  for domains for which the mappings are no longer valid. We
  add such domains in queue_add(), and when the queue size
  reaches FLUSH_QUEUE_SIZE, we perform __queue_flush().

  Since we have already taken lock before __queue_flush()
  is called, we need to make sure the IOTLB flushing is
  performed as quickly as possible.

  In the current implementation, we perform IOTLB flushing
  for all domains irrespective of which ones were actually
  added in the flush queue initially. This can be quite
  expensive especially for domains for which unmapping is
  not required at this point of time.

  This patch makes use of domain information in
  'struct flush_queue_entry' to make sure we only flush
  IOTLBs for domains who need it, skipping others.

Suggested-by: Joerg Roedel <j...@8bytes.org>
Signed-off-by: Arindam Nath <arindam.n...@amd.com>
---
 drivers/iommu/amd_iommu.c   | 27 ---
 drivers/iommu/amd_iommu_types.h |  2 ++
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 63cacf5..1edeebec 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2227,15 +2227,26 @@ static struct iommu_group 
*amd_iommu_device_group(struct device *dev)
 
 static void __queue_flush(struct flush_queue *queue)
 {
-   struct protection_domain *domain;
-   unsigned long flags;
int idx;
 
-   /* First flush TLB of all known domains */
-   spin_lock_irqsave(_iommu_pd_lock, flags);
-   list_for_each_entry(domain, _iommu_pd_list, list)
-   domain_flush_tlb(domain);
-   spin_unlock_irqrestore(_iommu_pd_lock, flags);
+   /* First flush TLB of all domains which were added to flush queue */
+   for (idx = 0; idx < queue->next; ++idx) {
+   struct flush_queue_entry *entry;
+
+   entry = queue->entries + idx;
+
+   /*
+* There might be cases where multiple IOVA entries for the
+* same domain are queued in the flush queue. To avoid
+* flushing the same domain again, we check whether the
+* flag is set or not. This improves the efficiency of
+* flush operation.
+*/
+   if (!entry->dma_dom->domain.already_flushed) {
+   entry->dma_dom->domain.already_flushed = true;
+   domain_flush_tlb(>dma_dom->domain);
+   }
+   }
 
/* Wait until flushes have completed */
domain_flush_complete(NULL);
@@ -2289,6 +2300,8 @@ static void queue_add(struct dma_ops_domain *dma_dom,
pages = __roundup_pow_of_two(pages);
address >>= PAGE_SHIFT;
 
+   dma_dom->domain.already_flushed = false;
+
queue = get_cpu_ptr(_queue);
spin_lock_irqsave(>lock, flags);
 
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 4de8f41..4f5519d 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -454,6 +454,8 @@ struct protection_domain {
bool updated;   /* complete domain flush required */
unsigned dev_cnt;   /* devices assigned to this domain */
unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
+   bool already_flushed;   /* flag to avoid flushing the same domain again
+  in a single invocation of __queue_flush() */
 };
 
 /*
-- 
2.7.4

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] iommu/amd: flush IOTLB for specific domains only

2017-03-27 Thread arindam . nath
From: Arindam Nath <arindam.n...@amd.com>

The idea behind flush queues is to defer the IOTLB flushing
for domains for which the mappings are no longer valid. We
add such domains in queue_add(), and when the queue size
reaches FLUSH_QUEUE_SIZE, we perform __queue_flush().

Since we have already taken lock before __queue_flush()
is called, we need to make sure the IOTLB flushing is
performed as quickly as possible.

In the current implementation, we perform IOTLB flushing
for all domains irrespective of which ones were actually
added in the flush queue initially. This can be quite
expensive especially for domains for which unmapping is
not required at this point of time.

This patch makes use of domain information in
'struct flush_queue_entry' to make sure we only flush
IOTLBs for domains who need it, skipping others.

Signed-off-by: Arindam Nath <arindam.n...@amd.com>
---
 drivers/iommu/amd_iommu.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 98940d1..6a9a048 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2227,15 +2227,16 @@ static struct iommu_group 
*amd_iommu_device_group(struct device *dev)
 
 static void __queue_flush(struct flush_queue *queue)
 {
-   struct protection_domain *domain;
-   unsigned long flags;
int idx;
 
-   /* First flush TLB of all known domains */
-   spin_lock_irqsave(_iommu_pd_lock, flags);
-   list_for_each_entry(domain, _iommu_pd_list, list)
-   domain_flush_tlb(domain);
-   spin_unlock_irqrestore(_iommu_pd_lock, flags);
+   /* First flush TLB of all domains which were added to flush queue */
+   for (idx = 0; idx < queue->next; ++idx) {
+   struct flush_queue_entry *entry;
+
+   entry = queue->entries + idx;
+
+   domain_flush_tlb(>dma_dom->domain);
+   }
 
/* Wait until flushes have completed */
domain_flush_complete(NULL);
-- 
1.9.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH v2] amdgpu: sync amdgpu_drm.h with the kernel

2017-01-09 Thread Arindam Nath
v1:
* User might want to query the maximum number of UVD
  instances supported by firmware. In addition to that,
  if there are multiple applications using UVD handles
  at the same time, he might also want to query the
  currently used number of handles.

  For this we add a new query AMDGPU_INFO_NUM_HANDLES
  and a new struct drm_amdgpu_info_num_handles to
  get these values.

v2:
* Generated using make headers_install.
* Generated from linux-stable/master commit
  a121103c922847ba5010819a3f250f1f7fc84ab8

Suggested-by: Emil Velikov <emil.l.veli...@gmail.com>
Signed-off-by: Arindam Nath <arindam.n...@amd.com>
Reviewed-by: Christian König <christian.koe...@amd.com>
---
 include/drm/amdgpu_drm.h | 106 +++
 1 file changed, 106 insertions(+)

diff --git a/include/drm/amdgpu_drm.h b/include/drm/amdgpu_drm.h
index d8f2497..d4e49de 100644
--- a/include/drm/amdgpu_drm.h
+++ b/include/drm/amdgpu_drm.h
@@ -50,6 +50,7 @@ extern "C" {
 #define DRM_AMDGPU_WAIT_CS 0x09
 #define DRM_AMDGPU_GEM_OP  0x10
 #define DRM_AMDGPU_GEM_USERPTR 0x11
+#define DRM_AMDGPU_WAIT_FENCES 0x12
 
 #define DRM_IOCTL_AMDGPU_GEM_CREATEDRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
 #define DRM_IOCTL_AMDGPU_GEM_MMAP  DRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
@@ -63,6 +64,7 @@ extern "C" {
 #define DRM_IOCTL_AMDGPU_WAIT_CS   DRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs)
 #define DRM_IOCTL_AMDGPU_GEM_OPDRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op)
 #define DRM_IOCTL_AMDGPU_GEM_USERPTR   DRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr)
+#define DRM_IOCTL_AMDGPU_WAIT_FENCES   DRM_IOWR(DRM_COMMAND_BASE + 
DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences)
 
 #define AMDGPU_GEM_DOMAIN_CPU  0x1
 #define AMDGPU_GEM_DOMAIN_GTT  0x2
@@ -79,6 +81,10 @@ extern "C" {
 #define AMDGPU_GEM_CREATE_CPU_GTT_USWC (1 << 2)
 /* Flag that the memory should be in VRAM and cleared */
 #define AMDGPU_GEM_CREATE_VRAM_CLEARED (1 << 3)
+/* Flag that create shadow bo(GTT) while allocating vram bo */
+#define AMDGPU_GEM_CREATE_SHADOW   (1 << 4)
+/* Flag that allocating the BO should use linear VRAM */
+#define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS  (1 << 5)
 
 struct drm_amdgpu_gem_create_in  {
/** the requested memory size */
@@ -303,6 +309,32 @@ union drm_amdgpu_wait_cs {
struct drm_amdgpu_wait_cs_out out;
 };
 
+struct drm_amdgpu_fence {
+   uint32_t ctx_id;
+   uint32_t ip_type;
+   uint32_t ip_instance;
+   uint32_t ring;
+   uint64_t seq_no;
+};
+
+struct drm_amdgpu_wait_fences_in {
+   /** This points to uint64_t * which points to fences */
+   uint64_t fences;
+   uint32_t fence_count;
+   uint32_t wait_all;
+   uint64_t timeout_ns;
+};
+
+struct drm_amdgpu_wait_fences_out {
+   uint32_t status;
+   uint32_t first_signaled;
+};
+
+union drm_amdgpu_wait_fences {
+   struct drm_amdgpu_wait_fences_in in;
+   struct drm_amdgpu_wait_fences_out out;
+};
+
 #define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO  0
 #define AMDGPU_GEM_OP_SET_PLACEMENT1
 
@@ -434,6 +466,7 @@ struct drm_amdgpu_cs_chunk_data {
  *
  */
 #define AMDGPU_IDS_FLAGS_FUSION 0x1
+#define AMDGPU_IDS_FLAGS_PREEMPTION 0x2
 
 /* indicate if acceleration can be working */
 #define AMDGPU_INFO_ACCEL_WORKING  0x00
@@ -483,6 +516,20 @@ struct drm_amdgpu_cs_chunk_data {
 #define AMDGPU_INFO_DEV_INFO   0x16
 /* visible vram usage */
 #define AMDGPU_INFO_VIS_VRAM_USAGE 0x17
+/* number of TTM buffer evictions */
+#define AMDGPU_INFO_NUM_EVICTIONS  0x18
+/* Query memory about VRAM and GTT domains */
+#define AMDGPU_INFO_MEMORY 0x19
+/* Query vce clock table */
+#define AMDGPU_INFO_VCE_CLOCK_TABLE0x1A
+/* Query vbios related information */
+#define AMDGPU_INFO_VBIOS  0x1B
+   /* Subquery id: Query vbios size */
+   #define AMDGPU_INFO_VBIOS_SIZE  0x1
+   /* Subquery id: Query vbios image */
+   #define AMDGPU_INFO_VBIOS_IMAGE 0x2
+/* Query UVD handles */
+#define AMDGPU_INFO_NUM_HANDLES0x1C
 
 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
 #define AMDGPU_INFO_MMR_SE_INDEX_MASK  0xff
@@ -541,6 +588,11 @@ struct drm_amdgpu_info {
} read_mmr_reg;
 
struct drm_amdgpu_query_fw query_fw;
+
+   struct {
+   uint32_t type;
+   uint32_t offset;
+   } vbios_info;
};
 };
 
@@ -568,6 +620,34 @@ struct drm_amdgpu_info_vram_gtt {
uint64_t gtt_size;
 };
 
+struct drm_amdgpu_heap_inf

[PATCH] amdgpu: get maximum and used UVD handles

2016-12-12 Thread arindam . nath
From: Arindam Nath <arindam.n...@amd.com>

User might want to query the maximum number of UVD
instances supported by firmware. In addition to that,
if there are multiple applications using UVD handles
at the same time, he might also want to query the
currently used number of handles.

For this we add a new query AMDGPU_INFO_NUM_HANDLES
and a new struct drm_amdgpu_info_num_handles to
get these values.

Signed-off-by: Arindam Nath <arindam.n...@amd.com>
Reviewed-by: Christian König <christian.koe...@amd.com>
---
 include/drm/amdgpu_drm.h | 9 +
 1 file changed, 9 insertions(+)

diff --git a/include/drm/amdgpu_drm.h b/include/drm/amdgpu_drm.h
index d8f2497..89fda6b 100644
--- a/include/drm/amdgpu_drm.h
+++ b/include/drm/amdgpu_drm.h
@@ -483,6 +483,8 @@ struct drm_amdgpu_cs_chunk_data {
 #define AMDGPU_INFO_DEV_INFO   0x16
 /* visible vram usage */
 #define AMDGPU_INFO_VIS_VRAM_USAGE 0x17
+/* Query UVD handles */
+#define AMDGPU_INFO_NUM_HANDLES0x1C
 
 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
 #define AMDGPU_INFO_MMR_SE_INDEX_MASK  0xff
@@ -641,6 +643,13 @@ struct drm_amdgpu_info_hw_ip {
uint32_t  _pad;
 };
 
+struct drm_amdgpu_info_num_handles {
+   /** Max handles as supported by firmware for UVD */
+   uint32_t  uvd_max_handles;
+   /** Handles currently in use for UVD */
+   uint32_t  uvd_used_handles;
+};
+
 /*
  * Supported GPU families
  */
-- 
1.9.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 1/1] drm/amd/amdgpu: get maximum and used UVD handles (v3)

2016-12-12 Thread arindam . nath
From: Arindam Nath <arindam.n...@amd.com>

Change History
--

v3: changes suggested by Christian
- Add a check for UVD IP block using AMDGPU_HW_IP_UVD
  query type.
- Add a check for asic_type to be less than
  CHIP_POLARIS10 since starting Polaris, we support
  unlimited UVD instances.
- Add kerneldoc style comment for
  amdgpu_uvd_used_handles().

v2: as suggested by Christian
- Add a new query AMDGPU_INFO_NUM_HANDLES
- Create a helper function to return the number
  of currently used UVD handles.
- Modify the logic to count the number of used
  UVD handles since handles can be freed in
  non-linear fashion.

v1:
- User might want to query the maximum number of UVD
  instances supported by firmware. In addition to that,
  if there are multiple applications using UVD handles
  at the same time, he might also want to query the
  currently used number of handles.

  For this we add two variables max_handles and
  used_handles inside drm_amdgpu_info_hw_ip. So now
  an application (or libdrm) can use AMDGPU_INFO IOCTL
  with AMDGPU_INFO_HW_IP_INFO query type to get these
  values.

Signed-off-by: Arindam Nath <arindam.n...@amd.com>
Reviewed-by: Christian König <christian.koe...@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 21 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 25 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h |  1 +
 include/uapi/drm/amdgpu_drm.h   |  9 +
 4 files changed, 56 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 174eb59..3273d8c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -570,6 +570,27 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void 
*data, struct drm_file
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, ,
+   min((size_t)size, sizeof(handle))) ? 
-EFAULT : 0;
+   } else {
+   return -EINVAL;
+   }
+
+   break;
+   default:
+   return -EINVAL;
+   }
+   }
default:
DRM_DEBUG_KMS("Invalid request %d\n", info->query);
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index a8816ba..02187fd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -1173,3 +1173,28 @@ int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, 
long timeout)
 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(>uvd.handles[i]))
+   used_handles++;
+   }
+
+   return used_handles;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
index c850009..0fee861 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
@@ -38,5 +38,6 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, 
uint32_t ib_idx);
 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
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index bea9875..2cf8df8 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -530,6 +530,8 @@ struct drm_amdgpu_cs_chunk_data {
#define AMDGPU_INFO_VBIOS_SIZE  0x1
/* Subquery id: Query vbios image */
#define AMDGPU_INFO_VBIOS_IMAGE 0x2
+/* Query UVD handles */
+#define AMDGPU_INFO_NUM_HANDLES0x1C