aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gpu_error.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gpu_error.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c102
1 files changed, 82 insertions, 20 deletions
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 653fb69e7ecb..7481c8e1b5a8 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -30,6 +30,8 @@
30#include <generated/utsrelease.h> 30#include <generated/utsrelease.h>
31#include <linux/stop_machine.h> 31#include <linux/stop_machine.h>
32#include <linux/zlib.h> 32#include <linux/zlib.h>
33#include <drm/drm_print.h>
34
33#include "i915_drv.h" 35#include "i915_drv.h"
34 36
35static const char *engine_str(int engine) 37static const char *engine_str(int engine)
@@ -175,6 +177,21 @@ static void i915_error_puts(struct drm_i915_error_state_buf *e,
175#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__) 177#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
176#define err_puts(e, s) i915_error_puts(e, s) 178#define err_puts(e, s) i915_error_puts(e, s)
177 179
180static void __i915_printfn_error(struct drm_printer *p, struct va_format *vaf)
181{
182 i915_error_vprintf(p->arg, vaf->fmt, *vaf->va);
183}
184
185static inline struct drm_printer
186i915_error_printer(struct drm_i915_error_state_buf *e)
187{
188 struct drm_printer p = {
189 .printfn = __i915_printfn_error,
190 .arg = e,
191 };
192 return p;
193}
194
178#ifdef CONFIG_DRM_I915_COMPRESS_ERROR 195#ifdef CONFIG_DRM_I915_COMPRESS_ERROR
179 196
180struct compress { 197struct compress {
@@ -589,6 +606,21 @@ static void err_print_pciid(struct drm_i915_error_state_buf *m,
589 pdev->subsystem_device); 606 pdev->subsystem_device);
590} 607}
591 608
609static void err_print_uc(struct drm_i915_error_state_buf *m,
610 const struct i915_error_uc *error_uc)
611{
612 struct drm_printer p = i915_error_printer(m);
613 const struct i915_gpu_state *error =
614 container_of(error_uc, typeof(*error), uc);
615
616 if (!error->device_info.has_guc)
617 return;
618
619 intel_uc_fw_dump(&error_uc->guc_fw, &p);
620 intel_uc_fw_dump(&error_uc->huc_fw, &p);
621 print_error_obj(m, NULL, "GuC log buffer", error_uc->guc_log);
622}
623
592int i915_error_state_to_str(struct drm_i915_error_state_buf *m, 624int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
593 const struct i915_gpu_state *error) 625 const struct i915_gpu_state *error)
594{ 626{
@@ -763,8 +795,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
763 795
764 print_error_obj(m, NULL, "Semaphores", error->semaphore); 796 print_error_obj(m, NULL, "Semaphores", error->semaphore);
765 797
766 print_error_obj(m, NULL, "GuC log buffer", error->guc_log);
767
768 if (error->overlay) 798 if (error->overlay)
769 intel_overlay_print_error_state(m, error->overlay); 799 intel_overlay_print_error_state(m, error->overlay);
770 800
@@ -773,6 +803,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
773 803
774 err_print_capabilities(m, &error->device_info); 804 err_print_capabilities(m, &error->device_info);
775 err_print_params(m, &error->params); 805 err_print_params(m, &error->params);
806 err_print_uc(m, &error->uc);
776 807
777 if (m->bytes == 0 && m->err) 808 if (m->bytes == 0 && m->err)
778 return m->err; 809 return m->err;
@@ -831,6 +862,22 @@ static __always_inline void free_param(const char *type, void *x)
831 kfree(*(void **)x); 862 kfree(*(void **)x);
832} 863}
833 864
865static void cleanup_params(struct i915_gpu_state *error)
866{
867#define FREE(T, x, ...) free_param(#T, &error->params.x);
868 I915_PARAMS_FOR_EACH(FREE);
869#undef FREE
870}
871
872static void cleanup_uc_state(struct i915_gpu_state *error)
873{
874 struct i915_error_uc *error_uc = &error->uc;
875
876 kfree(error_uc->guc_fw.path);
877 kfree(error_uc->huc_fw.path);
878 i915_error_object_free(error_uc->guc_log);
879}
880
834void __i915_gpu_state_free(struct kref *error_ref) 881void __i915_gpu_state_free(struct kref *error_ref)
835{ 882{
836 struct i915_gpu_state *error = 883 struct i915_gpu_state *error =
@@ -857,7 +904,6 @@ void __i915_gpu_state_free(struct kref *error_ref)
857 } 904 }
858 905
859 i915_error_object_free(error->semaphore); 906 i915_error_object_free(error->semaphore);
860 i915_error_object_free(error->guc_log);
861 907
862 for (i = 0; i < ARRAY_SIZE(error->active_bo); i++) 908 for (i = 0; i < ARRAY_SIZE(error->active_bo); i++)
863 kfree(error->active_bo[i]); 909 kfree(error->active_bo[i]);
@@ -866,9 +912,8 @@ void __i915_gpu_state_free(struct kref *error_ref)
866 kfree(error->overlay); 912 kfree(error->overlay);
867 kfree(error->display); 913 kfree(error->display);
868 914
869#define FREE(T, x, ...) free_param(#T, &error->params.x); 915 cleanup_params(error);
870 I915_PARAMS_FOR_EACH(FREE); 916 cleanup_uc_state(error);
871#undef FREE
872 917
873 kfree(error); 918 kfree(error);
874} 919}
@@ -1172,11 +1217,13 @@ static void error_record_engine_registers(struct i915_gpu_state *error,
1172 1217
1173 if (INTEL_GEN(dev_priv) >= 6) { 1218 if (INTEL_GEN(dev_priv) >= 6) {
1174 ee->rc_psmi = I915_READ(RING_PSMI_CTL(engine->mmio_base)); 1219 ee->rc_psmi = I915_READ(RING_PSMI_CTL(engine->mmio_base));
1175 ee->fault_reg = I915_READ(RING_FAULT_REG(engine)); 1220 if (INTEL_GEN(dev_priv) >= 8) {
1176 if (INTEL_GEN(dev_priv) >= 8)
1177 gen8_record_semaphore_state(error, engine, ee); 1221 gen8_record_semaphore_state(error, engine, ee);
1178 else 1222 ee->fault_reg = I915_READ(GEN8_RING_FAULT_REG);
1223 } else {
1179 gen6_record_semaphore_state(engine, ee); 1224 gen6_record_semaphore_state(engine, ee);
1225 ee->fault_reg = I915_READ(RING_FAULT_REG(engine));
1226 }
1180 } 1227 }
1181 1228
1182 if (INTEL_GEN(dev_priv) >= 4) { 1229 if (INTEL_GEN(dev_priv) >= 4) {
@@ -1559,15 +1606,25 @@ static void i915_capture_pinned_buffers(struct drm_i915_private *dev_priv,
1559 error->pinned_bo = bo; 1606 error->pinned_bo = bo;
1560} 1607}
1561 1608
1562static void i915_gem_capture_guc_log_buffer(struct drm_i915_private *dev_priv, 1609static void capture_uc_state(struct i915_gpu_state *error)
1563 struct i915_gpu_state *error)
1564{ 1610{
1565 /* Capturing log buf contents won't be useful if logging was disabled */ 1611 struct drm_i915_private *i915 = error->i915;
1566 if (!dev_priv->guc.log.vma || (i915_modparams.guc_log_level < 0)) 1612 struct i915_error_uc *error_uc = &error->uc;
1613
1614 /* Capturing uC state won't be useful if there is no GuC */
1615 if (!error->device_info.has_guc)
1567 return; 1616 return;
1568 1617
1569 error->guc_log = i915_error_object_create(dev_priv, 1618 error_uc->guc_fw = i915->guc.fw;
1570 dev_priv->guc.log.vma); 1619 error_uc->huc_fw = i915->huc.fw;
1620
1621 /* Non-default firmware paths will be specified by the modparam.
1622 * As modparams are generally accesible from the userspace make
1623 * explicit copies of the firmware paths.
1624 */
1625 error_uc->guc_fw.path = kstrdup(i915->guc.fw.path, GFP_ATOMIC);
1626 error_uc->huc_fw.path = kstrdup(i915->huc.fw.path, GFP_ATOMIC);
1627 error_uc->guc_log = i915_error_object_create(i915, i915->guc.log.vma);
1571} 1628}
1572 1629
1573/* Capture all registers which don't fit into another category. */ 1630/* Capture all registers which don't fit into another category. */
@@ -1695,6 +1752,14 @@ static __always_inline void dup_param(const char *type, void *x)
1695 *(void **)x = kstrdup(*(void **)x, GFP_ATOMIC); 1752 *(void **)x = kstrdup(*(void **)x, GFP_ATOMIC);
1696} 1753}
1697 1754
1755static void capture_params(struct i915_gpu_state *error)
1756{
1757 error->params = i915_modparams;
1758#define DUP(T, x, ...) dup_param(#T, &error->params.x);
1759 I915_PARAMS_FOR_EACH(DUP);
1760#undef DUP
1761}
1762
1698static int capture(void *data) 1763static int capture(void *data)
1699{ 1764{
1700 struct i915_gpu_state *error = data; 1765 struct i915_gpu_state *error = data;
@@ -1705,10 +1770,8 @@ static int capture(void *data)
1705 ktime_to_timeval(ktime_sub(ktime_get(), 1770 ktime_to_timeval(ktime_sub(ktime_get(),
1706 error->i915->gt.last_init_time)); 1771 error->i915->gt.last_init_time));
1707 1772
1708 error->params = i915_modparams; 1773 capture_params(error);
1709#define DUP(T, x, ...) dup_param(#T, &error->params.x); 1774 capture_uc_state(error);
1710 I915_PARAMS_FOR_EACH(DUP);
1711#undef DUP
1712 1775
1713 i915_capture_gen_state(error->i915, error); 1776 i915_capture_gen_state(error->i915, error);
1714 i915_capture_reg_state(error->i915, error); 1777 i915_capture_reg_state(error->i915, error);
@@ -1716,7 +1779,6 @@ static int capture(void *data)
1716 i915_gem_record_rings(error->i915, error); 1779 i915_gem_record_rings(error->i915, error);
1717 i915_capture_active_buffers(error->i915, error); 1780 i915_capture_active_buffers(error->i915, error);
1718 i915_capture_pinned_buffers(error->i915, error); 1781 i915_capture_pinned_buffers(error->i915, error);
1719 i915_gem_capture_guc_log_buffer(error->i915, error);
1720 1782
1721 error->overlay = intel_overlay_capture_error_state(error->i915); 1783 error->overlay = intel_overlay_capture_error_state(error->i915);
1722 error->display = intel_display_capture_error_state(error->i915); 1784 error->display = intel_display_capture_error_state(error->i915);