thunderbolt: Split setting link width and lane bonding into own functions
When bonding lanes over XDomain the host that has "higher" UUID triggers link re-train for bonding, and the host that has "lower" UUID just waits for this to happen. To support this split setting the link width and triggering the actual bonding a separate functions that can be called as needed. While there remove duplicated empty line in the kernel-doc comment of tb_port_lane_bonding_disable(). Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
This commit is contained in:
parent
94581b25d8
commit
0e14dd5e14
@ -999,7 +999,17 @@ static bool tb_port_is_width_supported(struct tb_port *port, int width)
|
||||
return !!(widths & width);
|
||||
}
|
||||
|
||||
static int tb_port_set_link_width(struct tb_port *port, unsigned int width)
|
||||
/**
|
||||
* tb_port_set_link_width() - Set target link width of the lane adapter
|
||||
* @port: Lane adapter
|
||||
* @width: Target link width (%1 or %2)
|
||||
*
|
||||
* Sets the target link width of the lane adapter to @width. Does not
|
||||
* enable/disable lane bonding. For that call tb_port_set_lane_bonding().
|
||||
*
|
||||
* Return: %0 in case of success and negative errno in case of error
|
||||
*/
|
||||
int tb_port_set_link_width(struct tb_port *port, unsigned int width)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
@ -1026,12 +1036,58 @@ static int tb_port_set_link_width(struct tb_port *port, unsigned int width)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val |= LANE_ADP_CS_1_LB;
|
||||
|
||||
return tb_port_write(port, &val, TB_CFG_PORT,
|
||||
port->cap_phy + LANE_ADP_CS_1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* tb_port_set_lane_bonding() - Enable/disable lane bonding
|
||||
* @port: Lane adapter
|
||||
* @bonding: enable/disable bonding
|
||||
*
|
||||
* Enables or disables lane bonding. This should be called after target
|
||||
* link width has been set (tb_port_set_link_width()). Note in most
|
||||
* cases one should use tb_port_lane_bonding_enable() instead to enable
|
||||
* lane bonding.
|
||||
*
|
||||
* As a side effect sets @port->bonding accordingly (and does the same
|
||||
* for lane 1 too).
|
||||
*
|
||||
* Return: %0 in case of success and negative errno in case of error
|
||||
*/
|
||||
int tb_port_set_lane_bonding(struct tb_port *port, bool bonding)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (!port->cap_phy)
|
||||
return -EINVAL;
|
||||
|
||||
ret = tb_port_read(port, &val, TB_CFG_PORT,
|
||||
port->cap_phy + LANE_ADP_CS_1, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bonding)
|
||||
val |= LANE_ADP_CS_1_LB;
|
||||
else
|
||||
val &= ~LANE_ADP_CS_1_LB;
|
||||
|
||||
ret = tb_port_write(port, &val, TB_CFG_PORT,
|
||||
port->cap_phy + LANE_ADP_CS_1, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* When lane 0 bonding is set it will affect lane 1 too so
|
||||
* update both.
|
||||
*/
|
||||
port->bonded = bonding;
|
||||
port->dual_link_port->bonded = bonding;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tb_port_lane_bonding_enable() - Enable bonding on port
|
||||
* @port: port to enable
|
||||
@ -1056,22 +1112,27 @@ int tb_port_lane_bonding_enable(struct tb_port *port)
|
||||
if (ret == 1) {
|
||||
ret = tb_port_set_link_width(port, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_lane0;
|
||||
}
|
||||
|
||||
ret = tb_port_get_link_width(port->dual_link_port);
|
||||
if (ret == 1) {
|
||||
ret = tb_port_set_link_width(port->dual_link_port, 2);
|
||||
if (ret) {
|
||||
tb_port_set_link_width(port, 1);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto err_lane0;
|
||||
}
|
||||
|
||||
port->bonded = true;
|
||||
port->dual_link_port->bonded = true;
|
||||
ret = tb_port_set_lane_bonding(port, true);
|
||||
if (ret)
|
||||
goto err_lane1;
|
||||
|
||||
return 0;
|
||||
|
||||
err_lane1:
|
||||
tb_port_set_link_width(port->dual_link_port, 1);
|
||||
err_lane0:
|
||||
tb_port_set_link_width(port, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1080,13 +1141,10 @@ int tb_port_lane_bonding_enable(struct tb_port *port)
|
||||
*
|
||||
* Disable bonding by setting the link width of the port and the
|
||||
* other port in case of dual link port.
|
||||
*
|
||||
*/
|
||||
void tb_port_lane_bonding_disable(struct tb_port *port)
|
||||
{
|
||||
port->dual_link_port->bonded = false;
|
||||
port->bonded = false;
|
||||
|
||||
tb_port_set_lane_bonding(port, false);
|
||||
tb_port_set_link_width(port->dual_link_port, 1);
|
||||
tb_port_set_link_width(port, 1);
|
||||
}
|
||||
|
@ -1024,6 +1024,8 @@ static inline bool tb_port_use_credit_allocation(const struct tb_port *port)
|
||||
|
||||
int tb_port_get_link_speed(struct tb_port *port);
|
||||
int tb_port_get_link_width(struct tb_port *port);
|
||||
int tb_port_set_link_width(struct tb_port *port, unsigned int width);
|
||||
int tb_port_set_lane_bonding(struct tb_port *port, bool bonding);
|
||||
int tb_port_lane_bonding_enable(struct tb_port *port);
|
||||
void tb_port_lane_bonding_disable(struct tb_port *port);
|
||||
int tb_port_wait_for_link_width(struct tb_port *port, int width,
|
||||
|
Loading…
Reference in New Issue
Block a user