diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3369-drm-amdkfd-Use-wait_queue_t-to-implement-event-waiti.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3369-drm-amdkfd-Use-wait_queue_t-to-implement-event-waiti.patch | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3369-drm-amdkfd-Use-wait_queue_t-to-implement-event-waiti.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3369-drm-amdkfd-Use-wait_queue_t-to-implement-event-waiti.patch new file mode 100644 index 00000000..52895e96 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3369-drm-amdkfd-Use-wait_queue_t-to-implement-event-waiti.patch @@ -0,0 +1,164 @@ +From 441b1d02d0d117edd731ad0c7fa0ae1c81bb63d0 Mon Sep 17 00:00:00 2001 +From: Felix Kuehling <Felix.Kuehling@amd.com> +Date: Fri, 27 Oct 2017 19:35:25 -0400 +Subject: [PATCH 3369/4131] drm/amdkfd: Use wait_queue_t to implement event + waiting + +Use standard wait queues for waiting and waking up waiting threads +instead of inventing our own. We still have our own wait loop +because the HSA event semantics require the ability to have one +thread waiting on multiple wait queues (events) at the same time. + +Signed-off-by: Kent Russell <kent.russell@amd.com> +Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> +Acked-by: Oded Gabbay <oded.gabbay@gmail.com> +Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com> +--- + drivers/gpu/drm/amd/amdkfd/kfd_events.c | 59 ++++++++++++--------------------- + drivers/gpu/drm/amd/amdkfd/kfd_events.h | 3 +- + 2 files changed, 24 insertions(+), 38 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c +index b4cda92..7dae26f 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c +@@ -33,22 +33,12 @@ + #include <linux/device.h> + + /* +- * A task can only be on a single wait_queue at a time, but we need to support +- * waiting on multiple events (any/all). +- * Instead of each event simply having a wait_queue with sleeping tasks, it +- * has a singly-linked list of tasks. +- * A thread that wants to sleep creates an array of these, one for each event +- * and adds one to each event's waiter chain. ++ * Wrapper around wait_queue_entry_t + */ + struct kfd_event_waiter { +- struct list_head waiters; +- struct task_struct *sleeping_task; +- +- /* Transitions to true when the event this belongs to is signaled. */ +- bool activated; +- +- /* Event */ +- struct kfd_event *event; ++ wait_queue_entry_t wait; ++ struct kfd_event *event; /* Event to wait for */ ++ bool activated; /* Becomes true when event is signaled */ + }; + + /* +@@ -344,17 +334,12 @@ void kfd_event_init_process(struct kfd_process *p) + + static void destroy_event(struct kfd_process *p, struct kfd_event *ev) + { +- /* Wake up pending waiters. They will return failure */ +- while (!list_empty(&ev->waiters)) { +- struct kfd_event_waiter *waiter = +- list_first_entry(&ev->waiters, struct kfd_event_waiter, +- waiters); ++ struct kfd_event_waiter *waiter; + ++ /* Wake up pending waiters. They will return failure */ ++ list_for_each_entry(waiter, &ev->wq.head, wait.entry) + waiter->event = NULL; +- /* _init because free_waiters will call list_del */ +- list_del_init(&waiter->waiters); +- wake_up_process(waiter->sleeping_task); +- } ++ wake_up_all(&ev->wq); + + if (ev->signal_page) { + release_event_notification_slot(ev->signal_page, +@@ -424,7 +409,7 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, + ev->auto_reset = auto_reset; + ev->signaled = false; + +- INIT_LIST_HEAD(&ev->waiters); ++ init_waitqueue_head(&ev->wq); + + *event_page_offset = 0; + +@@ -482,19 +467,18 @@ int kfd_event_destroy(struct kfd_process *p, uint32_t event_id) + static void set_event(struct kfd_event *ev) + { + struct kfd_event_waiter *waiter; +- struct kfd_event_waiter *next; + +- /* Auto reset if the list is non-empty and we're waking someone. */ +- ev->signaled = !ev->auto_reset || list_empty(&ev->waiters); ++ /* Auto reset if the list is non-empty and we're waking ++ * someone. waitqueue_active is safe here because we're ++ * protected by the p->event_mutex, which is also held when ++ * updating the wait queues in kfd_wait_on_events. ++ */ ++ ev->signaled = !ev->auto_reset || !waitqueue_active(&ev->wq); + +- list_for_each_entry_safe(waiter, next, &ev->waiters, waiters) { ++ list_for_each_entry(waiter, &ev->wq.head, wait.entry) + waiter->activated = true; + +- /* _init because free_waiters will call list_del */ +- list_del_init(&waiter->waiters); +- +- wake_up_process(waiter->sleeping_task); +- } ++ wake_up_all(&ev->wq); + } + + /* Assumes that p is current. */ +@@ -614,8 +598,7 @@ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events) + GFP_KERNEL); + + for (i = 0; (event_waiters) && (i < num_events) ; i++) { +- INIT_LIST_HEAD(&event_waiters[i].waiters); +- event_waiters[i].sleeping_task = current; ++ init_wait(&event_waiters[i].wait); + event_waiters[i].activated = false; + } + +@@ -646,7 +629,7 @@ static void init_event_waiter_add_to_waitlist(struct kfd_event_waiter *waiter) + * wait on this event. + */ + if (!waiter->activated) +- list_add(&waiter->waiters, &ev->waiters); ++ add_wait_queue(&ev->wq, &waiter->wait); + } + + /* test_event_condition - Test condition of events being waited for +@@ -736,7 +719,9 @@ static void free_waiters(uint32_t num_events, struct kfd_event_waiter *waiters) + uint32_t i; + + for (i = 0; i < num_events; i++) +- list_del(&waiters[i].waiters); ++ if (waiters[i].event) ++ remove_wait_queue(&waiters[i].event->wq, ++ &waiters[i].wait); + + kfree(waiters); + } +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_events.h +index 28f6838..96f9122 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.h +@@ -27,6 +27,7 @@ + #include <linux/hashtable.h> + #include <linux/types.h> + #include <linux/list.h> ++#include <linux/wait.h> + #include "kfd_priv.h" + #include <uapi/linux/kfd_ioctl.h> + +@@ -56,7 +57,7 @@ struct kfd_event { + + int type; + +- struct list_head waiters; /* List of kfd_event_waiter by waiters. */ ++ wait_queue_head_t wq; /* List of event waiters. */ + + /* Only for signal events. */ + struct signal_page *signal_page; +-- +2.7.4 + |