mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
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: Thomas 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
0de6ab8b91
commit
c5deb832d7
1 changed files with 30 additions and 19 deletions
|
@ -1213,6 +1213,11 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
|
||||||
tmp &= AMD_UNMASK_BIT(ep->num);
|
tmp &= AMD_UNMASK_BIT(ep->num);
|
||||||
writel(tmp, &dev->regs->ep_irqmsk);
|
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) {
|
} else if (ep->dma) {
|
||||||
|
@ -2005,18 +2010,17 @@ __acquires(dev->lock)
|
||||||
{
|
{
|
||||||
int tmp;
|
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) {
|
if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
|
||||||
spin_unlock(&dev->lock);
|
spin_unlock(&dev->lock);
|
||||||
driver->disconnect(&dev->gadget);
|
driver->disconnect(&dev->gadget);
|
||||||
spin_lock(&dev->lock);
|
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);
|
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 */
|
/* clear status bits */
|
||||||
|
@ -3279,6 +3290,17 @@ static int udc_pci_probe(
|
||||||
goto finished;
|
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) {
|
if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
|
||||||
dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
|
dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
|
@ -3331,7 +3353,6 @@ static int udc_probe(struct udc *dev)
|
||||||
udc_pollstall_timer.data = 0;
|
udc_pollstall_timer.data = 0;
|
||||||
|
|
||||||
/* device struct setup */
|
/* device struct setup */
|
||||||
spin_lock_init(&dev->lock);
|
|
||||||
dev->gadget.ops = &udc_ops;
|
dev->gadget.ops = &udc_ops;
|
||||||
|
|
||||||
dev_set_name(&dev->gadget.dev, "gadget");
|
dev_set_name(&dev->gadget.dev, "gadget");
|
||||||
|
@ -3340,16 +3361,6 @@ static int udc_probe(struct udc *dev)
|
||||||
dev->gadget.name = name;
|
dev->gadget.name = name;
|
||||||
dev->gadget.is_dualspeed = 1;
|
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, ... */
|
/* init registers, interrupts, ... */
|
||||||
startup_registers(dev);
|
startup_registers(dev);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue