2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-25 21:54:06 +08:00

gpu: host1x: Remove cancelled waiters immediately

Before this patch, cancelled waiters would only be cleaned up
once their threshold value was reached. Make host1x_intr_put_ref
process the cancellation immediately to fix this.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
Mikko Perttunen 2021-03-29 16:38:30 +03:00 committed by Thierry Reding
parent 49a5fb1679
commit ecfb888ade
3 changed files with 21 additions and 8 deletions

View File

@ -242,18 +242,29 @@ int host1x_intr_add_action(struct host1x *host, struct host1x_syncpt *syncpt,
return 0;
}
void host1x_intr_put_ref(struct host1x *host, unsigned int id, void *ref)
void host1x_intr_put_ref(struct host1x *host, unsigned int id, void *ref,
bool flush)
{
struct host1x_waitlist *waiter = ref;
struct host1x_syncpt *syncpt;
while (atomic_cmpxchg(&waiter->state, WLS_PENDING, WLS_CANCELLED) ==
WLS_REMOVED)
schedule();
atomic_cmpxchg(&waiter->state, WLS_PENDING, WLS_CANCELLED);
syncpt = host->syncpt + id;
(void)process_wait_list(host, syncpt,
host1x_syncpt_load(host->syncpt + id));
spin_lock(&syncpt->intr.lock);
if (atomic_cmpxchg(&waiter->state, WLS_CANCELLED, WLS_HANDLED) ==
WLS_CANCELLED) {
list_del(&waiter->list);
kref_put(&waiter->refcount, waiter_release);
}
spin_unlock(&syncpt->intr.lock);
if (flush) {
/* Wait until any concurrently executing handler has finished. */
while (atomic_read(&waiter->state) != WLS_HANDLED)
schedule();
}
kref_put(&waiter->refcount, waiter_release);
}

View File

@ -74,8 +74,10 @@ int host1x_intr_add_action(struct host1x *host, struct host1x_syncpt *syncpt,
* Unreference an action submitted to host1x_intr_add_action().
* You must call this if you passed non-NULL as ref.
* @ref the ref returned from host1x_intr_add_action()
* @flush wait until any pending handlers have completed before returning.
*/
void host1x_intr_put_ref(struct host1x *host, unsigned int id, void *ref);
void host1x_intr_put_ref(struct host1x *host, unsigned int id, void *ref,
bool flush);
/* Initialize host1x sync point interrupt */
int host1x_intr_init(struct host1x *host, unsigned int irq_sync);

View File

@ -308,7 +308,7 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
}
}
host1x_intr_put_ref(sp->host, sp->id, ref);
host1x_intr_put_ref(sp->host, sp->id, ref, true);
done:
return err;