aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2016-09-09 09:11:52 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2016-09-09 09:23:04 -0400
commit780f262a703a683bc56bbb860b25286a6f501d61 (patch)
treec31bdc885b028ae07757331ceebbcb3ebcc823b3 /drivers/gpu/drm
parent221fe7994554cc3985fc5d761ed7e44dcae0fa52 (diff)
drm/i915: Replace wait-on-mutex with wait-on-bit in reset worker
Since we have a cooperative mode now with a direct reset, we can avoid the contention on struct_mutex and instead try then sleep on the I915_RESET_IN_PROGRESS bit. If the mutex is held and that bit is cleared, all is fine. Otherwise, we sleep for a bit and try again. In the worst case we sleep for an extra second waiting for the mutex to be released (no one touching the GPU is allowed the struct_mutex whilst the I915_RESET_IN_PROGRESS bit is set). But when we have a direct reset, this allows us to clean up the reset worker faster. v2: Remember to call wake_up_bit() after changing (for the faster wakeup as promised) Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-12-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c14
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c31
3 files changed, 27 insertions, 20 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index ff4173e6e298..f2614b2f59f7 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1726,8 +1726,8 @@ int i915_resume_switcheroo(struct drm_device *dev)
1726 * i915_reset - reset chip after a hang 1726 * i915_reset - reset chip after a hang
1727 * @dev: drm device to reset 1727 * @dev: drm device to reset
1728 * 1728 *
1729 * Reset the chip. Useful if a hang is detected. Returns zero on successful 1729 * Reset the chip. Useful if a hang is detected. Marks the device as wedged
1730 * reset or otherwise an error code. 1730 * on failure.
1731 * 1731 *
1732 * Caller must hold the struct_mutex. 1732 * Caller must hold the struct_mutex.
1733 * 1733 *
@@ -1739,7 +1739,7 @@ int i915_resume_switcheroo(struct drm_device *dev)
1739 * - re-init interrupt state 1739 * - re-init interrupt state
1740 * - re-init display 1740 * - re-init display
1741 */ 1741 */
1742int i915_reset(struct drm_i915_private *dev_priv) 1742void i915_reset(struct drm_i915_private *dev_priv)
1743{ 1743{
1744 struct drm_device *dev = &dev_priv->drm; 1744 struct drm_device *dev = &dev_priv->drm;
1745 struct i915_gpu_error *error = &dev_priv->gpu_error; 1745 struct i915_gpu_error *error = &dev_priv->gpu_error;
@@ -1748,7 +1748,7 @@ int i915_reset(struct drm_i915_private *dev_priv)
1748 lockdep_assert_held(&dev->struct_mutex); 1748 lockdep_assert_held(&dev->struct_mutex);
1749 1749
1750 if (!test_and_clear_bit(I915_RESET_IN_PROGRESS, &error->flags)) 1750 if (!test_and_clear_bit(I915_RESET_IN_PROGRESS, &error->flags))
1751 return test_bit(I915_WEDGED, &error->flags) ? -EIO : 0; 1751 return;
1752 1752
1753 /* Clear any previous failed attempts at recovery. Time to try again. */ 1753 /* Clear any previous failed attempts at recovery. Time to try again. */
1754 __clear_bit(I915_WEDGED, &error->flags); 1754 __clear_bit(I915_WEDGED, &error->flags);
@@ -1798,11 +1798,13 @@ int i915_reset(struct drm_i915_private *dev_priv)
1798 intel_sanitize_gt_powersave(dev_priv); 1798 intel_sanitize_gt_powersave(dev_priv);
1799 intel_autoenable_gt_powersave(dev_priv); 1799 intel_autoenable_gt_powersave(dev_priv);
1800 1800
1801 return 0; 1801wakeup:
1802 wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS);
1803 return;
1802 1804
1803error: 1805error:
1804 set_bit(I915_WEDGED, &error->flags); 1806 set_bit(I915_WEDGED, &error->flags);
1805 return ret; 1807 goto wakeup;
1806} 1808}
1807 1809
1808static int i915_pm_suspend(struct device *kdev) 1810static int i915_pm_suspend(struct device *kdev)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 15f1977e356a..9a9f07f3574c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2884,7 +2884,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
2884#endif 2884#endif
2885extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); 2885extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask);
2886extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); 2886extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv);
2887extern int i915_reset(struct drm_i915_private *dev_priv); 2887extern void i915_reset(struct drm_i915_private *dev_priv);
2888extern int intel_guc_reset(struct drm_i915_private *dev_priv); 2888extern int intel_guc_reset(struct drm_i915_private *dev_priv);
2889extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine); 2889extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
2890extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); 2890extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2c7cb5041511..ef2d40278191 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2497,7 +2497,6 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
2497 char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; 2497 char *error_event[] = { I915_ERROR_UEVENT "=1", NULL };
2498 char *reset_event[] = { I915_RESET_UEVENT "=1", NULL }; 2498 char *reset_event[] = { I915_RESET_UEVENT "=1", NULL };
2499 char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL }; 2499 char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL };
2500 int ret;
2501 2500
2502 kobject_uevent_env(kobj, KOBJ_CHANGE, error_event); 2501 kobject_uevent_env(kobj, KOBJ_CHANGE, error_event);
2503 2502
@@ -2512,24 +2511,30 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
2512 * simulated reset via debugs, so get an RPM reference. 2511 * simulated reset via debugs, so get an RPM reference.
2513 */ 2512 */
2514 intel_runtime_pm_get(dev_priv); 2513 intel_runtime_pm_get(dev_priv);
2515
2516 intel_prepare_reset(dev_priv); 2514 intel_prepare_reset(dev_priv);
2517 2515
2518 /* 2516 do {
2519 * All state reset _must_ be completed before we update the 2517 /*
2520 * reset counter, for otherwise waiters might miss the reset 2518 * All state reset _must_ be completed before we update the
2521 * pending state and not properly drop locks, resulting in 2519 * reset counter, for otherwise waiters might miss the reset
2522 * deadlocks with the reset work. 2520 * pending state and not properly drop locks, resulting in
2523 */ 2521 * deadlocks with the reset work.
2524 mutex_lock(&dev_priv->drm.struct_mutex); 2522 */
2525 ret = i915_reset(dev_priv); 2523 if (mutex_trylock(&dev_priv->drm.struct_mutex)) {
2526 mutex_unlock(&dev_priv->drm.struct_mutex); 2524 i915_reset(dev_priv);
2525 mutex_unlock(&dev_priv->drm.struct_mutex);
2526 }
2527 2527
2528 intel_finish_reset(dev_priv); 2528 /* We need to wait for anyone holding the lock to wakeup */
2529 } while (wait_on_bit_timeout(&dev_priv->gpu_error.flags,
2530 I915_RESET_IN_PROGRESS,
2531 TASK_UNINTERRUPTIBLE,
2532 HZ));
2529 2533
2534 intel_finish_reset(dev_priv);
2530 intel_runtime_pm_put(dev_priv); 2535 intel_runtime_pm_put(dev_priv);
2531 2536
2532 if (ret == 0) 2537 if (!test_bit(I915_WEDGED, &dev_priv->gpu_error.flags))
2533 kobject_uevent_env(kobj, 2538 kobject_uevent_env(kobj,
2534 KOBJ_CHANGE, reset_done_event); 2539 KOBJ_CHANGE, reset_done_event);
2535 2540