summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/drm')
-rw-r--r--sys/dev/pci/drm/i915_drv.c30
-rw-r--r--sys/dev/pci/drm/i915_drv.h4
2 files changed, 28 insertions, 6 deletions
diff --git a/sys/dev/pci/drm/i915_drv.c b/sys/dev/pci/drm/i915_drv.c
index 74f874a7513..58e6e11e0e3 100644
--- a/sys/dev/pci/drm/i915_drv.c
+++ b/sys/dev/pci/drm/i915_drv.c
@@ -4385,7 +4385,7 @@ void
inteldrm_hangcheck(void *arg)
{
struct inteldrm_softc *dev_priv = arg;
- u_int32_t acthd;
+ u_int32_t acthd, instdone, instdone1;
/* are we idle? no requests, or ring is empty */
if (TAILQ_EMPTY(&dev_priv->mm.request_list) ||
@@ -4395,15 +4395,30 @@ inteldrm_hangcheck(void *arg)
return;
}
- if (IS_I965G(dev_priv))
+ if (IS_I965G(dev_priv)) {
acthd = I915_READ(ACTHD_I965);
- else
+ instdone = I915_READ(INSTDONE_I965);
+ instdone1 = I915_READ(INSTDONE1);
+ } else {
acthd = I915_READ(ACTHD);
+ instdone = I915_READ(INSTDONE);
+ instdone1 = 0;
+ }
/* if we've hit ourselves before and the hardware hasn't moved, hung. */
- if (dev_priv->mm.last_acthd == acthd) {
+ if (dev_priv->mm.last_acthd == acthd &&
+ dev_priv->mm.last_instdone == instdone &&
+ dev_priv->mm.last_instdone1 == instdone1) {
/* if that's twice we didn't hit it, then we're hung */
if (++dev_priv->mm.hang_cnt >= 2) {
+ if (!IS_GEN2(dev_priv)) {
+ u_int32_t tmp = I915_READ(PRB0_CTL);
+ if (tmp & RING_WAIT) {
+ I915_WRITE(PRB0_CTL, tmp);
+ (void)I915_READ(PRB0_CTL);
+ goto out;
+ }
+ }
dev_priv->mm.hang_cnt = 0;
/* XXX atomic */
dev_priv->mm.wedged = 1;
@@ -4415,9 +4430,12 @@ inteldrm_hangcheck(void *arg)
}
} else {
dev_priv->mm.hang_cnt = 0;
- }
- dev_priv->mm.last_acthd = acthd;
+ dev_priv->mm.last_acthd = acthd;
+ dev_priv->mm.last_instdone = instdone;
+ dev_priv->mm.last_instdone1 = instdone1;
+ }
+out:
/* Set ourselves up again, in case we haven't added another batch */
timeout_add_msec(&dev_priv->mm.hang_timer, 750);
}
diff --git a/sys/dev/pci/drm/i915_drv.h b/sys/dev/pci/drm/i915_drv.h
index 263fdae42c3..bd3527fca5e 100644
--- a/sys/dev/pci/drm/i915_drv.h
+++ b/sys/dev/pci/drm/i915_drv.h
@@ -376,6 +376,8 @@ struct inteldrm_softc {
/* for hangcheck */
int hang_cnt;
u_int32_t last_acthd;
+ u_int32_t last_instdone;
+ u_int32_t last_instdone1;
uint32_t next_gem_seqno;
@@ -785,6 +787,8 @@ read64(struct inteldrm_softc *dev_priv, bus_size_t off)
#define RING_VALID_MASK 0x00000001
#define RING_VALID 0x00000001
#define RING_INVALID 0x00000000
+#define RING_WAIT_I8XX (1<<0) /* gen2, PRBx_HEAD */
+#define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */
#define PRB1_TAIL 0x02040 /* 915+ only */
#define PRB1_HEAD 0x02044 /* 915+ only */
#define PRB1_START 0x02048 /* 915+ only */