aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_breadcrumbs.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-02-27 20:58:47 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2017-02-27 21:57:19 +0000
commit8d769ea7bc16c34c9dc5143be021e943014c4cd1 (patch)
tree84b0f782b37911dcaad138f0078eecb703dfabde /drivers/gpu/drm/i915/intel_breadcrumbs.c
parentdrm/i915: Distinguish between timeout and error in sideband transactions (diff)
downloadlinux-dev-8d769ea7bc16c34c9dc5143be021e943014c4cd1.tar.xz
linux-dev-8d769ea7bc16c34c9dc5143be021e943014c4cd1.zip
drm/i915: Report both waiters and success from intel_engine_wakeup()
The two users of the return value from intel_engine_wakeup() are expecting different results. In the breadcrumbs hangcheck, we are using it to determine whether wake_up_process() detected the waiter was currently running (and if so we presume that it hasn't yet missed the interrupt). However, in the fake_irq path, we are using the return value as a check as to whether there are any waiters, and so we may incorrectly stop the fake-irq if that waiter was currently running. To handle the two different needs, return both bits of information! We uninline it from the irq path in preparation for the next patch which makes the irq hotpath special and relegates intel_engine_wakeup() to the slow fixup paths. v2: s/ret/result/ Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170227205850.2828-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/intel_breadcrumbs.c')
-rw-r--r--drivers/gpu/drm/i915/intel_breadcrumbs.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
index 027c93e34c97..c8361f350350 100644
--- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -26,6 +26,32 @@
#include "i915_drv.h"
+unsigned int intel_engine_wakeup(struct intel_engine_cs *engine)
+{
+ unsigned int result = 0;
+
+ /* Note that for this not to dangerously chase a dangling pointer,
+ * we must hold the rcu_read_lock here.
+ *
+ * Also note that tsk is likely to be in !TASK_RUNNING state so an
+ * early test for tsk->state != TASK_RUNNING before wake_up_process()
+ * is unlikely to be beneficial.
+ */
+ if (intel_engine_has_waiter(engine)) {
+ struct task_struct *tsk;
+
+ result = ENGINE_WAKEUP_WAITER;
+
+ rcu_read_lock();
+ tsk = rcu_dereference(engine->breadcrumbs.irq_seqno_bh);
+ if (tsk && !wake_up_process(tsk))
+ result |= ENGINE_WAKEUP_ACTIVE;
+ rcu_read_unlock();
+ }
+
+ return result;
+}
+
static unsigned long wait_timeout(void)
{
return round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES);
@@ -49,7 +75,7 @@ static void intel_breadcrumbs_hangcheck(unsigned long data)
* to process the pending interrupt (e.g, low priority task on a loaded
* system) and wait until it sleeps before declaring a missed interrupt.
*/
- if (!intel_engine_wakeup(engine)) {
+ if (intel_engine_wakeup(engine) & ENGINE_WAKEUP_ACTIVE) {
mod_timer(&b->hangcheck, wait_timeout());
return;
}