summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2010-09-21 22:05:43 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2010-09-21 22:05:43 +0000
commit6c79c033a04d087ab85022dd1c2454efb34502ab (patch)
tree7ea5517814731adbad45732cb18038361a9a5a9b
parent2e11011107ebace70e60d2735c59cbebca201bb8 (diff)
Enable error interrupts on ironlake, as we do on all other chips.
The sodding bits moved again *sigh*.
-rw-r--r--sys/dev/pci/drm/i915_drv.c71
-rw-r--r--sys/dev/pci/drm/i915_drv.h17
2 files changed, 48 insertions, 40 deletions
diff --git a/sys/dev/pci/drm/i915_drv.c b/sys/dev/pci/drm/i915_drv.c
index 6be9397dffe..cb0835c3694 100644
--- a/sys/dev/pci/drm/i915_drv.c
+++ b/sys/dev/pci/drm/i915_drv.c
@@ -67,6 +67,7 @@ int inteldrm_activate(struct device *, int);
int inteldrm_ioctl(struct drm_device *, u_long, caddr_t, struct drm_file *);
int inteldrm_doioctl(struct drm_device *, u_long, caddr_t, struct drm_file *);
int inteldrm_intr(void *);
+void inteldrm_error(struct inteldrm_softc *);
int inteldrm_ironlake_intr(void *);
void inteldrm_lastclose(struct drm_device *);
@@ -669,6 +670,8 @@ inteldrm_ironlake_intr(void *arg)
dev_priv->mm.hang_cnt = 0;
timeout_add_msec(&dev_priv->mm.hang_timer, 750);
}
+ if (gt_iir & GT_MASTER_ERROR)
+ inteldrm_error(dev_priv);
if (de_iir & DE_PIPEA_VBLANK)
drm_handle_vblank(dev, 0);
@@ -686,6 +689,7 @@ done:
return (ret);
}
+
int
inteldrm_intr(void *arg)
{
@@ -4191,23 +4195,32 @@ inteldrm_timeout(void *arg)
void
inteldrm_error(struct inteldrm_softc *dev_priv)
{
- u_int32_t eir, ipeir, pgtbl_err, pipea_stats, pipeb_stats;
+ u_int32_t eir, ipeir;
u_int8_t reset = GDRST_RENDER;
+ char *errbitstr;
eir = I915_READ(EIR);
- pipea_stats = I915_READ(PIPEASTAT);
- pipeb_stats = I915_READ(PIPEBSTAT);
+ if (eir == 0)
+ return;
- /*
- * only actually check the error bits if we register one.
- * else we just hung, stay silent.
- */
- if (eir != 0) {
- printf("render error detected, EIR: 0x%08x\n", eir);
+ if (IS_IRONLAKE(dev_priv)) {
+ errbitstr = "\20\x05PTEE\x04MPVE\x03CPVE";
+ } else if (IS_G4X(dev_priv)) {
+ errbitstr = "\20\x10 BCSINSTERR\x06PTEERR\x05MPVERR\x04CPVERR"
+ "\x03 BCSPTEERR\x02REFRESHERR\x01INSTERR";
+ } else {
+ errbitstr = "\20\x5PTEERR\x2REFRESHERR\x1INSTERR";
+ }
+
+ printf("render error detected, EIR: %b\n", eir, errbitstr);
+ if (IS_IRONLAKE(dev_priv)) {
+ if (eir & GT_ERROR_PTE) {
+ dev_priv->mm.wedged = 1;
+ reset = GDRST_FULL;
+ }
+ } else {
if (IS_G4X(dev_priv)) {
if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
- ipeir = I915_READ(IPEIR_I965);
-
printf(" IPEIR: 0x%08x\n",
I915_READ(IPEIR_I965));
printf(" IPEHR: 0x%08x\n",
@@ -4220,38 +4233,26 @@ inteldrm_error(struct inteldrm_softc *dev_priv)
I915_READ(INSTDONE1));
printf(" ACTHD: 0x%08x\n",
I915_READ(ACTHD_I965));
- I915_WRITE(IPEIR_I965, ipeir);
- (void)I915_READ(IPEIR_I965);
}
if (eir & GM45_ERROR_PAGE_TABLE) {
- pgtbl_err = I915_READ(PGTBL_ER);
- printf("page table error\n");
- printf(" PGTBL_ER: 0x%08x\n", pgtbl_err);
- I915_WRITE(PGTBL_ER, pgtbl_err);
- (void)I915_READ(PGTBL_ER);
+ printf(" PGTBL_ER: 0x%08x\n",
+ I915_READ(PGTBL_ER));
dev_priv->mm.wedged = 1;
reset = GDRST_FULL;
}
} else if (IS_I9XX(dev_priv) && eir & I915_ERROR_PAGE_TABLE) {
- pgtbl_err = I915_READ(PGTBL_ER);
- printf("page table error\n");
- printf(" PGTBL_ER: 0x%08x\n", pgtbl_err);
- I915_WRITE(PGTBL_ER, pgtbl_err);
- (void)I915_READ(PGTBL_ER);
+ printf(" PGTBL_ER: 0x%08x\n", I915_READ(PGTBL_ER));
dev_priv->mm.wedged = 1;
reset = GDRST_FULL;
}
if (eir & I915_ERROR_MEMORY_REFRESH) {
- printf("memory refresh error\n");
printf("PIPEASTAT: 0x%08x\n",
- pipea_stats);
+ I915_READ(PIPEASTAT));
printf("PIPEBSTAT: 0x%08x\n",
- pipeb_stats);
- /* pipestat has already been acked */
+ I915_READ(PIPEBSTAT));
}
if (eir & I915_ERROR_INSTRUCTION) {
- printf("instruction error\n");
printf(" INSTPM: 0x%08x\n",
I915_READ(INSTPM));
if (!IS_I965G(dev_priv)) {
@@ -4286,20 +4287,24 @@ inteldrm_error(struct inteldrm_softc *dev_priv)
(void)I915_READ(IPEIR_I965);
}
}
-
- I915_WRITE(EIR, eir);
- eir = I915_READ(EIR);
}
+
+ I915_WRITE(EIR, eir);
+ eir = I915_READ(EIR);
/*
* nasty errors don't clear and need a reset, mask them until we reset
* else we'll get infinite interrupt storms.
*/
if (eir) {
- /* print so we know that we may want to reset here too */
if (dev_priv->mm.wedged == 0)
DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir);
I915_WRITE(EMR, I915_READ(EMR) | eir);
- I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+ if (IS_IRONLAKE(dev_priv)) {
+ I915_WRITE(GTIIR, GT_MASTER_ERROR);
+ } else {
+ I915_WRITE(IIR,
+ I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+ }
}
/*
* if it was a pagetable error, or we were called from hangcheck, then
diff --git a/sys/dev/pci/drm/i915_drv.h b/sys/dev/pci/drm/i915_drv.h
index ab5d501b41c..50ae6b980e4 100644
--- a/sys/dev/pci/drm/i915_drv.h
+++ b/sys/dev/pci/drm/i915_drv.h
@@ -502,7 +502,6 @@ void inteldrm_begin_ring(struct inteldrm_softc *, int);
void inteldrm_out_ring(struct inteldrm_softc *, u_int32_t);
void inteldrm_advance_ring(struct inteldrm_softc *);
void inteldrm_update_ring(struct inteldrm_softc *);
-void inteldrm_error(struct inteldrm_softc *);
int inteldrm_pipe_enabled(struct inteldrm_softc *, int);
int i915_init_phys_hws(struct inteldrm_softc *, bus_dma_tag_t);
@@ -839,6 +838,12 @@ read64(struct inteldrm_softc *dev_priv, bus_size_t off)
#define GM45_ERROR_CP_PRIV (1<<3)
#define I915_ERROR_MEMORY_REFRESH (1<<1)
#define I915_ERROR_INSTRUCTION (1<<0)
+/* ironlake error bits */
+#define GT_ERROR_PTE (1<<4)
+ /* memory privilege violation error */
+#define GT_ERROR_MPE (1<<3)
+ /* command privilege violation error */
+#define GT_ERROR_CPE (1<<2)
#define INSTPM 0x020c0
#define ACTHD 0x020c8
#define FW_BLC 0x020d8
@@ -2509,6 +2514,7 @@ read64(struct inteldrm_softc *dev_priv, bus_size_t off)
#define DEIER 0x4400c
/* GT interrupt */
+#define GT_MASTER_ERROR (1 << 3)
#define GT_SYNC_STATUS (1 << 2)
#define GT_USER_INTERRUPT (1 << 0)
@@ -3013,12 +3019,12 @@ read64(struct inteldrm_softc *dev_priv, bus_size_t off)
/*
* if kms we want pch event, gse, and plane flip masks too
*/
-#define PCH_SPLIT_DISPLAY_INTR_FIX DE_MASTER_IRQ_CONTROL
-#define PCH_SPLIT_DISPLAY_INTR_VAR DE_PIPEA_VBLANK | DE_PIPEB_VBLANK
+#define PCH_SPLIT_DISPLAY_INTR_FIX (DE_MASTER_IRQ_CONTROL)
+#define PCH_SPLIT_DISPLAY_INTR_VAR (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK)
#define PCH_SPLIT_DISPLAY_ENABLE_MASK \
(PCH_SPLIT_DISPLAY_INTR_FIX | PCH_SPLIT_DISPLAY_INTR_VAR)
#define PCH_SPLIT_RENDER_INTR_FIX (0)
-#define PCH_SPLIT_RENDER_INTR_VAR GT_USER_INTERRUPT
+#define PCH_SPLIT_RENDER_INTR_VAR (GT_USER_INTERRUPT | GT_MASTER_ERROR)
#define PCH_SPLIT_RENDER_ENABLE_MASK \
(PCH_SPLIT_RENDER_INTR_FIX | PCH_SPLIT_RENDER_INTR_VAR)
/* not yet */
@@ -3027,9 +3033,6 @@ read64(struct inteldrm_softc *dev_priv, bus_size_t off)
#define PCH_SPLIT_HOTPLUG_ENABLE_MASK \
(PCH_SPLIT_HOTPLUG_INTR_FIX | PCH_SPLIT_HOTPLUG_INTR_VAR)
-#define PCH_SPLIT_HOTPLUG_MASK
-
-
#define printeir(val) printf("%s: error reg: %b\n", __func__, val, \
"\20\x10PTEERR\x2REFRESHERR\x1INSTERR")