diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 116 |
1 files changed, 71 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5bd4361ea84d..6442ff269642 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, | |||
720 | reloc_offset = src->gtt_offset; | 720 | reloc_offset = src->gtt_offset; |
721 | for (page = 0; page < page_count; page++) { | 721 | for (page = 0; page < page_count; page++) { |
722 | unsigned long flags; | 722 | unsigned long flags; |
723 | void __iomem *s; | ||
724 | void *d; | 723 | void *d; |
725 | 724 | ||
726 | d = kmalloc(PAGE_SIZE, GFP_ATOMIC); | 725 | d = kmalloc(PAGE_SIZE, GFP_ATOMIC); |
@@ -728,10 +727,29 @@ i915_error_object_create(struct drm_i915_private *dev_priv, | |||
728 | goto unwind; | 727 | goto unwind; |
729 | 728 | ||
730 | local_irq_save(flags); | 729 | local_irq_save(flags); |
731 | s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | 730 | if (reloc_offset < dev_priv->mm.gtt_mappable_end) { |
732 | reloc_offset); | 731 | void __iomem *s; |
733 | memcpy_fromio(d, s, PAGE_SIZE); | 732 | |
734 | io_mapping_unmap_atomic(s); | 733 | /* Simply ignore tiling or any overlapping fence. |
734 | * It's part of the error state, and this hopefully | ||
735 | * captures what the GPU read. | ||
736 | */ | ||
737 | |||
738 | s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | ||
739 | reloc_offset); | ||
740 | memcpy_fromio(d, s, PAGE_SIZE); | ||
741 | io_mapping_unmap_atomic(s); | ||
742 | } else { | ||
743 | void *s; | ||
744 | |||
745 | drm_clflush_pages(&src->pages[page], 1); | ||
746 | |||
747 | s = kmap_atomic(src->pages[page]); | ||
748 | memcpy(d, s, PAGE_SIZE); | ||
749 | kunmap_atomic(s); | ||
750 | |||
751 | drm_clflush_pages(&src->pages[page], 1); | ||
752 | } | ||
735 | local_irq_restore(flags); | 753 | local_irq_restore(flags); |
736 | 754 | ||
737 | dst->pages[page] = d; | 755 | dst->pages[page] = d; |
@@ -804,7 +822,7 @@ static u32 capture_bo_list(struct drm_i915_error_buffer *err, | |||
804 | err->tiling = obj->tiling_mode; | 822 | err->tiling = obj->tiling_mode; |
805 | err->dirty = obj->dirty; | 823 | err->dirty = obj->dirty; |
806 | err->purgeable = obj->madv != I915_MADV_WILLNEED; | 824 | err->purgeable = obj->madv != I915_MADV_WILLNEED; |
807 | err->ring = obj->ring ? obj->ring->id : 0; | 825 | err->ring = obj->ring ? obj->ring->id : -1; |
808 | err->cache_level = obj->cache_level; | 826 | err->cache_level = obj->cache_level; |
809 | 827 | ||
810 | if (++i == count) | 828 | if (++i == count) |
@@ -876,6 +894,39 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv, | |||
876 | return NULL; | 894 | return NULL; |
877 | } | 895 | } |
878 | 896 | ||
897 | static void i915_record_ring_state(struct drm_device *dev, | ||
898 | struct drm_i915_error_state *error, | ||
899 | struct intel_ring_buffer *ring) | ||
900 | { | ||
901 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
902 | |||
903 | if (INTEL_INFO(dev)->gen >= 6) { | ||
904 | error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base)); | ||
905 | error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring)); | ||
906 | } | ||
907 | |||
908 | if (INTEL_INFO(dev)->gen >= 4) { | ||
909 | error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base)); | ||
910 | error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base)); | ||
911 | error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base)); | ||
912 | error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base)); | ||
913 | if (ring->id == RCS) { | ||
914 | error->instdone1 = I915_READ(INSTDONE1); | ||
915 | error->bbaddr = I915_READ64(BB_ADDR); | ||
916 | } | ||
917 | } else { | ||
918 | error->ipeir[ring->id] = I915_READ(IPEIR); | ||
919 | error->ipehr[ring->id] = I915_READ(IPEHR); | ||
920 | error->instdone[ring->id] = I915_READ(INSTDONE); | ||
921 | } | ||
922 | |||
923 | error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base)); | ||
924 | error->seqno[ring->id] = ring->get_seqno(ring); | ||
925 | error->acthd[ring->id] = intel_ring_get_active_head(ring); | ||
926 | error->head[ring->id] = I915_READ_HEAD(ring); | ||
927 | error->tail[ring->id] = I915_READ_TAIL(ring); | ||
928 | } | ||
929 | |||
879 | /** | 930 | /** |
880 | * i915_capture_error_state - capture an error record for later analysis | 931 | * i915_capture_error_state - capture an error record for later analysis |
881 | * @dev: drm device | 932 | * @dev: drm device |
@@ -900,7 +951,7 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
900 | return; | 951 | return; |
901 | 952 | ||
902 | /* Account for pipe specific data like PIPE*STAT */ | 953 | /* Account for pipe specific data like PIPE*STAT */ |
903 | error = kmalloc(sizeof(*error), GFP_ATOMIC); | 954 | error = kzalloc(sizeof(*error), GFP_ATOMIC); |
904 | if (!error) { | 955 | if (!error) { |
905 | DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); | 956 | DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); |
906 | return; | 957 | return; |
@@ -909,47 +960,22 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
909 | DRM_INFO("capturing error event; look for more information in /debug/dri/%d/i915_error_state\n", | 960 | DRM_INFO("capturing error event; look for more information in /debug/dri/%d/i915_error_state\n", |
910 | dev->primary->index); | 961 | dev->primary->index); |
911 | 962 | ||
912 | error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]); | ||
913 | error->eir = I915_READ(EIR); | 963 | error->eir = I915_READ(EIR); |
914 | error->pgtbl_er = I915_READ(PGTBL_ER); | 964 | error->pgtbl_er = I915_READ(PGTBL_ER); |
915 | for_each_pipe(pipe) | 965 | for_each_pipe(pipe) |
916 | error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); | 966 | error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); |
917 | error->instpm = I915_READ(INSTPM); | 967 | |
918 | error->error = 0; | ||
919 | if (INTEL_INFO(dev)->gen >= 6) { | 968 | if (INTEL_INFO(dev)->gen >= 6) { |
920 | error->error = I915_READ(ERROR_GEN6); | 969 | error->error = I915_READ(ERROR_GEN6); |
921 | 970 | error->done_reg = I915_READ(DONE_REG); | |
922 | error->bcs_acthd = I915_READ(BCS_ACTHD); | ||
923 | error->bcs_ipehr = I915_READ(BCS_IPEHR); | ||
924 | error->bcs_ipeir = I915_READ(BCS_IPEIR); | ||
925 | error->bcs_instdone = I915_READ(BCS_INSTDONE); | ||
926 | error->bcs_seqno = 0; | ||
927 | if (dev_priv->ring[BCS].get_seqno) | ||
928 | error->bcs_seqno = dev_priv->ring[BCS].get_seqno(&dev_priv->ring[BCS]); | ||
929 | |||
930 | error->vcs_acthd = I915_READ(VCS_ACTHD); | ||
931 | error->vcs_ipehr = I915_READ(VCS_IPEHR); | ||
932 | error->vcs_ipeir = I915_READ(VCS_IPEIR); | ||
933 | error->vcs_instdone = I915_READ(VCS_INSTDONE); | ||
934 | error->vcs_seqno = 0; | ||
935 | if (dev_priv->ring[VCS].get_seqno) | ||
936 | error->vcs_seqno = dev_priv->ring[VCS].get_seqno(&dev_priv->ring[VCS]); | ||
937 | } | ||
938 | if (INTEL_INFO(dev)->gen >= 4) { | ||
939 | error->ipeir = I915_READ(IPEIR_I965); | ||
940 | error->ipehr = I915_READ(IPEHR_I965); | ||
941 | error->instdone = I915_READ(INSTDONE_I965); | ||
942 | error->instps = I915_READ(INSTPS); | ||
943 | error->instdone1 = I915_READ(INSTDONE1); | ||
944 | error->acthd = I915_READ(ACTHD_I965); | ||
945 | error->bbaddr = I915_READ64(BB_ADDR); | ||
946 | } else { | ||
947 | error->ipeir = I915_READ(IPEIR); | ||
948 | error->ipehr = I915_READ(IPEHR); | ||
949 | error->instdone = I915_READ(INSTDONE); | ||
950 | error->acthd = I915_READ(ACTHD); | ||
951 | error->bbaddr = 0; | ||
952 | } | 971 | } |
972 | |||
973 | i915_record_ring_state(dev, error, &dev_priv->ring[RCS]); | ||
974 | if (HAS_BLT(dev)) | ||
975 | i915_record_ring_state(dev, error, &dev_priv->ring[BCS]); | ||
976 | if (HAS_BSD(dev)) | ||
977 | i915_record_ring_state(dev, error, &dev_priv->ring[VCS]); | ||
978 | |||
953 | i915_gem_record_fences(dev, error); | 979 | i915_gem_record_fences(dev, error); |
954 | 980 | ||
955 | /* Record the active batch and ring buffers */ | 981 | /* Record the active batch and ring buffers */ |
@@ -1017,11 +1043,12 @@ void i915_destroy_error_state(struct drm_device *dev) | |||
1017 | { | 1043 | { |
1018 | struct drm_i915_private *dev_priv = dev->dev_private; | 1044 | struct drm_i915_private *dev_priv = dev->dev_private; |
1019 | struct drm_i915_error_state *error; | 1045 | struct drm_i915_error_state *error; |
1046 | unsigned long flags; | ||
1020 | 1047 | ||
1021 | spin_lock(&dev_priv->error_lock); | 1048 | spin_lock_irqsave(&dev_priv->error_lock, flags); |
1022 | error = dev_priv->first_error; | 1049 | error = dev_priv->first_error; |
1023 | dev_priv->first_error = NULL; | 1050 | dev_priv->first_error = NULL; |
1024 | spin_unlock(&dev_priv->error_lock); | 1051 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); |
1025 | 1052 | ||
1026 | if (error) | 1053 | if (error) |
1027 | i915_error_state_free(dev, error); | 1054 | i915_error_state_free(dev, error); |
@@ -1698,6 +1725,7 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
1698 | dev_priv->last_instdone1 == instdone1) { | 1725 | dev_priv->last_instdone1 == instdone1) { |
1699 | if (dev_priv->hangcheck_count++ > 1) { | 1726 | if (dev_priv->hangcheck_count++ > 1) { |
1700 | DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); | 1727 | DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); |
1728 | i915_handle_error(dev, true); | ||
1701 | 1729 | ||
1702 | if (!IS_GEN2(dev)) { | 1730 | if (!IS_GEN2(dev)) { |
1703 | /* Is the chip hanging on a WAIT_FOR_EVENT? | 1731 | /* Is the chip hanging on a WAIT_FOR_EVENT? |
@@ -1705,7 +1733,6 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
1705 | * and break the hang. This should work on | 1733 | * and break the hang. This should work on |
1706 | * all but the second generation chipsets. | 1734 | * all but the second generation chipsets. |
1707 | */ | 1735 | */ |
1708 | |||
1709 | if (kick_ring(&dev_priv->ring[RCS])) | 1736 | if (kick_ring(&dev_priv->ring[RCS])) |
1710 | goto repeat; | 1737 | goto repeat; |
1711 | 1738 | ||
@@ -1718,7 +1745,6 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
1718 | goto repeat; | 1745 | goto repeat; |
1719 | } | 1746 | } |
1720 | 1747 | ||
1721 | i915_handle_error(dev, true); | ||
1722 | return; | 1748 | return; |
1723 | } | 1749 | } |
1724 | } else { | 1750 | } else { |