aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2110-drm-amdkfd-Clean-up-kfd_wait_on_events.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2110-drm-amdkfd-Clean-up-kfd_wait_on_events.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2110-drm-amdkfd-Clean-up-kfd_wait_on_events.patch235
1 files changed, 235 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2110-drm-amdkfd-Clean-up-kfd_wait_on_events.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2110-drm-amdkfd-Clean-up-kfd_wait_on_events.patch
new file mode 100644
index 00000000..9a5e7c27
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2110-drm-amdkfd-Clean-up-kfd_wait_on_events.patch
@@ -0,0 +1,235 @@
+From 9247322ebaf48ca207d33c4dcb65b775a864fd29 Mon Sep 17 00:00:00 2001
+From: Felix Kuehling <Felix.Kuehling@amd.com>
+Date: Thu, 28 Sep 2017 15:01:32 -0400
+Subject: [PATCH 2110/4131] drm/amdkfd: Clean up kfd_wait_on_events
+
+Cleaned up the code while resolving some potential bugs and
+inconsistencies in the process.
+
+Clean-ups:
+* Remove enum kfd_event_wait_result, which duplicates
+ KFD_IOC_EVENT_RESULT definitions
+* alloc_event_waiters can be called without holding p->event_mutex
+* Return an error code from copy_signaled_event_data instead of bool
+* Clean up error handling code paths to minimize duplication in
+ kfd_wait_on_events
+
+Fixes:
+* Consistently return an error code from kfd_wait_on_events and set
+ wait_result to KFD_IOC_WAIT_RESULT_FAIL in all failure cases.
+* Always call free_waiters while holding p->event_mutex
+* copy_signaled_event_data might sleep. Don't call it while the task state
+ is TASK_INTERRUPTIBLE.
+
+Change-Id: I6f1e979c0c59478e499f974a4aa906f4d05366f3
+Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 5 +--
+ drivers/gpu/drm/amd/amdkfd/kfd_events.c | 71 ++++++++++++++------------------
+ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 8 +---
+ 3 files changed, 32 insertions(+), 52 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+index 3a3de01..c7cae86 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+@@ -1075,15 +1075,12 @@ static int kfd_ioctl_wait_events(struct file *filp, struct kfd_process *p,
+ void *data)
+ {
+ struct kfd_ioctl_wait_events_args *args = data;
+- enum kfd_event_wait_result wait_result;
+ int err;
+
+ err = kfd_wait_on_events(p, args->num_events,
+ (void __user *)args->events_ptr,
+ (args->wait_for_all != 0),
+- args->timeout, &wait_result);
+-
+- args->wait_result = wait_result;
++ args->timeout, &args->wait_result);
+
+ return err;
+ }
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+index b130b64..f746cbc 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+@@ -733,7 +733,7 @@ static bool test_event_condition(bool all, uint32_t num_events,
+ * Copy event specific data, if defined.
+ * Currently only memory exception events have additional data to copy to user
+ */
+-static bool copy_signaled_event_data(uint32_t num_events,
++static int copy_signaled_event_data(uint32_t num_events,
+ struct kfd_event_waiter *event_waiters,
+ struct kfd_event_data __user *data)
+ {
+@@ -751,11 +751,11 @@ static bool copy_signaled_event_data(uint32_t num_events,
+ src = &event->memory_exception_data;
+ if (copy_to_user(dst, src,
+ sizeof(struct kfd_hsa_memory_exception_data)))
+- return false;
++ return -EFAULT;
+ }
+ }
+
+- return true;
++ return 0;
+
+ }
+
+@@ -792,7 +792,7 @@ static void free_waiters(uint32_t num_events, struct kfd_event_waiter *waiters)
+ int kfd_wait_on_events(struct kfd_process *p,
+ uint32_t num_events, void __user *data,
+ bool all, uint32_t user_timeout_ms,
+- enum kfd_event_wait_result *wait_result)
++ uint32_t *wait_result)
+ {
+ struct kfd_event_data __user *events =
+ (struct kfd_event_data __user *) data;
+@@ -801,18 +801,18 @@ int kfd_wait_on_events(struct kfd_process *p,
+ struct kfd_event_waiter *event_waiters = NULL;
+ long timeout = user_timeout_to_jiffies(user_timeout_ms);
+
++ event_waiters = alloc_event_waiters(num_events);
++ if (!event_waiters) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
+ mutex_lock(&p->event_mutex);
+
+ /* Set to something unreasonable - this is really
+ * just a bool for now.
+ */
+- *wait_result = KFD_WAIT_TIMEOUT;
+-
+- event_waiters = alloc_event_waiters(num_events);
+- if (!event_waiters) {
+- ret = -ENOMEM;
+- goto fail;
+- }
++ *wait_result = KFD_IOC_WAIT_RESULT_TIMEOUT;
+
+ for (i = 0; i < num_events; i++) {
+ struct kfd_event_data event_data;
+@@ -820,23 +820,21 @@ int kfd_wait_on_events(struct kfd_process *p,
+ if (copy_from_user(&event_data, &events[i],
+ sizeof(struct kfd_event_data))) {
+ ret = -EFAULT;
+- goto fail;
++ goto out_unlock;
+ }
+
+ ret = init_event_waiter_get_status(p, &event_waiters[i],
+ event_data.event_id, i);
+ if (ret)
+- goto fail;
++ goto out_unlock;
+ }
+
+ /* Check condition once. */
+ if (test_event_condition(all, num_events, event_waiters)) {
+- if (copy_signaled_event_data(num_events,
+- event_waiters, events))
+- *wait_result = KFD_WAIT_COMPLETE;
+- else
+- *wait_result = KFD_WAIT_ERROR;
+- free_waiters(num_events, event_waiters);
++ *wait_result = KFD_IOC_WAIT_RESULT_COMPLETE;
++ ret = copy_signaled_event_data(num_events,
++ event_waiters, events);
++ goto out_unlock;
+ } else {
+ /* Add to wait lists if we need to wait. */
+ for (i = 0; i < num_events; i++)
+@@ -845,12 +843,6 @@ int kfd_wait_on_events(struct kfd_process *p,
+
+ mutex_unlock(&p->event_mutex);
+
+- /* Return if all waits were already satisfied. */
+- if (*wait_result != KFD_WAIT_TIMEOUT) {
+- __set_current_state(TASK_RUNNING);
+- return ret;
+- }
+-
+ while (true) {
+ if (fatal_signal_pending(current)) {
+ ret = -EINTR;
+@@ -882,16 +874,12 @@ int kfd_wait_on_events(struct kfd_process *p,
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (test_event_condition(all, num_events, event_waiters)) {
+- if (copy_signaled_event_data(num_events,
+- event_waiters, events))
+- *wait_result = KFD_WAIT_COMPLETE;
+- else
+- *wait_result = KFD_WAIT_ERROR;
++ *wait_result = KFD_IOC_WAIT_RESULT_COMPLETE;
+ break;
+ }
+
+ if (timeout <= 0) {
+- *wait_result = KFD_WAIT_TIMEOUT;
++ *wait_result = KFD_IOC_WAIT_RESULT_TIMEOUT;
+ break;
+ }
+
+@@ -899,19 +887,20 @@ int kfd_wait_on_events(struct kfd_process *p,
+ }
+ __set_current_state(TASK_RUNNING);
+
++ /* copy_signaled_event_data may sleep. So this has to happen
++ * after the task state is set back to RUNNING.
++ */
++ if (!ret && *wait_result == KFD_IOC_WAIT_RESULT_COMPLETE)
++ ret = copy_signaled_event_data(num_events,
++ event_waiters, events);
++
+ mutex_lock(&p->event_mutex);
++out_unlock:
+ free_waiters(num_events, event_waiters);
+ mutex_unlock(&p->event_mutex);
+-
+- return ret;
+-
+-fail:
+- if (event_waiters)
+- free_waiters(num_events, event_waiters);
+-
+- mutex_unlock(&p->event_mutex);
+-
+- *wait_result = KFD_WAIT_ERROR;
++out:
++ if (ret)
++ *wait_result = KFD_IOC_WAIT_RESULT_FAIL;
+
+ return ret;
+ }
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+index ccac951..1ac4db5 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+@@ -1037,19 +1037,13 @@ extern const struct kfd_event_interrupt_class event_interrupt_class_v9;
+
+ extern const struct kfd_device_global_init_class device_global_init_class_cik;
+
+-enum kfd_event_wait_result {
+- KFD_WAIT_COMPLETE,
+- KFD_WAIT_TIMEOUT,
+- KFD_WAIT_ERROR
+-};
+-
+ void kfd_event_init_process(struct kfd_process *p);
+ void kfd_event_free_process(struct kfd_process *p);
+ int kfd_event_mmap(struct kfd_process *process, struct vm_area_struct *vma);
+ int kfd_wait_on_events(struct kfd_process *p,
+ uint32_t num_events, void __user *data,
+ bool all, uint32_t user_timeout_ms,
+- enum kfd_event_wait_result *wait_result);
++ uint32_t *wait_result);
+ void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id,
+ uint32_t valid_id_bits);
+ #if defined(CONFIG_AMD_IOMMU_V2_MODULE) || defined(CONFIG_AMD_IOMMU_V2)
+--
+2.7.4
+