|
10 | 10 | #include "i915_irq.h"
|
11 | 11 | #include "i915_reg.h"
|
12 | 12 | #include "icl_dsi_regs.h"
|
| 13 | +#include "intel_atomic_plane.h" |
13 | 14 | #include "intel_crtc.h"
|
14 | 15 | #include "intel_de.h"
|
15 | 16 | #include "intel_display_irq.h"
|
@@ -67,6 +68,52 @@ intel_display_irq_regs_assert_irr_is_zero(struct intel_display *display, i915_re
|
67 | 68 | intel_dmc_wl_put(display, reg);
|
68 | 69 | }
|
69 | 70 |
|
| 71 | +struct pipe_fault_handler { |
| 72 | + bool (*handle)(struct intel_crtc *crtc, enum plane_id plane_id); |
| 73 | + u32 fault; |
| 74 | + enum plane_id plane_id; |
| 75 | +}; |
| 76 | + |
| 77 | +static bool handle_plane_fault(struct intel_crtc *crtc, enum plane_id plane_id) |
| 78 | +{ |
| 79 | + struct intel_display *display = to_intel_display(crtc); |
| 80 | + struct intel_plane_error error = {}; |
| 81 | + struct intel_plane *plane; |
| 82 | + |
| 83 | + plane = intel_crtc_get_plane(crtc, plane_id); |
| 84 | + if (!plane || !plane->capture_error) |
| 85 | + return false; |
| 86 | + |
| 87 | + plane->capture_error(crtc, plane, &error); |
| 88 | + |
| 89 | + drm_err_ratelimited(display->drm, |
| 90 | + "[CRTC:%d:%s][PLANE:%d:%s] fault (CTL=0x%x, SURF=0x%x, SURFLIVE=0x%x)\n", |
| 91 | + crtc->base.base.id, crtc->base.name, |
| 92 | + plane->base.base.id, plane->base.name, |
| 93 | + error.ctl, error.surf, error.surflive); |
| 94 | + |
| 95 | + return true; |
| 96 | +} |
| 97 | + |
| 98 | +static void intel_pipe_fault_irq_handler(struct intel_display *display, |
| 99 | + const struct pipe_fault_handler *handlers, |
| 100 | + enum pipe pipe, u32 fault_errors) |
| 101 | +{ |
| 102 | + struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe); |
| 103 | + const struct pipe_fault_handler *handler; |
| 104 | + |
| 105 | + for (handler = handlers; handler && handler->fault; handler++) { |
| 106 | + if ((fault_errors & handler->fault) == 0) |
| 107 | + continue; |
| 108 | + |
| 109 | + if (handler->handle(crtc, handler->plane_id)) |
| 110 | + fault_errors &= ~handler->fault; |
| 111 | + } |
| 112 | + |
| 113 | + WARN_ONCE(fault_errors, "[CRTC:%d:%s] unreported faults 0x%x\n", |
| 114 | + crtc->base.base.id, crtc->base.name, fault_errors); |
| 115 | +} |
| 116 | + |
70 | 117 | static void
|
71 | 118 | intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
|
72 | 119 | {
|
@@ -947,6 +994,108 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
|
947 | 994 | GEN8_PIPE_PRIMARY_FAULT;
|
948 | 995 | }
|
949 | 996 |
|
| 997 | +static bool handle_plane_ats_fault(struct intel_crtc *crtc, enum plane_id plane_id) |
| 998 | +{ |
| 999 | + struct intel_display *display = to_intel_display(crtc); |
| 1000 | + |
| 1001 | + drm_err_ratelimited(display->drm, |
| 1002 | + "[CRTC:%d:%s] PLANE ATS fault\n", |
| 1003 | + crtc->base.base.id, crtc->base.name); |
| 1004 | + |
| 1005 | + return false; |
| 1006 | +} |
| 1007 | + |
| 1008 | +static bool handle_pipedmc_ats_fault(struct intel_crtc *crtc, enum plane_id plane_id) |
| 1009 | +{ |
| 1010 | + struct intel_display *display = to_intel_display(crtc); |
| 1011 | + |
| 1012 | + drm_err_ratelimited(display->drm, |
| 1013 | + "[CRTC:%d:%s] PIPEDMC ATS fault\n", |
| 1014 | + crtc->base.base.id, crtc->base.name); |
| 1015 | + |
| 1016 | + return false; |
| 1017 | +} |
| 1018 | + |
| 1019 | +static bool handle_pipedmc_fault(struct intel_crtc *crtc, enum plane_id plane_id) |
| 1020 | +{ |
| 1021 | + struct intel_display *display = to_intel_display(crtc); |
| 1022 | + |
| 1023 | + drm_err_ratelimited(display->drm, |
| 1024 | + "[CRTC:%d:%s] PIPEDMC fault\n", |
| 1025 | + crtc->base.base.id, crtc->base.name); |
| 1026 | + |
| 1027 | + return false; |
| 1028 | +} |
| 1029 | + |
| 1030 | +static const struct pipe_fault_handler mtl_pipe_fault_handlers[] = { |
| 1031 | + { .fault = MTL_PLANE_ATS_FAULT, .handle = handle_plane_ats_fault, }, |
| 1032 | + { .fault = MTL_PIPEDMC_ATS_FAULT, .handle = handle_pipedmc_ats_fault, }, |
| 1033 | + { .fault = GEN12_PIPEDMC_FAULT, .handle = handle_pipedmc_fault, }, |
| 1034 | + { .fault = GEN11_PIPE_PLANE5_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_5, }, |
| 1035 | + { .fault = GEN9_PIPE_PLANE4_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_4, }, |
| 1036 | + { .fault = GEN9_PIPE_PLANE3_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_3, }, |
| 1037 | + { .fault = GEN9_PIPE_PLANE2_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_2, }, |
| 1038 | + { .fault = GEN9_PIPE_PLANE1_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_1, }, |
| 1039 | + { .fault = GEN9_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, |
| 1040 | + {} |
| 1041 | +}; |
| 1042 | + |
| 1043 | +static const struct pipe_fault_handler tgl_pipe_fault_handlers[] = { |
| 1044 | + { .fault = GEN12_PIPEDMC_FAULT, .handle = handle_pipedmc_fault, }, |
| 1045 | + { .fault = GEN11_PIPE_PLANE7_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_7, }, |
| 1046 | + { .fault = GEN11_PIPE_PLANE6_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_6, }, |
| 1047 | + { .fault = GEN11_PIPE_PLANE5_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_5, }, |
| 1048 | + { .fault = GEN9_PIPE_PLANE4_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_4, }, |
| 1049 | + { .fault = GEN9_PIPE_PLANE3_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_3, }, |
| 1050 | + { .fault = GEN9_PIPE_PLANE2_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_2, }, |
| 1051 | + { .fault = GEN9_PIPE_PLANE1_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_1, }, |
| 1052 | + { .fault = GEN9_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, |
| 1053 | + {} |
| 1054 | +}; |
| 1055 | + |
| 1056 | +static const struct pipe_fault_handler icl_pipe_fault_handlers[] = { |
| 1057 | + { .fault = GEN11_PIPE_PLANE7_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_7, }, |
| 1058 | + { .fault = GEN11_PIPE_PLANE6_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_6, }, |
| 1059 | + { .fault = GEN11_PIPE_PLANE5_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_5, }, |
| 1060 | + { .fault = GEN9_PIPE_PLANE4_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_4, }, |
| 1061 | + { .fault = GEN9_PIPE_PLANE3_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_3, }, |
| 1062 | + { .fault = GEN9_PIPE_PLANE2_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_2, }, |
| 1063 | + { .fault = GEN9_PIPE_PLANE1_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_1, }, |
| 1064 | + { .fault = GEN9_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, |
| 1065 | + {} |
| 1066 | +}; |
| 1067 | + |
| 1068 | +static const struct pipe_fault_handler skl_pipe_fault_handlers[] = { |
| 1069 | + { .fault = GEN9_PIPE_PLANE4_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_4, }, |
| 1070 | + { .fault = GEN9_PIPE_PLANE3_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_3, }, |
| 1071 | + { .fault = GEN9_PIPE_PLANE2_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_2, }, |
| 1072 | + { .fault = GEN9_PIPE_PLANE1_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_1, }, |
| 1073 | + { .fault = GEN9_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, |
| 1074 | + {} |
| 1075 | +}; |
| 1076 | + |
| 1077 | +static const struct pipe_fault_handler bdw_pipe_fault_handlers[] = { |
| 1078 | + { .fault = GEN8_PIPE_SPRITE_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, |
| 1079 | + { .fault = GEN8_PIPE_PRIMARY_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, |
| 1080 | + { .fault = GEN8_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, |
| 1081 | + {} |
| 1082 | +}; |
| 1083 | + |
| 1084 | +static const struct pipe_fault_handler * |
| 1085 | +gen8_pipe_fault_handlers(struct intel_display *display) |
| 1086 | +{ |
| 1087 | + if (DISPLAY_VER(display) >= 14) |
| 1088 | + return mtl_pipe_fault_handlers; |
| 1089 | + else if (DISPLAY_VER(display) >= 12) |
| 1090 | + return tgl_pipe_fault_handlers; |
| 1091 | + else if (DISPLAY_VER(display) >= 11) |
| 1092 | + return icl_pipe_fault_handlers; |
| 1093 | + else if (DISPLAY_VER(display) >= 9) |
| 1094 | + return skl_pipe_fault_handlers; |
| 1095 | + else |
| 1096 | + return bdw_pipe_fault_handlers; |
| 1097 | +} |
| 1098 | + |
950 | 1099 | static void intel_pmdemand_irq_handler(struct drm_i915_private *dev_priv)
|
951 | 1100 | {
|
952 | 1101 | wake_up_all(&dev_priv->display.pmdemand.waitqueue);
|
@@ -1233,10 +1382,9 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
|
1233 | 1382 |
|
1234 | 1383 | fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
|
1235 | 1384 | if (fault_errors)
|
1236 |
| - drm_err_ratelimited(&dev_priv->drm, |
1237 |
| - "Fault errors on pipe %c: 0x%08x\n", |
1238 |
| - pipe_name(pipe), |
1239 |
| - fault_errors); |
| 1385 | + intel_pipe_fault_irq_handler(display, |
| 1386 | + gen8_pipe_fault_handlers(display), |
| 1387 | + pipe, fault_errors); |
1240 | 1388 | }
|
1241 | 1389 |
|
1242 | 1390 | if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
|
|
0 commit comments