@@ -1758,14 +1758,21 @@ struct drm_i915_private {
struct llist_head free_list;
struct work_struct free_work;
- /* The hw wants to have a stable context identifier for the
+ /*
+ * The HW wants to have a stable context identifier for the
* lifetime of the context (for OA, PASID, faults, etc).
* This is limited in execlists to 21 bits.
+ * In enhanced execlist (GEN11+) this is limited to 11 bits
+ * (the SW Context ID field) but GuC limits it further so
+ * without taking advantage of part of the SW counter field the
+ * firmware only supports a max number of contexts equal to the
+ * number of entries in the GuC stage descriptor pool.
*/
struct ida hw_ida;
#define MAX_CONTEXT_HW_ID (1<<21) /* exclusive */
#define MAX_GUC_CONTEXT_HW_ID (1 << 20) /* exclusive */
#define GEN11_MAX_CONTEXT_HW_ID (1<<11) /* exclusive */
+#define GEN11_MAX_CONTEXT_HW_ID_WITH_GUC GUC_MAX_STAGE_DESCRIPTORS
struct list_head hw_id_list;
} contexts;
@@ -144,8 +144,12 @@ static inline int new_hw_id(struct drm_i915_private *i915, gfp_t gfp)
lockdep_assert_held(&i915->contexts.mutex);
+ BUILD_BUG_ON(GUC_MAX_STAGE_DESCRIPTORS > GEN11_MAX_CONTEXT_HW_ID);
+
if (INTEL_GEN(i915) >= 11)
- max = GEN11_MAX_CONTEXT_HW_ID;
+ max = USES_GUC_SUBMISSION(i915) ?
+ GEN11_MAX_CONTEXT_HW_ID_WITH_GUC :
+ GEN11_MAX_CONTEXT_HW_ID;
else if (USES_GUC_SUBMISSION(i915))
/*
* When using GuC in proxy submission, GuC consumes the
@@ -1292,6 +1292,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
case 11: {
i915->perf.oa.specific_ctx_id_mask =
((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32) |
+ ((1U << GEN11_SW_COUNTER_WIDTH) - 1) << (GEN11_SW_COUNTER_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);
@@ -4008,6 +4008,8 @@ enum {
#define GEN8_CTX_ID_WIDTH 21
#define GEN11_SW_CTX_ID_SHIFT 37
#define GEN11_SW_CTX_ID_WIDTH 11
+#define GEN11_SW_COUNTER_SHIFT 55
+#define GEN11_SW_COUNTER_WIDTH 6
#define GEN11_ENGINE_CLASS_SHIFT 61
#define GEN11_ENGINE_CLASS_WIDTH 3
#define GEN11_ENGINE_INSTANCE_SHIFT 48
@@ -53,6 +53,8 @@ struct intel_context {
u32 *lrc_reg_state;
u64 lrc_desc;
+ u32 sw_context_id;
+ u32 sw_counter;
atomic_t pin_count;
struct mutex pin_mutex; /* guards pinning and associated on-gpuing */
@@ -345,14 +345,15 @@ lrc_descriptor(struct intel_context *ce, struct intel_engine_cs *engine)
* anything below.
*/
if (INTEL_GEN(engine->i915) >= 11) {
- GEM_BUG_ON(ctx->hw_id >= BIT(GEN11_SW_CTX_ID_WIDTH));
- desc |= (u64)ctx->hw_id << GEN11_SW_CTX_ID_SHIFT;
+ GEM_BUG_ON(ce->sw_context_id >= BIT(GEN11_SW_CTX_ID_WIDTH));
+ desc |= (u64)ce->sw_context_id << GEN11_SW_CTX_ID_SHIFT;
/* bits 37-47 */
desc |= (u64)engine->instance << GEN11_ENGINE_INSTANCE_SHIFT;
/* bits 48-53 */
- /* TODO: decide what to do with SW counter (bits 55-60) */
+ desc |= (u64)ce->sw_counter << GEN11_SW_COUNTER_SHIFT;
+ /* bits 55-60 */
desc |= (u64)engine->class << GEN11_ENGINE_CLASS_SHIFT;
/* bits 61-63 */
@@ -1358,6 +1359,11 @@ __execlists_context_pin(struct intel_context *ce,
if (ret)
goto unpin_ring;
+ if (INTEL_GEN(engine->i915) >= 11) {
+ ce->sw_context_id = ce->gem_context->hw_id;
+ ce->sw_counter = engine->instance;
+ }
+
ce->lrc_desc = lrc_descriptor(ce, engine);
ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
__execlists_update_reg_state(ce, engine);