From: Iouri Tarassov <[email protected]>

Implement the ioctl to query video memory information from the host
(LX_DXQUERYVIDEOMEMORYINFO).

Signed-off-by: Iouri Tarassov <[email protected]>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <[email protected]>
---
 drivers/hv/dxgkrnl/dxgkrnl.h  |  5 +++
 drivers/hv/dxgkrnl/dxgvmbus.c | 64 +++++++++++++++++++++++++++++++++++
 drivers/hv/dxgkrnl/dxgvmbus.h | 14 ++++++++
 drivers/hv/dxgkrnl/ioctl.c    | 50 ++++++++++++++++++++++++++-
 include/uapi/misc/d3dkmthk.h  | 13 +++++++
 5 files changed, 145 insertions(+), 1 deletion(-)

diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index ced9dd294f5f..b6a7288a4177 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -894,6 +894,11 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess 
*process,
                                      struct dxgadapter *adapter,
                                      struct d3dkmt_queryallocationresidency
                                      *args);
+int dxgvmb_send_query_vidmem_info(struct dxgprocess *process,
+                                 struct dxgadapter *adapter,
+                                 struct d3dkmt_queryvideomemoryinfo *args,
+                                 struct d3dkmt_queryvideomemoryinfo
+                                 *__user iargs);
 int dxgvmb_send_get_device_state(struct dxgprocess *process,
                                 struct dxgadapter *adapter,
                                 struct d3dkmt_getdevicestate *args,
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 928fad5f133b..48ff49456057 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -1925,6 +1925,70 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess 
*process,
        return ret;
 }
 
+int dxgvmb_send_query_vidmem_info(struct dxgprocess *process,
+                                 struct dxgadapter *adapter,
+                                 struct d3dkmt_queryvideomemoryinfo *args,
+                                 struct d3dkmt_queryvideomemoryinfo *__user
+                                 output)
+{
+       int ret;
+       struct dxgkvmb_command_queryvideomemoryinfo *command;
+       struct dxgkvmb_command_queryvideomemoryinfo_return result = { };
+       struct dxgvmbusmsg msg = {.hdr = NULL};
+
+       ret = init_message(&msg, adapter, process, sizeof(*command));
+       if (ret)
+               goto cleanup;
+       command = (void *)msg.msg;
+       command_vgpu_to_host_init2(&command->hdr,
+                                  dxgk_vmbcommand_queryvideomemoryinfo,
+                                  process->host_handle);
+       command->adapter = args->adapter;
+       command->memory_segment_group = args->memory_segment_group;
+       command->physical_adapter_index = args->physical_adapter_index;
+
+       ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
+                                  &result, sizeof(result));
+       if (ret < 0)
+               goto cleanup;
+
+       ret = copy_to_user(&output->budget, &result.budget,
+                          sizeof(output->budget));
+       if (ret) {
+               pr_err("%s failed to copy budget", __func__);
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       ret = copy_to_user(&output->current_usage, &result.current_usage,
+                          sizeof(output->current_usage));
+       if (ret) {
+               pr_err("%s failed to copy current usage", __func__);
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       ret = copy_to_user(&output->current_reservation,
+                          &result.current_reservation,
+                          sizeof(output->current_reservation));
+       if (ret) {
+               pr_err("%s failed to copy reservation", __func__);
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       ret = copy_to_user(&output->available_for_reservation,
+                          &result.available_for_reservation,
+                          sizeof(output->available_for_reservation));
+       if (ret) {
+               pr_err("%s failed to copy avail reservation", __func__);
+               ret = -EINVAL;
+       }
+
+cleanup:
+       free_message(&msg, process);
+       if (ret)
+               dev_dbg(DXGDEV, "err: %d", ret);
+       return ret;
+}
+
 int dxgvmb_send_get_device_state(struct dxgprocess *process,
                                 struct dxgadapter *adapter,
                                 struct d3dkmt_getdevicestate *args,
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
index d232eb234e2c..a1549983d50f 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.h
+++ b/drivers/hv/dxgkrnl/dxgvmbus.h
@@ -664,6 +664,20 @@ struct dxgkvmb_command_queryallocationresidency_return {
        /* d3dkmt_allocationresidencystatus[NumAllocations] */
 };
 
+struct dxgkvmb_command_queryvideomemoryinfo {
+       struct dxgkvmb_command_vgpu_to_host hdr;
+       struct d3dkmthandle             adapter;
+       enum d3dkmt_memory_segment_group memory_segment_group;
+       u32                             physical_adapter_index;
+};
+
+struct dxgkvmb_command_queryvideomemoryinfo_return {
+       u64                     budget;
+       u64                     current_usage;
+       u64                     current_reservation;
+       u64                     available_for_reservation;
+};
+
 struct dxgkvmb_command_getdevicestate {
        struct dxgkvmb_command_vgpu_to_host hdr;
        struct d3dkmt_getdevicestate    args;
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 8b7d00e4c881..e692b127e219 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -3547,6 +3547,54 @@ dxgkio_flush_heap_transitions(struct dxgprocess 
*process, void *__user inargs)
        return ret;
 }
 
+static int
+dxgkio_query_vidmem_info(struct dxgprocess *process, void *__user inargs)
+{
+       struct d3dkmt_queryvideomemoryinfo args;
+       int ret;
+       struct dxgadapter *adapter = NULL;
+       bool adapter_locked = false;
+
+       ret = copy_from_user(&args, inargs, sizeof(args));
+       if (ret) {
+               DXG_ERR("failed to copy input args");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       if (args.process != 0) {
+               DXG_ERR("query vidmem info from another process");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       adapter = dxgprocess_adapter_by_handle(process, args.adapter);
+       if (adapter == NULL) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       ret = dxgadapter_acquire_lock_shared(adapter);
+       if (ret < 0) {
+               adapter = NULL;
+               goto cleanup;
+       }
+       adapter_locked = true;
+
+       args.adapter = adapter->host_handle;
+       ret = dxgvmb_send_query_vidmem_info(process, adapter, &args, inargs);
+
+cleanup:
+
+       if (adapter_locked)
+               dxgadapter_release_lock_shared(adapter);
+       if (adapter)
+               kref_put(&adapter->adapter_kref, dxgadapter_release);
+       if (ret < 0)
+               DXG_ERR("failed: %x", ret);
+       return ret;
+}
+
 static int
 dxgkio_get_device_state(struct dxgprocess *process, void *__user inargs)
 {
@@ -4287,7 +4335,7 @@ static struct ioctl_desc ioctls[] = {
 /* 0x07 */     {dxgkio_create_paging_queue, LX_DXCREATEPAGINGQUEUE},
 /* 0x08 */     {},
 /* 0x09 */     {dxgkio_query_adapter_info, LX_DXQUERYADAPTERINFO},
-/* 0x0a */     {},
+/* 0x0a */     {dxgkio_query_vidmem_info, LX_DXQUERYVIDEOMEMORYINFO},
 /* 0x0b */     {},
 /* 0x0c */     {},
 /* 0x0d */     {},
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index 873feb951129..b7d8b1d91cfc 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -897,6 +897,17 @@ enum d3dkmt_memory_segment_group {
        _D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL  = 1
 };
 
+struct d3dkmt_queryvideomemoryinfo {
+       __u64                                   process;
+       struct d3dkmthandle                     adapter;
+       enum d3dkmt_memory_segment_group        memory_segment_group;
+       __u64                                   budget;
+       __u64                                   current_usage;
+       __u64                                   current_reservation;
+       __u64                                   available_for_reservation;
+       __u32                                   physical_adapter_index;
+};
+
 struct d3dkmt_adaptertype {
        union {
                struct {
@@ -1204,6 +1215,8 @@ struct d3dkmt_shareobjectwithhost {
        _IOWR(0x47, 0x07, struct d3dkmt_createpagingqueue)
 #define LX_DXQUERYADAPTERINFO          \
        _IOWR(0x47, 0x09, struct d3dkmt_queryadapterinfo)
+#define LX_DXQUERYVIDEOMEMORYINFO      \
+       _IOWR(0x47, 0x0a, struct d3dkmt_queryvideomemoryinfo)
 #define LX_DXGETDEVICESTATE            \
        _IOWR(0x47, 0x0e, struct d3dkmt_getdevicestate)
 #define LX_DXSUBMITCOMMAND             \

Reply via email to