Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88767cc1 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'fixes-for-v4.11-rc2' of...

Merge tag 'fixes-for-v4.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus

Felipe writes:

usb: fixes for v4.11-rc2

dwc3 got a few fixes this time around:

Fixed an old bug where a broken endpoint descriptor passed in via
userspace through f_fs could prevent dwc3 from working because when
calculating max bursts, we could overwrite top 16 bits of a register.

Also fixed a bug on dwc3's ep_dequeue implementation which wasn't
properly incrementing our TRB dequeue pointer.

dwc3 on omap got two fixes: one for system suspend/resume and another
added a missing break statement on dwc3_omap_set_mailbox().

Apart from these, we have a set of smaller fixes including memory leak
in configfs, build warning fix in atmel udc and a revert of a broken
patch that went in during the merge window
parents c1ae3cfa 35b2719e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -250,6 +250,7 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
		val = dwc3_omap_read_utmi_ctrl(omap);
		val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG;
		dwc3_omap_write_utmi_ctrl(omap, val);
		break;

	case OMAP_DWC3_VBUS_OFF:
		val = dwc3_omap_read_utmi_ctrl(omap);
@@ -392,7 +393,7 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
{
	u32			reg;
	struct device_node	*node = omap->dev->of_node;
	int			utmi_mode = 0;
	u32			utmi_mode = 0;

	reg = dwc3_omap_read_utmi_ctrl(omap);

+67 −9
Original line number Diff line number Diff line
@@ -1342,6 +1342,68 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
		if (r == req) {
			/* wait until it is processed */
			dwc3_stop_active_transfer(dwc, dep->number, true);

			/*
			 * If request was already started, this means we had to
			 * stop the transfer. With that we also need to ignore
			 * all TRBs used by the request, however TRBs can only
			 * be modified after completion of END_TRANSFER
			 * command. So what we do here is that we wait for
			 * END_TRANSFER completion and only after that, we jump
			 * over TRBs by clearing HWO and incrementing dequeue
			 * pointer.
			 *
			 * Note that we have 2 possible types of transfers here:
			 *
			 * i) Linear buffer request
			 * ii) SG-list based request
			 *
			 * SG-list based requests will have r->num_pending_sgs
			 * set to a valid number (> 0). Linear requests,
			 * normally use a single TRB.
			 *
			 * For each of these two cases, if r->unaligned flag is
			 * set, one extra TRB has been used to align transfer
			 * size to wMaxPacketSize.
			 *
			 * All of these cases need to be taken into
			 * consideration so we don't mess up our TRB ring
			 * pointers.
			 */
			wait_event_lock_irq(dep->wait_end_transfer,
					!(dep->flags & DWC3_EP_END_TRANSFER_PENDING),
					dwc->lock);

			if (!r->trb)
				goto out1;

			if (r->num_pending_sgs) {
				struct dwc3_trb *trb;
				int i = 0;

				for (i = 0; i < r->num_pending_sgs; i++) {
					trb = r->trb + i;
					trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
					dwc3_ep_inc_deq(dep);
				}

				if (r->unaligned) {
					trb = r->trb + r->num_pending_sgs + 1;
					trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
					dwc3_ep_inc_deq(dep);
				}
			} else {
				struct dwc3_trb *trb = r->trb;

				trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
				dwc3_ep_inc_deq(dep);

				if (r->unaligned) {
					trb = r->trb + 1;
					trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
					dwc3_ep_inc_deq(dep);
				}
			}
			goto out1;
		}
		dev_err(dwc->dev, "request %p was not queued to %s\n",
@@ -1352,6 +1414,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,

out1:
	/* giveback the request */
	dep->queued_requests--;
	dwc3_gadget_giveback(dep, req, -ECONNRESET);

out0:
@@ -2126,12 +2189,12 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
		return 1;
	}

	if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
		return 1;

	count = trb->size & DWC3_TRB_SIZE_MASK;
	req->remaining += count;

	if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
		return 1;

	if (dep->direction) {
		if (count) {
			trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size);
@@ -3228,15 +3291,10 @@ void dwc3_gadget_exit(struct dwc3 *dwc)

int dwc3_gadget_suspend(struct dwc3 *dwc)
{
	int ret;

	if (!dwc->gadget_driver)
		return 0;

	ret = dwc3_gadget_run_stop(dwc, false, false);
	if (ret < 0)
		return ret;

	dwc3_gadget_run_stop(dwc, false, false);
	dwc3_disconnect_gadget(dwc);
	__dwc3_gadget_stop(dwc);

+7 −7
Original line number Diff line number Diff line
@@ -28,23 +28,23 @@ struct dwc3;
#define gadget_to_dwc(g)	(container_of(g, struct dwc3, gadget))

/* DEPCFG parameter 1 */
#define DWC3_DEPCFG_INT_NUM(n)		((n) << 0)
#define DWC3_DEPCFG_INT_NUM(n)		(((n) & 0x1f) << 0)
#define DWC3_DEPCFG_XFER_COMPLETE_EN	(1 << 8)
#define DWC3_DEPCFG_XFER_IN_PROGRESS_EN	(1 << 9)
#define DWC3_DEPCFG_XFER_NOT_READY_EN	(1 << 10)
#define DWC3_DEPCFG_FIFO_ERROR_EN	(1 << 11)
#define DWC3_DEPCFG_STREAM_EVENT_EN	(1 << 13)
#define DWC3_DEPCFG_BINTERVAL_M1(n)	((n) << 16)
#define DWC3_DEPCFG_BINTERVAL_M1(n)	(((n) & 0xff) << 16)
#define DWC3_DEPCFG_STREAM_CAPABLE	(1 << 24)
#define DWC3_DEPCFG_EP_NUMBER(n)	((n) << 25)
#define DWC3_DEPCFG_EP_NUMBER(n)	(((n) & 0x1f) << 25)
#define DWC3_DEPCFG_BULK_BASED		(1 << 30)
#define DWC3_DEPCFG_FIFO_BASED		(1 << 31)

/* DEPCFG parameter 0 */
#define DWC3_DEPCFG_EP_TYPE(n)		((n) << 1)
#define DWC3_DEPCFG_MAX_PACKET_SIZE(n)	((n) << 3)
#define DWC3_DEPCFG_FIFO_NUMBER(n)	((n) << 17)
#define DWC3_DEPCFG_BURST_SIZE(n)	((n) << 22)
#define DWC3_DEPCFG_EP_TYPE(n)		(((n) & 0x3) << 1)
#define DWC3_DEPCFG_MAX_PACKET_SIZE(n)	(((n) & 0x7ff) << 3)
#define DWC3_DEPCFG_FIFO_NUMBER(n)	(((n) & 0x1f) << 17)
#define DWC3_DEPCFG_BURST_SIZE(n)	(((n) & 0xf) << 22)
#define DWC3_DEPCFG_DATA_SEQ_NUM(n)	((n) << 26)
/* This applies for core versions earlier than 1.94a */
#define DWC3_DEPCFG_IGN_SEQ_NUM		(1 << 31)
+1 −0
Original line number Diff line number Diff line
@@ -269,6 +269,7 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
		ret = unregister_gadget(gi);
		if (ret)
			goto err;
		kfree(name);
	} else {
		if (gi->composite.gadget_driver.udc_name) {
			ret = -EBUSY;
+14 −3
Original line number Diff line number Diff line
@@ -1834,11 +1834,14 @@ static int ffs_func_eps_enable(struct ffs_function *func)
	spin_lock_irqsave(&func->ffs->eps_lock, flags);
	while(count--) {
		struct usb_endpoint_descriptor *ds;
		struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
		int needs_comp_desc = false;
		int desc_idx;

		if (ffs->gadget->speed == USB_SPEED_SUPER)
		if (ffs->gadget->speed == USB_SPEED_SUPER) {
			desc_idx = 2;
		else if (ffs->gadget->speed == USB_SPEED_HIGH)
			needs_comp_desc = true;
		} else if (ffs->gadget->speed == USB_SPEED_HIGH)
			desc_idx = 1;
		else
			desc_idx = 0;
@@ -1855,6 +1858,14 @@ static int ffs_func_eps_enable(struct ffs_function *func)

		ep->ep->driver_data = ep;
		ep->ep->desc = ds;

		comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds +
				USB_DT_ENDPOINT_SIZE);
		ep->ep->maxburst = comp_desc->bMaxBurst + 1;

		if (needs_comp_desc)
			ep->ep->comp_desc = comp_desc;

		ret = usb_ep_enable(ep->ep);
		if (likely(!ret)) {
			epfile->ep = ep;
@@ -2253,7 +2264,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,

		if (len < sizeof(*d) ||
		    d->bFirstInterfaceNumber >= ffs->interfaces_count ||
		    d->Reserved1)
		    !d->Reserved1)
			return -EINVAL;
		for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
			if (d->Reserved2[i])
Loading