Commit d5367307 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Wait for concurrent global resets to complete

If we enter i915_handle_error() a second time and a global reset is
already in progress, we can simply wait for completion of the first
reset. Currently we exit early prior to the actual reset being
performed -- the worst of both worlds!

v2: Plug into the existing reset_queue, and remember that kselftests is
playing games with I915_RESET_BACKOFF to prevent hangcheck from screwing
up.
v3: Rename to i915_reset_device to fit in better with i915_reset_engine
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Michel Thierry <michel.thierry@intel.com>
Reviewed-by: default avatarMichel Thierry <michel.thierry@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-2-chris@chris-wilson.co.uk
parent 1acfc104
...@@ -2600,13 +2600,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) ...@@ -2600,13 +2600,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
} }
/** /**
* i915_reset_and_wakeup - do process context error handling work * i915_reset_device - do process context error handling work
* @dev_priv: i915 device private * @dev_priv: i915 device private
* *
* Fire an error uevent so userspace can see that a hang or error * Fire an error uevent so userspace can see that a hang or error
* was detected. * was detected.
*/ */
static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) static void i915_reset_device(struct drm_i915_private *dev_priv)
{ {
struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj; struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj;
char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; char *error_event[] = { I915_ERROR_UEVENT "=1", NULL };
...@@ -2646,13 +2646,6 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) ...@@ -2646,13 +2646,6 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
if (!test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) if (!test_bit(I915_WEDGED, &dev_priv->gpu_error.flags))
kobject_uevent_env(kobj, kobject_uevent_env(kobj,
KOBJ_CHANGE, reset_done_event); KOBJ_CHANGE, reset_done_event);
/*
* Note: The wake_up also serves as a memory barrier so that
* waiters see the updated value of the dev_priv->gpu_error.
*/
clear_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags);
wake_up_all(&dev_priv->gpu_error.reset_queue);
} }
static inline void static inline void
...@@ -2744,11 +2737,17 @@ void i915_handle_error(struct drm_i915_private *dev_priv, ...@@ -2744,11 +2737,17 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
if (!engine_mask) if (!engine_mask)
goto out; goto out;
if (test_and_set_bit(I915_RESET_BACKOFF, if (test_and_set_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags)) {
&dev_priv->gpu_error.flags)) wait_event(dev_priv->gpu_error.reset_queue,
!test_bit(I915_RESET_BACKOFF,
&dev_priv->gpu_error.flags));
goto out; goto out;
}
i915_reset_device(dev_priv);
i915_reset_and_wakeup(dev_priv); clear_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags);
wake_up_all(&dev_priv->gpu_error.reset_queue);
out: out:
intel_runtime_pm_put(dev_priv); intel_runtime_pm_put(dev_priv);
......
...@@ -316,6 +316,8 @@ static int igt_global_reset(void *arg) ...@@ -316,6 +316,8 @@ static int igt_global_reset(void *arg)
GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags)); GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags));
clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags);
wake_up_all(&i915->gpu_error.reset_queue);
if (i915_terminally_wedged(&i915->gpu_error)) if (i915_terminally_wedged(&i915->gpu_error))
err = -EIO; err = -EIO;
...@@ -404,6 +406,7 @@ static int igt_wait_reset(void *arg) ...@@ -404,6 +406,7 @@ static int igt_wait_reset(void *arg)
unlock: unlock:
mutex_unlock(&i915->drm.struct_mutex); mutex_unlock(&i915->drm.struct_mutex);
clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags);
wake_up_all(&i915->gpu_error.reset_queue);
if (i915_terminally_wedged(&i915->gpu_error)) if (i915_terminally_wedged(&i915->gpu_error))
return -EIO; return -EIO;
...@@ -519,6 +522,7 @@ static int igt_reset_queue(void *arg) ...@@ -519,6 +522,7 @@ static int igt_reset_queue(void *arg)
unlock: unlock:
mutex_unlock(&i915->drm.struct_mutex); mutex_unlock(&i915->drm.struct_mutex);
clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags);
wake_up_all(&i915->gpu_error.reset_queue);
if (i915_terminally_wedged(&i915->gpu_error)) if (i915_terminally_wedged(&i915->gpu_error))
return -EIO; return -EIO;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment