summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_uncore.c
diff options
context:
space:
mode:
authorChris Wilson2017-04-11 12:13:38 +0200
committerChris Wilson2017-04-11 13:44:34 +0200
commit0564654340e2776843ade007c1aaa8e8f30dd147 (patch)
treef9483b848ad9f12dc6ee4b8f9033fe909c3fa9ae /drivers/gpu/drm/i915/intel_uncore.c
parentdrm/i915: Stop sleeping from inside gen6_bsd_submit_request() (diff)
downloadkernel-qcow2-linux-0564654340e2776843ade007c1aaa8e8f30dd147.tar.gz
kernel-qcow2-linux-0564654340e2776843ade007c1aaa8e8f30dd147.tar.xz
kernel-qcow2-linux-0564654340e2776843ade007c1aaa8e8f30dd147.zip
drm/i915: Acquire uncore.lock over intel_uncore_wait_for_register()
We acquire the forcewake and use I915_READ_FW instead for the atomic wait within intel_uncore_wait_for_register. However, this still leaves us vulnerable to concurrent mmio access to the register, which can cause system hangs on gen7. The protection is to acquire uncore.lock around each register, so lets add it back. v2: Wrap __intel_wait_for_register_fw() to re-use its atomic wait_for loop and spare adding another for ourselves. v3: Add might_sleep() annotation Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170411101340.31994-3-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_uncore.c')
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index dded42db880b..fb38c7692fc2 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1662,14 +1662,22 @@ int intel_wait_for_register(struct drm_i915_private *dev_priv,
u32 value,
unsigned int timeout_ms)
{
-
unsigned fw =
intel_uncore_forcewake_for_reg(dev_priv, reg, FW_REG_READ);
int ret;
- intel_uncore_forcewake_get(dev_priv, fw);
- ret = wait_for_us((I915_READ_FW(reg) & mask) == value, 2);
- intel_uncore_forcewake_put(dev_priv, fw);
+ might_sleep();
+
+ spin_lock_irq(&dev_priv->uncore.lock);
+ intel_uncore_forcewake_get__locked(dev_priv, fw);
+
+ ret = __intel_wait_for_register_fw(dev_priv,
+ reg, mask, value,
+ 2, 0, NULL);
+
+ intel_uncore_forcewake_put__locked(dev_priv, fw);
+ spin_unlock_irq(&dev_priv->uncore.lock);
+
if (ret)
ret = wait_for((I915_READ_NOTRACE(reg) & mask) == value,
timeout_ms);