Commit 4a420eb1 authored by Mika Westerberg's avatar Mika Westerberg
Browse files

thunderbolt: Make tb_switch_clx_disable() return CL states that were enabled



This allows us to disable all CL states temporarily when running lane
margining and then return back the previously enabled states.

Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent 768e6fe6
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -317,6 +317,9 @@ int tb_switch_clx_enable(struct tb_switch *sw, unsigned int clx)
	struct tb_port *up, *down;
	struct tb_port *up, *down;
	int ret;
	int ret;


	if (!clx)
		return 0;

	if (!validate_mask(clx))
	if (!validate_mask(clx))
		return -EINVAL;
		return -EINVAL;


@@ -380,7 +383,8 @@ int tb_switch_clx_enable(struct tb_switch *sw, unsigned int clx)
 * Disables all CL states of the given router. Can be called on any
 * Disables all CL states of the given router. Can be called on any
 * router and if the states were not enabled already does nothing.
 * router and if the states were not enabled already does nothing.
 *
 *
 * Returns %0 on success or an error code on failure.
 * Returns the CL states that were disabled or negative errno in case of
 * failure.
 */
 */
int tb_switch_clx_disable(struct tb_switch *sw)
int tb_switch_clx_disable(struct tb_switch *sw)
{
{
@@ -408,5 +412,5 @@ int tb_switch_clx_disable(struct tb_switch *sw)
	sw->clx = 0;
	sw->clx = 0;


	tb_sw_dbg(sw, "CLx: %s disabled\n", clx_name(clx));
	tb_sw_dbg(sw, "CLx: %s disabled\n", clx_name(clx));
	return 0;
	return clx;
}
}
+24 −11
Original line number Original line Diff line number Diff line
@@ -553,8 +553,9 @@ static int margining_run_write(void *data, u64 val)
	struct usb4_port *usb4 = port->usb4;
	struct usb4_port *usb4 = port->usb4;
	struct tb_switch *sw = port->sw;
	struct tb_switch *sw = port->sw;
	struct tb_margining *margining;
	struct tb_margining *margining;
	struct tb_switch *down_sw;
	struct tb *tb = sw->tb;
	struct tb *tb = sw->tb;
	int ret;
	int ret, clx;


	if (val != 1)
	if (val != 1)
		return -EINVAL;
		return -EINVAL;
@@ -566,16 +567,25 @@ static int margining_run_write(void *data, u64 val)
		goto out_rpm_put;
		goto out_rpm_put;
	}
	}


	if (tb_is_upstream_port(port))
		down_sw = sw;
	else if (port->remote)
		down_sw = port->remote->sw;
	else
		down_sw = NULL;

	if (down_sw) {
		/*
		/*
	 * CL states may interfere with lane margining so inform the user know
		 * CL states may interfere with lane margining so
	 * and bail out.
		 * disable them temporarily now.
		 */
		 */
	if (tb_port_clx_is_enabled(port, TB_CL1 | TB_CL2)) {
		ret = tb_switch_clx_disable(down_sw);
		tb_port_warn(port,
		if (ret < 0) {
			     "CL states are enabled, Disable them with clx=0 and re-connect\n");
			tb_sw_warn(down_sw, "failed to disable CL states\n");
		ret = -EINVAL;
			goto out_unlock;
			goto out_unlock;
		}
		}
		clx = ret;
	}


	margining = usb4->margining;
	margining = usb4->margining;


@@ -586,7 +596,7 @@ static int margining_run_write(void *data, u64 val)
					  margining->right_high,
					  margining->right_high,
					  USB4_MARGIN_SW_COUNTER_CLEAR);
					  USB4_MARGIN_SW_COUNTER_CLEAR);
		if (ret)
		if (ret)
			goto out_unlock;
			goto out_clx;


		ret = usb4_port_sw_margin_errors(port, &margining->results[0]);
		ret = usb4_port_sw_margin_errors(port, &margining->results[0]);
	} else {
	} else {
@@ -600,6 +610,9 @@ static int margining_run_write(void *data, u64 val)
					  margining->right_high, margining->results);
					  margining->right_high, margining->results);
	}
	}


out_clx:
	if (down_sw)
		tb_switch_clx_enable(down_sw, clx);
out_unlock:
out_unlock:
	mutex_unlock(&tb->lock);
	mutex_unlock(&tb->lock);
out_rpm_put:
out_rpm_put: