diff options
author | Mika Kuoppala <mika.kuoppala@intel.com> | 2016-01-28 11:51:53 +0200 |
---|---|---|
committer | Mika Kuoppala <mika.kuoppala@intel.com> | 2016-02-16 14:16:38 +0200 |
commit | 5720e01c2765cd038c9a1749ad580f866d624077 (patch) | |
tree | 0e9277408a77f124dcbc5f8c6ab3e59ad8974843 | |
parent | fb9e6d18dce895cc6a6c00d08184d8d88f746711 (diff) |
drm/i915: Don't mark idle if hangcheck is duemissed_irqs
Postpone marking device idle until hangcheck has been done.
This guarantees that we hold the pm ref for hangcheck.
Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com>
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ca8ea6e42eb6..7701167ad98b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2963,6 +2963,13 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) WARN_ON(i915_verify_lists(ring->dev)); } +static void i915_queue_idle_work(struct drm_i915_private *dev_priv) +{ + mod_delayed_work(dev_priv->wq, + &dev_priv->mm.idle_work, + msecs_to_jiffies(100)); +} + bool i915_gem_retire_requests(struct drm_device *dev) { @@ -2984,9 +2991,7 @@ i915_gem_retire_requests(struct drm_device *dev) } if (idle) - mod_delayed_work(dev_priv->wq, - &dev_priv->mm.idle_work, - msecs_to_jiffies(100)); + i915_queue_idle_work(dev_priv); return idle; } @@ -3010,6 +3015,14 @@ i915_gem_retire_work_handler(struct work_struct *work) round_jiffies_up_relative(HZ)); } +static bool i915_hangcheck_active(struct drm_i915_private *dev_priv) +{ + if (!i915.enable_hangcheck) + return false; + + return delayed_work_pending(&dev_priv->gpu_error.hangcheck_work); +} + static void i915_gem_idle_work_handler(struct work_struct *work) { @@ -3017,27 +3030,27 @@ i915_gem_idle_work_handler(struct work_struct *work) container_of(work, typeof(*dev_priv), mm.idle_work.work); struct drm_device *dev = dev_priv->dev; struct intel_engine_cs *ring; + bool idle; int i; - for_each_ring(ring, dev_priv, i) - if (!list_empty(&ring->request_list)) - return; - - /* we probably should sync with hangcheck here, using cancel_work_sync. - * Also locking seems to be fubar here, ring->request_list is protected - * by dev->struct_mutex. */ - - intel_mark_idle(dev); + if (i915_hangcheck_active(dev_priv) || + !mutex_trylock(&dev->struct_mutex)) { + i915_queue_idle_work(dev_priv); + return; + } - if (mutex_trylock(&dev->struct_mutex)) { - struct intel_engine_cs *ring; - int i; + idle = true; + for_each_ring(ring, dev_priv, i) + idle &= list_empty(&ring->request_list); + if (idle) { for_each_ring(ring, dev_priv, i) i915_gem_batch_pool_fini(&ring->batch_pool); - mutex_unlock(&dev->struct_mutex); + intel_mark_idle(dev); } + + mutex_unlock(&dev->struct_mutex); } /** |