Implement iocts to manage compute device scheduling priority: - LX_DXGETCONTEXTINPROCESSSCHEDULINGPRIORITY - LX_DXGETCONTEXTSCHEDULINGPRIORITY - LX_DXSETCONTEXTINPROCESSSCHEDULINGPRIORITY - LX_DXSETCONTEXTSCHEDULINGPRIORITY Each compute device execution context has an assigned scheduling priority. It is used by the compute device scheduler on the host to pick contexts for execution. There is a global priority and a priority within a process. Signed-off-by: Iouri Tarassov <iourit@xxxxxxxxxxxxxxxxxxx> --- drivers/hv/dxgkrnl/dxgkrnl.h | 9 ++ drivers/hv/dxgkrnl/dxgvmbus.c | 63 +++++++++++++ drivers/hv/dxgkrnl/dxgvmbus.h | 19 ++++ drivers/hv/dxgkrnl/ioctl.c | 173 ++++++++++++++++++++++++++++++++++ include/uapi/misc/d3dkmthk.h | 28 ++++++ 5 files changed, 292 insertions(+) diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h index 59e10e7202cd..00c3bb5f3ab8 100644 --- a/drivers/hv/dxgkrnl/dxgkrnl.h +++ b/drivers/hv/dxgkrnl/dxgkrnl.h @@ -845,6 +845,15 @@ int dxgvmb_send_set_allocation_priority(struct dxgprocess *process, int dxgvmb_send_get_allocation_priority(struct dxgprocess *process, struct dxgadapter *adapter, struct d3dkmt_getallocationpriority *a); +int dxgvmb_send_set_context_sch_priority(struct dxgprocess *process, + struct dxgadapter *adapter, + struct d3dkmthandle context, + int priority, bool in_process); +int dxgvmb_send_get_context_sch_priority(struct dxgprocess *process, + struct dxgadapter *adapter, + struct d3dkmthandle context, + int *priority, + bool in_process); int dxgvmb_send_offer_allocations(struct dxgprocess *process, struct dxgadapter *adapter, struct d3dkmt_offerallocations *args); diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c index 0ab7acf3787b..2f0914b71c3c 100644 --- a/drivers/hv/dxgkrnl/dxgvmbus.c +++ b/drivers/hv/dxgkrnl/dxgvmbus.c @@ -2927,6 +2927,69 @@ int dxgvmb_send_get_allocation_priority(struct dxgprocess *process, return ret; } +int dxgvmb_send_set_context_sch_priority(struct dxgprocess *process, + struct dxgadapter *adapter, + struct d3dkmthandle context, + int priority, + bool in_process) +{ + struct dxgkvmb_command_setcontextschedulingpriority2 *command; + int ret; + 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_SETCONTEXTSCHEDULINGPRIORITY, + process->host_handle); + command->context = context; + command->priority = priority; + command->in_process = in_process; + ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size); +cleanup: + free_message(&msg, process); + if (ret) + pr_debug("err: %s %d", __func__, ret); + return ret; +} + +int dxgvmb_send_get_context_sch_priority(struct dxgprocess *process, + struct dxgadapter *adapter, + struct d3dkmthandle context, + int *priority, + bool in_process) +{ + struct dxgkvmb_command_getcontextschedulingpriority *command; + struct dxgkvmb_command_getcontextschedulingpriority_return result = { }; + int ret; + 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_GETCONTEXTSCHEDULINGPRIORITY, + process->host_handle); + command->context = context; + command->in_process = in_process; + ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size, + &result, sizeof(result)); + if (ret >= 0) { + ret = ntstatus2int(result.status); + *priority = result.priority; + } +cleanup: + free_message(&msg, process); + if (ret) + pr_debug("err: %s %d", __func__, ret); + return ret; +} + int dxgvmb_send_offer_allocations(struct dxgprocess *process, struct dxgadapter *adapter, struct d3dkmt_offerallocations *args) diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h index 7fa89ed16c2d..2e522d6652da 100644 --- a/drivers/hv/dxgkrnl/dxgvmbus.h +++ b/drivers/hv/dxgkrnl/dxgvmbus.h @@ -331,6 +331,25 @@ struct dxgkvmb_command_getallocationpriority_return { /* u32 priorities[allocation_count or 1]; */ }; +/* Returns ntstatus */ +struct dxgkvmb_command_setcontextschedulingpriority2 { + struct dxgkvmb_command_vgpu_to_host hdr; + struct d3dkmthandle context; + int priority; + bool in_process; +}; + +struct dxgkvmb_command_getcontextschedulingpriority { + struct dxgkvmb_command_vgpu_to_host hdr; + struct d3dkmthandle context; + bool in_process; +}; + +struct dxgkvmb_command_getcontextschedulingpriority_return { + struct ntstatus status; + int priority; +}; + struct dxgkvmb_command_createdevice { struct dxgkvmb_command_vgpu_to_host hdr; struct d3dkmt_createdeviceflags flags; diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c index 47ffdd1dda93..0a4fca6ee2aa 100644 --- a/drivers/hv/dxgkrnl/ioctl.c +++ b/drivers/hv/dxgkrnl/ioctl.c @@ -3703,6 +3703,171 @@ dxgk_get_allocation_priority(struct dxgprocess *process, void *__user inargs) return ret; } +static int +set_context_scheduling_priority(struct dxgprocess *process, + struct d3dkmthandle hcontext, + int priority, bool in_process) +{ + int ret = 0; + struct dxgdevice *device = NULL; + struct dxgadapter *adapter = NULL; + + device = dxgprocess_device_by_object_handle(process, + HMGRENTRY_TYPE_DXGCONTEXT, + hcontext); + if (device == NULL) { + ret = -EINVAL; + goto cleanup; + } + adapter = device->adapter; + ret = dxgadapter_acquire_lock_shared(adapter); + if (ret < 0) { + adapter = NULL; + goto cleanup; + } + ret = dxgvmb_send_set_context_sch_priority(process, adapter, + hcontext, priority, + in_process); + if (ret < 0) + pr_err("send_set_context_scheduling_priority failed"); +cleanup: + if (adapter) + dxgadapter_release_lock_shared(adapter); + if (device) + kref_put(&device->device_kref, dxgdevice_release); + + return ret; +} + +static int +dxgk_set_context_scheduling_priority(struct dxgprocess *process, + void *__user inargs) +{ + struct d3dkmt_setcontextschedulingpriority args; + int ret; + + ret = copy_from_user(&args, inargs, sizeof(args)); + if (ret) { + pr_err("%s failed to copy input args", __func__); + ret = -EINVAL; + goto cleanup; + } + + ret = set_context_scheduling_priority(process, args.context, + args.priority, false); +cleanup: + pr_debug("ioctl:%s %s %d", errorstr(ret), __func__, ret); + return ret; +} + +static int +get_context_scheduling_priority(struct dxgprocess *process, + struct d3dkmthandle hcontext, + int __user *priority, + bool in_process) +{ + int ret; + struct dxgdevice *device = NULL; + struct dxgadapter *adapter = NULL; + int pri = 0; + + device = dxgprocess_device_by_object_handle(process, + HMGRENTRY_TYPE_DXGCONTEXT, + hcontext); + if (device == NULL) { + ret = -EINVAL; + goto cleanup; + } + adapter = device->adapter; + ret = dxgadapter_acquire_lock_shared(adapter); + if (ret < 0) { + adapter = NULL; + goto cleanup; + } + ret = dxgvmb_send_get_context_sch_priority(process, adapter, + hcontext, &pri, in_process); + if (ret < 0) + goto cleanup; + ret = copy_to_user(priority, &pri, sizeof(pri)); + if (ret) { + pr_err("%s failed to copy priority to user", __func__); + ret = -EINVAL; + } + +cleanup: + if (adapter) + dxgadapter_release_lock_shared(adapter); + if (device) + kref_put(&device->device_kref, dxgdevice_release); + + return ret; +} + +static int +dxgk_get_context_scheduling_priority(struct dxgprocess *process, + void *__user inargs) +{ + struct d3dkmt_getcontextschedulingpriority args; + struct d3dkmt_getcontextschedulingpriority __user *input = inargs; + int ret; + + ret = copy_from_user(&args, inargs, sizeof(args)); + if (ret) { + pr_err("%s failed to copy input args", __func__); + ret = -EINVAL; + goto cleanup; + } + + ret = get_context_scheduling_priority(process, args.context, + &input->priority, false); +cleanup: + pr_debug("ioctl:%s %s %d", errorstr(ret), __func__, ret); + return ret; +} + +static int +dxgk_set_context_process_scheduling_priority(struct dxgprocess *process, + void *__user inargs) +{ + struct d3dkmt_setcontextinprocessschedulingpriority args; + int ret; + + ret = copy_from_user(&args, inargs, sizeof(args)); + if (ret) { + pr_err("%s failed to copy input args", __func__); + ret = -EINVAL; + goto cleanup; + } + + ret = set_context_scheduling_priority(process, args.context, + args.priority, true); +cleanup: + pr_debug("ioctl:%s %s %d", errorstr(ret), __func__, ret); + return ret; +} + +static int +dxgk_get_context_process_scheduling_priority(struct dxgprocess *process, + void __user *inargs) +{ + struct d3dkmt_getcontextinprocessschedulingpriority args; + int ret; + + ret = copy_from_user(&args, inargs, sizeof(args)); + if (ret) { + pr_err("%s failed to copy input args", __func__); + ret = -EINVAL; + goto cleanup; + } + + ret = get_context_scheduling_priority(process, args.context, + &((struct d3dkmt_getcontextinprocessschedulingpriority *) + inargs)->priority, true); +cleanup: + pr_debug("ioctl:%s %s %d", errorstr(ret), __func__, ret); + return ret; +} + static int dxgk_change_vidmem_reservation(struct dxgprocess *process, void *__user inargs) { @@ -4773,6 +4938,10 @@ void init_ioctls(void) LX_DXDESTROYSYNCHRONIZATIONOBJECT); SET_IOCTL(/*0x1f */ dxgk_flush_heap_transitions, LX_DXFLUSHHEAPTRANSITIONS); + SET_IOCTL(/*0x21 */ dxgk_get_context_process_scheduling_priority, + LX_DXGETCONTEXTINPROCESSSCHEDULINGPRIORITY); + SET_IOCTL(/*0x22 */ dxgk_get_context_scheduling_priority, + LX_DXGETCONTEXTSCHEDULINGPRIORITY); SET_IOCTL(/*0x25 */ dxgk_lock2, LX_DXLOCK2); SET_IOCTL(/*0x26 */ dxgk_mark_device_as_error, @@ -4785,6 +4954,10 @@ void init_ioctls(void) LX_DXRECLAIMALLOCATIONS2); SET_IOCTL(/*0x2e */ dxgk_set_allocation_priority, LX_DXSETALLOCATIONPRIORITY); + SET_IOCTL(/*0x2f */ dxgk_set_context_process_scheduling_priority, + LX_DXSETCONTEXTINPROCESSSCHEDULINGPRIORITY); + SET_IOCTL(/*0x30 */ dxgk_set_context_scheduling_priority, + LX_DXSETCONTEXTSCHEDULINGPRIORITY); SET_IOCTL(/*0x31 */ dxgk_signal_sync_object_cpu, LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMCPU); SET_IOCTL(/*0x32 */ dxgk_signal_sync_object_gpu, diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h index 3849f714ae9c..11e2f3c9c88c 100644 --- a/include/uapi/misc/d3dkmthk.h +++ b/include/uapi/misc/d3dkmthk.h @@ -704,6 +704,26 @@ struct d3dkmt_submitcommandtohwqueue { #endif }; +struct d3dkmt_setcontextschedulingpriority { + struct d3dkmthandle context; + int priority; +}; + +struct d3dkmt_setcontextinprocessschedulingpriority { + struct d3dkmthandle context; + int priority; +}; + +struct d3dkmt_getcontextschedulingpriority { + struct d3dkmthandle context; + int priority; +}; + +struct d3dkmt_getcontextinprocessschedulingpriority { + struct d3dkmthandle context; + int priority; +}; + struct d3dkmt_setallocationpriority { struct d3dkmthandle device; struct d3dkmthandle resource; @@ -1415,6 +1435,10 @@ struct d3dkmt_shareobjectwithhost { _IOWR(0x47, 0x1d, struct d3dkmt_destroysynchronizationobject) #define LX_DXFLUSHHEAPTRANSITIONS \ _IOWR(0x47, 0x1f, struct d3dkmt_flushheaptransitions) +#define LX_DXGETCONTEXTINPROCESSSCHEDULINGPRIORITY \ + _IOWR(0x47, 0x21, struct d3dkmt_getcontextinprocessschedulingpriority) +#define LX_DXGETCONTEXTSCHEDULINGPRIORITY \ + _IOWR(0x47, 0x22, struct d3dkmt_getcontextschedulingpriority) #define LX_DXLOCK2 \ _IOWR(0x47, 0x25, struct d3dkmt_lock2) #define LX_DXMARKDEVICEASERROR \ @@ -1427,6 +1451,10 @@ struct d3dkmt_shareobjectwithhost { _IOWR(0x47, 0x2c, struct d3dkmt_reclaimallocations2) #define LX_DXSETALLOCATIONPRIORITY \ _IOWR(0x47, 0x2e, struct d3dkmt_setallocationpriority) +#define LX_DXSETCONTEXTINPROCESSSCHEDULINGPRIORITY \ + _IOWR(0x47, 0x2f, struct d3dkmt_setcontextinprocessschedulingpriority) +#define LX_DXSETCONTEXTSCHEDULINGPRIORITY \ + _IOWR(0x47, 0x30, struct d3dkmt_setcontextschedulingpriority) #define LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMCPU \ _IOWR(0x47, 0x31, struct d3dkmt_signalsynchronizationobjectfromcpu) #define LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU \ -- 2.35.1