+ /* For Gen8+ since the counters continue while other
+ * contexts are running we need to discount any unrelated
+ * deltas. The hardware automatically generates a report
+ * on context switch which gives us a new reference point
+ * to continuing adding deltas from.
+ *
+ * For Haswell we can rely on the HW to stop the progress
+ * of OA counters while any other context is acctive.
+ */
+ if (devinfo->gen >= 8) {
+ if (in_ctx && report[2] != ctx_id) {
+ DBG("i915 perf: Switch AWAY (observed by ID change)\n");
+ in_ctx = false;
+ out_duration = 0;
+ } else if (in_ctx == false && report[2] == ctx_id) {
+ DBG("i915 perf: Switch TO\n");
+ in_ctx = true;
+
+ /* From experimentation in IGT, we found that the OA unit
+ * might label some report as "idle" (using an invalid
+ * context ID), right after a report for a given context.
+ * Deltas generated by those reports actually belong to the
+ * previous context, even though they're not labelled as
+ * such.
+ *
+ * We didn't *really* Switch AWAY in the case that we e.g.
+ * saw a single periodic report while idle...
+ */
+ if (out_duration >= 1)
+ add = false;
+ } else if (in_ctx) {
+ assert(report[2] == ctx_id);
+ DBG("i915 perf: Continuation IN\n");
+ } else {
+ assert(report[2] != ctx_id);
+ DBG("i915 perf: Continuation OUT\n");
+ add = false;
+ out_duration++;
+ }
+ }
+
+ if (add)
+ add_deltas(brw, obj, last, report);