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(®s, DP_ALLOCATED_BW) * + tunnel->bw_granularity; + if (!tunnel->allocated_bw) + tunnel->allocated_bw = -1; + if (!tunnel->max_dprx_rate) update_dprx_caps(tunnel, ®s); -- 2.25.1
