@@ -1866,14 +1866,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 a bit further
+ * (11 bits - 16) due to some entries being reserved for future
+ * use (so the firmware only supports a GuC stage descriptor
+ * pool of 2032 entries).
*/
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 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 (GEN11_MAX_CONTEXT_HW_ID - 16)
} contexts;
u32 fdi_rx_config;
@@ -209,7 +209,10 @@ static int assign_hw_id(struct drm_i915_private *dev_priv, unsigned *out)
unsigned int max;
if (INTEL_GEN(dev_priv) >= 11) {
- max = GEN11_MAX_CONTEXT_HW_ID;
+ if (USES_GUC_SUBMISSION(dev_priv))
+ max = GEN11_MAX_CONTEXT_HW_ID_WITH_GUC;
+ else
+ max = GEN11_MAX_CONTEXT_HW_ID;
} else {
/*
* When using GuC in proxy submission, GuC consumes the
@@ -154,6 +154,8 @@ struct i915_gem_context {
struct intel_ring *ring;
u32 *lrc_reg_state;
u64 lrc_desc;
+ u32 sw_context_id;
+ u32 sw_counter;
int pin_count;
const struct intel_context_ops *ops;
@@ -3900,6 +3900,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
@@ -240,14 +240,15 @@ static inline bool need_preempt(const struct intel_engine_cs *engine,
* anything below.
*/
if (INTEL_GEN(ctx->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 */
/*
* Although GuC will never see this upper part as it fills
@@ -2771,6 +2772,11 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
ce->ring = ring;
ce->state = vma;
+ if (INTEL_GEN(ctx->i915) >= 11) {
+ ce->sw_context_id = ctx->hw_id;
+ ce->sw_counter = engine->instance;
+ }
+
return 0;
error_ring_free: