diff options
Diffstat (limited to 'drivers/gpu/host1x/intr.c')
| -rw-r--r-- | drivers/gpu/host1x/intr.c | 28 | 
1 files changed, 20 insertions, 8 deletions
| diff --git a/drivers/gpu/host1x/intr.c b/drivers/gpu/host1x/intr.c index 9245add23b5d..6d1f3c0fdbe7 100644 --- a/drivers/gpu/host1x/intr.c +++ b/drivers/gpu/host1x/intr.c @@ -235,25 +235,37 @@ int host1x_intr_add_action(struct host1x *host, struct host1x_syncpt *syncpt,  			host1x_hw_intr_enable_syncpt_intr(host, syncpt->id);  	} -	spin_unlock(&syncpt->intr.lock); -  	if (ref)  		*ref = waiter; + +	spin_unlock(&syncpt->intr.lock); +  	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);  } | 
