diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-10-24 08:15:58 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-12-03 00:11:16 -0500 |
commit | 1f6d2de2c539df6fe52ad2187191a9dfe10c7233 (patch) | |
tree | 29758c192b7e9dfef4c4f4793bc8c459d5cdb85f | |
parent | 1c180fa5bd5f264e4863bb88861e8cd7d135b917 (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.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_graph.c | 3 |
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 | ||