aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/host1x/intr.c
diff options
context:
space:
mode:
authorDave Airlie <[email protected]>2021-04-30 09:56:31 +1000
committerDave Airlie <[email protected]>2021-04-30 09:57:07 +1000
commit12fc11bce6f29a73eb3d61ab4e76a9ece3da1f1d (patch)
treee17d2fdc2ea4a8f9363e242b6465ce88e5c283d3 /drivers/gpu/host1x/intr.c
parenta1a1ca70deb3ec600eeabb21de7f3f48aaae5695 (diff)
parent7b6f846785f41d57917e36851c120cfbe87f0809 (diff)
Merge tag 'drm/tegra/for-5.13-rc1' of ssh://git.freedesktop.org/git/tegra/linux into drm-next
drm/tegra: Changes for v5.13-rc1 The changes this time around contain a couple of fixes for host1x along with some improvements for Tegra DRM. Most notably the Tegra DRM driver now supports the hardware cursor on Tegra186 and later, more correctly reflects the capabilities of the display pipelines on various Tegra SoC generations and knows how to deal with the dGPU sector layout by using framebuffer modifiers. Signed-off-by: Dave Airlie <[email protected]> From: Thierry Reding <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
Diffstat (limited to 'drivers/gpu/host1x/intr.c')
-rw-r--r--drivers/gpu/host1x/intr.c28
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);
}