[Intel-gfx] [PATCH] drm/i915/perf: Refactor oa object to better manage resources

Lionel Landwerlin lionel.g.landwerlin at intel.com
Thu May 2 10:26:57 UTC 2019


On 01/05/2019 17:50, Umesh Nerlige Ramappa wrote:
> The oa object manages the oa buffer and must be allocated when the user
> intends to read performance counter snapshots. This can be achieved by
> making the oa object part of the stream object which is allocated when a
> stream is opened by the user.
>
> Attributes in the oa object that are gen-specific are moved to the perf
> object so that they can be initialized on driver load.
>
> The split provides a better separation of the objects used in perf
> implementation of i915 driver so that resources are allocated and
> initialized only when needed.
>
> Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa at intel.com>


This refactoring makes sense.

I've opened a PR on gputop to match the changes in the generated files : 
https://github.com/rib/gputop/pull/201


Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>


> ---
>   drivers/gpu/drm/i915/gt/intel_sseu.c  |   2 +-
>   drivers/gpu/drm/i915/gvt/scheduler.c  |   4 +-
>   drivers/gpu/drm/i915/i915_drv.h       | 219 +++++-----
>   drivers/gpu/drm/i915/i915_oa_bdw.c    |  30 +-
>   drivers/gpu/drm/i915/i915_oa_bxt.c    |  30 +-
>   drivers/gpu/drm/i915/i915_oa_cflgt2.c |  30 +-
>   drivers/gpu/drm/i915/i915_oa_cflgt3.c |  30 +-
>   drivers/gpu/drm/i915/i915_oa_chv.c    |  30 +-
>   drivers/gpu/drm/i915/i915_oa_cnl.c    |  30 +-
>   drivers/gpu/drm/i915/i915_oa_glk.c    |  30 +-
>   drivers/gpu/drm/i915/i915_oa_hsw.c    |  30 +-
>   drivers/gpu/drm/i915/i915_oa_icl.c    |  30 +-
>   drivers/gpu/drm/i915/i915_oa_kblgt2.c |  30 +-
>   drivers/gpu/drm/i915/i915_oa_kblgt3.c |  30 +-
>   drivers/gpu/drm/i915/i915_oa_sklgt2.c |  30 +-
>   drivers/gpu/drm/i915/i915_oa_sklgt3.c |  30 +-
>   drivers/gpu/drm/i915/i915_oa_sklgt4.c |  30 +-
>   drivers/gpu/drm/i915/i915_perf.c      | 580 ++++++++++++++------------
>   18 files changed, 627 insertions(+), 598 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
> index 7f448f3bea0b..fa78df39521a 100644
> --- a/drivers/gpu/drm/i915/gt/intel_sseu.c
> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
> @@ -32,7 +32,7 @@ u32 intel_sseu_make_rpcs(struct drm_i915_private *i915,
>   	 * cases which disable slices for functional, apart for performance
>   	 * reasons. So in this case we select a known stable subset.
>   	 */
> -	if (!i915->perf.oa.exclusive_stream) {
> +	if (!i915->perf.exclusive_stream) {
>   		ctx_sseu = *req_sseu;
>   	} else {
>   		ctx_sseu = intel_sseu_from_device_info(sseu);
> diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
> index 7ae42f2ebfe8..878e71a927de 100644
> --- a/drivers/gpu/drm/i915/gvt/scheduler.c
> +++ b/drivers/gpu/drm/i915/gvt/scheduler.c
> @@ -81,8 +81,8 @@ static void sr_oa_regs(struct intel_vgpu_workload *workload,
>   		u32 *reg_state, bool save)
>   {
>   	struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv;
> -	u32 ctx_oactxctrl = dev_priv->perf.oa.ctx_oactxctrl_offset;
> -	u32 ctx_flexeu0 = dev_priv->perf.oa.ctx_flexeu0_offset;
> +	u32 ctx_oactxctrl = dev_priv->perf.ctx_oactxctrl_offset;
> +	u32 ctx_flexeu0 = dev_priv->perf.ctx_flexeu0_offset;
>   	int i = 0;
>   	u32 flex_mmio[] = {
>   		i915_mmio_reg_offset(EU_PERF_CNTL0),
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 1cea98f8b85c..9536550f11cc 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1399,6 +1399,86 @@ struct i915_perf_stream {
>   	 * @oa_config: The OA configuration used by the stream.
>   	 */
>   	struct i915_oa_config *oa_config;
> +
> +	/**
> +	 * The OA context specific information.
> +	 */
> +	struct intel_context *pinned_ctx;
> +	u32 specific_ctx_id;
> +	u32 specific_ctx_id_mask;
> +
> +	struct hrtimer poll_check_timer;
> +	wait_queue_head_t poll_wq;
> +	bool pollin;
> +
> +	bool periodic;
> +	int period_exponent;
> +
> +	/**
> +	 * State of the OA buffer.
> +	 */
> +	struct {
> +		struct i915_vma *vma;
> +		u8 *vaddr;
> +		u32 last_ctx_id;
> +		int format;
> +		int format_size;
> +		int size_exponent;
> +
> +		/**
> +		 * Locks reads and writes to all head/tail state
> +		 *
> +		 * Consider: the head and tail pointer state needs to be read
> +		 * consistently from a hrtimer callback (atomic context) and
> +		 * read() fop (user context) with tail pointer updates happening
> +		 * in atomic context and head updates in user context and the
> +		 * (unlikely) possibility of read() errors needing to reset all
> +		 * head/tail state.
> +		 *
> +		 * Note: Contention/performance aren't currently a significant
> +		 * concern here considering the relatively low frequency of
> +		 * hrtimer callbacks (5ms period) and that reads typically only
> +		 * happen in response to a hrtimer event and likely complete
> +		 * before the next callback.
> +		 *
> +		 * Note: This lock is not held *while* reading and copying data
> +		 * to userspace so the value of head observed in htrimer
> +		 * callbacks won't represent any partial consumption of data.
> +		 */
> +		spinlock_t ptr_lock;
> +
> +		/**
> +		 * One 'aging' tail pointer and one 'aged' tail pointer ready to
> +		 * used for reading.
> +		 *
> +		 * Initial values of 0xffffffff are invalid and imply that an
> +		 * update is required (and should be ignored by an attempted
> +		 * read)
> +		 */
> +		struct {
> +			u32 offset;
> +		} tails[2];
> +
> +		/**
> +		 * Index for the aged tail ready to read() data up to.
> +		 */
> +		unsigned int aged_tail_idx;
> +
> +		/**
> +		 * A monotonic timestamp for when the current aging tail pointer
> +		 * was read; used to determine when it is old enough to trust.
> +		 */
> +		u64 aging_timestamp;
> +
> +		/**
> +		 * Although we can always read back the head pointer register,
> +		 * we prefer to avoid trusting the HW state, just to avoid any
> +		 * risk that some hardware condition could * somehow bump the
> +		 * head pointer unpredictably and cause us to forward the wrong
> +		 * OA buffer data to userspace.
> +		 */
> +		u32 head;
> +	} oa_buffer;
>   };
>   
>   /**
> @@ -1436,7 +1516,7 @@ struct i915_oa_ops {
>   	 * @disable_metric_set: Remove system constraints associated with using
>   	 * the OA unit.
>   	 */
> -	void (*disable_metric_set)(struct drm_i915_private *dev_priv);
> +	void (*disable_metric_set)(struct i915_perf_stream *stream);
>   
>   	/**
>   	 * @oa_enable: Enable periodic sampling
> @@ -1464,7 +1544,7 @@ struct i915_oa_ops {
>   	 * handling the OA unit tail pointer race that affects multiple
>   	 * generations.
>   	 */
> -	u32 (*oa_hw_tail_read)(struct drm_i915_private *dev_priv);
> +	u32 (*oa_hw_tail_read)(struct i915_perf_stream *stream);
>   };
>   
>   struct intel_cdclk_state {
> @@ -1867,120 +1947,35 @@ struct drm_i915_private {
>   		struct mutex lock;
>   		struct list_head streams;
>   
> -		struct {
> -			/*
> -			 * The stream currently using the OA unit. If accessed
> -			 * outside a syscall associated to its file
> -			 * descriptor, you need to hold
> -			 * dev_priv->drm.struct_mutex.
> -			 */
> -			struct i915_perf_stream *exclusive_stream;
> +		/*
> +		 * The stream currently using the OA unit. If accessed
> +		 * outside a syscall associated to its file
> +		 * descriptor, you need to hold
> +		 * dev_priv->drm.struct_mutex.
> +		 */
> +		struct i915_perf_stream *exclusive_stream;
> +
> +		/**
> +		 * For rate limiting any notifications of spurious
> +		 * invalid OA reports
> +		 */
> +		struct ratelimit_state spurious_report_rs;
>   
> -			struct intel_context *pinned_ctx;
> -			u32 specific_ctx_id;
> -			u32 specific_ctx_id_mask;
> +		struct i915_oa_config test_config;
>   
> -			struct hrtimer poll_check_timer;
> -			wait_queue_head_t poll_wq;
> -			bool pollin;
> +		u32 gen7_latched_oastatus1;
> +		u32 ctx_oactxctrl_offset;
> +		u32 ctx_flexeu0_offset;
>   
> -			/**
> -			 * For rate limiting any notifications of spurious
> -			 * invalid OA reports
> -			 */
> -			struct ratelimit_state spurious_report_rs;
> -
> -			bool periodic;
> -			int period_exponent;
> -
> -			struct i915_oa_config test_config;
> -
> -			struct {
> -				struct i915_vma *vma;
> -				u8 *vaddr;
> -				u32 last_ctx_id;
> -				int format;
> -				int format_size;
> -
> -				/**
> -				 * Locks reads and writes to all head/tail state
> -				 *
> -				 * Consider: the head and tail pointer state
> -				 * needs to be read consistently from a hrtimer
> -				 * callback (atomic context) and read() fop
> -				 * (user context) with tail pointer updates
> -				 * happening in atomic context and head updates
> -				 * in user context and the (unlikely)
> -				 * possibility of read() errors needing to
> -				 * reset all head/tail state.
> -				 *
> -				 * Note: Contention or performance aren't
> -				 * currently a significant concern here
> -				 * considering the relatively low frequency of
> -				 * hrtimer callbacks (5ms period) and that
> -				 * reads typically only happen in response to a
> -				 * hrtimer event and likely complete before the
> -				 * next callback.
> -				 *
> -				 * Note: This lock is not held *while* reading
> -				 * and copying data to userspace so the value
> -				 * of head observed in htrimer callbacks won't
> -				 * represent any partial consumption of data.
> -				 */
> -				spinlock_t ptr_lock;
> -
> -				/**
> -				 * One 'aging' tail pointer and one 'aged'
> -				 * tail pointer ready to used for reading.
> -				 *
> -				 * Initial values of 0xffffffff are invalid
> -				 * and imply that an update is required
> -				 * (and should be ignored by an attempted
> -				 * read)
> -				 */
> -				struct {
> -					u32 offset;
> -				} tails[2];
> -
> -				/**
> -				 * Index for the aged tail ready to read()
> -				 * data up to.
> -				 */
> -				unsigned int aged_tail_idx;
> -
> -				/**
> -				 * A monotonic timestamp for when the current
> -				 * aging tail pointer was read; used to
> -				 * determine when it is old enough to trust.
> -				 */
> -				u64 aging_timestamp;
> -
> -				/**
> -				 * Although we can always read back the head
> -				 * pointer register, we prefer to avoid
> -				 * trusting the HW state, just to avoid any
> -				 * risk that some hardware condition could
> -				 * somehow bump the head pointer unpredictably
> -				 * and cause us to forward the wrong OA buffer
> -				 * data to userspace.
> -				 */
> -				u32 head;
> -			} oa_buffer;
> -
> -			u32 gen7_latched_oastatus1;
> -			u32 ctx_oactxctrl_offset;
> -			u32 ctx_flexeu0_offset;
> -
> -			/**
> -			 * The RPT_ID/reason field for Gen8+ includes a bit
> -			 * to determine if the CTX ID in the report is valid
> -			 * but the specific bit differs between Gen 8 and 9
> -			 */
> -			u32 gen8_valid_ctx_bit;
> +		/**
> +		 * The RPT_ID/reason field for Gen8+ includes a bit
> +		 * to determine if the CTX ID in the report is valid
> +		 * but the specific bit differs between Gen 8 and 9
> +		 */
> +		u32 gen8_valid_ctx_bit;
>   
> -			struct i915_oa_ops ops;
> -			const struct i915_oa_format *oa_formats;
> -		} oa;
> +		struct i915_oa_ops ops;
> +		const struct i915_oa_format *oa_formats;
>   	} perf;
>   
>   	/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
> diff --git a/drivers/gpu/drm/i915/i915_oa_bdw.c b/drivers/gpu/drm/i915/i915_oa_bdw.c
> index 4acdb94555b7..7d632d503510 100644
> --- a/drivers/gpu/drm/i915/i915_oa_bdw.c
> +++ b/drivers/gpu/drm/i915/i915_oa_bdw.c
> @@ -66,26 +66,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_bdw(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"d6de6f55-e526-4f79-a6a6-d7315c09044e",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "d6de6f55-e526-4f79-a6a6-d7315c09044e";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "d6de6f55-e526-4f79-a6a6-d7315c09044e";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_bxt.c b/drivers/gpu/drm/i915/i915_oa_bxt.c
> index a44195c39923..a4cc584fb5c9 100644
> --- a/drivers/gpu/drm/i915/i915_oa_bxt.c
> +++ b/drivers/gpu/drm/i915/i915_oa_bxt.c
> @@ -64,26 +64,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_bxt(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"5ee72f5c-092f-421e-8b70-225f7c3e9612",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "5ee72f5c-092f-421e-8b70-225f7c3e9612";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "5ee72f5c-092f-421e-8b70-225f7c3e9612";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_cflgt2.c b/drivers/gpu/drm/i915/i915_oa_cflgt2.c
> index 7f60d51b8761..51930c71bf7c 100644
> --- a/drivers/gpu/drm/i915/i915_oa_cflgt2.c
> +++ b/drivers/gpu/drm/i915/i915_oa_cflgt2.c
> @@ -65,26 +65,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_cflgt2(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"74fb4902-d3d3-4237-9e90-cbdc68d0a446",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "74fb4902-d3d3-4237-9e90-cbdc68d0a446";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "74fb4902-d3d3-4237-9e90-cbdc68d0a446";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_cflgt3.c b/drivers/gpu/drm/i915/i915_oa_cflgt3.c
> index a92c38e3a0ce..de630b53d364 100644
> --- a/drivers/gpu/drm/i915/i915_oa_cflgt3.c
> +++ b/drivers/gpu/drm/i915/i915_oa_cflgt3.c
> @@ -65,26 +65,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_cflgt3(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"577e8e2c-3fa0-4875-8743-3538d585e3b0",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "577e8e2c-3fa0-4875-8743-3538d585e3b0";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "577e8e2c-3fa0-4875-8743-3538d585e3b0";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_chv.c b/drivers/gpu/drm/i915/i915_oa_chv.c
> index 71ec889a0114..7d7f33c4468f 100644
> --- a/drivers/gpu/drm/i915/i915_oa_chv.c
> +++ b/drivers/gpu/drm/i915/i915_oa_chv.c
> @@ -65,26 +65,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_chv(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"4a534b07-cba3-414d-8d60-874830e883aa",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "4a534b07-cba3-414d-8d60-874830e883aa";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "4a534b07-cba3-414d-8d60-874830e883aa";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_cnl.c b/drivers/gpu/drm/i915/i915_oa_cnl.c
> index 5c23d883d6c9..4ae86a8983c3 100644
> --- a/drivers/gpu/drm/i915/i915_oa_cnl.c
> +++ b/drivers/gpu/drm/i915/i915_oa_cnl.c
> @@ -77,26 +77,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_cnl(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"db41edd4-d8e7-4730-ad11-b9a2d6833503",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "db41edd4-d8e7-4730-ad11-b9a2d6833503";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "db41edd4-d8e7-4730-ad11-b9a2d6833503";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_glk.c b/drivers/gpu/drm/i915/i915_oa_glk.c
> index 4bdda66df7d2..d8d634dca158 100644
> --- a/drivers/gpu/drm/i915/i915_oa_glk.c
> +++ b/drivers/gpu/drm/i915/i915_oa_glk.c
> @@ -64,26 +64,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_glk(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"dd3fd789-e783-4204-8cd0-b671bbccb0cf",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "dd3fd789-e783-4204-8cd0-b671bbccb0cf";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "dd3fd789-e783-4204-8cd0-b671bbccb0cf";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_hsw.c b/drivers/gpu/drm/i915/i915_oa_hsw.c
> index cc6526fdd2bd..7032277876db 100644
> --- a/drivers/gpu/drm/i915/i915_oa_hsw.c
> +++ b/drivers/gpu/drm/i915/i915_oa_hsw.c
> @@ -94,26 +94,26 @@ show_render_basic_id(struct device *kdev, struct device_attribute *attr, char *b
>   void
>   i915_perf_load_test_config_hsw(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"403d8832-1a27-4aa6-a64e-f5389ce7b212",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_render_basic;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_render_basic);
> +	dev_priv->perf.test_config.mux_regs = mux_config_render_basic;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_render_basic);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_render_basic;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_render_basic);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_render_basic;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_render_basic);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_render_basic;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_render_basic);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_render_basic;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_render_basic);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "403d8832-1a27-4aa6-a64e-f5389ce7b212";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "403d8832-1a27-4aa6-a64e-f5389ce7b212";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_render_basic_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_render_basic_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_icl.c b/drivers/gpu/drm/i915/i915_oa_icl.c
> index baa51427a543..bca23f150626 100644
> --- a/drivers/gpu/drm/i915/i915_oa_icl.c
> +++ b/drivers/gpu/drm/i915/i915_oa_icl.c
> @@ -74,26 +74,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_icl(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"a291665e-244b-4b76-9b9a-01de9d3c8068",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "a291665e-244b-4b76-9b9a-01de9d3c8068";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "a291665e-244b-4b76-9b9a-01de9d3c8068";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_kblgt2.c b/drivers/gpu/drm/i915/i915_oa_kblgt2.c
> index 168e49ab0d4d..2e1d12f78c9b 100644
> --- a/drivers/gpu/drm/i915/i915_oa_kblgt2.c
> +++ b/drivers/gpu/drm/i915/i915_oa_kblgt2.c
> @@ -65,26 +65,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_kblgt2(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"baa3c7e4-52b6-4b85-801e-465a94b746dd",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "baa3c7e4-52b6-4b85-801e-465a94b746dd";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "baa3c7e4-52b6-4b85-801e-465a94b746dd";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_kblgt3.c b/drivers/gpu/drm/i915/i915_oa_kblgt3.c
> index 6ffa553c388e..07a8567bd5be 100644
> --- a/drivers/gpu/drm/i915/i915_oa_kblgt3.c
> +++ b/drivers/gpu/drm/i915/i915_oa_kblgt3.c
> @@ -65,26 +65,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_kblgt3(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"f1792f32-6db2-4b50-b4b2-557128f1688d",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "f1792f32-6db2-4b50-b4b2-557128f1688d";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "f1792f32-6db2-4b50-b4b2-557128f1688d";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_sklgt2.c b/drivers/gpu/drm/i915/i915_oa_sklgt2.c
> index 7ce6ee851d43..fa463a92f5bb 100644
> --- a/drivers/gpu/drm/i915/i915_oa_sklgt2.c
> +++ b/drivers/gpu/drm/i915/i915_oa_sklgt2.c
> @@ -64,26 +64,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_sklgt2(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"1651949f-0ac0-4cb1-a06f-dafd74a407d1",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "1651949f-0ac0-4cb1-a06f-dafd74a407d1";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "1651949f-0ac0-4cb1-a06f-dafd74a407d1";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_sklgt3.c b/drivers/gpu/drm/i915/i915_oa_sklgt3.c
> index 086ca2631e1c..9c9497d7a9d5 100644
> --- a/drivers/gpu/drm/i915/i915_oa_sklgt3.c
> +++ b/drivers/gpu/drm/i915/i915_oa_sklgt3.c
> @@ -65,26 +65,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_sklgt3(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"2b985803-d3c9-4629-8a4f-634bfecba0e8",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "2b985803-d3c9-4629-8a4f-634bfecba0e8";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "2b985803-d3c9-4629-8a4f-634bfecba0e8";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_oa_sklgt4.c b/drivers/gpu/drm/i915/i915_oa_sklgt4.c
> index b291a6eb8a87..65ebc6b8dd70 100644
> --- a/drivers/gpu/drm/i915/i915_oa_sklgt4.c
> +++ b/drivers/gpu/drm/i915/i915_oa_sklgt4.c
> @@ -65,26 +65,26 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
>   void
>   i915_perf_load_test_config_sklgt4(struct drm_i915_private *dev_priv)
>   {
> -	strlcpy(dev_priv->perf.oa.test_config.uuid,
> +	strlcpy(dev_priv->perf.test_config.uuid,
>   		"882fa433-1f4a-4a67-a962-c741888fe5f5",
> -		sizeof(dev_priv->perf.oa.test_config.uuid));
> -	dev_priv->perf.oa.test_config.id = 1;
> +		sizeof(dev_priv->perf.test_config.uuid));
> +	dev_priv->perf.test_config.id = 1;
>   
> -	dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;
> -	dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
> +	dev_priv->perf.test_config.mux_regs = mux_config_test_oa;
> +	dev_priv->perf.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa;
> -	dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
> +	dev_priv->perf.test_config.b_counter_regs = b_counter_config_test_oa;
> +	dev_priv->perf.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa;
> -	dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
> +	dev_priv->perf.test_config.flex_regs = flex_eu_config_test_oa;
> +	dev_priv->perf.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa);
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric.name = "882fa433-1f4a-4a67-a962-c741888fe5f5";
> -	dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs;
> +	dev_priv->perf.test_config.sysfs_metric.name = "882fa433-1f4a-4a67-a962-c741888fe5f5";
> +	dev_priv->perf.test_config.sysfs_metric.attrs = dev_priv->perf.test_config.attrs;
>   
> -	dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr;
> +	dev_priv->perf.test_config.attrs[0] = &dev_priv->perf.test_config.sysfs_metric_id.attr;
>   
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id";
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444;
> -	dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id;
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.name = "id";
> +	dev_priv->perf.test_config.sysfs_metric_id.attr.mode = 0444;
> +	dev_priv->perf.test_config.sysfs_metric_id.show = show_test_oa_id;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
> index c4995d5a16d2..be3f68461c50 100644
> --- a/drivers/gpu/drm/i915/i915_perf.c
> +++ b/drivers/gpu/drm/i915/i915_perf.c
> @@ -364,6 +364,8 @@ struct perf_open_properties {
>   	int oa_period_exponent;
>   };
>   
> +static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer);
> +
>   static void free_oa_config(struct drm_i915_private *dev_priv,
>   			   struct i915_oa_config *oa_config)
>   {
> @@ -392,8 +394,8 @@ static int get_oa_config(struct drm_i915_private *dev_priv,
>   	int ret;
>   
>   	if (metrics_set == 1) {
> -		*out_config = &dev_priv->perf.oa.test_config;
> -		atomic_inc(&dev_priv->perf.oa.test_config.ref_count);
> +		*out_config = &dev_priv->perf.test_config;
> +		atomic_inc(&dev_priv->perf.test_config.ref_count);
>   		return 0;
>   	}
>   
> @@ -412,13 +414,16 @@ static int get_oa_config(struct drm_i915_private *dev_priv,
>   	return ret;
>   }
>   
> -static u32 gen8_oa_hw_tail_read(struct drm_i915_private *dev_priv)
> +static u32 gen8_oa_hw_tail_read(struct i915_perf_stream *stream)
>   {
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
> +
>   	return I915_READ(GEN8_OATAILPTR) & GEN8_OATAILPTR_MASK;
>   }
>   
> -static u32 gen7_oa_hw_tail_read(struct drm_i915_private *dev_priv)
> +static u32 gen7_oa_hw_tail_read(struct i915_perf_stream *stream)
>   {
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
>   	u32 oastatus1 = I915_READ(GEN7_OASTATUS1);
>   
>   	return oastatus1 & GEN7_OASTATUS1_TAIL_MASK;
> @@ -426,7 +431,7 @@ static u32 gen7_oa_hw_tail_read(struct drm_i915_private *dev_priv)
>   
>   /**
>    * oa_buffer_check_unlocked - check for data and update tail ptr state
> - * @dev_priv: i915 device instance
> + * @stream: i915 stream instance
>    *
>    * This is either called via fops (for blocking reads in user ctx) or the poll
>    * check hrtimer (atomic ctx) to check the OA buffer tail pointer and check
> @@ -448,9 +453,10 @@ static u32 gen7_oa_hw_tail_read(struct drm_i915_private *dev_priv)
>    *
>    * Returns: %true if the OA buffer contains data, else %false
>    */
> -static bool oa_buffer_check_unlocked(struct drm_i915_private *dev_priv)
> +static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream)
>   {
> -	int report_size = dev_priv->perf.oa.oa_buffer.format_size;
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
> +	int report_size = stream->oa_buffer.format_size;
>   	unsigned long flags;
>   	unsigned int aged_idx;
>   	u32 head, hw_tail, aged_tail, aging_tail;
> @@ -460,19 +466,19 @@ static bool oa_buffer_check_unlocked(struct drm_i915_private *dev_priv)
>   	 * could result in an OA buffer reset which might reset the head,
>   	 * tails[] and aged_tail state.
>   	 */
> -	spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
>   
>   	/* NB: The head we observe here might effectively be a little out of
>   	 * date (between head and tails[aged_idx].offset if there is currently
>   	 * a read() in progress.
>   	 */
> -	head = dev_priv->perf.oa.oa_buffer.head;
> +	head = stream->oa_buffer.head;
>   
> -	aged_idx = dev_priv->perf.oa.oa_buffer.aged_tail_idx;
> -	aged_tail = dev_priv->perf.oa.oa_buffer.tails[aged_idx].offset;
> -	aging_tail = dev_priv->perf.oa.oa_buffer.tails[!aged_idx].offset;
> +	aged_idx = stream->oa_buffer.aged_tail_idx;
> +	aged_tail = stream->oa_buffer.tails[aged_idx].offset;
> +	aging_tail = stream->oa_buffer.tails[!aged_idx].offset;
>   
> -	hw_tail = dev_priv->perf.oa.ops.oa_hw_tail_read(dev_priv);
> +	hw_tail = dev_priv->perf.ops.oa_hw_tail_read(stream);
>   
>   	/* The tail pointer increases in 64 byte increments,
>   	 * not in report_size steps...
> @@ -492,16 +498,16 @@ static bool oa_buffer_check_unlocked(struct drm_i915_private *dev_priv)
>   	 * available) without needing to wait for a later hrtimer callback.
>   	 */
>   	if (aging_tail != INVALID_TAIL_PTR &&
> -	    ((now - dev_priv->perf.oa.oa_buffer.aging_timestamp) >
> +	    ((now - stream->oa_buffer.aging_timestamp) >
>   	     OA_TAIL_MARGIN_NSEC)) {
>   
>   		aged_idx ^= 1;
> -		dev_priv->perf.oa.oa_buffer.aged_tail_idx = aged_idx;
> +		stream->oa_buffer.aged_tail_idx = aged_idx;
>   
>   		aged_tail = aging_tail;
>   
>   		/* Mark that we need a new pointer to start aging... */
> -		dev_priv->perf.oa.oa_buffer.tails[!aged_idx].offset = INVALID_TAIL_PTR;
> +		stream->oa_buffer.tails[!aged_idx].offset = INVALID_TAIL_PTR;
>   		aging_tail = INVALID_TAIL_PTR;
>   	}
>   
> @@ -516,7 +522,7 @@ static bool oa_buffer_check_unlocked(struct drm_i915_private *dev_priv)
>   	if (aging_tail == INVALID_TAIL_PTR &&
>   	    (aged_tail == INVALID_TAIL_PTR ||
>   	     OA_TAKEN(hw_tail, aged_tail) >= report_size)) {
> -		struct i915_vma *vma = dev_priv->perf.oa.oa_buffer.vma;
> +		struct i915_vma *vma = stream->oa_buffer.vma;
>   		u32 gtt_offset = i915_ggtt_offset(vma);
>   
>   		/* Be paranoid and do a bounds check on the pointer read back
> @@ -525,16 +531,16 @@ static bool oa_buffer_check_unlocked(struct drm_i915_private *dev_priv)
>   		 */
>   		if (hw_tail >= gtt_offset &&
>   		    hw_tail < (gtt_offset + OA_BUFFER_SIZE)) {
> -			dev_priv->perf.oa.oa_buffer.tails[!aged_idx].offset =
> +			stream->oa_buffer.tails[!aged_idx].offset =
>   				aging_tail = hw_tail;
> -			dev_priv->perf.oa.oa_buffer.aging_timestamp = now;
> +			stream->oa_buffer.aging_timestamp = now;
>   		} else {
>   			DRM_ERROR("Ignoring spurious out of range OA buffer tail pointer = %u\n",
>   				  hw_tail);
>   		}
>   	}
>   
> -	spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
>   
>   	return aged_tail == INVALID_TAIL_PTR ?
>   		false : OA_TAKEN(aged_tail, head) >= report_size;
> @@ -597,8 +603,7 @@ static int append_oa_sample(struct i915_perf_stream *stream,
>   			    size_t *offset,
>   			    const u8 *report)
>   {
> -	struct drm_i915_private *dev_priv = stream->dev_priv;
> -	int report_size = dev_priv->perf.oa.oa_buffer.format_size;
> +	int report_size = stream->oa_buffer.format_size;
>   	struct drm_i915_perf_record_header header;
>   	u32 sample_flags = stream->sample_flags;
>   
> @@ -650,9 +655,9 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
>   				  size_t *offset)
>   {
>   	struct drm_i915_private *dev_priv = stream->dev_priv;
> -	int report_size = dev_priv->perf.oa.oa_buffer.format_size;
> -	u8 *oa_buf_base = dev_priv->perf.oa.oa_buffer.vaddr;
> -	u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma);
> +	int report_size = stream->oa_buffer.format_size;
> +	u8 *oa_buf_base = stream->oa_buffer.vaddr;
> +	u32 gtt_offset = i915_ggtt_offset(stream->oa_buffer.vma);
>   	u32 mask = (OA_BUFFER_SIZE - 1);
>   	size_t start_offset = *offset;
>   	unsigned long flags;
> @@ -664,13 +669,13 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
>   	if (WARN_ON(!stream->enabled))
>   		return -EIO;
>   
> -	spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
>   
> -	head = dev_priv->perf.oa.oa_buffer.head;
> -	aged_tail_idx = dev_priv->perf.oa.oa_buffer.aged_tail_idx;
> -	tail = dev_priv->perf.oa.oa_buffer.tails[aged_tail_idx].offset;
> +	head = stream->oa_buffer.head;
> +	aged_tail_idx = stream->oa_buffer.aged_tail_idx;
> +	tail = stream->oa_buffer.tails[aged_tail_idx].offset;
>   
> -	spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
>   
>   	/*
>   	 * An invalid tail pointer here means we're still waiting for the poll
> @@ -734,12 +739,12 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
>   		reason = ((report32[0] >> OAREPORT_REASON_SHIFT) &
>   			  OAREPORT_REASON_MASK);
>   		if (reason == 0) {
> -			if (__ratelimit(&dev_priv->perf.oa.spurious_report_rs))
> +			if (__ratelimit(&dev_priv->perf.spurious_report_rs))
>   				DRM_NOTE("Skipping spurious, invalid OA report\n");
>   			continue;
>   		}
>   
> -		ctx_id = report32[2] & dev_priv->perf.oa.specific_ctx_id_mask;
> +		ctx_id = report32[2] & stream->specific_ctx_id_mask;
>   
>   		/*
>   		 * Squash whatever is in the CTX_ID field if it's marked as
> @@ -749,7 +754,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
>   		 * Note: that we don't clear the valid_ctx_bit so userspace can
>   		 * understand that the ID has been squashed by the kernel.
>   		 */
> -		if (!(report32[0] & dev_priv->perf.oa.gen8_valid_ctx_bit))
> +		if (!(report32[0] & dev_priv->perf.gen8_valid_ctx_bit))
>   			ctx_id = report32[2] = INVALID_CTX_ID;
>   
>   		/*
> @@ -783,18 +788,18 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
>   		 * switches since it's not-uncommon for periodic samples to
>   		 * identify a switch before any 'context switch' report.
>   		 */
> -		if (!dev_priv->perf.oa.exclusive_stream->ctx ||
> -		    dev_priv->perf.oa.specific_ctx_id == ctx_id ||
> -		    (dev_priv->perf.oa.oa_buffer.last_ctx_id ==
> -		     dev_priv->perf.oa.specific_ctx_id) ||
> +		if (!dev_priv->perf.exclusive_stream->ctx ||
> +		    stream->specific_ctx_id == ctx_id ||
> +		    (stream->oa_buffer.last_ctx_id ==
> +		     stream->specific_ctx_id) ||
>   		    reason & OAREPORT_REASON_CTX_SWITCH) {
>   
>   			/*
>   			 * While filtering for a single context we avoid
>   			 * leaking the IDs of other contexts.
>   			 */
> -			if (dev_priv->perf.oa.exclusive_stream->ctx &&
> -			    dev_priv->perf.oa.specific_ctx_id != ctx_id) {
> +			if (dev_priv->perf.exclusive_stream->ctx &&
> +			    stream->specific_ctx_id != ctx_id) {
>   				report32[2] = INVALID_CTX_ID;
>   			}
>   
> @@ -803,7 +808,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
>   			if (ret)
>   				break;
>   
> -			dev_priv->perf.oa.oa_buffer.last_ctx_id = ctx_id;
> +			stream->oa_buffer.last_ctx_id = ctx_id;
>   		}
>   
>   		/*
> @@ -817,7 +822,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
>   	}
>   
>   	if (start_offset != *offset) {
> -		spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +		spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
>   
>   		/*
>   		 * We removed the gtt_offset for the copy loop above, indexing
> @@ -826,9 +831,9 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
>   		head += gtt_offset;
>   
>   		I915_WRITE(GEN8_OAHEADPTR, head & GEN8_OAHEADPTR_MASK);
> -		dev_priv->perf.oa.oa_buffer.head = head;
> +		stream->oa_buffer.head = head;
>   
> -		spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +		spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
>   	}
>   
>   	return ret;
> @@ -863,7 +868,7 @@ static int gen8_oa_read(struct i915_perf_stream *stream,
>   	u32 oastatus;
>   	int ret;
>   
> -	if (WARN_ON(!dev_priv->perf.oa.oa_buffer.vaddr))
> +	if (WARN_ON(!stream->oa_buffer.vaddr))
>   		return -EIO;
>   
>   	oastatus = I915_READ(GEN8_OASTATUS);
> @@ -889,10 +894,10 @@ static int gen8_oa_read(struct i915_perf_stream *stream,
>   			return ret;
>   
>   		DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n",
> -			  dev_priv->perf.oa.period_exponent);
> +			  stream->period_exponent);
>   
> -		dev_priv->perf.oa.ops.oa_disable(stream);
> -		dev_priv->perf.oa.ops.oa_enable(stream);
> +		dev_priv->perf.ops.oa_disable(stream);
> +		dev_priv->perf.ops.oa_enable(stream);
>   
>   		/*
>   		 * Note: .oa_enable() is expected to re-init the oabuffer and
> @@ -939,9 +944,9 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream,
>   				  size_t *offset)
>   {
>   	struct drm_i915_private *dev_priv = stream->dev_priv;
> -	int report_size = dev_priv->perf.oa.oa_buffer.format_size;
> -	u8 *oa_buf_base = dev_priv->perf.oa.oa_buffer.vaddr;
> -	u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma);
> +	int report_size = stream->oa_buffer.format_size;
> +	u8 *oa_buf_base = stream->oa_buffer.vaddr;
> +	u32 gtt_offset = i915_ggtt_offset(stream->oa_buffer.vma);
>   	u32 mask = (OA_BUFFER_SIZE - 1);
>   	size_t start_offset = *offset;
>   	unsigned long flags;
> @@ -953,13 +958,13 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream,
>   	if (WARN_ON(!stream->enabled))
>   		return -EIO;
>   
> -	spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
>   
> -	head = dev_priv->perf.oa.oa_buffer.head;
> -	aged_tail_idx = dev_priv->perf.oa.oa_buffer.aged_tail_idx;
> -	tail = dev_priv->perf.oa.oa_buffer.tails[aged_tail_idx].offset;
> +	head = stream->oa_buffer.head;
> +	aged_tail_idx = stream->oa_buffer.aged_tail_idx;
> +	tail = stream->oa_buffer.tails[aged_tail_idx].offset;
>   
> -	spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
>   
>   	/* An invalid tail pointer here means we're still waiting for the poll
>   	 * hrtimer callback to give us a pointer
> @@ -1012,7 +1017,7 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream,
>   		 * copying it to userspace...
>   		 */
>   		if (report32[0] == 0) {
> -			if (__ratelimit(&dev_priv->perf.oa.spurious_report_rs))
> +			if (__ratelimit(&dev_priv->perf.spurious_report_rs))
>   				DRM_NOTE("Skipping spurious, invalid OA report\n");
>   			continue;
>   		}
> @@ -1031,7 +1036,7 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream,
>   	}
>   
>   	if (start_offset != *offset) {
> -		spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +		spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
>   
>   		/* We removed the gtt_offset for the copy loop above, indexing
>   		 * relative to oa_buf_base so put back here...
> @@ -1041,9 +1046,9 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream,
>   		I915_WRITE(GEN7_OASTATUS2,
>   			   ((head & GEN7_OASTATUS2_HEAD_MASK) |
>   			    GEN7_OASTATUS2_MEM_SELECT_GGTT));
> -		dev_priv->perf.oa.oa_buffer.head = head;
> +		stream->oa_buffer.head = head;
>   
> -		spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +		spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
>   	}
>   
>   	return ret;
> @@ -1074,7 +1079,7 @@ static int gen7_oa_read(struct i915_perf_stream *stream,
>   	u32 oastatus1;
>   	int ret;
>   
> -	if (WARN_ON(!dev_priv->perf.oa.oa_buffer.vaddr))
> +	if (WARN_ON(!stream->oa_buffer.vaddr))
>   		return -EIO;
>   
>   	oastatus1 = I915_READ(GEN7_OASTATUS1);
> @@ -1084,7 +1089,7 @@ static int gen7_oa_read(struct i915_perf_stream *stream,
>   	 * may be updated asynchronously) so we ignore status bits
>   	 * that have already been reported to userspace.
>   	 */
> -	oastatus1 &= ~dev_priv->perf.oa.gen7_latched_oastatus1;
> +	oastatus1 &= ~dev_priv->perf.gen7_latched_oastatus1;
>   
>   	/* We treat OABUFFER_OVERFLOW as a significant error:
>   	 *
> @@ -1113,10 +1118,10 @@ static int gen7_oa_read(struct i915_perf_stream *stream,
>   			return ret;
>   
>   		DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n",
> -			  dev_priv->perf.oa.period_exponent);
> +			  stream->period_exponent);
>   
> -		dev_priv->perf.oa.ops.oa_disable(stream);
> -		dev_priv->perf.oa.ops.oa_enable(stream);
> +		dev_priv->perf.ops.oa_disable(stream);
> +		dev_priv->perf.ops.oa_enable(stream);
>   
>   		oastatus1 = I915_READ(GEN7_OASTATUS1);
>   	}
> @@ -1126,7 +1131,7 @@ static int gen7_oa_read(struct i915_perf_stream *stream,
>   				       DRM_I915_PERF_RECORD_OA_REPORT_LOST);
>   		if (ret)
>   			return ret;
> -		dev_priv->perf.oa.gen7_latched_oastatus1 |=
> +		dev_priv->perf.gen7_latched_oastatus1 |=
>   			GEN7_OASTATUS1_REPORT_LOST;
>   	}
>   
> @@ -1149,14 +1154,12 @@ static int gen7_oa_read(struct i915_perf_stream *stream,
>    */
>   static int i915_oa_wait_unlocked(struct i915_perf_stream *stream)
>   {
> -	struct drm_i915_private *dev_priv = stream->dev_priv;
> -
>   	/* We would wait indefinitely if periodic sampling is not enabled */
> -	if (!dev_priv->perf.oa.periodic)
> +	if (!stream->periodic)
>   		return -EIO;
>   
> -	return wait_event_interruptible(dev_priv->perf.oa.poll_wq,
> -					oa_buffer_check_unlocked(dev_priv));
> +	return wait_event_interruptible(stream->poll_wq,
> +					oa_buffer_check_unlocked(stream));
>   }
>   
>   /**
> @@ -1173,9 +1176,7 @@ static void i915_oa_poll_wait(struct i915_perf_stream *stream,
>   			      struct file *file,
>   			      poll_table *wait)
>   {
> -	struct drm_i915_private *dev_priv = stream->dev_priv;
> -
> -	poll_wait(file, &dev_priv->perf.oa.poll_wq, wait);
> +	poll_wait(file, &stream->poll_wq, wait);
>   }
>   
>   /**
> @@ -1197,13 +1198,14 @@ static int i915_oa_read(struct i915_perf_stream *stream,
>   {
>   	struct drm_i915_private *dev_priv = stream->dev_priv;
>   
> -	return dev_priv->perf.oa.ops.read(stream, buf, count, offset);
> +	return dev_priv->perf.ops.read(stream, buf, count, offset);
>   }
>   
> -static struct intel_context *oa_pin_context(struct drm_i915_private *i915,
> -					    struct i915_gem_context *ctx)
> +static struct intel_context *oa_pin_context(struct i915_perf_stream *stream)
>   {
>   	struct i915_gem_engines_iter it;
> +	struct drm_i915_private *i915 = stream->dev_priv;
> +	struct i915_gem_context *ctx = stream->ctx;
>   	struct intel_context *ce;
>   	int err;
>   
> @@ -1221,7 +1223,7 @@ static struct intel_context *oa_pin_context(struct drm_i915_private *i915,
>   		 */
>   		err = intel_context_pin(ce);
>   		if (err == 0) {
> -			i915->perf.oa.pinned_ctx = ce;
> +			stream->pinned_ctx = ce;
>   			break;
>   		}
>   	}
> @@ -1231,7 +1233,7 @@ static struct intel_context *oa_pin_context(struct drm_i915_private *i915,
>   	if (err)
>   		return ERR_PTR(err);
>   
> -	return i915->perf.oa.pinned_ctx;
> +	return stream->pinned_ctx;
>   }
>   
>   /**
> @@ -1249,7 +1251,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
>   	struct drm_i915_private *i915 = stream->dev_priv;
>   	struct intel_context *ce;
>   
> -	ce = oa_pin_context(i915, stream->ctx);
> +	ce = oa_pin_context(stream);
>   	if (IS_ERR(ce))
>   		return PTR_ERR(ce);
>   
> @@ -1259,8 +1261,8 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
>   		 * On Haswell we don't do any post processing of the reports
>   		 * and don't need to use the mask.
>   		 */
> -		i915->perf.oa.specific_ctx_id = i915_ggtt_offset(ce->state);
> -		i915->perf.oa.specific_ctx_id_mask = 0;
> +		stream->specific_ctx_id = i915_ggtt_offset(ce->state);
> +		stream->specific_ctx_id_mask = 0;
>   		break;
>   	}
>   
> @@ -1278,33 +1280,36 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
>   			 * dropped by GuC. They won't be part of the context
>   			 * ID in the OA reports, so squash those lower bits.
>   			 */
> -			i915->perf.oa.specific_ctx_id =
> +			stream->specific_ctx_id =
>   				lower_32_bits(ce->lrc_desc) >> 12;
>   
>   			/*
>   			 * GuC uses the top bit to signal proxy submission, so
>   			 * ignore that bit.
>   			 */
> -			i915->perf.oa.specific_ctx_id_mask =
> +			stream->specific_ctx_id_mask =
>   				(1U << (GEN8_CTX_ID_WIDTH - 1)) - 1;
>   		} else {
> -			i915->perf.oa.specific_ctx_id_mask =
> +			stream->specific_ctx_id_mask =
>   				(1U << GEN8_CTX_ID_WIDTH) - 1;
> -			i915->perf.oa.specific_ctx_id =
> +			stream->specific_ctx_id =
>   				upper_32_bits(ce->lrc_desc);
> -			i915->perf.oa.specific_ctx_id &=
> -				i915->perf.oa.specific_ctx_id_mask;
> +			stream->specific_ctx_id &=
> +				stream->specific_ctx_id_mask;
>   		}
>   		break;
>   
>   	case 11: {
> -		i915->perf.oa.specific_ctx_id_mask =
> -			((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32) |
> -			((1U << GEN11_ENGINE_INSTANCE_WIDTH) - 1) << (GEN11_ENGINE_INSTANCE_SHIFT - 32) |
> -			((1 << GEN11_ENGINE_CLASS_WIDTH) - 1) << (GEN11_ENGINE_CLASS_SHIFT - 32);
> -		i915->perf.oa.specific_ctx_id = upper_32_bits(ce->lrc_desc);
> -		i915->perf.oa.specific_ctx_id &=
> -			i915->perf.oa.specific_ctx_id_mask;
> +		stream->specific_ctx_id_mask =
> +			((1U << GEN11_SW_CTX_ID_WIDTH) - 1)
> +				<< (GEN11_SW_CTX_ID_SHIFT - 32) |
> +			((1U << GEN11_ENGINE_INSTANCE_WIDTH) - 1)
> +				<< (GEN11_ENGINE_INSTANCE_SHIFT - 32) |
> +			((1 << GEN11_ENGINE_CLASS_WIDTH) - 1)
> +				<< (GEN11_ENGINE_CLASS_SHIFT - 32);
> +		stream->specific_ctx_id = upper_32_bits(ce->lrc_desc);
> +		stream->specific_ctx_id &=
> +			stream->specific_ctx_id_mask;
>   		break;
>   	}
>   
> @@ -1313,8 +1318,8 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
>   	}
>   
>   	DRM_DEBUG_DRIVER("filtering on ctx_id=0x%x ctx_id_mask=0x%x\n",
> -			 i915->perf.oa.specific_ctx_id,
> -			 i915->perf.oa.specific_ctx_id_mask);
> +			 stream->specific_ctx_id,
> +			 stream->specific_ctx_id_mask);
>   
>   	return 0;
>   }
> @@ -1331,10 +1336,10 @@ static void oa_put_render_ctx_id(struct i915_perf_stream *stream)
>   	struct drm_i915_private *dev_priv = stream->dev_priv;
>   	struct intel_context *ce;
>   
> -	dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID;
> -	dev_priv->perf.oa.specific_ctx_id_mask = 0;
> +	stream->specific_ctx_id = INVALID_CTX_ID;
> +	stream->specific_ctx_id_mask = 0;
>   
> -	ce = fetch_and_zero(&dev_priv->perf.oa.pinned_ctx);
> +	ce = fetch_and_zero(&stream->pinned_ctx);
>   	if (ce) {
>   		mutex_lock(&dev_priv->drm.struct_mutex);
>   		intel_context_unpin(ce);
> @@ -1343,34 +1348,34 @@ static void oa_put_render_ctx_id(struct i915_perf_stream *stream)
>   }
>   
>   static void
> -free_oa_buffer(struct drm_i915_private *i915)
> +free_oa_buffer(struct i915_perf_stream *stream)
>   {
> -	mutex_lock(&i915->drm.struct_mutex);
> +	struct drm_i915_private *i915 = stream->dev_priv;
>   
> -	i915_vma_unpin_and_release(&i915->perf.oa.oa_buffer.vma,
> +	mutex_lock(&i915->drm.struct_mutex);
> +	i915_vma_unpin_and_release(&stream->oa_buffer.vma,
>   				   I915_VMA_RELEASE_MAP);
> -
>   	mutex_unlock(&i915->drm.struct_mutex);
>   
> -	i915->perf.oa.oa_buffer.vaddr = NULL;
> +	stream->oa_buffer.vaddr = NULL;
>   }
>   
>   static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
>   {
>   	struct drm_i915_private *dev_priv = stream->dev_priv;
>   
> -	BUG_ON(stream != dev_priv->perf.oa.exclusive_stream);
> +	BUG_ON(stream != dev_priv->perf.exclusive_stream);
>   
>   	/*
>   	 * Unset exclusive_stream first, it will be checked while disabling
>   	 * the metric set on gen8+.
>   	 */
>   	mutex_lock(&dev_priv->drm.struct_mutex);
> -	dev_priv->perf.oa.exclusive_stream = NULL;
> -	dev_priv->perf.oa.ops.disable_metric_set(dev_priv);
> +	dev_priv->perf.exclusive_stream = NULL;
> +	dev_priv->perf.ops.disable_metric_set(stream);
>   	mutex_unlock(&dev_priv->drm.struct_mutex);
>   
> -	free_oa_buffer(dev_priv);
> +	free_oa_buffer(stream);
>   
>   	intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
>   	intel_runtime_pm_put(dev_priv, stream->wakeref);
> @@ -1380,41 +1385,42 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
>   
>   	put_oa_config(dev_priv, stream->oa_config);
>   
> -	if (dev_priv->perf.oa.spurious_report_rs.missed) {
> +	if (dev_priv->perf.spurious_report_rs.missed) {
>   		DRM_NOTE("%d spurious OA report notices suppressed due to ratelimiting\n",
> -			 dev_priv->perf.oa.spurious_report_rs.missed);
> +			 dev_priv->perf.spurious_report_rs.missed);
>   	}
>   }
>   
> -static void gen7_init_oa_buffer(struct drm_i915_private *dev_priv)
> +static void gen7_init_oa_buffer(struct i915_perf_stream *stream)
>   {
> -	u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma);
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
> +	u32 gtt_offset = i915_ggtt_offset(stream->oa_buffer.vma);
>   	unsigned long flags;
>   
> -	spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
>   
>   	/* Pre-DevBDW: OABUFFER must be set with counters off,
>   	 * before OASTATUS1, but after OASTATUS2
>   	 */
>   	I915_WRITE(GEN7_OASTATUS2,
>   		   gtt_offset | GEN7_OASTATUS2_MEM_SELECT_GGTT); /* head */
> -	dev_priv->perf.oa.oa_buffer.head = gtt_offset;
> +	stream->oa_buffer.head = gtt_offset;
>   
>   	I915_WRITE(GEN7_OABUFFER, gtt_offset);
>   
>   	I915_WRITE(GEN7_OASTATUS1, gtt_offset | OABUFFER_SIZE_16M); /* tail */
>   
>   	/* Mark that we need updated tail pointers to read from... */
> -	dev_priv->perf.oa.oa_buffer.tails[0].offset = INVALID_TAIL_PTR;
> -	dev_priv->perf.oa.oa_buffer.tails[1].offset = INVALID_TAIL_PTR;
> +	stream->oa_buffer.tails[0].offset = INVALID_TAIL_PTR;
> +	stream->oa_buffer.tails[1].offset = INVALID_TAIL_PTR;
>   
> -	spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
>   
>   	/* On Haswell we have to track which OASTATUS1 flags we've
>   	 * already seen since they can't be cleared while periodic
>   	 * sampling is enabled.
>   	 */
> -	dev_priv->perf.oa.gen7_latched_oastatus1 = 0;
> +	dev_priv->perf.gen7_latched_oastatus1 = 0;
>   
>   	/* NB: although the OA buffer will initially be allocated
>   	 * zeroed via shmfs (and so this memset is redundant when
> @@ -1427,24 +1433,25 @@ static void gen7_init_oa_buffer(struct drm_i915_private *dev_priv)
>   	 * the assumption that new reports are being written to zeroed
>   	 * memory...
>   	 */
> -	memset(dev_priv->perf.oa.oa_buffer.vaddr, 0, OA_BUFFER_SIZE);
> +	memset(stream->oa_buffer.vaddr, 0, OA_BUFFER_SIZE);
>   
>   	/* Maybe make ->pollin per-stream state if we support multiple
>   	 * concurrent streams in the future.
>   	 */
> -	dev_priv->perf.oa.pollin = false;
> +	stream->pollin = false;
>   }
>   
> -static void gen8_init_oa_buffer(struct drm_i915_private *dev_priv)
> +static void gen8_init_oa_buffer(struct i915_perf_stream *stream)
>   {
> -	u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma);
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
> +	u32 gtt_offset = i915_ggtt_offset(stream->oa_buffer.vma);
>   	unsigned long flags;
>   
> -	spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
>   
>   	I915_WRITE(GEN8_OASTATUS, 0);
>   	I915_WRITE(GEN8_OAHEADPTR, gtt_offset);
> -	dev_priv->perf.oa.oa_buffer.head = gtt_offset;
> +	stream->oa_buffer.head = gtt_offset;
>   
>   	I915_WRITE(GEN8_OABUFFER_UDW, 0);
>   
> @@ -1461,17 +1468,17 @@ static void gen8_init_oa_buffer(struct drm_i915_private *dev_priv)
>   	I915_WRITE(GEN8_OATAILPTR, gtt_offset & GEN8_OATAILPTR_MASK);
>   
>   	/* Mark that we need updated tail pointers to read from... */
> -	dev_priv->perf.oa.oa_buffer.tails[0].offset = INVALID_TAIL_PTR;
> -	dev_priv->perf.oa.oa_buffer.tails[1].offset = INVALID_TAIL_PTR;
> +	stream->oa_buffer.tails[0].offset = INVALID_TAIL_PTR;
> +	stream->oa_buffer.tails[1].offset = INVALID_TAIL_PTR;
>   
>   	/*
>   	 * Reset state used to recognise context switches, affecting which
>   	 * reports we will forward to userspace while filtering for a single
>   	 * context.
>   	 */
> -	dev_priv->perf.oa.oa_buffer.last_ctx_id = INVALID_CTX_ID;
> +	stream->oa_buffer.last_ctx_id = INVALID_CTX_ID;
>   
> -	spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
> +	spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
>   
>   	/*
>   	 * NB: although the OA buffer will initially be allocated
> @@ -1485,22 +1492,23 @@ static void gen8_init_oa_buffer(struct drm_i915_private *dev_priv)
>   	 * the assumption that new reports are being written to zeroed
>   	 * memory...
>   	 */
> -	memset(dev_priv->perf.oa.oa_buffer.vaddr, 0, OA_BUFFER_SIZE);
> +	memset(stream->oa_buffer.vaddr, 0, OA_BUFFER_SIZE);
>   
>   	/*
>   	 * Maybe make ->pollin per-stream state if we support multiple
>   	 * concurrent streams in the future.
>   	 */
> -	dev_priv->perf.oa.pollin = false;
> +	stream->pollin = false;
>   }
>   
> -static int alloc_oa_buffer(struct drm_i915_private *dev_priv)
> +static int alloc_oa_buffer(struct i915_perf_stream *stream)
>   {
>   	struct drm_i915_gem_object *bo;
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
>   	struct i915_vma *vma;
>   	int ret;
>   
> -	if (WARN_ON(dev_priv->perf.oa.oa_buffer.vma))
> +	if (WARN_ON(stream->oa_buffer.vma))
>   		return -ENODEV;
>   
>   	ret = i915_mutex_lock_interruptible(&dev_priv->drm);
> @@ -1525,18 +1533,18 @@ static int alloc_oa_buffer(struct drm_i915_private *dev_priv)
>   		ret = PTR_ERR(vma);
>   		goto err_unref;
>   	}
> -	dev_priv->perf.oa.oa_buffer.vma = vma;
> +	stream->oa_buffer.vma = vma;
>   
> -	dev_priv->perf.oa.oa_buffer.vaddr =
> +	stream->oa_buffer.vaddr =
>   		i915_gem_object_pin_map(bo, I915_MAP_WB);
> -	if (IS_ERR(dev_priv->perf.oa.oa_buffer.vaddr)) {
> -		ret = PTR_ERR(dev_priv->perf.oa.oa_buffer.vaddr);
> +	if (IS_ERR(stream->oa_buffer.vaddr)) {
> +		ret = PTR_ERR(stream->oa_buffer.vaddr);
>   		goto err_unpin;
>   	}
>   
>   	DRM_DEBUG_DRIVER("OA Buffer initialized, gtt offset = 0x%x, vaddr = %p\n",
> -			 i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma),
> -			 dev_priv->perf.oa.oa_buffer.vaddr);
> +			 i915_ggtt_offset(stream->oa_buffer.vma),
> +			 stream->oa_buffer.vaddr);
>   
>   	goto unlock;
>   
> @@ -1546,8 +1554,8 @@ static int alloc_oa_buffer(struct drm_i915_private *dev_priv)
>   err_unref:
>   	i915_gem_object_put(bo);
>   
> -	dev_priv->perf.oa.oa_buffer.vaddr = NULL;
> -	dev_priv->perf.oa.oa_buffer.vma = NULL;
> +	stream->oa_buffer.vaddr = NULL;
> +	stream->oa_buffer.vma = NULL;
>   
>   unlock:
>   	mutex_unlock(&dev_priv->drm.struct_mutex);
> @@ -1617,8 +1625,10 @@ static int hsw_enable_metric_set(struct i915_perf_stream *stream)
>   	return 0;
>   }
>   
> -static void hsw_disable_metric_set(struct drm_i915_private *dev_priv)
> +static void hsw_disable_metric_set(struct i915_perf_stream *stream)
>   {
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
> +
>   	I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) &
>   				  ~GEN6_CSUNIT_CLOCK_GATE_DISABLE));
>   	I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) |
> @@ -1636,13 +1646,14 @@ static void hsw_disable_metric_set(struct drm_i915_private *dev_priv)
>    * in the case that the OA unit has been disabled.
>    */
>   static void
> -gen8_update_reg_state_unlocked(struct intel_context *ce,
> +gen8_update_reg_state_unlocked(struct i915_perf_stream *stream,
> +			       struct intel_context *ce,
>   			       u32 *reg_state,
>   			       const struct i915_oa_config *oa_config)
>   {
>   	struct drm_i915_private *i915 = ce->gem_context->i915;
> -	u32 ctx_oactxctrl = i915->perf.oa.ctx_oactxctrl_offset;
> -	u32 ctx_flexeu0 = i915->perf.oa.ctx_flexeu0_offset;
> +	u32 ctx_oactxctrl = i915->perf.ctx_oactxctrl_offset;
> +	u32 ctx_flexeu0 = i915->perf.ctx_flexeu0_offset;
>   	/* The MMIO offsets for Flex EU registers aren't contiguous */
>   	i915_reg_t flex_regs[] = {
>   		EU_PERF_CNTL0,
> @@ -1656,8 +1667,8 @@ gen8_update_reg_state_unlocked(struct intel_context *ce,
>   	int i;
>   
>   	CTX_REG(reg_state, ctx_oactxctrl, GEN8_OACTXCONTROL,
> -		(i915->perf.oa.period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
> -		(i915->perf.oa.periodic ? GEN8_OA_TIMER_ENABLE : 0) |
> +		(stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
> +		(stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
>   		GEN8_OA_COUNTER_RESUME);
>   
>   	for (i = 0; i < ARRAY_SIZE(flex_regs); i++) {
> @@ -1673,10 +1684,12 @@ gen8_update_reg_state_unlocked(struct intel_context *ce,
>   
>   		if (oa_config) {
>   			u32 j;
> +			struct i915_oa_reg reg;
>   
>   			for (j = 0; j < oa_config->flex_regs_len; j++) {
> -				if (i915_mmio_reg_offset(oa_config->flex_regs[j].addr) == mmio) {
> -					value = oa_config->flex_regs[j].value;
> +				reg = oa_config->flex_regs[j];
> +				if (i915_mmio_reg_offset(reg.addr) == mmio) {
> +					value = reg.value;
>   					break;
>   				}
>   			}
> @@ -1714,9 +1727,10 @@ gen8_update_reg_state_unlocked(struct intel_context *ce,
>    *
>    * Note: it's only the RCS/Render context that has any OA state.
>    */
> -static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv,
> +static int gen8_configure_all_contexts(struct i915_perf_stream *stream,
>   				       const struct i915_oa_config *oa_config)
>   {
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
>   	unsigned int map_type = i915_coherent_map_type(dev_priv);
>   	struct i915_gem_context *ctx;
>   	struct i915_request *rq;
> @@ -1770,7 +1784,7 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv,
>   			ce->state->obj->mm.dirty = true;
>   			regs += LRC_STATE_PN * PAGE_SIZE / sizeof(*regs);
>   
> -			gen8_update_reg_state_unlocked(ce, regs, oa_config);
> +			gen8_update_reg_state_unlocked(stream, ce, regs, oa_config);
>   
>   			i915_gem_object_unpin_map(ce->state->obj);
>   		}
> @@ -1821,8 +1835,9 @@ static int gen8_enable_metric_set(struct i915_perf_stream *stream)
>   	 */
>   	if (IS_GEN_RANGE(dev_priv, 9, 11)) {
>   		I915_WRITE(GEN8_OA_DEBUG,
> -			   _MASKED_BIT_ENABLE(GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS |
> -					      GEN9_OA_DEBUG_INCLUDE_CLK_RATIO));
> +			   _MASKED_BIT_ENABLE(
> +				   GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS |
> +				   GEN9_OA_DEBUG_INCLUDE_CLK_RATIO));
>   	}
>   
>   	/*
> @@ -1830,7 +1845,7 @@ static int gen8_enable_metric_set(struct i915_perf_stream *stream)
>   	 * to make sure all slices/subslices are ON before writing to NOA
>   	 * registers.
>   	 */
> -	ret = gen8_configure_all_contexts(dev_priv, oa_config);
> +	ret = gen8_configure_all_contexts(stream, oa_config);
>   	if (ret)
>   		return ret;
>   
> @@ -1842,19 +1857,23 @@ static int gen8_enable_metric_set(struct i915_perf_stream *stream)
>   	return 0;
>   }
>   
> -static void gen8_disable_metric_set(struct drm_i915_private *dev_priv)
> +static void gen8_disable_metric_set(struct i915_perf_stream *stream)
>   {
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
> +
>   	/* Reset all contexts' slices/subslices configurations. */
> -	gen8_configure_all_contexts(dev_priv, NULL);
> +	gen8_configure_all_contexts(stream, NULL);
>   
>   	I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) &
>   				      ~GT_NOA_ENABLE));
>   }
>   
> -static void gen10_disable_metric_set(struct drm_i915_private *dev_priv)
> +static void gen10_disable_metric_set(struct i915_perf_stream *stream)
>   {
> +	struct drm_i915_private *dev_priv = stream->dev_priv;
> +
>   	/* Reset all contexts' slices/subslices configurations. */
> -	gen8_configure_all_contexts(dev_priv, NULL);
> +	gen8_configure_all_contexts(stream, NULL);
>   
>   	/* Make sure we disable noa to save power. */
>   	I915_WRITE(RPM_CONFIG1,
> @@ -1865,10 +1884,10 @@ static void gen7_oa_enable(struct i915_perf_stream *stream)
>   {
>   	struct drm_i915_private *dev_priv = stream->dev_priv;
>   	struct i915_gem_context *ctx = stream->ctx;
> -	u32 ctx_id = dev_priv->perf.oa.specific_ctx_id;
> -	bool periodic = dev_priv->perf.oa.periodic;
> -	u32 period_exponent = dev_priv->perf.oa.period_exponent;
> -	u32 report_format = dev_priv->perf.oa.oa_buffer.format;
> +	u32 ctx_id = stream->specific_ctx_id;
> +	bool periodic = stream->periodic;
> +	u32 period_exponent = stream->period_exponent;
> +	u32 report_format = stream->oa_buffer.format;
>   
>   	/*
>   	 * Reset buf pointers so we don't forward reports from before now.
> @@ -1879,7 +1898,7 @@ static void gen7_oa_enable(struct i915_perf_stream *stream)
>   	 * on the assumption that certain fields are written to zeroed
>   	 * memory which this helps maintains.
>   	 */
> -	gen7_init_oa_buffer(dev_priv);
> +	gen7_init_oa_buffer(stream);
>   
>   	I915_WRITE(GEN7_OACONTROL,
>   		   (ctx_id & GEN7_OACONTROL_CTX_MASK) |
> @@ -1894,7 +1913,7 @@ static void gen7_oa_enable(struct i915_perf_stream *stream)
>   static void gen8_oa_enable(struct i915_perf_stream *stream)
>   {
>   	struct drm_i915_private *dev_priv = stream->dev_priv;
> -	u32 report_format = dev_priv->perf.oa.oa_buffer.format;
> +	u32 report_format = stream->oa_buffer.format;
>   
>   	/*
>   	 * Reset buf pointers so we don't forward reports from before now.
> @@ -1905,7 +1924,7 @@ static void gen8_oa_enable(struct i915_perf_stream *stream)
>   	 * on the assumption that certain fields are written to zeroed
>   	 * memory which this helps maintains.
>   	 */
> -	gen8_init_oa_buffer(dev_priv);
> +	gen8_init_oa_buffer(stream);
>   
>   	/*
>   	 * Note: we don't rely on the hardware to perform single context
> @@ -1930,10 +1949,10 @@ static void i915_oa_stream_enable(struct i915_perf_stream *stream)
>   {
>   	struct drm_i915_private *dev_priv = stream->dev_priv;
>   
> -	dev_priv->perf.oa.ops.oa_enable(stream);
> +	dev_priv->perf.ops.oa_enable(stream);
>   
> -	if (dev_priv->perf.oa.periodic)
> -		hrtimer_start(&dev_priv->perf.oa.poll_check_timer,
> +	if (stream->periodic)
> +		hrtimer_start(&stream->poll_check_timer,
>   			      ns_to_ktime(POLL_PERIOD),
>   			      HRTIMER_MODE_REL_PINNED);
>   }
> @@ -1972,10 +1991,10 @@ static void i915_oa_stream_disable(struct i915_perf_stream *stream)
>   {
>   	struct drm_i915_private *dev_priv = stream->dev_priv;
>   
> -	dev_priv->perf.oa.ops.oa_disable(stream);
> +	dev_priv->perf.ops.oa_disable(stream);
>   
> -	if (dev_priv->perf.oa.periodic)
> -		hrtimer_cancel(&dev_priv->perf.oa.poll_check_timer);
> +	if (stream->periodic)
> +		hrtimer_cancel(&stream->poll_check_timer);
>   }
>   
>   static const struct i915_perf_stream_ops i915_oa_stream_ops = {
> @@ -2027,7 +2046,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
>   		return -EINVAL;
>   	}
>   
> -	if (!dev_priv->perf.oa.ops.enable_metric_set) {
> +	if (!dev_priv->perf.ops.enable_metric_set) {
>   		DRM_DEBUG("OA unit not supported\n");
>   		return -ENODEV;
>   	}
> @@ -2036,7 +2055,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
>   	 * counter reports and marshal to the appropriate client
>   	 * we currently only allow exclusive access
>   	 */
> -	if (dev_priv->perf.oa.exclusive_stream) {
> +	if (dev_priv->perf.exclusive_stream) {
>   		DRM_DEBUG("OA unit already in use\n");
>   		return -EBUSY;
>   	}
> @@ -2046,43 +2065,23 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
>   		return -EINVAL;
>   	}
>   
> -	/* We set up some ratelimit state to potentially throttle any _NOTES
> -	 * about spurious, invalid OA reports which we don't forward to
> -	 * userspace.
> -	 *
> -	 * The initialization is associated with opening the stream (not driver
> -	 * init) considering we print a _NOTE about any throttling when closing
> -	 * the stream instead of waiting until driver _fini which no one would
> -	 * ever see.
> -	 *
> -	 * Using the same limiting factors as printk_ratelimit()
> -	 */
> -	ratelimit_state_init(&dev_priv->perf.oa.spurious_report_rs,
> -			     5 * HZ, 10);
> -	/* Since we use a DRM_NOTE for spurious reports it would be
> -	 * inconsistent to let __ratelimit() automatically print a warning for
> -	 * throttling.
> -	 */
> -	ratelimit_set_flags(&dev_priv->perf.oa.spurious_report_rs,
> -			    RATELIMIT_MSG_ON_RELEASE);
> -
>   	stream->sample_size = sizeof(struct drm_i915_perf_record_header);
>   
> -	format_size = dev_priv->perf.oa.oa_formats[props->oa_format].size;
> +	format_size = dev_priv->perf.oa_formats[props->oa_format].size;
>   
>   	stream->sample_flags |= SAMPLE_OA_REPORT;
>   	stream->sample_size += format_size;
>   
> -	dev_priv->perf.oa.oa_buffer.format_size = format_size;
> -	if (WARN_ON(dev_priv->perf.oa.oa_buffer.format_size == 0))
> +	stream->oa_buffer.format_size = format_size;
> +	if (WARN_ON(stream->oa_buffer.format_size == 0))
>   		return -EINVAL;
>   
> -	dev_priv->perf.oa.oa_buffer.format =
> -		dev_priv->perf.oa.oa_formats[props->oa_format].format;
> +	stream->oa_buffer.format =
> +		dev_priv->perf.oa_formats[props->oa_format].format;
>   
> -	dev_priv->perf.oa.periodic = props->oa_periodic;
> -	if (dev_priv->perf.oa.periodic)
> -		dev_priv->perf.oa.period_exponent = props->oa_period_exponent;
> +	stream->periodic = props->oa_periodic;
> +	if (stream->periodic)
> +		stream->period_exponent = props->oa_period_exponent;
>   
>   	if (stream->ctx) {
>   		ret = oa_get_render_ctx_id(stream);
> @@ -2113,7 +2112,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
>   	stream->wakeref = intel_runtime_pm_get(dev_priv);
>   	intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL);
>   
> -	ret = alloc_oa_buffer(dev_priv);
> +	ret = alloc_oa_buffer(stream);
>   	if (ret)
>   		goto err_oa_buf_alloc;
>   
> @@ -2122,9 +2121,9 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
>   		goto err_lock;
>   
>   	stream->ops = &i915_oa_stream_ops;
> -	dev_priv->perf.oa.exclusive_stream = stream;
> +	dev_priv->perf.exclusive_stream = stream;
>   
> -	ret = dev_priv->perf.oa.ops.enable_metric_set(stream);
> +	ret = dev_priv->perf.ops.enable_metric_set(stream);
>   	if (ret) {
>   		DRM_DEBUG("Unable to enable metric set\n");
>   		goto err_enable;
> @@ -2132,15 +2131,21 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
>   
>   	mutex_unlock(&dev_priv->drm.struct_mutex);
>   
> +	hrtimer_init(&stream->poll_check_timer,
> +		     CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +	stream->poll_check_timer.function = oa_poll_check_timer_cb;
> +	init_waitqueue_head(&stream->poll_wq);
> +	spin_lock_init(&stream->oa_buffer.ptr_lock);
> +
>   	return 0;
>   
>   err_enable:
> -	dev_priv->perf.oa.exclusive_stream = NULL;
> -	dev_priv->perf.oa.ops.disable_metric_set(dev_priv);
> +	dev_priv->perf.exclusive_stream = NULL;
> +	dev_priv->perf.ops.disable_metric_set(stream);
>   	mutex_unlock(&dev_priv->drm.struct_mutex);
>   
>   err_lock:
> -	free_oa_buffer(dev_priv);
> +	free_oa_buffer(stream);
>   
>   err_oa_buf_alloc:
>   	put_oa_config(dev_priv, stream->oa_config);
> @@ -2164,9 +2169,12 @@ void i915_oa_init_reg_state(struct intel_engine_cs *engine,
>   	if (engine->class != RENDER_CLASS)
>   		return;
>   
> -	stream = engine->i915->perf.oa.exclusive_stream;
> +	stream = engine->i915->perf.exclusive_stream;
>   	if (stream)
> -		gen8_update_reg_state_unlocked(ce, regs, stream->oa_config);
> +		gen8_update_reg_state_unlocked(stream,
> +					       ce,
> +					       regs,
> +					       stream->oa_config);
>   }
>   
>   /**
> @@ -2282,7 +2290,7 @@ static ssize_t i915_perf_read(struct file *file,
>   		/* Maybe make ->pollin per-stream state if we support multiple
>   		 * concurrent streams in the future.
>   		 */
> -		dev_priv->perf.oa.pollin = false;
> +		stream->pollin = false;
>   	}
>   
>   	return ret;
> @@ -2290,13 +2298,13 @@ static ssize_t i915_perf_read(struct file *file,
>   
>   static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer)
>   {
> -	struct drm_i915_private *dev_priv =
> -		container_of(hrtimer, typeof(*dev_priv),
> -			     perf.oa.poll_check_timer);
> +	struct i915_perf_stream *stream = container_of(hrtimer,
> +						       typeof(*stream),
> +						       poll_check_timer);
>   
> -	if (oa_buffer_check_unlocked(dev_priv)) {
> -		dev_priv->perf.oa.pollin = true;
> -		wake_up(&dev_priv->perf.oa.poll_wq);
> +	if (oa_buffer_check_unlocked(stream)) {
> +		stream->pollin = true;
> +		wake_up(&stream->poll_wq);
>   	}
>   
>   	hrtimer_forward_now(hrtimer, ns_to_ktime(POLL_PERIOD));
> @@ -2335,7 +2343,7 @@ static __poll_t i915_perf_poll_locked(struct drm_i915_private *dev_priv,
>   	 * the hrtimer/oa_poll_check_timer_cb to notify us when there are
>   	 * samples to read.
>   	 */
> -	if (dev_priv->perf.oa.pollin)
> +	if (stream->pollin)
>   		events |= EPOLLIN;
>   
>   	return events;
> @@ -2668,8 +2676,10 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv,
>   
>   static u64 oa_exponent_to_ns(struct drm_i915_private *dev_priv, int exponent)
>   {
> +	struct intel_runtime_info *ri = RUNTIME_INFO(dev_priv);
> +
>   	return div64_u64(1000000000ULL * (2ULL << exponent),
> -			 1000ULL * RUNTIME_INFO(dev_priv)->cs_timestamp_frequency_khz);
> +			 1000ULL * ri->cs_timestamp_frequency_khz);
>   }
>   
>   /**
> @@ -2753,7 +2763,7 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv,
>   					  value);
>   				return -EINVAL;
>   			}
> -			if (!dev_priv->perf.oa.oa_formats[value].size) {
> +			if (!dev_priv->perf.oa_formats[value].size) {
>   				DRM_DEBUG("Unsupported OA report format %llu\n",
>   					  value);
>   				return -EINVAL;
> @@ -2897,7 +2907,7 @@ void i915_perf_register(struct drm_i915_private *dev_priv)
>   	if (!dev_priv->perf.metrics_kobj)
>   		goto exit;
>   
> -	sysfs_attr_init(&dev_priv->perf.oa.test_config.sysfs_metric_id.attr);
> +	sysfs_attr_init(&dev_priv->perf.test_config.sysfs_metric_id.attr);
>   
>   	if (INTEL_GEN(dev_priv) >= 11) {
>   		i915_perf_load_test_config_icl(dev_priv);
> @@ -2932,15 +2942,15 @@ void i915_perf_register(struct drm_i915_private *dev_priv)
>   		i915_perf_load_test_config_hsw(dev_priv);
>   }
>   
> -	if (dev_priv->perf.oa.test_config.id == 0)
> +	if (dev_priv->perf.test_config.id == 0)
>   		goto sysfs_error;
>   
>   	ret = sysfs_create_group(dev_priv->perf.metrics_kobj,
> -				 &dev_priv->perf.oa.test_config.sysfs_metric);
> +				 &dev_priv->perf.test_config.sysfs_metric);
>   	if (ret)
>   		goto sysfs_error;
>   
> -	atomic_set(&dev_priv->perf.oa.test_config.ref_count, 1);
> +	atomic_set(&dev_priv->perf.test_config.ref_count, 1);
>   
>   	goto exit;
>   
> @@ -2967,7 +2977,7 @@ void i915_perf_unregister(struct drm_i915_private *dev_priv)
>   		return;
>   
>   	sysfs_remove_group(dev_priv->perf.metrics_kobj,
> -			   &dev_priv->perf.oa.test_config.sysfs_metric);
> +			   &dev_priv->perf.test_config.sysfs_metric);
>   
>   	kobject_put(dev_priv->perf.metrics_kobj);
>   	dev_priv->perf.metrics_kobj = NULL;
> @@ -2993,7 +3003,8 @@ static bool gen8_is_valid_flex_addr(struct drm_i915_private *dev_priv, u32 addr)
>   	return false;
>   }
>   
> -static bool gen7_is_valid_b_counter_addr(struct drm_i915_private *dev_priv, u32 addr)
> +static bool gen7_is_valid_b_counter_addr(struct drm_i915_private *dev_priv,
> +					 u32 addr)
>   {
>   	return (addr >= i915_mmio_reg_offset(OASTARTTRIG1) &&
>   		addr <= i915_mmio_reg_offset(OASTARTTRIG8)) ||
> @@ -3078,7 +3089,9 @@ static struct i915_oa_reg *alloc_oa_regs(struct drm_i915_private *dev_priv,
>   	if (!access_ok(regs, n_regs * sizeof(u32) * 2))
>   		return ERR_PTR(-EFAULT);
>   
> -	/* No is_valid function means we're not allowing any register to be programmed. */
> +	/* No is_valid function means we're not allowing any register to be
> +	 * programmed.
> +	 */
>   	GEM_BUG_ON(!is_valid);
>   	if (!is_valid)
>   		return ERR_PTR(-EINVAL);
> @@ -3211,7 +3224,7 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
>   	oa_config->mux_regs_len = args->n_mux_regs;
>   	oa_config->mux_regs =
>   		alloc_oa_regs(dev_priv,
> -			      dev_priv->perf.oa.ops.is_valid_mux_reg,
> +			      dev_priv->perf.ops.is_valid_mux_reg,
>   			      u64_to_user_ptr(args->mux_regs_ptr),
>   			      args->n_mux_regs);
>   
> @@ -3224,7 +3237,7 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
>   	oa_config->b_counter_regs_len = args->n_boolean_regs;
>   	oa_config->b_counter_regs =
>   		alloc_oa_regs(dev_priv,
> -			      dev_priv->perf.oa.ops.is_valid_b_counter_reg,
> +			      dev_priv->perf.ops.is_valid_b_counter_reg,
>   			      u64_to_user_ptr(args->boolean_regs_ptr),
>   			      args->n_boolean_regs);
>   
> @@ -3243,7 +3256,7 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
>   		oa_config->flex_regs_len = args->n_flex_regs;
>   		oa_config->flex_regs =
>   			alloc_oa_regs(dev_priv,
> -				      dev_priv->perf.oa.ops.is_valid_flex_reg,
> +				      dev_priv->perf.ops.is_valid_flex_reg,
>   				      u64_to_user_ptr(args->flex_regs_ptr),
>   				      args->n_flex_regs);
>   
> @@ -3300,7 +3313,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
>   }
>   
>   /**
> - * i915_perf_remove_config_ioctl - DRM ioctl() for userspace to remove an OA config
> + * i915_perf_remove_config_ioctl - DRM ioctl() for userspace to remove an OA
> + * config
>    * @dev: drm device
>    * @data: ioctl data (pointer to u64 integer) copied from userspace
>    * @file: drm file
> @@ -3409,21 +3423,23 @@ static struct ctl_table dev_root[] = {
>    */
>   void i915_perf_init(struct drm_i915_private *dev_priv)
>   {
> +	struct intel_runtime_info *ri;
> +
>   	if (IS_HASWELL(dev_priv)) {
> -		dev_priv->perf.oa.ops.is_valid_b_counter_reg =
> +		dev_priv->perf.ops.is_valid_b_counter_reg =
>   			gen7_is_valid_b_counter_addr;
> -		dev_priv->perf.oa.ops.is_valid_mux_reg =
> +		dev_priv->perf.ops.is_valid_mux_reg =
>   			hsw_is_valid_mux_addr;
> -		dev_priv->perf.oa.ops.is_valid_flex_reg = NULL;
> -		dev_priv->perf.oa.ops.enable_metric_set = hsw_enable_metric_set;
> -		dev_priv->perf.oa.ops.disable_metric_set = hsw_disable_metric_set;
> -		dev_priv->perf.oa.ops.oa_enable = gen7_oa_enable;
> -		dev_priv->perf.oa.ops.oa_disable = gen7_oa_disable;
> -		dev_priv->perf.oa.ops.read = gen7_oa_read;
> -		dev_priv->perf.oa.ops.oa_hw_tail_read =
> +		dev_priv->perf.ops.is_valid_flex_reg = NULL;
> +		dev_priv->perf.ops.enable_metric_set = hsw_enable_metric_set;
> +		dev_priv->perf.ops.disable_metric_set = hsw_disable_metric_set;
> +		dev_priv->perf.ops.oa_enable = gen7_oa_enable;
> +		dev_priv->perf.ops.oa_disable = gen7_oa_disable;
> +		dev_priv->perf.ops.read = gen7_oa_read;
> +		dev_priv->perf.ops.oa_hw_tail_read =
>   			gen7_oa_hw_tail_read;
>   
> -		dev_priv->perf.oa.oa_formats = hsw_oa_formats;
> +		dev_priv->perf.oa_formats = hsw_oa_formats;
>   	} else if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) {
>   		/* Note: that although we could theoretically also support the
>   		 * legacy ringbuffer mode on BDW (and earlier iterations of
> @@ -3431,75 +3447,93 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
>   		 * worth the complexity to maintain now that BDW+ enable
>   		 * execlist mode by default.
>   		 */
> -		dev_priv->perf.oa.oa_formats = gen8_plus_oa_formats;
> +		dev_priv->perf.oa_formats = gen8_plus_oa_formats;
>   
> -		dev_priv->perf.oa.ops.oa_enable = gen8_oa_enable;
> -		dev_priv->perf.oa.ops.oa_disable = gen8_oa_disable;
> -		dev_priv->perf.oa.ops.read = gen8_oa_read;
> -		dev_priv->perf.oa.ops.oa_hw_tail_read = gen8_oa_hw_tail_read;
> +		dev_priv->perf.ops.oa_enable = gen8_oa_enable;
> +		dev_priv->perf.ops.oa_disable = gen8_oa_disable;
> +		dev_priv->perf.ops.read = gen8_oa_read;
> +		dev_priv->perf.ops.oa_hw_tail_read = gen8_oa_hw_tail_read;
>   
>   		if (IS_GEN_RANGE(dev_priv, 8, 9)) {
> -			dev_priv->perf.oa.ops.is_valid_b_counter_reg =
> +			dev_priv->perf.ops.is_valid_b_counter_reg =
>   				gen7_is_valid_b_counter_addr;
> -			dev_priv->perf.oa.ops.is_valid_mux_reg =
> +			dev_priv->perf.ops.is_valid_mux_reg =
>   				gen8_is_valid_mux_addr;
> -			dev_priv->perf.oa.ops.is_valid_flex_reg =
> +			dev_priv->perf.ops.is_valid_flex_reg =
>   				gen8_is_valid_flex_addr;
>   
>   			if (IS_CHERRYVIEW(dev_priv)) {
> -				dev_priv->perf.oa.ops.is_valid_mux_reg =
> +				dev_priv->perf.ops.is_valid_mux_reg =
>   					chv_is_valid_mux_addr;
>   			}
>   
> -			dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set;
> -			dev_priv->perf.oa.ops.disable_metric_set = gen8_disable_metric_set;
> +			dev_priv->perf.ops.enable_metric_set =
> +				gen8_enable_metric_set;
> +			dev_priv->perf.ops.disable_metric_set =
> +				gen8_disable_metric_set;
>   
>   			if (IS_GEN(dev_priv, 8)) {
> -				dev_priv->perf.oa.ctx_oactxctrl_offset = 0x120;
> -				dev_priv->perf.oa.ctx_flexeu0_offset = 0x2ce;
> +				dev_priv->perf.ctx_oactxctrl_offset = 0x120;
> +				dev_priv->perf.ctx_flexeu0_offset = 0x2ce;
>   
> -				dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<25);
> +				dev_priv->perf.gen8_valid_ctx_bit = (1<<25);
>   			} else {
> -				dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128;
> -				dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de;
> +				dev_priv->perf.ctx_oactxctrl_offset = 0x128;
> +				dev_priv->perf.ctx_flexeu0_offset = 0x3de;
>   
> -				dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16);
> +				dev_priv->perf.gen8_valid_ctx_bit = (1<<16);
>   			}
>   		} else if (IS_GEN_RANGE(dev_priv, 10, 11)) {
> -			dev_priv->perf.oa.ops.is_valid_b_counter_reg =
> +			dev_priv->perf.ops.is_valid_b_counter_reg =
>   				gen7_is_valid_b_counter_addr;
> -			dev_priv->perf.oa.ops.is_valid_mux_reg =
> +			dev_priv->perf.ops.is_valid_mux_reg =
>   				gen10_is_valid_mux_addr;
> -			dev_priv->perf.oa.ops.is_valid_flex_reg =
> +			dev_priv->perf.ops.is_valid_flex_reg =
>   				gen8_is_valid_flex_addr;
>   
> -			dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set;
> -			dev_priv->perf.oa.ops.disable_metric_set = gen10_disable_metric_set;
> +			dev_priv->perf.ops.enable_metric_set =
> +				gen8_enable_metric_set;
> +			dev_priv->perf.ops.disable_metric_set =
> +				gen10_disable_metric_set;
>   
> -			dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128;
> -			dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de;
> +			dev_priv->perf.ctx_oactxctrl_offset = 0x128;
> +			dev_priv->perf.ctx_flexeu0_offset = 0x3de;
>   
> -			dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16);
> +			dev_priv->perf.gen8_valid_ctx_bit = (1<<16);
>   		}
>   	}
>   
> -	if (dev_priv->perf.oa.ops.enable_metric_set) {
> -		hrtimer_init(&dev_priv->perf.oa.poll_check_timer,
> -				CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> -		dev_priv->perf.oa.poll_check_timer.function = oa_poll_check_timer_cb;
> -		init_waitqueue_head(&dev_priv->perf.oa.poll_wq);
> -
> +	if (dev_priv->perf.ops.enable_metric_set) {
>   		INIT_LIST_HEAD(&dev_priv->perf.streams);
>   		mutex_init(&dev_priv->perf.lock);
> -		spin_lock_init(&dev_priv->perf.oa.oa_buffer.ptr_lock);
>   
> +		ri = RUNTIME_INFO(dev_priv);
>   		oa_sample_rate_hard_limit = 1000 *
> -			(RUNTIME_INFO(dev_priv)->cs_timestamp_frequency_khz / 2);
> +			(ri->cs_timestamp_frequency_khz / 2);
>   		dev_priv->perf.sysctl_header = register_sysctl_table(dev_root);
>   
>   		mutex_init(&dev_priv->perf.metrics_lock);
>   		idr_init(&dev_priv->perf.metrics_idr);
>   
> +		/* We set up some ratelimit state to potentially throttle any
> +		 * _NOTES about spurious, invalid OA reports which we don't
> +		 * forward to userspace.
> +		 *
> +		 * We print a _NOTE about any throttling when closing the
> +		 * stream instead of waiting until driver _fini which no one
> +		 * would ever see.
> +		 *
> +		 * Using the same limiting factors as printk_ratelimit()
> +		 */
> +		ratelimit_state_init(&dev_priv->perf.spurious_report_rs,
> +				     5 * HZ, 10);
> +		/* Since we use a DRM_NOTE for spurious reports it would be
> +		 * inconsistent to let __ratelimit() automatically print a
> +		 * warning for throttling.
> +		 */
> +		ratelimit_set_flags(&dev_priv->perf.spurious_report_rs,
> +				    RATELIMIT_MSG_ON_RELEASE);
> +
>   		dev_priv->perf.initialized = true;
>   	}
>   }
> @@ -3528,7 +3562,7 @@ void i915_perf_fini(struct drm_i915_private *dev_priv)
>   
>   	unregister_sysctl_table(dev_priv->perf.sysctl_header);
>   
> -	memset(&dev_priv->perf.oa.ops, 0, sizeof(dev_priv->perf.oa.ops));
> +	memset(&dev_priv->perf.ops, 0, sizeof(dev_priv->perf.ops));
>   
>   	dev_priv->perf.initialized = false;
>   }




More information about the Intel-gfx mailing list