diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 15 |
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) | |||
309 | DRM_DEBUG("generating error event\n"); | 309 | DRM_DEBUG("generating error event\n"); |
310 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); | 310 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); |
311 | 311 | ||
312 | if (dev_priv->mm.wedged) { | 312 | if (atomic_read(&dev_priv->mm.wedged)) { |
313 | if (IS_I965G(dev)) { | 313 | if (IS_I965G(dev)) { |
314 | DRM_DEBUG("resetting chip\n"); | 314 | DRM_DEBUG("resetting chip\n"); |
315 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); | 315 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); |
316 | if (!i965_reset(dev, GDRST_RENDER)) { | 316 | if (!i965_reset(dev, GDRST_RENDER)) { |
317 | dev_priv->mm.wedged = 0; | 317 | atomic_set(&dev_priv->mm.wedged, 0); |
318 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); | 318 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); |
319 | } | 319 | } |
320 | } else { | 320 | } else { |
@@ -385,7 +385,7 @@ out: | |||
385 | * so userspace knows something bad happened (should trigger collection | 385 | * so userspace knows something bad happened (should trigger collection |
386 | * of a ring dump etc.). | 386 | * of a ring dump etc.). |
387 | */ | 387 | */ |
388 | static void i915_handle_error(struct drm_device *dev) | 388 | static void i915_handle_error(struct drm_device *dev, bool wedged) |
389 | { | 389 | { |
390 | struct drm_i915_private *dev_priv = dev->dev_private; | 390 | struct drm_i915_private *dev_priv = dev->dev_private; |
391 | u32 eir = I915_READ(EIR); | 391 | u32 eir = I915_READ(EIR); |
@@ -495,7 +495,9 @@ static void i915_handle_error(struct drm_device *dev) | |||
495 | I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); | 495 | I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); |
496 | } | 496 | } |
497 | 497 | ||
498 | if (dev_priv->mm.wedged) { | 498 | if (wedged) { |
499 | atomic_set(&dev_priv->mm.wedged, 1); | ||
500 | |||
499 | /* | 501 | /* |
500 | * Wakeup waiting processes so they don't hang | 502 | * Wakeup waiting processes so they don't hang |
501 | */ | 503 | */ |
@@ -548,7 +550,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
548 | pipeb_stats = I915_READ(PIPEBSTAT); | 550 | pipeb_stats = I915_READ(PIPEBSTAT); |
549 | 551 | ||
550 | if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) | 552 | if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) |
551 | i915_handle_error(dev); | 553 | i915_handle_error(dev, false); |
552 | 554 | ||
553 | /* | 555 | /* |
554 | * Clear the PIPE(A|B)STAT regs before the IIR | 556 | * Clear the PIPE(A|B)STAT regs before the IIR |
@@ -934,8 +936,7 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
934 | 936 | ||
935 | if (dev_priv->last_acthd == acthd && dev_priv->hangcheck_count > 0) { | 937 | if (dev_priv->last_acthd == acthd && dev_priv->hangcheck_count > 0) { |
936 | DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); | 938 | DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); |
937 | dev_priv->mm.wedged = true; /* Hopefully this is atomic */ | 939 | i915_handle_error(dev, true); |
938 | i915_handle_error(dev); | ||
939 | return; | 940 | return; |
940 | } | 941 | } |
941 | 942 | ||