Commit 11d3f726 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents 41226a36 c9ca8de2
Loading
Loading
Loading
Loading
+20 −20
Original line number Diff line number Diff line
@@ -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

@@ -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;
@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

@@ -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;

+7 −0
Original line number Diff line number Diff line
@@ -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");
+1 −1
Original line number Diff line number Diff line
@@ -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;
+41 −17
Original line number Diff line number Diff line
@@ -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);
@@ -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:
@@ -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);
@@ -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)
@@ -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;
		}
@@ -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:
@@ -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));
+3 −0
Original line number Diff line number Diff line
@@ -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",
Loading