Commit 8e1de704 authored by Mika Westerberg's avatar Mika Westerberg

thunderbolt: Add support for XDomain lane bonding

The USB4 Inter-Domain Service specification defines a protocol that can
be used to establish lane bonding between two USB4 domains (hosts). So
far we have not implemented it because the host controller DMA was not
fast enough to be able to go over 20 Gbits/s even if lanes were bonded.
However, starting from Intel Alder Lake CPUs the DMA can go over
20 Gbits/s so now it makes more sense to add this support to the driver.

Because both ends need to negotiate the bonding we add a simple state
machine that tracks the connection state and does the necessary steps
described by the USB4 Inter-Domain Service specification. We only
establish lane bonding when both sides of the link support it. Otherwise
we default to use the single lane. Also this is only done when software
connection manager is used. On systems with firmware based connection
manager, it handles the high-speed tunneling so bonding lanes is
specific to the implementation (Intel firmware based connection manager
does not support lane bonding).
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent 0a2e1667
......@@ -169,12 +169,6 @@ static void tb_discover_tunnels(struct tb *tb)
static int tb_port_configure_xdomain(struct tb_port *port)
{
/*
* XDomain paths currently only support single lane so we must
* disable the other lane according to USB4 spec.
*/
tb_port_disable(port->dual_link_port);
if (tb_switch_is_usb4(port->sw))
return usb4_port_configure_xdomain(port);
return tb_lc_configure_xdomain(port);
......
......@@ -527,6 +527,10 @@ enum tb_xdp_type {
PROPERTIES_CHANGED_RESPONSE,
ERROR_RESPONSE,
UUID_REQUEST = 12,
LINK_STATE_STATUS_REQUEST = 15,
LINK_STATE_STATUS_RESPONSE,
LINK_STATE_CHANGE_REQUEST,
LINK_STATE_CHANGE_RESPONSE,
};
struct tb_xdp_header {
......@@ -540,6 +544,41 @@ struct tb_xdp_error_response {
u32 error;
};
struct tb_xdp_link_state_status {
struct tb_xdp_header hdr;
};
struct tb_xdp_link_state_status_response {
union {
struct tb_xdp_error_response err;
struct {
struct tb_xdp_header hdr;
u32 status;
u8 slw;
u8 tlw;
u8 sls;
u8 tls;
};
};
};
struct tb_xdp_link_state_change {
struct tb_xdp_header hdr;
u8 tlw;
u8 tls;
u16 reserved;
};
struct tb_xdp_link_state_change_response {
union {
struct tb_xdp_error_response err;
struct {
struct tb_xdp_header hdr;
u32 status;
};
};
};
struct tb_xdp_uuid {
struct tb_xdp_header hdr;
};
......
......@@ -311,11 +311,16 @@ struct tb_regs_port_header {
/* Lane adapter registers */
#define LANE_ADP_CS_0 0x00
#define LANE_ADP_CS_0_SUPPORTED_SPEED_MASK GENMASK(19, 16)
#define LANE_ADP_CS_0_SUPPORTED_SPEED_SHIFT 16
#define LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK GENMASK(25, 20)
#define LANE_ADP_CS_0_SUPPORTED_WIDTH_SHIFT 20
#define LANE_ADP_CS_0_SUPPORTED_WIDTH_DUAL 0x2
#define LANE_ADP_CS_0_CL0S_SUPPORT BIT(26)
#define LANE_ADP_CS_0_CL1_SUPPORT BIT(27)
#define LANE_ADP_CS_1 0x01
#define LANE_ADP_CS_1_TARGET_SPEED_MASK GENMASK(3, 0)
#define LANE_ADP_CS_1_TARGET_SPEED_GEN3 0xc
#define LANE_ADP_CS_1_TARGET_WIDTH_MASK GENMASK(9, 4)
#define LANE_ADP_CS_1_TARGET_WIDTH_SHIFT 4
#define LANE_ADP_CS_1_TARGET_WIDTH_SINGLE 0x1
......
This diff is collapsed.
......@@ -198,15 +198,15 @@ void tb_unregister_property_dir(const char *key, struct tb_property_dir *dir);
* @local_property_block_len: Length of the @local_property_block in dwords
* @remote_properties: Properties exported by the remote domain
* @remote_property_block_gen: Generation of @remote_properties
* @get_uuid_work: Work used to retrieve @remote_uuid
* @uuid_retries: Number of times left @remote_uuid is requested before
* giving up
* @get_properties_work: Work used to get remote domain properties
* @properties_retries: Number of times left to read properties
* @state: Next XDomain discovery state to run
* @state_work: Work used to run the next state
* @state_retries: Number of retries remain for the state
* @properties_changed_work: Work used to notify the remote domain that
* our properties have changed
* @properties_changed_retries: Number of times left to send properties
* changed notification
* @bonding_possible: True if lane bonding is possible on local side
* @target_link_width: Target link width from the remote host
* @link: Root switch link the remote domain is connected (ICM only)
* @depth: Depth in the chain the remote domain is connected (ICM only)
*
......@@ -244,12 +244,13 @@ struct tb_xdomain {
u32 local_property_block_len;
struct tb_property_dir *remote_properties;
u32 remote_property_block_gen;
struct delayed_work get_uuid_work;
int uuid_retries;
struct delayed_work get_properties_work;
int properties_retries;
int state;
struct delayed_work state_work;
int state_retries;
struct delayed_work properties_changed_work;
int properties_changed_retries;
bool bonding_possible;
u8 target_link_width;
u8 link;
u8 depth;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment