X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fi915%2Fi915_irq.c;h=6442ff269642f4489ac723c9f27d3f26483571eb;hb=cdbe8b5426e71d09882212073c27c9dcf25a71b6;hp=5d433fc11ace138748907b17cbb3a9932732b46b;hpb=00b1d444afc2e5c3129b4a9c16b1de03c0fce3f0;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5d433fc..6442ff2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -720,7 +720,6 @@ i915_error_object_create(struct drm_i915_private *dev_priv, reloc_offset = src->gtt_offset; for (page = 0; page < page_count; page++) { unsigned long flags; - void __iomem *s; void *d; d = kmalloc(PAGE_SIZE, GFP_ATOMIC); @@ -728,10 +727,29 @@ i915_error_object_create(struct drm_i915_private *dev_priv, goto unwind; local_irq_save(flags); - s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, - reloc_offset); - memcpy_fromio(d, s, PAGE_SIZE); - io_mapping_unmap_atomic(s); + if (reloc_offset < dev_priv->mm.gtt_mappable_end) { + void __iomem *s; + + /* Simply ignore tiling or any overlapping fence. + * It's part of the error state, and this hopefully + * captures what the GPU read. + */ + + s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, + reloc_offset); + memcpy_fromio(d, s, PAGE_SIZE); + io_mapping_unmap_atomic(s); + } else { + void *s; + + drm_clflush_pages(&src->pages[page], 1); + + s = kmap_atomic(src->pages[page]); + memcpy(d, s, PAGE_SIZE); + kunmap_atomic(s); + + drm_clflush_pages(&src->pages[page], 1); + } local_irq_restore(flags); dst->pages[page] = d; @@ -804,7 +822,7 @@ static u32 capture_bo_list(struct drm_i915_error_buffer *err, err->tiling = obj->tiling_mode; err->dirty = obj->dirty; err->purgeable = obj->madv != I915_MADV_WILLNEED; - err->ring = obj->ring ? obj->ring->id : 0; + err->ring = obj->ring ? obj->ring->id : -1; err->cache_level = obj->cache_level; if (++i == count) @@ -876,6 +894,39 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv, return NULL; } +static void i915_record_ring_state(struct drm_device *dev, + struct drm_i915_error_state *error, + struct intel_ring_buffer *ring) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (INTEL_INFO(dev)->gen >= 6) { + error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base)); + error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring)); + } + + if (INTEL_INFO(dev)->gen >= 4) { + error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base)); + error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base)); + error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base)); + error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base)); + if (ring->id == RCS) { + error->instdone1 = I915_READ(INSTDONE1); + error->bbaddr = I915_READ64(BB_ADDR); + } + } else { + error->ipeir[ring->id] = I915_READ(IPEIR); + error->ipehr[ring->id] = I915_READ(IPEHR); + error->instdone[ring->id] = I915_READ(INSTDONE); + } + + error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base)); + error->seqno[ring->id] = ring->get_seqno(ring); + error->acthd[ring->id] = intel_ring_get_active_head(ring); + error->head[ring->id] = I915_READ_HEAD(ring); + error->tail[ring->id] = I915_READ_TAIL(ring); +} + /** * i915_capture_error_state - capture an error record for later analysis * @dev: drm device @@ -900,7 +951,7 @@ static void i915_capture_error_state(struct drm_device *dev) return; /* Account for pipe specific data like PIPE*STAT */ - error = kmalloc(sizeof(*error), GFP_ATOMIC); + error = kzalloc(sizeof(*error), GFP_ATOMIC); if (!error) { DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); return; @@ -909,47 +960,22 @@ static void i915_capture_error_state(struct drm_device *dev) DRM_INFO("capturing error event; look for more information in /debug/dri/%d/i915_error_state\n", dev->primary->index); - error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]); error->eir = I915_READ(EIR); error->pgtbl_er = I915_READ(PGTBL_ER); for_each_pipe(pipe) error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); - error->instpm = I915_READ(INSTPM); - error->error = 0; + if (INTEL_INFO(dev)->gen >= 6) { error->error = I915_READ(ERROR_GEN6); - - error->bcs_acthd = I915_READ(BCS_ACTHD); - error->bcs_ipehr = I915_READ(BCS_IPEHR); - error->bcs_ipeir = I915_READ(BCS_IPEIR); - error->bcs_instdone = I915_READ(BCS_INSTDONE); - error->bcs_seqno = 0; - if (dev_priv->ring[BCS].get_seqno) - error->bcs_seqno = dev_priv->ring[BCS].get_seqno(&dev_priv->ring[BCS]); - - error->vcs_acthd = I915_READ(VCS_ACTHD); - error->vcs_ipehr = I915_READ(VCS_IPEHR); - error->vcs_ipeir = I915_READ(VCS_IPEIR); - error->vcs_instdone = I915_READ(VCS_INSTDONE); - error->vcs_seqno = 0; - if (dev_priv->ring[VCS].get_seqno) - error->vcs_seqno = dev_priv->ring[VCS].get_seqno(&dev_priv->ring[VCS]); - } - if (INTEL_INFO(dev)->gen >= 4) { - error->ipeir = I915_READ(IPEIR_I965); - error->ipehr = I915_READ(IPEHR_I965); - error->instdone = I915_READ(INSTDONE_I965); - error->instps = I915_READ(INSTPS); - error->instdone1 = I915_READ(INSTDONE1); - error->acthd = I915_READ(ACTHD_I965); - error->bbaddr = I915_READ64(BB_ADDR); - } else { - error->ipeir = I915_READ(IPEIR); - error->ipehr = I915_READ(IPEHR); - error->instdone = I915_READ(INSTDONE); - error->acthd = I915_READ(ACTHD); - error->bbaddr = 0; + error->done_reg = I915_READ(DONE_REG); } + + i915_record_ring_state(dev, error, &dev_priv->ring[RCS]); + if (HAS_BLT(dev)) + i915_record_ring_state(dev, error, &dev_priv->ring[BCS]); + if (HAS_BSD(dev)) + i915_record_ring_state(dev, error, &dev_priv->ring[VCS]); + i915_gem_record_fences(dev, error); /* Record the active batch and ring buffers */ @@ -1017,11 +1043,12 @@ void i915_destroy_error_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_error_state *error; + unsigned long flags; - spin_lock(&dev_priv->error_lock); + spin_lock_irqsave(&dev_priv->error_lock, flags); error = dev_priv->first_error; dev_priv->first_error = NULL; - spin_unlock(&dev_priv->error_lock); + spin_unlock_irqrestore(&dev_priv->error_lock, flags); if (error) i915_error_state_free(dev, error); @@ -1698,6 +1725,7 @@ void i915_hangcheck_elapsed(unsigned long data) dev_priv->last_instdone1 == instdone1) { if (dev_priv->hangcheck_count++ > 1) { DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); + i915_handle_error(dev, true); if (!IS_GEN2(dev)) { /* Is the chip hanging on a WAIT_FOR_EVENT? @@ -1705,7 +1733,6 @@ void i915_hangcheck_elapsed(unsigned long data) * and break the hang. This should work on * all but the second generation chipsets. */ - if (kick_ring(&dev_priv->ring[RCS])) goto repeat; @@ -1718,7 +1745,6 @@ void i915_hangcheck_elapsed(unsigned long data) goto repeat; } - i915_handle_error(dev, true); return; } } else { @@ -1751,7 +1777,8 @@ static void ironlake_irq_preinstall(struct drm_device *dev) INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); I915_WRITE(HWSTAM, 0xeffe); - if (IS_GEN6(dev) || IS_GEN7(dev)) { + + if (IS_GEN6(dev)) { /* Workaround stalls observed on Sandy Bridge GPUs by * making the blitter command streamer generate a * write to the Hardware Status Page for