aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-10-24 08:15:58 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-12-03 00:11:16 -0500
commit1f6d2de2c539df6fe52ad2187191a9dfe10c7233 (patch)
tree29758c192b7e9dfef4c4f4793bc8c459d5cdb85f
parent1c180fa5bd5f264e4863bb88861e8cd7d135b917 (diff)
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>
-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 2bb1f1572a55..5814db82f778 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -257,6 +257,7 @@ struct nouveau_channel {
257 257
258 struct { 258 struct {
259 struct nouveau_gpuobj *vblsem; 259 struct nouveau_gpuobj *vblsem;
260 uint32_t vblsem_head;
260 uint32_t vblsem_offset; 261 uint32_t vblsem_offset;
261 uint32_t vblsem_rval; 262 uint32_t vblsem_rval;
262 struct list_head vbl_wait; 263 struct list_head vbl_wait;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 17b950abf200..41b212801870 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)
432 432
433 list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting, 433 list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting,
434 nvsw.vbl_wait) { 434 nvsw.vbl_wait) {
435 if (chan->nvsw.vblsem_head != crtc)
436 continue;
437
435 nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset, 438 nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset,
436 chan->nvsw.vblsem_rval); 439 chan->nvsw.vblsem_rval);
437 list_del(&chan->nvsw.vbl_wait); 440 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 6d81f4dab37d..e0f52942b2eb 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,
387 return -EINVAL; 387 return -EINVAL;
388 388
389 drm_vblank_get(dev, data); 389 drm_vblank_get(dev, data);
390
391 chan->nvsw.vblsem_head = data;
390 list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); 392 list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting);
393
391 return 0; 394 return 0;
392} 395}
393 396