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

Commit c5deb832 authored by Thomas Dahlmann's avatar Thomas Dahlmann Committed by Greg Kroah-Hartman
Browse files

usb: amd5536udc: fixed shared interrupt bug and warning oops



- fixed shared interrupt bug reported by Vadim Lobanov
 - fixed possible warning oops on driver unload when connected
 - prevent interrupt flood in PIO mode ("modprobe amd5536udc use_dma=0")
   when using gadget ether

Signed-off-by: default avatarThomas Dahlmann <dahlmann.thomas@arcor.de>
Cc: Robert Richter <robert.richter@amd.com>
Cc: David Brownell <david-b@pacbell.net>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 0de6ab8b
Loading
Loading
Loading
Loading
+30 −19
Original line number Diff line number Diff line
@@ -1213,6 +1213,11 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
				tmp &= AMD_UNMASK_BIT(ep->num);
				writel(tmp, &dev->regs->ep_irqmsk);
			}
		} else if (ep->in) {
				/* enable ep irq */
				tmp = readl(&dev->regs->ep_irqmsk);
				tmp &= AMD_UNMASK_BIT(ep->num);
				writel(tmp, &dev->regs->ep_irqmsk);
			}

	} else if (ep->dma) {
@@ -2005,18 +2010,17 @@ __acquires(dev->lock)
{
	int tmp;

	/* empty queues and init hardware */
	udc_basic_init(dev);
	for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
		empty_req_queue(&dev->ep[tmp]);
	}

	if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
		spin_unlock(&dev->lock);
		driver->disconnect(&dev->gadget);
		spin_lock(&dev->lock);
	}
	/* init */

	/* empty queues and init hardware */
	udc_basic_init(dev);
	for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
		empty_req_queue(&dev->ep[tmp]);

	udc_setup_endpoints(dev);
}

@@ -2472,6 +2476,13 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
				}
			}

		} else if (!use_dma && ep->in) {
			/* disable interrupt */
			tmp = readl(
				&dev->regs->ep_irqmsk);
			tmp |= AMD_BIT(ep->num);
			writel(tmp,
				&dev->regs->ep_irqmsk);
		}
	}
	/* clear status bits */
@@ -3279,6 +3290,17 @@ static int udc_pci_probe(
		goto finished;
	}

	spin_lock_init(&dev->lock);
	/* udc csr registers base */
	dev->csr = dev->virt_addr + UDC_CSR_ADDR;
	/* dev registers base */
	dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
	/* ep registers base */
	dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
	/* fifo's base */
	dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
	dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);

	if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
		dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
		kfree(dev);
@@ -3331,7 +3353,6 @@ static int udc_probe(struct udc *dev)
	udc_pollstall_timer.data = 0;

	/* device struct setup */
	spin_lock_init(&dev->lock);
	dev->gadget.ops = &udc_ops;

	dev_set_name(&dev->gadget.dev, "gadget");
@@ -3340,16 +3361,6 @@ static int udc_probe(struct udc *dev)
	dev->gadget.name = name;
	dev->gadget.is_dualspeed = 1;

	/* udc csr registers base */
	dev->csr = dev->virt_addr + UDC_CSR_ADDR;
	/* dev registers base */
	dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
	/* ep registers base */
	dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
	/* fifo's base */
	dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
	dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);

	/* init registers, interrupts, ... */
	startup_registers(dev);