thunderbolt: Fail the failed bandwidth request properly
authorMika Westerberg <mika.westerberg@linux.intel.com>
Tue, 9 Jan 2024 15:53:53 +0000 (17:53 +0200)
committerMika Westerberg <mika.westerberg@linux.intel.com>
Fri, 16 Feb 2024 10:29:22 +0000 (12:29 +0200)
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>
drivers/thunderbolt/tb.c

index abd86fd8d71fe7d59a72375d35142358395dd8f7..9dbdf2770f0b1aa693285f61360671eb442f07ca 100644 (file)
@@ -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;
 }