aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3408-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/3408-drm-amdkfd-Make-kfd_process-reference-counted.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3408-drm-amdkfd-Make-kfd_process-reference-counted.patch164
1 files changed, 164 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3408-drm-amdkfd-Make-kfd_process-reference-counted.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3408-drm-amdkfd-Make-kfd_process-reference-counted.patch
new file mode 100644
index 00000000..290d4532
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3408-drm-amdkfd-Make-kfd_process-reference-counted.patch
@@ -0,0 +1,164 @@
+From 22bc18ee39670854f9cb922ec84664400967d0ae Mon Sep 17 00:00:00 2001
+From: Felix Kuehling <Felix.Kuehling@amd.com>
+Date: Mon, 27 Nov 2017 18:29:51 -0500
+Subject: [PATCH 3408/4131] drm/amdkfd: Make kfd_process reference counted
+
+This will be used to elliminate the use of the process lock for
+preventing concurrent process destruction. This will simplify lock
+dependencies between KFD and KGD.
+
+This also simplifies the process destruction in a few ways:
+* Don't allocate work struct dynamically
+* Remove unnecessary hack that increments mm reference counter
+* Remove unnecessary process locking during destruction
+
+Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
+Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com>
+Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +++
+ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 58 ++++++++++++--------------------
+ 2 files changed, 26 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+index dca493b..248e4f5 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+@@ -34,6 +34,7 @@
+ #include <linux/idr.h>
+ #include <linux/kfifo.h>
+ #include <linux/seq_file.h>
++#include <linux/kref.h>
+ #include <kgd_kfd_interface.h>
+
+ #include "amd_shared.h"
+@@ -537,6 +538,9 @@ struct kfd_process {
+ */
+ void *mm;
+
++ struct kref ref;
++ struct work_struct release_work;
++
+ struct mutex mutex;
+
+ /*
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index 660d8bc..e02e8a2 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -48,11 +48,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;
+-};
+-
+ static struct kfd_process *find_process(const struct task_struct *thread);
+ static struct kfd_process *create_process(const struct task_struct *thread);
+ static int kfd_process_init_cwsr(struct kfd_process *p, struct file *filep);
+@@ -151,21 +146,20 @@ static struct kfd_process *find_process(const struct task_struct *thread)
+ return p;
+ }
+
++/* No process locking is needed in this function, because the process
++ * 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
++ * structure in the end.
++ */
+ static void kfd_process_wq_release(struct work_struct *work)
+ {
+- struct kfd_process_release_work *my_work;
++ struct kfd_process *p = container_of(work, struct kfd_process,
++ release_work);
+ struct kfd_process_device *pdd, *temp;
+- struct kfd_process *p;
+-
+- my_work = (struct kfd_process_release_work *) work;
+-
+- p = my_work->p;
+
+ pr_debug("Releasing process (pasid %d) in workqueue\n",
+ p->pasid);
+
+- mutex_lock(&p->mutex);
+-
+ list_for_each_entry_safe(pdd, temp, &p->per_device_data,
+ per_device_list) {
+ pr_debug("Releasing pdd (topology id %d) for process (pasid %d) in workqueue\n",
+@@ -188,33 +182,26 @@ static void kfd_process_wq_release(struct work_struct *work)
+ kfd_pasid_free(p->pasid);
+ kfd_free_process_doorbells(p);
+
+- mutex_unlock(&p->mutex);
+-
+ mutex_destroy(&p->mutex);
+
+ put_task_struct(p->lead_thread);
+
+ kfree(p);
+-
+- kfree(work);
+ }
+
+-static void kfd_process_destroy_delayed(struct rcu_head *rcu)
++static void kfd_process_ref_release(struct kref *ref)
+ {
+- struct kfd_process_release_work *work;
+- struct kfd_process *p;
+-
+- p = container_of(rcu, struct kfd_process, rcu);
++ struct kfd_process *p = container_of(ref, struct kfd_process, ref);
+
+- mmdrop(p->mm);
++ INIT_WORK(&p->release_work, kfd_process_wq_release);
++ queue_work(kfd_process_wq, &p->release_work);
++}
+
+- work = kmalloc(sizeof(struct kfd_process_release_work), GFP_ATOMIC);
++static void kfd_process_destroy_delayed(struct rcu_head *rcu)
++{
++ struct kfd_process *p = container_of(rcu, struct kfd_process, rcu);
+
+- if (work) {
+- INIT_WORK((struct work_struct *) work, kfd_process_wq_release);
+- work->p = p;
+- queue_work(kfd_process_wq, (struct work_struct *) work);
+- }
++ kref_put(&p->ref, kfd_process_ref_release);
+ }
+
+ static void kfd_process_notifier_release(struct mmu_notifier *mn,
+@@ -258,15 +245,12 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,
+ kfd_process_dequeue_from_all_devices(p);
+ pqm_uninit(&p->pqm);
+
++ /* Indicate to other users that MM is no longer valid */
++ p->mm = NULL;
++
+ mutex_unlock(&p->mutex);
+
+- /*
+- * 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);
+ }
+
+@@ -331,6 +315,8 @@ static struct kfd_process *create_process(const struct task_struct *thread)
+ if (kfd_alloc_process_doorbells(process) < 0)
+ goto err_alloc_doorbells;
+
++ kref_init(&process->ref);
++
+ mutex_init(&process->mutex);
+
+ process->mm = thread->mm;
+--
+2.7.4
+