--- a/sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -192,6 +192,30 @@ } +/* + * DF-5055 (DF-4933 twin on the dce80 table wiring): the dce80 + * vupdate_int_entry (irq_service_dce80.c:132-146) initializes no + * .src_id -- and neither does dce110's own (irq_service_dce110.c:127-141) + * -- so for DC_IRQ_SOURCE_VUPDATE1..6 the re-derivation inside + * dce110_vblank_set returns DC_IRQ_SOURCE_INVALID and + * `dal_irq_src - IRQ_TYPE_VBLANK' underflows (uint8_t)178, a far-OOB + * pipe_ctx[] read on the MAX_PIPES array whose garbage tg is immediately + * called through tg->funcs->arm_vert_intr(tg, 2). Derive the pipe from + * the table index instead: provably 0..5 for both the VUPDATE and VBLANK + * ranges, independent of src_id. + */ +static uint8_t vblank_pipe_offset( + const struct irq_service *irq_service, + const struct irq_source_info *info) +{ + enum dc_irq_source src = + (enum dc_irq_source)(info - irq_service->info); + + if (src >= DC_IRQ_SOURCE_VUPDATE1 && src <= DC_IRQ_SOURCE_VUPDATE6) + return (uint8_t)(src - DC_IRQ_SOURCE_VUPDATE1); + return (uint8_t)(src - DC_IRQ_SOURCE_VBLANK1); +} + bool dce110_vblank_set(struct irq_service *irq_service, const struct irq_source_info *info, bool enable) @@ -202,7 +226,9 @@ dc_interrupt_to_irq_source(irq_service->ctx->dc, info->src_id, info->ext_id); - uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK; + uint8_t pipe_offset = vblank_pipe_offset(irq_service, info); + (void)dal_irq_src; /* DF-5055/DF-4933: pipe no longer derived + * from the re-mapped src_id */ struct timing_generator *tg = core_dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg;