aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3409-drm-amdkfd-Use-ref-count-to-prevent-kfd_process-dest.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3409-drm-amdkfd-Use-ref-count-to-prevent-kfd_process-dest.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3409-drm-amdkfd-Use-ref-count-to-prevent-kfd_process-dest.patch178
1 files changed, 178 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3409-drm-amdkfd-Use-ref-count-to-prevent-kfd_process-dest.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3409-drm-amdkfd-Use-ref-count-to-prevent-kfd_process-dest.patch
new file mode 100644
index 00000000..7ca51434
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3409-drm-amdkfd-Use-ref-count-to-prevent-kfd_process-dest.patch
@@ -0,0 +1,178 @@
+From 585ef4980c6d475c9c15d6e763e4cac155f0394b Mon Sep 17 00:00:00 2001
+From: Felix Kuehling <Felix.Kuehling@amd.com>
+Date: Mon, 27 Nov 2017 18:29:52 -0500
+Subject: [PATCH 3409/4131] drm/amdkfd: Use ref count to prevent kfd_process
+ destruction
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Use a reference counter instead of a lock to prevent process
+destruction while functions running out of process context are using
+the kfd_process structure. In many cases these functions don't need
+the structure to be locked. In the few cases that really do need the
+process lock, take it explicitly.
+
+This helps simplify lock dependencies between the process lock and
+other locks, particularly amdgpu and mm_struct locks. This will be
+important when amdgpu calls back to amdkfd for memory evictions.
+
+Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
+Acked-by: Christian König <christian.koenig@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_events.c | 14 +++++++-------
+ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 +
+ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 16 +++++++++++++---
+ 3 files changed, 21 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+index cb92d4b..93aae5c 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+@@ -441,7 +441,7 @@ void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id,
+ /*
+ * Because we are called from arbitrary context (workqueue) as opposed
+ * to process context, kfd_process could attempt to exit while we are
+- * running so the lookup function returns a locked process.
++ * running so the lookup function increments the process ref count.
+ */
+ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
+
+@@ -493,7 +493,7 @@ void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id,
+ }
+
+ mutex_unlock(&p->event_mutex);
+- mutex_unlock(&p->mutex);
++ kfd_unref_process(p);
+ }
+
+ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events)
+@@ -847,7 +847,7 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
+ /*
+ * Because we are called from arbitrary context (workqueue) as opposed
+ * to process context, kfd_process could attempt to exit while we are
+- * running so the lookup function returns a locked process.
++ * running so the lookup function increments the process ref count.
+ */
+ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
+ struct mm_struct *mm;
+@@ -860,7 +860,7 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
+ */
+ mm = get_task_mm(p->lead_thread);
+ if (!mm) {
+- mutex_unlock(&p->mutex);
++ kfd_unref_process(p);
+ return; /* Process is exiting */
+ }
+
+@@ -903,7 +903,7 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
+ &memory_exception_data);
+
+ mutex_unlock(&p->event_mutex);
+- mutex_unlock(&p->mutex);
++ kfd_unref_process(p);
+ }
+
+ void kfd_signal_hw_exception_event(unsigned int pasid)
+@@ -911,7 +911,7 @@ void kfd_signal_hw_exception_event(unsigned int pasid)
+ /*
+ * Because we are called from arbitrary context (workqueue) as opposed
+ * to process context, kfd_process could attempt to exit while we are
+- * running so the lookup function returns a locked process.
++ * running so the lookup function increments the process ref count.
+ */
+ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
+
+@@ -924,5 +924,5 @@ void kfd_signal_hw_exception_event(unsigned int pasid)
+ lookup_events_by_type_and_signal(p, KFD_EVENT_TYPE_HW_EXCEPTION, NULL);
+
+ mutex_unlock(&p->event_mutex);
+- mutex_unlock(&p->mutex);
++ kfd_unref_process(p);
+ }
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+index 248e4f5..0c96a6b 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+@@ -606,6 +606,7 @@ void kfd_process_destroy_wq(void);
+ struct kfd_process *kfd_create_process(struct file *filep);
+ struct kfd_process *kfd_get_process(const struct task_struct *);
+ struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid);
++void kfd_unref_process(struct kfd_process *p);
+
+ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev,
+ struct kfd_process *p);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index e02e8a2..509f987 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -49,6 +49,7 @@ DEFINE_STATIC_SRCU(kfd_processes_srcu);
+ static struct workqueue_struct *kfd_process_wq;
+
+ static struct kfd_process *find_process(const struct task_struct *thread);
++static void kfd_process_ref_release(struct kref *ref);
+ static struct kfd_process *create_process(const struct task_struct *thread);
+ static int kfd_process_init_cwsr(struct kfd_process *p, struct file *filep);
+
+@@ -146,6 +147,11 @@ static struct kfd_process *find_process(const struct task_struct *thread)
+ return p;
+ }
+
++void kfd_unref_process(struct kfd_process *p)
++{
++ kref_put(&p->ref, kfd_process_ref_release);
++}
++
+ /* 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
+@@ -201,7 +207,7 @@ static void kfd_process_destroy_delayed(struct rcu_head *rcu)
+ {
+ struct kfd_process *p = container_of(rcu, struct kfd_process, rcu);
+
+- kref_put(&p->ref, kfd_process_ref_release);
++ kfd_unref_process(p);
+ }
+
+ static void kfd_process_notifier_release(struct mmu_notifier *mn,
+@@ -525,6 +531,8 @@ void kfd_process_iommu_unbind_callback(struct kfd_dev *dev, unsigned int pasid)
+
+ mutex_unlock(kfd_get_dbgmgr_mutex());
+
++ mutex_lock(&p->mutex);
++
+ pdd = kfd_get_process_device_data(dev, p);
+ if (pdd)
+ /* For GPU relying on IOMMU, we need to dequeue here
+@@ -533,6 +541,8 @@ void kfd_process_iommu_unbind_callback(struct kfd_dev *dev, unsigned int pasid)
+ kfd_process_dequeue_from_device(pdd);
+
+ mutex_unlock(&p->mutex);
++
++ kfd_unref_process(p);
+ }
+
+ struct kfd_process_device *kfd_get_first_process_device_data(
+@@ -557,7 +567,7 @@ bool kfd_has_process_device_data(struct kfd_process *p)
+ return !(list_empty(&p->per_device_data));
+ }
+
+-/* This returns with process->mutex locked. */
++/* This increments the process->ref counter. */
+ struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid)
+ {
+ struct kfd_process *p;
+@@ -567,7 +577,7 @@ struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid)
+
+ hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) {
+ if (p->pasid == pasid) {
+- mutex_lock(&p->mutex);
++ kref_get(&p->ref);
+ break;
+ }
+ }
+--
+2.7.4
+