aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMika Kuoppala <mika.kuoppala@linux.intel.com>2013-12-10 10:02:43 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-12-12 09:27:21 -0500
commit47e9766df0298739aab87c9874a21feb71560953 (patch)
treed1ffa8dcd2c87573f61b340565483b67d914ed28 /drivers
parentf9dcb0dfee98406c9c64e1aad10af427d644b78f (diff)
drm/i915: Fix timeout with missed interrupts in __wait_seqno
Commit 094f9a54e355 ("drm/i915: Fix __wait_seqno to use true infinite timeouts") added support for __wait_seqno to detect missing interrupts and go around them by polling. As there is also timeout detection in __wait_seqno, the polling and timeout detection were done with the same timer. When there has been missed interrupts and polling is needed, the timer is set to trigger in (now + 1) jiffies in future, instead of the caller specified timeout. Now when io_schedule() returns, we calculate the jiffies left to timeout using the timer expiration value. As the current jiffies is now bound to be always equal or greater than the expiration value, the timeout_jiffies will become zero or negative and we return -ETIME to caller even tho the timeout was never reached. Fix this by decoupling timeout calculation from timer expiration. v2: Commit message with some sense in it (Chris Wilson) v3: add parenthesis on timeout_expire calculation v4: don't read jiffies without timeout (Chris Wilson) Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c14
1 files changed, 6 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index df83fec174e9..279387a2fef5 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1017,7 +1017,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
1017 drm_i915_private_t *dev_priv = ring->dev->dev_private; 1017 drm_i915_private_t *dev_priv = ring->dev->dev_private;
1018 struct timespec before, now; 1018 struct timespec before, now;
1019 DEFINE_WAIT(wait); 1019 DEFINE_WAIT(wait);
1020 long timeout_jiffies; 1020 unsigned long timeout_expire;
1021 int ret; 1021 int ret;
1022 1022
1023 WARN(dev_priv->pc8.irqs_disabled, "IRQs disabled\n"); 1023 WARN(dev_priv->pc8.irqs_disabled, "IRQs disabled\n");
@@ -1025,7 +1025,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
1025 if (i915_seqno_passed(ring->get_seqno(ring, true), seqno)) 1025 if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
1026 return 0; 1026 return 0;
1027 1027
1028 timeout_jiffies = timeout ? timespec_to_jiffies_timeout(timeout) : 1; 1028 timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0;
1029 1029
1030 if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) { 1030 if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) {
1031 gen6_rps_boost(dev_priv); 1031 gen6_rps_boost(dev_priv);
@@ -1044,7 +1044,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
1044 getrawmonotonic(&before); 1044 getrawmonotonic(&before);
1045 for (;;) { 1045 for (;;) {
1046 struct timer_list timer; 1046 struct timer_list timer;
1047 unsigned long expire;
1048 1047
1049 prepare_to_wait(&ring->irq_queue, &wait, 1048 prepare_to_wait(&ring->irq_queue, &wait,
1050 interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 1049 interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
@@ -1070,23 +1069,22 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
1070 break; 1069 break;
1071 } 1070 }
1072 1071
1073 if (timeout_jiffies <= 0) { 1072 if (timeout && time_after_eq(jiffies, timeout_expire)) {
1074 ret = -ETIME; 1073 ret = -ETIME;
1075 break; 1074 break;
1076 } 1075 }
1077 1076
1078 timer.function = NULL; 1077 timer.function = NULL;
1079 if (timeout || missed_irq(dev_priv, ring)) { 1078 if (timeout || missed_irq(dev_priv, ring)) {
1079 unsigned long expire;
1080
1080 setup_timer_on_stack(&timer, fake_irq, (unsigned long)current); 1081 setup_timer_on_stack(&timer, fake_irq, (unsigned long)current);
1081 expire = jiffies + (missed_irq(dev_priv, ring) ? 1: timeout_jiffies); 1082 expire = missed_irq(dev_priv, ring) ? jiffies + 1 : timeout_expire;
1082 mod_timer(&timer, expire); 1083 mod_timer(&timer, expire);
1083 } 1084 }
1084 1085
1085 io_schedule(); 1086 io_schedule();
1086 1087
1087 if (timeout)
1088 timeout_jiffies = expire - jiffies;
1089
1090 if (timer.function) { 1088 if (timer.function) {
1091 del_singleshot_timer_sync(&timer); 1089 del_singleshot_timer_sync(&timer);
1092 destroy_timer_on_stack(&timer); 1090 destroy_timer_on_stack(&timer);