@@ -2129,6 +2129,12 @@ struct i915_oa_ops {
*/
u32 (*oa_buffer_num_reports)(struct drm_i915_private *dev_priv,
u32 *last_ts);
+
+ /**
+ * @get_ctx_id: Retrieve the ctx_id associated with the (periodic) OA
+ * report.
+ */
+ u32 (*get_ctx_id)(struct i915_perf_stream *stream, const u8 *report);
};
/*
@@ -2613,6 +2619,7 @@ struct drm_i915_private {
u32 status;
} command_stream_buf;
+ u32 last_cmd_stream_ctx_id;
struct list_head cs_samples;
spinlock_t sample_lock;
} perf;
@@ -850,6 +850,46 @@ static u32 gen7_oa_buffer_num_reports_unlocked(
return aged_tail == INVALID_TAIL_PTR ? 0 : num_reports;
}
+static u32 gen7_oa_buffer_get_ctx_id(struct i915_perf_stream *stream,
+ const u8 *report)
+{
+ struct drm_i915_private *dev_priv = stream->dev_priv;
+
+ if (!stream->cs_mode)
+ WARN_ONCE(1,
+ "CTX ID can't be retrieved if command stream mode not enabled");
+
+ /*
+ * OA reports generated in Gen7 don't have the ctx ID information.
+ * Therefore, just rely on the ctx ID information from the last CS
+ * sample forwarded
+ */
+ return dev_priv->perf.last_cmd_stream_ctx_id;
+}
+
+static u32 gen8_oa_buffer_get_ctx_id(struct i915_perf_stream *stream,
+ const u8 *report)
+{
+ struct drm_i915_private *dev_priv = stream->dev_priv;
+
+ /* The ctx ID present in the OA reports have intel_context::hw_id
+ * present, since this is programmed into the ELSP in execlist mode.
+ * In non-execlist mode, fall back to retrieving the ctx ID from the
+ * last saved ctx ID from command stream mode.
+ */
+ if (i915.enable_execlists) {
+ u32 *report32 = (void *)report;
+ u32 ctx_id = report32[2] & 0x1fffff;
+ return ctx_id;
+ } else {
+ if (!stream->cs_mode)
+ WARN_ONCE(1,
+ "CTX ID can't be retrieved if command stream mode not enabled");
+
+ return dev_priv->perf.last_cmd_stream_ctx_id;
+ }
+}
+
/**
* append_oa_status - Appends a status record to a userspace read() buffer.
* @stream: An i915-perf stream opened for OA metrics
@@ -963,18 +1003,15 @@ static int append_oa_buffer_sample(struct i915_perf_stream *stream,
char __user *buf, size_t count,
size_t *offset, const u8 *report)
{
+ struct drm_i915_private *dev_priv = stream->dev_priv;
u32 sample_flags = stream->sample_flags;
struct oa_sample_data data = { 0 };
if (sample_flags & SAMPLE_OA_SOURCE_INFO)
data.source = I915_PERF_OA_EVENT_SOURCE_PERIODIC;
- /*
- * FIXME: append_oa_buffer_sample: read ctx ID from report and map
- * that to a intel_context::hw_id"
- */
if (sample_flags & SAMPLE_CTX_ID)
- data.ctx_id = 0;
+ data.ctx_id = dev_priv->perf.oa.ops.get_ctx_id(stream, report);
if (sample_flags & SAMPLE_OA_REPORT)
data.report = report;
@@ -1547,8 +1584,10 @@ static int append_oa_rcs_sample(struct i915_perf_stream *stream,
if (sample_flags & SAMPLE_OA_SOURCE_INFO)
data.source = I915_PERF_OA_EVENT_SOURCE_RCS;
- if (sample_flags & SAMPLE_CTX_ID)
+ if (sample_flags & SAMPLE_CTX_ID) {
data.ctx_id = node->ctx_id;
+ dev_priv->perf.last_cmd_stream_ctx_id = node->ctx_id;
+ }
if (sample_flags & SAMPLE_OA_REPORT)
data.report = report;
@@ -3794,6 +3833,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
dev_priv->perf.oa.ops.read = gen7_oa_read;
dev_priv->perf.oa.ops.oa_buffer_num_reports =
gen7_oa_buffer_num_reports_unlocked;
+ dev_priv->perf.oa.ops.get_ctx_id = gen7_oa_buffer_get_ctx_id;
dev_priv->perf.oa.oa_formats = hsw_oa_formats;
@@ -3859,6 +3899,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
dev_priv->perf.oa.ops.read = gen8_oa_read;
dev_priv->perf.oa.ops.oa_buffer_num_reports =
gen8_oa_buffer_num_reports_unlocked;
+ dev_priv->perf.oa.ops.get_ctx_id = gen8_oa_buffer_get_ctx_id;
dev_priv->perf.oa.oa_formats = gen8_plus_oa_formats;
}