Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Francisco Jerez and committed by
Ben Skeggs
1f6d2de2 1c180fa5

+7
+1
drivers/gpu/drm/nouveau/nouveau_drv.h
··· 257 257 258 258 struct { 259 259 struct nouveau_gpuobj *vblsem; 260 + uint32_t vblsem_head; 260 261 uint32_t vblsem_offset; 261 262 uint32_t vblsem_rval; 262 263 struct list_head vbl_wait;
+3
drivers/gpu/drm/nouveau/nv50_display.c
··· 432 432 433 433 list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting, 434 434 nvsw.vbl_wait) { 435 + if (chan->nvsw.vblsem_head != crtc) 436 + continue; 437 + 435 438 nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset, 436 439 chan->nvsw.vblsem_rval); 437 440 list_del(&chan->nvsw.vbl_wait);
+3
drivers/gpu/drm/nouveau/nv50_graph.c
··· 387 387 return -EINVAL; 388 388 389 389 drm_vblank_get(dev, data); 390 + 391 + chan->nvsw.vblsem_head = data; 390 392 list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); 393 + 391 394 return 0; 392 395 } 393 396