Commit 9b5ff3c9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull USB driver fixes from Greg KH:
 "Here are a number of small bugfixes for reported issues in some USB
  drivers. They include:

   - typec bugfixes

   - xhci bugfixes and lockdep warning fixes

   - cdc-acm driver regression fix

   - kernel doc fixes

   - cdns3 driver bugfixes for a bunch of reported issues

   - other tiny USB driver fixes

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

* tag 'usb-5.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: cdns3: gadget: own the lock wrongly at the suspend routine
  usb: cdns3: Fix on-chip memory overflow issue
  usb: cdns3: gadget: suspicious implicit sign extension
  xhci: Don't create stream debugfs files with spinlock held.
  usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
  xhci: Fix sizeof() mismatch
  usb: typec: stusb160x: fix signedness comparison issue with enum variables
  usb: typec: add missing MODULE_DEVICE_TABLE() to stusb160x
  USB: apple-mfi-fastcharge: don't probe unhandled devices
  usbcore: Check both id_table and match() when both available
  usb: host: ehci-tegra: Fix error handling in tegra_ehci_probe()
  usb: typec: stusb160x: fix an IS_ERR() vs NULL check in probe
  usb: typec: tcpm: reset hard_reset_count for any disconnect
  usb: cdc-acm: fix cooldown mechanism
  usb: host: fsl-mph-dr-of: check return of dma_set_mask()
  usb: fix kernel-doc markups
  usb: typec: stusb160x: fix some signedness bugs
  usb: cdns3: Variable 'length' set but not used
parents 2d38c80d 00c27a1d
Loading
Loading
Loading
Loading
+35 −30
Original line number Diff line number Diff line
@@ -137,48 +137,36 @@ static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev,
					   struct usb_ctrlrequest *ctrl_req)
{
	enum usb_device_state device_state = priv_dev->gadget.state;
	struct cdns3_endpoint *priv_ep;
	u32 config = le16_to_cpu(ctrl_req->wValue);
	int result = 0;
	int i;

	switch (device_state) {
	case USB_STATE_ADDRESS:
		/* Configure non-control EPs */
		for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) {
			priv_ep = priv_dev->eps[i];
			if (!priv_ep)
				continue;

			if (priv_ep->flags & EP_CLAIMED)
				cdns3_ep_config(priv_ep);
		}

		result = cdns3_ep0_delegate_req(priv_dev, ctrl_req);

		if (result)
			return result;

		if (!config) {
			cdns3_hw_reset_eps_config(priv_dev);
			usb_gadget_set_state(&priv_dev->gadget,
					     USB_STATE_ADDRESS);
		}
		if (result || !config)
			goto reset_config;

		break;
	case USB_STATE_CONFIGURED:
		result = cdns3_ep0_delegate_req(priv_dev, ctrl_req);
		if (!config && !result)
			goto reset_config;

		if (!config && !result) {
			cdns3_hw_reset_eps_config(priv_dev);
			usb_gadget_set_state(&priv_dev->gadget,
					     USB_STATE_ADDRESS);
		}
		break;
	default:
		result = -EINVAL;
		return -EINVAL;
	}

	return 0;

reset_config:
	if (result != USB_GADGET_DELAYED_STATUS)
		cdns3_hw_reset_eps_config(priv_dev);

	usb_gadget_set_state(&priv_dev->gadget,
			     USB_STATE_ADDRESS);

	return result;
}

@@ -705,6 +693,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
	unsigned long flags;
	int ret = 0;
	u8 zlp = 0;
	int i;

	spin_lock_irqsave(&priv_dev->lock, flags);
	trace_cdns3_ep0_queue(priv_dev, request);
@@ -720,6 +709,17 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
		u32 val;

		cdns3_select_ep(priv_dev, 0x00);

		/*
		 * Configure all non-control EPs which are not enabled by class driver
		 */
		for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) {
			priv_ep = priv_dev->eps[i];
			if (priv_ep && priv_ep->flags & EP_CLAIMED &&
			    !(priv_ep->flags & EP_ENABLED))
				cdns3_ep_config(priv_ep, 0);
		}

		cdns3_set_hw_configuration(priv_dev);
		cdns3_ep0_complete_setup(priv_dev, 0, 1);
		/* wait until configuration set */
@@ -811,6 +811,7 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev)
	struct cdns3_usb_regs __iomem *regs;
	struct cdns3_endpoint *priv_ep;
	u32 max_packet_size = 64;
	u32 ep_cfg;

	regs = priv_dev->regs;

@@ -842,8 +843,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev)
				       BIT(0) | BIT(16));
	}

	writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size),
	       &regs->ep_cfg);
	ep_cfg = EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size);

	if (!(priv_ep->flags & EP_CONFIGURED))
		writel(ep_cfg, &regs->ep_cfg);

	writel(EP_STS_EN_SETUPEN | EP_STS_EN_DESCMISEN | EP_STS_EN_TRBERREN,
	       &regs->ep_sts_en);
@@ -851,8 +854,10 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev)
	/* init ep in */
	cdns3_select_ep(priv_dev, USB_DIR_IN);

	writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size),
	       &regs->ep_cfg);
	if (!(priv_ep->flags & EP_CONFIGURED))
		writel(ep_cfg, &regs->ep_cfg);

	priv_ep->flags |= EP_CONFIGURED;

	writel(EP_STS_EN_SETUPEN | EP_STS_EN_TRBERREN, &regs->ep_sts_en);

+64 −51
Original line number Diff line number Diff line
@@ -296,6 +296,8 @@ static void cdns3_ep_stall_flush(struct cdns3_endpoint *priv_ep)
 */
void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev)
{
	int i;

	writel(USB_CONF_CFGRST, &priv_dev->regs->usb_conf);

	cdns3_allow_enable_l1(priv_dev, 0);
@@ -304,6 +306,10 @@ void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev)
	priv_dev->out_mem_is_allocated = 0;
	priv_dev->wait_for_setup = 0;
	priv_dev->using_streams = 0;

	for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++)
		if (priv_dev->eps[i])
			priv_dev->eps[i]->flags &= ~EP_CONFIGURED;
}

/**
@@ -506,7 +512,6 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep,

	while (!list_empty(&priv_ep->wa2_descmiss_req_list)) {
		int chunk_end;
		int length;

		descmiss_priv_req =
			cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list);
@@ -517,7 +522,6 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep,
			break;

		chunk_end = descmiss_priv_req->flags & REQUEST_INTERNAL_CH;
		length = request->actual + descmiss_req->actual;
		request->status = descmiss_req->status;
		__cdns3_descmiss_copy_data(request, descmiss_req);
		list_del_init(&descmiss_priv_req->list);
@@ -1746,11 +1750,8 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep)

static void cdns3_disconnect_gadget(struct cdns3_device *priv_dev)
{
	if (priv_dev->gadget_driver && priv_dev->gadget_driver->disconnect) {
		spin_unlock(&priv_dev->lock);
	if (priv_dev->gadget_driver && priv_dev->gadget_driver->disconnect)
		priv_dev->gadget_driver->disconnect(&priv_dev->gadget);
		spin_lock(&priv_dev->lock);
	}
}

/**
@@ -1761,6 +1762,7 @@ static void cdns3_disconnect_gadget(struct cdns3_device *priv_dev)
 */
static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev,
					      u32 usb_ists)
__must_hold(&priv_dev->lock)
{
	int speed = 0;

@@ -1785,7 +1787,9 @@ static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev,

	/* Disconnection detected */
	if (usb_ists & (USB_ISTS_DIS2I | USB_ISTS_DISI)) {
		spin_unlock(&priv_dev->lock);
		cdns3_disconnect_gadget(priv_dev);
		spin_lock(&priv_dev->lock);
		priv_dev->gadget.speed = USB_SPEED_UNKNOWN;
		usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED);
		cdns3_hw_reset_eps_config(priv_dev);
@@ -1979,27 +1983,6 @@ static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev,
	return 0;
}

static void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev,
				     struct cdns3_endpoint *priv_ep)
{
	if (!priv_ep->use_streams || priv_dev->gadget.speed < USB_SPEED_SUPER)
		return;

	if (priv_dev->dev_ver >= DEV_VER_V3) {
		u32 mask = BIT(priv_ep->num + (priv_ep->dir ? 16 : 0));

		/*
		 * Stream capable endpoints are handled by using ep_tdl
		 * register. Other endpoints use TDL from TRB feature.
		 */
		cdns3_clear_register_bit(&priv_dev->regs->tdl_from_trb, mask);
	}

	/*  Enable Stream Bit TDL chk and SID chk */
	cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_STREAM_EN |
			       EP_CFG_TDL_CHK | EP_CFG_SID_CHK);
}

static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
				  struct cdns3_endpoint *priv_ep)
{
@@ -2037,8 +2020,9 @@ static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
/**
 * cdns3_ep_config Configure hardware endpoint
 * @priv_ep: extended endpoint object
 * @enable: set EP_CFG_ENABLE bit in ep_cfg register.
 */
void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
{
	bool is_iso_ep = (priv_ep->type == USB_ENDPOINT_XFER_ISOC);
	struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
@@ -2099,7 +2083,7 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
		break;
	default:
		/* all other speed are not supported */
		return;
		return -EINVAL;
	}

	if (max_packet_size == 1024)
@@ -2109,11 +2093,33 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
	else
		priv_ep->trb_burst_size = 16;

	/* onchip buffer is only allocated before configuration */
	if (!priv_dev->hw_configured_flag) {
		ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1,
						     !!priv_ep->dir);
		if (ret) {
			dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n");
		return;
			return ret;
		}
	}

	if (enable)
		ep_cfg |= EP_CFG_ENABLE;

	if (priv_ep->use_streams && priv_dev->gadget.speed >= USB_SPEED_SUPER) {
		if (priv_dev->dev_ver >= DEV_VER_V3) {
			u32 mask = BIT(priv_ep->num + (priv_ep->dir ? 16 : 0));

			/*
			 * Stream capable endpoints are handled by using ep_tdl
			 * register. Other endpoints use TDL from TRB feature.
			 */
			cdns3_clear_register_bit(&priv_dev->regs->tdl_from_trb,
						 mask);
		}

		/*  Enable Stream Bit TDL chk and SID chk */
		ep_cfg |=  EP_CFG_STREAM_EN | EP_CFG_TDL_CHK | EP_CFG_SID_CHK;
	}

	ep_cfg |= EP_CFG_MAXPKTSIZE(max_packet_size) |
@@ -2123,9 +2129,12 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)

	cdns3_select_ep(priv_dev, bEndpointAddress);
	writel(ep_cfg, &priv_dev->regs->ep_cfg);
	priv_ep->flags |= EP_CONFIGURED;

	dev_dbg(priv_dev->dev, "Configure %s: with val %08x\n",
		priv_ep->name, ep_cfg);

	return 0;
}

/* Find correct direction for HW endpoint according to description */
@@ -2266,7 +2275,7 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
	u32 bEndpointAddress;
	unsigned long flags;
	int enable = 1;
	int ret;
	int ret = 0;
	int val;

	priv_ep = ep_to_cdns3_ep(ep);
@@ -2305,6 +2314,17 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
	bEndpointAddress = priv_ep->num | priv_ep->dir;
	cdns3_select_ep(priv_dev, bEndpointAddress);

	/*
	 * For some versions of controller at some point during ISO OUT traffic
	 * DMA reads Transfer Ring for the EP which has never got doorbell.
	 * This issue was detected only on simulation, but to avoid this issue
	 * driver add protection against it. To fix it driver enable ISO OUT
	 * endpoint before setting DRBL. This special treatment of ISO OUT
	 * endpoints are recommended by controller specification.
	 */
	if (priv_ep->type == USB_ENDPOINT_XFER_ISOC  && !priv_ep->dir)
		enable = 0;

	if (usb_ss_max_streams(comp_desc) && usb_endpoint_xfer_bulk(desc)) {
		/*
		 * Enable stream support (SS mode) related interrupts
@@ -2315,13 +2335,17 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
				EP_STS_EN_SIDERREN | EP_STS_EN_MD_EXITEN |
				EP_STS_EN_STREAMREN;
			priv_ep->use_streams = true;
			cdns3_stream_ep_reconfig(priv_dev, priv_ep);
			ret = cdns3_ep_config(priv_ep, enable);
			priv_dev->using_streams |= true;
		}
	} else {
		ret = cdns3_ep_config(priv_ep, enable);
	}

	ret = cdns3_allocate_trb_pool(priv_ep);
	if (ret)
		goto exit;

	ret = cdns3_allocate_trb_pool(priv_ep);
	if (ret)
		goto exit;

@@ -2351,20 +2375,6 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,

	writel(reg, &priv_dev->regs->ep_sts_en);

	/*
	 * For some versions of controller at some point during ISO OUT traffic
	 * DMA reads Transfer Ring for the EP which has never got doorbell.
	 * This issue was detected only on simulation, but to avoid this issue
	 * driver add protection against it. To fix it driver enable ISO OUT
	 * endpoint before setting DRBL. This special treatment of ISO OUT
	 * endpoints are recommended by controller specification.
	 */
	if (priv_ep->type == USB_ENDPOINT_XFER_ISOC  && !priv_ep->dir)
		enable = 0;

	if (enable)
		cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_ENABLE);

	ep->desc = desc;
	priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALLED | EP_STALL_PENDING |
			    EP_QUIRK_ISO_OUT_EN | EP_QUIRK_EXTRA_BUF_EN);
@@ -3265,10 +3275,13 @@ err0:
}

static int cdns3_gadget_suspend(struct cdns3 *cdns, bool do_wakeup)
__must_hold(&cdns->lock)
{
	struct cdns3_device *priv_dev = cdns->gadget_dev;

	spin_unlock(&cdns->lock);
	cdns3_disconnect_gadget(priv_dev);
	spin_lock(&cdns->lock);

	priv_dev->gadget.speed = USB_SPEED_UNKNOWN;
	usb_gadget_set_state(&priv_dev->gadget, USB_STATE_NOTATTACHED);
+3 −2
Original line number Diff line number Diff line
@@ -1072,7 +1072,7 @@ struct cdns3_trb {
#define TRB_TDL_SS_SIZE_GET(p)	(((p) & GENMASK(23, 17)) >> 17)

/* transfer_len bitmasks - bits 31:24 */
#define TRB_BURST_LEN(p)	(((p) << 24) & GENMASK(31, 24))
#define TRB_BURST_LEN(p)	((unsigned int)((p) << 24) & GENMASK(31, 24))
#define TRB_BURST_LEN_GET(p)	(((p) & GENMASK(31, 24)) >> 24)

/* Data buffer pointer bitmasks*/
@@ -1159,6 +1159,7 @@ struct cdns3_endpoint {
#define EP_QUIRK_EXTRA_BUF_DET	BIT(12)
#define EP_QUIRK_EXTRA_BUF_EN	BIT(13)
#define EP_TDLCHK_EN		BIT(15)
#define EP_CONFIGURED		BIT(16)
	u32			flags;

	struct cdns3_request	*descmis_req;
@@ -1360,7 +1361,7 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
int cdns3_init_ep0(struct cdns3_device *priv_dev,
		   struct cdns3_endpoint *priv_ep);
void cdns3_ep0_config(struct cdns3_device *priv_dev);
void cdns3_ep_config(struct cdns3_endpoint *priv_ep);
int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable);
void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir);
int __cdns3_gadget_wakeup(struct cdns3_device *priv_dev);

+5 −7
Original line number Diff line number Diff line
@@ -508,6 +508,7 @@ static void acm_read_bulk_callback(struct urb *urb)
			"%s - cooling babbling device\n", __func__);
		usb_mark_last_busy(acm->dev);
		set_bit(rb->index, &acm->urbs_in_error_delay);
		set_bit(ACM_ERROR_DELAY, &acm->flags);
		cooldown = true;
		break;
	default:
@@ -533,7 +534,7 @@ static void acm_read_bulk_callback(struct urb *urb)

	if (stopped || stalled || cooldown) {
		if (stalled)
			schedule_work(&acm->work);
			schedule_delayed_work(&acm->dwork, 0);
		else if (cooldown)
			schedule_delayed_work(&acm->dwork, HZ / 2);
		return;
@@ -563,13 +564,13 @@ static void acm_write_bulk(struct urb *urb)
	acm_write_done(acm, wb);
	spin_unlock_irqrestore(&acm->write_lock, flags);
	set_bit(EVENT_TTY_WAKEUP, &acm->flags);
	schedule_work(&acm->work);
	schedule_delayed_work(&acm->dwork, 0);
}

static void acm_softint(struct work_struct *work)
{
	int i;
	struct acm *acm = container_of(work, struct acm, work);
	struct acm *acm = container_of(work, struct acm, dwork.work);

	if (test_bit(EVENT_RX_STALL, &acm->flags)) {
		smp_mb(); /* against acm_suspend() */
@@ -585,7 +586,7 @@ static void acm_softint(struct work_struct *work)
	if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) {
		for (i = 0; i < acm->rx_buflimit; i++)
			if (test_and_clear_bit(i, &acm->urbs_in_error_delay))
					acm_submit_read_urb(acm, i, GFP_NOIO);
				acm_submit_read_urb(acm, i, GFP_KERNEL);
	}

	if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags))
@@ -1351,7 +1352,6 @@ made_compressed_probe:
	acm->ctrlsize = ctrlsize;
	acm->readsize = readsize;
	acm->rx_buflimit = num_rx_buf;
	INIT_WORK(&acm->work, acm_softint);
	INIT_DELAYED_WORK(&acm->dwork, acm_softint);
	init_waitqueue_head(&acm->wioctl);
	spin_lock_init(&acm->write_lock);
@@ -1561,7 +1561,6 @@ static void acm_disconnect(struct usb_interface *intf)
	}

	acm_kill_urbs(acm);
	cancel_work_sync(&acm->work);
	cancel_delayed_work_sync(&acm->dwork);

	tty_unregister_device(acm_tty_driver, acm->minor);
@@ -1604,7 +1603,6 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
		return 0;

	acm_kill_urbs(acm);
	cancel_work_sync(&acm->work);
	cancel_delayed_work_sync(&acm->dwork);
	acm->urbs_in_error_delay = 0;

+1 −2
Original line number Diff line number Diff line
@@ -112,8 +112,7 @@ struct acm {
#		define ACM_ERROR_DELAY	3
	unsigned long urbs_in_error_delay;		/* these need to be restarted after a delay */
	struct usb_cdc_line_coding line;		/* bits, stop, parity */
	struct work_struct work;			/* work queue entry for various purposes*/
	struct delayed_work dwork;			/* for cool downs needed in error recovery */
	struct delayed_work dwork;		        /* work queue entry for various purposes */
	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
	struct async_icount iocount;			/* counters for control line changes */
Loading