Hello Sebastian,
At 2026-08-07 01:02:12, "Sebastian Reichel" <[email protected]> wrote: >The DP AUX transfer method uses a completion triggered by an interrupt, >which can timeout. If the function runs into the timeout and the >interrupt fires afterwards, the following DP aux transfer completion >would trigger immediately without waiting for the interrupt. This in >turn means the next one would also be broken and so on. > >Fix this potential issue by re-initializing the completion directly >before sending the AUX command. > >As this is racy (the interrupt might arrive between the completion >re-init and the new command being programmed), also reset the AUX >controller on timeouts and synchronize pending interrupts to gurantee Typo: s/gurantee/guarantee >that there are no pending AUX transfers when the dw_dp_aux_transfer() >returns. > >Due to lack of a sink, which generates AUX timeouts, this change is >effectively untested. > >Reported-by: Sashiko <[email protected]> >Fixes: 86eecc3a9c2e ("drm/bridge: synopsys: Add DW DPTX Controller support >library") >Signed-off-by: Sebastian Reichel <[email protected]> >--- > drivers/gpu/drm/bridge/synopsys/dw-dp.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c >b/drivers/gpu/drm/bridge/synopsys/dw-dp.c >index b1856418f441..2573ea2bb574 100644 >--- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c >+++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c >@@ -1466,6 +1466,8 @@ static ssize_t dw_dp_aux_transfer(struct drm_dp_aux *aux, > if (WARN_ON(msg->size > 16)) > return -E2BIG; > >+ reinit_completion(&dp->complete); >+ > switch (msg->request & ~DP_AUX_I2C_MOT) { > case DP_AUX_NATIVE_WRITE: > case DP_AUX_I2C_WRITE: >@@ -1492,6 +1494,12 @@ static ssize_t dw_dp_aux_transfer(struct drm_dp_aux >*aux, > status = wait_for_completion_timeout(&dp->complete, timeout); > if (!status) { > dev_err(dp->dev, "timeout waiting for AUX reply\n"); >+ regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, >+ AUX_RESET, FIELD_PREP(AUX_RESET, 1)); >+ usleep_range(10, 20); >+ regmap_update_bits(dp->regmap, DW_DP_SOFT_RESET_CTRL, >+ AUX_RESET, FIELD_PREP(AUX_RESET, 0)); >+ synchronize_irq(dp->irq); > return -ETIMEDOUT; > } > > >-- >2.53.0 >
