aboutsummaryrefslogtreecommitdiffstats
path: root/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1561-drm-amdkfd-initial-implementation-of-handle-based-IP.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1561-drm-amdkfd-initial-implementation-of-handle-based-IP.patch')
-rw-r--r--meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1561-drm-amdkfd-initial-implementation-of-handle-based-IP.patch690
1 files changed, 0 insertions, 690 deletions
diff --git a/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1561-drm-amdkfd-initial-implementation-of-handle-based-IP.patch b/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1561-drm-amdkfd-initial-implementation-of-handle-based-IP.patch
deleted file mode 100644
index ca0a437f..00000000
--- a/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1561-drm-amdkfd-initial-implementation-of-handle-based-IP.patch
+++ /dev/null
@@ -1,690 +0,0 @@
-From 67115bb6b36683f65f4baf1c3e4c47b6799bd663 Mon Sep 17 00:00:00 2001
-From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
-Date: Sun, 20 Nov 2016 10:14:05 -0500
-Subject: [PATCH 1561/4131] drm/amdkfd: initial implementation of handle based
- IPC
-
-To implement IPC support for legacy compute APIs, we need a handle based
-sharing interface. The interfaces are incompatible with DMABUF, which
-would be preferable for enhanced security (explicit sharing, and no
-extra code for handle management that increases the attack vectors).
-
-The handles are 128bit wide to prevent inter-process snooping.
-
-The buffer lifetime is refcounted. As long as one process maintains a
-reference to the buffer, the handle and the memory will be valid.
-
-Change-Id: I9f9b8e149eb1c540f6b1ef6429e56bf9533f0a9a
-Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
----
- drivers/gpu/drm/amd/amdkfd/Makefile | 2 +-
- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 87 +++++---
- drivers/gpu/drm/amd/amdkfd/kfd_ipc.c | 331 +++++++++++++++++++++++++++++++
- drivers/gpu/drm/amd/amdkfd/kfd_ipc.h | 52 +++++
- drivers/gpu/drm/amd/amdkfd/kfd_module.c | 4 +
- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 9 +-
- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 10 +-
- 7 files changed, 459 insertions(+), 36 deletions(-)
- create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_ipc.c
- create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_ipc.h
-
-diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile
-index 8f3cbf6..84646ed 100644
---- a/drivers/gpu/drm/amd/amdkfd/Makefile
-+++ b/drivers/gpu/drm/amd/amdkfd/Makefile
-@@ -17,7 +17,7 @@ amdkfd-y := kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \
- kfd_device_queue_manager_cik.o kfd_device_queue_manager_vi.o \
- kfd_interrupt.o kfd_events.o cik_event_interrupt.o \
- kfd_dbgdev.o kfd_dbgmgr.o kfd_flat_memory.o kfd_crat.o kfd_rdma.o \
-- kfd_peerdirect.o
-+ kfd_peerdirect.o kfd_ipc.o
-
- amdkfd-$(CONFIG_DEBUG_FS) += kfd_debugfs.o
-
-diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
-index f28b1c3..e664471 100644
---- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
-+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
-@@ -37,6 +37,7 @@
- #include "kfd_priv.h"
- #include "kfd_device_queue_manager.h"
- #include "kfd_dbgmgr.h"
-+#include "kfd_ipc.h"
- #include "cik_regs.h"
-
- static long kfd_ioctl(struct file *, unsigned int, unsigned long);
-@@ -1179,7 +1180,7 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
-
- down_write(&p->lock);
- idr_handle = kfd_process_device_create_obj_handle(pdd, mem,
-- args->va_addr, args->size);
-+ args->va_addr, args->size, NULL);
- up_write(&p->lock);
- if (idr_handle < 0) {
- dev->kfd2kgd->free_memory_of_gpu(dev->kgd,
-@@ -1320,7 +1321,7 @@ static int kfd_ioctl_alloc_memory_of_gpu_new(struct file *filep,
-
- down_write(&p->lock);
- idr_handle = kfd_process_device_create_obj_handle(pdd, mem,
-- args->va_addr, args->size);
-+ args->va_addr, args->size, NULL);
- up_write(&p->lock);
- if (idr_handle < 0) {
- dev->kfd2kgd->free_memory_of_gpu(dev->kgd,
-@@ -1671,7 +1672,7 @@ static int kfd_ioctl_open_graphic_handle(struct file *filep,
- * the corresponding interval tree. We need to know the size of
- * the buffer through open_graphic_handle(). We use 1 for now.*/
- idr_handle = kfd_process_device_create_obj_handle(pdd, mem,
-- args->va_addr, 1);
-+ args->va_addr, 1, NULL);
- up_write(&p->lock);
- if (idr_handle < 0) {
- /* FIXME: destroy_process_gpumem doesn't seem to be
-@@ -1776,47 +1777,62 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
- }
-
- static int kfd_ioctl_import_dmabuf(struct file *filep,
-- struct kfd_process *p, void *data)
-+ struct kfd_process *p, void *data)
- {
- struct kfd_ioctl_import_dmabuf_args *args = data;
- struct kfd_dev *dev;
-- struct kfd_process_device *pdd;
-- void *mem;
-- uint64_t size;
-- int idr_handle;
- int r;
-
- dev = kfd_device_by_id(args->gpu_id);
-- if (!dev || !dev->kfd2kgd->import_dmabuf)
-+ if (!dev)
- return -EINVAL;
-
-- down_write(&p->lock);
-- pdd = kfd_bind_process_to_device(dev, p);
-- up_write(&p->lock);
-- if (IS_ERR(pdd) < 0)
-- return PTR_ERR(pdd);
-+ r = kfd_ipc_import_dmabuf(dev, p, args->gpu_id, args->dmabuf_fd,
-+ args->va_addr, &args->handle, NULL);
-+ if (r)
-+ dev_err(kfd_device, "Failed to import dmabuf\n");
-+
-+ return r;
-+}
-+
-+static int kfd_ioctl_ipc_export_handle(struct file *filep,
-+ struct kfd_process *p,
-+ void *data)
-+{
-+ struct kfd_ioctl_ipc_export_handle_args *args = data;
-+ struct kfd_dev *dev;
-+ int r;
-
-- r = dev->kfd2kgd->import_dmabuf(dev->kgd, args->dmabuf_fd,
-- args->va_addr, pdd->vm,
-- (struct kgd_mem **)&mem, &size,
-- NULL);
-+ dev = kfd_device_by_id(args->gpu_id);
-+ if (!dev)
-+ return -EINVAL;
-+
-+ r = kfd_ipc_export_as_handle(dev, p, args->handle, args->share_handle);
- if (r)
-- return r;
-+ dev_err(kfd_device, "Failed to export IPC handle\n");
-
-- down_write(&p->lock);
-- idr_handle = kfd_process_device_create_obj_handle(pdd, mem,
-- args->va_addr, size);
-- up_write(&p->lock);
-- if (idr_handle < 0) {
-- dev->kfd2kgd->free_memory_of_gpu(dev->kgd,
-- (struct kgd_mem *)mem,
-- pdd->vm);
-- return -EFAULT;
-- }
-+ return r;
-+}
-
-- args->handle = MAKE_HANDLE(args->gpu_id, idr_handle);
-+static int kfd_ioctl_ipc_import_handle(struct file *filep,
-+ struct kfd_process *p,
-+ void *data)
-+{
-+ struct kfd_ioctl_ipc_import_handle_args *args = data;
-+ struct kfd_dev *dev = NULL;
-+ int r;
-
-- return 0;
-+ dev = kfd_device_by_id(args->gpu_id);
-+ if (!dev)
-+ return -EINVAL;
-+
-+ r = kfd_ipc_import_handle(dev, p, args->gpu_id, args->share_handle,
-+ args->va_addr, &args->handle,
-+ &args->mmap_offset);
-+ if (r)
-+ dev_err(kfd_device, "Failed to import IPC handle\n");
-+
-+ return r;
- }
-
- static int kfd_ioctl_get_tile_config(struct file *filep,
-@@ -1958,7 +1974,14 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
- kfd_ioctl_import_dmabuf, 0),
-
- AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_TILE_CONFIG,
-- kfd_ioctl_get_tile_config, 0)
-+ kfd_ioctl_get_tile_config, 0),
-+
-+ AMDKFD_IOCTL_DEF(AMDKFD_IOC_IPC_IMPORT_HANDLE,
-+ kfd_ioctl_ipc_import_handle, 0),
-+
-+ AMDKFD_IOCTL_DEF(AMDKFD_IOC_IPC_EXPORT_HANDLE,
-+ kfd_ioctl_ipc_export_handle, 0)
-+
- };
-
- #define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls)
-diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_ipc.c b/drivers/gpu/drm/amd/amdkfd/kfd_ipc.c
-new file mode 100644
-index 0000000..edd2d43
---- /dev/null
-+++ b/drivers/gpu/drm/amd/amdkfd/kfd_ipc.c
-@@ -0,0 +1,331 @@
-+/*
-+ * Copyright 2014 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ */
-+
-+#include <linux/dma-buf.h>
-+#include <linux/assoc_array.h>
-+#include <linux/slab.h>
-+#include <linux/random.h>
-+
-+#include "kfd_ipc.h"
-+#include "kfd_priv.h"
-+
-+/**
-+ * The assoc_array data structure provides a non-intrusive
-+ * key-value data store mechanism where the key can be
-+ * arbitratily long (and value is just a void*).
-+ *
-+ * This provides us good control for managing IPC handle length
-+ * in case we require extra entropy to discourage handle-guessing.
-+ */
-+static struct assoc_array ipc_handles;
-+
-+static unsigned long ipc_get_key_chunk(const void *index_key, int level)
-+{
-+ unsigned long chunk;
-+ int index = level/ASSOC_ARRAY_KEY_CHUNK_SIZE;
-+
-+ /* no more data, but we can't fail */
-+ if (level > IPC_KEY_SIZE_BYTES*8)
-+ return 0;
-+
-+ chunk = ((unsigned long *)index_key)[index];
-+ return chunk;
-+}
-+
-+static unsigned long ipc_get_object_key_chunk(const void *object, int level)
-+{
-+ const struct kfd_ipc_obj *obj = (const struct kfd_ipc_obj *)object;
-+
-+ return ipc_get_key_chunk(&obj->key, level);
-+}
-+
-+static bool ipc_compare_object(const void *object, const void *index_key)
-+{
-+ const struct kfd_ipc_obj *obj = (const struct kfd_ipc_obj *)object;
-+
-+ return memcmp(obj->key, index_key, IPC_KEY_SIZE_BYTES) == 0;
-+}
-+
-+/*
-+ * Compare the index keys of a pair of objects and determine the bit position
-+ * at which they differ - if they differ.
-+ */
-+static int ipc_diff_objects(const void *object, const void *index_key)
-+{
-+ const struct kfd_ipc_obj *obj = (const struct kfd_ipc_obj *)object;
-+ int i;
-+
-+ /* naive linear byte search */
-+ for (i = 0; i < IPC_KEY_SIZE_BYTES; ++i) {
-+ if (obj->key[i] != ((char *)index_key)[i])
-+ return i * 8;
-+ }
-+
-+ return -1;
-+}
-+
-+/*
-+ * Free an object after stripping the ipc flag off of the pointer.
-+ */
-+static void ipc_free_object(void *object)
-+{
-+}
-+
-+/*
-+ * Operations for ipc management by the index-tree routines.
-+ */
-+static const struct assoc_array_ops ipc_assoc_array_ops = {
-+ .get_key_chunk = ipc_get_key_chunk,
-+ .get_object_key_chunk = ipc_get_object_key_chunk,
-+ .compare_object = ipc_compare_object,
-+ .diff_objects = ipc_diff_objects,
-+ .free_object = ipc_free_object,
-+};
-+
-+static void ipc_gen_key(void *buf)
-+{
-+ uint32_t *key = (uint32_t *) buf;
-+
-+ get_random_bytes(buf, IPC_KEY_SIZE_BYTES);
-+
-+ /* last byte of the key is reserved */
-+ key[3] = (key[3] & ~0xFF) | 0x1;
-+}
-+
-+static int ipc_store_insert(void *val, void *key, struct kfd_ipc_obj **ipc_obj)
-+{
-+ struct kfd_ipc_obj *obj;
-+ struct assoc_array_edit *edit;
-+
-+ obj = kmalloc(sizeof(struct kfd_ipc_obj), GFP_KERNEL);
-+ if (!obj)
-+ return -ENOMEM;
-+
-+ /* The initial ref belongs to the allocator process.
-+ * The IPC object store itself does not hold a ref since
-+ * there is no specific moment in time where that ref should
-+ * be dropped, except "when there are no more userspace processes
-+ * holding a ref to the object". Therefore the removal from IPC
-+ * storage happens at ipc_obj release time.
-+ */
-+ kref_init(&obj->ref);
-+ obj->data = val;
-+ ipc_gen_key(obj->key);
-+
-+ memcpy(key, obj->key, IPC_KEY_SIZE_BYTES);
-+
-+ pr_debug("ipc: val::%p ref:%p\n", val, &obj->ref);
-+
-+ edit = assoc_array_insert(&ipc_handles,
-+ &ipc_assoc_array_ops,
-+ obj->key, obj);
-+ assoc_array_apply_edit(edit);
-+
-+ if (ipc_obj)
-+ *ipc_obj = obj;
-+
-+ return 0;
-+}
-+
-+static int ipc_store_remove(void *key)
-+{
-+ struct assoc_array_edit *edit;
-+
-+ edit = assoc_array_delete(&ipc_handles, &ipc_assoc_array_ops, key);
-+ assoc_array_apply_edit(edit);
-+ return 0;
-+}
-+
-+static void ipc_obj_release(struct kref *r)
-+{
-+ struct kfd_ipc_obj *obj;
-+
-+ obj = container_of(r, struct kfd_ipc_obj, ref);
-+
-+ ipc_store_remove(obj->key);
-+ dma_buf_put(obj->data);
-+ kfree(obj);
-+}
-+
-+void ipc_obj_get(struct kfd_ipc_obj *obj)
-+{
-+ kref_get(&obj->ref);
-+}
-+
-+void ipc_obj_put(struct kfd_ipc_obj **obj)
-+{
-+ kref_put(&(*obj)->ref, ipc_obj_release);
-+ *obj = NULL;
-+}
-+
-+int kfd_ipc_init(void)
-+{
-+ assoc_array_init(&ipc_handles);
-+ return 0;
-+}
-+
-+static int kfd_import_dmabuf_create_kfd_bo(struct kfd_dev *dev,
-+ struct kfd_process *p,
-+ uint32_t gpu_id, int dmabuf_fd,
-+ uint64_t va_addr, uint64_t *handle,
-+ uint64_t *mmap_offset,
-+ struct kfd_ipc_obj *ipc_obj)
-+{
-+ int r;
-+ void *mem;
-+ uint64_t size;
-+ int idr_handle;
-+ struct kfd_process_device *pdd = NULL;
-+ uint64_t kfd_mmap_flags = KFD_MMAP_TYPE_MAP_BO |
-+ KFD_MMAP_GPU_ID(gpu_id);
-+
-+ if (!handle)
-+ return -EINVAL;
-+
-+ if (!dev || !dev->kfd2kgd->import_dmabuf)
-+ return -EINVAL;
-+
-+ down_write(&p->lock);
-+ pdd = kfd_bind_process_to_device(dev, p);
-+ up_write(&p->lock);
-+ if (IS_ERR(pdd) < 0)
-+ return PTR_ERR(pdd);
-+
-+ r = dev->kfd2kgd->import_dmabuf(dev->kgd, dmabuf_fd,
-+ va_addr, pdd->vm,
-+ (struct kgd_mem **)&mem, &size,
-+ mmap_offset);
-+ if (r)
-+ return r;
-+
-+ down_write(&p->lock);
-+ idr_handle = kfd_process_device_create_obj_handle(pdd, mem,
-+ va_addr, size,
-+ ipc_obj);
-+ up_write(&p->lock);
-+ if (idr_handle < 0) {
-+ dev->kfd2kgd->free_memory_of_gpu(dev->kgd,
-+ (struct kgd_mem *)mem,
-+ pdd->vm);
-+ return -EFAULT;
-+ }
-+
-+ *handle = MAKE_HANDLE(gpu_id, idr_handle);
-+
-+ if (mmap_offset)
-+ *mmap_offset = (kfd_mmap_flags << PAGE_SHIFT) | *mmap_offset;
-+
-+ return r;
-+}
-+
-+int kfd_ipc_import_dmabuf(struct kfd_dev *dev,
-+ struct kfd_process *p,
-+ uint32_t gpu_id, int dmabuf_fd,
-+ uint64_t va_addr, uint64_t *handle,
-+ uint64_t *mmap_offset)
-+{
-+ return kfd_import_dmabuf_create_kfd_bo(dev, p, gpu_id, dmabuf_fd,
-+ va_addr, handle, mmap_offset,
-+ NULL);
-+}
-+
-+int kfd_ipc_import_handle(struct kfd_dev *dev, struct kfd_process *p,
-+ uint32_t gpu_id, uint32_t *share_handle,
-+ uint64_t va_addr, uint64_t *handle,
-+ uint64_t *mmap_offset)
-+{
-+ int r;
-+ int dmabuf_fd;
-+ struct kfd_ipc_obj *found;
-+
-+ found = assoc_array_find(&ipc_handles,
-+ &ipc_assoc_array_ops,
-+ share_handle);
-+ if (!found)
-+ return -EINVAL;
-+ ipc_obj_get(found);
-+
-+ pr_debug("ipc: found ipc_dma_buf: %p\n", found->data);
-+
-+ dmabuf_fd = dma_buf_fd(found->data, 0);
-+ r = kfd_import_dmabuf_create_kfd_bo(dev, p, gpu_id, dmabuf_fd,
-+ va_addr, handle, mmap_offset,
-+ found);
-+ if (r)
-+ goto error_unref;
-+
-+ return r;
-+
-+error_unref:
-+ ipc_obj_put(&found);
-+ return r;
-+}
-+
-+int kfd_ipc_export_as_handle(struct kfd_dev *dev, struct kfd_process *p,
-+ uint64_t handle, uint32_t *ipc_handle)
-+{
-+ struct kfd_process_device *pdd = NULL;
-+ struct kfd_ipc_obj *obj;
-+ struct kfd_bo *kfd_bo = NULL;
-+ int dmabuf_fd;
-+ int r;
-+
-+ if (!dev || !ipc_handle)
-+ return -EINVAL;
-+
-+ down_write(&p->lock);
-+ pdd = kfd_bind_process_to_device(dev, p);
-+ up_write(&p->lock);
-+
-+ if (IS_ERR(pdd) < 0) {
-+ pr_err("failed to get pdd\n");
-+ return PTR_ERR(pdd);
-+ }
-+
-+ down_write(&p->lock);
-+ kfd_bo = kfd_process_device_find_bo(pdd, GET_IDR_HANDLE(handle));
-+ up_write(&p->lock);
-+
-+ if (!kfd_bo) {
-+ pr_err("failed to get bo");
-+ return -EINVAL;
-+ }
-+ if (kfd_bo->kfd_ipc_obj) {
-+ memcpy(ipc_handle, kfd_bo->kfd_ipc_obj->key,
-+ sizeof(kfd_bo->kfd_ipc_obj->key));
-+ return 0;
-+ }
-+
-+ r = dev->kfd2kgd->export_dmabuf(dev->kgd, pdd->vm,
-+ (struct kgd_mem *)kfd_bo->mem,
-+ &dmabuf_fd);
-+ if (r)
-+ goto err;
-+
-+ r = ipc_store_insert(dma_buf_get(dmabuf_fd), ipc_handle, &obj);
-+ if (r)
-+ goto err;
-+
-+ kfd_bo->kfd_ipc_obj = obj;
-+err:
-+ return r;
-+}
-diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_ipc.h b/drivers/gpu/drm/amd/amdkfd/kfd_ipc.h
-new file mode 100644
-index 0000000..52049d2
---- /dev/null
-+++ b/drivers/gpu/drm/amd/amdkfd/kfd_ipc.h
-@@ -0,0 +1,52 @@
-+/*
-+ * Copyright 2014 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ */
-+
-+#ifndef KFD_IPC_H_
-+#define KFD_IPC_H_
-+
-+#include <linux/types.h>
-+#include "kfd_priv.h"
-+
-+#define IPC_KEY_SIZE_BYTES 16
-+
-+struct kfd_ipc_obj {
-+ struct kref ref;
-+ void *data;
-+ char key[IPC_KEY_SIZE_BYTES];
-+};
-+
-+int kfd_ipc_import_handle(struct kfd_dev *dev, struct kfd_process *p,
-+ uint32_t gpu_id, uint32_t *share_handle,
-+ uint64_t va_addr, uint64_t *handle,
-+ uint64_t *mmap_offset);
-+int kfd_ipc_import_dmabuf(struct kfd_dev *kfd, struct kfd_process *p,
-+ uint32_t gpu_id, int dmabuf_fd,
-+ uint64_t va_addr, uint64_t *handle,
-+ uint64_t *mmap_offset);
-+int kfd_ipc_export_as_handle(struct kfd_dev *dev, struct kfd_process *p,
-+ uint64_t handle, uint32_t *ipc_handle);
-+
-+void ipc_obj_get(struct kfd_ipc_obj *obj);
-+void ipc_obj_put(struct kfd_ipc_obj **obj);
-+
-+#endif /* KFD_IPC_H_ */
-diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c
-index ca82a02..274312f 100644
---- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c
-+++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c
-@@ -133,6 +133,10 @@ static int __init kfd_module_init(void)
- if (err < 0)
- goto err_topology;
-
-+ err = kfd_ipc_init();
-+ if (err < 0)
-+ goto err_topology;
-+
- kfd_process_create_wq();
-
- kfd_init_peer_direct();
-diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
-index d96d256..40dd5db 100644
---- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
-+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
-@@ -280,11 +280,14 @@ struct kfd_dev {
- uint32_t ib_size;
- };
-
-+struct kfd_ipc_obj;
-+
- struct kfd_bo {
- void *mem;
- struct interval_tree_node it;
- struct kfd_dev *dev;
- struct list_head cb_data_head;
-+ struct kfd_ipc_obj *kfd_ipc_obj;
- };
-
- /* KGD2KFD callbacks */
-@@ -729,7 +732,8 @@ int kfd_reserved_mem_mmap(struct kfd_process *process, struct vm_area_struct *vm
- /* KFD process API for creating and translating handles */
- int kfd_process_device_create_obj_handle(struct kfd_process_device *pdd,
- void *mem, uint64_t start,
-- uint64_t length);
-+ uint64_t length,
-+ struct kfd_ipc_obj *ipc_obj);
- void *kfd_process_device_translate_handle(struct kfd_process_device *p,
- int handle);
- struct kfd_bo *kfd_process_device_find_bo(struct kfd_process_device *pdd,
-@@ -964,6 +968,9 @@ int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p);
- void kfd_init_peer_direct(void);
- void kfd_close_peer_direct(void);
-
-+/* IPC Support */
-+int kfd_ipc_init(void);
-+
- /* Debugfs */
- #if defined(CONFIG_DEBUG_FS)
-
-diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
-index fa13696..63e85de 100644
---- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
-+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
-@@ -32,6 +32,7 @@
- #include <asm/tlb.h>
- #include <linux/highmem.h>
- #include <uapi/asm-generic/mman-common.h>
-+#include "kfd_ipc.h"
-
- struct mm_struct;
-
-@@ -118,7 +119,7 @@ static int kfd_process_alloc_gpuvm(struct kfd_process *p,
- * created and the ioctls have not had the chance to run.
- */
- if (kfd_process_device_create_obj_handle(
-- pdd, mem, gpu_va, size) < 0) {
-+ pdd, mem, gpu_va, size, NULL) < 0) {
- err = -ENOMEM;
- *kptr = NULL;
- goto free_gpuvm;
-@@ -803,7 +804,8 @@ bool kfd_has_process_device_data(struct kfd_process *p)
- * Assumes that the process lock is held. */
- int kfd_process_device_create_obj_handle(struct kfd_process_device *pdd,
- void *mem, uint64_t start,
-- uint64_t length)
-+ uint64_t length,
-+ struct kfd_ipc_obj *ipc_obj)
- {
- int handle;
- struct kfd_bo *buf_obj;
-@@ -825,6 +827,7 @@ int kfd_process_device_create_obj_handle(struct kfd_process_device *pdd,
-
- buf_obj->mem = mem;
- buf_obj->dev = pdd->dev;
-+ buf_obj->kfd_ipc_obj = ipc_obj;
-
- INIT_LIST_HEAD(&buf_obj->cb_data_head);
-
-@@ -904,6 +907,9 @@ void kfd_process_device_remove_obj_handle(struct kfd_process_device *pdd,
-
- buf_obj = kfd_process_device_find_bo(pdd, handle);
-
-+ if (buf_obj->kfd_ipc_obj)
-+ ipc_obj_put(&buf_obj->kfd_ipc_obj);
-+
- idr_remove(&pdd->alloc_idr, handle);
-
- interval_tree_remove(&buf_obj->it, &p->bo_interval_tree);
---
-2.7.4
-