Skip to content

Commit

Permalink
Merge tag 'usb-6.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/gregkh/usb

Pull USB / Thunderbolt fixes from Greg KH:
 "Here are some USB and Thunderbolt driver fixes for 6.6-rc6 to resolve
  a number of small reported issues. Included in here are:

   - thunderbolt driver fixes

   - xhci driver fixes

   - cdns3 driver fixes

   - musb driver fixes

   - a number of typec driver fixes

   - a few other small driver fixes

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

* tag 'usb-6.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (22 commits)
  usb: typec: ucsi: Use GET_CAPABILITY attributes data to set power supply scope
  usb: typec: ucsi: Fix missing link removal
  usb: typec: altmodes/displayport: Signal hpd low when exiting mode
  xhci: Preserve RsvdP bits in ERSTBA register correctly
  xhci: Clear EHB bit only at end of interrupt handler
  xhci: track port suspend state correctly in unsuccessful resume cases
  usb: xhci: xhci-ring: Use sysdev for mapping bounce buffer
  usb: typec: ucsi: Clear EVENT_PENDING bit if ucsi_send_command fails
  usb: misc: onboard_hub: add support for Microchip USB2412 USB 2.0 hub
  usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
  usb: cdns3: Modify the return value of cdns_set_active () to void when CONFIG_PM_SLEEP is disabled
  usb: dwc3: Soft reset phy on probe for host
  usb: hub: Guard against accesses to uninitialized BOS descriptors
  usb: typec: qcom: Update the logic of regulator enable and disable
  usb: gadget: ncm: Handle decoding of multiple NTB's in unwrap call
  usb: musb: Get the musb_qh poniter after musb_giveback
  usb: musb: Modify the "HWVers" register address
  usb: cdnsp: Fixes issue with dequeuing not queued requests
  thunderbolt: Restart XDomain discovery handshake after failure
  thunderbolt: Correct TMU mode initialization from hardware
  ...
  • Loading branch information
torvalds committed Oct 15, 2023
2 parents 41226a3 + c9ca8de commit 11d3f72
Show file tree
Hide file tree
Showing 23 changed files with 220 additions and 87 deletions.
40 changes: 20 additions & 20 deletions drivers/thunderbolt/icm.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#define PHY_PORT_CS1_LINK_STATE_SHIFT 26

#define ICM_TIMEOUT 5000 /* ms */
#define ICM_RETRIES 3
#define ICM_APPROVE_TIMEOUT 10000 /* ms */
#define ICM_MAX_LINK 4

Expand Down Expand Up @@ -296,10 +297,9 @@ static bool icm_copy(struct tb_cfg_request *req, const struct ctl_pkg *pkg)

static int icm_request(struct tb *tb, const void *request, size_t request_size,
void *response, size_t response_size, size_t npackets,
unsigned int timeout_msec)
int retries, unsigned int timeout_msec)
{
struct icm *icm = tb_priv(tb);
int retries = 3;

do {
struct tb_cfg_request *req;
Expand Down Expand Up @@ -410,7 +410,7 @@ static int icm_fr_get_route(struct tb *tb, u8 link, u8 depth, u64 *route)
return -ENOMEM;

ret = icm_request(tb, &request, sizeof(request), switches,
sizeof(*switches), npackets, ICM_TIMEOUT);
sizeof(*switches), npackets, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
goto err_free;

Expand Down Expand Up @@ -463,7 +463,7 @@ icm_fr_driver_ready(struct tb *tb, enum tb_security_level *security_level,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand All @@ -488,7 +488,7 @@ static int icm_fr_approve_switch(struct tb *tb, struct tb_switch *sw)
memset(&reply, 0, sizeof(reply));
/* Use larger timeout as establishing tunnels can take some time */
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_APPROVE_TIMEOUT);
1, ICM_RETRIES, ICM_APPROVE_TIMEOUT);
if (ret)
return ret;

Expand All @@ -515,7 +515,7 @@ static int icm_fr_add_switch_key(struct tb *tb, struct tb_switch *sw)

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand Down Expand Up @@ -543,7 +543,7 @@ static int icm_fr_challenge_switch_key(struct tb *tb, struct tb_switch *sw,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand Down Expand Up @@ -577,7 +577,7 @@ static int icm_fr_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand Down Expand Up @@ -1020,7 +1020,7 @@ icm_tr_driver_ready(struct tb *tb, enum tb_security_level *security_level,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, 20000);
1, 10, 2000);
if (ret)
return ret;

Expand Down Expand Up @@ -1053,7 +1053,7 @@ static int icm_tr_approve_switch(struct tb *tb, struct tb_switch *sw)

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_APPROVE_TIMEOUT);
1, ICM_RETRIES, ICM_APPROVE_TIMEOUT);
if (ret)
return ret;

Expand Down Expand Up @@ -1081,7 +1081,7 @@ static int icm_tr_add_switch_key(struct tb *tb, struct tb_switch *sw)

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand Down Expand Up @@ -1110,7 +1110,7 @@ static int icm_tr_challenge_switch_key(struct tb *tb, struct tb_switch *sw,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand Down Expand Up @@ -1144,7 +1144,7 @@ static int icm_tr_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand All @@ -1170,7 +1170,7 @@ static int icm_tr_xdomain_tear_down(struct tb *tb, struct tb_xdomain *xd,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand Down Expand Up @@ -1496,7 +1496,7 @@ icm_ar_driver_ready(struct tb *tb, enum tb_security_level *security_level,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand All @@ -1522,7 +1522,7 @@ static int icm_ar_get_route(struct tb *tb, u8 link, u8 depth, u64 *route)

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand All @@ -1543,7 +1543,7 @@ static int icm_ar_get_boot_acl(struct tb *tb, uuid_t *uuids, size_t nuuids)

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand Down Expand Up @@ -1604,7 +1604,7 @@ static int icm_ar_set_boot_acl(struct tb *tb, const uuid_t *uuids,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand All @@ -1626,7 +1626,7 @@ icm_icl_driver_ready(struct tb *tb, enum tb_security_level *security_level,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, 20000);
1, ICM_RETRIES, 20000);
if (ret)
return ret;

Expand Down Expand Up @@ -2298,7 +2298,7 @@ static int icm_usb4_switch_op(struct tb_switch *sw, u16 opcode, u32 *metadata,

memset(&reply, 0, sizeof(reply));
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1, ICM_TIMEOUT);
1, ICM_RETRIES, ICM_TIMEOUT);
if (ret)
return ret;

Expand Down
7 changes: 7 additions & 0 deletions drivers/thunderbolt/switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -2725,6 +2725,13 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw)
!tb_port_is_width_supported(down, TB_LINK_WIDTH_DUAL))
return 0;

/*
* Both lanes need to be in CL0. Here we assume lane 0 already be in
* CL0 and check just for lane 1.
*/
if (tb_wait_for_port(down->dual_link_port, false) <= 0)
return -ENOTCONN;

ret = tb_port_lane_bonding_enable(up);
if (ret) {
tb_port_warn(up, "failed to enable lane bonding\n");
Expand Down
2 changes: 1 addition & 1 deletion drivers/thunderbolt/tmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ static int tmu_mode_init(struct tb_switch *sw)
} else if (ucap && tb_port_tmu_is_unidirectional(up)) {
if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate)
sw->tmu.mode = TB_SWITCH_TMU_MODE_LOWRES;
else if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate)
else if (tmu_rates[TB_SWITCH_TMU_MODE_HIFI_UNI] == rate)
sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_UNI;
} else if (rate) {
sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_BI;
Expand Down
58 changes: 41 additions & 17 deletions drivers/thunderbolt/xdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,27 @@ static void update_property_block(struct tb_xdomain *xd)
mutex_unlock(&xdomain_lock);
}

static void start_handshake(struct tb_xdomain *xd)
{
xd->state = XDOMAIN_STATE_INIT;
queue_delayed_work(xd->tb->wq, &xd->state_work,
msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
}

/* Can be called from state_work */
static void __stop_handshake(struct tb_xdomain *xd)
{
cancel_delayed_work_sync(&xd->properties_changed_work);
xd->properties_changed_retries = 0;
xd->state_retries = 0;
}

static void stop_handshake(struct tb_xdomain *xd)
{
cancel_delayed_work_sync(&xd->state_work);
__stop_handshake(xd);
}

static void tb_xdp_handle_request(struct work_struct *work)
{
struct xdomain_request_work *xw = container_of(work, typeof(*xw), work);
Expand Down Expand Up @@ -765,6 +786,15 @@ static void tb_xdp_handle_request(struct work_struct *work)
case UUID_REQUEST:
tb_dbg(tb, "%llx: received XDomain UUID request\n", route);
ret = tb_xdp_uuid_response(ctl, route, sequence, uuid);
/*
* If we've stopped the discovery with an error such as
* timing out, we will restart the handshake now that we
* received UUID request from the remote host.
*/
if (!ret && xd && xd->state == XDOMAIN_STATE_ERROR) {
dev_dbg(&xd->dev, "restarting handshake\n");
start_handshake(xd);
}
break;

case LINK_STATE_STATUS_REQUEST:
Expand Down Expand Up @@ -1521,6 +1551,13 @@ static void tb_xdomain_queue_properties_changed(struct tb_xdomain *xd)
msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
}

static void tb_xdomain_failed(struct tb_xdomain *xd)
{
xd->state = XDOMAIN_STATE_ERROR;
queue_delayed_work(xd->tb->wq, &xd->state_work,
msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
}

static void tb_xdomain_state_work(struct work_struct *work)
{
struct tb_xdomain *xd = container_of(work, typeof(*xd), state_work.work);
Expand All @@ -1547,7 +1584,7 @@ static void tb_xdomain_state_work(struct work_struct *work)
if (ret) {
if (ret == -EAGAIN)
goto retry_state;
xd->state = XDOMAIN_STATE_ERROR;
tb_xdomain_failed(xd);
} else {
tb_xdomain_queue_properties_changed(xd);
if (xd->bonding_possible)
Expand Down Expand Up @@ -1612,7 +1649,7 @@ static void tb_xdomain_state_work(struct work_struct *work)
if (ret) {
if (ret == -EAGAIN)
goto retry_state;
xd->state = XDOMAIN_STATE_ERROR;
tb_xdomain_failed(xd);
} else {
xd->state = XDOMAIN_STATE_ENUMERATED;
}
Expand All @@ -1623,6 +1660,8 @@ static void tb_xdomain_state_work(struct work_struct *work)
break;

case XDOMAIN_STATE_ERROR:
dev_dbg(&xd->dev, "discovery failed, stopping handshake\n");
__stop_handshake(xd);
break;

default:
Expand Down Expand Up @@ -1833,21 +1872,6 @@ static void tb_xdomain_release(struct device *dev)
kfree(xd);
}

static void start_handshake(struct tb_xdomain *xd)
{
xd->state = XDOMAIN_STATE_INIT;
queue_delayed_work(xd->tb->wq, &xd->state_work,
msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
}

static void stop_handshake(struct tb_xdomain *xd)
{
cancel_delayed_work_sync(&xd->properties_changed_work);
cancel_delayed_work_sync(&xd->state_work);
xd->properties_changed_retries = 0;
xd->state_retries = 0;
}

static int __maybe_unused tb_xdomain_suspend(struct device *dev)
{
stop_handshake(tb_to_xdomain(dev));
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/cdns3/cdnsp-gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,9 @@ static int cdnsp_gadget_ep_dequeue(struct usb_ep *ep,
unsigned long flags;
int ret;

if (request->status != -EINPROGRESS)
return 0;

if (!pep->endpoint.desc) {
dev_err(pdev->dev,
"%s: can't dequeue to disabled endpoint\n",
Expand Down
3 changes: 1 addition & 2 deletions drivers/usb/cdns3/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,7 @@ void cdns_set_active(struct cdns *cdns, u8 set_active);
#else /* CONFIG_PM_SLEEP */
static inline int cdns_resume(struct cdns *cdns)
{ return 0; }
static inline int cdns_set_active(struct cdns *cdns, u8 set_active)
{ return 0; }
static inline void cdns_set_active(struct cdns *cdns, u8 set_active) { }
static inline int cdns_suspend(struct cdns *cdns)
{ return 0; }
#endif /* CONFIG_PM_SLEEP */
Expand Down
25 changes: 22 additions & 3 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ int usb_device_supports_lpm(struct usb_device *udev)
if (udev->quirks & USB_QUIRK_NO_LPM)
return 0;

/* Skip if the device BOS descriptor couldn't be read */
if (!udev->bos)
return 0;

/* USB 2.1 (and greater) devices indicate LPM support through
* their USB 2.0 Extended Capabilities BOS descriptor.
*/
Expand Down Expand Up @@ -327,6 +331,10 @@ static void usb_set_lpm_parameters(struct usb_device *udev)
if (!udev->lpm_capable || udev->speed < USB_SPEED_SUPER)
return;

/* Skip if the device BOS descriptor couldn't be read */
if (!udev->bos)
return;

hub = usb_hub_to_struct_hub(udev->parent);
/* It doesn't take time to transition the roothub into U0, since it
* doesn't have an upstream link.
Expand Down Expand Up @@ -2704,13 +2712,17 @@ int usb_authorize_device(struct usb_device *usb_dev)
static enum usb_ssp_rate get_port_ssp_rate(struct usb_device *hdev,
u32 ext_portstatus)
{
struct usb_ssp_cap_descriptor *ssp_cap = hdev->bos->ssp_cap;
struct usb_ssp_cap_descriptor *ssp_cap;
u32 attr;
u8 speed_id;
u8 ssac;
u8 lanes;
int i;

if (!hdev->bos)
goto out;

ssp_cap = hdev->bos->ssp_cap;
if (!ssp_cap)
goto out;

Expand Down Expand Up @@ -4215,8 +4227,15 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
enum usb3_link_state state)
{
int timeout;
__u8 u1_mel = udev->bos->ss_cap->bU1devExitLat;
__le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat;
__u8 u1_mel;
__le16 u2_mel;

/* Skip if the device BOS descriptor couldn't be read */
if (!udev->bos)
return;

u1_mel = udev->bos->ss_cap->bU1devExitLat;
u2_mel = udev->bos->ss_cap->bU2DevExitLat;

/* If the device says it doesn't have *any* exit latency to come out of
* U1 or U2, it's probably lying. Assume it doesn't implement that link
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/core/hub.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ static inline int hub_is_superspeedplus(struct usb_device *hdev)
{
return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS &&
le16_to_cpu(hdev->descriptor.bcdUSB) >= 0x0310 &&
hdev->bos->ssp_cap);
hdev->bos && hdev->bos->ssp_cap);
}

static inline unsigned hub_power_on_good_delay(struct usb_hub *hub)
Expand Down
Loading

0 comments on commit 11d3f72

Please sign in to comment.