diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index d030cd7..58a1118 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -240,6 +240,13 @@ static u32 i915_perf_stream_paranoid = true;
  */
 #define OA_EXPONENT_MAX 31
 
+#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;
@@ -279,7 +286,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 {
 	u32 sample_flags;
@@ -385,6 +393,27 @@ static int append_oa_sample(struct i915_perf_stream *stream,
 		return -EFAULT;
 	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(buf, &source, 4))
+			return -EFAULT;
+		buf += 4;
+	}
+
 	if (sample_flags & SAMPLE_OA_REPORT) {
 		if (copy_to_user(buf, report, report_size))
 			return -EFAULT;
@@ -1453,11 +1482,6 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
 		return -EINVAL;
 	}
 
-	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;
@@ -1486,8 +1510,20 @@ 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) {
+		if (!(props->sample_flags & SAMPLE_OA_REPORT)) {
+			DRM_ERROR(
+			"OA source type can't be sampled without OA report");
+			return -EINVAL;
+		}
+		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);
@@ -2160,6 +2196,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_PROP_SAMPLE_OA_SOURCE:
+			props->sample_flags |= SAMPLE_OA_SOURCE_INFO;
+			break;
 		case DRM_I915_PERF_PROP_MAX:
 			BUG();
 		}
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index e95f666..0583812 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1244,6 +1244,14 @@ enum drm_i915_oa_format {
 	I915_OA_FORMAT_MAX	    /* non-ABI */
 };
 
+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
@@ -1278,6 +1286,13 @@ enum drm_i915_perf_property_id {
 	 */
 	DRM_I915_PERF_PROP_OA_EXPONENT,
 
+	/**
+	 * 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_PROP_SAMPLE_OA_SOURCE,
+
 	DRM_I915_PERF_PROP_MAX /* non-ABI */
 };
 
@@ -1342,6 +1357,7 @@ enum drm_i915_perf_record_type {
 	 * struct {
 	 *     struct drm_i915_perf_record_header header;
 	 *
+	 *     { u32 source_info; } && DRM_I915_PERF_PROP_SAMPLE_OA_SOURCE
 	 *     { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA
 	 * };
 	 */
