diff options
author | Dave Airlie <airlied@redhat.com> | 2016-06-01 17:50:23 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-06-01 17:50:23 -0400 |
commit | 65439b68bb10afd877af05463bbff5d25200fd06 (patch) | |
tree | 846aeadab033ec39a3ed942c82976b40ea4994a2 /drivers/gpu/drm/drm_irq.c | |
parent | 1a695a905c18548062509178b98bc91e67510864 (diff) | |
parent | b82caafcf230362e2233ccf912a37face07f6d76 (diff) |
Merge tag 'topic/drm-misc-2016-06-01' of git://anongit.freedesktop.org/drm-intel into drm-next
Frist -misc pull for 4.8, with pretty much just random all over plus a few
more lockless gem BO patches acked/reviewed by driver maintainers.
I'm starting a bit earlier this time around because there's a few invasive
patch series to land (nonblocking atomic prep work, fence prep work,
rst/sphinx kerneldoc finally happening) and I need a baseline with all the
branches merged.
* tag 'topic/drm-misc-2016-06-01' of git://anongit.freedesktop.org/drm-intel: (21 commits)
drm/vc4: Use lockless gem BO free callback
drm/vc4: Use drm_gem_object_unreference_unlocked
drm: Initialize a linear gamma table by default
drm/vgem: Use lockless gem BO free callback
drm/qxl: Don't set a gamma table size
drm/msm: Nuke dummy gamma_set/get functions
drm/cirrus: Drop redundnant gamma size check
drm/fb-helper: Remove dead code in setcolreg
drm/mediatek: Use lockless gem BO free callback
drm/hisilicon: Use lockless gem BO free callback
drm/hlcd: Use lockless gem BO free callback
vga_switcheroo: Support deferred probing of audio clients
vga_switcheroo: Add helper for deferred probing
virtio-gpu: fix output lookup
drm/doc: Unify KMS Locking docs
drm/atomic-helper: Do not call ->mode_fixup for CRTC which will be disabled
Fix annoyingly awkward typo in drm_edid_load.c
drm/doc: Drop vblank_disable_allow wording
drm: use seqlock for vblank time/count
drm/mm: avoid possible null pointer dereference
...
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 90 |
1 files changed, 12 insertions, 78 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 0fac801c18fe..66e5c1e412d3 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -42,10 +42,6 @@ | |||
42 | #include <linux/vgaarb.h> | 42 | #include <linux/vgaarb.h> |
43 | #include <linux/export.h> | 43 | #include <linux/export.h> |
44 | 44 | ||
45 | /* Access macro for slots in vblank timestamp ringbuffer. */ | ||
46 | #define vblanktimestamp(dev, pipe, count) \ | ||
47 | ((dev)->vblank[pipe].time[(count) % DRM_VBLANKTIME_RBSIZE]) | ||
48 | |||
49 | /* Retry timestamp calculation up to 3 times to satisfy | 45 | /* Retry timestamp calculation up to 3 times to satisfy |
50 | * drm_timestamp_precision before giving up. | 46 | * drm_timestamp_precision before giving up. |
51 | */ | 47 | */ |
@@ -82,29 +78,15 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe, | |||
82 | struct timeval *t_vblank, u32 last) | 78 | struct timeval *t_vblank, u32 last) |
83 | { | 79 | { |
84 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | 80 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
85 | u32 tslot; | ||
86 | 81 | ||
87 | assert_spin_locked(&dev->vblank_time_lock); | 82 | assert_spin_locked(&dev->vblank_time_lock); |
88 | 83 | ||
89 | vblank->last = last; | 84 | vblank->last = last; |
90 | 85 | ||
91 | /* All writers hold the spinlock, but readers are serialized by | 86 | write_seqlock(&vblank->seqlock); |
92 | * the latching of vblank->count below. | 87 | vblank->time = *t_vblank; |
93 | */ | ||
94 | tslot = vblank->count + vblank_count_inc; | ||
95 | vblanktimestamp(dev, pipe, tslot) = *t_vblank; | ||
96 | |||
97 | /* | ||
98 | * vblank timestamp updates are protected on the write side with | ||
99 | * vblank_time_lock, but on the read side done locklessly using a | ||
100 | * sequence-lock on the vblank counter. Ensure correct ordering using | ||
101 | * memory barrriers. We need the barrier both before and also after the | ||
102 | * counter update to synchronize with the next timestamp write. | ||
103 | * The read-side barriers for this are in drm_vblank_count_and_time. | ||
104 | */ | ||
105 | smp_wmb(); | ||
106 | vblank->count += vblank_count_inc; | 88 | vblank->count += vblank_count_inc; |
107 | smp_wmb(); | 89 | write_sequnlock(&vblank->seqlock); |
108 | } | 90 | } |
109 | 91 | ||
110 | /** | 92 | /** |
@@ -205,7 +187,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, | |||
205 | const struct timeval *t_old; | 187 | const struct timeval *t_old; |
206 | u64 diff_ns; | 188 | u64 diff_ns; |
207 | 189 | ||
208 | t_old = &vblanktimestamp(dev, pipe, vblank->count); | 190 | t_old = &vblank->time; |
209 | diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old); | 191 | diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old); |
210 | 192 | ||
211 | /* | 193 | /* |
@@ -239,49 +221,6 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, | |||
239 | diff = 1; | 221 | diff = 1; |
240 | } | 222 | } |
241 | 223 | ||
242 | /* | ||
243 | * FIMXE: Need to replace this hack with proper seqlocks. | ||
244 | * | ||
245 | * Restrict the bump of the software vblank counter to a safe maximum | ||
246 | * value of +1 whenever there is the possibility that concurrent readers | ||
247 | * of vblank timestamps could be active at the moment, as the current | ||
248 | * implementation of the timestamp caching and updating is not safe | ||
249 | * against concurrent readers for calls to store_vblank() with a bump | ||
250 | * of anything but +1. A bump != 1 would very likely return corrupted | ||
251 | * timestamps to userspace, because the same slot in the cache could | ||
252 | * be concurrently written by store_vblank() and read by one of those | ||
253 | * readers without the read-retry logic detecting the collision. | ||
254 | * | ||
255 | * Concurrent readers can exist when we are called from the | ||
256 | * drm_vblank_off() or drm_vblank_on() functions and other non-vblank- | ||
257 | * irq callers. However, all those calls to us are happening with the | ||
258 | * vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount | ||
259 | * can't increase while we are executing. Therefore a zero refcount at | ||
260 | * this point is safe for arbitrary counter bumps if we are called | ||
261 | * outside vblank irq, a non-zero count is not 100% safe. Unfortunately | ||
262 | * we must also accept a refcount of 1, as whenever we are called from | ||
263 | * drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and | ||
264 | * we must let that one pass through in order to not lose vblank counts | ||
265 | * during vblank irq off - which would completely defeat the whole | ||
266 | * point of this routine. | ||
267 | * | ||
268 | * Whenever we are called from vblank irq, we have to assume concurrent | ||
269 | * readers exist or can show up any time during our execution, even if | ||
270 | * the refcount is currently zero, as vblank irqs are usually only | ||
271 | * enabled due to the presence of readers, and because when we are called | ||
272 | * from vblank irq we can't hold the vbl_lock to protect us from sudden | ||
273 | * bumps in vblank refcount. Therefore also restrict bumps to +1 when | ||
274 | * called from vblank irq. | ||
275 | */ | ||
276 | if ((diff > 1) && (atomic_read(&vblank->refcount) > 1 || | ||
277 | (flags & DRM_CALLED_FROM_VBLIRQ))) { | ||
278 | DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u " | ||
279 | "refcount %u, vblirq %u\n", pipe, diff, | ||
280 | atomic_read(&vblank->refcount), | ||
281 | (flags & DRM_CALLED_FROM_VBLIRQ) != 0); | ||
282 | diff = 1; | ||
283 | } | ||
284 | |||
285 | DRM_DEBUG_VBL("updating vblank count on crtc %u:" | 224 | DRM_DEBUG_VBL("updating vblank count on crtc %u:" |
286 | " current=%u, diff=%u, hw=%u hw_last=%u\n", | 225 | " current=%u, diff=%u, hw=%u hw_last=%u\n", |
287 | pipe, vblank->count, diff, cur_vblank, vblank->last); | 226 | pipe, vblank->count, diff, cur_vblank, vblank->last); |
@@ -417,6 +356,7 @@ int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs) | |||
417 | init_waitqueue_head(&vblank->queue); | 356 | init_waitqueue_head(&vblank->queue); |
418 | setup_timer(&vblank->disable_timer, vblank_disable_fn, | 357 | setup_timer(&vblank->disable_timer, vblank_disable_fn, |
419 | (unsigned long)vblank); | 358 | (unsigned long)vblank); |
359 | seqlock_init(&vblank->seqlock); | ||
420 | } | 360 | } |
421 | 361 | ||
422 | DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); | 362 | DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); |
@@ -986,25 +926,19 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, | |||
986 | struct timeval *vblanktime) | 926 | struct timeval *vblanktime) |
987 | { | 927 | { |
988 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | 928 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
989 | int count = DRM_TIMESTAMP_MAXRETRIES; | 929 | u32 vblank_count; |
990 | u32 cur_vblank; | 930 | unsigned int seq; |
991 | 931 | ||
992 | if (WARN_ON(pipe >= dev->num_crtcs)) | 932 | if (WARN_ON(pipe >= dev->num_crtcs)) |
993 | return 0; | 933 | return 0; |
994 | 934 | ||
995 | /* | ||
996 | * Vblank timestamps are read lockless. To ensure consistency the vblank | ||
997 | * counter is rechecked and ordering is ensured using memory barriers. | ||
998 | * This works like a seqlock. The write-side barriers are in store_vblank. | ||
999 | */ | ||
1000 | do { | 935 | do { |
1001 | cur_vblank = vblank->count; | 936 | seq = read_seqbegin(&vblank->seqlock); |
1002 | smp_rmb(); | 937 | vblank_count = vblank->count; |
1003 | *vblanktime = vblanktimestamp(dev, pipe, cur_vblank); | 938 | *vblanktime = vblank->time; |
1004 | smp_rmb(); | 939 | } while (read_seqretry(&vblank->seqlock, seq)); |
1005 | } while (cur_vblank != vblank->count && --count > 0); | ||
1006 | 940 | ||
1007 | return cur_vblank; | 941 | return vblank_count; |
1008 | } | 942 | } |
1009 | EXPORT_SYMBOL(drm_vblank_count_and_time); | 943 | EXPORT_SYMBOL(drm_vblank_count_and_time); |
1010 | 944 | ||