aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r--drivers/gpu/drm/drm_irq.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 3830e9e478c0..44a5d0ad8b7c 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -40,6 +40,7 @@
40#include <linux/slab.h> 40#include <linux/slab.h>
41 41
42#include <linux/vgaarb.h> 42#include <linux/vgaarb.h>
43#include <linux/export.h>
43 44
44/* Access macro for slots in vblank timestamp ringbuffer. */ 45/* Access macro for slots in vblank timestamp ringbuffer. */
45#define vblanktimestamp(dev, crtc, count) ( \ 46#define vblanktimestamp(dev, crtc, count) ( \
@@ -109,10 +110,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
109 /* Prevent vblank irq processing while disabling vblank irqs, 110 /* Prevent vblank irq processing while disabling vblank irqs,
110 * so no updates of timestamps or count can happen after we've 111 * so no updates of timestamps or count can happen after we've
111 * disabled. Needed to prevent races in case of delayed irq's. 112 * disabled. Needed to prevent races in case of delayed irq's.
112 * Disable preemption, so vblank_time_lock is held as short as
113 * possible, even under a kernel with PREEMPT_RT patches.
114 */ 113 */
115 preempt_disable();
116 spin_lock_irqsave(&dev->vblank_time_lock, irqflags); 114 spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
117 115
118 dev->driver->disable_vblank(dev, crtc); 116 dev->driver->disable_vblank(dev, crtc);
@@ -163,7 +161,6 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
163 clear_vblank_timestamps(dev, crtc); 161 clear_vblank_timestamps(dev, crtc);
164 162
165 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); 163 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
166 preempt_enable();
167} 164}
168 165
169static void vblank_disable_fn(unsigned long arg) 166static void vblank_disable_fn(unsigned long arg)
@@ -406,13 +403,16 @@ int drm_irq_uninstall(struct drm_device *dev)
406 /* 403 /*
407 * Wake up any waiters so they don't hang. 404 * Wake up any waiters so they don't hang.
408 */ 405 */
409 spin_lock_irqsave(&dev->vbl_lock, irqflags); 406 if (dev->num_crtcs) {
410 for (i = 0; i < dev->num_crtcs; i++) { 407 spin_lock_irqsave(&dev->vbl_lock, irqflags);
411 DRM_WAKEUP(&dev->vbl_queue[i]); 408 for (i = 0; i < dev->num_crtcs; i++) {
412 dev->vblank_enabled[i] = 0; 409 DRM_WAKEUP(&dev->vbl_queue[i]);
413 dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i); 410 dev->vblank_enabled[i] = 0;
411 dev->last_vblank[i] =
412 dev->driver->get_vblank_counter(dev, i);
413 }
414 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
414 } 415 }
415 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
416 416
417 if (!irq_enabled) 417 if (!irq_enabled)
418 return -EINVAL; 418 return -EINVAL;
@@ -885,10 +885,6 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
885 spin_lock_irqsave(&dev->vbl_lock, irqflags); 885 spin_lock_irqsave(&dev->vbl_lock, irqflags);
886 /* Going from 0->1 means we have to enable interrupts again */ 886 /* Going from 0->1 means we have to enable interrupts again */
887 if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { 887 if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
888 /* Disable preemption while holding vblank_time_lock. Do
889 * it explicitely to guard against PREEMPT_RT kernel.
890 */
891 preempt_disable();
892 spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); 888 spin_lock_irqsave(&dev->vblank_time_lock, irqflags2);
893 if (!dev->vblank_enabled[crtc]) { 889 if (!dev->vblank_enabled[crtc]) {
894 /* Enable vblank irqs under vblank_time_lock protection. 890 /* Enable vblank irqs under vblank_time_lock protection.
@@ -908,7 +904,6 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
908 } 904 }
909 } 905 }
910 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); 906 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2);
911 preempt_enable();
912 } else { 907 } else {
913 if (!dev->vblank_enabled[crtc]) { 908 if (!dev->vblank_enabled[crtc]) {
914 atomic_dec(&dev->vblank_refcount[crtc]); 909 atomic_dec(&dev->vblank_refcount[crtc]);
@@ -1124,6 +1119,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
1124 trace_drm_vblank_event_delivered(current->pid, pipe, 1119 trace_drm_vblank_event_delivered(current->pid, pipe,
1125 vblwait->request.sequence); 1120 vblwait->request.sequence);
1126 } else { 1121 } else {
1122 /* drm_handle_vblank_events will call drm_vblank_put */
1127 list_add_tail(&e->base.link, &dev->vblank_event_list); 1123 list_add_tail(&e->base.link, &dev->vblank_event_list);
1128 vblwait->reply.sequence = vblwait->request.sequence; 1124 vblwait->reply.sequence = vblwait->request.sequence;
1129 } 1125 }
@@ -1204,8 +1200,12 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
1204 goto done; 1200 goto done;
1205 } 1201 }
1206 1202
1207 if (flags & _DRM_VBLANK_EVENT) 1203 if (flags & _DRM_VBLANK_EVENT) {
1204 /* must hold on to the vblank ref until the event fires
1205 * drm_vblank_put will be called asynchronously
1206 */
1208 return drm_queue_vblank_event(dev, crtc, vblwait, file_priv); 1207 return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
1208 }
1209 1209
1210 if ((flags & _DRM_VBLANK_NEXTONMISS) && 1210 if ((flags & _DRM_VBLANK_NEXTONMISS) &&
1211 (seq - vblwait->request.sequence) <= (1<<23)) { 1211 (seq - vblwait->request.sequence) <= (1<<23)) {