diff options
author | Dave Airlie <airlied@redhat.com> | 2016-12-13 03:05:12 +0100 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-12-13 03:05:12 +0100 |
commit | 2601a15d5d9b7f262e94b88784b1e1cf28ec020d (patch) | |
tree | 52a5434ad72100759552f18c706dc44598fa6dbc /drivers/gpu/drm/vc4/vc4_kms.c | |
parent | Merge tag 'drm-fsl-dcu-for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu... (diff) | |
parent | drm/vc4: Don't use drm_put_dev (diff) | |
download | linux-2601a15d5d9b7f262e94b88784b1e1cf28ec020d.tar.xz linux-2601a15d5d9b7f262e94b88784b1e1cf28ec020d.zip |
Merge tag 'drm-vc4-next-2016-12-09' of https://github.com/anholt/linux into drm-next
This pull request brings in VEC (TV-out) support for vc4, along with a
pageflipping race fix.
* tag 'drm-vc4-next-2016-12-09' of https://github.com/anholt/linux:
drm/vc4: Don't use drm_put_dev
drm/vc4: Document VEC DT binding
drm/vc4: Add support for the VEC (Video Encoder) IP
drm: Add TV connector states to drm_connector_state
drm: Turn DRM_MODE_SUBCONNECTOR_xx definitions into an enum
drm/vc4: Fix ->clock_select setting for the VEC encoder
drm/vc4: Fix race between page flip completion event and clean-up
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_kms.c')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_kms.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index f31f72af8551..be8dd8262f27 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); |