Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 166005
b: refs/heads/master
c: f65d942
h: refs/heads/master
i:
  166003: 615c18d
v: v3
  • Loading branch information
Ben Gamari authored and Jesse Barnes committed Sep 17, 2009
1 parent 0600ede commit 1891133
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 22be172423b0007a02a06d70db8aeb4d9e64c6b3
refs/heads/master: f65d94211e2bcba17faf05a6a3809af0e4217767
3 changes: 3 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1447,6 +1447,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (!IS_IGDNG(dev))
intel_opregion_init(dev, 0);

setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
(unsigned long) dev);
return 0;

out_workqueue_free:
Expand All @@ -1467,6 +1469,7 @@ int i915_driver_unload(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;

destroy_workqueue(dev_priv->wq);
del_timer_sync(&dev_priv->hangcheck_timer);

io_mapping_free(dev_priv->mm.gtt_mapping);
if (dev_priv->mm.gtt_mtrr >= 0) {
Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ typedef struct drm_i915_private {
unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
int vblank_pipe;

/* For hangcheck timer */
#define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */
struct timer_list hangcheck_timer;
int hangcheck_count;
uint32_t last_acthd;

bool cursor_needs_physical;

struct drm_mm vram;
Expand Down Expand Up @@ -620,6 +626,7 @@ extern int i915_emit_box(struct drm_device *dev,
int i, int DR1, int DR4);

/* i915_irq.c */
void i915_hangcheck_elapsed(unsigned long data);
extern int i915_irq_emit(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int i915_irq_wait(struct drm_device *dev, void *data,
Expand Down
8 changes: 6 additions & 2 deletions trunk/drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1584,8 +1584,11 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,

}

if (was_empty && !dev_priv->mm.suspended)
queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
if (!dev_priv->mm.suspended) {
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
if (was_empty)
queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
}
return seqno;
}

Expand Down Expand Up @@ -3896,6 +3899,7 @@ i915_gem_idle(struct drm_device *dev)
* We need to replace this with a semaphore, or something.
*/
dev_priv->mm.suspended = 1;
del_timer(&dev_priv->hangcheck_timer);

/* Cancel the retire work handler, wait for it to finish if running
*/
Expand Down
49 changes: 49 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
if (iir & I915_USER_INTERRUPT) {
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
DRM_WAKEUP(&dev_priv->irq_queue);
dev_priv->hangcheck_count = 0;
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
}

if (pipea_stats & vblank_status) {
Expand Down Expand Up @@ -880,6 +882,53 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
return -EINVAL;
}

struct drm_i915_gem_request *i915_get_tail_request(struct drm_device *dev) {
drm_i915_private_t *dev_priv = dev->dev_private;
return list_entry(dev_priv->mm.request_list.prev, struct drm_i915_gem_request, list);
}

/**
* This is called when the chip hasn't reported back with completed
* batchbuffers in a long time. The first time this is called we simply record
* ACTHD. If ACTHD hasn't changed by the time the hangcheck timer elapses
* again, we assume the chip is wedged and try to fix it.
*/
void i915_hangcheck_elapsed(unsigned long data)
{
struct drm_device *dev = (struct drm_device *)data;
drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t acthd;

if (!IS_I965G(dev))
acthd = I915_READ(ACTHD);
else
acthd = I915_READ(ACTHD_I965);

/* If all work is done then ACTHD clearly hasn't advanced. */
if (list_empty(&dev_priv->mm.request_list) ||
i915_seqno_passed(i915_get_gem_seqno(dev), i915_get_tail_request(dev)->seqno)) {
dev_priv->hangcheck_count = 0;
return;
}

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);
return;
}

/* Reset timer case chip hangs without another request being added */
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);

if (acthd != dev_priv->last_acthd)
dev_priv->hangcheck_count = 0;
else
dev_priv->hangcheck_count++;

dev_priv->last_acthd = acthd;
}

/* drm_dma.h hooks
*/
static void igdng_irq_preinstall(struct drm_device *dev)
Expand Down

0 comments on commit 1891133

Please sign in to comment.