From 250e64a3f06c42e993e7b8c6f727d43b5b9f8c96 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Tue, 12 Apr 2022 16:24:49 -0400 Subject: [PATCH] drm/amdkfd: fix race condition in kfd_wait_on_events Add the waiters to the wait queue during initialization, while holding the event spinlock. Otherwise the waiter will not get activated if the event signals before being added to the wait queue. Signed-off-by: Felix Kuehling Reviewed-by: Philip Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 26 +++++-------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index e449bc70bf084..6e5e8d637f48b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -780,7 +780,7 @@ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events) return event_waiters; } -static int init_event_waiter_get_status(struct kfd_process *p, +static int init_event_waiter(struct kfd_process *p, struct kfd_event_waiter *waiter, uint32_t event_id) { @@ -793,25 +793,13 @@ static int init_event_waiter_get_status(struct kfd_process *p, waiter->event = ev; waiter->activated = ev->signaled; ev->signaled = ev->signaled && !ev->auto_reset; + if (!waiter->activated) + add_wait_queue(&ev->wq, &waiter->wait); spin_unlock(&ev->lock); return 0; } -static void init_event_waiter_add_to_waitlist(struct kfd_event_waiter *waiter) -{ - struct kfd_event *ev = waiter->event; - - /* Only add to the wait list if we actually need to - * wait on this event. - */ - if (!waiter->activated) { - spin_lock(&ev->lock); - add_wait_queue(&ev->wq, &waiter->wait); - spin_unlock(&ev->lock); - } -} - /* test_event_condition - Test condition of events being waited for * @all: Return completion only if all events have signaled * @num_events: Number of events to wait for @@ -941,8 +929,8 @@ int kfd_wait_on_events(struct kfd_process *p, goto out_unlock; } - ret = init_event_waiter_get_status(p, &event_waiters[i], - event_data.event_id); + ret = init_event_waiter(p, &event_waiters[i], + event_data.event_id); if (ret) goto out_unlock; } @@ -960,10 +948,6 @@ int kfd_wait_on_events(struct kfd_process *p, goto out_unlock; } - /* Add to wait lists if we need to wait. */ - for (i = 0; i < num_events; i++) - init_event_waiter_add_to_waitlist(&event_waiters[i]); - mutex_unlock(&p->event_mutex); while (true) { -- 2.30.2