Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1531750 > unrolled thread
| Started by | Eric Anholt <eric@anholt.net> |
|---|---|
| First post | 2016-11-28 23:40 +0100 |
| Last post | 2016-11-29 11:00 +0100 |
| Articles | 2 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH] drm/vc4: Fix race between page flip completion event and clean-up Eric Anholt <eric@anholt.net> - 2016-11-28 23:40 +0100
Re: [PATCH] drm/vc4: Fix race between page flip completion event and clean-up Daniel Stone <daniel@fooishbar.org> - 2016-11-29 11:00 +0100
| From | Eric Anholt <eric@anholt.net> |
|---|---|
| Date | 2016-11-28 23:40 +0100 |
| Subject | [PATCH] drm/vc4: Fix race between page flip completion event and clean-up |
| Message-ID | <sICKB-89o-35@gated-at.bofh.it> |
From: Derek Foreman <derekf@osg.samsung.com>
There was a small window where a userspace program could submit
a pageflip after receiving a pageflip completion event yet still
receive EBUSY.
Signed-off-by: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Eric Anholt <eric@anholt.net>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++++++
drivers/gpu/drm/vc4/vc4_drv.h | 1 +
drivers/gpu/drm/vc4/vc4_kms.c | 33 +++++++++++++++++++++++++--------
3 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 7f08d681a74b..82f914af4156 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -669,6 +669,14 @@ void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id)
CRTC_WRITE(PV_INTEN, 0);
}
+/* Must be called with the event lock held */
+bool vc4_event_pending(struct drm_crtc *crtc)
+{
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+ return !!vc4_crtc->event;
+}
+
static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
{
struct drm_crtc *crtc = &vc4_crtc->base;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index fef172804345..b3064e2e79c1 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -442,6 +442,7 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg);
extern struct platform_driver vc4_crtc_driver;
int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id);
void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id);
+bool vc4_event_pending(struct drm_crtc *crtc);
int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
unsigned int flags, int *vpos, int *hpos,
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index c1f65c6c8e60..67af2af70af0 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -119,17 +119,34 @@ static int vc4_atomic_commit(struct drm_device *dev,
/* Make sure that any outstanding modesets have finished. */
if (nonblock) {
- ret = down_trylock(&vc4->async_modeset);
- if (ret) {
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ unsigned long flags;
+ bool busy = false;
+
+ /*
+ * If there's an undispatched event to send then we're
+ * obviously still busy. If there isn't, then we can
+ * unconditionally wait for the semaphore because it
+ * shouldn't be contended (for long).
+ *
+ * This is to prevent a race where queuing a new flip
+ * from userspace immediately on receipt of an event
+ * beats our clean-up and returns EBUSY.
+ */
+ spin_lock_irqsave(&dev->event_lock, flags);
+ for_each_crtc_in_state(state, crtc, crtc_state, i)
+ busy |= vc4_event_pending(crtc);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ if (busy) {
kfree(c);
return -EBUSY;
}
- } else {
- ret = down_interruptible(&vc4->async_modeset);
- if (ret) {
- kfree(c);
- return ret;
- }
+ }
+ ret = down_interruptible(&vc4->async_modeset);
+ if (ret) {
+ kfree(c);
+ return ret;
}
ret = drm_atomic_helper_prepare_planes(dev, state);
--
2.10.2
[toc] | [next] | [standalone]
| From | Daniel Stone <daniel@fooishbar.org> |
|---|---|
| Date | 2016-11-29 11:00 +0100 |
| Message-ID | <sINmF-6Mq-21@gated-at.bofh.it> |
| In reply to | #1531750 |
On 28 November 2016 at 22:31, Eric Anholt <eric@anholt.net> wrote: > There was a small window where a userspace program could submit > a pageflip after receiving a pageflip completion event yet still > receive EBUSY. > > Signed-off-by: Derek Foreman <derekf@osg.samsung.com> > Signed-off-by: Eric Anholt <eric@anholt.net> > Reviewed-by: Eric Anholt <eric@anholt.net> Reviewed-by: Daniel Stone <daniels@collabora.com>
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web