aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2024-01-09 17:53:53 +0200
committerMika Westerberg <mika.westerberg@linux.intel.com>2024-02-16 12:29:22 +0200
commit37f49727cc53b1987859fc767ac637078d351c4d (patch)
treeb16d9e12a014d3212d295853709a5309f693a4d3 /drivers/thunderbolt
parent2ec67a48cf8f18b8c6cecc70dcd5d52cbf8eba7e (diff)
downloadlinux-37f49727cc53b1987859fc767ac637078d351c4d.tar.gz
thunderbolt: Fail the failed bandwidth request properly
The USB4 spec says that if the Connection Manager writes Allocated_BW that is smaller than Requested_BW, the DisplayPort IN adapter signals this failure back to the DPTX (graphics driver). Implement this by rewriting the same allocated bandwidth values back. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/thunderbolt')
-rw-r--r--drivers/thunderbolt/tb.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index abd86fd8d71fe7..9dbdf2770f0b1a 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -2270,11 +2270,11 @@ static int tb_alloc_dp_bandwidth(struct tb_tunnel *tunnel, int *requested_up,
*/
ret = tb_tunnel_maximum_bandwidth(tunnel, &max_up, &max_down);
if (ret)
- return ret;
+ goto fail;
ret = usb4_dp_port_granularity(in);
if (ret < 0)
- return ret;
+ goto fail;
granularity = ret;
max_up_rounded = roundup(max_up, granularity);
@@ -2304,7 +2304,8 @@ static int tb_alloc_dp_bandwidth(struct tb_tunnel *tunnel, int *requested_up,
"bandwidth request too high (%d/%d Mb/s > %d/%d Mb/s)\n",
requested_up_corrected, requested_down_corrected,
max_up_rounded, max_down_rounded);
- return -ENOBUFS;
+ ret = -ENOBUFS;
+ goto fail;
}
if ((*requested_up >= 0 && requested_up_corrected <= allocated_up) ||
@@ -2332,7 +2333,7 @@ static int tb_alloc_dp_bandwidth(struct tb_tunnel *tunnel, int *requested_up,
*/
ret = tb_release_unused_usb3_bandwidth(tb, in, out);
if (ret)
- return ret;
+ goto fail;
/*
* Then go over all tunnels that cross the same USB4 ports (they
@@ -2357,7 +2358,7 @@ static int tb_alloc_dp_bandwidth(struct tb_tunnel *tunnel, int *requested_up,
*requested_down);
if (ret) {
tb_configure_sym(tb, in, out, 0, 0, true);
- return ret;
+ goto fail;
}
ret = tb_tunnel_alloc_bandwidth(tunnel, requested_up,
@@ -2372,6 +2373,18 @@ static int tb_alloc_dp_bandwidth(struct tb_tunnel *tunnel, int *requested_up,
reclaim:
tb_reclaim_usb3_bandwidth(tb, in, out);
+fail:
+ if (ret && ret != -ENODEV) {
+ /*
+ * Write back the same allocated (so no change), this
+ * makes the DPTX request fail on graphics side.
+ */
+ tb_tunnel_dbg(tunnel,
+ "failing the request by rewriting allocated %d/%d Mb/s\n",
+ allocated_up, allocated_down);
+ tb_tunnel_alloc_bandwidth(tunnel, &allocated_up, &allocated_down);
+ }
+
return ret;
}