[PATCH v8 06/21] drm/bridge: synopsys: dw-dp: Fix AUX transfer timeout race condition
From: Sebastian Reichel
Date: Fri Jul 31 2026 - 10:52:31 EST
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
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 <sashiko-bot@xxxxxxxxxx>
Fixes: 86eecc3a9c2e ("drm/bridge: synopsys: Add DW DPTX Controller support library")
Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxx>
---
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 f373643a9cc1..57b6a8fc98d0 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