Merge tag 'drm-intel-fixes-2024-12-11' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-fixes

- Don't use indexed register writes needlessly [dsb] (Ville Syrjälä)
- Stop using non-posted DSB writes for legacy LUT [color] (Ville Syrjälä)
- Fix NULL pointer dereference in capture_engine (Eugene Kobyak)
- Fix memory leak by correcting cache object name in error handler (Jiasheng Jiang)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Tvrtko Ursulin <tursulin@igalia.com>
Link: https://patchwork.freedesktop.org/patch/msgid/Z1nULMrutE4HERvB@linux
This commit is contained in:
Dave Airlie 2024-12-13 08:53:15 +10:00
commit c98f9ab909
5 changed files with 85 additions and 37 deletions

View File

@ -1343,6 +1343,17 @@ static void ilk_lut_write(const struct intel_crtc_state *crtc_state,
intel_de_write_fw(display, reg, val);
}
static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state,
i915_reg_t reg, u32 val)
{
struct intel_display *display = to_intel_display(crtc_state);
if (crtc_state->dsb_color_vblank)
intel_dsb_reg_write_indexed(crtc_state->dsb_color_vblank, reg, val);
else
intel_de_write_fw(display, reg, val);
}
static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
const struct drm_property_blob *blob)
{
@ -1357,19 +1368,29 @@ static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
lut = blob->data;
/*
* DSB fails to correctly load the legacy LUT
* unless we either write each entry twice,
* or use non-posted writes
* DSB fails to correctly load the legacy LUT unless
* we either write each entry twice when using posted
* writes, or we use non-posted writes.
*
* If palette anti-collision is active during LUT
* register writes:
* - posted writes simply get dropped and thus the LUT
* contents may not be correctly updated
* - non-posted writes are blocked and thus the LUT
* contents are always correct, but simultaneous CPU
* MMIO access will start to fail
*
* Choose the lesser of two evils and use posted writes.
* Using posted writes is also faster, even when having
* to write each register twice.
*/
if (crtc_state->dsb_color_vblank)
intel_dsb_nonpost_start(crtc_state->dsb_color_vblank);
for (i = 0; i < 256; i++)
for (i = 0; i < 256; i++) {
ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
i9xx_lut_8(&lut[i]));
if (crtc_state->dsb_color_vblank)
intel_dsb_nonpost_end(crtc_state->dsb_color_vblank);
if (crtc_state->dsb_color_vblank)
ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
i9xx_lut_8(&lut[i]));
}
}
static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state,
@ -1458,8 +1479,8 @@ static void bdw_load_lut_10(const struct intel_crtc_state *crtc_state,
prec_index);
for (i = 0; i < lut_size; i++)
ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_10(&lut[i]));
ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_10(&lut[i]));
/*
* Reset the index, otherwise it prevents the legacy palette to be
@ -1612,16 +1633,16 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state,
* ToDo: Extend to max 7.0. Enable 32 bit input value
* as compared to just 16 to achieve this.
*/
ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
DISPLAY_VER(display) >= 14 ?
mtl_degamma_lut(&lut[i]) : glk_degamma_lut(&lut[i]));
ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe),
DISPLAY_VER(display) >= 14 ?
mtl_degamma_lut(&lut[i]) : glk_degamma_lut(&lut[i]));
}
/* Clamp values > 1.0. */
while (i++ < glk_degamma_lut_size(display))
ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
DISPLAY_VER(display) >= 14 ?
1 << 24 : 1 << 16);
ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe),
DISPLAY_VER(display) >= 14 ?
1 << 24 : 1 << 16);
ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0);
}
@ -1687,10 +1708,10 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state)
for (i = 0; i < 9; i++) {
const struct drm_color_lut *entry = &lut[i];
ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
ilk_lut_12p4_ldw(entry));
ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
ilk_lut_12p4_udw(entry));
ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
ilk_lut_12p4_ldw(entry));
ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
ilk_lut_12p4_udw(entry));
}
ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe),
@ -1726,10 +1747,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
for (i = 1; i < 257; i++) {
entry = &lut[i * 8];
ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_12p4_ldw(entry));
ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_12p4_udw(entry));
ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_12p4_ldw(entry));
ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_12p4_udw(entry));
}
/*
@ -1747,10 +1768,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
for (i = 0; i < 256; i++) {
entry = &lut[i * 8 * 128];
ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_12p4_ldw(entry));
ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_12p4_udw(entry));
ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_12p4_ldw(entry));
ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
ilk_lut_12p4_udw(entry));
}
ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),

View File

@ -273,16 +273,20 @@ static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_
}
/**
* intel_dsb_reg_write() - Emit register wriite to the DSB context
* intel_dsb_reg_write_indexed() - Emit register wriite to the DSB context
* @dsb: DSB context
* @reg: register address.
* @val: value.
*
* This function is used for writing register-value pair in command
* buffer of DSB.
*
* Note that indexed writes are slower than normal MMIO writes
* for a small number (less than 5 or so) of writes to the same
* register.
*/
void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val)
void intel_dsb_reg_write_indexed(struct intel_dsb *dsb,
i915_reg_t reg, u32 val)
{
/*
* For example the buffer will look like below for 3 dwords for auto
@ -340,6 +344,15 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
}
}
void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val)
{
intel_dsb_emit(dsb, val,
(DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) |
(DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) |
i915_mmio_reg_offset(reg));
}
static u32 intel_dsb_mask_to_byte_en(u32 mask)
{
return (!!(mask & 0xff000000) << 3 |

View File

@ -34,6 +34,8 @@ void intel_dsb_finish(struct intel_dsb *dsb);
void intel_dsb_cleanup(struct intel_dsb *dsb);
void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val);
void intel_dsb_reg_write_indexed(struct intel_dsb *dsb,
i915_reg_t reg, u32 val);
void intel_dsb_reg_write_masked(struct intel_dsb *dsb,
i915_reg_t reg, u32 mask, u32 val);
void intel_dsb_noop(struct intel_dsb *dsb, int count);

View File

@ -1643,9 +1643,21 @@ capture_engine(struct intel_engine_cs *engine,
return NULL;
intel_engine_get_hung_entity(engine, &ce, &rq);
if (rq && !i915_request_started(rq))
drm_info(&engine->gt->i915->drm, "Got hung context on %s with active request %lld:%lld [0x%04X] not yet started\n",
engine->name, rq->fence.context, rq->fence.seqno, ce->guc_id.id);
if (rq && !i915_request_started(rq)) {
/*
* We want to know also what is the guc_id of the context,
* but if we don't have the context reference, then skip
* printing it.
*/
if (ce)
drm_info(&engine->gt->i915->drm,
"Got hung context on %s with active request %lld:%lld [0x%04X] not yet started\n",
engine->name, rq->fence.context, rq->fence.seqno, ce->guc_id.id);
else
drm_info(&engine->gt->i915->drm,
"Got hung context on %s with active request %lld:%lld not yet started\n",
engine->name, rq->fence.context, rq->fence.seqno);
}
if (rq) {
capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL);

View File

@ -506,6 +506,6 @@ int __init i915_scheduler_module_init(void)
return 0;
err_priorities:
kmem_cache_destroy(slab_priorities);
kmem_cache_destroy(slab_dependencies);
return -ENOMEM;
}