Commit d7a133d8 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Disable mmio debugging during user access

If the user bypasses i915 and accesses mmio directly, that easily
confuses our automatic mmio debugging (any error we then detect is
likely to be as a result of the user). Since we expect userspace to open
debugfs/i915_forcewake_user if i915.ko is loaded and they want mmio
access, that makes the opportune time to disable our debugging for
duration of the bypass.

v2: Move the fiddling of uncore internals to uncore.c

References: https://bugs.freedesktop.org/show_bug.cgi?id=102543Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20170907134441.12881-1-chris@chris-wilson.co.uk
parent d2d4f39b
...@@ -1421,6 +1421,9 @@ static int i915_forcewake_domains(struct seq_file *m, void *data) ...@@ -1421,6 +1421,9 @@ static int i915_forcewake_domains(struct seq_file *m, void *data)
struct intel_uncore_forcewake_domain *fw_domain; struct intel_uncore_forcewake_domain *fw_domain;
unsigned int tmp; unsigned int tmp;
seq_printf(m, "user.bypass_count = %u\n",
i915->uncore.user_forcewake.count);
for_each_fw_domain(fw_domain, i915, tmp) for_each_fw_domain(fw_domain, i915, tmp)
seq_printf(m, "%s.wake_count = %u\n", seq_printf(m, "%s.wake_count = %u\n",
intel_uncore_forcewake_domain_to_str(fw_domain->id), intel_uncore_forcewake_domain_to_str(fw_domain->id),
...@@ -4724,26 +4727,26 @@ static int i915_sseu_status(struct seq_file *m, void *unused) ...@@ -4724,26 +4727,26 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
static int i915_forcewake_open(struct inode *inode, struct file *file) static int i915_forcewake_open(struct inode *inode, struct file *file)
{ {
struct drm_i915_private *dev_priv = inode->i_private; struct drm_i915_private *i915 = inode->i_private;
if (INTEL_GEN(dev_priv) < 6) if (INTEL_GEN(i915) < 6)
return 0; return 0;
intel_runtime_pm_get(dev_priv); intel_runtime_pm_get(i915);
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); intel_uncore_forcewake_user_get(i915);
return 0; return 0;
} }
static int i915_forcewake_release(struct inode *inode, struct file *file) static int i915_forcewake_release(struct inode *inode, struct file *file)
{ {
struct drm_i915_private *dev_priv = inode->i_private; struct drm_i915_private *i915 = inode->i_private;
if (INTEL_GEN(dev_priv) < 6) if (INTEL_GEN(i915) < 6)
return 0; return 0;
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); intel_uncore_forcewake_user_put(i915);
intel_runtime_pm_put(dev_priv); intel_runtime_pm_put(i915);
return 0; return 0;
} }
......
...@@ -489,6 +489,57 @@ void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, ...@@ -489,6 +489,57 @@ void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
} }
/**
* intel_uncore_forcewake_user_get - claim forcewake on behalf of userspace
* @dev_priv: i915 device instance
*
* This function is a wrapper around intel_uncore_forcewake_get() to acquire
* the GT powerwell and in the process disable our debugging for the
* duration of userspace's bypass.
*/
void intel_uncore_forcewake_user_get(struct drm_i915_private *dev_priv)
{
spin_lock_irq(&dev_priv->uncore.lock);
if (!dev_priv->uncore.user_forcewake.count++) {
intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL);
/* Save and disable mmio debugging for the user bypass */
dev_priv->uncore.user_forcewake.saved_mmio_check =
dev_priv->uncore.unclaimed_mmio_check;
dev_priv->uncore.user_forcewake.saved_mmio_debug =
i915.mmio_debug;
dev_priv->uncore.unclaimed_mmio_check = 0;
i915.mmio_debug = 0;
}
spin_unlock_irq(&dev_priv->uncore.lock);
}
/**
* intel_uncore_forcewake_user_put - release forcewake on behalf of userspace
* @dev_priv: i915 device instance
*
* This function complements intel_uncore_forcewake_user_get() and releases
* the GT powerwell taken on behalf of the userspace bypass.
*/
void intel_uncore_forcewake_user_put(struct drm_i915_private *dev_priv)
{
spin_lock_irq(&dev_priv->uncore.lock);
if (!--dev_priv->uncore.user_forcewake.count) {
if (intel_uncore_unclaimed_mmio(dev_priv))
dev_info(dev_priv->drm.dev,
"Invalid mmio detected during user access\n");
dev_priv->uncore.unclaimed_mmio_check =
dev_priv->uncore.user_forcewake.saved_mmio_check;
i915.mmio_debug =
dev_priv->uncore.user_forcewake.saved_mmio_debug;
intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL);
}
spin_unlock_irq(&dev_priv->uncore.lock);
}
/** /**
* intel_uncore_forcewake_get__locked - grab forcewake domain references * intel_uncore_forcewake_get__locked - grab forcewake domain references
* @dev_priv: i915 device instance * @dev_priv: i915 device instance
......
...@@ -102,6 +102,13 @@ struct intel_uncore { ...@@ -102,6 +102,13 @@ struct intel_uncore {
i915_reg_t reg_ack; i915_reg_t reg_ack;
} fw_domain[FW_DOMAIN_ID_COUNT]; } fw_domain[FW_DOMAIN_ID_COUNT];
struct {
unsigned int count;
int saved_mmio_check;
int saved_mmio_debug;
} user_forcewake;
int unclaimed_mmio_check; int unclaimed_mmio_check;
}; };
...@@ -144,6 +151,9 @@ void intel_uncore_forcewake_get__locked(struct drm_i915_private *dev_priv, ...@@ -144,6 +151,9 @@ void intel_uncore_forcewake_get__locked(struct drm_i915_private *dev_priv,
void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv, void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv,
enum forcewake_domains domains); enum forcewake_domains domains);
void intel_uncore_forcewake_user_get(struct drm_i915_private *dev_priv);
void intel_uncore_forcewake_user_put(struct drm_i915_private *dev_priv);
int intel_wait_for_register(struct drm_i915_private *dev_priv, int intel_wait_for_register(struct drm_i915_private *dev_priv,
i915_reg_t reg, i915_reg_t reg,
u32 mask, u32 mask,
......
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