]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/thunderbolt/tb.c
Merge tag 'vfs-5.5-merge-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[linux.git] / drivers / thunderbolt / tb.c
index 8f58b9c3ef07b9026ae8a0f978bb55be1d07c652..ea8727f769d639c82fc70f08833246e3df658b3f 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <linux/platform_data/x86/apple.h>
 
 #include "tb.h"
 #include "tb_regs.h"
@@ -422,11 +421,51 @@ static struct tb_port *tb_find_pcie_down(struct tb_switch *sw,
        return tb_find_unused_port(sw, TB_TYPE_PCIE_DOWN);
 }
 
+static int tb_available_bw(struct tb_cm *tcm, struct tb_port *in,
+                          struct tb_port *out)
+{
+       struct tb_switch *sw = out->sw;
+       struct tb_tunnel *tunnel;
+       int bw, available_bw = 40000;
+
+       while (sw && sw != in->sw) {
+               bw = sw->link_speed * sw->link_width * 1000; /* Mb/s */
+               /* Leave 10% guard band */
+               bw -= bw / 10;
+
+               /*
+                * Check for any active DP tunnels that go through this
+                * switch and reduce their consumed bandwidth from
+                * available.
+                */
+               list_for_each_entry(tunnel, &tcm->tunnel_list, list) {
+                       int consumed_bw;
+
+                       if (!tb_tunnel_switch_on_path(tunnel, sw))
+                               continue;
+
+                       consumed_bw = tb_tunnel_consumed_bandwidth(tunnel);
+                       if (consumed_bw < 0)
+                               return consumed_bw;
+
+                       bw -= consumed_bw;
+               }
+
+               if (bw < available_bw)
+                       available_bw = bw;
+
+               sw = tb_switch_parent(sw);
+       }
+
+       return available_bw;
+}
+
 static void tb_tunnel_dp(struct tb *tb)
 {
        struct tb_cm *tcm = tb_priv(tb);
        struct tb_port *port, *in, *out;
        struct tb_tunnel *tunnel;
+       int available_bw;
 
        /*
         * Find pair of inactive DP IN and DP OUT adapters and then
@@ -464,7 +503,17 @@ static void tb_tunnel_dp(struct tb *tb)
                return;
        }
 
-       tunnel = tb_tunnel_alloc_dp(tb, in, out);
+       /* Calculate available bandwidth between in and out */
+       available_bw = tb_available_bw(tcm, in, out);
+       if (available_bw < 0) {
+               tb_warn(tb, "failed to determine available bandwidth\n");
+               return;
+       }
+
+       tb_dbg(tb, "available bandwidth for new DP tunnel %u Mb/s\n",
+              available_bw);
+
+       tunnel = tb_tunnel_alloc_dp(tb, in, out, available_bw);
        if (!tunnel) {
                tb_port_dbg(out, "could not allocate DP tunnel\n");
                goto dealloc_dp;
@@ -940,9 +989,6 @@ struct tb *tb_probe(struct tb_nhi *nhi)
        struct tb_cm *tcm;
        struct tb *tb;
 
-       if (!x86_apple_machine)
-               return NULL;
-
        tb = tb_domain_alloc(nhi, sizeof(*tcm));
        if (!tb)
                return NULL;