Commit 96ae93b4 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'fixes-for-v4.20-rc4' of...

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

Felipe writes:

USB: fixes for v4.20-rc4

In this second set of fixes for the current -rc cycle, we have some
regressions fixes for the old omap_udc driver done by Aaro Koskinen.

We're also reverting an old patch on dwc3 which is, now, known to
break USB certification in some cases.

We have a fix on u_ether for an unsafe list iteration.

* tag 'fixes-for-v4.20-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb:
  usb: gadget: u_ether: fix unsafe list iteration
  USB: omap_udc: fix rejection of out transfers when DMA is used
  USB: omap_udc: fix USB gadget functionality on Palm Tungsten E
  USB: omap_udc: fix omap_udc_start() on 15xx machines
  USB: omap_udc: fix crashes on probe error and module removal
  USB: omap_udc: use devm_request_irq()
  Revert "usb: dwc3: gadget: skip Set/Clear Halt when invalid"
parents effd14f6 c9287fa6
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -1470,9 +1470,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
		unsigned transfer_in_flight;
		unsigned started;

		if (dep->flags & DWC3_EP_STALL)
			return 0;

		if (dep->number > 1)
			trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue);
		else
@@ -1494,8 +1491,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
		else
			dep->flags |= DWC3_EP_STALL;
	} else {
		if (!(dep->flags & DWC3_EP_STALL))
			return 0;

		ret = dwc3_send_clear_stall_ep_cmd(dep);
		if (ret)
+6 −5
Original line number Diff line number Diff line
@@ -401,12 +401,12 @@ done:
static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
{
	struct usb_request	*req;
	struct usb_request	*tmp;
	unsigned long		flags;

	/* fill unused rxq slots with some skb */
	spin_lock_irqsave(&dev->req_lock, flags);
	list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) {
	while (!list_empty(&dev->rx_reqs)) {
		req = list_first_entry(&dev->rx_reqs, struct usb_request, list);
		list_del_init(&req->list);
		spin_unlock_irqrestore(&dev->req_lock, flags);

@@ -1125,7 +1125,6 @@ void gether_disconnect(struct gether *link)
{
	struct eth_dev		*dev = link->ioport;
	struct usb_request	*req;
	struct usb_request	*tmp;

	WARN_ON(!dev);
	if (!dev)
@@ -1142,7 +1141,8 @@ void gether_disconnect(struct gether *link)
	 */
	usb_ep_disable(link->in_ep);
	spin_lock(&dev->req_lock);
	list_for_each_entry_safe(req, tmp, &dev->tx_reqs, list) {
	while (!list_empty(&dev->tx_reqs)) {
		req = list_first_entry(&dev->tx_reqs, struct usb_request, list);
		list_del(&req->list);

		spin_unlock(&dev->req_lock);
@@ -1154,7 +1154,8 @@ void gether_disconnect(struct gether *link)

	usb_ep_disable(link->out_ep);
	spin_lock(&dev->req_lock);
	list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) {
	while (!list_empty(&dev->rx_reqs)) {
		req = list_first_entry(&dev->rx_reqs, struct usb_request, list);
		list_del(&req->list);

		spin_unlock(&dev->req_lock);
+31 −57
Original line number Diff line number Diff line
@@ -2033,6 +2033,7 @@ static inline int machine_without_vbus_sense(void)
{
	return machine_is_omap_innovator()
		|| machine_is_omap_osk()
		|| machine_is_omap_palmte()
		|| machine_is_sx1()
		/* No known omap7xx boards with vbus sense */
		|| cpu_is_omap7xx();
@@ -2041,7 +2042,7 @@ static inline int machine_without_vbus_sense(void)
static int omap_udc_start(struct usb_gadget *g,
		struct usb_gadget_driver *driver)
{
	int		status = -ENODEV;
	int		status;
	struct omap_ep	*ep;
	unsigned long	flags;

@@ -2079,6 +2080,7 @@ static int omap_udc_start(struct usb_gadget *g,
			goto done;
		}
	} else {
		status = 0;
		if (can_pullup(udc))
			pullup_enable(udc);
		else
@@ -2593,9 +2595,22 @@ omap_ep_setup(char *name, u8 addr, u8 type,

static void omap_udc_release(struct device *dev)
{
	pullup_disable(udc);
	if (!IS_ERR_OR_NULL(udc->transceiver)) {
		usb_put_phy(udc->transceiver);
		udc->transceiver = NULL;
	}
	omap_writew(0, UDC_SYSCON1);
	remove_proc_file();
	if (udc->dc_clk) {
		if (udc->clk_requested)
			omap_udc_enable_clock(0);
		clk_put(udc->hhc_clk);
		clk_put(udc->dc_clk);
	}
	if (udc->done)
		complete(udc->done);
	kfree(udc);
	udc = NULL;
}

static int
@@ -2627,6 +2642,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
	udc->gadget.speed = USB_SPEED_UNKNOWN;
	udc->gadget.max_speed = USB_SPEED_FULL;
	udc->gadget.name = driver_name;
	udc->gadget.quirk_ep_out_aligned_size = 1;
	udc->transceiver = xceiv;

	/* ep0 is special; put it right after the SETUP buffer */
@@ -2867,8 +2883,8 @@ bad_on_1710:
		udc->clr_halt = UDC_RESET_EP;

	/* USB general purpose IRQ:  ep0, state changes, dma, etc */
	status = request_irq(pdev->resource[1].start, omap_udc_irq,
			0, driver_name, udc);
	status = devm_request_irq(&pdev->dev, pdev->resource[1].start,
				  omap_udc_irq, 0, driver_name, udc);
	if (status != 0) {
		ERR("can't get irq %d, err %d\n",
			(int) pdev->resource[1].start, status);
@@ -2876,20 +2892,20 @@ bad_on_1710:
	}

	/* USB "non-iso" IRQ (PIO for all but ep0) */
	status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
			0, "omap_udc pio", udc);
	status = devm_request_irq(&pdev->dev, pdev->resource[2].start,
				  omap_udc_pio_irq, 0, "omap_udc pio", udc);
	if (status != 0) {
		ERR("can't get irq %d, err %d\n",
			(int) pdev->resource[2].start, status);
		goto cleanup2;
		goto cleanup1;
	}
#ifdef	USE_ISO
	status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
			0, "omap_udc iso", udc);
	status = devm_request_irq(&pdev->dev, pdev->resource[3].start,
				  omap_udc_iso_irq, 0, "omap_udc iso", udc);
	if (status != 0) {
		ERR("can't get irq %d, err %d\n",
			(int) pdev->resource[3].start, status);
		goto cleanup3;
		goto cleanup1;
	}
#endif
	if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
@@ -2900,23 +2916,8 @@ bad_on_1710:
	}

	create_proc_file();
	status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
	return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
					  omap_udc_release);
	if (status)
		goto cleanup4;

	return 0;

cleanup4:
	remove_proc_file();

#ifdef	USE_ISO
cleanup3:
	free_irq(pdev->resource[2].start, udc);
#endif

cleanup2:
	free_irq(pdev->resource[1].start, udc);

cleanup1:
	kfree(udc);
@@ -2943,42 +2944,15 @@ static int omap_udc_remove(struct platform_device *pdev)
{
	DECLARE_COMPLETION_ONSTACK(done);

	if (!udc)
		return -ENODEV;

	usb_del_gadget_udc(&udc->gadget);
	if (udc->driver)
		return -EBUSY;

	udc->done = &done;

	pullup_disable(udc);
	if (!IS_ERR_OR_NULL(udc->transceiver)) {
		usb_put_phy(udc->transceiver);
		udc->transceiver = NULL;
	}
	omap_writew(0, UDC_SYSCON1);

	remove_proc_file();

#ifdef	USE_ISO
	free_irq(pdev->resource[3].start, udc);
#endif
	free_irq(pdev->resource[2].start, udc);
	free_irq(pdev->resource[1].start, udc);
	usb_del_gadget_udc(&udc->gadget);

	if (udc->dc_clk) {
		if (udc->clk_requested)
			omap_udc_enable_clock(0);
		clk_put(udc->hhc_clk);
		clk_put(udc->dc_clk);
	}
	wait_for_completion(&done);

	release_mem_region(pdev->resource[0].start,
			pdev->resource[0].end - pdev->resource[0].start + 1);

	wait_for_completion(&done);

	return 0;
}