aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2015-12-11 06:32:57 -0500
committerJani Nikula <jani.nikula@intel.com>2015-12-22 05:55:01 -0500
commite7571f7fd66c77a760338340adbe41d994fe93ac (patch)
tree2b602efe7521f2ab8ff60256ec4ff9be6a484013 /drivers/gpu
parenta59fac67d31235730378180774fdb46f5a270f1e (diff)
drm/i915: Break busywaiting for requests on pending signals
The busywait in __i915_spin_request() does not respect pending signals and so may consume the entire timeslice for the task instead of returning to userspace to handle the signal. In the worst case this could cause a delay in signal processing of 20ms, which would be a noticeable jitter in cursor tracking. If a higher resolution signal was being used, for example to provide fairness of a server timeslices between clients, we could expect to detect some unfairness between clients (i.e. some windows not updating as fast as others). This issue was noticed when inspecting a report of poor interactivity resulting from excessively high __i915_spin_request usage. Fixes regression from commit 2def4ad99befa25775dd2f714fdd4d92faec6e34 [v4.2] Author: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue Apr 7 16:20:41 2015 +0100 drm/i915: Optimistically spin for the request completion v2: Try to assess the impact of the bug Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> Cc: Jens Axboe <axboe@kernel.dk> Cc; "Rogozhkin, Dmitry V" <dmitry.v.rogozhkin@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> Cc: Eero Tamminen <eero.t.tamminen@intel.com> Cc: "Rantala, Valtteri" <valtteri.rantala@intel.com> Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/1449833608-22125-2-git-send-email-chris@chris-wilson.co.uk (cherry picked from commit 91b0c352ace9afec1fb51590c7b8bd60e0eb9fbd) Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3163518ba19a..06631e130efc 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1146,7 +1146,7 @@ static bool missed_irq(struct drm_i915_private *dev_priv,
1146 return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); 1146 return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
1147} 1147}
1148 1148
1149static int __i915_spin_request(struct drm_i915_gem_request *req) 1149static int __i915_spin_request(struct drm_i915_gem_request *req, int state)
1150{ 1150{
1151 unsigned long timeout; 1151 unsigned long timeout;
1152 1152
@@ -1158,6 +1158,9 @@ static int __i915_spin_request(struct drm_i915_gem_request *req)
1158 if (i915_gem_request_completed(req, true)) 1158 if (i915_gem_request_completed(req, true))
1159 return 0; 1159 return 0;
1160 1160
1161 if (signal_pending_state(state, current))
1162 break;
1163
1161 if (time_after_eq(jiffies, timeout)) 1164 if (time_after_eq(jiffies, timeout))
1162 break; 1165 break;
1163 1166
@@ -1197,6 +1200,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1197 struct drm_i915_private *dev_priv = dev->dev_private; 1200 struct drm_i915_private *dev_priv = dev->dev_private;
1198 const bool irq_test_in_progress = 1201 const bool irq_test_in_progress =
1199 ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring); 1202 ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
1203 int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
1200 DEFINE_WAIT(wait); 1204 DEFINE_WAIT(wait);
1201 unsigned long timeout_expire; 1205 unsigned long timeout_expire;
1202 s64 before, now; 1206 s64 before, now;
@@ -1229,7 +1233,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1229 before = ktime_get_raw_ns(); 1233 before = ktime_get_raw_ns();
1230 1234
1231 /* Optimistic spin for the next jiffie before touching IRQs */ 1235 /* Optimistic spin for the next jiffie before touching IRQs */
1232 ret = __i915_spin_request(req); 1236 ret = __i915_spin_request(req, state);
1233 if (ret == 0) 1237 if (ret == 0)
1234 goto out; 1238 goto out;
1235 1239
@@ -1241,8 +1245,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1241 for (;;) { 1245 for (;;) {
1242 struct timer_list timer; 1246 struct timer_list timer;
1243 1247
1244 prepare_to_wait(&ring->irq_queue, &wait, 1248 prepare_to_wait(&ring->irq_queue, &wait, state);
1245 interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
1246 1249
1247 /* We need to check whether any gpu reset happened in between 1250 /* We need to check whether any gpu reset happened in between
1248 * the caller grabbing the seqno and now ... */ 1251 * the caller grabbing the seqno and now ... */
@@ -1260,7 +1263,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1260 break; 1263 break;
1261 } 1264 }
1262 1265
1263 if (interruptible && signal_pending(current)) { 1266 if (signal_pending_state(state, current)) {
1264 ret = -ERESTARTSYS; 1267 ret = -ERESTARTSYS;
1265 break; 1268 break;
1266 } 1269 }