drm/i915/perf: workaround register corruption in OATAILPTR
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Tue, 17 Nov 2020 13:01:24 +0000 (15:01 +0200)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Tue, 24 Nov 2020 17:17:41 +0000 (09:17 -0800)
After having written the entire OA buffer with reports, the HW will
write again at the beginning of the OA buffer. It'll indicate it by
setting the WRAP bits in the OASTATUS register.

When a wrap happens and that at the end of the read vfunc we write the
OASTATUS register back to clear the REPORT_LOST bit, we sometimes see
that the OATAILPTR register is reset to a previous position on Gen8/9
(apparently not the case on Gen11+). This leads the next call to the
read vfunc to process reports we've already read. Because we've marked
those as read by clearing the reason & timestamp dwords, they're
discarded and a "Skipping spurious, invalid OA report" message is
emitted.

The workaround to avoid this OATAILPTR value reset seems to be to set
the wrap bits when writing back OASTATUS.

This change has no impact on userspace, it only avoids a bunch of
DRM_NOTE("Skipping spurious, invalid OA report\n") messages.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Fixes: 19f81df2859eb1 ("drm/i915/perf: Add OA unit support for Gen 8+")
Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201117130124.829979-1-lionel.g.landwerlin@intel.com
(cherry picked from commit 059a0beb486344a577ff476acce75e69eab704be)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_reg.h

index e94976976571fe61181dd87f24cb3227eb7a544a..3640d0e229d22595b6f5d9e44d98f663e401520d 100644 (file)
@@ -909,8 +909,13 @@ static int gen8_oa_read(struct i915_perf_stream *stream,
                                       DRM_I915_PERF_RECORD_OA_REPORT_LOST);
                if (ret)
                        return ret;
-               intel_uncore_write(uncore, oastatus_reg,
-                                  oastatus & ~GEN8_OASTATUS_REPORT_LOST);
+
+               intel_uncore_rmw(uncore, oastatus_reg,
+                                GEN8_OASTATUS_COUNTER_OVERFLOW |
+                                GEN8_OASTATUS_REPORT_LOST,
+                                IS_GEN_RANGE(uncore->i915, 8, 10) ?
+                                (GEN8_OASTATUS_HEAD_POINTER_WRAP |
+                                 GEN8_OASTATUS_TAIL_POINTER_WRAP) : 0);
        }
 
        return gen8_append_oa_reports(stream, buf, count, offset);
index 664f3bf9af03c631decd35875df8fd214f1cf1a6..5cd83eac940c321424eeeb87ec1ddb6b0f14489a 100644 (file)
@@ -676,6 +676,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define  GEN7_OASTATUS2_MEM_SELECT_GGTT     (1 << 0) /* 0: PPGTT, 1: GGTT */
 
 #define GEN8_OASTATUS _MMIO(0x2b08)
+#define  GEN8_OASTATUS_TAIL_POINTER_WRAP    (1 << 17)
+#define  GEN8_OASTATUS_HEAD_POINTER_WRAP    (1 << 16)
 #define  GEN8_OASTATUS_OVERRUN_STATUS      (1 << 3)
 #define  GEN8_OASTATUS_COUNTER_OVERFLOW     (1 << 2)
 #define  GEN8_OASTATUS_OABUFFER_OVERFLOW    (1 << 1)