mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
659 lines
20 KiB
Diff
659 lines
20 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Iouri Tarassov <iourit@linux.microsoft.com>
|
|
Date: Mon, 2 May 2022 11:46:48 -0700
|
|
Subject: drivers: hv: dxgkrnl: Implement D3DKMTWaitSyncFile
|
|
|
|
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/dxgkrnl.h | 11 +
|
|
drivers/hv/dxgkrnl/dxgmodule.c | 7 +-
|
|
drivers/hv/dxgkrnl/dxgprocess.c | 12 +-
|
|
drivers/hv/dxgkrnl/dxgsyncfile.c | 291 +++++++++-
|
|
drivers/hv/dxgkrnl/dxgsyncfile.h | 3 +
|
|
drivers/hv/dxgkrnl/dxgvmbus.c | 49 ++
|
|
drivers/hv/dxgkrnl/ioctl.c | 16 +-
|
|
include/uapi/misc/d3dkmthk.h | 23 +
|
|
8 files changed, 396 insertions(+), 16 deletions(-)
|
|
|
|
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
|
|
@@ -254,6 +254,10 @@ void dxgsharedsyncobj_add_syncobj(struct dxgsharedsyncobject *sharedsyncobj,
|
|
struct dxgsyncobject *syncobj);
|
|
void dxgsharedsyncobj_remove_syncobj(struct dxgsharedsyncobject *sharedsyncobj,
|
|
struct dxgsyncobject *syncobj);
|
|
+int dxgsharedsyncobj_get_host_nt_handle(struct dxgsharedsyncobject *syncobj,
|
|
+ struct dxgprocess *process,
|
|
+ struct d3dkmthandle objecthandle);
|
|
+void dxgsharedsyncobj_put(struct dxgsharedsyncobject *syncobj);
|
|
|
|
struct dxgsyncobject *dxgsyncobject_create(struct dxgprocess *process,
|
|
struct dxgdevice *device,
|
|
@@ -384,6 +388,8 @@ struct dxgprocess {
|
|
pid_t tgid;
|
|
/* how many time the process was opened */
|
|
struct kref process_kref;
|
|
+ /* protects the object memory */
|
|
+ struct kref process_mem_kref;
|
|
/*
|
|
* This handle table is used for all objects except dxgadapter
|
|
* The handle table lock order is higher than the local_handle_table
|
|
@@ -405,6 +411,7 @@ struct dxgprocess {
|
|
struct dxgprocess *dxgprocess_create(void);
|
|
void dxgprocess_destroy(struct dxgprocess *process);
|
|
void dxgprocess_release(struct kref *refcount);
|
|
+void dxgprocess_mem_release(struct kref *refcount);
|
|
int dxgprocess_open_adapter(struct dxgprocess *process,
|
|
struct dxgadapter *adapter,
|
|
struct d3dkmthandle *handle);
|
|
@@ -932,6 +939,10 @@ int dxgvmb_send_open_sync_object_nt(struct dxgprocess *process,
|
|
struct d3dkmt_opensyncobjectfromnthandle2
|
|
*args,
|
|
struct dxgsyncobject *syncobj);
|
|
+int dxgvmb_send_open_sync_object(struct dxgprocess *process,
|
|
+ struct d3dkmthandle device,
|
|
+ struct d3dkmthandle host_shared_syncobj,
|
|
+ struct d3dkmthandle *syncobj);
|
|
int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
|
|
struct dxgadapter *adapter,
|
|
struct d3dkmt_queryallocationresidency
|
|
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
|
|
@@ -149,10 +149,11 @@ void dxgglobal_remove_host_event(struct dxghostevent *event)
|
|
spin_unlock_irq(&dxgglobal->host_event_list_mutex);
|
|
}
|
|
|
|
-static void signal_dma_fence(struct dxghostevent *eventhdr)
|
|
+static void dxg_signal_dma_fence(struct dxghostevent *eventhdr)
|
|
{
|
|
struct dxgsyncpoint *event = (struct dxgsyncpoint *)eventhdr;
|
|
|
|
+ DXG_TRACE("syncpoint: %px, fence: %lld", event, event->fence_value);
|
|
event->fence_value++;
|
|
list_del(&eventhdr->host_event_list_entry);
|
|
dma_fence_signal(&event->base);
|
|
@@ -198,7 +199,7 @@ void dxgglobal_signal_host_event(u64 event_id)
|
|
if (event->event_type == dxghostevent_cpu_event)
|
|
signal_host_cpu_event(event);
|
|
else if (event->event_type == dxghostevent_dma_fence)
|
|
- signal_dma_fence(event);
|
|
+ dxg_signal_dma_fence(event);
|
|
else
|
|
DXG_ERR("Unknown host event type");
|
|
break;
|
|
@@ -355,6 +356,7 @@ static struct dxgprocess *dxgglobal_get_current_process(void)
|
|
if (entry->tgid == current->tgid) {
|
|
if (kref_get_unless_zero(&entry->process_kref)) {
|
|
process = entry;
|
|
+ kref_get(&entry->process_mem_kref);
|
|
DXG_TRACE("found dxgprocess");
|
|
} else {
|
|
DXG_TRACE("process is destroyed");
|
|
@@ -405,6 +407,7 @@ static int dxgk_release(struct inode *n, struct file *f)
|
|
return -EINVAL;
|
|
|
|
kref_put(&process->process_kref, dxgprocess_release);
|
|
+ kref_put(&process->process_mem_kref, dxgprocess_mem_release);
|
|
|
|
f->private_data = NULL;
|
|
return 0;
|
|
diff --git a/drivers/hv/dxgkrnl/dxgprocess.c b/drivers/hv/dxgkrnl/dxgprocess.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgprocess.c
|
|
+++ b/drivers/hv/dxgkrnl/dxgprocess.c
|
|
@@ -39,6 +39,7 @@ struct dxgprocess *dxgprocess_create(void)
|
|
} else {
|
|
INIT_LIST_HEAD(&process->plistentry);
|
|
kref_init(&process->process_kref);
|
|
+ kref_init(&process->process_mem_kref);
|
|
|
|
mutex_lock(&dxgglobal->plistmutex);
|
|
list_add_tail(&process->plistentry,
|
|
@@ -117,8 +118,17 @@ void dxgprocess_release(struct kref *refcount)
|
|
|
|
dxgprocess_destroy(process);
|
|
|
|
- if (process->host_handle.v)
|
|
+ if (process->host_handle.v) {
|
|
dxgvmb_send_destroy_process(process->host_handle);
|
|
+ process->host_handle.v = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+void dxgprocess_mem_release(struct kref *refcount)
|
|
+{
|
|
+ struct dxgprocess *process;
|
|
+
|
|
+ process = container_of(refcount, struct dxgprocess, process_mem_kref);
|
|
kfree(process);
|
|
}
|
|
|
|
diff --git a/drivers/hv/dxgkrnl/dxgsyncfile.c b/drivers/hv/dxgkrnl/dxgsyncfile.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgsyncfile.c
|
|
+++ b/drivers/hv/dxgkrnl/dxgsyncfile.c
|
|
@@ -9,6 +9,20 @@
|
|
* Dxgkrnl Graphics Driver
|
|
* Ioctl implementation
|
|
*
|
|
+ * dxgsyncpoint:
|
|
+ * - pointer to dxgsharedsyncobject
|
|
+ * - host_shared_handle_nt_reference incremented
|
|
+ * - list of (process, local syncobj d3dkmthandle) pairs
|
|
+ * wait for sync file
|
|
+ * - get dxgsyncpoint
|
|
+ * - if process doesn't have a local syncobj
|
|
+ * - create local dxgsyncobject
|
|
+ * - send open syncobj to the host
|
|
+ * - Send wait for syncobj to the context
|
|
+ * dxgsyncpoint destruction
|
|
+ * - walk the list of (process, local syncobj)
|
|
+ * - destroy syncobj
|
|
+ * - remove reference to dxgsharedsyncobject
|
|
*/
|
|
|
|
#include <linux/eventfd.h>
|
|
@@ -45,12 +59,15 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
|
|
struct d3dkmt_createsyncfile args;
|
|
struct dxgsyncpoint *pt = NULL;
|
|
int ret = 0;
|
|
- int fd = get_unused_fd_flags(O_CLOEXEC);
|
|
+ int fd;
|
|
struct sync_file *sync_file = NULL;
|
|
struct dxgdevice *device = NULL;
|
|
struct dxgadapter *adapter = NULL;
|
|
+ struct dxgsyncobject *syncobj = NULL;
|
|
struct d3dkmt_waitforsynchronizationobjectfromcpu waitargs = {};
|
|
+ bool device_lock_acquired = false;
|
|
|
|
+ fd = get_unused_fd_flags(O_CLOEXEC);
|
|
if (fd < 0) {
|
|
DXG_ERR("get_unused_fd_flags failed: %d", fd);
|
|
ret = fd;
|
|
@@ -74,9 +91,9 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
|
|
ret = dxgdevice_acquire_lock_shared(device);
|
|
if (ret < 0) {
|
|
DXG_ERR("dxgdevice_acquire_lock_shared failed");
|
|
- device = NULL;
|
|
goto cleanup;
|
|
}
|
|
+ device_lock_acquired = true;
|
|
|
|
adapter = device->adapter;
|
|
ret = dxgadapter_acquire_lock_shared(adapter);
|
|
@@ -109,6 +126,30 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
|
|
}
|
|
dma_fence_put(&pt->base);
|
|
|
|
+ hmgrtable_lock(&process->handle_table, DXGLOCK_SHARED);
|
|
+ syncobj = hmgrtable_get_object(&process->handle_table,
|
|
+ args.monitored_fence);
|
|
+ if (syncobj == NULL) {
|
|
+ DXG_ERR("invalid syncobj handle %x", args.monitored_fence.v);
|
|
+ ret = -EINVAL;
|
|
+ } else {
|
|
+ if (syncobj->shared) {
|
|
+ kref_get(&syncobj->syncobj_kref);
|
|
+ pt->shared_syncobj = syncobj->shared_owner;
|
|
+ }
|
|
+ }
|
|
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_SHARED);
|
|
+
|
|
+ if (pt->shared_syncobj) {
|
|
+ ret = dxgsharedsyncobj_get_host_nt_handle(pt->shared_syncobj,
|
|
+ process,
|
|
+ args.monitored_fence);
|
|
+ if (ret)
|
|
+ pt->shared_syncobj = NULL;
|
|
+ }
|
|
+ if (ret)
|
|
+ goto cleanup;
|
|
+
|
|
waitargs.device = args.device;
|
|
waitargs.object_count = 1;
|
|
waitargs.objects = &args.monitored_fence;
|
|
@@ -132,10 +173,15 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
|
|
fd_install(fd, sync_file->file);
|
|
|
|
cleanup:
|
|
+ if (syncobj && syncobj->shared)
|
|
+ kref_put(&syncobj->syncobj_kref, dxgsyncobject_release);
|
|
if (adapter)
|
|
dxgadapter_release_lock_shared(adapter);
|
|
- if (device)
|
|
- dxgdevice_release_lock_shared(device);
|
|
+ if (device) {
|
|
+ if (device_lock_acquired)
|
|
+ dxgdevice_release_lock_shared(device);
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+ }
|
|
if (ret) {
|
|
if (sync_file) {
|
|
fput(sync_file->file);
|
|
@@ -151,6 +197,228 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
|
|
return ret;
|
|
}
|
|
|
|
+int dxgkio_open_syncobj_from_syncfile(struct dxgprocess *process,
|
|
+ void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_opensyncobjectfromsyncfile args;
|
|
+ int ret = 0;
|
|
+ struct dxgsyncpoint *pt = NULL;
|
|
+ struct dma_fence *dmafence = NULL;
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ struct dxgsyncobject *syncobj = NULL;
|
|
+ struct d3dddi_synchronizationobject_flags flags = { };
|
|
+ struct d3dkmt_opensyncobjectfromnthandle2 openargs = { };
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EFAULT;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ dmafence = sync_file_get_fence(args.sync_file_handle);
|
|
+ if (dmafence == NULL) {
|
|
+ DXG_ERR("failed to get dmafence from handle: %llx",
|
|
+ args.sync_file_handle);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ pt = to_syncpoint(dmafence);
|
|
+ if (pt->shared_syncobj == NULL) {
|
|
+ DXG_ERR("Sync object is not shared");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ device = dxgprocess_device_by_handle(process, args.device);
|
|
+ if (device == NULL) {
|
|
+ DXG_ERR("dxgprocess_device_by_handle failed");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ ret = dxgdevice_acquire_lock_shared(device);
|
|
+ if (ret < 0) {
|
|
+ DXG_ERR("dxgdevice_acquire_lock_shared failed");
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+ device = NULL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ adapter = device->adapter;
|
|
+ ret = dxgadapter_acquire_lock_shared(adapter);
|
|
+ if (ret < 0) {
|
|
+ DXG_ERR("dxgadapter_acquire_lock_shared failed");
|
|
+ adapter = NULL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ flags.shared = 1;
|
|
+ flags.nt_security_sharing = 1;
|
|
+ syncobj = dxgsyncobject_create(process, device, adapter,
|
|
+ _D3DDDI_MONITORED_FENCE, flags);
|
|
+ if (syncobj == NULL) {
|
|
+ DXG_ERR("failed to create sync object");
|
|
+ ret = -ENOMEM;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ dxgsharedsyncobj_add_syncobj(pt->shared_syncobj, syncobj);
|
|
+
|
|
+ /* Open the shared syncobj to get a local handle */
|
|
+
|
|
+ openargs.device = device->handle;
|
|
+ openargs.flags.shared = 1;
|
|
+ openargs.flags.nt_security_sharing = 1;
|
|
+ openargs.flags.no_signal = 1;
|
|
+
|
|
+ ret = dxgvmb_send_open_sync_object_nt(process,
|
|
+ &dxgglobal->channel, &openargs, syncobj);
|
|
+ if (ret) {
|
|
+ DXG_ERR("Failed to open shared syncobj on host");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
|
|
+ ret = hmgrtable_assign_handle(&process->handle_table,
|
|
+ syncobj,
|
|
+ HMGRENTRY_TYPE_DXGSYNCOBJECT,
|
|
+ openargs.sync_object);
|
|
+ if (ret == 0) {
|
|
+ syncobj->handle = openargs.sync_object;
|
|
+ kref_get(&syncobj->syncobj_kref);
|
|
+ }
|
|
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
|
|
+
|
|
+ args.syncobj = openargs.sync_object;
|
|
+ args.fence_value = pt->fence_value;
|
|
+ args.fence_value_cpu_va = openargs.monitored_fence.fence_value_cpu_va;
|
|
+ args.fence_value_gpu_va = openargs.monitored_fence.fence_value_gpu_va;
|
|
+
|
|
+ ret = copy_to_user(inargs, &args, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy output args");
|
|
+ ret = -EFAULT;
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+ if (dmafence)
|
|
+ dma_fence_put(dmafence);
|
|
+ if (ret) {
|
|
+ if (syncobj) {
|
|
+ dxgsyncobject_destroy(process, syncobj);
|
|
+ kref_put(&syncobj->syncobj_kref, dxgsyncobject_release);
|
|
+ }
|
|
+ }
|
|
+ if (adapter)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (device) {
|
|
+ dxgdevice_release_lock_shared(device);
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+ }
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int dxgkio_wait_sync_file(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_waitsyncfile args;
|
|
+ struct dma_fence *dmafence = NULL;
|
|
+ int ret = 0;
|
|
+ struct dxgsyncpoint *pt = NULL;
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ struct d3dkmthandle syncobj_handle = {};
|
|
+ bool device_lock_acquired = false;
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EFAULT;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ dmafence = sync_file_get_fence(args.sync_file_handle);
|
|
+ if (dmafence == NULL) {
|
|
+ DXG_ERR("failed to get dmafence from handle: %llx",
|
|
+ args.sync_file_handle);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ pt = to_syncpoint(dmafence);
|
|
+
|
|
+ device = dxgprocess_device_by_object_handle(process,
|
|
+ HMGRENTRY_TYPE_DXGCONTEXT,
|
|
+ args.context);
|
|
+ if (device == NULL) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ ret = dxgdevice_acquire_lock_shared(device);
|
|
+ if (ret < 0) {
|
|
+ DXG_ERR("dxgdevice_acquire_lock_shared failed");
|
|
+ device = NULL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ device_lock_acquired = true;
|
|
+
|
|
+ adapter = device->adapter;
|
|
+ ret = dxgadapter_acquire_lock_shared(adapter);
|
|
+ if (ret < 0) {
|
|
+ DXG_ERR("dxgadapter_acquire_lock_shared failed");
|
|
+ adapter = NULL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ /* Open the shared syncobj to get a local handle */
|
|
+ if (pt->shared_syncobj == NULL) {
|
|
+ DXG_ERR("Sync object is not shared");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ret = dxgvmb_send_open_sync_object(process,
|
|
+ device->handle,
|
|
+ pt->shared_syncobj->host_shared_handle,
|
|
+ &syncobj_handle);
|
|
+ if (ret) {
|
|
+ DXG_ERR("Failed to open shared syncobj on host");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ /* Ask the host to insert the syncobj to the context queue */
|
|
+ ret = dxgvmb_send_wait_sync_object_gpu(process, adapter,
|
|
+ args.context, 1,
|
|
+ &syncobj_handle,
|
|
+ &pt->fence_value,
|
|
+ false);
|
|
+ if (ret < 0) {
|
|
+ DXG_ERR("dxgvmb_send_wait_sync_object_cpu failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Destroy the local syncobject immediately. This will not unblock
|
|
+ * GPU waiters, but will unblock CPU waiter, which includes the sync
|
|
+ * file itself.
|
|
+ */
|
|
+ ret = dxgvmb_send_destroy_sync_object(process, syncobj_handle);
|
|
+
|
|
+cleanup:
|
|
+ if (adapter)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (device) {
|
|
+ if (device_lock_acquired)
|
|
+ dxgdevice_release_lock_shared(device);
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+ }
|
|
+ if (dmafence)
|
|
+ dma_fence_put(dmafence);
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static const char *dxgdmafence_get_driver_name(struct dma_fence *fence)
|
|
{
|
|
return "dxgkrnl";
|
|
@@ -166,11 +434,16 @@ static void dxgdmafence_release(struct dma_fence *fence)
|
|
struct dxgsyncpoint *syncpoint;
|
|
|
|
syncpoint = to_syncpoint(fence);
|
|
- if (syncpoint) {
|
|
- if (syncpoint->hdr.event_id)
|
|
- dxgglobal_get_host_event(syncpoint->hdr.event_id);
|
|
- kfree(syncpoint);
|
|
- }
|
|
+ if (syncpoint == NULL)
|
|
+ return;
|
|
+
|
|
+ if (syncpoint->hdr.event_id)
|
|
+ dxgglobal_get_host_event(syncpoint->hdr.event_id);
|
|
+
|
|
+ if (syncpoint->shared_syncobj)
|
|
+ dxgsharedsyncobj_put(syncpoint->shared_syncobj);
|
|
+
|
|
+ kfree(syncpoint);
|
|
}
|
|
|
|
static bool dxgdmafence_signaled(struct dma_fence *fence)
|
|
diff --git a/drivers/hv/dxgkrnl/dxgsyncfile.h b/drivers/hv/dxgkrnl/dxgsyncfile.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgsyncfile.h
|
|
+++ b/drivers/hv/dxgkrnl/dxgsyncfile.h
|
|
@@ -17,10 +17,13 @@
|
|
#include <linux/sync_file.h>
|
|
|
|
int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs);
|
|
+int dxgkio_wait_sync_file(struct dxgprocess *process, void *__user inargs);
|
|
+int dxgkio_open_syncobj_from_syncfile(struct dxgprocess *p, void *__user args);
|
|
|
|
struct dxgsyncpoint {
|
|
struct dxghostevent hdr;
|
|
struct dma_fence base;
|
|
+ struct dxgsharedsyncobject *shared_syncobj;
|
|
u64 fence_value;
|
|
u64 context;
|
|
spinlock_t lock;
|
|
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
|
|
@@ -796,6 +796,55 @@ int dxgvmb_send_open_sync_object_nt(struct dxgprocess *process,
|
|
return ret;
|
|
}
|
|
|
|
+int dxgvmb_send_open_sync_object(struct dxgprocess *process,
|
|
+ struct d3dkmthandle device,
|
|
+ struct d3dkmthandle host_shared_syncobj,
|
|
+ struct d3dkmthandle *syncobj)
|
|
+{
|
|
+ struct dxgkvmb_command_opensyncobject *command;
|
|
+ struct dxgkvmb_command_opensyncobject_return result = { };
|
|
+ int ret;
|
|
+ struct dxgvmbusmsg msg;
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ ret = init_message(&msg, NULL, process, sizeof(*command));
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ command = (void *)msg.msg;
|
|
+
|
|
+ command_vm_to_host_init2(&command->hdr, DXGK_VMBCOMMAND_OPENSYNCOBJECT,
|
|
+ process->host_handle);
|
|
+ command->device = device;
|
|
+ command->global_sync_object = host_shared_syncobj;
|
|
+ command->flags.shared = 1;
|
|
+ command->flags.nt_security_sharing = 1;
|
|
+ command->flags.no_signal = 1;
|
|
+
|
|
+ ret = dxgglobal_acquire_channel_lock();
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ ret = dxgvmb_send_sync_msg(&dxgglobal->channel, msg.hdr, msg.size,
|
|
+ &result, sizeof(result));
|
|
+
|
|
+ dxgglobal_release_channel_lock();
|
|
+
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ ret = ntstatus2int(result.status);
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ *syncobj = result.sync_object;
|
|
+
|
|
+cleanup:
|
|
+ free_message(&msg, process);
|
|
+ if (ret)
|
|
+ DXG_TRACE("err: %d", ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int dxgvmb_send_create_nt_shared_object(struct dxgprocess *process,
|
|
struct d3dkmthandle object,
|
|
struct d3dkmthandle *shared_handle)
|
|
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
|
|
@@ -36,10 +36,8 @@ static char *errorstr(int ret)
|
|
}
|
|
#endif
|
|
|
|
-static int dxgsyncobj_release(struct inode *inode, struct file *file)
|
|
+void dxgsharedsyncobj_put(struct dxgsharedsyncobject *syncobj)
|
|
{
|
|
- struct dxgsharedsyncobject *syncobj = file->private_data;
|
|
-
|
|
DXG_TRACE("Release syncobj: %p", syncobj);
|
|
mutex_lock(&syncobj->fd_mutex);
|
|
kref_get(&syncobj->ssyncobj_kref);
|
|
@@ -56,6 +54,13 @@ static int dxgsyncobj_release(struct inode *inode, struct file *file)
|
|
}
|
|
mutex_unlock(&syncobj->fd_mutex);
|
|
kref_put(&syncobj->ssyncobj_kref, dxgsharedsyncobj_release);
|
|
+}
|
|
+
|
|
+static int dxgsyncobj_release(struct inode *inode, struct file *file)
|
|
+{
|
|
+ struct dxgsharedsyncobject *syncobj = file->private_data;
|
|
+
|
|
+ dxgsharedsyncobj_put(syncobj);
|
|
return 0;
|
|
}
|
|
|
|
@@ -4478,7 +4483,7 @@ dxgkio_get_device_state(struct dxgprocess *process, void *__user inargs)
|
|
return ret;
|
|
}
|
|
|
|
-static int
|
|
+int
|
|
dxgsharedsyncobj_get_host_nt_handle(struct dxgsharedsyncobject *syncobj,
|
|
struct dxgprocess *process,
|
|
struct d3dkmthandle objecthandle)
|
|
@@ -5226,6 +5231,9 @@ static struct ioctl_desc ioctls[] = {
|
|
/* 0x43 */ {dxgkio_query_statistics, LX_DXQUERYSTATISTICS},
|
|
/* 0x44 */ {dxgkio_share_object_with_host, LX_DXSHAREOBJECTWITHHOST},
|
|
/* 0x45 */ {dxgkio_create_sync_file, LX_DXCREATESYNCFILE},
|
|
+/* 0x46 */ {dxgkio_wait_sync_file, LX_DXWAITSYNCFILE},
|
|
+/* 0x46 */ {dxgkio_open_syncobj_from_syncfile,
|
|
+ LX_DXOPENSYNCOBJECTFROMSYNCFILE},
|
|
};
|
|
|
|
/*
|
|
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
|
|
@@ -1561,6 +1561,25 @@ struct d3dkmt_createsyncfile {
|
|
__u64 sync_file_handle; /* out */
|
|
};
|
|
|
|
+struct d3dkmt_waitsyncfile {
|
|
+ __u64 sync_file_handle;
|
|
+ struct d3dkmthandle context;
|
|
+ __u32 reserved;
|
|
+};
|
|
+
|
|
+struct d3dkmt_opensyncobjectfromsyncfile {
|
|
+ __u64 sync_file_handle;
|
|
+ struct d3dkmthandle device;
|
|
+ struct d3dkmthandle syncobj; /* out */
|
|
+ __u64 fence_value; /* out */
|
|
+#ifdef __KERNEL__
|
|
+ void *fence_value_cpu_va; /* out */
|
|
+#else
|
|
+ __u64 fence_value_cpu_va; /* out */
|
|
+#endif
|
|
+ __u64 fence_value_gpu_va; /* out */
|
|
+};
|
|
+
|
|
/*
|
|
* Dxgkrnl Graphics Port Driver ioctl definitions
|
|
*
|
|
@@ -1686,5 +1705,9 @@ struct d3dkmt_createsyncfile {
|
|
_IOWR(0x47, 0x44, struct d3dkmt_shareobjectwithhost)
|
|
#define LX_DXCREATESYNCFILE \
|
|
_IOWR(0x47, 0x45, struct d3dkmt_createsyncfile)
|
|
+#define LX_DXWAITSYNCFILE \
|
|
+ _IOWR(0x47, 0x46, struct d3dkmt_waitsyncfile)
|
|
+#define LX_DXOPENSYNCOBJECTFROMSYNCFILE \
|
|
+ _IOWR(0x47, 0x47, struct d3dkmt_opensyncobjectfromsyncfile)
|
|
|
|
#endif /* _D3DKMTHK_H */
|
|
--
|
|
Armbian
|
|
|