aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-09-12 05:04:53 -0400
committerDave Airlie <airlied@redhat.com>2014-09-12 05:04:53 -0400
commitedbaae5a5cab89de0e64b8c03ebd9a8d5d266550 (patch)
tree97844f26ad675a37a74c70ea715f42b891827fa4 /drivers/gpu/drm/drm_irq.c
parenta9d6dd2554e35c0213382fff19f5dbf151707955 (diff)
parent336879b1da97fffc097f77c6d6f818660f2826f0 (diff)
Merge tag 'topic/vblank-rework-2014-09-12' of git://anongit.freedesktop.org/drm-intel into drm-next
So updated vblank-rework pull request, now with the polish that Mario requested applied (and reviewed by him). Also with backmerge like you've requested for easier merging. The neat thing this finally allows is to immediately disable the vblank interrupt on the last drm_vblank_put if the hardware has perfectly accurate vblank counter and timestamp readout support. On i915 that required piles of small adjustements from Ville since depending upon the platform and port the vblank happens at different scanout lines. Of course this is fully opt-in and per-device (we need that since gen2 doesn't have a hw vblank counter). * tag 'topic/vblank-rework-2014-09-12' of git://anongit.freedesktop.org/drm-intel: (22 commits) drm: Clarify vblank ts/scanoutpos sampling #defines drm: Simplify return value of drm_get_last_vbltimestamp drm: Only update final vblank count when precise ts is available drm: Really never disable vblank irqs for offdelay==0 drm: Use vblank_disable_and_save in drm_vblank_cleanup() drm: Remove drm_vblank_cleanup from drm_vblank_init error path. drm: Store the vblank timestamp when adjusting the counter during disable drm: Fix confusing debug message in drm_update_vblank_count() drm/i915: Update scanline_offset only for active crtcs drm: Kick start vblank interrupts at drm_vblank_on() drm/i915: Opt out of vblank disable timer on >gen2 drm: Add dev->vblank_disable_immediate flag drm: Disable vblank interrupt immediately when drm_vblank_offdelay<0 drm: Fix race between drm_vblank_off() and drm_queue_vblank_event() drm: Fix deadlock between event_lock and vbl_lock/vblank_time_lock drm: Reduce the amount of dev->vblank[crtc] in the code drm: Avoid random vblank counter jumps if the hardware counter has been reset drm: Have the vblank counter account for the time between vblank irq disable and drm_vblank_off() drm: Move drm_update_vblank_count() drm: Don't clear vblank timestamps when vblank interrupt is disabled ...
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r--drivers/gpu/drm/drm_irq.c379
1 files changed, 239 insertions, 140 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 5708c056fa1b..034297640b48 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -55,12 +55,74 @@
55 */ 55 */
56#define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 56#define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
57 57
58/* 58static bool
59 * Clear vblank timestamp buffer for a crtc. 59drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
60 struct timeval *tvblank, unsigned flags);
61
62/**
63 * drm_update_vblank_count - update the master vblank counter
64 * @dev: DRM device
65 * @crtc: counter to update
66 *
67 * Call back into the driver to update the appropriate vblank counter
68 * (specified by @crtc). Deal with wraparound, if it occurred, and
69 * update the last read value so we can deal with wraparound on the next
70 * call if necessary.
71 *
72 * Only necessary when going from off->on, to account for frames we
73 * didn't get an interrupt for.
74 *
75 * Note: caller must hold dev->vbl_lock since this reads & writes
76 * device vblank fields.
60 */ 77 */
61static void clear_vblank_timestamps(struct drm_device *dev, int crtc) 78static void drm_update_vblank_count(struct drm_device *dev, int crtc)
62{ 79{
63 memset(dev->vblank[crtc].time, 0, sizeof(dev->vblank[crtc].time)); 80 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
81 u32 cur_vblank, diff, tslot;
82 bool rc;
83 struct timeval t_vblank;
84
85 /*
86 * Interrupts were disabled prior to this call, so deal with counter
87 * wrap if needed.
88 * NOTE! It's possible we lost a full dev->max_vblank_count events
89 * here if the register is small or we had vblank interrupts off for
90 * a long time.
91 *
92 * We repeat the hardware vblank counter & timestamp query until
93 * we get consistent results. This to prevent races between gpu
94 * updating its hardware counter while we are retrieving the
95 * corresponding vblank timestamp.
96 */
97 do {
98 cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
99 rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0);
100 } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc));
101
102 /* Deal with counter wrap */
103 diff = cur_vblank - vblank->last;
104 if (cur_vblank < vblank->last) {
105 diff += dev->max_vblank_count;
106
107 DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
108 crtc, vblank->last, cur_vblank, diff);
109 }
110
111 DRM_DEBUG("updating vblank count on crtc %d, missed %d\n",
112 crtc, diff);
113
114 /* Reinitialize corresponding vblank timestamp if high-precision query
115 * available. Skip this step if query unsupported or failed. Will
116 * reinitialize delayed at next vblank interrupt in that case.
117 */
118 if (rc) {
119 tslot = atomic_read(&vblank->count) + diff;
120 vblanktimestamp(dev, crtc, tslot) = t_vblank;
121 }
122
123 smp_mb__before_atomic();
124 atomic_add(diff, &vblank->count);
125 smp_mb__after_atomic();
64} 126}
65 127
66/* 128/*
@@ -71,10 +133,11 @@ static void clear_vblank_timestamps(struct drm_device *dev, int crtc)
71 */ 133 */
72static void vblank_disable_and_save(struct drm_device *dev, int crtc) 134static void vblank_disable_and_save(struct drm_device *dev, int crtc)
73{ 135{
136 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
74 unsigned long irqflags; 137 unsigned long irqflags;
75 u32 vblcount; 138 u32 vblcount;
76 s64 diff_ns; 139 s64 diff_ns;
77 int vblrc; 140 bool vblrc;
78 struct timeval tvblank; 141 struct timeval tvblank;
79 int count = DRM_TIMESTAMP_MAXRETRIES; 142 int count = DRM_TIMESTAMP_MAXRETRIES;
80 143
@@ -84,8 +147,28 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
84 */ 147 */
85 spin_lock_irqsave(&dev->vblank_time_lock, irqflags); 148 spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
86 149
150 /*
151 * If the vblank interrupt was already disbled update the count
152 * and timestamp to maintain the appearance that the counter
153 * has been ticking all along until this time. This makes the
154 * count account for the entire time between drm_vblank_on() and
155 * drm_vblank_off().
156 *
157 * But only do this if precise vblank timestamps are available.
158 * Otherwise we might read a totally bogus timestamp since drivers
159 * lacking precise timestamp support rely upon sampling the system clock
160 * at vblank interrupt time. Which obviously won't work out well if the
161 * vblank interrupt is disabled.
162 */
163 if (!vblank->enabled &&
164 drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0)) {
165 drm_update_vblank_count(dev, crtc);
166 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
167 return;
168 }
169
87 dev->driver->disable_vblank(dev, crtc); 170 dev->driver->disable_vblank(dev, crtc);
88 dev->vblank[crtc].enabled = false; 171 vblank->enabled = false;
89 172
90 /* No further vblank irq's will be processed after 173 /* No further vblank irq's will be processed after
91 * this point. Get current hardware vblank count and 174 * this point. Get current hardware vblank count and
@@ -100,9 +183,9 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
100 * delayed gpu counter increment. 183 * delayed gpu counter increment.
101 */ 184 */
102 do { 185 do {
103 dev->vblank[crtc].last = dev->driver->get_vblank_counter(dev, crtc); 186 vblank->last = dev->driver->get_vblank_counter(dev, crtc);
104 vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); 187 vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0);
105 } while (dev->vblank[crtc].last != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); 188 } while (vblank->last != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc);
106 189
107 if (!count) 190 if (!count)
108 vblrc = 0; 191 vblrc = 0;
@@ -110,7 +193,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
110 /* Compute time difference to stored timestamp of last vblank 193 /* Compute time difference to stored timestamp of last vblank
111 * as updated by last invocation of drm_handle_vblank() in vblank irq. 194 * as updated by last invocation of drm_handle_vblank() in vblank irq.
112 */ 195 */
113 vblcount = atomic_read(&dev->vblank[crtc].count); 196 vblcount = atomic_read(&vblank->count);
114 diff_ns = timeval_to_ns(&tvblank) - 197 diff_ns = timeval_to_ns(&tvblank) -
115 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); 198 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
116 199
@@ -126,14 +209,18 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
126 * available. In that case we can't account for this and just 209 * available. In that case we can't account for this and just
127 * hope for the best. 210 * hope for the best.
128 */ 211 */
129 if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { 212 if (vblrc && (abs64(diff_ns) > 1000000)) {
130 atomic_inc(&dev->vblank[crtc].count); 213 /* Store new timestamp in ringbuffer. */
214 vblanktimestamp(dev, crtc, vblcount + 1) = tvblank;
215
216 /* Increment cooked vblank count. This also atomically commits
217 * the timestamp computed above.
218 */
219 smp_mb__before_atomic();
220 atomic_inc(&vblank->count);
131 smp_mb__after_atomic(); 221 smp_mb__after_atomic();
132 } 222 }
133 223
134 /* Invalidate all timestamps while vblank irq's are off. */
135 clear_vblank_timestamps(dev, crtc);
136
137 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); 224 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
138} 225}
139 226
@@ -164,14 +251,20 @@ static void vblank_disable_fn(unsigned long arg)
164void drm_vblank_cleanup(struct drm_device *dev) 251void drm_vblank_cleanup(struct drm_device *dev)
165{ 252{
166 int crtc; 253 int crtc;
254 unsigned long irqflags;
167 255
168 /* Bail if the driver didn't call drm_vblank_init() */ 256 /* Bail if the driver didn't call drm_vblank_init() */
169 if (dev->num_crtcs == 0) 257 if (dev->num_crtcs == 0)
170 return; 258 return;
171 259
172 for (crtc = 0; crtc < dev->num_crtcs; crtc++) { 260 for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
173 del_timer_sync(&dev->vblank[crtc].disable_timer); 261 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
174 vblank_disable_fn((unsigned long)&dev->vblank[crtc]); 262
263 del_timer_sync(&vblank->disable_timer);
264
265 spin_lock_irqsave(&dev->vbl_lock, irqflags);
266 vblank_disable_and_save(dev, crtc);
267 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
175 } 268 }
176 269
177 kfree(dev->vblank); 270 kfree(dev->vblank);
@@ -204,11 +297,13 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
204 goto err; 297 goto err;
205 298
206 for (i = 0; i < num_crtcs; i++) { 299 for (i = 0; i < num_crtcs; i++) {
207 dev->vblank[i].dev = dev; 300 struct drm_vblank_crtc *vblank = &dev->vblank[i];
208 dev->vblank[i].crtc = i; 301
209 init_waitqueue_head(&dev->vblank[i].queue); 302 vblank->dev = dev;
210 setup_timer(&dev->vblank[i].disable_timer, vblank_disable_fn, 303 vblank->crtc = i;
211 (unsigned long)&dev->vblank[i]); 304 init_waitqueue_head(&vblank->queue);
305 setup_timer(&vblank->disable_timer, vblank_disable_fn,
306 (unsigned long)vblank);
212 } 307 }
213 308
214 DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); 309 DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n");
@@ -224,7 +319,7 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
224 return 0; 319 return 0;
225 320
226err: 321err:
227 drm_vblank_cleanup(dev); 322 dev->num_crtcs = 0;
228 return ret; 323 return ret;
229} 324}
230EXPORT_SYMBOL(drm_vblank_init); 325EXPORT_SYMBOL(drm_vblank_init);
@@ -360,9 +455,11 @@ int drm_irq_uninstall(struct drm_device *dev)
360 if (dev->num_crtcs) { 455 if (dev->num_crtcs) {
361 spin_lock_irqsave(&dev->vbl_lock, irqflags); 456 spin_lock_irqsave(&dev->vbl_lock, irqflags);
362 for (i = 0; i < dev->num_crtcs; i++) { 457 for (i = 0; i < dev->num_crtcs; i++) {
363 wake_up(&dev->vblank[i].queue); 458 struct drm_vblank_crtc *vblank = &dev->vblank[i];
364 dev->vblank[i].enabled = false; 459
365 dev->vblank[i].last = 460 wake_up(&vblank->queue);
461 vblank->enabled = false;
462 vblank->last =
366 dev->driver->get_vblank_counter(dev, i); 463 dev->driver->get_vblank_counter(dev, i);
367 } 464 }
368 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 465 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -617,7 +714,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
617 * within vblank area, counting down the number of lines until 714 * within vblank area, counting down the number of lines until
618 * start of scanout. 715 * start of scanout.
619 */ 716 */
620 invbl = vbl_status & DRM_SCANOUTPOS_INVBL; 717 invbl = vbl_status & DRM_SCANOUTPOS_IN_VBLANK;
621 718
622 /* Convert scanout position into elapsed time at raw_time query 719 /* Convert scanout position into elapsed time at raw_time query
623 * since start of scanout at first display scanline. delta_ns 720 * since start of scanout at first display scanline. delta_ns
@@ -647,7 +744,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
647 744
648 vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD; 745 vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD;
649 if (invbl) 746 if (invbl)
650 vbl_status |= DRM_VBLANKTIME_INVBL; 747 vbl_status |= DRM_VBLANKTIME_IN_VBLANK;
651 748
652 return vbl_status; 749 return vbl_status;
653} 750}
@@ -679,10 +776,11 @@ static struct timeval get_drm_timestamp(void)
679 * call, i.e., it isn't very precisely locked to the true vblank. 776 * call, i.e., it isn't very precisely locked to the true vblank.
680 * 777 *
681 * Returns: 778 * Returns:
682 * Non-zero if timestamp is considered to be very precise, zero otherwise. 779 * True if timestamp is considered to be very precise, false otherwise.
683 */ 780 */
684u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, 781static bool
685 struct timeval *tvblank, unsigned flags) 782drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
783 struct timeval *tvblank, unsigned flags)
686{ 784{
687 int ret; 785 int ret;
688 786
@@ -694,7 +792,7 @@ u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
694 ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error, 792 ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error,
695 tvblank, flags); 793 tvblank, flags);
696 if (ret > 0) 794 if (ret > 0)
697 return (u32) ret; 795 return true;
698 } 796 }
699 797
700 /* GPU high precision timestamp query unsupported or failed. 798 /* GPU high precision timestamp query unsupported or failed.
@@ -702,9 +800,8 @@ u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
702 */ 800 */
703 *tvblank = get_drm_timestamp(); 801 *tvblank = get_drm_timestamp();
704 802
705 return 0; 803 return false;
706} 804}
707EXPORT_SYMBOL(drm_get_last_vbltimestamp);
708 805
709/** 806/**
710 * drm_vblank_count - retrieve "cooked" vblank counter value 807 * drm_vblank_count - retrieve "cooked" vblank counter value
@@ -720,9 +817,11 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp);
720 */ 817 */
721u32 drm_vblank_count(struct drm_device *dev, int crtc) 818u32 drm_vblank_count(struct drm_device *dev, int crtc)
722{ 819{
820 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
821
723 if (WARN_ON(crtc >= dev->num_crtcs)) 822 if (WARN_ON(crtc >= dev->num_crtcs))
724 return 0; 823 return 0;
725 return atomic_read(&dev->vblank[crtc].count); 824 return atomic_read(&vblank->count);
726} 825}
727EXPORT_SYMBOL(drm_vblank_count); 826EXPORT_SYMBOL(drm_vblank_count);
728 827
@@ -742,6 +841,7 @@ EXPORT_SYMBOL(drm_vblank_count);
742u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, 841u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
743 struct timeval *vblanktime) 842 struct timeval *vblanktime)
744{ 843{
844 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
745 u32 cur_vblank; 845 u32 cur_vblank;
746 846
747 if (WARN_ON(crtc >= dev->num_crtcs)) 847 if (WARN_ON(crtc >= dev->num_crtcs))
@@ -753,10 +853,10 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
753 * a seqlock. 853 * a seqlock.
754 */ 854 */
755 do { 855 do {
756 cur_vblank = atomic_read(&dev->vblank[crtc].count); 856 cur_vblank = atomic_read(&vblank->count);
757 *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); 857 *vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
758 smp_rmb(); 858 smp_rmb();
759 } while (cur_vblank != atomic_read(&dev->vblank[crtc].count)); 859 } while (cur_vblank != atomic_read(&vblank->count));
760 860
761 return cur_vblank; 861 return cur_vblank;
762} 862}
@@ -805,83 +905,20 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc,
805EXPORT_SYMBOL(drm_send_vblank_event); 905EXPORT_SYMBOL(drm_send_vblank_event);
806 906
807/** 907/**
808 * drm_update_vblank_count - update the master vblank counter
809 * @dev: DRM device
810 * @crtc: counter to update
811 *
812 * Call back into the driver to update the appropriate vblank counter
813 * (specified by @crtc). Deal with wraparound, if it occurred, and
814 * update the last read value so we can deal with wraparound on the next
815 * call if necessary.
816 *
817 * Only necessary when going from off->on, to account for frames we
818 * didn't get an interrupt for.
819 *
820 * Note: caller must hold dev->vbl_lock since this reads & writes
821 * device vblank fields.
822 */
823static void drm_update_vblank_count(struct drm_device *dev, int crtc)
824{
825 u32 cur_vblank, diff, tslot, rc;
826 struct timeval t_vblank;
827
828 /*
829 * Interrupts were disabled prior to this call, so deal with counter
830 * wrap if needed.
831 * NOTE! It's possible we lost a full dev->max_vblank_count events
832 * here if the register is small or we had vblank interrupts off for
833 * a long time.
834 *
835 * We repeat the hardware vblank counter & timestamp query until
836 * we get consistent results. This to prevent races between gpu
837 * updating its hardware counter while we are retrieving the
838 * corresponding vblank timestamp.
839 */
840 do {
841 cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
842 rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0);
843 } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc));
844
845 /* Deal with counter wrap */
846 diff = cur_vblank - dev->vblank[crtc].last;
847 if (cur_vblank < dev->vblank[crtc].last) {
848 diff += dev->max_vblank_count;
849
850 DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
851 crtc, dev->vblank[crtc].last, cur_vblank, diff);
852 }
853
854 DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
855 crtc, diff);
856
857 /* Reinitialize corresponding vblank timestamp if high-precision query
858 * available. Skip this step if query unsupported or failed. Will
859 * reinitialize delayed at next vblank interrupt in that case.
860 */
861 if (rc) {
862 tslot = atomic_read(&dev->vblank[crtc].count) + diff;
863 vblanktimestamp(dev, crtc, tslot) = t_vblank;
864 }
865
866 smp_mb__before_atomic();
867 atomic_add(diff, &dev->vblank[crtc].count);
868 smp_mb__after_atomic();
869}
870
871/**
872 * drm_vblank_enable - enable the vblank interrupt on a CRTC 908 * drm_vblank_enable - enable the vblank interrupt on a CRTC
873 * @dev: DRM device 909 * @dev: DRM device
874 * @crtc: CRTC in question 910 * @crtc: CRTC in question
875 */ 911 */
876static int drm_vblank_enable(struct drm_device *dev, int crtc) 912static int drm_vblank_enable(struct drm_device *dev, int crtc)
877{ 913{
914 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
878 int ret = 0; 915 int ret = 0;
879 916
880 assert_spin_locked(&dev->vbl_lock); 917 assert_spin_locked(&dev->vbl_lock);
881 918
882 spin_lock(&dev->vblank_time_lock); 919 spin_lock(&dev->vblank_time_lock);
883 920
884 if (!dev->vblank[crtc].enabled) { 921 if (!vblank->enabled) {
885 /* 922 /*
886 * Enable vblank irqs under vblank_time_lock protection. 923 * Enable vblank irqs under vblank_time_lock protection.
887 * All vblank count & timestamp updates are held off 924 * All vblank count & timestamp updates are held off
@@ -892,9 +929,9 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc)
892 ret = dev->driver->enable_vblank(dev, crtc); 929 ret = dev->driver->enable_vblank(dev, crtc);
893 DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); 930 DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
894 if (ret) 931 if (ret)
895 atomic_dec(&dev->vblank[crtc].refcount); 932 atomic_dec(&vblank->refcount);
896 else { 933 else {
897 dev->vblank[crtc].enabled = true; 934 vblank->enabled = true;
898 drm_update_vblank_count(dev, crtc); 935 drm_update_vblank_count(dev, crtc);
899 } 936 }
900 } 937 }
@@ -919,6 +956,7 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc)
919 */ 956 */
920int drm_vblank_get(struct drm_device *dev, int crtc) 957int drm_vblank_get(struct drm_device *dev, int crtc)
921{ 958{
959 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
922 unsigned long irqflags; 960 unsigned long irqflags;
923 int ret = 0; 961 int ret = 0;
924 962
@@ -927,11 +965,11 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
927 965
928 spin_lock_irqsave(&dev->vbl_lock, irqflags); 966 spin_lock_irqsave(&dev->vbl_lock, irqflags);
929 /* Going from 0->1 means we have to enable interrupts again */ 967 /* Going from 0->1 means we have to enable interrupts again */
930 if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) { 968 if (atomic_add_return(1, &vblank->refcount) == 1) {
931 ret = drm_vblank_enable(dev, crtc); 969 ret = drm_vblank_enable(dev, crtc);
932 } else { 970 } else {
933 if (!dev->vblank[crtc].enabled) { 971 if (!vblank->enabled) {
934 atomic_dec(&dev->vblank[crtc].refcount); 972 atomic_dec(&vblank->refcount);
935 ret = -EINVAL; 973 ret = -EINVAL;
936 } 974 }
937 } 975 }
@@ -971,16 +1009,23 @@ EXPORT_SYMBOL(drm_crtc_vblank_get);
971 */ 1009 */
972void drm_vblank_put(struct drm_device *dev, int crtc) 1010void drm_vblank_put(struct drm_device *dev, int crtc)
973{ 1011{
974 BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0); 1012 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
1013
1014 BUG_ON(atomic_read(&vblank->refcount) == 0);
975 1015
976 if (WARN_ON(crtc >= dev->num_crtcs)) 1016 if (WARN_ON(crtc >= dev->num_crtcs))
977 return; 1017 return;
978 1018
979 /* Last user schedules interrupt disable */ 1019 /* Last user schedules interrupt disable */
980 if (atomic_dec_and_test(&dev->vblank[crtc].refcount) && 1020 if (atomic_dec_and_test(&vblank->refcount)) {
981 (drm_vblank_offdelay > 0)) 1021 if (drm_vblank_offdelay == 0)
982 mod_timer(&dev->vblank[crtc].disable_timer, 1022 return;
983 jiffies + ((drm_vblank_offdelay * HZ)/1000)); 1023 else if (dev->vblank_disable_immediate || drm_vblank_offdelay < 0)
1024 vblank_disable_fn((unsigned long)vblank);
1025 else
1026 mod_timer(&vblank->disable_timer,
1027 jiffies + ((drm_vblank_offdelay * HZ)/1000));
1028 }
984} 1029}
985EXPORT_SYMBOL(drm_vblank_put); 1030EXPORT_SYMBOL(drm_vblank_put);
986 1031
@@ -1059,6 +1104,7 @@ EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
1059 */ 1104 */
1060void drm_vblank_off(struct drm_device *dev, int crtc) 1105void drm_vblank_off(struct drm_device *dev, int crtc)
1061{ 1106{
1107 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
1062 struct drm_pending_vblank_event *e, *t; 1108 struct drm_pending_vblank_event *e, *t;
1063 struct timeval now; 1109 struct timeval now;
1064 unsigned long irqflags; 1110 unsigned long irqflags;
@@ -1067,14 +1113,25 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
1067 if (WARN_ON(crtc >= dev->num_crtcs)) 1113 if (WARN_ON(crtc >= dev->num_crtcs))
1068 return; 1114 return;
1069 1115
1070 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1116 spin_lock_irqsave(&dev->event_lock, irqflags);
1117
1118 spin_lock(&dev->vbl_lock);
1071 vblank_disable_and_save(dev, crtc); 1119 vblank_disable_and_save(dev, crtc);
1072 wake_up(&dev->vblank[crtc].queue); 1120 wake_up(&vblank->queue);
1121
1122 /*
1123 * Prevent subsequent drm_vblank_get() from re-enabling
1124 * the vblank interrupt by bumping the refcount.
1125 */
1126 if (!vblank->inmodeset) {
1127 atomic_inc(&vblank->refcount);
1128 vblank->inmodeset = 1;
1129 }
1130 spin_unlock(&dev->vbl_lock);
1073 1131
1074 /* Send any queued vblank events, lest the natives grow disquiet */ 1132 /* Send any queued vblank events, lest the natives grow disquiet */
1075 seq = drm_vblank_count_and_time(dev, crtc, &now); 1133 seq = drm_vblank_count_and_time(dev, crtc, &now);
1076 1134
1077 spin_lock(&dev->event_lock);
1078 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { 1135 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
1079 if (e->pipe != crtc) 1136 if (e->pipe != crtc)
1080 continue; 1137 continue;
@@ -1085,9 +1142,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
1085 drm_vblank_put(dev, e->pipe); 1142 drm_vblank_put(dev, e->pipe);
1086 send_vblank_event(dev, e, seq, &now); 1143 send_vblank_event(dev, e, seq, &now);
1087 } 1144 }
1088 spin_unlock(&dev->event_lock); 1145 spin_unlock_irqrestore(&dev->event_lock, irqflags);
1089
1090 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
1091} 1146}
1092EXPORT_SYMBOL(drm_vblank_off); 1147EXPORT_SYMBOL(drm_vblank_off);
1093 1148
@@ -1124,14 +1179,35 @@ EXPORT_SYMBOL(drm_crtc_vblank_off);
1124 */ 1179 */
1125void drm_vblank_on(struct drm_device *dev, int crtc) 1180void drm_vblank_on(struct drm_device *dev, int crtc)
1126{ 1181{
1182 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
1127 unsigned long irqflags; 1183 unsigned long irqflags;
1128 1184
1129 if (WARN_ON(crtc >= dev->num_crtcs)) 1185 if (WARN_ON(crtc >= dev->num_crtcs))
1130 return; 1186 return;
1131 1187
1132 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1188 spin_lock_irqsave(&dev->vbl_lock, irqflags);
1133 /* re-enable interrupts if there's are users left */ 1189 /* Drop our private "prevent drm_vblank_get" refcount */
1134 if (atomic_read(&dev->vblank[crtc].refcount) != 0) 1190 if (vblank->inmodeset) {
1191 atomic_dec(&vblank->refcount);
1192 vblank->inmodeset = 0;
1193 }
1194
1195 /*
1196 * sample the current counter to avoid random jumps
1197 * when drm_vblank_enable() applies the diff
1198 *
1199 * -1 to make sure user will never see the same
1200 * vblank counter value before and after a modeset
1201 */
1202 vblank->last =
1203 (dev->driver->get_vblank_counter(dev, crtc) - 1) &
1204 dev->max_vblank_count;
1205 /*
1206 * re-enable interrupts if there are users left, or the
1207 * user wishes vblank interrupts to be enabled all the time.
1208 */
1209 if (atomic_read(&vblank->refcount) != 0 ||
1210 (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0))
1135 WARN_ON(drm_vblank_enable(dev, crtc)); 1211 WARN_ON(drm_vblank_enable(dev, crtc));
1136 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 1212 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
1137} 1213}
@@ -1179,6 +1255,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_on);
1179 */ 1255 */
1180void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) 1256void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
1181{ 1257{
1258 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
1259
1182 /* vblank is not initialized (IRQ not installed ?), or has been freed */ 1260 /* vblank is not initialized (IRQ not installed ?), or has been freed */
1183 if (!dev->num_crtcs) 1261 if (!dev->num_crtcs)
1184 return; 1262 return;
@@ -1193,10 +1271,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
1193 * to avoid corrupting the count if multiple, mismatch calls occur), 1271 * to avoid corrupting the count if multiple, mismatch calls occur),
1194 * so that interrupts remain enabled in the interim. 1272 * so that interrupts remain enabled in the interim.
1195 */ 1273 */
1196 if (!dev->vblank[crtc].inmodeset) { 1274 if (!vblank->inmodeset) {
1197 dev->vblank[crtc].inmodeset = 0x1; 1275 vblank->inmodeset = 0x1;
1198 if (drm_vblank_get(dev, crtc) == 0) 1276 if (drm_vblank_get(dev, crtc) == 0)
1199 dev->vblank[crtc].inmodeset |= 0x2; 1277 vblank->inmodeset |= 0x2;
1200 } 1278 }
1201} 1279}
1202EXPORT_SYMBOL(drm_vblank_pre_modeset); 1280EXPORT_SYMBOL(drm_vblank_pre_modeset);
@@ -1211,21 +1289,22 @@ EXPORT_SYMBOL(drm_vblank_pre_modeset);
1211 */ 1289 */
1212void drm_vblank_post_modeset(struct drm_device *dev, int crtc) 1290void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
1213{ 1291{
1292 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
1214 unsigned long irqflags; 1293 unsigned long irqflags;
1215 1294
1216 /* vblank is not initialized (IRQ not installed ?), or has been freed */ 1295 /* vblank is not initialized (IRQ not installed ?), or has been freed */
1217 if (!dev->num_crtcs) 1296 if (!dev->num_crtcs)
1218 return; 1297 return;
1219 1298
1220 if (dev->vblank[crtc].inmodeset) { 1299 if (vblank->inmodeset) {
1221 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1300 spin_lock_irqsave(&dev->vbl_lock, irqflags);
1222 dev->vblank_disable_allowed = true; 1301 dev->vblank_disable_allowed = true;
1223 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 1302 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
1224 1303
1225 if (dev->vblank[crtc].inmodeset & 0x2) 1304 if (vblank->inmodeset & 0x2)
1226 drm_vblank_put(dev, crtc); 1305 drm_vblank_put(dev, crtc);
1227 1306
1228 dev->vblank[crtc].inmodeset = 0; 1307 vblank->inmodeset = 0;
1229 } 1308 }
1230} 1309}
1231EXPORT_SYMBOL(drm_vblank_post_modeset); 1310EXPORT_SYMBOL(drm_vblank_post_modeset);
@@ -1277,6 +1356,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
1277 union drm_wait_vblank *vblwait, 1356 union drm_wait_vblank *vblwait,
1278 struct drm_file *file_priv) 1357 struct drm_file *file_priv)
1279{ 1358{
1359 struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1280 struct drm_pending_vblank_event *e; 1360 struct drm_pending_vblank_event *e;
1281 struct timeval now; 1361 struct timeval now;
1282 unsigned long flags; 1362 unsigned long flags;
@@ -1300,6 +1380,18 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
1300 1380
1301 spin_lock_irqsave(&dev->event_lock, flags); 1381 spin_lock_irqsave(&dev->event_lock, flags);
1302 1382
1383 /*
1384 * drm_vblank_off() might have been called after we called
1385 * drm_vblank_get(). drm_vblank_off() holds event_lock
1386 * around the vblank disable, so no need for further locking.
1387 * The reference from drm_vblank_get() protects against
1388 * vblank disable from another source.
1389 */
1390 if (!vblank->enabled) {
1391 ret = -EINVAL;
1392 goto err_unlock;
1393 }
1394
1303 if (file_priv->event_space < sizeof e->event) { 1395 if (file_priv->event_space < sizeof e->event) {
1304 ret = -EBUSY; 1396 ret = -EBUSY;
1305 goto err_unlock; 1397 goto err_unlock;
@@ -1360,6 +1452,7 @@ err_put:
1360int drm_wait_vblank(struct drm_device *dev, void *data, 1452int drm_wait_vblank(struct drm_device *dev, void *data,
1361 struct drm_file *file_priv) 1453 struct drm_file *file_priv)
1362{ 1454{
1455 struct drm_vblank_crtc *vblank;
1363 union drm_wait_vblank *vblwait = data; 1456 union drm_wait_vblank *vblwait = data;
1364 int ret; 1457 int ret;
1365 unsigned int flags, seq, crtc, high_crtc; 1458 unsigned int flags, seq, crtc, high_crtc;
@@ -1389,6 +1482,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
1389 if (crtc >= dev->num_crtcs) 1482 if (crtc >= dev->num_crtcs)
1390 return -EINVAL; 1483 return -EINVAL;
1391 1484
1485 vblank = &dev->vblank[crtc];
1486
1392 ret = drm_vblank_get(dev, crtc); 1487 ret = drm_vblank_get(dev, crtc);
1393 if (ret) { 1488 if (ret) {
1394 DRM_DEBUG("failed to acquire vblank counter, %d\n", ret); 1489 DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
@@ -1421,11 +1516,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
1421 1516
1422 DRM_DEBUG("waiting on vblank count %d, crtc %d\n", 1517 DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
1423 vblwait->request.sequence, crtc); 1518 vblwait->request.sequence, crtc);
1424 dev->vblank[crtc].last_wait = vblwait->request.sequence; 1519 vblank->last_wait = vblwait->request.sequence;
1425 DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * HZ, 1520 DRM_WAIT_ON(ret, vblank->queue, 3 * HZ,
1426 (((drm_vblank_count(dev, crtc) - 1521 (((drm_vblank_count(dev, crtc) -
1427 vblwait->request.sequence) <= (1 << 23)) || 1522 vblwait->request.sequence) <= (1 << 23)) ||
1428 !dev->vblank[crtc].enabled || 1523 !vblank->enabled ||
1429 !dev->irq_enabled)); 1524 !dev->irq_enabled));
1430 1525
1431 if (ret != -EINTR) { 1526 if (ret != -EINTR) {
@@ -1450,12 +1545,11 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
1450{ 1545{
1451 struct drm_pending_vblank_event *e, *t; 1546 struct drm_pending_vblank_event *e, *t;
1452 struct timeval now; 1547 struct timeval now;
1453 unsigned long flags;
1454 unsigned int seq; 1548 unsigned int seq;
1455 1549
1456 seq = drm_vblank_count_and_time(dev, crtc, &now); 1550 assert_spin_locked(&dev->event_lock);
1457 1551
1458 spin_lock_irqsave(&dev->event_lock, flags); 1552 seq = drm_vblank_count_and_time(dev, crtc, &now);
1459 1553
1460 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { 1554 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
1461 if (e->pipe != crtc) 1555 if (e->pipe != crtc)
@@ -1471,8 +1565,6 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
1471 send_vblank_event(dev, e, seq, &now); 1565 send_vblank_event(dev, e, seq, &now);
1472 } 1566 }
1473 1567
1474 spin_unlock_irqrestore(&dev->event_lock, flags);
1475
1476 trace_drm_vblank_event(crtc, seq); 1568 trace_drm_vblank_event(crtc, seq);
1477} 1569}
1478 1570
@@ -1486,6 +1578,7 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
1486 */ 1578 */
1487bool drm_handle_vblank(struct drm_device *dev, int crtc) 1579bool drm_handle_vblank(struct drm_device *dev, int crtc)
1488{ 1580{
1581 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
1489 u32 vblcount; 1582 u32 vblcount;
1490 s64 diff_ns; 1583 s64 diff_ns;
1491 struct timeval tvblank; 1584 struct timeval tvblank;
@@ -1497,15 +1590,18 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
1497 if (WARN_ON(crtc >= dev->num_crtcs)) 1590 if (WARN_ON(crtc >= dev->num_crtcs))
1498 return false; 1591 return false;
1499 1592
1593 spin_lock_irqsave(&dev->event_lock, irqflags);
1594
1500 /* Need timestamp lock to prevent concurrent execution with 1595 /* Need timestamp lock to prevent concurrent execution with
1501 * vblank enable/disable, as this would cause inconsistent 1596 * vblank enable/disable, as this would cause inconsistent
1502 * or corrupted timestamps and vblank counts. 1597 * or corrupted timestamps and vblank counts.
1503 */ 1598 */
1504 spin_lock_irqsave(&dev->vblank_time_lock, irqflags); 1599 spin_lock(&dev->vblank_time_lock);
1505 1600
1506 /* Vblank irq handling disabled. Nothing to do. */ 1601 /* Vblank irq handling disabled. Nothing to do. */
1507 if (!dev->vblank[crtc].enabled) { 1602 if (!vblank->enabled) {
1508 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); 1603 spin_unlock(&dev->vblank_time_lock);
1604 spin_unlock_irqrestore(&dev->event_lock, irqflags);
1509 return false; 1605 return false;
1510 } 1606 }
1511 1607
@@ -1514,7 +1610,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
1514 */ 1610 */
1515 1611
1516 /* Get current timestamp and count. */ 1612 /* Get current timestamp and count. */
1517 vblcount = atomic_read(&dev->vblank[crtc].count); 1613 vblcount = atomic_read(&vblank->count);
1518 drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); 1614 drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ);
1519 1615
1520 /* Compute time difference to timestamp of last vblank */ 1616 /* Compute time difference to timestamp of last vblank */
@@ -1538,17 +1634,20 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
1538 * the timestamp computed above. 1634 * the timestamp computed above.
1539 */ 1635 */
1540 smp_mb__before_atomic(); 1636 smp_mb__before_atomic();
1541 atomic_inc(&dev->vblank[crtc].count); 1637 atomic_inc(&vblank->count);
1542 smp_mb__after_atomic(); 1638 smp_mb__after_atomic();
1543 } else { 1639 } else {
1544 DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", 1640 DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n",
1545 crtc, (int) diff_ns); 1641 crtc, (int) diff_ns);
1546 } 1642 }
1547 1643
1548 wake_up(&dev->vblank[crtc].queue); 1644 spin_unlock(&dev->vblank_time_lock);
1645
1646 wake_up(&vblank->queue);
1549 drm_handle_vblank_events(dev, crtc); 1647 drm_handle_vblank_events(dev, crtc);
1550 1648
1551 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); 1649 spin_unlock_irqrestore(&dev->event_lock, irqflags);
1650
1552 return true; 1651 return true;
1553} 1652}
1554EXPORT_SYMBOL(drm_handle_vblank); 1653EXPORT_SYMBOL(drm_handle_vblank);