diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1213-drm-amdkfd-Remove-assoc_array-dependency-for-IPC.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1213-drm-amdkfd-Remove-assoc_array-dependency-for-IPC.patch | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1213-drm-amdkfd-Remove-assoc_array-dependency-for-IPC.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1213-drm-amdkfd-Remove-assoc_array-dependency-for-IPC.patch new file mode 100644 index 00000000..25bf647a --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1213-drm-amdkfd-Remove-assoc_array-dependency-for-IPC.patch @@ -0,0 +1,251 @@ +From b866b13a2bb891e9dd0943fdae48883a259066ca Mon Sep 17 00:00:00 2001 +From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com> +Date: Wed, 30 Nov 2016 17:31:04 -0500 +Subject: [PATCH 1213/4131] drm/amdkfd: Remove assoc_array dependency for IPC + +Use hash table instead. This makes IPC support compatible with older +kernels + +Change-Id: Ia099f7d99d96dd3741d1ebfa3c2c1c7498ec1a73 +Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com> +--- + drivers/gpu/drm/amd/amdkfd/kfd_ipc.c | 147 ++++++++++------------------------- + drivers/gpu/drm/amd/amdkfd/kfd_ipc.h | 5 +- + 2 files changed, 42 insertions(+), 110 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_ipc.c b/drivers/gpu/drm/amd/amdkfd/kfd_ipc.c +index 5391f8a..62aaeac 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_ipc.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_ipc.c +@@ -21,100 +21,29 @@ + */ + + #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; ++#define KFD_IPC_HASH_TABLE_SIZE_SHIFT 4 ++#define KFD_IPC_HASH_TABLE_SIZE_MASK ((1 << KFD_IPC_HASH_TABLE_SIZE_SHIFT) - 1) + +- return memcmp(obj->key, index_key, IPC_KEY_SIZE_BYTES) == 0; +-} ++static struct kfd_ipc_handles { ++ DECLARE_HASHTABLE(handles, KFD_IPC_HASH_TABLE_SIZE_SHIFT); ++ struct mutex lock; ++} kfd_ipc_handles; + +-/* +- * Compare the index keys of a pair of objects and determine the bit position +- * at which they differ - if they differ. ++/* Since, handles are random numbers, it can be used directly as hashing key. ++ * The least 4 bits of the handle are used as key. However, during import all ++ * 128 bits of the handle are checked to prevent handle snooping. + */ +-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; ++#define HANDLE_TO_KEY(sh) ((*(uint64_t *)sh) & KFD_IPC_HASH_TABLE_SIZE_MASK) + +- /* 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) ++static int ipc_store_insert(void *val, void *sh, 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) +@@ -129,16 +58,14 @@ static int ipc_store_insert(void *val, void *key, struct kfd_ipc_obj **ipc_obj) + */ + kref_init(&obj->ref); + obj->data = val; +- ipc_gen_key(obj->key); ++ get_random_bytes(obj->share_handle, sizeof(obj->share_handle)); + +- memcpy(key, obj->key, IPC_KEY_SIZE_BYTES); ++ memcpy(sh, obj->share_handle, sizeof(obj->share_handle)); + +- 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); ++ mutex_lock(&kfd_ipc_handles.lock); ++ hlist_add_head(&obj->node, ++ &kfd_ipc_handles.handles[HANDLE_TO_KEY(obj->share_handle)]); ++ mutex_unlock(&kfd_ipc_handles.lock); + + if (ipc_obj) + *ipc_obj = obj; +@@ -146,22 +73,16 @@ static int ipc_store_insert(void *val, void *key, struct kfd_ipc_obj **ipc_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); ++ mutex_lock(&kfd_ipc_handles.lock); ++ hash_del(&obj->node); ++ mutex_unlock(&kfd_ipc_handles.lock); ++ + dma_buf_put(obj->data); + kfree(obj); + } +@@ -179,7 +100,8 @@ void ipc_obj_put(struct kfd_ipc_obj **obj) + + int kfd_ipc_init(void) + { +- assoc_array_init(&ipc_handles); ++ mutex_init(&kfd_ipc_handles.lock); ++ hash_init(kfd_ipc_handles.handles); + return 0; + } + +@@ -262,11 +184,22 @@ int kfd_ipc_import_handle(struct kfd_dev *dev, struct kfd_process *p, + uint64_t *mmap_offset) + { + int r; +- struct kfd_ipc_obj *found; ++ struct kfd_ipc_obj *entry, *found = NULL; ++ ++ mutex_lock(&kfd_ipc_handles.lock); ++ /* Convert the user provided handle to hash key and search only in that ++ * bucket ++ */ ++ hlist_for_each_entry(entry, ++ &kfd_ipc_handles.handles[HANDLE_TO_KEY(share_handle)], node) { ++ if (!memcmp(entry->share_handle, share_handle, ++ sizeof(entry->share_handle))) { ++ found = entry; ++ break; ++ } ++ } ++ mutex_unlock(&kfd_ipc_handles.lock); + +- found = assoc_array_find(&ipc_handles, +- &ipc_assoc_array_ops, +- share_handle); + if (!found) + return -EINVAL; + ipc_obj_get(found); +@@ -316,8 +249,8 @@ int kfd_ipc_export_as_handle(struct kfd_dev *dev, struct kfd_process *p, + return -EINVAL; + } + if (kfd_bo->kfd_ipc_obj) { +- memcpy(ipc_handle, kfd_bo->kfd_ipc_obj->key, +- sizeof(kfd_bo->kfd_ipc_obj->key)); ++ memcpy(ipc_handle, kfd_bo->kfd_ipc_obj->share_handle, ++ sizeof(kfd_bo->kfd_ipc_obj->share_handle)); + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_ipc.h b/drivers/gpu/drm/amd/amdkfd/kfd_ipc.h +index 52049d2..9ee8627 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_ipc.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_ipc.h +@@ -27,12 +27,11 @@ + #include <linux/types.h> + #include "kfd_priv.h" + +-#define IPC_KEY_SIZE_BYTES 16 +- + struct kfd_ipc_obj { ++ struct hlist_node node; + struct kref ref; + void *data; +- char key[IPC_KEY_SIZE_BYTES]; ++ uint32_t share_handle[4]; + }; + + int kfd_ipc_import_handle(struct kfd_dev *dev, struct kfd_process *p, +-- +2.7.4 + |