aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1161-drm-amdkfd-Make-kfd_process-reference-counted.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1161-drm-amdkfd-Make-kfd_process-reference-counted.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1161-drm-amdkfd-Make-kfd_process-reference-counted.patch160
1 files changed, 160 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1161-drm-amdkfd-Make-kfd_process-reference-counted.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1161-drm-amdkfd-Make-kfd_process-reference-counted.patch
new file mode 100644
index 00000000..51144a3a
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1161-drm-amdkfd-Make-kfd_process-reference-counted.patch
@@ -0,0 +1,160 @@
+From 3cd54dfc7075e64fd4ea5349775d90e429aa4a5b Mon Sep 17 00:00:00 2001
+From: Felix Kuehling <Felix.Kuehling@amd.com>
+Date: Mon, 25 Jul 2016 16:02:03 -0400
+Subject: [PATCH 1161/4131] drm/amdkfd: Make kfd_process reference counted
+
+This will be used to elliminate the use of the processe lock for
+preventing process destruction. This will simplify lock
+dependencies between KFD and KGD.
+
+This also simplifies the process destruction in two ways:
+* Don't allocate work struct dynamically
+* Remove unnecessary hack that increments mm reference counter
+
+Change-Id: I498e55856c5ab7dcc5a619a74a99db895fdaa7e3
+Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
+
+ Conflicts:
+ drivers/gpu/drm/amd/amdkfd/kfd_process.c
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +++
+ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 55 +++++++++++---------------------
+ 2 files changed, 23 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+index 2465685..1a9aab7 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+@@ -35,6 +35,7 @@
+ #include <linux/pid.h>
+ #include <linux/interval_tree.h>
+ #include <linux/seq_file.h>
++#include <linux/kref.h>
+ #include <kgd_kfd_interface.h>
+
+ #include "amd_rdma.h"
+@@ -608,6 +609,9 @@ struct kfd_process {
+
+ struct mm_struct *mm;
+
++ struct kref ref;
++ struct work_struct release_work;
++
+ struct rw_semaphore lock;
+
+ /*
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index b0fb998..ec066d8 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -51,11 +51,6 @@ DEFINE_STATIC_SRCU(kfd_processes_srcu);
+
+ static struct workqueue_struct *kfd_process_wq;
+
+-struct kfd_process_release_work {
+- struct work_struct kfd_work;
+- struct kfd_process *p;
+-};
+-
+ #define MIN_IDR_ID 1
+ #define MAX_IDR_ID 0 /*0 - for unlimited*/
+
+@@ -415,23 +410,18 @@ int restore(struct kfd_dev *kfd)
+ * is not findable any more. We must assume that no other thread is
+ * using it any more, otherwise we couldn't safely free the process
+ * stucture in the end. */
+-static void kfd_process_wq_release(struct work_struct *work)
++static void kfd_process_ref_release(struct kref *ref)
+ {
+- struct kfd_process_release_work *my_work;
++ struct kfd_process *p = container_of(ref, struct kfd_process, ref);
+ struct kfd_process_device *pdd, *temp, *peer_pdd;
+- struct kfd_process *p;
+ struct kfd_bo *buf_obj;
+ int id;
+
+- my_work = (struct kfd_process_release_work *) work;
+-
+- p = my_work->p;
+-
+- pr_debug("Releasing process (pasid %d) in workqueue\n",
++ pr_debug("Releasing process (pasid %d)\n",
+ p->pasid);
+
+ list_for_each_entry(pdd, &p->per_device_data, per_device_list) {
+- pr_debug("Releasing pdd (topology id %d) for process (pasid %d) in workqueue\n",
++ pr_debug("Releasing pdd (topology id %d) for process (pasid %d)\n",
+ pdd->dev->id, p->pasid);
+
+ if (pdd->dev->device_info->is_need_iommu_device) {
+@@ -477,29 +467,24 @@ static void kfd_process_wq_release(struct work_struct *work)
+ kfd_pasid_free(p->pasid);
+
+ kfree(p);
++}
++
++static void kfd_process_wq_release(struct work_struct *work)
++{
++ struct kfd_process *p = container_of(work, struct kfd_process,
++ release_work);
+
+- kfree((void *)work);
++ kref_put(&p->ref, kfd_process_ref_release);
+ }
+
+ static void kfd_process_destroy_delayed(struct rcu_head *rcu)
+ {
+- struct kfd_process_release_work *work;
+- struct kfd_process *p;
++ struct kfd_process *p = container_of(rcu, struct kfd_process, rcu);
+
+ BUG_ON(!kfd_process_wq);
+
+- p = container_of(rcu, struct kfd_process, rcu);
+- BUG_ON(atomic_read(&p->mm->mm_count) <= 0);
+-
+- mmdrop(p->mm);
+-
+- work = kmalloc(sizeof(struct kfd_process_release_work), GFP_ATOMIC);
+-
+- if (work) {
+- INIT_WORK((struct work_struct *) work, kfd_process_wq_release);
+- work->p = p;
+- queue_work(kfd_process_wq, (struct work_struct *) work);
+- }
++ INIT_WORK(&p->release_work, kfd_process_wq_release);
++ queue_work(kfd_process_wq, &p->release_work);
+ }
+
+ static void kfd_process_notifier_release(struct mmu_notifier *mn,
+@@ -564,15 +549,12 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,
+ }
+ }
+
++ /* Indicate to other users that MM is no longer valid */
++ p->mm = NULL;
++
+ up_write(&p->lock);
+
+- /*
+- * Because we drop mm_count inside kfd_process_destroy_delayed
+- * and because the mmu_notifier_unregister function also drop
+- * mm_count we need to take an extra count here.
+- */
+- mmgrab(p->mm);
+- mmu_notifier_unregister_no_release(&p->mmu_notifier, p->mm);
++ mmu_notifier_unregister_no_release(&p->mmu_notifier, mm);
+ mmu_notifier_call_srcu(&p->rcu, &kfd_process_destroy_delayed);
+ }
+
+@@ -650,6 +632,7 @@ static struct kfd_process *create_process(const struct task_struct *thread)
+ if (process->pasid == 0)
+ goto err_alloc_pasid;
+
++ kref_init(&process->ref);
+ init_rwsem(&process->lock);
+
+ process->mm = thread->mm;
+--
+2.7.4
+