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

drm: Peek at the current counter/timestamp for vblank queries

Bypass all the spinlocks and return the last timestamp and counter from
the last vblank if the driver delcares that it is accurate (and stable
across on/off), and the vblank is currently enabled.

This is dependent upon the both the hardware and driver to provide the
proper barriers to facilitate reading our bookkeeping outside of the
vblank interrupt and outside of the explicit vblank locks.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: Michel Dänzer <michel@daenzer.net>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Dave Airlie <airlied@redhat.com>,
Cc: Mario Kleiner <mario.kleiner.de@gmail.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170317202030.24410-4-chris@chris-wilson.co.uk
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

authored by

Chris Wilson and committed by
Ville Syrjälä
b33b0270 9a4d9bab

+26
+26
drivers/gpu/drm/drm_irq.c
··· 1561 1561 return ret; 1562 1562 } 1563 1563 1564 + static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait) 1565 + { 1566 + if (vblwait->request.sequence) 1567 + return false; 1568 + 1569 + return _DRM_VBLANK_RELATIVE == 1570 + (vblwait->request.type & (_DRM_VBLANK_TYPES_MASK | 1571 + _DRM_VBLANK_EVENT | 1572 + _DRM_VBLANK_NEXTONMISS)); 1573 + } 1574 + 1564 1575 /* 1565 1576 * Wait for VBLANK. 1566 1577 * ··· 1620 1609 return -EINVAL; 1621 1610 1622 1611 vblank = &dev->vblank[pipe]; 1612 + 1613 + /* If the counter is currently enabled and accurate, short-circuit 1614 + * queries to return the cached timestamp of the last vblank. 1615 + */ 1616 + if (dev->vblank_disable_immediate && 1617 + drm_wait_vblank_is_query(vblwait) && 1618 + READ_ONCE(vblank->enabled)) { 1619 + struct timeval now; 1620 + 1621 + vblwait->reply.sequence = 1622 + drm_vblank_count_and_time(dev, pipe, &now); 1623 + vblwait->reply.tval_sec = now.tv_sec; 1624 + vblwait->reply.tval_usec = now.tv_usec; 1625 + return 0; 1626 + } 1623 1627 1624 1628 ret = drm_vblank_get(dev, pipe); 1625 1629 if (ret) {