@@ -553,6 +553,8 @@ int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv)
int intel_ctx_workarounds_emit(struct i915_request *rq)
{
struct i915_workarounds *w = &rq->i915->workarounds;
+ struct i915_wa_reg *reg = w->reg;
+ unsigned int remain;
u32 *cs;
int ret, i;
@@ -563,18 +565,27 @@ int intel_ctx_workarounds_emit(struct i915_request *rq)
if (ret)
return ret;
- cs = intel_ring_begin(rq, (w->count * 2 + 2));
- if (IS_ERR(cs))
- return PTR_ERR(cs);
+ remain = w->count;
+ do {
+ unsigned int count;
- *cs++ = MI_LOAD_REGISTER_IMM(w->count);
- for (i = 0; i < w->count; i++) {
- *cs++ = w->reg[i].addr;
- *cs++ = w->reg[i].value;
- }
- *cs++ = MI_NOOP;
+ count = min(remain, 15u);
+ remain -= count;
+
+ cs = intel_ring_begin(rq, 2 * count + 2);
+ if (IS_ERR(cs))
+ return PTR_ERR(cs);
+
+ *cs++ = MI_LOAD_REGISTER_IMM(count);
+ for (i = 0; i < count; i++) {
+ *cs++ = reg->addr;
+ *cs++ = reg->value;
+ reg++;
+ }
+ *cs++ = MI_NOOP;
- intel_ring_advance(rq, cs);
+ intel_ring_advance(rq, cs);
+ } while (remain);
ret = rq->engine->emit_flush(rq, EMIT_BARRIER);
if (ret)
We are restricted to the number of registers we can rewrite into a single command by the packet length. If we have more registers than can be fitted into a single packet, we therefore need to split the writes into multiple packets. Reported-by: Kenneth Graunke <kenneth@whitecape.org> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Oscar Mateo <oscar.mateo@intel.com> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Kenneth Graunke <kenneth@whitecape.org> --- drivers/gpu/drm/i915/intel_workarounds.c | 31 ++++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-)