diff options
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index cb3794a00f98..44a5d0ad8b7c 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -110,10 +110,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
110 | /* Prevent vblank irq processing while disabling vblank irqs, | 110 | /* Prevent vblank irq processing while disabling vblank irqs, |
111 | * 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 |
112 | * disabled. Needed to prevent races in case of delayed irq's. | 112 | * disabled. Needed to prevent races in case of delayed irq's. |
113 | * Disable preemption, so vblank_time_lock is held as short as | ||
114 | * possible, even under a kernel with PREEMPT_RT patches. | ||
115 | */ | 113 | */ |
116 | preempt_disable(); | ||
117 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); | 114 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); |
118 | 115 | ||
119 | dev->driver->disable_vblank(dev, crtc); | 116 | dev->driver->disable_vblank(dev, crtc); |
@@ -164,7 +161,6 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
164 | clear_vblank_timestamps(dev, crtc); | 161 | clear_vblank_timestamps(dev, crtc); |
165 | 162 | ||
166 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); | 163 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); |
167 | preempt_enable(); | ||
168 | } | 164 | } |
169 | 165 | ||
170 | static void vblank_disable_fn(unsigned long arg) | 166 | static void vblank_disable_fn(unsigned long arg) |
@@ -407,13 +403,16 @@ int drm_irq_uninstall(struct drm_device *dev) | |||
407 | /* | 403 | /* |
408 | * Wake up any waiters so they don't hang. | 404 | * Wake up any waiters so they don't hang. |
409 | */ | 405 | */ |
410 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 406 | if (dev->num_crtcs) { |
411 | for (i = 0; i < dev->num_crtcs; i++) { | 407 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
412 | DRM_WAKEUP(&dev->vbl_queue[i]); | 408 | for (i = 0; i < dev->num_crtcs; i++) { |
413 | dev->vblank_enabled[i] = 0; | 409 | DRM_WAKEUP(&dev->vbl_queue[i]); |
414 | 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); | ||
415 | } | 415 | } |
416 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | ||
417 | 416 | ||
418 | if (!irq_enabled) | 417 | if (!irq_enabled) |
419 | return -EINVAL; | 418 | return -EINVAL; |
@@ -886,10 +885,6 @@ int drm_vblank_get(struct drm_device *dev, int crtc) | |||
886 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 885 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
887 | /* Going from 0->1 means we have to enable interrupts again */ | 886 | /* Going from 0->1 means we have to enable interrupts again */ |
888 | if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { | 887 | if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { |
889 | /* Disable preemption while holding vblank_time_lock. Do | ||
890 | * it explicitely to guard against PREEMPT_RT kernel. | ||
891 | */ | ||
892 | preempt_disable(); | ||
893 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); | 888 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); |
894 | if (!dev->vblank_enabled[crtc]) { | 889 | if (!dev->vblank_enabled[crtc]) { |
895 | /* Enable vblank irqs under vblank_time_lock protection. | 890 | /* Enable vblank irqs under vblank_time_lock protection. |
@@ -909,7 +904,6 @@ int drm_vblank_get(struct drm_device *dev, int crtc) | |||
909 | } | 904 | } |
910 | } | 905 | } |
911 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); | 906 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); |
912 | preempt_enable(); | ||
913 | } else { | 907 | } else { |
914 | if (!dev->vblank_enabled[crtc]) { | 908 | if (!dev->vblank_enabled[crtc]) { |
915 | atomic_dec(&dev->vblank_refcount[crtc]); | 909 | atomic_dec(&dev->vblank_refcount[crtc]); |
@@ -1125,6 +1119,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, | |||
1125 | trace_drm_vblank_event_delivered(current->pid, pipe, | 1119 | trace_drm_vblank_event_delivered(current->pid, pipe, |
1126 | vblwait->request.sequence); | 1120 | vblwait->request.sequence); |
1127 | } else { | 1121 | } else { |
1122 | /* drm_handle_vblank_events will call drm_vblank_put */ | ||
1128 | list_add_tail(&e->base.link, &dev->vblank_event_list); | 1123 | list_add_tail(&e->base.link, &dev->vblank_event_list); |
1129 | vblwait->reply.sequence = vblwait->request.sequence; | 1124 | vblwait->reply.sequence = vblwait->request.sequence; |
1130 | } | 1125 | } |
@@ -1205,8 +1200,12 @@ int drm_wait_vblank(struct drm_device *dev, void *data, | |||
1205 | goto done; | 1200 | goto done; |
1206 | } | 1201 | } |
1207 | 1202 | ||
1208 | 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 | */ | ||
1209 | return drm_queue_vblank_event(dev, crtc, vblwait, file_priv); | 1207 | return drm_queue_vblank_event(dev, crtc, vblwait, file_priv); |
1208 | } | ||
1210 | 1209 | ||
1211 | if ((flags & _DRM_VBLANK_NEXTONMISS) && | 1210 | if ((flags & _DRM_VBLANK_NEXTONMISS) && |
1212 | (seq - vblwait->request.sequence) <= (1<<23)) { | 1211 | (seq - vblwait->request.sequence) <= (1<<23)) { |