diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gpu_error.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gpu_error.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index dae364f0028c..79dcb8f896c6 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c | |||
@@ -215,6 +215,24 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m, | |||
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | static const char *hangcheck_action_to_str(enum intel_ring_hangcheck_action a) | ||
219 | { | ||
220 | switch (a) { | ||
221 | case HANGCHECK_IDLE: | ||
222 | return "idle"; | ||
223 | case HANGCHECK_WAIT: | ||
224 | return "wait"; | ||
225 | case HANGCHECK_ACTIVE: | ||
226 | return "active"; | ||
227 | case HANGCHECK_KICK: | ||
228 | return "kick"; | ||
229 | case HANGCHECK_HUNG: | ||
230 | return "hung"; | ||
231 | } | ||
232 | |||
233 | return "unknown"; | ||
234 | } | ||
235 | |||
218 | static void i915_ring_error_state(struct drm_i915_error_state_buf *m, | 236 | static void i915_ring_error_state(struct drm_i915_error_state_buf *m, |
219 | struct drm_device *dev, | 237 | struct drm_device *dev, |
220 | struct drm_i915_error_state *error, | 238 | struct drm_i915_error_state *error, |
@@ -231,7 +249,8 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m, | |||
231 | err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]); | 249 | err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]); |
232 | if (ring == RCS && INTEL_INFO(dev)->gen >= 4) | 250 | if (ring == RCS && INTEL_INFO(dev)->gen >= 4) |
233 | err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr); | 251 | err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr); |
234 | 252 | if (INTEL_INFO(dev)->gen >= 4) | |
253 | err_printf(m, " BB_STATE: 0x%08x\n", error->bbstate[ring]); | ||
235 | if (INTEL_INFO(dev)->gen >= 4) | 254 | if (INTEL_INFO(dev)->gen >= 4) |
236 | err_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]); | 255 | err_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]); |
237 | err_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); | 256 | err_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); |
@@ -255,6 +274,9 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m, | |||
255 | err_printf(m, " waiting: %s\n", yesno(error->waiting[ring])); | 274 | err_printf(m, " waiting: %s\n", yesno(error->waiting[ring])); |
256 | err_printf(m, " ring->head: 0x%08x\n", error->cpu_ring_head[ring]); | 275 | err_printf(m, " ring->head: 0x%08x\n", error->cpu_ring_head[ring]); |
257 | err_printf(m, " ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]); | 276 | err_printf(m, " ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]); |
277 | err_printf(m, " hangcheck: %s [%d]\n", | ||
278 | hangcheck_action_to_str(error->hangcheck_action[ring]), | ||
279 | error->hangcheck_score[ring]); | ||
258 | } | 280 | } |
259 | 281 | ||
260 | void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) | 282 | void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) |
@@ -283,13 +305,14 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
283 | err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, | 305 | err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, |
284 | error->time.tv_usec); | 306 | error->time.tv_usec); |
285 | err_printf(m, "Kernel: " UTS_RELEASE "\n"); | 307 | err_printf(m, "Kernel: " UTS_RELEASE "\n"); |
286 | err_printf(m, "PCI ID: 0x%04x\n", dev->pci_device); | 308 | err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device); |
287 | err_printf(m, "EIR: 0x%08x\n", error->eir); | 309 | err_printf(m, "EIR: 0x%08x\n", error->eir); |
288 | err_printf(m, "IER: 0x%08x\n", error->ier); | 310 | err_printf(m, "IER: 0x%08x\n", error->ier); |
289 | err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); | 311 | err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); |
290 | err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); | 312 | err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); |
291 | err_printf(m, "DERRMR: 0x%08x\n", error->derrmr); | 313 | err_printf(m, "DERRMR: 0x%08x\n", error->derrmr); |
292 | err_printf(m, "CCID: 0x%08x\n", error->ccid); | 314 | err_printf(m, "CCID: 0x%08x\n", error->ccid); |
315 | err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings); | ||
293 | 316 | ||
294 | for (i = 0; i < dev_priv->num_fence_regs; i++) | 317 | for (i = 0; i < dev_priv->num_fence_regs; i++) |
295 | err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); | 318 | err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); |
@@ -601,6 +624,7 @@ static void i915_gem_record_fences(struct drm_device *dev, | |||
601 | 624 | ||
602 | /* Fences */ | 625 | /* Fences */ |
603 | switch (INTEL_INFO(dev)->gen) { | 626 | switch (INTEL_INFO(dev)->gen) { |
627 | case 8: | ||
604 | case 7: | 628 | case 7: |
605 | case 6: | 629 | case 6: |
606 | for (i = 0; i < dev_priv->num_fence_regs; i++) | 630 | for (i = 0; i < dev_priv->num_fence_regs; i++) |
@@ -703,6 +727,7 @@ static void i915_record_ring_state(struct drm_device *dev, | |||
703 | error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base)); | 727 | error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base)); |
704 | if (ring->id == RCS) | 728 | if (ring->id == RCS) |
705 | error->bbaddr = I915_READ64(BB_ADDR); | 729 | error->bbaddr = I915_READ64(BB_ADDR); |
730 | error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base)); | ||
706 | } else { | 731 | } else { |
707 | error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX); | 732 | error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX); |
708 | error->ipeir[ring->id] = I915_READ(IPEIR); | 733 | error->ipeir[ring->id] = I915_READ(IPEIR); |
@@ -720,6 +745,9 @@ static void i915_record_ring_state(struct drm_device *dev, | |||
720 | 745 | ||
721 | error->cpu_ring_head[ring->id] = ring->head; | 746 | error->cpu_ring_head[ring->id] = ring->head; |
722 | error->cpu_ring_tail[ring->id] = ring->tail; | 747 | error->cpu_ring_tail[ring->id] = ring->tail; |
748 | |||
749 | error->hangcheck_score[ring->id] = ring->hangcheck.score; | ||
750 | error->hangcheck_action[ring->id] = ring->hangcheck.action; | ||
723 | } | 751 | } |
724 | 752 | ||
725 | 753 | ||
@@ -769,7 +797,7 @@ static void i915_gem_record_rings(struct drm_device *dev, | |||
769 | 797 | ||
770 | error->ring[i].num_requests = count; | 798 | error->ring[i].num_requests = count; |
771 | error->ring[i].requests = | 799 | error->ring[i].requests = |
772 | kmalloc(count*sizeof(struct drm_i915_error_request), | 800 | kcalloc(count, sizeof(*error->ring[i].requests), |
773 | GFP_ATOMIC); | 801 | GFP_ATOMIC); |
774 | if (error->ring[i].requests == NULL) { | 802 | if (error->ring[i].requests == NULL) { |
775 | error->ring[i].num_requests = 0; | 803 | error->ring[i].num_requests = 0; |
@@ -811,7 +839,7 @@ static void i915_gem_capture_vm(struct drm_i915_private *dev_priv, | |||
811 | error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx]; | 839 | error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx]; |
812 | 840 | ||
813 | if (i) { | 841 | if (i) { |
814 | active_bo = kmalloc(sizeof(*active_bo)*i, GFP_ATOMIC); | 842 | active_bo = kcalloc(i, sizeof(*active_bo), GFP_ATOMIC); |
815 | if (active_bo) | 843 | if (active_bo) |
816 | pinned_bo = active_bo + error->active_bo_count[ndx]; | 844 | pinned_bo = active_bo + error->active_bo_count[ndx]; |
817 | } | 845 | } |
@@ -885,8 +913,12 @@ void i915_capture_error_state(struct drm_device *dev) | |||
885 | return; | 913 | return; |
886 | } | 914 | } |
887 | 915 | ||
888 | DRM_INFO("capturing error event; look for more information in " | 916 | DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n", |
889 | "/sys/class/drm/card%d/error\n", dev->primary->index); | 917 | dev->primary->index); |
918 | DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n"); | ||
919 | DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n"); | ||
920 | DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n"); | ||
921 | DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n"); | ||
890 | 922 | ||
891 | kref_init(&error->ref); | 923 | kref_init(&error->ref); |
892 | error->eir = I915_READ(EIR); | 924 | error->eir = I915_READ(EIR); |
@@ -988,6 +1020,7 @@ const char *i915_cache_level_str(int type) | |||
988 | case I915_CACHE_NONE: return " uncached"; | 1020 | case I915_CACHE_NONE: return " uncached"; |
989 | case I915_CACHE_LLC: return " snooped or LLC"; | 1021 | case I915_CACHE_LLC: return " snooped or LLC"; |
990 | case I915_CACHE_L3_LLC: return " L3+LLC"; | 1022 | case I915_CACHE_L3_LLC: return " L3+LLC"; |
1023 | case I915_CACHE_WT: return " WT"; | ||
991 | default: return ""; | 1024 | default: return ""; |
992 | } | 1025 | } |
993 | } | 1026 | } |
@@ -1012,6 +1045,7 @@ void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone) | |||
1012 | default: | 1045 | default: |
1013 | WARN_ONCE(1, "Unsupported platform\n"); | 1046 | WARN_ONCE(1, "Unsupported platform\n"); |
1014 | case 7: | 1047 | case 7: |
1048 | case 8: | ||
1015 | instdone[0] = I915_READ(GEN7_INSTDONE_1); | 1049 | instdone[0] = I915_READ(GEN7_INSTDONE_1); |
1016 | instdone[1] = I915_READ(GEN7_SC_INSTDONE); | 1050 | instdone[1] = I915_READ(GEN7_SC_INSTDONE); |
1017 | instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE); | 1051 | instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE); |