Merge tag 'drm-intel-fixes-2019-12-12' of git://anongit.freedesktop.org/drm/drm-intel...
authorDave Airlie <airlied@redhat.com>
Fri, 13 Dec 2019 04:44:08 +0000 (14:44 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 13 Dec 2019 04:44:09 +0000 (14:44 +1000)
- Fix user reported issue #673: GPU hang on transition to idle
- Avoid corruption on the top of the screen on GLK+ by disabling FBC
- Fix non-privileged access to OA on Tigerlake
- Fix HDCP code not to touch global state when just computing commit
- Fix CI splat by saving irqstate around virtual_context_destroy
- Serialise context retirement possibly on another CPU

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191212100759.GA22260@jlahtine-desk.ger.corp.intel.com
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_fbc.c
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/display/intel_hdcp.h
drivers/gpu/drm/i915/display/intel_hdmi.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_perf.c

index c7c2b349858d221310da1513cf6e0d6d8b0fbe1d..2a27fb5d7dc6f0a8183a39e8f88783f73934c7b7 100644 (file)
@@ -3986,6 +3986,7 @@ static void intel_enable_ddi(struct intel_encoder *encoder,
        if (conn_state->content_protection ==
            DRM_MODE_CONTENT_PROTECTION_DESIRED)
                intel_hdcp_enable(to_intel_connector(conn_state->connector),
+                                 crtc_state->cpu_transcoder,
                                  (u8)conn_state->hdcp_content_type);
 }
 
@@ -4089,7 +4090,9 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder,
        if (conn_state->content_protection ==
            DRM_MODE_CONTENT_PROTECTION_DESIRED ||
            content_protection_type_changed)
-               intel_hdcp_enable(connector, (u8)conn_state->hdcp_content_type);
+               intel_hdcp_enable(connector,
+                                 crtc_state->cpu_transcoder,
+                                 (u8)conn_state->hdcp_content_type);
 }
 
 static void
index 050655a1a3d8d9c2920cf557f3a81388c2a60870..b05b2191b919b1ff886f7335ddf423ffbb3751c7 100644 (file)
@@ -2414,9 +2414,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
        intel_psr_compute_config(intel_dp, pipe_config);
 
-       intel_hdcp_transcoder_config(intel_connector,
-                                    pipe_config->cpu_transcoder);
-
        return 0;
 }
 
index 3111ecaeabd0ef4717a01fe76e7488ad2b3fea6c..20616639b8ab10180f345cc2f247a67047b8e38d 100644 (file)
@@ -1284,7 +1284,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
                return 0;
 
        /* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */
-       if (IS_GEMINILAKE(dev_priv))
+       if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
                return 0;
 
        if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
index f1f41ca8402bf79585047d2c269c6bbe40675e4b..a448815d8fc2e70bc18689bb169074f70343bac5 100644 (file)
@@ -1821,23 +1821,6 @@ enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder)
        }
 }
 
-void intel_hdcp_transcoder_config(struct intel_connector *connector,
-                                 enum transcoder cpu_transcoder)
-{
-       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-       struct intel_hdcp *hdcp = &connector->hdcp;
-
-       if (!hdcp->shim)
-               return;
-
-       if (INTEL_GEN(dev_priv) >= 12) {
-               mutex_lock(&hdcp->mutex);
-               hdcp->cpu_transcoder = cpu_transcoder;
-               hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder);
-               mutex_unlock(&hdcp->mutex);
-       }
-}
-
 static inline int initialize_hdcp_port_data(struct intel_connector *connector,
                                            const struct intel_hdcp_shim *shim)
 {
@@ -1959,8 +1942,10 @@ int intel_hdcp_init(struct intel_connector *connector,
        return 0;
 }
 
-int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
+int intel_hdcp_enable(struct intel_connector *connector,
+                     enum transcoder cpu_transcoder, u8 content_type)
 {
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        struct intel_hdcp *hdcp = &connector->hdcp;
        unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS;
        int ret = -EINVAL;
@@ -1972,6 +1957,11 @@ int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
        WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED);
        hdcp->content_type = content_type;
 
+       if (INTEL_GEN(dev_priv) >= 12) {
+               hdcp->cpu_transcoder = cpu_transcoder;
+               hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder);
+       }
+
        /*
         * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
         * is capable of HDCP2.2, it is preferred to use HDCP2.2.
index 41c1053d9e38b1e6a3f24fa1b21a3c10b07fb40a..f3c3272e712a18a6fdb6e8cc255ca90d936a3073 100644 (file)
@@ -21,11 +21,10 @@ enum transcoder;
 void intel_hdcp_atomic_check(struct drm_connector *connector,
                             struct drm_connector_state *old_state,
                             struct drm_connector_state *new_state);
-void intel_hdcp_transcoder_config(struct intel_connector *connector,
-                                 enum transcoder cpu_transcoder);
 int intel_hdcp_init(struct intel_connector *connector,
                    const struct intel_hdcp_shim *hdcp_shim);
-int intel_hdcp_enable(struct intel_connector *connector, u8 content_type);
+int intel_hdcp_enable(struct intel_connector *connector,
+                     enum transcoder cpu_transcoder, u8 content_type);
 int intel_hdcp_disable(struct intel_connector *connector);
 bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
 bool intel_hdcp_capable(struct intel_connector *connector);
index f6f5312205c49ede75fed758cab856b696882bab..f56fffc474faf98868420d81ac415552973c491a 100644 (file)
@@ -2489,9 +2489,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
                return -EINVAL;
        }
 
-       intel_hdcp_transcoder_config(intel_hdmi->attached_connector,
-                                    pipe_config->cpu_transcoder);
-
        return 0;
 }
 
index 9fdefbdc35467399afc5c0709c7b5ba6fd9987b4..75dd0e0367b7a5c467bd5dee3313feae6941da1b 100644 (file)
@@ -845,12 +845,6 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
        }
 }
 
-static void unwind_wa_tail(struct i915_request *rq)
-{
-       rq->tail = intel_ring_wrap(rq->ring, rq->wa_tail - WA_TAIL_BYTES);
-       assert_ring_tail_valid(rq->ring, rq->tail);
-}
-
 static struct i915_request *
 __unwind_incomplete_requests(struct intel_engine_cs *engine)
 {
@@ -863,12 +857,10 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
        list_for_each_entry_safe_reverse(rq, rn,
                                         &engine->active.requests,
                                         sched.link) {
-
                if (i915_request_completed(rq))
                        continue; /* XXX */
 
                __i915_request_unsubmit(rq);
-               unwind_wa_tail(rq);
 
                /*
                 * Push the request back into the queue for later resubmission.
@@ -1161,13 +1153,29 @@ execlists_schedule_out(struct i915_request *rq)
        i915_request_put(rq);
 }
 
-static u64 execlists_update_context(const struct i915_request *rq)
+static u64 execlists_update_context(struct i915_request *rq)
 {
        struct intel_context *ce = rq->hw_context;
-       u64 desc;
+       u64 desc = ce->lrc_desc;
+       u32 tail;
 
-       ce->lrc_reg_state[CTX_RING_TAIL] =
-               intel_ring_set_tail(rq->ring, rq->tail);
+       /*
+        * WaIdleLiteRestore:bdw,skl
+        *
+        * We should never submit the context with the same RING_TAIL twice
+        * just in case we submit an empty ring, which confuses the HW.
+        *
+        * We append a couple of NOOPs (gen8_emit_wa_tail) after the end of
+        * the normal request to be able to always advance the RING_TAIL on
+        * subsequent resubmissions (for lite restore). Should that fail us,
+        * and we try and submit the same tail again, force the context
+        * reload.
+        */
+       tail = intel_ring_set_tail(rq->ring, rq->tail);
+       if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL] == tail))
+               desc |= CTX_DESC_FORCE_RESTORE;
+       ce->lrc_reg_state[CTX_RING_TAIL] = tail;
+       rq->tail = rq->wa_tail;
 
        /*
         * Make sure the context image is complete before we submit it to HW.
@@ -1186,13 +1194,11 @@ static u64 execlists_update_context(const struct i915_request *rq)
         */
        mb();
 
-       desc = ce->lrc_desc;
-       ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
-
        /* Wa_1607138340:tgl */
        if (IS_TGL_REVID(rq->i915, TGL_REVID_A0, TGL_REVID_A0))
                desc |= CTX_DESC_FORCE_RESTORE;
 
+       ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
        return desc;
 }
 
@@ -1703,16 +1709,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 
                                return;
                        }
-
-                       /*
-                        * WaIdleLiteRestore:bdw,skl
-                        * Apply the wa NOOPs to prevent
-                        * ring:HEAD == rq:TAIL as we resubmit the
-                        * request. See gen8_emit_fini_breadcrumb() for
-                        * where we prepare the padding after the
-                        * end of the request.
-                        */
-                       last->tail = last->wa_tail;
                }
        }
 
@@ -4120,17 +4116,18 @@ static void virtual_context_destroy(struct kref *kref)
        for (n = 0; n < ve->num_siblings; n++) {
                struct intel_engine_cs *sibling = ve->siblings[n];
                struct rb_node *node = &ve->nodes[sibling->id].rb;
+               unsigned long flags;
 
                if (RB_EMPTY_NODE(node))
                        continue;
 
-               spin_lock_irq(&sibling->active.lock);
+               spin_lock_irqsave(&sibling->active.lock, flags);
 
                /* Detachment is lazily performed in the execlists tasklet */
                if (!RB_EMPTY_NODE(node))
                        rb_erase_cached(node, &sibling->execlists.virtual);
 
-               spin_unlock_irq(&sibling->active.lock);
+               spin_unlock_irqrestore(&sibling->active.lock, flags);
        }
        GEM_BUG_ON(__tasklet_is_scheduled(&ve->base.execlists.tasklet));
 
index b9eb6b3149b711cea3a4a1673c5ae6bcf7c7bc23..d034fa413164bfeb3f68bdb9bf18a17ce131405b 100644 (file)
@@ -45,6 +45,7 @@
 #include "gem/i915_gem_context.h"
 #include "gem/i915_gem_ioctls.h"
 #include "gem/i915_gem_pm.h"
+#include "gt/intel_context.h"
 #include "gt/intel_engine_user.h"
 #include "gt/intel_gt.h"
 #include "gt/intel_gt_pm.h"
@@ -1053,6 +1054,18 @@ out:
        return err;
 }
 
+static int __intel_context_flush_retire(struct intel_context *ce)
+{
+       struct intel_timeline *tl;
+
+       tl = intel_context_timeline_lock(ce);
+       if (IS_ERR(tl))
+               return PTR_ERR(tl);
+
+       intel_context_timeline_unlock(tl);
+       return 0;
+}
+
 static int __intel_engines_record_defaults(struct intel_gt *gt)
 {
        struct i915_request *requests[I915_NUM_ENGINES] = {};
@@ -1121,13 +1134,20 @@ err_rq:
                if (!rq)
                        continue;
 
-               /* We want to be able to unbind the state from the GGTT */
-               GEM_BUG_ON(intel_context_is_pinned(rq->hw_context));
-
+               GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT,
+                                    &rq->hw_context->flags));
                state = rq->hw_context->state;
                if (!state)
                        continue;
 
+               /* Serialise with retirement on another CPU */
+               err = __intel_context_flush_retire(rq->hw_context);
+               if (err)
+                       goto out;
+
+               /* We want to be able to unbind the state from the GGTT */
+               GEM_BUG_ON(intel_context_is_pinned(rq->hw_context));
+
                /*
                 * As we will hold a reference to the logical state, it will
                 * not be torn down with the context, and importantly the
index 65d7c2e599de03718c3466f165b75183b2d27ad1..2ae14bc149317afb65d2b8d04bd6fefd9a1f33e5 100644 (file)
@@ -2078,20 +2078,12 @@ gen8_update_reg_state_unlocked(const struct intel_context *ce,
        u32 *reg_state = ce->lrc_reg_state;
        int i;
 
-       if (IS_GEN(stream->perf->i915, 12)) {
-               u32 format = stream->oa_buffer.format;
+       reg_state[ctx_oactxctrl + 1] =
+               (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
+               (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
+               GEN8_OA_COUNTER_RESUME;
 
-               reg_state[ctx_oactxctrl + 1] =
-                       (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) |
-                       (stream->oa_config ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0);
-       } else {
-               reg_state[ctx_oactxctrl + 1] =
-                       (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
-                       (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
-                       GEN8_OA_COUNTER_RESUME;
-       }
-
-       for (i = 0; !!ctx_flexeu0 && i < ARRAY_SIZE(flex_regs); i++)
+       for (i = 0; i < ARRAY_SIZE(flex_regs); i++)
                reg_state[ctx_flexeu0 + i * 2 + 1] =
                        oa_config_flex_reg(stream->oa_config, flex_regs[i]);
 
@@ -2224,34 +2216,51 @@ static int gen8_configure_context(struct i915_gem_context *ctx,
        return err;
 }
 
-static int gen12_emit_oar_config(struct intel_context *ce, bool enable)
+static int gen12_configure_oar_context(struct i915_perf_stream *stream, bool enable)
 {
-       struct i915_request *rq;
-       u32 *cs;
-       int err = 0;
-
-       rq = i915_request_create(ce);
-       if (IS_ERR(rq))
-               return PTR_ERR(rq);
-
-       cs = intel_ring_begin(rq, 4);
-       if (IS_ERR(cs)) {
-               err = PTR_ERR(cs);
-               goto out;
-       }
-
-       *cs++ = MI_LOAD_REGISTER_IMM(1);
-       *cs++ = i915_mmio_reg_offset(RING_CONTEXT_CONTROL(ce->engine->mmio_base));
-       *cs++ = _MASKED_FIELD(GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE,
-                             enable ? GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE : 0);
-       *cs++ = MI_NOOP;
+       int err;
+       struct intel_context *ce = stream->pinned_ctx;
+       u32 format = stream->oa_buffer.format;
+       struct flex regs_context[] = {
+               {
+                       GEN8_OACTXCONTROL,
+                       stream->perf->ctx_oactxctrl_offset + 1,
+                       enable ? GEN8_OA_COUNTER_RESUME : 0,
+               },
+       };
+       /* Offsets in regs_lri are not used since this configuration is only
+        * applied using LRI. Initialize the correct offsets for posterity.
+        */
+#define GEN12_OAR_OACONTROL_OFFSET 0x5B0
+       struct flex regs_lri[] = {
+               {
+                       GEN12_OAR_OACONTROL,
+                       GEN12_OAR_OACONTROL_OFFSET + 1,
+                       (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) |
+                       (enable ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0)
+               },
+               {
+                       RING_CONTEXT_CONTROL(ce->engine->mmio_base),
+                       CTX_CONTEXT_CONTROL,
+                       _MASKED_FIELD(GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE,
+                                     enable ?
+                                     GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE :
+                                     0)
+               },
+       };
 
-       intel_ring_advance(rq, cs);
+       /* Modify the context image of pinned context with regs_context*/
+       err = intel_context_lock_pinned(ce);
+       if (err)
+               return err;
 
-out:
-       i915_request_add(rq);
+       err = gen8_modify_context(ce, regs_context, ARRAY_SIZE(regs_context));
+       intel_context_unlock_pinned(ce);
+       if (err)
+               return err;
 
-       return err;
+       /* Apply regs_lri using LRI with pinned context */
+       return gen8_modify_self(ce, regs_lri, ARRAY_SIZE(regs_lri));
 }
 
 /*
@@ -2277,53 +2286,16 @@ out:
  *   per-context OA state.
  *
  * Note: it's only the RCS/Render context that has any OA state.
+ * Note: the first flex register passed must always be R_PWR_CLK_STATE
  */
-static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
-                                     const struct i915_oa_config *oa_config)
+static int oa_configure_all_contexts(struct i915_perf_stream *stream,
+                                    struct flex *regs,
+                                    size_t num_regs)
 {
        struct drm_i915_private *i915 = stream->perf->i915;
-       /* The MMIO offsets for Flex EU registers aren't contiguous */
-       const u32 ctx_flexeu0 = stream->perf->ctx_flexeu0_offset;
-#define ctx_flexeuN(N) (ctx_flexeu0 + 2 * (N) + 1)
-       struct flex regs[] = {
-               {
-                       GEN8_R_PWR_CLK_STATE,
-                       CTX_R_PWR_CLK_STATE,
-               },
-               {
-                       IS_GEN(i915, 12) ?
-                       GEN12_OAR_OACONTROL : GEN8_OACTXCONTROL,
-                       stream->perf->ctx_oactxctrl_offset + 1,
-               },
-               { EU_PERF_CNTL0, ctx_flexeuN(0) },
-               { EU_PERF_CNTL1, ctx_flexeuN(1) },
-               { EU_PERF_CNTL2, ctx_flexeuN(2) },
-               { EU_PERF_CNTL3, ctx_flexeuN(3) },
-               { EU_PERF_CNTL4, ctx_flexeuN(4) },
-               { EU_PERF_CNTL5, ctx_flexeuN(5) },
-               { EU_PERF_CNTL6, ctx_flexeuN(6) },
-       };
-#undef ctx_flexeuN
        struct intel_engine_cs *engine;
        struct i915_gem_context *ctx, *cn;
-       size_t array_size = IS_GEN(i915, 12) ? 2 : ARRAY_SIZE(regs);
-       int i, err;
-
-       if (IS_GEN(i915, 12)) {
-               u32 format = stream->oa_buffer.format;
-
-               regs[1].value =
-                       (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) |
-                       (oa_config ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0);
-       } else {
-               regs[1].value =
-                       (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
-                       (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
-                       GEN8_OA_COUNTER_RESUME;
-       }
-
-       for (i = 2; !!ctx_flexeu0 && i < array_size; i++)
-               regs[i].value = oa_config_flex_reg(oa_config, regs[i].reg);
+       int err;
 
        lockdep_assert_held(&stream->perf->lock);
 
@@ -2353,7 +2325,7 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
 
                spin_unlock(&i915->gem.contexts.lock);
 
-               err = gen8_configure_context(ctx, regs, array_size);
+               err = gen8_configure_context(ctx, regs, num_regs);
                if (err) {
                        i915_gem_context_put(ctx);
                        return err;
@@ -2378,7 +2350,7 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
 
                regs[0].value = intel_sseu_make_rpcs(i915, &ce->sseu);
 
-               err = gen8_modify_self(ce, regs, array_size);
+               err = gen8_modify_self(ce, regs, num_regs);
                if (err)
                        return err;
        }
@@ -2386,6 +2358,56 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
        return 0;
 }
 
+static int gen12_configure_all_contexts(struct i915_perf_stream *stream,
+                                       const struct i915_oa_config *oa_config)
+{
+       struct flex regs[] = {
+               {
+                       GEN8_R_PWR_CLK_STATE,
+                       CTX_R_PWR_CLK_STATE,
+               },
+       };
+
+       return oa_configure_all_contexts(stream, regs, ARRAY_SIZE(regs));
+}
+
+static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
+                                     const struct i915_oa_config *oa_config)
+{
+       /* The MMIO offsets for Flex EU registers aren't contiguous */
+       const u32 ctx_flexeu0 = stream->perf->ctx_flexeu0_offset;
+#define ctx_flexeuN(N) (ctx_flexeu0 + 2 * (N) + 1)
+       struct flex regs[] = {
+               {
+                       GEN8_R_PWR_CLK_STATE,
+                       CTX_R_PWR_CLK_STATE,
+               },
+               {
+                       GEN8_OACTXCONTROL,
+                       stream->perf->ctx_oactxctrl_offset + 1,
+               },
+               { EU_PERF_CNTL0, ctx_flexeuN(0) },
+               { EU_PERF_CNTL1, ctx_flexeuN(1) },
+               { EU_PERF_CNTL2, ctx_flexeuN(2) },
+               { EU_PERF_CNTL3, ctx_flexeuN(3) },
+               { EU_PERF_CNTL4, ctx_flexeuN(4) },
+               { EU_PERF_CNTL5, ctx_flexeuN(5) },
+               { EU_PERF_CNTL6, ctx_flexeuN(6) },
+       };
+#undef ctx_flexeuN
+       int i;
+
+       regs[1].value =
+               (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
+               (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
+               GEN8_OA_COUNTER_RESUME;
+
+       for (i = 2; i < ARRAY_SIZE(regs); i++)
+               regs[i].value = oa_config_flex_reg(oa_config, regs[i].reg);
+
+       return oa_configure_all_contexts(stream, regs, ARRAY_SIZE(regs));
+}
+
 static int gen8_enable_metric_set(struct i915_perf_stream *stream)
 {
        struct intel_uncore *uncore = stream->uncore;
@@ -2464,7 +2486,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream)
         * to make sure all slices/subslices are ON before writing to NOA
         * registers.
         */
-       ret = lrc_configure_all_contexts(stream, oa_config);
+       ret = gen12_configure_all_contexts(stream, oa_config);
        if (ret)
                return ret;
 
@@ -2474,8 +2496,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream)
         * requested this.
         */
        if (stream->ctx) {
-               ret = gen12_emit_oar_config(stream->pinned_ctx,
-                                           oa_config != NULL);
+               ret = gen12_configure_oar_context(stream, true);
                if (ret)
                        return ret;
        }
@@ -2509,11 +2530,11 @@ static void gen12_disable_metric_set(struct i915_perf_stream *stream)
        struct intel_uncore *uncore = stream->uncore;
 
        /* Reset all contexts' slices/subslices configurations. */
-       lrc_configure_all_contexts(stream, NULL);
+       gen12_configure_all_contexts(stream, NULL);
 
        /* disable the context save/restore or OAR counters */
        if (stream->ctx)
-               gen12_emit_oar_config(stream->pinned_ctx, false);
+               gen12_configure_oar_context(stream, false);
 
        /* Make sure we disable noa to save power. */
        intel_uncore_rmw(uncore, RPM_CONFIG1, GEN10_GT_NOA_ENABLE, 0);
@@ -2713,7 +2734,8 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
                return -EINVAL;
        }
 
-       if (!(props->sample_flags & SAMPLE_OA_REPORT)) {
+       if (!(props->sample_flags & SAMPLE_OA_REPORT) &&
+           (INTEL_GEN(perf->i915) < 12 || !stream->ctx)) {
                DRM_DEBUG("Only OA report sampling supported\n");
                return -EINVAL;
        }
@@ -2745,7 +2767,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
 
        format_size = perf->oa_formats[props->oa_format].size;
 
-       stream->sample_flags |= SAMPLE_OA_REPORT;
+       stream->sample_flags = props->sample_flags;
        stream->sample_size += format_size;
 
        stream->oa_buffer.format_size = format_size;
@@ -2854,7 +2876,11 @@ void i915_oa_init_reg_state(const struct intel_context *ce,
                return;
 
        stream = engine->i915->perf.exclusive_stream;
-       if (stream)
+       /*
+        * For gen12, only CTX_R_PWR_CLK_STATE needs update, but the caller
+        * is already doing that, so nothing to be done for gen12 here.
+        */
+       if (stream && INTEL_GEN(stream->perf->i915) < 12)
                gen8_update_reg_state_unlocked(ce, stream);
 }