215,6 → 215,24 |
} |
} |
|
static const char *hangcheck_action_to_str(enum intel_ring_hangcheck_action a) |
{ |
switch (a) { |
case HANGCHECK_IDLE: |
return "idle"; |
case HANGCHECK_WAIT: |
return "wait"; |
case HANGCHECK_ACTIVE: |
return "active"; |
case HANGCHECK_KICK: |
return "kick"; |
case HANGCHECK_HUNG: |
return "hung"; |
} |
|
return "unknown"; |
} |
|
static void i915_ring_error_state(struct drm_i915_error_state_buf *m, |
struct drm_device *dev, |
struct drm_i915_error_state *error, |
221,6 → 239,9 |
unsigned ring) |
{ |
BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */ |
if (!error->ring[ring].valid) |
return; |
|
err_printf(m, "%s command stream:\n", ring_str(ring)); |
err_printf(m, " HEAD: 0x%08x\n", error->head[ring]); |
err_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); |
229,11 → 250,11 |
err_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); |
err_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); |
err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]); |
if (ring == RCS && INTEL_INFO(dev)->gen >= 4) |
err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr); |
|
if (INTEL_INFO(dev)->gen >= 4) |
if (INTEL_INFO(dev)->gen >= 4) { |
err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr[ring]); |
err_printf(m, " BB_STATE: 0x%08x\n", error->bbstate[ring]); |
err_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]); |
} |
err_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); |
err_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]); |
if (INTEL_INFO(dev)->gen >= 6) { |
255,6 → 276,9 |
err_printf(m, " waiting: %s\n", yesno(error->waiting[ring])); |
err_printf(m, " ring->head: 0x%08x\n", error->cpu_ring_head[ring]); |
err_printf(m, " ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]); |
err_printf(m, " hangcheck: %s [%d]\n", |
hangcheck_action_to_str(error->hangcheck_action[ring]), |
error->hangcheck_score[ring]); |
} |
|
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) |
272,7 → 296,6 |
struct drm_device *dev = error_priv->dev; |
drm_i915_private_t *dev_priv = dev->dev_private; |
struct drm_i915_error_state *error = error_priv->error; |
struct intel_ring_buffer *ring; |
int i, j, page, offset, elt; |
|
if (!error) { |
283,7 → 306,7 |
err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, |
error->time.tv_usec); |
err_printf(m, "Kernel: " UTS_RELEASE "\n"); |
err_printf(m, "PCI ID: 0x%04x\n", dev->pci_device); |
err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device); |
err_printf(m, "EIR: 0x%08x\n", error->eir); |
err_printf(m, "IER: 0x%08x\n", error->ier); |
err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); |
290,6 → 313,7 |
err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); |
err_printf(m, "DERRMR: 0x%08x\n", error->derrmr); |
err_printf(m, "CCID: 0x%08x\n", error->ccid); |
err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings); |
|
for (i = 0; i < dev_priv->num_fence_regs; i++) |
err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); |
306,7 → 330,7 |
if (INTEL_INFO(dev)->gen == 7) |
err_printf(m, "ERR_INT: 0x%08x\n", error->err_int); |
|
for_each_ring(ring, dev_priv, i) |
for (i = 0; i < ARRAY_SIZE(error->ring); i++) |
i915_ring_error_state(m, dev, error, i); |
|
if (error->active_bo) |
363,8 → 387,7 |
} |
} |
|
obj = error->ring[i].ctx; |
if (obj) { |
if ((obj = error->ring[i].ctx)) { |
err_printf(m, "%s --- HW Context = 0x%08x\n", |
dev_priv->ring[i].name, |
obj->gtt_offset); |
601,6 → 624,7 |
|
/* Fences */ |
switch (INTEL_INFO(dev)->gen) { |
case 8: |
case 7: |
case 6: |
for (i = 0; i < dev_priv->num_fence_regs; i++) |
644,7 → 668,8 |
return NULL; |
|
obj = ring->scratch.obj; |
if (acthd >= i915_gem_obj_ggtt_offset(obj) && |
if (obj != NULL && |
acthd >= i915_gem_obj_ggtt_offset(obj) && |
acthd < i915_gem_obj_ggtt_offset(obj) + obj->base.size) |
return i915_error_object_create(dev_priv, obj); |
} |
701,8 → 726,10 |
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->bbaddr = I915_READ64(BB_ADDR); |
error->bbaddr[ring->id] = I915_READ(RING_BBADDR(ring->mmio_base)); |
if (INTEL_INFO(dev)->gen >= 8) |
error->bbaddr[ring->id] |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32; |
error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base)); |
} else { |
error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX); |
error->ipeir[ring->id] = I915_READ(IPEIR); |
720,6 → 747,9 |
|
error->cpu_ring_head[ring->id] = ring->head; |
error->cpu_ring_tail[ring->id] = ring->tail; |
|
error->hangcheck_score[ring->id] = ring->hangcheck.score; |
error->hangcheck_action[ring->id] = ring->hangcheck.action; |
} |
|
|
747,11 → 777,17 |
struct drm_i915_error_state *error) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_ring_buffer *ring; |
struct drm_i915_gem_request *request; |
int i, count; |
|
for_each_ring(ring, dev_priv, i) { |
for (i = 0; i < I915_NUM_RINGS; i++) { |
struct intel_ring_buffer *ring = &dev_priv->ring[i]; |
|
if (ring->dev == NULL) |
continue; |
|
error->ring[i].valid = true; |
|
i915_record_ring_state(dev, error, ring); |
|
error->ring[i].batchbuffer = |
769,7 → 805,7 |
|
error->ring[i].num_requests = count; |
error->ring[i].requests = |
kmalloc(count*sizeof(struct drm_i915_error_request), |
kcalloc(count, sizeof(*error->ring[i].requests), |
GFP_ATOMIC); |
if (error->ring[i].requests == NULL) { |
error->ring[i].num_requests = 0; |
811,7 → 847,7 |
error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx]; |
|
if (i) { |
active_bo = kmalloc(sizeof(*active_bo)*i, GFP_ATOMIC); |
active_bo = kcalloc(i, sizeof(*active_bo), GFP_ATOMIC); |
if (active_bo) |
pinned_bo = active_bo + error->active_bo_count[ndx]; |
} |
885,8 → 921,12 |
return; |
} |
|
DRM_INFO("capturing error event; look for more information in " |
"/sys/class/drm/card%d/error\n", dev->primary->index); |
DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n", |
dev->primary->index); |
DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n"); |
DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n"); |
DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n"); |
DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n"); |
|
kref_init(&error->ref); |
error->eir = I915_READ(EIR); |
988,6 → 1028,7 |
case I915_CACHE_NONE: return " uncached"; |
case I915_CACHE_LLC: return " snooped or LLC"; |
case I915_CACHE_L3_LLC: return " L3+LLC"; |
case I915_CACHE_WT: return " WT"; |
default: return ""; |
} |
} |
1013,6 → 1054,7 |
default: |
WARN_ONCE(1, "Unsupported platform\n"); |
case 7: |
case 8: |
instdone[0] = I915_READ(GEN7_INSTDONE_1); |
instdone[1] = I915_READ(GEN7_SC_INSTDONE); |
instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE); |