After drm_dp_tunnel_enable_bw_alloc() the read-back DP_ALLOCATED_BW
is not synced back to tunnel->allocated_bw, leaving a stale SW
value. The next drm_dp_tunnel_update_state() call sees a SW vs. HW
mismatch, trips tunnel_info_changes_are_valid(), and returns
-EINVAL causing the driver to tear down and re-detect the tunnel
even though BWA enabled correctly.

Sync tunnel->allocated_bw from the just-read register value after
the post-enable verification, mirroring the initial sync done in
create_tunnel().

Cc: Imre Deak <[email protected]>
Assisted-by: Copilot:claude-sonnet-4-6
Signed-off-by: Kunal Joshi <[email protected]>
---
 drivers/gpu/drm/display/drm_dp_tunnel.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c 
b/drivers/gpu/drm/display/drm_dp_tunnel.c
index c16b36d3bcf8a..e0474e09f4388 100644
--- a/drivers/gpu/drm/display/drm_dp_tunnel.c
+++ b/drivers/gpu/drm/display/drm_dp_tunnel.c
@@ -1048,6 +1048,22 @@ int drm_dp_tunnel_enable_bw_alloc(struct drm_dp_tunnel 
*tunnel)
                goto out;
        }
 
+       /*
+        * Sync the SW allocated_bw to whatever the HW reports right after
+        * enabling BWA mode. The TBT CM may settle to a different
+        * allocation than the SW state held before BWA was disabled (e.g.
+        * after a disable/enable toggle while streams are active, or after
+        * suspend/resume). Without this sync, the next
+        * drm_dp_tunnel_update_state() call - which does NOT pass
+        * ALLOW_ALLOCATED_BW_CHANGE - would observe the SW/HW mismatch in
+        * tunnel_info_changes_are_valid() and return -EINVAL, triggering
+        * an unnecessary tunnel teardown/re-detect.
+        */
+       tunnel->allocated_bw = tunnel_reg(&regs, DP_ALLOCATED_BW) *
+                              tunnel->bw_granularity;
+       if (!tunnel->allocated_bw)
+               tunnel->allocated_bw = -1;
+
        if (!tunnel->max_dprx_rate)
                update_dprx_caps(tunnel, &regs);
 
-- 
2.25.1

Reply via email to