alistair23-linux/drivers/gpu/drm
Mario Kleiner 99b8e71597 drm: Prevent vblank counter bumps > 1 with active vblank clients. (v2)
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: Mario Kleiner <mario.kleiner.de@gmail.com>
Reviewed-by: Daniel 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: Dave Airlie <airlied@redhat.com>
2016-02-17 14:18:59 +10:00
..
amd drm/amdgpu: fix issue with overlapping userptrs 2016-02-10 14:07:52 -05:00
armada Merge branch 'drm-armada-devel' of git://ftp.arm.linux.org.uk/~rmk/linux-arm into drm-next 2015-12-23 09:19:58 +10:00
ast
atmel-hlcdc
bochs
bridge Merge tag 'topic/drm-misc-2016-01-17' of git://anongit.freedesktop.org/drm-intel into drm-next 2016-01-18 07:01:16 +10:00
cirrus
etnaviv drm/etnaviv: call correct function when trying to vmap a DMABUF 2016-01-26 18:54:01 +01:00
exynos drm/exynos/decon: fix disable clocks order 2016-02-15 23:25:23 +09:00
fsl-dcu
gma500 Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux 2016-01-17 13:40:25 -08:00
i2c drm: adv7511: it's HPD, not HDP 2016-02-02 15:37:55 +01:00
i810
i915 drm/i915: fix error path in intel_setup_gmbus() 2016-02-10 18:11:34 +02:00
imx dma-mapping: always provide the dma_map_ops based implementation 2016-01-20 17:09:18 -08:00
mga
mgag200 asm-generic changes for 4.5 2016-01-20 17:30:20 -08:00
msm Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux 2016-01-17 13:40:25 -08:00
nouveau asm-generic changes for 4.5 2016-01-20 17:30:20 -08:00
omapdrm fbdev changes for 4.5 2016-01-18 11:58:31 -08:00
panel
qxl drm/qxl: use kmalloc_array to alloc reloc_info in qxl_process_single_command 2016-02-17 14:16:06 +10:00
r128
radeon drm/radeon: hold reference to fences in radeon_sa_bo_new 2016-02-10 14:07:44 -05:00
rcar-du dma-mapping: always provide the dma_map_ops based implementation 2016-01-20 17:09:18 -08:00
rockchip drm/rockchip: respect CONFIG_DRM_FBDEV_EMULATION 2016-01-22 08:45:31 +08:00
savage
shmobile dma-mapping: always provide the dma_map_ops based implementation 2016-01-20 17:09:18 -08:00
sis
sti dma-mapping: always provide the dma_map_ops based implementation 2016-01-20 17:09:18 -08:00
tdfx
tegra Merge tag 'topic/drm-misc-2016-01-17' of git://anongit.freedesktop.org/drm-intel into drm-next 2016-01-18 07:01:16 +10:00
tilcdc dma-mapping: always provide the dma_map_ops based implementation 2016-01-20 17:09:18 -08:00
ttm Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux 2016-01-17 13:40:25 -08:00
udl
vc4 This pull request just includes the !CONFIG_PM_SLEEP build fix for 2016-01-29 10:02:35 +10:00
vgem
via
virtio virtio: barrier rework+fixes 2016-01-18 16:44:24 -08:00
vmwgfx drm/vmwgfx: respect 'nomodeset' 2016-01-29 10:03:44 +10:00
ati_pcigart.c
drm_agpsupport.c
drm_atomic.c drm/atomic: Remove drm_atomic_connectors_for_crtc. 2016-01-06 16:37:39 +01:00
drm_atomic_helper.c drm/atomic-helper: Export framebuffer_changed() 2016-01-20 08:55:43 +08:00
drm_auth.c
drm_bridge.c
drm_bufs.c
drm_cache.c
drm_context.c
drm_crtc.c drm: Do not set connector->encoder in drivers 2016-01-13 13:30:53 +01:00
drm_crtc_helper.c
drm_crtc_internal.h
drm_debugfs.c
drm_dma.c
drm_dp_helper.c
drm_dp_mst_topology.c Revert "drm/dp/mst: change MST detection scheme" 2016-02-17 14:07:48 +10:00
drm_drv.c drm: move MODULE_PARM_DESC to other file 2016-01-08 15:32:29 +01:00
drm_edid.c drm/edid: index CEA/HDMI mode tables using the VIC 2016-01-08 15:30:28 +01:00
drm_edid_load.c
drm_encoder_slave.c
drm_fb_cma_helper.c drm/fb_cma_helper: Remove implicit call to disable_unused_functions 2016-01-15 11:16:15 +01:00
drm_fb_helper.c
drm_flip_work.c
drm_fops.c
drm_gem.c drm: Remove opencoded drm_gem_object_release_handle() 2016-01-05 16:23:09 +01:00
drm_gem_cma_helper.c
drm_global.c
drm_hashtab.c tree wide: use kvfree() than conditional kfree()/vfree() 2016-01-22 17:02:18 -08:00
drm_info.c
drm_internal.h
drm_ioc32.c
drm_ioctl.c
drm_irq.c drm: Prevent vblank counter bumps > 1 with active vblank clients. (v2) 2016-02-17 14:18:59 +10:00
drm_legacy.h
drm_lock.c
drm_memory.c
drm_mipi_dsi.c
drm_mm.c
drm_modes.c
drm_modeset_lock.c
drm_of.c
drm_panel.c
drm_pci.c
drm_plane_helper.c
drm_platform.c
drm_prime.c
drm_probe_helper.c Merge branch 'for-linus' into for-next 2015-12-23 08:33:34 +01:00
drm_rect.c
drm_scatter.c
drm_sysfs.c drm/sysfs: use kobj_to_dev() 2016-01-13 16:43:07 +01:00
drm_trace.h
drm_trace_points.c
drm_vm.c
drm_vma_manager.c
Kconfig dma-mapping: always provide the dma_map_ops based implementation 2016-01-20 17:09:18 -08:00
Makefile Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild 2016-01-20 09:45:43 -08:00