• Mario Kleiner's avatar
    drm: Prevent vblank counter bumps > 1 with active vblank clients. (v2) · 99b8e715
    Mario Kleiner authored
    This fixes a regression introduced by the new drm_update_vblank_count()
    implementation in Linux 4.4:
    
    Restrict the bump of the software vblank counter in drm_update_vblank_count()
    to a safe maximum value of +1 whenever there is the possibility that
    concurrent readers of vblank timestamps could be active at the moment,
    as the current implementation of the timestamp caching and updating is
    not safe against concurrent readers for calls to store_vblank() with a
    bump of anything but +1. A bump != 1 would very likely return corrupted
    timestamps to userspace, because the same slot in the cache could
    be concurrently written by store_vblank() and read by one of those
    readers in a non-atomic fashion and without the read-retry logic
    detecting this collision.
    
    Concurrent readers can exist while drm_update_vblank_count() is called
    from the drm_vblank_off() or drm_vblank_on() functions or other non-vblank-
    irq callers. However, all those calls are happening with the vbl_lock
    locked thereby preventing a drm_vblank_get(), so the vblank refcount
    can't increase while drm_update_vblank_count() is executing. Therefore
    a zero vblank refcount during execution of that function signals that
    is safe for arbitrary counter bumps if called from outside vblank irq,
    whereas a non-zero count is not safe.
    
    Whenever the function is called from vblank irq, we have to assume concurrent
    readers could show up any time during its execution, even if the refcount
    is currently zero, as vblank irqs are usually only enabled due to the
    presence of readers, and because when it is called from vblank irq it
    can't hold the vbl_lock to protect it from sudden bumps in vblank refcount.
    Therefore also restrict bumps to +1 when the function is called from vblank
    irq.
    
    Such bumps of more than +1 can happen at other times than reenabling
    vblank irqs, e.g., when regular vblank interrupts get delayed by more
    than 1 frame due to long held locks, long irq off periods, realtime
    preemption on RT kernels, or system management interrupts.
    
    A better solution would be to rewrite the timestamp caching to use
    full seqlocks to allow concurrent writes and reads for arbitrary
    vblank counter increments.
    
    v2: Add code comment that this is essentially a hack and should
        be replaced by a full seqlock implementation for caching of
        timestamps.
    Signed-off-by: default avatarMario Kleiner <mario.kleiner.de@gmail.com>
    Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
    
    Cc: <stable@vger.kernel.org> # 4.4+
    Cc: michel@daenzer.net
    Cc: vbabka@suse.cz
    Cc: ville.syrjala@linux.intel.com
    Cc: daniel.vetter@ffwll.ch
    Cc: dri-devel@lists.freedesktop.org
    Cc: alexander.deucher@amd.com
    Cc: christian.koenig@amd.com
    Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
    99b8e715
drm_irq.c 57.8 KB