mirror of
https://github.com/armbian/build.git
synced 2025-08-15 23:56:57 +02:00
1690 lines
48 KiB
Diff
1690 lines
48 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Iouri Tarassov <iourit@linux.microsoft.com>
|
|
Date: Tue, 1 Feb 2022 13:59:23 -0800
|
|
Subject: drivers: hv: dxgkrnl: Operations using sync objects
|
|
|
|
Implement ioctls to submit operations with compute device
|
|
sync objects:
|
|
- the LX_DXSIGNALSYNCHRONIZATIONOBJECT ioctl.
|
|
The ioctl is used to submit a signal to a sync object.
|
|
- the LX_DXWAITFORSYNCHRONIZATIONOBJECT ioctl.
|
|
The ioctl is used to submit a wait for a sync object
|
|
- the LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMCPU ioctl
|
|
The ioctl is used to signal to a monitored fence sync object
|
|
from a CPU thread.
|
|
- the LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU ioctl.
|
|
The ioctl is used to submit a signal to a monitored fence
|
|
sync object..
|
|
- the LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU2 ioctl.
|
|
The ioctl is used to submit a signal to a monitored fence
|
|
sync object.
|
|
- the LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU ioctl.
|
|
The ioctl is used to submit a wait for a monitored fence
|
|
sync object.
|
|
|
|
Compute device synchronization objects are used to synchronize
|
|
execution of DMA buffers between different execution contexts.
|
|
Operations with sync objects include "signal" and "wait". A wait
|
|
for a sync object is satisfied when the sync object is signaled.
|
|
|
|
A signal operation could be submitted to a compute device context or
|
|
the sync object could be signaled by a CPU thread.
|
|
|
|
To improve performance, submitting operations to the host is done
|
|
asynchronously when the host supports it.
|
|
|
|
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
|
|
[kms: Forward port to v6.1]
|
|
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
|
|
---
|
|
drivers/hv/dxgkrnl/dxgadapter.c | 38 +-
|
|
drivers/hv/dxgkrnl/dxgkrnl.h | 62 +
|
|
drivers/hv/dxgkrnl/dxgmodule.c | 102 +-
|
|
drivers/hv/dxgkrnl/dxgvmbus.c | 219 ++-
|
|
drivers/hv/dxgkrnl/dxgvmbus.h | 48 +
|
|
drivers/hv/dxgkrnl/ioctl.c | 702 +++++++++-
|
|
drivers/hv/dxgkrnl/misc.h | 2 +
|
|
include/uapi/misc/d3dkmthk.h | 159 +++
|
|
8 files changed, 1311 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapter.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgadapter.c
|
|
+++ b/drivers/hv/dxgkrnl/dxgadapter.c
|
|
@@ -249,7 +249,7 @@ void dxgdevice_stop(struct dxgdevice *device)
|
|
struct dxgallocation *alloc;
|
|
struct dxgsyncobject *syncobj;
|
|
|
|
- DXG_TRACE("Destroying device: %p", device);
|
|
+ DXG_TRACE("Stopping device: %p", device);
|
|
dxgdevice_acquire_alloc_list_lock(device);
|
|
list_for_each_entry(alloc, &device->alloc_list_head, alloc_list_entry) {
|
|
dxgallocation_stop(alloc);
|
|
@@ -743,15 +743,13 @@ void dxgallocation_destroy(struct dxgallocation *alloc)
|
|
}
|
|
#ifdef _MAIN_KERNEL_
|
|
if (alloc->gpadl.gpadl_handle) {
|
|
- DXG_TRACE("Teardown gpadl %d",
|
|
- alloc->gpadl.gpadl_handle);
|
|
+ DXG_TRACE("Teardown gpadl %d", alloc->gpadl.gpadl_handle);
|
|
vmbus_teardown_gpadl(dxgglobal_get_vmbus(), &alloc->gpadl);
|
|
alloc->gpadl.gpadl_handle = 0;
|
|
}
|
|
else
|
|
if (alloc->gpadl) {
|
|
- DXG_TRACE("Teardown gpadl %d",
|
|
- alloc->gpadl);
|
|
+ DXG_TRACE("Teardown gpadl %d", alloc->gpadl);
|
|
vmbus_teardown_gpadl(dxgglobal_get_vmbus(), alloc->gpadl);
|
|
alloc->gpadl = 0;
|
|
}
|
|
@@ -901,6 +899,13 @@ struct dxgsyncobject *dxgsyncobject_create(struct dxgprocess *process,
|
|
case _D3DDDI_PERIODIC_MONITORED_FENCE:
|
|
syncobj->monitored_fence = 1;
|
|
break;
|
|
+ case _D3DDDI_CPU_NOTIFICATION:
|
|
+ syncobj->cpu_event = 1;
|
|
+ syncobj->host_event = kzalloc(sizeof(*syncobj->host_event),
|
|
+ GFP_KERNEL);
|
|
+ if (syncobj->host_event == NULL)
|
|
+ goto cleanup;
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
@@ -928,6 +933,8 @@ struct dxgsyncobject *dxgsyncobject_create(struct dxgprocess *process,
|
|
DXG_TRACE("Syncobj created: %p", syncobj);
|
|
return syncobj;
|
|
cleanup:
|
|
+ if (syncobj->host_event)
|
|
+ kfree(syncobj->host_event);
|
|
if (syncobj)
|
|
kfree(syncobj);
|
|
return NULL;
|
|
@@ -937,6 +944,7 @@ void dxgsyncobject_destroy(struct dxgprocess *process,
|
|
struct dxgsyncobject *syncobj)
|
|
{
|
|
int destroyed;
|
|
+ struct dxghosteventcpu *host_event;
|
|
|
|
DXG_TRACE("Destroying syncobj: %p", syncobj);
|
|
|
|
@@ -955,6 +963,16 @@ void dxgsyncobject_destroy(struct dxgprocess *process,
|
|
}
|
|
hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
|
|
|
|
+ if (syncobj->cpu_event) {
|
|
+ host_event = syncobj->host_event;
|
|
+ if (host_event->cpu_event) {
|
|
+ eventfd_ctx_put(host_event->cpu_event);
|
|
+ if (host_event->hdr.event_id)
|
|
+ dxgglobal_remove_host_event(
|
|
+ &host_event->hdr);
|
|
+ host_event->cpu_event = NULL;
|
|
+ }
|
|
+ }
|
|
if (syncobj->monitored_fence)
|
|
dxgdevice_remove_syncobj(syncobj);
|
|
else
|
|
@@ -971,16 +989,14 @@ void dxgsyncobject_destroy(struct dxgprocess *process,
|
|
void dxgsyncobject_stop(struct dxgsyncobject *syncobj)
|
|
{
|
|
int stopped = test_and_set_bit(1, &syncobj->flags);
|
|
+ int ret;
|
|
|
|
if (!stopped) {
|
|
DXG_TRACE("Stopping syncobj");
|
|
if (syncobj->monitored_fence) {
|
|
if (syncobj->mapped_address) {
|
|
- int ret =
|
|
- dxg_unmap_iospace(syncobj->mapped_address,
|
|
- PAGE_SIZE);
|
|
-
|
|
- (void)ret;
|
|
+ ret = dxg_unmap_iospace(syncobj->mapped_address,
|
|
+ PAGE_SIZE);
|
|
DXG_TRACE("unmap fence %d %p",
|
|
ret, syncobj->mapped_address);
|
|
syncobj->mapped_address = NULL;
|
|
@@ -994,5 +1010,7 @@ void dxgsyncobject_release(struct kref *refcount)
|
|
struct dxgsyncobject *syncobj;
|
|
|
|
syncobj = container_of(refcount, struct dxgsyncobject, syncobj_kref);
|
|
+ if (syncobj->host_event)
|
|
+ kfree(syncobj->host_event);
|
|
kfree(syncobj);
|
|
}
|
|
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
|
|
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
|
|
@@ -101,6 +101,29 @@ int dxgvmbuschannel_init(struct dxgvmbuschannel *ch, struct hv_device *hdev);
|
|
void dxgvmbuschannel_destroy(struct dxgvmbuschannel *ch);
|
|
void dxgvmbuschannel_receive(void *ctx);
|
|
|
|
+/*
|
|
+ * The structure describes an event, which will be signaled by
|
|
+ * a message from host.
|
|
+ */
|
|
+enum dxghosteventtype {
|
|
+ dxghostevent_cpu_event = 1,
|
|
+};
|
|
+
|
|
+struct dxghostevent {
|
|
+ struct list_head host_event_list_entry;
|
|
+ u64 event_id;
|
|
+ enum dxghosteventtype event_type;
|
|
+};
|
|
+
|
|
+struct dxghosteventcpu {
|
|
+ struct dxghostevent hdr;
|
|
+ struct dxgprocess *process;
|
|
+ struct eventfd_ctx *cpu_event;
|
|
+ struct completion *completion_event;
|
|
+ bool destroy_after_signal;
|
|
+ bool remove_from_list;
|
|
+};
|
|
+
|
|
/*
|
|
* This is GPU synchronization object, which is used to synchronize execution
|
|
* between GPU contextx/hardware queues or for tracking GPU execution progress.
|
|
@@ -130,6 +153,8 @@ struct dxgsyncobject {
|
|
*/
|
|
struct dxgdevice *device;
|
|
struct dxgprocess *process;
|
|
+ /* Used by D3DDDI_CPU_NOTIFICATION objects */
|
|
+ struct dxghosteventcpu *host_event;
|
|
/* CPU virtual address of the fence value for "device" syncobjects */
|
|
void *mapped_address;
|
|
/* Handle in the process handle table */
|
|
@@ -144,6 +169,7 @@ struct dxgsyncobject {
|
|
u32 stopped:1;
|
|
/* device syncobject */
|
|
u32 monitored_fence:1;
|
|
+ u32 cpu_event:1;
|
|
u32 shared:1;
|
|
u32 reserved:27;
|
|
};
|
|
@@ -206,6 +232,11 @@ struct dxgglobal {
|
|
/* protects the dxgprocess_adapter lists */
|
|
struct mutex process_adapter_mutex;
|
|
|
|
+ /* list of events, waiting to be signaled by the host */
|
|
+ struct list_head host_event_list_head;
|
|
+ spinlock_t host_event_list_mutex;
|
|
+ atomic64_t host_event_id;
|
|
+
|
|
bool global_channel_initialized;
|
|
bool async_msg_enabled;
|
|
bool misc_registered;
|
|
@@ -228,6 +259,11 @@ struct vmbus_channel *dxgglobal_get_vmbus(void);
|
|
struct dxgvmbuschannel *dxgglobal_get_dxgvmbuschannel(void);
|
|
void dxgglobal_acquire_process_adapter_lock(void);
|
|
void dxgglobal_release_process_adapter_lock(void);
|
|
+void dxgglobal_add_host_event(struct dxghostevent *hostevent);
|
|
+void dxgglobal_remove_host_event(struct dxghostevent *hostevent);
|
|
+u64 dxgglobal_new_host_event_id(void);
|
|
+void dxgglobal_signal_host_event(u64 event_id);
|
|
+struct dxghostevent *dxgglobal_get_host_event(u64 event_id);
|
|
int dxgglobal_acquire_channel_lock(void);
|
|
void dxgglobal_release_channel_lock(void);
|
|
|
|
@@ -594,6 +630,31 @@ int dxgvmb_send_create_sync_object(struct dxgprocess *pr,
|
|
*args, struct dxgsyncobject *so);
|
|
int dxgvmb_send_destroy_sync_object(struct dxgprocess *pr,
|
|
struct d3dkmthandle h);
|
|
+int dxgvmb_send_signal_sync_object(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct d3dddicb_signalflags flags,
|
|
+ u64 legacy_fence_value,
|
|
+ struct d3dkmthandle context,
|
|
+ u32 object_count,
|
|
+ struct d3dkmthandle *object,
|
|
+ u32 context_count,
|
|
+ struct d3dkmthandle *contexts,
|
|
+ u32 fence_count, u64 *fences,
|
|
+ struct eventfd_ctx *cpu_event,
|
|
+ struct d3dkmthandle device);
|
|
+int dxgvmb_send_wait_sync_object_gpu(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct d3dkmthandle context,
|
|
+ u32 object_count,
|
|
+ struct d3dkmthandle *objects,
|
|
+ u64 *fences,
|
|
+ bool legacy_fence);
|
|
+int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct
|
|
+ d3dkmt_waitforsynchronizationobjectfromcpu
|
|
+ *args,
|
|
+ u64 cpu_event);
|
|
int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
|
|
struct dxgadapter *adapter,
|
|
struct d3dkmt_queryadapterinfo *args);
|
|
@@ -609,6 +670,7 @@ int dxgvmb_send_async_msg(struct dxgvmbuschannel *channel,
|
|
void *command,
|
|
u32 cmd_size);
|
|
|
|
+void signal_host_cpu_event(struct dxghostevent *eventhdr);
|
|
int ntstatus2int(struct ntstatus status);
|
|
|
|
#ifdef DEBUG
|
|
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgmodule.c
|
|
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
|
|
@@ -123,6 +123,102 @@ static struct dxgadapter *find_adapter(struct winluid *luid)
|
|
return adapter;
|
|
}
|
|
|
|
+void dxgglobal_add_host_event(struct dxghostevent *event)
|
|
+{
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ spin_lock_irq(&dxgglobal->host_event_list_mutex);
|
|
+ list_add_tail(&event->host_event_list_entry,
|
|
+ &dxgglobal->host_event_list_head);
|
|
+ spin_unlock_irq(&dxgglobal->host_event_list_mutex);
|
|
+}
|
|
+
|
|
+void dxgglobal_remove_host_event(struct dxghostevent *event)
|
|
+{
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ spin_lock_irq(&dxgglobal->host_event_list_mutex);
|
|
+ if (event->host_event_list_entry.next != NULL) {
|
|
+ list_del(&event->host_event_list_entry);
|
|
+ event->host_event_list_entry.next = NULL;
|
|
+ }
|
|
+ spin_unlock_irq(&dxgglobal->host_event_list_mutex);
|
|
+}
|
|
+
|
|
+void signal_host_cpu_event(struct dxghostevent *eventhdr)
|
|
+{
|
|
+ struct dxghosteventcpu *event = (struct dxghosteventcpu *)eventhdr;
|
|
+
|
|
+ if (event->remove_from_list ||
|
|
+ event->destroy_after_signal) {
|
|
+ list_del(&eventhdr->host_event_list_entry);
|
|
+ eventhdr->host_event_list_entry.next = NULL;
|
|
+ }
|
|
+ if (event->cpu_event) {
|
|
+ DXG_TRACE("signal cpu event");
|
|
+ eventfd_signal(event->cpu_event, 1);
|
|
+ if (event->destroy_after_signal)
|
|
+ eventfd_ctx_put(event->cpu_event);
|
|
+ } else {
|
|
+ DXG_TRACE("signal completion");
|
|
+ complete(event->completion_event);
|
|
+ }
|
|
+ if (event->destroy_after_signal) {
|
|
+ DXG_TRACE("destroying event %p", event);
|
|
+ kfree(event);
|
|
+ }
|
|
+}
|
|
+
|
|
+void dxgglobal_signal_host_event(u64 event_id)
|
|
+{
|
|
+ struct dxghostevent *event;
|
|
+ unsigned long flags;
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ DXG_TRACE("Signaling host event %lld", event_id);
|
|
+
|
|
+ spin_lock_irqsave(&dxgglobal->host_event_list_mutex, flags);
|
|
+ list_for_each_entry(event, &dxgglobal->host_event_list_head,
|
|
+ host_event_list_entry) {
|
|
+ if (event->event_id == event_id) {
|
|
+ DXG_TRACE("found event to signal");
|
|
+ if (event->event_type == dxghostevent_cpu_event)
|
|
+ signal_host_cpu_event(event);
|
|
+ else
|
|
+ DXG_ERR("Unknown host event type");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ spin_unlock_irqrestore(&dxgglobal->host_event_list_mutex, flags);
|
|
+}
|
|
+
|
|
+struct dxghostevent *dxgglobal_get_host_event(u64 event_id)
|
|
+{
|
|
+ struct dxghostevent *entry;
|
|
+ struct dxghostevent *event = NULL;
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ spin_lock_irq(&dxgglobal->host_event_list_mutex);
|
|
+ list_for_each_entry(entry, &dxgglobal->host_event_list_head,
|
|
+ host_event_list_entry) {
|
|
+ if (entry->event_id == event_id) {
|
|
+ list_del(&entry->host_event_list_entry);
|
|
+ entry->host_event_list_entry.next = NULL;
|
|
+ event = entry;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ spin_unlock_irq(&dxgglobal->host_event_list_mutex);
|
|
+ return event;
|
|
+}
|
|
+
|
|
+u64 dxgglobal_new_host_event_id(void)
|
|
+{
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ return atomic64_inc_return(&dxgglobal->host_event_id);
|
|
+}
|
|
+
|
|
void dxgglobal_acquire_process_adapter_lock(void)
|
|
{
|
|
struct dxgglobal *dxgglobal = dxggbl();
|
|
@@ -720,12 +816,16 @@ static struct dxgglobal *dxgglobal_create(void)
|
|
INIT_LIST_HEAD(&dxgglobal->vgpu_ch_list_head);
|
|
INIT_LIST_HEAD(&dxgglobal->adapter_list_head);
|
|
init_rwsem(&dxgglobal->adapter_list_lock);
|
|
-
|
|
init_rwsem(&dxgglobal->channel_lock);
|
|
|
|
+ INIT_LIST_HEAD(&dxgglobal->host_event_list_head);
|
|
+ spin_lock_init(&dxgglobal->host_event_list_mutex);
|
|
+ atomic64_set(&dxgglobal->host_event_id, 1);
|
|
+
|
|
#ifdef DEBUG
|
|
dxgk_validate_ioctls();
|
|
#endif
|
|
+
|
|
return dxgglobal;
|
|
}
|
|
|
|
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
|
|
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
|
|
@@ -281,6 +281,22 @@ static void command_vm_to_host_init1(struct dxgkvmb_command_vm_to_host *command,
|
|
command->channel_type = DXGKVMB_VM_TO_HOST;
|
|
}
|
|
|
|
+static void signal_guest_event(struct dxgkvmb_command_host_to_vm *packet,
|
|
+ u32 packet_length)
|
|
+{
|
|
+ struct dxgkvmb_command_signalguestevent *command = (void *)packet;
|
|
+
|
|
+ if (packet_length < sizeof(struct dxgkvmb_command_signalguestevent)) {
|
|
+ DXG_ERR("invalid signal guest event packet size");
|
|
+ return;
|
|
+ }
|
|
+ if (command->event == 0) {
|
|
+ DXG_ERR("invalid event pointer");
|
|
+ return;
|
|
+ }
|
|
+ dxgglobal_signal_host_event(command->event);
|
|
+}
|
|
+
|
|
static void process_inband_packet(struct dxgvmbuschannel *channel,
|
|
struct vmpacket_descriptor *desc)
|
|
{
|
|
@@ -297,6 +313,7 @@ static void process_inband_packet(struct dxgvmbuschannel *channel,
|
|
switch (packet->command_type) {
|
|
case DXGK_VMBCOMMAND_SIGNALGUESTEVENT:
|
|
case DXGK_VMBCOMMAND_SIGNALGUESTEVENTPASSIVE:
|
|
+ signal_guest_event(packet, packet_length);
|
|
break;
|
|
case DXGK_VMBCOMMAND_SENDWNFNOTIFICATION:
|
|
break;
|
|
@@ -959,7 +976,7 @@ dxgvmb_send_create_context(struct dxgadapter *adapter,
|
|
command->priv_drv_data,
|
|
args->priv_drv_data_size);
|
|
if (ret) {
|
|
- dev_err(DXGDEV,
|
|
+ DXG_ERR(
|
|
"Faled to copy private data to user");
|
|
ret = -EINVAL;
|
|
dxgvmb_send_destroy_context(adapter, process,
|
|
@@ -1706,6 +1723,206 @@ dxgvmb_send_create_sync_object(struct dxgprocess *process,
|
|
return ret;
|
|
}
|
|
|
|
+int dxgvmb_send_signal_sync_object(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct d3dddicb_signalflags flags,
|
|
+ u64 legacy_fence_value,
|
|
+ struct d3dkmthandle context,
|
|
+ u32 object_count,
|
|
+ struct d3dkmthandle __user *objects,
|
|
+ u32 context_count,
|
|
+ struct d3dkmthandle __user *contexts,
|
|
+ u32 fence_count,
|
|
+ u64 __user *fences,
|
|
+ struct eventfd_ctx *cpu_event_handle,
|
|
+ struct d3dkmthandle device)
|
|
+{
|
|
+ int ret;
|
|
+ struct dxgkvmb_command_signalsyncobject *command;
|
|
+ u32 object_size = object_count * sizeof(struct d3dkmthandle);
|
|
+ u32 context_size = context_count * sizeof(struct d3dkmthandle);
|
|
+ u32 fence_size = fences ? fence_count * sizeof(u64) : 0;
|
|
+ u8 *current_pos;
|
|
+ u32 cmd_size = sizeof(struct dxgkvmb_command_signalsyncobject) +
|
|
+ object_size + context_size + fence_size;
|
|
+ struct dxgvmbusmsg msg = {.hdr = NULL};
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ if (context.v)
|
|
+ cmd_size += sizeof(struct d3dkmthandle);
|
|
+
|
|
+ ret = init_message(&msg, adapter, process, cmd_size);
|
|
+ if (ret)
|
|
+ goto cleanup;
|
|
+ command = (void *)msg.msg;
|
|
+
|
|
+ command_vgpu_to_host_init2(&command->hdr,
|
|
+ DXGK_VMBCOMMAND_SIGNALSYNCOBJECT,
|
|
+ process->host_handle);
|
|
+
|
|
+ if (flags.enqueue_cpu_event)
|
|
+ command->cpu_event_handle = (u64) cpu_event_handle;
|
|
+ else
|
|
+ command->device = device;
|
|
+ command->flags = flags;
|
|
+ command->fence_value = legacy_fence_value;
|
|
+ command->object_count = object_count;
|
|
+ command->context_count = context_count;
|
|
+ current_pos = (u8 *) &command[1];
|
|
+ ret = copy_from_user(current_pos, objects, object_size);
|
|
+ if (ret) {
|
|
+ DXG_ERR("Failed to read objects %p %d",
|
|
+ objects, object_size);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ current_pos += object_size;
|
|
+ if (context.v) {
|
|
+ command->context_count++;
|
|
+ *(struct d3dkmthandle *) current_pos = context;
|
|
+ current_pos += sizeof(struct d3dkmthandle);
|
|
+ }
|
|
+ if (context_size) {
|
|
+ ret = copy_from_user(current_pos, contexts, context_size);
|
|
+ if (ret) {
|
|
+ DXG_ERR("Failed to read contexts %p %d",
|
|
+ contexts, context_size);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ current_pos += context_size;
|
|
+ }
|
|
+ if (fence_size) {
|
|
+ ret = copy_from_user(current_pos, fences, fence_size);
|
|
+ if (ret) {
|
|
+ DXG_ERR("Failed to read fences %p %d",
|
|
+ fences, fence_size);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (dxgglobal->async_msg_enabled) {
|
|
+ command->hdr.async_msg = 1;
|
|
+ ret = dxgvmb_send_async_msg(msg.channel, msg.hdr, msg.size);
|
|
+ } else {
|
|
+ ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr,
|
|
+ msg.size);
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+ free_message(&msg, process);
|
|
+ if (ret)
|
|
+ DXG_TRACE("err: %d", ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct
|
|
+ d3dkmt_waitforsynchronizationobjectfromcpu
|
|
+ *args,
|
|
+ u64 cpu_event)
|
|
+{
|
|
+ int ret = -EINVAL;
|
|
+ struct dxgkvmb_command_waitforsyncobjectfromcpu *command;
|
|
+ u32 object_size = args->object_count * sizeof(struct d3dkmthandle);
|
|
+ u32 fence_size = args->object_count * sizeof(u64);
|
|
+ u8 *current_pos;
|
|
+ u32 cmd_size = sizeof(*command) + object_size + fence_size;
|
|
+ struct dxgvmbusmsg msg = {.hdr = NULL};
|
|
+
|
|
+ ret = init_message(&msg, adapter, process, cmd_size);
|
|
+ if (ret)
|
|
+ goto cleanup;
|
|
+ command = (void *)msg.msg;
|
|
+
|
|
+ command_vgpu_to_host_init2(&command->hdr,
|
|
+ DXGK_VMBCOMMAND_WAITFORSYNCOBJECTFROMCPU,
|
|
+ process->host_handle);
|
|
+ command->device = args->device;
|
|
+ command->flags = args->flags;
|
|
+ command->object_count = args->object_count;
|
|
+ command->guest_event_pointer = (u64) cpu_event;
|
|
+ current_pos = (u8 *) &command[1];
|
|
+
|
|
+ ret = copy_from_user(current_pos, args->objects, object_size);
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy objects");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ current_pos += object_size;
|
|
+ ret = copy_from_user(current_pos, args->fence_values,
|
|
+ fence_size);
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy fences");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
|
|
+
|
|
+cleanup:
|
|
+ free_message(&msg, process);
|
|
+ if (ret)
|
|
+ DXG_TRACE("err: %d", ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int dxgvmb_send_wait_sync_object_gpu(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct d3dkmthandle context,
|
|
+ u32 object_count,
|
|
+ struct d3dkmthandle *objects,
|
|
+ u64 *fences,
|
|
+ bool legacy_fence)
|
|
+{
|
|
+ int ret;
|
|
+ struct dxgkvmb_command_waitforsyncobjectfromgpu *command;
|
|
+ u32 fence_size = object_count * sizeof(u64);
|
|
+ u32 object_size = object_count * sizeof(struct d3dkmthandle);
|
|
+ u8 *current_pos;
|
|
+ u32 cmd_size = object_size + fence_size - sizeof(u64) +
|
|
+ sizeof(struct dxgkvmb_command_waitforsyncobjectfromgpu);
|
|
+ struct dxgvmbusmsg msg = {.hdr = NULL};
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ if (object_count == 0 || object_count > D3DDDI_MAX_OBJECT_WAITED_ON) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ret = init_message(&msg, adapter, process, cmd_size);
|
|
+ if (ret)
|
|
+ goto cleanup;
|
|
+ command = (void *)msg.msg;
|
|
+
|
|
+ command_vgpu_to_host_init2(&command->hdr,
|
|
+ DXGK_VMBCOMMAND_WAITFORSYNCOBJECTFROMGPU,
|
|
+ process->host_handle);
|
|
+ command->context = context;
|
|
+ command->object_count = object_count;
|
|
+ command->legacy_fence_object = legacy_fence;
|
|
+ current_pos = (u8 *) command->fence_values;
|
|
+ memcpy(current_pos, fences, fence_size);
|
|
+ current_pos += fence_size;
|
|
+ memcpy(current_pos, objects, object_size);
|
|
+
|
|
+ if (dxgglobal->async_msg_enabled) {
|
|
+ command->hdr.async_msg = 1;
|
|
+ ret = dxgvmb_send_async_msg(msg.channel, msg.hdr, msg.size);
|
|
+ } else {
|
|
+ ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr,
|
|
+ msg.size);
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+ free_message(&msg, process);
|
|
+ if (ret)
|
|
+ DXG_TRACE("err: %d", ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
|
|
struct dxgadapter *adapter,
|
|
struct d3dkmt_queryadapterinfo *args)
|
|
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgvmbus.h
|
|
+++ b/drivers/hv/dxgkrnl/dxgvmbus.h
|
|
@@ -165,6 +165,13 @@ struct dxgkvmb_command_host_to_vm {
|
|
enum dxgkvmb_commandtype_host_to_vm command_type;
|
|
};
|
|
|
|
+struct dxgkvmb_command_signalguestevent {
|
|
+ struct dxgkvmb_command_host_to_vm hdr;
|
|
+ u64 event;
|
|
+ u64 process_id;
|
|
+ bool dereference_event;
|
|
+};
|
|
+
|
|
/* Returns ntstatus */
|
|
struct dxgkvmb_command_setiospaceregion {
|
|
struct dxgkvmb_command_vm_to_host hdr;
|
|
@@ -430,4 +437,45 @@ struct dxgkvmb_command_destroysyncobject {
|
|
struct d3dkmthandle sync_object;
|
|
};
|
|
|
|
+/* The command returns ntstatus */
|
|
+struct dxgkvmb_command_signalsyncobject {
|
|
+ struct dxgkvmb_command_vgpu_to_host hdr;
|
|
+ u32 object_count;
|
|
+ struct d3dddicb_signalflags flags;
|
|
+ u32 context_count;
|
|
+ u64 fence_value;
|
|
+ union {
|
|
+ /* Pointer to the guest event object */
|
|
+ u64 cpu_event_handle;
|
|
+ /* Non zero when signal from CPU is done */
|
|
+ struct d3dkmthandle device;
|
|
+ };
|
|
+ /* struct d3dkmthandle ObjectHandleArray[object_count] */
|
|
+ /* struct d3dkmthandle ContextArray[context_count] */
|
|
+ /* u64 MonitoredFenceValueArray[object_count] */
|
|
+};
|
|
+
|
|
+/* The command returns ntstatus */
|
|
+struct dxgkvmb_command_waitforsyncobjectfromcpu {
|
|
+ struct dxgkvmb_command_vgpu_to_host hdr;
|
|
+ struct d3dkmthandle device;
|
|
+ u32 object_count;
|
|
+ struct d3dddi_waitforsynchronizationobjectfromcpu_flags flags;
|
|
+ u64 guest_event_pointer;
|
|
+ bool dereference_event;
|
|
+ /* struct d3dkmthandle ObjectHandleArray[object_count] */
|
|
+ /* u64 FenceValueArray [object_count] */
|
|
+};
|
|
+
|
|
+/* The command returns ntstatus */
|
|
+struct dxgkvmb_command_waitforsyncobjectfromgpu {
|
|
+ struct dxgkvmb_command_vgpu_to_host hdr;
|
|
+ struct d3dkmthandle context;
|
|
+ /* Must be 1 when bLegacyFenceObject is TRUE */
|
|
+ u32 object_count;
|
|
+ bool legacy_fence_object;
|
|
+ u64 fence_values[1];
|
|
+ /* struct d3dkmthandle ObjectHandles[object_count] */
|
|
+};
|
|
+
|
|
#endif /* _DXGVMBUS_H */
|
|
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/ioctl.c
|
|
+++ b/drivers/hv/dxgkrnl/ioctl.c
|
|
@@ -759,7 +759,7 @@ get_standard_alloc_priv_data(struct dxgdevice *device,
|
|
res_priv_data = vzalloc(res_priv_data_size);
|
|
if (res_priv_data == NULL) {
|
|
ret = -ENOMEM;
|
|
- dev_err(DXGDEV,
|
|
+ DXG_ERR(
|
|
"failed to alloc memory for res priv data: %d",
|
|
res_priv_data_size);
|
|
goto cleanup;
|
|
@@ -1065,7 +1065,7 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
|
|
alloc_info[i].priv_drv_data,
|
|
priv_data_size);
|
|
if (ret) {
|
|
- dev_err(DXGDEV,
|
|
+ DXG_ERR(
|
|
"failed to copy priv data");
|
|
ret = -EFAULT;
|
|
goto cleanup;
|
|
@@ -1348,8 +1348,10 @@ dxgkio_create_sync_object(struct dxgprocess *process, void *__user inargs)
|
|
struct d3dkmt_createsynchronizationobject2 args;
|
|
struct dxgdevice *device = NULL;
|
|
struct dxgadapter *adapter = NULL;
|
|
+ struct eventfd_ctx *event = NULL;
|
|
struct dxgsyncobject *syncobj = NULL;
|
|
bool device_lock_acquired = false;
|
|
+ struct dxghosteventcpu *host_event = NULL;
|
|
|
|
ret = copy_from_user(&args, inargs, sizeof(args));
|
|
if (ret) {
|
|
@@ -1384,6 +1386,27 @@ dxgkio_create_sync_object(struct dxgprocess *process, void *__user inargs)
|
|
goto cleanup;
|
|
}
|
|
|
|
+ if (args.info.type == _D3DDDI_CPU_NOTIFICATION) {
|
|
+ event = eventfd_ctx_fdget((int)
|
|
+ args.info.cpu_notification.event);
|
|
+ if (IS_ERR(event)) {
|
|
+ DXG_ERR("failed to reference the event");
|
|
+ event = NULL;
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ host_event = syncobj->host_event;
|
|
+ host_event->hdr.event_id = dxgglobal_new_host_event_id();
|
|
+ host_event->cpu_event = event;
|
|
+ host_event->remove_from_list = false;
|
|
+ host_event->destroy_after_signal = false;
|
|
+ host_event->hdr.event_type = dxghostevent_cpu_event;
|
|
+ dxgglobal_add_host_event(&host_event->hdr);
|
|
+ args.info.cpu_notification.event = host_event->hdr.event_id;
|
|
+ DXG_TRACE("creating CPU notification event: %lld",
|
|
+ args.info.cpu_notification.event);
|
|
+ }
|
|
+
|
|
ret = dxgvmb_send_create_sync_object(process, adapter, &args, syncobj);
|
|
if (ret < 0)
|
|
goto cleanup;
|
|
@@ -1411,7 +1434,10 @@ dxgkio_create_sync_object(struct dxgprocess *process, void *__user inargs)
|
|
if (args.sync_object.v)
|
|
dxgvmb_send_destroy_sync_object(process,
|
|
args.sync_object);
|
|
+ event = NULL;
|
|
}
|
|
+ if (event)
|
|
+ eventfd_ctx_put(event);
|
|
}
|
|
if (adapter)
|
|
dxgadapter_release_lock_shared(adapter);
|
|
@@ -1467,6 +1493,659 @@ dxgkio_destroy_sync_object(struct dxgprocess *process, void *__user inargs)
|
|
return ret;
|
|
}
|
|
|
|
+static int
|
|
+dxgkio_signal_sync_object(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_signalsynchronizationobject2 args;
|
|
+ struct d3dkmt_signalsynchronizationobject2 *__user in_args = inargs;
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ int ret;
|
|
+ u32 fence_count = 1;
|
|
+ struct eventfd_ctx *event = NULL;
|
|
+ struct dxghosteventcpu *host_event = NULL;
|
|
+ bool host_event_added = false;
|
|
+ u64 host_event_id = 0;
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (args.context_count >= D3DDDI_MAX_BROADCAST_CONTEXT ||
|
|
+ args.object_count > D3DDDI_MAX_OBJECT_SIGNALED) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (args.flags.enqueue_cpu_event) {
|
|
+ host_event = kzalloc(sizeof(*host_event), GFP_KERNEL);
|
|
+ if (host_event == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ host_event->process = process;
|
|
+ event = eventfd_ctx_fdget((int)args.cpu_event_handle);
|
|
+ if (IS_ERR(event)) {
|
|
+ DXG_ERR("failed to reference the event");
|
|
+ event = NULL;
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ fence_count = 0;
|
|
+ host_event->cpu_event = event;
|
|
+ host_event_id = dxgglobal_new_host_event_id();
|
|
+ host_event->hdr.event_type = dxghostevent_cpu_event;
|
|
+ host_event->hdr.event_id = host_event_id;
|
|
+ host_event->remove_from_list = true;
|
|
+ host_event->destroy_after_signal = true;
|
|
+ dxgglobal_add_host_event(&host_event->hdr);
|
|
+ host_event_added = true;
|
|
+ }
|
|
+
|
|
+ device = dxgprocess_device_by_object_handle(process,
|
|
+ HMGRENTRY_TYPE_DXGCONTEXT,
|
|
+ args.context);
|
|
+ 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_signal_sync_object(process, adapter,
|
|
+ args.flags, args.fence.fence_value,
|
|
+ args.context, args.object_count,
|
|
+ in_args->object_array,
|
|
+ args.context_count,
|
|
+ in_args->contexts, fence_count,
|
|
+ NULL, (void *)host_event_id,
|
|
+ zerohandle);
|
|
+
|
|
+ /*
|
|
+ * When the send operation succeeds, the host event will be destroyed
|
|
+ * after signal from the host
|
|
+ */
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (ret < 0) {
|
|
+ if (host_event_added) {
|
|
+ /* The event might be signaled and destroyed by host */
|
|
+ host_event = (struct dxghosteventcpu *)
|
|
+ dxgglobal_get_host_event(host_event_id);
|
|
+ if (host_event) {
|
|
+ eventfd_ctx_put(event);
|
|
+ event = NULL;
|
|
+ kfree(host_event);
|
|
+ host_event = NULL;
|
|
+ }
|
|
+ }
|
|
+ if (event)
|
|
+ eventfd_ctx_put(event);
|
|
+ if (host_event)
|
|
+ kfree(host_event);
|
|
+ }
|
|
+ if (adapter)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (device)
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+dxgkio_signal_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_signalsynchronizationobjectfromcpu args;
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ int ret;
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (args.object_count == 0 ||
|
|
+ args.object_count > D3DDDI_MAX_OBJECT_SIGNALED) {
|
|
+ DXG_TRACE("Too many syncobjects : %d", args.object_count);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ device = dxgprocess_device_by_handle(process, args.device);
|
|
+ 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_signal_sync_object(process, adapter,
|
|
+ args.flags, 0, zerohandle,
|
|
+ args.object_count, args.objects, 0,
|
|
+ NULL, args.object_count,
|
|
+ args.fence_values, NULL,
|
|
+ args.device);
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (adapter)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (device)
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+dxgkio_signal_sync_object_gpu(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_signalsynchronizationobjectfromgpu args;
|
|
+ struct d3dkmt_signalsynchronizationobjectfromgpu *__user user_args =
|
|
+ inargs;
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ struct d3dddicb_signalflags flags = { };
|
|
+ int ret;
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (args.object_count == 0 ||
|
|
+ args.object_count > DXG_MAX_VM_BUS_PACKET_SIZE) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ device = dxgprocess_device_by_object_handle(process,
|
|
+ HMGRENTRY_TYPE_DXGCONTEXT,
|
|
+ args.context);
|
|
+ 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_signal_sync_object(process, adapter,
|
|
+ flags, 0, zerohandle,
|
|
+ args.object_count,
|
|
+ args.objects, 1,
|
|
+ &user_args->context,
|
|
+ args.object_count,
|
|
+ args.monitored_fence_values, NULL,
|
|
+ zerohandle);
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (adapter)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (device)
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+dxgkio_signal_sync_object_gpu2(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_signalsynchronizationobjectfromgpu2 args;
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ struct d3dkmthandle context_handle;
|
|
+ struct eventfd_ctx *event = NULL;
|
|
+ u64 *fences = NULL;
|
|
+ u32 fence_count = 0;
|
|
+ int ret;
|
|
+ struct dxghosteventcpu *host_event = NULL;
|
|
+ bool host_event_added = false;
|
|
+ u64 host_event_id = 0;
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (args.flags.enqueue_cpu_event) {
|
|
+ if (args.object_count != 0 || args.cpu_event_handle == 0) {
|
|
+ DXG_ERR("Bad input in EnqueueCpuEvent: %d %lld",
|
|
+ args.object_count, args.cpu_event_handle);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ } else if (args.object_count == 0 ||
|
|
+ args.object_count > DXG_MAX_VM_BUS_PACKET_SIZE ||
|
|
+ args.context_count == 0 ||
|
|
+ args.context_count > DXG_MAX_VM_BUS_PACKET_SIZE) {
|
|
+ DXG_ERR("Invalid input: %d %d",
|
|
+ args.object_count, args.context_count);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ ret = copy_from_user(&context_handle, args.contexts,
|
|
+ sizeof(struct d3dkmthandle));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy context handle");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (args.flags.enqueue_cpu_event) {
|
|
+ host_event = kzalloc(sizeof(*host_event), GFP_KERNEL);
|
|
+ if (host_event == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ host_event->process = process;
|
|
+ event = eventfd_ctx_fdget((int)args.cpu_event_handle);
|
|
+ if (IS_ERR(event)) {
|
|
+ DXG_ERR("failed to reference the event");
|
|
+ event = NULL;
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ fence_count = 0;
|
|
+ host_event->cpu_event = event;
|
|
+ host_event_id = dxgglobal_new_host_event_id();
|
|
+ host_event->hdr.event_id = host_event_id;
|
|
+ host_event->hdr.event_type = dxghostevent_cpu_event;
|
|
+ host_event->remove_from_list = true;
|
|
+ host_event->destroy_after_signal = true;
|
|
+ dxgglobal_add_host_event(&host_event->hdr);
|
|
+ host_event_added = true;
|
|
+ } else {
|
|
+ fences = args.monitored_fence_values;
|
|
+ fence_count = args.object_count;
|
|
+ }
|
|
+
|
|
+ device = dxgprocess_device_by_object_handle(process,
|
|
+ HMGRENTRY_TYPE_DXGCONTEXT,
|
|
+ context_handle);
|
|
+ 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_signal_sync_object(process, adapter,
|
|
+ args.flags, 0, zerohandle,
|
|
+ args.object_count, args.objects,
|
|
+ args.context_count, args.contexts,
|
|
+ fence_count, fences,
|
|
+ (void *)host_event_id, zerohandle);
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (ret < 0) {
|
|
+ if (host_event_added) {
|
|
+ /* The event might be signaled and destroyed by host */
|
|
+ host_event = (struct dxghosteventcpu *)
|
|
+ dxgglobal_get_host_event(host_event_id);
|
|
+ if (host_event) {
|
|
+ eventfd_ctx_put(event);
|
|
+ event = NULL;
|
|
+ kfree(host_event);
|
|
+ host_event = NULL;
|
|
+ }
|
|
+ }
|
|
+ if (event)
|
|
+ eventfd_ctx_put(event);
|
|
+ if (host_event)
|
|
+ kfree(host_event);
|
|
+ }
|
|
+ if (adapter)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (device)
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+dxgkio_wait_sync_object(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_waitforsynchronizationobject2 args;
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ int ret;
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (args.object_count > D3DDDI_MAX_OBJECT_WAITED_ON ||
|
|
+ args.object_count == 0) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ device = dxgprocess_device_by_object_handle(process,
|
|
+ HMGRENTRY_TYPE_DXGCONTEXT,
|
|
+ args.context);
|
|
+ if (device == NULL) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ adapter = device->adapter;
|
|
+ ret = dxgadapter_acquire_lock_shared(adapter);
|
|
+ if (ret < 0) {
|
|
+ adapter = NULL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ DXG_TRACE("Fence value: %lld", args.fence.fence_value);
|
|
+ ret = dxgvmb_send_wait_sync_object_gpu(process, adapter,
|
|
+ args.context, args.object_count,
|
|
+ args.object_array,
|
|
+ &args.fence.fence_value, true);
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (adapter)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (device)
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+dxgkio_wait_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_waitforsynchronizationobjectfromcpu args;
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ struct eventfd_ctx *event = NULL;
|
|
+ struct dxghosteventcpu host_event = { };
|
|
+ struct dxghosteventcpu *async_host_event = NULL;
|
|
+ struct completion local_event = { };
|
|
+ u64 event_id = 0;
|
|
+ int ret;
|
|
+ bool host_event_added = false;
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (args.object_count > DXG_MAX_VM_BUS_PACKET_SIZE ||
|
|
+ args.object_count == 0) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (args.async_event) {
|
|
+ async_host_event = kzalloc(sizeof(*async_host_event),
|
|
+ GFP_KERNEL);
|
|
+ if (async_host_event == NULL) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ async_host_event->process = process;
|
|
+ event = eventfd_ctx_fdget((int)args.async_event);
|
|
+ if (IS_ERR(event)) {
|
|
+ DXG_ERR("failed to reference the event");
|
|
+ event = NULL;
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ async_host_event->cpu_event = event;
|
|
+ async_host_event->hdr.event_id = dxgglobal_new_host_event_id();
|
|
+ async_host_event->destroy_after_signal = true;
|
|
+ async_host_event->hdr.event_type = dxghostevent_cpu_event;
|
|
+ dxgglobal_add_host_event(&async_host_event->hdr);
|
|
+ event_id = async_host_event->hdr.event_id;
|
|
+ host_event_added = true;
|
|
+ } else {
|
|
+ init_completion(&local_event);
|
|
+ host_event.completion_event = &local_event;
|
|
+ host_event.hdr.event_id = dxgglobal_new_host_event_id();
|
|
+ host_event.hdr.event_type = dxghostevent_cpu_event;
|
|
+ dxgglobal_add_host_event(&host_event.hdr);
|
|
+ event_id = host_event.hdr.event_id;
|
|
+ }
|
|
+
|
|
+ device = dxgprocess_device_by_handle(process, args.device);
|
|
+ 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_wait_sync_object_cpu(process, adapter,
|
|
+ &args, event_id);
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ if (args.async_event == 0) {
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ adapter = NULL;
|
|
+ ret = wait_for_completion_interruptible(&local_event);
|
|
+ if (ret) {
|
|
+ DXG_ERR("wait_completion_interruptible: %d",
|
|
+ ret);
|
|
+ ret = -ERESTARTSYS;
|
|
+ }
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (adapter)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (device)
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+ if (host_event.hdr.event_id)
|
|
+ dxgglobal_remove_host_event(&host_event.hdr);
|
|
+ if (ret < 0) {
|
|
+ if (host_event_added) {
|
|
+ async_host_event = (struct dxghosteventcpu *)
|
|
+ dxgglobal_get_host_event(event_id);
|
|
+ if (async_host_event) {
|
|
+ if (async_host_event->hdr.event_type ==
|
|
+ dxghostevent_cpu_event) {
|
|
+ eventfd_ctx_put(event);
|
|
+ event = NULL;
|
|
+ kfree(async_host_event);
|
|
+ async_host_event = NULL;
|
|
+ } else {
|
|
+ DXG_ERR("Invalid event type");
|
|
+ DXGKRNL_ASSERT(0);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (event)
|
|
+ eventfd_ctx_put(event);
|
|
+ if (async_host_event)
|
|
+ kfree(async_host_event);
|
|
+ }
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+dxgkio_wait_sync_object_gpu(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_waitforsynchronizationobjectfromgpu args;
|
|
+ struct dxgcontext *context = NULL;
|
|
+ struct d3dkmthandle device_handle = {};
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ struct dxgsyncobject *syncobj = NULL;
|
|
+ struct d3dkmthandle *objects = NULL;
|
|
+ u32 object_size;
|
|
+ u64 *fences = NULL;
|
|
+ int ret;
|
|
+ enum hmgrentry_type syncobj_type = HMGRENTRY_TYPE_FREE;
|
|
+ bool monitored_fence = false;
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (args.object_count > DXG_MAX_VM_BUS_PACKET_SIZE ||
|
|
+ args.object_count == 0) {
|
|
+ DXG_ERR("Invalid object count: %d", args.object_count);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ object_size = sizeof(struct d3dkmthandle) * args.object_count;
|
|
+ objects = vzalloc(object_size);
|
|
+ if (objects == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ret = copy_from_user(objects, args.objects, object_size);
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy objects");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ hmgrtable_lock(&process->handle_table, DXGLOCK_SHARED);
|
|
+ context = hmgrtable_get_object_by_type(&process->handle_table,
|
|
+ HMGRENTRY_TYPE_DXGCONTEXT,
|
|
+ args.context);
|
|
+ if (context) {
|
|
+ device_handle = context->device_handle;
|
|
+ syncobj_type =
|
|
+ hmgrtable_get_object_type(&process->handle_table,
|
|
+ objects[0]);
|
|
+ }
|
|
+ if (device_handle.v == 0) {
|
|
+ DXG_ERR("Invalid context handle: %x", args.context.v);
|
|
+ ret = -EINVAL;
|
|
+ } else {
|
|
+ if (syncobj_type == HMGRENTRY_TYPE_MONITOREDFENCE) {
|
|
+ monitored_fence = true;
|
|
+ } else if (syncobj_type == HMGRENTRY_TYPE_DXGSYNCOBJECT) {
|
|
+ syncobj =
|
|
+ hmgrtable_get_object_by_type(&process->handle_table,
|
|
+ HMGRENTRY_TYPE_DXGSYNCOBJECT,
|
|
+ objects[0]);
|
|
+ if (syncobj == NULL) {
|
|
+ DXG_ERR("Invalid syncobj: %x",
|
|
+ objects[0].v);
|
|
+ ret = -EINVAL;
|
|
+ } else {
|
|
+ monitored_fence = syncobj->monitored_fence;
|
|
+ }
|
|
+ } else {
|
|
+ DXG_ERR("Invalid syncobj type: %x",
|
|
+ objects[0].v);
|
|
+ ret = -EINVAL;
|
|
+ }
|
|
+ }
|
|
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_SHARED);
|
|
+
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ if (monitored_fence) {
|
|
+ object_size = sizeof(u64) * args.object_count;
|
|
+ fences = vzalloc(object_size);
|
|
+ if (fences == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ret = copy_from_user(fences, args.monitored_fence_values,
|
|
+ object_size);
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy fences");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ } else {
|
|
+ fences = &args.fence_value;
|
|
+ }
|
|
+
|
|
+ device = dxgprocess_device_by_handle(process, device_handle);
|
|
+ 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_wait_sync_object_gpu(process, adapter,
|
|
+ args.context, args.object_count,
|
|
+ objects, fences,
|
|
+ !monitored_fence);
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (adapter)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (device)
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+ if (objects)
|
|
+ vfree(objects);
|
|
+ if (fences && fences != &args.fence_value)
|
|
+ vfree(fences);
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static struct ioctl_desc ioctls[] = {
|
|
/* 0x00 */ {},
|
|
/* 0x01 */ {dxgkio_open_adapter_from_luid, LX_DXOPENADAPTERFROMLUID},
|
|
@@ -1485,8 +2164,8 @@ static struct ioctl_desc ioctls[] = {
|
|
/* 0x0e */ {},
|
|
/* 0x0f */ {},
|
|
/* 0x10 */ {dxgkio_create_sync_object, LX_DXCREATESYNCHRONIZATIONOBJECT},
|
|
-/* 0x11 */ {},
|
|
-/* 0x12 */ {},
|
|
+/* 0x11 */ {dxgkio_signal_sync_object, LX_DXSIGNALSYNCHRONIZATIONOBJECT},
|
|
+/* 0x12 */ {dxgkio_wait_sync_object, LX_DXWAITFORSYNCHRONIZATIONOBJECT},
|
|
/* 0x13 */ {dxgkio_destroy_allocation, LX_DXDESTROYALLOCATION2},
|
|
/* 0x14 */ {dxgkio_enum_adapters, LX_DXENUMADAPTERS2},
|
|
/* 0x15 */ {dxgkio_close_adapter, LX_DXCLOSEADAPTER},
|
|
@@ -1517,17 +2196,22 @@ static struct ioctl_desc ioctls[] = {
|
|
/* 0x2e */ {},
|
|
/* 0x2f */ {},
|
|
/* 0x30 */ {},
|
|
-/* 0x31 */ {},
|
|
-/* 0x32 */ {},
|
|
-/* 0x33 */ {},
|
|
+/* 0x31 */ {dxgkio_signal_sync_object_cpu,
|
|
+ LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMCPU},
|
|
+/* 0x32 */ {dxgkio_signal_sync_object_gpu,
|
|
+ LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU},
|
|
+/* 0x33 */ {dxgkio_signal_sync_object_gpu2,
|
|
+ LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU2},
|
|
/* 0x34 */ {},
|
|
/* 0x35 */ {},
|
|
/* 0x36 */ {},
|
|
/* 0x37 */ {},
|
|
/* 0x38 */ {},
|
|
/* 0x39 */ {},
|
|
-/* 0x3a */ {},
|
|
-/* 0x3b */ {},
|
|
+/* 0x3a */ {dxgkio_wait_sync_object_cpu,
|
|
+ LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMCPU},
|
|
+/* 0x3b */ {dxgkio_wait_sync_object_gpu,
|
|
+ LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU},
|
|
/* 0x3c */ {},
|
|
/* 0x3d */ {},
|
|
/* 0x3e */ {dxgkio_enum_adapters3, LX_DXENUMADAPTERS3},
|
|
diff --git a/drivers/hv/dxgkrnl/misc.h b/drivers/hv/dxgkrnl/misc.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/misc.h
|
|
+++ b/drivers/hv/dxgkrnl/misc.h
|
|
@@ -25,6 +25,8 @@ extern const struct d3dkmthandle zerohandle;
|
|
* The locks here are in the order from lowest to highest.
|
|
* When a lower lock is held, the higher lock should not be acquired.
|
|
*
|
|
+ * device_list_mutex
|
|
+ * host_event_list_mutex
|
|
* channel_lock (VMBus channel lock)
|
|
* fd_mutex
|
|
* plistmutex (process list mutex)
|
|
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/include/uapi/misc/d3dkmthk.h
|
|
+++ b/include/uapi/misc/d3dkmthk.h
|
|
@@ -60,6 +60,9 @@ struct winluid {
|
|
|
|
#define D3DKMT_CREATEALLOCATION_MAX 1024
|
|
#define D3DKMT_ADAPTERS_MAX 64
|
|
+#define D3DDDI_MAX_BROADCAST_CONTEXT 64
|
|
+#define D3DDDI_MAX_OBJECT_WAITED_ON 32
|
|
+#define D3DDDI_MAX_OBJECT_SIGNALED 32
|
|
|
|
struct d3dkmt_adapterinfo {
|
|
struct d3dkmthandle adapter_handle;
|
|
@@ -343,6 +346,148 @@ struct d3dkmt_createsynchronizationobject2 {
|
|
__u32 reserved1;
|
|
};
|
|
|
|
+struct d3dkmt_waitforsynchronizationobject2 {
|
|
+ struct d3dkmthandle context;
|
|
+ __u32 object_count;
|
|
+ struct d3dkmthandle object_array[D3DDDI_MAX_OBJECT_WAITED_ON];
|
|
+ union {
|
|
+ struct {
|
|
+ __u64 fence_value;
|
|
+ } fence;
|
|
+ __u64 reserved[8];
|
|
+ };
|
|
+};
|
|
+
|
|
+struct d3dddicb_signalflags {
|
|
+ union {
|
|
+ struct {
|
|
+ __u32 signal_at_submission:1;
|
|
+ __u32 enqueue_cpu_event:1;
|
|
+ __u32 allow_fence_rewind:1;
|
|
+ __u32 reserved:28;
|
|
+ __u32 DXGK_SIGNAL_FLAG_INTERNAL0:1;
|
|
+ };
|
|
+ __u32 value;
|
|
+ };
|
|
+};
|
|
+
|
|
+struct d3dkmt_signalsynchronizationobject2 {
|
|
+ struct d3dkmthandle context;
|
|
+ __u32 object_count;
|
|
+ struct d3dkmthandle object_array[D3DDDI_MAX_OBJECT_SIGNALED];
|
|
+ struct d3dddicb_signalflags flags;
|
|
+ __u32 context_count;
|
|
+ struct d3dkmthandle contexts[D3DDDI_MAX_BROADCAST_CONTEXT];
|
|
+ union {
|
|
+ struct {
|
|
+ __u64 fence_value;
|
|
+ } fence;
|
|
+ __u64 cpu_event_handle;
|
|
+ __u64 reserved[8];
|
|
+ };
|
|
+};
|
|
+
|
|
+struct d3dddi_waitforsynchronizationobjectfromcpu_flags {
|
|
+ union {
|
|
+ struct {
|
|
+ __u32 wait_any:1;
|
|
+ __u32 reserved:31;
|
|
+ };
|
|
+ __u32 value;
|
|
+ };
|
|
+};
|
|
+
|
|
+struct d3dkmt_waitforsynchronizationobjectfromcpu {
|
|
+ struct d3dkmthandle device;
|
|
+ __u32 object_count;
|
|
+#ifdef __KERNEL__
|
|
+ struct d3dkmthandle *objects;
|
|
+ __u64 *fence_values;
|
|
+#else
|
|
+ __u64 objects;
|
|
+ __u64 fence_values;
|
|
+#endif
|
|
+ __u64 async_event;
|
|
+ struct d3dddi_waitforsynchronizationobjectfromcpu_flags flags;
|
|
+};
|
|
+
|
|
+struct d3dkmt_signalsynchronizationobjectfromcpu {
|
|
+ struct d3dkmthandle device;
|
|
+ __u32 object_count;
|
|
+#ifdef __KERNEL__
|
|
+ struct d3dkmthandle *objects;
|
|
+ __u64 *fence_values;
|
|
+#else
|
|
+ __u64 objects;
|
|
+ __u64 fence_values;
|
|
+#endif
|
|
+ struct d3dddicb_signalflags flags;
|
|
+};
|
|
+
|
|
+struct d3dkmt_waitforsynchronizationobjectfromgpu {
|
|
+ struct d3dkmthandle context;
|
|
+ __u32 object_count;
|
|
+#ifdef __KERNEL__
|
|
+ struct d3dkmthandle *objects;
|
|
+#else
|
|
+ __u64 objects;
|
|
+#endif
|
|
+ union {
|
|
+#ifdef __KERNEL__
|
|
+ __u64 *monitored_fence_values;
|
|
+#else
|
|
+ __u64 monitored_fence_values;
|
|
+#endif
|
|
+ __u64 fence_value;
|
|
+ __u64 reserved[8];
|
|
+ };
|
|
+};
|
|
+
|
|
+struct d3dkmt_signalsynchronizationobjectfromgpu {
|
|
+ struct d3dkmthandle context;
|
|
+ __u32 object_count;
|
|
+#ifdef __KERNEL__
|
|
+ struct d3dkmthandle *objects;
|
|
+#else
|
|
+ __u64 objects;
|
|
+#endif
|
|
+ union {
|
|
+#ifdef __KERNEL__
|
|
+ __u64 *monitored_fence_values;
|
|
+#else
|
|
+ __u64 monitored_fence_values;
|
|
+#endif
|
|
+ __u64 reserved[8];
|
|
+ };
|
|
+};
|
|
+
|
|
+struct d3dkmt_signalsynchronizationobjectfromgpu2 {
|
|
+ __u32 object_count;
|
|
+ __u32 reserved1;
|
|
+#ifdef __KERNEL__
|
|
+ struct d3dkmthandle *objects;
|
|
+#else
|
|
+ __u64 objects;
|
|
+#endif
|
|
+ struct d3dddicb_signalflags flags;
|
|
+ __u32 context_count;
|
|
+#ifdef __KERNEL__
|
|
+ struct d3dkmthandle *contexts;
|
|
+#else
|
|
+ __u64 contexts;
|
|
+#endif
|
|
+ union {
|
|
+ __u64 fence_value;
|
|
+ __u64 cpu_event_handle;
|
|
+#ifdef __KERNEL__
|
|
+ __u64 *monitored_fence_values;
|
|
+#else
|
|
+ __u64 monitored_fence_values;
|
|
+#endif
|
|
+ __u64 reserved[8];
|
|
+ };
|
|
+};
|
|
+
|
|
struct d3dkmt_destroysynchronizationobject {
|
|
struct d3dkmthandle sync_object;
|
|
};
|
|
@@ -576,6 +721,10 @@ struct d3dkmt_enumadapters3 {
|
|
_IOWR(0x47, 0x09, struct d3dkmt_queryadapterinfo)
|
|
#define LX_DXCREATESYNCHRONIZATIONOBJECT \
|
|
_IOWR(0x47, 0x10, struct d3dkmt_createsynchronizationobject2)
|
|
+#define LX_DXSIGNALSYNCHRONIZATIONOBJECT \
|
|
+ _IOWR(0x47, 0x11, struct d3dkmt_signalsynchronizationobject2)
|
|
+#define LX_DXWAITFORSYNCHRONIZATIONOBJECT \
|
|
+ _IOWR(0x47, 0x12, struct d3dkmt_waitforsynchronizationobject2)
|
|
#define LX_DXDESTROYALLOCATION2 \
|
|
_IOWR(0x47, 0x13, struct d3dkmt_destroyallocation2)
|
|
#define LX_DXENUMADAPTERS2 \
|
|
@@ -586,6 +735,16 @@ struct d3dkmt_enumadapters3 {
|
|
_IOWR(0x47, 0x19, struct d3dkmt_destroydevice)
|
|
#define LX_DXDESTROYSYNCHRONIZATIONOBJECT \
|
|
_IOWR(0x47, 0x1d, struct d3dkmt_destroysynchronizationobject)
|
|
+#define LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMCPU \
|
|
+ _IOWR(0x47, 0x31, struct d3dkmt_signalsynchronizationobjectfromcpu)
|
|
+#define LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU \
|
|
+ _IOWR(0x47, 0x32, struct d3dkmt_signalsynchronizationobjectfromgpu)
|
|
+#define LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU2 \
|
|
+ _IOWR(0x47, 0x33, struct d3dkmt_signalsynchronizationobjectfromgpu2)
|
|
+#define LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMCPU \
|
|
+ _IOWR(0x47, 0x3a, struct d3dkmt_waitforsynchronizationobjectfromcpu)
|
|
+#define LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU \
|
|
+ _IOWR(0x47, 0x3b, struct d3dkmt_waitforsynchronizationobjectfromgpu)
|
|
#define LX_DXENUMADAPTERS3 \
|
|
_IOWR(0x47, 0x3e, struct d3dkmt_enumadapters3)
|
|
|
|
--
|
|
Armbian
|
|
|