summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-10-24 14:15:58 +0200
committerBen Skeggs <bskeggs@redhat.com>2010-12-03 15:11:16 +1000
commit1f6d2de2c539df6fe52ad2187191a9dfe10c7233 (patch)
tree29758c192b7e9dfef4c4f4793bc8c459d5cdb85f /drivers/gpu/drm
parent1c180fa5bd5f264e4863bb88861e8cd7d135b917 (diff)
downloadop-kernel-dev-1f6d2de2c539df6fe52ad2187191a9dfe10c7233.zip
op-kernel-dev-1f6d2de2c539df6fe52ad2187191a9dfe10c7233.tar.gz
drm/nv50: Keep track of the head a channel is vsync'ing to.
In a multihead setup vblank interrupts may end up enabled in both heads. In that case we want to ignore the vblank interrupts coming from the wrong CRTC to avoid tearing and unbalanced calls to drm_vblank_get/put (fdo bug 31074). Reported-by: Felix Leimbach <felix.leimbach@gmx.net> Signed-off-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c3
-rw-r--r--drivers/gpu/drm/nouveau/nv50_graph.c3
3 files changed, 7 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 2bb1f15..5814db8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -257,6 +257,7 @@ struct nouveau_channel {
struct {
struct nouveau_gpuobj *vblsem;
+ uint32_t vblsem_head;
uint32_t vblsem_offset;
uint32_t vblsem_rval;
struct list_head vbl_wait;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 17b950a..41b2128 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -432,6 +432,9 @@ nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc)
list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting,
nvsw.vbl_wait) {
+ if (chan->nvsw.vblsem_head != crtc)
+ continue;
+
nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset,
chan->nvsw.vblsem_rval);
list_del(&chan->nvsw.vbl_wait);
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
index 6d81f4d..e0f5294 100644
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -387,7 +387,10 @@ nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan,
return -EINVAL;
drm_vblank_get(dev, data);
+
+ chan->nvsw.vblsem_head = data;
list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting);
+
return 0;
}
OpenPOWER on IntegriCloud