mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
thunderbolt: Verify PCIe adapter in detect state before tunnel setup
The USB4 Connection Manager guide suggests that a PCIe downstream and PCIe upstream adapters of the USB4 router is in the Detect state before setting up a PCIe tunnel. Add this check by verifying the LTSSM field in ADP_PCIE_CS_0 before tunnel setup. Signed-off-by: Gil Fine <gil.fine@linux.intel.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
This commit is contained in:
parent
b69af182b5
commit
69a7b98770
|
|
@ -1481,6 +1481,7 @@ int usb4_dp_port_allocate_bandwidth(struct tb_port *port, int bw);
|
|||
int usb4_dp_port_requested_bandwidth(struct tb_port *port);
|
||||
|
||||
int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable);
|
||||
int usb4_pci_port_ltssm_state(struct tb_port *port);
|
||||
|
||||
static inline bool tb_is_usb4_port_device(const struct device *dev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -473,10 +473,25 @@ struct tb_regs_port_header {
|
|||
|
||||
/* PCIe adapter registers */
|
||||
#define ADP_PCIE_CS_0 0x00
|
||||
#define ADP_PCIE_CS_0_LTSSM_MASK GENMASK(28, 25)
|
||||
#define ADP_PCIE_CS_0_PE BIT(31)
|
||||
#define ADP_PCIE_CS_1 0x01
|
||||
#define ADP_PCIE_CS_1_EE BIT(0)
|
||||
|
||||
enum tb_pcie_ltssm_state {
|
||||
USB4_PCIE_LTSSM_DETECT,
|
||||
USB4_PCIE_LTSSM_POLLING,
|
||||
USB4_PCIE_LTSSM_CONFIG,
|
||||
USB4_PCIE_LTSSM_CONFIG_IDLE,
|
||||
USB4_PCIE_LTSSM_RECOVERY,
|
||||
USB4_PCIE_LTSSM_RECOVERY_IDLE,
|
||||
USB4_PCIE_LTSSM_L0,
|
||||
USB4_PCIE_LTSSM_L1,
|
||||
USB4_PCIE_LTSSM_L2,
|
||||
USB4_PCIE_LTSSM_DISABLED,
|
||||
USB4_PCIE_LTSSM_HOT_RESET,
|
||||
};
|
||||
|
||||
/* USB adapter registers */
|
||||
#define ADP_USB3_CS_0 0x00
|
||||
#define ADP_USB3_CS_0_V BIT(30)
|
||||
|
|
|
|||
|
|
@ -290,6 +290,40 @@ static inline void tb_tunnel_changed(struct tb_tunnel *tunnel)
|
|||
tunnel->src_port, tunnel->dst_port);
|
||||
}
|
||||
|
||||
static int tb_pci_port_ltssm_state_detect(struct tb_port *port)
|
||||
{
|
||||
ktime_t timeout = ktime_add_ms(ktime_get(), 500);
|
||||
|
||||
do {
|
||||
int ret;
|
||||
|
||||
ret = usb4_pci_port_ltssm_state(port);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == USB4_PCIE_LTSSM_DETECT)
|
||||
return 0;
|
||||
|
||||
fsleep(50);
|
||||
} while (ktime_before(ktime_get(), timeout));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int tb_pci_pre_activate(struct tb_tunnel *tunnel)
|
||||
{
|
||||
struct tb_port *down = tunnel->src_port;
|
||||
struct tb_port *up = tunnel->dst_port;
|
||||
int ret;
|
||||
|
||||
ret = tb_switch_is_usb4(down->sw) ?
|
||||
tb_pci_port_ltssm_state_detect(down) : 0;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return tb_switch_is_usb4(up->sw) ?
|
||||
tb_pci_port_ltssm_state_detect(up) : 0;
|
||||
}
|
||||
|
||||
static int tb_pci_set_ext_encapsulation(struct tb_tunnel *tunnel, bool enable)
|
||||
{
|
||||
struct tb_port *port = tb_upstream_port(tunnel->dst_port->sw);
|
||||
|
|
@ -505,6 +539,7 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,
|
|||
if (!tunnel)
|
||||
return NULL;
|
||||
|
||||
tunnel->pre_activate = tb_pci_pre_activate;
|
||||
tunnel->activate = tb_pci_activate;
|
||||
tunnel->src_port = down;
|
||||
tunnel->dst_port = up;
|
||||
|
|
|
|||
|
|
@ -3145,3 +3145,27 @@ int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable)
|
|||
return tb_port_write(port, &val, TB_CFG_PORT,
|
||||
port->cap_adap + ADP_PCIE_CS_1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb4_pci_port_ltssm_state() - Read PCIe adapter LTSSM state
|
||||
* @port: PCIe adapter
|
||||
*
|
||||
* Return:
|
||||
* * LTSSM state of @port.
|
||||
* * Negative errno - On failure.
|
||||
*/
|
||||
int usb4_pci_port_ltssm_state(struct tb_port *port)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (!tb_port_is_pcie_down(port) && !tb_port_is_pcie_up(port))
|
||||
return -EINVAL;
|
||||
|
||||
ret = tb_port_read(port, &val, TB_CFG_PORT,
|
||||
port->cap_adap + ADP_PCIE_CS_0, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return FIELD_GET(ADP_PCIE_CS_0_LTSSM_MASK, val);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user