thunderbolt: Disable CL states only when actually needed
authorMika Westerberg <mika.westerberg@linux.intel.com>
Fri, 17 Nov 2023 10:58:39 +0000 (12:58 +0200)
committerMika Westerberg <mika.westerberg@linux.intel.com>
Thu, 14 Dec 2023 06:07:45 +0000 (08:07 +0200)
If there is not going to be an actual transition to asymmetric or
symmetric, there is no point to disable and re-enable CL states either.
So instead disable them only when we know that an actual transition is
going to take place.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
drivers/thunderbolt/tb.c

index f81e7cf53d69141652b1c4f095d3106e2702d4ac..cf1a20a33b9a9694f57d013ca17ca27daac770eb 100644 (file)
@@ -1075,15 +1075,14 @@ static int tb_configure_asym(struct tb *tb, struct tb_port *src_port,
                             struct tb_port *dst_port, int requested_up,
                             int requested_down)
 {
+       bool clx = false, clx_disabled = false, downstream;
        struct tb_switch *sw;
-       bool clx, downstream;
        struct tb_port *up;
        int ret = 0;
 
        if (!asym_threshold)
                return 0;
 
-       /* Disable CL states before doing any transitions */
        downstream = tb_port_path_direction_downstream(src_port, dst_port);
        /* Pick up router deepest in the hierarchy */
        if (downstream)
@@ -1091,8 +1090,6 @@ static int tb_configure_asym(struct tb *tb, struct tb_port *src_port,
        else
                sw = src_port->sw;
 
-       clx = tb_disable_clx(sw);
-
        tb_for_each_upstream_port_on_path(src_port, dst_port, up) {
                struct tb_port *down = tb_switch_downstream_port(up->sw);
                enum tb_link_width width_up, width_down;
@@ -1139,6 +1136,16 @@ static int tb_configure_asym(struct tb *tb, struct tb_port *src_port,
                    !tb_port_width_supported(down, width_down))
                        continue;
 
+               /*
+                * Disable CL states before doing any transitions. We
+                * delayed it until now that we know there is a real
+                * transition taking place.
+                */
+               if (!clx_disabled) {
+                       clx = tb_disable_clx(sw);
+                       clx_disabled = true;
+               }
+
                tb_sw_dbg(up->sw, "configuring asymmetric link\n");
 
                /*
@@ -1175,15 +1182,14 @@ static int tb_configure_sym(struct tb *tb, struct tb_port *src_port,
                            struct tb_port *dst_port, int requested_up,
                            int requested_down)
 {
+       bool clx = false, clx_disabled = false, downstream;
        struct tb_switch *sw;
-       bool clx, downstream;
        struct tb_port *up;
        int ret = 0;
 
        if (!asym_threshold)
                return 0;
 
-       /* Disable CL states before doing any transitions */
        downstream = tb_port_path_direction_downstream(src_port, dst_port);
        /* Pick up router deepest in the hierarchy */
        if (downstream)
@@ -1191,8 +1197,6 @@ static int tb_configure_sym(struct tb *tb, struct tb_port *src_port,
        else
                sw = src_port->sw;
 
-       clx = tb_disable_clx(sw);
-
        tb_for_each_upstream_port_on_path(src_port, dst_port, up) {
                int consumed_up, consumed_down;
 
@@ -1225,6 +1229,12 @@ static int tb_configure_sym(struct tb *tb, struct tb_port *src_port,
                if (up->sw->link_width == TB_LINK_WIDTH_DUAL)
                        continue;
 
+               /* Disable CL states before doing any transitions */
+               if (!clx_disabled) {
+                       clx = tb_disable_clx(sw);
+                       clx_disabled = true;
+               }
+
                tb_sw_dbg(up->sw, "configuring symmetric link\n");
 
                ret = tb_switch_set_link_width(up->sw, TB_LINK_WIDTH_DUAL);