diff options
author | Thomas Dahlmann <dahlmann.thomas@arcor.de> | 2009-11-17 17:18:27 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-11-30 19:43:15 -0500 |
commit | c5deb832d7a3f9618b09e6eeaa91a1a845c90c65 (patch) | |
tree | 7676793d67592bac01c7605e4b37e26a63a27e9e /drivers/usb | |
parent | 0de6ab8b91f2e1e8e7fc66a8b5c5e8ca82ea16b7 (diff) |
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/amd5536udc.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index d5b65962dd36..731150d4b1d9 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c | |||
@@ -1213,7 +1213,12 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp) | |||
1213 | tmp &= AMD_UNMASK_BIT(ep->num); | 1213 | tmp &= AMD_UNMASK_BIT(ep->num); |
1214 | writel(tmp, &dev->regs->ep_irqmsk); | 1214 | writel(tmp, &dev->regs->ep_irqmsk); |
1215 | } | 1215 | } |
1216 | } | 1216 | } else if (ep->in) { |
1217 | /* enable ep irq */ | ||
1218 | tmp = readl(&dev->regs->ep_irqmsk); | ||
1219 | tmp &= AMD_UNMASK_BIT(ep->num); | ||
1220 | writel(tmp, &dev->regs->ep_irqmsk); | ||
1221 | } | ||
1217 | 1222 | ||
1218 | } else if (ep->dma) { | 1223 | } else if (ep->dma) { |
1219 | 1224 | ||
@@ -2005,18 +2010,17 @@ __acquires(dev->lock) | |||
2005 | { | 2010 | { |
2006 | int tmp; | 2011 | int tmp; |
2007 | 2012 | ||
2008 | /* empty queues and init hardware */ | ||
2009 | udc_basic_init(dev); | ||
2010 | for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { | ||
2011 | empty_req_queue(&dev->ep[tmp]); | ||
2012 | } | ||
2013 | |||
2014 | if (dev->gadget.speed != USB_SPEED_UNKNOWN) { | 2013 | if (dev->gadget.speed != USB_SPEED_UNKNOWN) { |
2015 | spin_unlock(&dev->lock); | 2014 | spin_unlock(&dev->lock); |
2016 | driver->disconnect(&dev->gadget); | 2015 | driver->disconnect(&dev->gadget); |
2017 | spin_lock(&dev->lock); | 2016 | spin_lock(&dev->lock); |
2018 | } | 2017 | } |
2019 | /* init */ | 2018 | |
2019 | /* empty queues and init hardware */ | ||
2020 | udc_basic_init(dev); | ||
2021 | for (tmp = 0; tmp < UDC_EP_NUM; tmp++) | ||
2022 | empty_req_queue(&dev->ep[tmp]); | ||
2023 | |||
2020 | udc_setup_endpoints(dev); | 2024 | udc_setup_endpoints(dev); |
2021 | } | 2025 | } |
2022 | 2026 | ||
@@ -2472,6 +2476,13 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix) | |||
2472 | } | 2476 | } |
2473 | } | 2477 | } |
2474 | 2478 | ||
2479 | } else if (!use_dma && ep->in) { | ||
2480 | /* disable interrupt */ | ||
2481 | tmp = readl( | ||
2482 | &dev->regs->ep_irqmsk); | ||
2483 | tmp |= AMD_BIT(ep->num); | ||
2484 | writel(tmp, | ||
2485 | &dev->regs->ep_irqmsk); | ||
2475 | } | 2486 | } |
2476 | } | 2487 | } |
2477 | /* clear status bits */ | 2488 | /* clear status bits */ |
@@ -3279,6 +3290,17 @@ static int udc_pci_probe( | |||
3279 | goto finished; | 3290 | goto finished; |
3280 | } | 3291 | } |
3281 | 3292 | ||
3293 | spin_lock_init(&dev->lock); | ||
3294 | /* udc csr registers base */ | ||
3295 | dev->csr = dev->virt_addr + UDC_CSR_ADDR; | ||
3296 | /* dev registers base */ | ||
3297 | dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR; | ||
3298 | /* ep registers base */ | ||
3299 | dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR; | ||
3300 | /* fifo's base */ | ||
3301 | dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR); | ||
3302 | dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); | ||
3303 | |||
3282 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { | 3304 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { |
3283 | dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq); | 3305 | dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq); |
3284 | kfree(dev); | 3306 | kfree(dev); |
@@ -3331,7 +3353,6 @@ static int udc_probe(struct udc *dev) | |||
3331 | udc_pollstall_timer.data = 0; | 3353 | udc_pollstall_timer.data = 0; |
3332 | 3354 | ||
3333 | /* device struct setup */ | 3355 | /* device struct setup */ |
3334 | spin_lock_init(&dev->lock); | ||
3335 | dev->gadget.ops = &udc_ops; | 3356 | dev->gadget.ops = &udc_ops; |
3336 | 3357 | ||
3337 | dev_set_name(&dev->gadget.dev, "gadget"); | 3358 | dev_set_name(&dev->gadget.dev, "gadget"); |
@@ -3340,16 +3361,6 @@ static int udc_probe(struct udc *dev) | |||
3340 | dev->gadget.name = name; | 3361 | dev->gadget.name = name; |
3341 | dev->gadget.is_dualspeed = 1; | 3362 | dev->gadget.is_dualspeed = 1; |
3342 | 3363 | ||
3343 | /* udc csr registers base */ | ||
3344 | dev->csr = dev->virt_addr + UDC_CSR_ADDR; | ||
3345 | /* dev registers base */ | ||
3346 | dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR; | ||
3347 | /* ep registers base */ | ||
3348 | dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR; | ||
3349 | /* fifo's base */ | ||
3350 | dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR); | ||
3351 | dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); | ||
3352 | |||
3353 | /* init registers, interrupts, ... */ | 3364 | /* init registers, interrupts, ... */ |
3354 | startup_registers(dev); | 3365 | startup_registers(dev); |
3355 | 3366 | ||