thunderbolt: Changes for v6.10 merge window

This includes following USB4/Thunderbolt changes for the v6.10 merge
 window:
 
   - Enable NVM firmare upgrade on Intel Maple Ridge Thunderbolt 4
     controller
   - Improve USB3 tunnel bandwidth calculation
   - Improve sideband access
   - Minor cleanups and fixes.
 
 All these have been in linux-next with no reported issues.
 -----BEGIN PGP SIGNATURE-----
 
 iQJUBAABCgA+FiEEVTdhRGBbNzLrSUBaAP2fSd+ZWKAFAmY9p68gHG1pa2Eud2Vz
 dGVyYmVyZ0BsaW51eC5pbnRlbC5jb20ACgkQAP2fSd+ZWKAncQ/7BHfSiGFgAxo0
 COALJ0sChaYBT7qOfnf6QVJv6jPV1pfRx21FrTwjbwQXGZVT+Q2QmMK66TvHviO2
 5pCeJdpdphMpUR5ZQE1USY4Ig3DW3TBmDEx2HxtdOzl7ot60eVQNpcnrrp+wWJNO
 ha1tWnDt2mTVsZoASDReztdZCZbZXS0zW3ODdfXMqaeRxI+/IwvmfmRo5YvL6qBG
 ChdMHTMKEgPSvZY918fMVoJi46ugOiTJgXfk4X7fmGeRIMUPpcU5k6hk9TDxK9bV
 L2Xi930AhSACzTNto+mLEyfdNeErkot2V4Yhx5OVaKPpLdjOjN6p1Lrh5GkcgP+F
 mGG1as793JZX7VyBDrIhWp2wglELqQcZKTlmQJkuXPXyDCfLWeJTaqKDx9z1de4s
 w0ltpS5cgDyeCRNLTTmY5ARq+CyUVMb/tE687ZkqWrrxYRaMfsHCZe0pupZgPVKA
 OzH9ItC1xlDf7ErpiZI6whOeTunJ9pBRvhQmx2m5MYq+Gcs/kC/EH0NMO6nTjLz5
 7bbTiih7WMgJUFR953dUbC/LqAo0Xg5V2dSlSU+rAJWQ4ocOVRasCK3jxp9StMzf
 bdaJZbD7mDR5BT/xVhMYDYZnZiG2huwPag6L1OXyRSVPl1RLJpznIu3TvcqcunLN
 MQPZKiW3S3tGPYlRmAhxmi+M2nwdbP4=
 =fiCC
 -----END PGP SIGNATURE-----

Merge tag 'thunderbolt-for-v6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-next

Mika writes:

thunderbolt: Changes for v6.10 merge window

This includes following USB4/Thunderbolt changes for the v6.10 merge
window:

  - Enable NVM firmare upgrade on Intel Maple Ridge Thunderbolt 4
    controller
  - Improve USB3 tunnel bandwidth calculation
  - Improve sideband access
  - Minor cleanups and fixes.

All these have been in linux-next with no reported issues.

* tag 'thunderbolt-for-v6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt:
  thunderbolt: Correct trace output of firmware connection manager packets
  thunderbolt: Fix kernel-doc for tb_tunnel_alloc_dp()
  thunderbolt: Fix uninitialized variable in tb_tunnel_alloc_usb3()
  thunderbolt: There are only 5 basic router registers in pre-USB4 routers
  thunderbolt: No need to loop over all retimers if access fails
  thunderbolt: Increase sideband access polling delay
  thunderbolt: Get rid of TB_CFG_PKG_PREPARE_TO_SLEEP
  thunderbolt: Use correct error code with ERROR_NOT_SUPPORTED
  thunderbolt: Allow USB3 bandwidth to be lower than maximum supported
  thunderbolt: Fix calculation of consumed USB3 bandwidth on a path
  thunderbolt: Enable NVM upgrade support on Intel Maple Ridge
This commit is contained in:
Greg Kroah-Hartman 2024-05-10 10:25:22 +01:00
commit e4306116b5
10 changed files with 59 additions and 48 deletions

View file

@ -1346,7 +1346,7 @@ static int switch_basic_regs_show(struct tb_switch *sw, struct seq_file *s)
if (tb_switch_is_usb4(sw))
dwords = ARRAY_SIZE(data);
else
dwords = 7;
dwords = 5;
ret = tb_sw_read(sw, data, TB_CFG_SWITCH, 0, dwords);
if (ret)

View file

@ -2532,6 +2532,7 @@ struct tb *icm_probe(struct tb_nhi *nhi)
case PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_2C_NHI:
case PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_4C_NHI:
icm->can_upgrade_nvm = true;
icm->is_supported = icm_tgl_is_supported;
icm->get_mode = icm_ar_get_mode;
icm->driver_ready = icm_tr_driver_ready;

View file

@ -199,8 +199,10 @@ static void tb_retimer_nvm_authenticate_status(struct tb_port *port, u32 *status
* If the retimer has it set, store it for the new retimer
* device instance.
*/
for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
usb4_port_retimer_nvm_authenticate_status(port, i, &status[i]);
for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) {
if (usb4_port_retimer_nvm_authenticate_status(port, i, &status[i]))
break;
}
}
static void tb_retimer_set_inbound_sbtx(struct tb_port *port)
@ -234,8 +236,10 @@ static void tb_retimer_unset_inbound_sbtx(struct tb_port *port)
tb_port_dbg(port, "disabling sideband transactions\n");
for (i = TB_MAX_RETIMER_INDEX; i >= 1; i--)
usb4_port_retimer_unset_inbound_sbtx(port, i);
for (i = TB_MAX_RETIMER_INDEX; i >= 1; i--) {
if (usb4_port_retimer_unset_inbound_sbtx(port, i))
break;
}
}
static ssize_t nvm_authenticate_store(struct device *dev,

View file

@ -498,8 +498,9 @@ static struct tb_tunnel *tb_find_first_usb3_tunnel(struct tb *tb,
* @consumed_down: Consumed downstream bandwidth (Mb/s)
*
* Calculates consumed USB3 and PCIe bandwidth at @port between path
* from @src_port to @dst_port. Does not take tunnel starting from
* @src_port and ending from @src_port into account.
* from @src_port to @dst_port. Does not take USB3 tunnel starting from
* @src_port and ending on @src_port into account because that bandwidth is
* already included in as part of the "first hop" USB3 tunnel.
*/
static int tb_consumed_usb3_pcie_bandwidth(struct tb *tb,
struct tb_port *src_port,
@ -514,8 +515,8 @@ static int tb_consumed_usb3_pcie_bandwidth(struct tb *tb,
*consumed_up = *consumed_down = 0;
tunnel = tb_find_first_usb3_tunnel(tb, src_port, dst_port);
if (tunnel && tunnel->src_port != src_port &&
tunnel->dst_port != dst_port) {
if (tunnel && !tb_port_is_usb3_down(src_port) &&
!tb_port_is_usb3_up(dst_port)) {
int ret;
ret = tb_tunnel_consumed_bandwidth(tunnel, consumed_up,

View file

@ -98,12 +98,6 @@ struct cfg_reset_pkg {
struct tb_cfg_header header;
} __packed;
/* TB_CFG_PKG_PREPARE_TO_SLEEP */
struct cfg_pts_pkg {
struct tb_cfg_header header;
u32 data;
} __packed;
/* ICM messages */
enum icm_pkg_code {

View file

@ -87,23 +87,32 @@ static inline const char *show_data(struct trace_seq *p, u8 type,
const char *prefix = "";
int i;
show_route(p, data);
switch (type) {
case TB_CFG_PKG_READ:
case TB_CFG_PKG_WRITE:
show_route(p, data);
show_data_read_write(p, data);
break;
case TB_CFG_PKG_ERROR:
show_route(p, data);
show_data_error(p, data);
break;
case TB_CFG_PKG_EVENT:
show_route(p, data);
show_data_event(p, data);
break;
case TB_CFG_PKG_ICM_EVENT:
case TB_CFG_PKG_ICM_CMD:
case TB_CFG_PKG_ICM_RESP:
/* ICM messages always target the host router */
trace_seq_puts(p, "route=0, ");
break;
default:
show_route(p, data);
break;
}

View file

@ -1435,10 +1435,10 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in,
* @in: DP in adapter port
* @out: DP out adapter port
* @link_nr: Preferred lane adapter when the link is not bonded
* @max_up: Maximum available upstream bandwidth for the DP tunnel (%0
* if not limited)
* @max_down: Maximum available downstream bandwidth for the DP tunnel
* (%0 if not limited)
* @max_up: Maximum available upstream bandwidth for the DP tunnel.
* %0 if no available bandwidth.
* @max_down: Maximum available downstream bandwidth for the DP tunnel.
* %0 if no available bandwidth.
*
* Allocates a tunnel between @in and @out that is capable of tunneling
* Display Port traffic.
@ -2048,10 +2048,10 @@ struct tb_tunnel *tb_tunnel_discover_usb3(struct tb *tb, struct tb_port *down,
* @tb: Pointer to the domain structure
* @up: USB3 upstream adapter port
* @down: USB3 downstream adapter port
* @max_up: Maximum available upstream bandwidth for the USB3 tunnel (%0
* if not limited).
* @max_down: Maximum available downstream bandwidth for the USB3 tunnel
* (%0 if not limited).
* @max_up: Maximum available upstream bandwidth for the USB3 tunnel.
* %0 if no available bandwidth.
* @max_down: Maximum available downstream bandwidth for the USB3 tunnel.
* %0 if no available bandwidth.
*
* Allocate an USB3 tunnel. The ports must be of type @TB_TYPE_USB3_UP and
* @TB_TYPE_USB3_DOWN.
@ -2066,24 +2066,19 @@ struct tb_tunnel *tb_tunnel_alloc_usb3(struct tb *tb, struct tb_port *up,
struct tb_path *path;
int max_rate = 0;
/*
* Check that we have enough bandwidth available for the new
* USB3 tunnel.
*/
if (max_up > 0 || max_down > 0) {
if (!tb_route(down->sw) && (max_up > 0 || max_down > 0)) {
/*
* For USB3 isochronous transfers, we allow bandwidth which is
* not higher than 90% of maximum supported bandwidth by USB3
* adapters.
*/
max_rate = tb_usb3_max_link_rate(down, up);
if (max_rate < 0)
return NULL;
/* Only 90% can be allocated for USB3 isochronous transfers */
max_rate = max_rate * 90 / 100;
tb_port_dbg(up, "required bandwidth for USB3 tunnel %d Mb/s\n",
tb_port_dbg(up, "maximum required bandwidth for USB3 tunnel %d Mb/s\n",
max_rate);
if (max_rate > max_up || max_rate > max_down) {
tb_port_warn(up, "not enough bandwidth for USB3 tunnel\n");
return NULL;
}
}
tunnel = tb_tunnel_alloc(tb, 2, TB_TUNNEL_USB3);
@ -2115,8 +2110,8 @@ struct tb_tunnel *tb_tunnel_alloc_usb3(struct tb *tb, struct tb_port *up,
tunnel->paths[TB_USB3_PATH_UP] = path;
if (!tb_route(down->sw)) {
tunnel->allocated_up = max_rate;
tunnel->allocated_down = max_rate;
tunnel->allocated_up = min(max_rate, max_up);
tunnel->allocated_down = min(max_rate, max_down);
tunnel->init = tb_usb3_init;
tunnel->consumed_bandwidth = tb_usb3_consumed_bandwidth;

View file

@ -52,6 +52,10 @@ enum usb4_ba_index {
#define USB4_BA_VALUE_MASK GENMASK(31, 16)
#define USB4_BA_VALUE_SHIFT 16
/* Delays in us used with usb4_port_wait_for_bit() */
#define USB4_PORT_DELAY 50
#define USB4_PORT_SB_DELAY 5000
static int usb4_native_switch_op(struct tb_switch *sw, u16 opcode,
u32 *metadata, u8 *status,
const void *tx_data, size_t tx_dwords,
@ -1245,7 +1249,7 @@ void usb4_port_unconfigure_xdomain(struct tb_port *port)
}
static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit,
u32 value, int timeout_msec)
u32 value, int timeout_msec, unsigned long delay_usec)
{
ktime_t timeout = ktime_add_ms(ktime_get(), timeout_msec);
@ -1260,7 +1264,7 @@ static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit,
if ((val & bit) == value)
return 0;
usleep_range(50, 100);
fsleep(delay_usec);
} while (ktime_before(ktime_get(), timeout));
return -ETIMEDOUT;
@ -1308,7 +1312,7 @@ static int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target,
return ret;
ret = usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_1,
PORT_CS_1_PND, 0, 500);
PORT_CS_1_PND, 0, 500, USB4_PORT_SB_DELAY);
if (ret)
return ret;
@ -1355,7 +1359,7 @@ static int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target,
return ret;
ret = usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_1,
PORT_CS_1_PND, 0, 500);
PORT_CS_1_PND, 0, 500, USB4_PORT_SB_DELAY);
if (ret)
return ret;
@ -1410,6 +1414,8 @@ static int usb4_port_sb_op(struct tb_port *port, enum usb4_sb_target target,
if (val != opcode)
return usb4_port_sb_opcode_err_to_errno(val);
fsleep(USB4_PORT_SB_DELAY);
} while (ktime_before(ktime_get(), timeout));
return -ETIMEDOUT;
@ -1591,13 +1597,14 @@ int usb4_port_asym_start(struct tb_port *port)
* port started the symmetry transition.
*/
ret = usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_19,
PORT_CS_19_START_ASYM, 0, 1000);
PORT_CS_19_START_ASYM, 0, 1000,
USB4_PORT_DELAY);
if (ret)
return ret;
/* Then wait for the transtion to be completed */
return usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_18,
PORT_CS_18_TIP, 0, 5000);
PORT_CS_18_TIP, 0, 5000, USB4_PORT_DELAY);
}
/**
@ -2123,7 +2130,8 @@ static int usb4_usb3_port_cm_request(struct tb_port *port, bool request)
*/
val &= ADP_USB3_CS_2_CMR;
return usb4_port_wait_for_bit(port, port->cap_adap + ADP_USB3_CS_1,
ADP_USB3_CS_1_HCA, val, 1500);
ADP_USB3_CS_1_HCA, val, 1500,
USB4_PORT_DELAY);
}
static inline int usb4_usb3_port_set_cm_request(struct tb_port *port)

View file

@ -250,7 +250,7 @@ static int tb_xdp_handle_error(const struct tb_xdp_error_response *res)
case ERROR_UNKNOWN_DOMAIN:
return -EIO;
case ERROR_NOT_SUPPORTED:
return -ENOTSUPP;
return -EOPNOTSUPP;
case ERROR_NOT_READY:
return -EAGAIN;
default:

View file

@ -33,7 +33,6 @@ enum tb_cfg_pkg_type {
TB_CFG_PKG_ICM_EVENT = 10,
TB_CFG_PKG_ICM_CMD = 11,
TB_CFG_PKG_ICM_RESP = 12,
TB_CFG_PKG_PREPARE_TO_SLEEP = 13,
};
/**