diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2010-09-21 22:05:43 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2010-09-21 22:05:43 +0000 |
commit | 6c79c033a04d087ab85022dd1c2454efb34502ab (patch) | |
tree | 7ea5517814731adbad45732cb18038361a9a5a9b | |
parent | 2e11011107ebace70e60d2735c59cbebca201bb8 (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.c | 71 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.h | 17 |
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") |