@@ -44,6 +44,13 @@ static u32 i915_perf_stream_paranoid = true;
#define OA_EXPONENT_MAX 0x3f
+#define GEN8_OAREPORT_REASON_TIMER (1<<19)
+#define GEN8_OAREPORT_REASON_TRIGGER1 (1<<20)
+#define GEN8_OAREPORT_REASON_TRIGGER2 (1<<21)
+#define GEN8_OAREPORT_REASON_CTX_SWITCH (1<<22)
+#define GEN8_OAREPORT_REASON_GO_TRANSITION (1<<23)
+#define GEN9_OAREPORT_REASON_CLK_RATIO (1<<24)
+
/* for sysctl proc_dointvec_minmax of i915_oa_min_timer_exponent */
static int zero;
static int oa_exponent_max = OA_EXPONENT_MAX;
@@ -79,7 +86,8 @@ static struct i915_oa_format gen8_plus_oa_formats[I915_OA_FORMAT_MAX] = {
[I915_OA_FORMAT_C4_B8] = { 7, 64 },
};
-#define SAMPLE_OA_REPORT (1<<0)
+#define SAMPLE_OA_REPORT (1<<0)
+#define SAMPLE_OA_SOURCE_INFO (1<<1)
struct perf_open_properties
{
@@ -149,6 +157,27 @@ static bool append_oa_sample(struct i915_perf_stream *stream,
copy_to_user(read_state->buf, &header, sizeof(header));
read_state->buf += sizeof(header);
+ if (sample_flags & SAMPLE_OA_SOURCE_INFO) {
+ enum drm_i915_perf_oa_event_source source;
+
+ if (INTEL_INFO(dev_priv)->gen >= 8) {
+ u32 reason = *(u32 *)report;
+
+ if (reason & GEN8_OAREPORT_REASON_CTX_SWITCH)
+ source =
+ I915_PERF_OA_EVENT_SOURCE_CONTEXT_SWITCH;
+ else if (reason & GEN8_OAREPORT_REASON_TIMER)
+ source = I915_PERF_OA_EVENT_SOURCE_PERIODIC;
+ else
+ source = I915_PERF_OA_EVENT_SOURCE_UNDEFINED;
+ } else
+ source = I915_PERF_OA_EVENT_SOURCE_PERIODIC;
+
+ if (copy_to_user(read_state->buf, &source, 4))
+ return false;
+ read_state->buf += 4;
+ }
+
if (sample_flags & SAMPLE_OA_REPORT) {
copy_to_user(read_state->buf, report, report_size);
read_state->buf += report_size;
@@ -841,11 +870,6 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
int format_size;
int ret;
- if (!(props->sample_flags & SAMPLE_OA_REPORT)) {
- DRM_ERROR("Only OA report sampling supported\n");
- return -EINVAL;
- }
-
if (!dev_priv->perf.oa.ops.init_oa_buffer) {
DRM_ERROR("OA unit not supported\n");
return -ENODEV;
@@ -873,8 +897,15 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
format_size = dev_priv->perf.oa.oa_formats[props->oa_format].size;
- stream->sample_flags |= SAMPLE_OA_REPORT;
- stream->sample_size += format_size;
+ if (props->sample_flags & SAMPLE_OA_REPORT) {
+ stream->sample_flags |= SAMPLE_OA_REPORT;
+ stream->sample_size += format_size;
+ }
+
+ if (props->sample_flags & SAMPLE_OA_SOURCE_INFO) {
+ stream->sample_flags |= SAMPLE_OA_SOURCE_INFO;
+ stream->sample_size += 4;
+ }
dev_priv->perf.oa.oa_buffer.format_size = format_size;
BUG_ON(dev_priv->perf.oa.oa_buffer.format_size == 0);
@@ -1480,6 +1511,9 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv,
props->oa_periodic = true;
props->oa_period_exponent = value;
break;
+ case DRM_I915_PERF_SAMPLE_OA_SOURCE_PROP:
+ props->sample_flags |= SAMPLE_OA_SOURCE_INFO;
+ break;
case DRM_I915_PERF_PROP_MAX:
BUG();
}
@@ -1156,6 +1156,14 @@ enum drm_i915_oa_format {
#define I915_PERF_FLAG_FD_NONBLOCK (1<<1)
#define I915_PERF_FLAG_DISABLED (1<<2)
+enum drm_i915_perf_oa_event_source {
+ I915_PERF_OA_EVENT_SOURCE_UNDEFINED,
+ I915_PERF_OA_EVENT_SOURCE_PERIODIC,
+ I915_PERF_OA_EVENT_SOURCE_CONTEXT_SWITCH,
+
+ I915_PERF_OA_EVENT_SOURCE_MAX /* non-ABI */
+};
+
enum drm_i915_perf_property_id {
/**
* Open the stream for a specific context handle (as used with
@@ -1190,6 +1198,13 @@ enum drm_i915_perf_property_id {
*/
DRM_I915_PERF_OA_EXPONENT_PROP,
+ /**
+ * The value of this property set to 1 requests inclusion of sample
+ * source field to be given to userspace. The sample source field
+ * specifies the origin of OA report.
+ */
+ DRM_I915_PERF_SAMPLE_OA_SOURCE_PROP,
+
DRM_I915_PERF_PROP_MAX /* non-ABI */
};
@@ -1237,6 +1252,7 @@ enum drm_i915_perf_record_type {
* struct {
* struct drm_i915_perf_record_header header;
*
+ * { u32 source_info; } && DRM_I915_PERF_SAMPLE_OA_SOURCE_PROP
* { u32 oa_report[]; } && DRM_I915_PERF_SAMPLE_OA_PROP
* };
*/