diff options
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 32 |
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 | ||
169 | static void vblank_disable_fn(unsigned long arg) | 166 | static 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)) { |