aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorBen Gamari <bgamari.foss@gmail.com>2009-09-14 17:48:47 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-09-17 14:36:46 -0700
commitba1234d17b3b1fe7087defb191a3c705f208aca6 (patch)
tree1d26be1196eeef15dda3e5386cd021d94249f0be /drivers/gpu/drm/i915/i915_irq.c
parentdrm/i915: Hookup chip reset in error handler (diff)
downloadlinux-dev-ba1234d17b3b1fe7087defb191a3c705f208aca6.tar.xz
linux-dev-ba1234d17b3b1fe7087defb191a3c705f208aca6.zip
drm/i915: Make dev_priv->mm.wedged an atomic_t
There is a very real possibility that multiple CPUs will notice that the GPU is wedged. This introduces all sorts of potential race conditions. Make the wedged flag atomic to mitigate this risk. Signed-off-by: Ben Gamari <bgamari.foss@gmail.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 8f5276614ce2..13e664ddb611 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -309,12 +309,12 @@ static void i915_error_work_func(struct work_struct *work)
DRM_DEBUG("generating error event\n");
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event);
- if (dev_priv->mm.wedged) {
+ if (atomic_read(&dev_priv->mm.wedged)) {
if (IS_I965G(dev)) {
DRM_DEBUG("resetting chip\n");
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event);
if (!i965_reset(dev, GDRST_RENDER)) {
- dev_priv->mm.wedged = 0;
+ atomic_set(&dev_priv->mm.wedged, 0);
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event);
}
} else {
@@ -385,7 +385,7 @@ out:
* so userspace knows something bad happened (should trigger collection
* of a ring dump etc.).
*/
-static void i915_handle_error(struct drm_device *dev)
+static void i915_handle_error(struct drm_device *dev, bool wedged)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 eir = I915_READ(EIR);
@@ -495,7 +495,9 @@ static void i915_handle_error(struct drm_device *dev)
I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
}
- if (dev_priv->mm.wedged) {
+ if (wedged) {
+ atomic_set(&dev_priv->mm.wedged, 1);
+
/*
* Wakeup waiting processes so they don't hang
*/
@@ -548,7 +550,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
pipeb_stats = I915_READ(PIPEBSTAT);
if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
- i915_handle_error(dev);
+ i915_handle_error(dev, false);
/*
* Clear the PIPE(A|B)STAT regs before the IIR
@@ -934,8 +936,7 @@ void i915_hangcheck_elapsed(unsigned long data)
if (dev_priv->last_acthd == acthd && dev_priv->hangcheck_count > 0) {
DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
- dev_priv->mm.wedged = true; /* Hopefully this is atomic */
- i915_handle_error(dev);
+ i915_handle_error(dev, true);
return;
}