@@ -1085,15 +1085,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)
@@ -1101,8 +1100,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;
@@ -1149,6 +1146,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");
/*
@@ -1185,15 +1192,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)
@@ -1201,8 +1207,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;
@@ -1235,6 +1239,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);
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 | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-)