diff options
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 177 |
1 files changed, 66 insertions, 111 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f92da0a32f0d..d80d95289e10 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -43,9 +43,8 @@ | |||
43 | #include <linux/export.h> | 43 | #include <linux/export.h> |
44 | 44 | ||
45 | /* Access macro for slots in vblank timestamp ringbuffer. */ | 45 | /* Access macro for slots in vblank timestamp ringbuffer. */ |
46 | #define vblanktimestamp(dev, crtc, count) ( \ | 46 | #define vblanktimestamp(dev, crtc, count) \ |
47 | (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \ | 47 | ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE]) |
48 | ((count) % DRM_VBLANKTIME_RBSIZE)]) | ||
49 | 48 | ||
50 | /* Retry timestamp calculation up to 3 times to satisfy | 49 | /* Retry timestamp calculation up to 3 times to satisfy |
51 | * drm_timestamp_precision before giving up. | 50 | * drm_timestamp_precision before giving up. |
@@ -89,8 +88,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, | |||
89 | */ | 88 | */ |
90 | static void clear_vblank_timestamps(struct drm_device *dev, int crtc) | 89 | static void clear_vblank_timestamps(struct drm_device *dev, int crtc) |
91 | { | 90 | { |
92 | memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0, | 91 | memset(dev->vblank[crtc].time, 0, sizeof(dev->vblank[crtc].time)); |
93 | DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval)); | ||
94 | } | 92 | } |
95 | 93 | ||
96 | /* | 94 | /* |
@@ -115,7 +113,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
115 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); | 113 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); |
116 | 114 | ||
117 | dev->driver->disable_vblank(dev, crtc); | 115 | dev->driver->disable_vblank(dev, crtc); |
118 | dev->vblank_enabled[crtc] = 0; | 116 | dev->vblank[crtc].enabled = false; |
119 | 117 | ||
120 | /* No further vblank irq's will be processed after | 118 | /* No further vblank irq's will be processed after |
121 | * this point. Get current hardware vblank count and | 119 | * this point. Get current hardware vblank count and |
@@ -130,9 +128,9 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
130 | * delayed gpu counter increment. | 128 | * delayed gpu counter increment. |
131 | */ | 129 | */ |
132 | do { | 130 | do { |
133 | dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); | 131 | dev->vblank[crtc].last = dev->driver->get_vblank_counter(dev, crtc); |
134 | vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); | 132 | vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); |
135 | } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); | 133 | } while (dev->vblank[crtc].last != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); |
136 | 134 | ||
137 | if (!count) | 135 | if (!count) |
138 | vblrc = 0; | 136 | vblrc = 0; |
@@ -140,7 +138,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
140 | /* Compute time difference to stored timestamp of last vblank | 138 | /* Compute time difference to stored timestamp of last vblank |
141 | * as updated by last invocation of drm_handle_vblank() in vblank irq. | 139 | * as updated by last invocation of drm_handle_vblank() in vblank irq. |
142 | */ | 140 | */ |
143 | vblcount = atomic_read(&dev->_vblank_count[crtc]); | 141 | vblcount = atomic_read(&dev->vblank[crtc].count); |
144 | diff_ns = timeval_to_ns(&tvblank) - | 142 | diff_ns = timeval_to_ns(&tvblank) - |
145 | timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); | 143 | timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); |
146 | 144 | ||
@@ -157,7 +155,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
157 | * hope for the best. | 155 | * hope for the best. |
158 | */ | 156 | */ |
159 | if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { | 157 | if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { |
160 | atomic_inc(&dev->_vblank_count[crtc]); | 158 | atomic_inc(&dev->vblank[crtc].count); |
161 | smp_mb__after_atomic_inc(); | 159 | smp_mb__after_atomic_inc(); |
162 | } | 160 | } |
163 | 161 | ||
@@ -178,8 +176,8 @@ static void vblank_disable_fn(unsigned long arg) | |||
178 | 176 | ||
179 | for (i = 0; i < dev->num_crtcs; i++) { | 177 | for (i = 0; i < dev->num_crtcs; i++) { |
180 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 178 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
181 | if (atomic_read(&dev->vblank_refcount[i]) == 0 && | 179 | if (atomic_read(&dev->vblank[i].refcount) == 0 && |
182 | dev->vblank_enabled[i]) { | 180 | dev->vblank[i].enabled) { |
183 | DRM_DEBUG("disabling vblank on crtc %d\n", i); | 181 | DRM_DEBUG("disabling vblank on crtc %d\n", i); |
184 | vblank_disable_and_save(dev, i); | 182 | vblank_disable_and_save(dev, i); |
185 | } | 183 | } |
@@ -197,14 +195,7 @@ void drm_vblank_cleanup(struct drm_device *dev) | |||
197 | 195 | ||
198 | vblank_disable_fn((unsigned long)dev); | 196 | vblank_disable_fn((unsigned long)dev); |
199 | 197 | ||
200 | kfree(dev->vbl_queue); | 198 | kfree(dev->vblank); |
201 | kfree(dev->_vblank_count); | ||
202 | kfree(dev->vblank_refcount); | ||
203 | kfree(dev->vblank_enabled); | ||
204 | kfree(dev->last_vblank); | ||
205 | kfree(dev->last_vblank_wait); | ||
206 | kfree(dev->vblank_inmodeset); | ||
207 | kfree(dev->_vblank_time); | ||
208 | 199 | ||
209 | dev->num_crtcs = 0; | 200 | dev->num_crtcs = 0; |
210 | } | 201 | } |
@@ -221,42 +212,14 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) | |||
221 | 212 | ||
222 | dev->num_crtcs = num_crtcs; | 213 | dev->num_crtcs = num_crtcs; |
223 | 214 | ||
224 | dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs, | 215 | dev->vblank = kcalloc(num_crtcs, sizeof(*dev->vblank), GFP_KERNEL); |
225 | GFP_KERNEL); | 216 | if (!dev->vblank) |
226 | if (!dev->vbl_queue) | ||
227 | goto err; | 217 | goto err; |
228 | 218 | ||
229 | dev->_vblank_count = kmalloc(sizeof(atomic_t) * num_crtcs, GFP_KERNEL); | 219 | for (i = 0; i < num_crtcs; i++) |
230 | if (!dev->_vblank_count) | 220 | init_waitqueue_head(&dev->vblank[i].queue); |
231 | goto err; | ||
232 | |||
233 | dev->vblank_refcount = kmalloc(sizeof(atomic_t) * num_crtcs, | ||
234 | GFP_KERNEL); | ||
235 | if (!dev->vblank_refcount) | ||
236 | goto err; | ||
237 | |||
238 | dev->vblank_enabled = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL); | ||
239 | if (!dev->vblank_enabled) | ||
240 | goto err; | ||
241 | 221 | ||
242 | dev->last_vblank = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL); | 222 | DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); |
243 | if (!dev->last_vblank) | ||
244 | goto err; | ||
245 | |||
246 | dev->last_vblank_wait = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL); | ||
247 | if (!dev->last_vblank_wait) | ||
248 | goto err; | ||
249 | |||
250 | dev->vblank_inmodeset = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL); | ||
251 | if (!dev->vblank_inmodeset) | ||
252 | goto err; | ||
253 | |||
254 | dev->_vblank_time = kcalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE, | ||
255 | sizeof(struct timeval), GFP_KERNEL); | ||
256 | if (!dev->_vblank_time) | ||
257 | goto err; | ||
258 | |||
259 | DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n"); | ||
260 | 223 | ||
261 | /* Driver specific high-precision vblank timestamping supported? */ | 224 | /* Driver specific high-precision vblank timestamping supported? */ |
262 | if (dev->driver->get_vblank_timestamp) | 225 | if (dev->driver->get_vblank_timestamp) |
@@ -264,14 +227,8 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) | |||
264 | else | 227 | else |
265 | DRM_INFO("No driver support for vblank timestamp query.\n"); | 228 | DRM_INFO("No driver support for vblank timestamp query.\n"); |
266 | 229 | ||
267 | /* Zero per-crtc vblank stuff */ | 230 | dev->vblank_disable_allowed = false; |
268 | for (i = 0; i < num_crtcs; i++) { | ||
269 | init_waitqueue_head(&dev->vbl_queue[i]); | ||
270 | atomic_set(&dev->_vblank_count[i], 0); | ||
271 | atomic_set(&dev->vblank_refcount[i], 0); | ||
272 | } | ||
273 | 231 | ||
274 | dev->vblank_disable_allowed = 0; | ||
275 | return 0; | 232 | return 0; |
276 | 233 | ||
277 | err: | 234 | err: |
@@ -336,7 +293,7 @@ int drm_irq_install(struct drm_device *dev) | |||
336 | mutex_unlock(&dev->struct_mutex); | 293 | mutex_unlock(&dev->struct_mutex); |
337 | return -EBUSY; | 294 | return -EBUSY; |
338 | } | 295 | } |
339 | dev->irq_enabled = 1; | 296 | dev->irq_enabled = true; |
340 | mutex_unlock(&dev->struct_mutex); | 297 | mutex_unlock(&dev->struct_mutex); |
341 | 298 | ||
342 | DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); | 299 | DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); |
@@ -359,7 +316,7 @@ int drm_irq_install(struct drm_device *dev) | |||
359 | 316 | ||
360 | if (ret < 0) { | 317 | if (ret < 0) { |
361 | mutex_lock(&dev->struct_mutex); | 318 | mutex_lock(&dev->struct_mutex); |
362 | dev->irq_enabled = 0; | 319 | dev->irq_enabled = false; |
363 | mutex_unlock(&dev->struct_mutex); | 320 | mutex_unlock(&dev->struct_mutex); |
364 | return ret; | 321 | return ret; |
365 | } | 322 | } |
@@ -373,7 +330,7 @@ int drm_irq_install(struct drm_device *dev) | |||
373 | 330 | ||
374 | if (ret < 0) { | 331 | if (ret < 0) { |
375 | mutex_lock(&dev->struct_mutex); | 332 | mutex_lock(&dev->struct_mutex); |
376 | dev->irq_enabled = 0; | 333 | dev->irq_enabled = false; |
377 | mutex_unlock(&dev->struct_mutex); | 334 | mutex_unlock(&dev->struct_mutex); |
378 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 335 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
379 | vga_client_register(dev->pdev, NULL, NULL, NULL); | 336 | vga_client_register(dev->pdev, NULL, NULL, NULL); |
@@ -394,14 +351,15 @@ EXPORT_SYMBOL(drm_irq_install); | |||
394 | int drm_irq_uninstall(struct drm_device *dev) | 351 | int drm_irq_uninstall(struct drm_device *dev) |
395 | { | 352 | { |
396 | unsigned long irqflags; | 353 | unsigned long irqflags; |
397 | int irq_enabled, i; | 354 | bool irq_enabled; |
355 | int i; | ||
398 | 356 | ||
399 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) | 357 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
400 | return -EINVAL; | 358 | return -EINVAL; |
401 | 359 | ||
402 | mutex_lock(&dev->struct_mutex); | 360 | mutex_lock(&dev->struct_mutex); |
403 | irq_enabled = dev->irq_enabled; | 361 | irq_enabled = dev->irq_enabled; |
404 | dev->irq_enabled = 0; | 362 | dev->irq_enabled = false; |
405 | mutex_unlock(&dev->struct_mutex); | 363 | mutex_unlock(&dev->struct_mutex); |
406 | 364 | ||
407 | /* | 365 | /* |
@@ -410,9 +368,9 @@ int drm_irq_uninstall(struct drm_device *dev) | |||
410 | if (dev->num_crtcs) { | 368 | if (dev->num_crtcs) { |
411 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 369 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
412 | for (i = 0; i < dev->num_crtcs; i++) { | 370 | for (i = 0; i < dev->num_crtcs; i++) { |
413 | DRM_WAKEUP(&dev->vbl_queue[i]); | 371 | DRM_WAKEUP(&dev->vblank[i].queue); |
414 | dev->vblank_enabled[i] = 0; | 372 | dev->vblank[i].enabled = false; |
415 | dev->last_vblank[i] = | 373 | dev->vblank[i].last = |
416 | dev->driver->get_vblank_counter(dev, i); | 374 | dev->driver->get_vblank_counter(dev, i); |
417 | } | 375 | } |
418 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 376 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
@@ -628,24 +586,20 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, | |||
628 | * code gets preempted or delayed for some reason. | 586 | * code gets preempted or delayed for some reason. |
629 | */ | 587 | */ |
630 | for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) { | 588 | for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) { |
631 | /* Disable preemption to make it very likely to | 589 | /* |
632 | * succeed in the first iteration even on PREEMPT_RT kernel. | 590 | * Get vertical and horizontal scanout position vpos, hpos, |
591 | * and bounding timestamps stime, etime, pre/post query. | ||
633 | */ | 592 | */ |
634 | preempt_disable(); | 593 | vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, |
594 | &hpos, &stime, &etime); | ||
635 | 595 | ||
636 | /* Get system timestamp before query. */ | 596 | /* |
637 | stime = ktime_get(); | 597 | * Get correction for CLOCK_MONOTONIC -> CLOCK_REALTIME if |
638 | 598 | * CLOCK_REALTIME is requested. | |
639 | /* Get vertical and horizontal scanout pos. vpos, hpos. */ | 599 | */ |
640 | vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos); | ||
641 | |||
642 | /* Get system timestamp after query. */ | ||
643 | etime = ktime_get(); | ||
644 | if (!drm_timestamp_monotonic) | 600 | if (!drm_timestamp_monotonic) |
645 | mono_time_offset = ktime_get_monotonic_offset(); | 601 | mono_time_offset = ktime_get_monotonic_offset(); |
646 | 602 | ||
647 | preempt_enable(); | ||
648 | |||
649 | /* Return as no-op if scanout query unsupported or failed. */ | 603 | /* Return as no-op if scanout query unsupported or failed. */ |
650 | if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { | 604 | if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { |
651 | DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n", | 605 | DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n", |
@@ -653,6 +607,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, | |||
653 | return -EIO; | 607 | return -EIO; |
654 | } | 608 | } |
655 | 609 | ||
610 | /* Compute uncertainty in timestamp of scanout position query. */ | ||
656 | duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime); | 611 | duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime); |
657 | 612 | ||
658 | /* Accept result with < max_error nsecs timing uncertainty. */ | 613 | /* Accept result with < max_error nsecs timing uncertainty. */ |
@@ -795,7 +750,7 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp); | |||
795 | */ | 750 | */ |
796 | u32 drm_vblank_count(struct drm_device *dev, int crtc) | 751 | u32 drm_vblank_count(struct drm_device *dev, int crtc) |
797 | { | 752 | { |
798 | return atomic_read(&dev->_vblank_count[crtc]); | 753 | return atomic_read(&dev->vblank[crtc].count); |
799 | } | 754 | } |
800 | EXPORT_SYMBOL(drm_vblank_count); | 755 | EXPORT_SYMBOL(drm_vblank_count); |
801 | 756 | ||
@@ -824,10 +779,10 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, | |||
824 | * a seqlock. | 779 | * a seqlock. |
825 | */ | 780 | */ |
826 | do { | 781 | do { |
827 | cur_vblank = atomic_read(&dev->_vblank_count[crtc]); | 782 | cur_vblank = atomic_read(&dev->vblank[crtc].count); |
828 | *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); | 783 | *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); |
829 | smp_rmb(); | 784 | smp_rmb(); |
830 | } while (cur_vblank != atomic_read(&dev->_vblank_count[crtc])); | 785 | } while (cur_vblank != atomic_read(&dev->vblank[crtc].count)); |
831 | 786 | ||
832 | return cur_vblank; | 787 | return cur_vblank; |
833 | } | 788 | } |
@@ -914,12 +869,12 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) | |||
914 | } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); | 869 | } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); |
915 | 870 | ||
916 | /* Deal with counter wrap */ | 871 | /* Deal with counter wrap */ |
917 | diff = cur_vblank - dev->last_vblank[crtc]; | 872 | diff = cur_vblank - dev->vblank[crtc].last; |
918 | if (cur_vblank < dev->last_vblank[crtc]) { | 873 | if (cur_vblank < dev->vblank[crtc].last) { |
919 | diff += dev->max_vblank_count; | 874 | diff += dev->max_vblank_count; |
920 | 875 | ||
921 | DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", | 876 | DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", |
922 | crtc, dev->last_vblank[crtc], cur_vblank, diff); | 877 | crtc, dev->vblank[crtc].last, cur_vblank, diff); |
923 | } | 878 | } |
924 | 879 | ||
925 | DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", | 880 | DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", |
@@ -930,12 +885,12 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) | |||
930 | * reinitialize delayed at next vblank interrupt in that case. | 885 | * reinitialize delayed at next vblank interrupt in that case. |
931 | */ | 886 | */ |
932 | if (rc) { | 887 | if (rc) { |
933 | tslot = atomic_read(&dev->_vblank_count[crtc]) + diff; | 888 | tslot = atomic_read(&dev->vblank[crtc].count) + diff; |
934 | vblanktimestamp(dev, crtc, tslot) = t_vblank; | 889 | vblanktimestamp(dev, crtc, tslot) = t_vblank; |
935 | } | 890 | } |
936 | 891 | ||
937 | smp_mb__before_atomic_inc(); | 892 | smp_mb__before_atomic_inc(); |
938 | atomic_add(diff, &dev->_vblank_count[crtc]); | 893 | atomic_add(diff, &dev->vblank[crtc].count); |
939 | smp_mb__after_atomic_inc(); | 894 | smp_mb__after_atomic_inc(); |
940 | } | 895 | } |
941 | 896 | ||
@@ -957,9 +912,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc) | |||
957 | 912 | ||
958 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 913 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
959 | /* Going from 0->1 means we have to enable interrupts again */ | 914 | /* Going from 0->1 means we have to enable interrupts again */ |
960 | if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { | 915 | if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) { |
961 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); | 916 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); |
962 | if (!dev->vblank_enabled[crtc]) { | 917 | if (!dev->vblank[crtc].enabled) { |
963 | /* Enable vblank irqs under vblank_time_lock protection. | 918 | /* Enable vblank irqs under vblank_time_lock protection. |
964 | * All vblank count & timestamp updates are held off | 919 | * All vblank count & timestamp updates are held off |
965 | * until we are done reinitializing master counter and | 920 | * until we are done reinitializing master counter and |
@@ -970,16 +925,16 @@ int drm_vblank_get(struct drm_device *dev, int crtc) | |||
970 | DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", | 925 | DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", |
971 | crtc, ret); | 926 | crtc, ret); |
972 | if (ret) | 927 | if (ret) |
973 | atomic_dec(&dev->vblank_refcount[crtc]); | 928 | atomic_dec(&dev->vblank[crtc].refcount); |
974 | else { | 929 | else { |
975 | dev->vblank_enabled[crtc] = 1; | 930 | dev->vblank[crtc].enabled = true; |
976 | drm_update_vblank_count(dev, crtc); | 931 | drm_update_vblank_count(dev, crtc); |
977 | } | 932 | } |
978 | } | 933 | } |
979 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); | 934 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); |
980 | } else { | 935 | } else { |
981 | if (!dev->vblank_enabled[crtc]) { | 936 | if (!dev->vblank[crtc].enabled) { |
982 | atomic_dec(&dev->vblank_refcount[crtc]); | 937 | atomic_dec(&dev->vblank[crtc].refcount); |
983 | ret = -EINVAL; | 938 | ret = -EINVAL; |
984 | } | 939 | } |
985 | } | 940 | } |
@@ -999,10 +954,10 @@ EXPORT_SYMBOL(drm_vblank_get); | |||
999 | */ | 954 | */ |
1000 | void drm_vblank_put(struct drm_device *dev, int crtc) | 955 | void drm_vblank_put(struct drm_device *dev, int crtc) |
1001 | { | 956 | { |
1002 | BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0); | 957 | BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0); |
1003 | 958 | ||
1004 | /* Last user schedules interrupt disable */ | 959 | /* Last user schedules interrupt disable */ |
1005 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) && | 960 | if (atomic_dec_and_test(&dev->vblank[crtc].refcount) && |
1006 | (drm_vblank_offdelay > 0)) | 961 | (drm_vblank_offdelay > 0)) |
1007 | mod_timer(&dev->vblank_disable_timer, | 962 | mod_timer(&dev->vblank_disable_timer, |
1008 | jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); | 963 | jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); |
@@ -1025,7 +980,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc) | |||
1025 | 980 | ||
1026 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 981 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
1027 | vblank_disable_and_save(dev, crtc); | 982 | vblank_disable_and_save(dev, crtc); |
1028 | DRM_WAKEUP(&dev->vbl_queue[crtc]); | 983 | DRM_WAKEUP(&dev->vblank[crtc].queue); |
1029 | 984 | ||
1030 | /* Send any queued vblank events, lest the natives grow disquiet */ | 985 | /* Send any queued vblank events, lest the natives grow disquiet */ |
1031 | seq = drm_vblank_count_and_time(dev, crtc, &now); | 986 | seq = drm_vblank_count_and_time(dev, crtc, &now); |
@@ -1067,10 +1022,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) | |||
1067 | * to avoid corrupting the count if multiple, mismatch calls occur), | 1022 | * to avoid corrupting the count if multiple, mismatch calls occur), |
1068 | * so that interrupts remain enabled in the interim. | 1023 | * so that interrupts remain enabled in the interim. |
1069 | */ | 1024 | */ |
1070 | if (!dev->vblank_inmodeset[crtc]) { | 1025 | if (!dev->vblank[crtc].inmodeset) { |
1071 | dev->vblank_inmodeset[crtc] = 0x1; | 1026 | dev->vblank[crtc].inmodeset = 0x1; |
1072 | if (drm_vblank_get(dev, crtc) == 0) | 1027 | if (drm_vblank_get(dev, crtc) == 0) |
1073 | dev->vblank_inmodeset[crtc] |= 0x2; | 1028 | dev->vblank[crtc].inmodeset |= 0x2; |
1074 | } | 1029 | } |
1075 | } | 1030 | } |
1076 | EXPORT_SYMBOL(drm_vblank_pre_modeset); | 1031 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
@@ -1083,15 +1038,15 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) | |||
1083 | if (!dev->num_crtcs) | 1038 | if (!dev->num_crtcs) |
1084 | return; | 1039 | return; |
1085 | 1040 | ||
1086 | if (dev->vblank_inmodeset[crtc]) { | 1041 | if (dev->vblank[crtc].inmodeset) { |
1087 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 1042 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
1088 | dev->vblank_disable_allowed = 1; | 1043 | dev->vblank_disable_allowed = true; |
1089 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 1044 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
1090 | 1045 | ||
1091 | if (dev->vblank_inmodeset[crtc] & 0x2) | 1046 | if (dev->vblank[crtc].inmodeset & 0x2) |
1092 | drm_vblank_put(dev, crtc); | 1047 | drm_vblank_put(dev, crtc); |
1093 | 1048 | ||
1094 | dev->vblank_inmodeset[crtc] = 0; | 1049 | dev->vblank[crtc].inmodeset = 0; |
1095 | } | 1050 | } |
1096 | } | 1051 | } |
1097 | EXPORT_SYMBOL(drm_vblank_post_modeset); | 1052 | EXPORT_SYMBOL(drm_vblank_post_modeset); |
@@ -1288,8 +1243,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data, | |||
1288 | 1243 | ||
1289 | DRM_DEBUG("waiting on vblank count %d, crtc %d\n", | 1244 | DRM_DEBUG("waiting on vblank count %d, crtc %d\n", |
1290 | vblwait->request.sequence, crtc); | 1245 | vblwait->request.sequence, crtc); |
1291 | dev->last_vblank_wait[crtc] = vblwait->request.sequence; | 1246 | dev->vblank[crtc].last_wait = vblwait->request.sequence; |
1292 | DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, | 1247 | DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ, |
1293 | (((drm_vblank_count(dev, crtc) - | 1248 | (((drm_vblank_count(dev, crtc) - |
1294 | vblwait->request.sequence) <= (1 << 23)) || | 1249 | vblwait->request.sequence) <= (1 << 23)) || |
1295 | !dev->irq_enabled)); | 1250 | !dev->irq_enabled)); |
@@ -1367,7 +1322,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) | |||
1367 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); | 1322 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); |
1368 | 1323 | ||
1369 | /* Vblank irq handling disabled. Nothing to do. */ | 1324 | /* Vblank irq handling disabled. Nothing to do. */ |
1370 | if (!dev->vblank_enabled[crtc]) { | 1325 | if (!dev->vblank[crtc].enabled) { |
1371 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); | 1326 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); |
1372 | return false; | 1327 | return false; |
1373 | } | 1328 | } |
@@ -1377,7 +1332,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) | |||
1377 | */ | 1332 | */ |
1378 | 1333 | ||
1379 | /* Get current timestamp and count. */ | 1334 | /* Get current timestamp and count. */ |
1380 | vblcount = atomic_read(&dev->_vblank_count[crtc]); | 1335 | vblcount = atomic_read(&dev->vblank[crtc].count); |
1381 | drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); | 1336 | drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); |
1382 | 1337 | ||
1383 | /* Compute time difference to timestamp of last vblank */ | 1338 | /* Compute time difference to timestamp of last vblank */ |
@@ -1401,14 +1356,14 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) | |||
1401 | * the timestamp computed above. | 1356 | * the timestamp computed above. |
1402 | */ | 1357 | */ |
1403 | smp_mb__before_atomic_inc(); | 1358 | smp_mb__before_atomic_inc(); |
1404 | atomic_inc(&dev->_vblank_count[crtc]); | 1359 | atomic_inc(&dev->vblank[crtc].count); |
1405 | smp_mb__after_atomic_inc(); | 1360 | smp_mb__after_atomic_inc(); |
1406 | } else { | 1361 | } else { |
1407 | DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", | 1362 | DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", |
1408 | crtc, (int) diff_ns); | 1363 | crtc, (int) diff_ns); |
1409 | } | 1364 | } |
1410 | 1365 | ||
1411 | DRM_WAKEUP(&dev->vbl_queue[crtc]); | 1366 | DRM_WAKEUP(&dev->vblank[crtc].queue); |
1412 | drm_handle_vblank_events(dev, crtc); | 1367 | drm_handle_vblank_events(dev, crtc); |
1413 | 1368 | ||
1414 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); | 1369 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); |