aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-06-01 17:50:23 -0400
committerDave Airlie <airlied@redhat.com>2016-06-01 17:50:23 -0400
commit65439b68bb10afd877af05463bbff5d25200fd06 (patch)
tree846aeadab033ec39a3ed942c82976b40ea4994a2 /drivers/gpu/drm/drm_irq.c
parent1a695a905c18548062509178b98bc91e67510864 (diff)
parentb82caafcf230362e2233ccf912a37face07f6d76 (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.c90
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}
1009EXPORT_SYMBOL(drm_vblank_count_and_time); 943EXPORT_SYMBOL(drm_vblank_count_and_time);
1010 944