summaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@atmel.com>2007-12-14 00:52:58 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2007-12-17 19:47:15 +0100
commit08cbc706acd2dd601b0663e28fa97ffb0564e105 (patch)
treefc9cc0a4aab57dee2b30a8b145dfbb5ee3688388 /drivers/usb/gadget
parentUSB: use IRQF_DISABLED for HCD interrupt handlers (diff)
downloadlinux-08cbc706acd2dd601b0663e28fa97ffb0564e105.tar.xz
linux-08cbc706acd2dd601b0663e28fa97ffb0564e105.zip
USB: at91_udc: correct hanging while disconnecting usb cable
Correct hanging while disconnecting the USB device cable. Prevent a race between vbus and UDP interrupts. This bug was tracked on at91sam9260ek boards. A usb resume interrupt was firing after the vbus interrupt : the IP was then already stoped and not able to deal with it (no more clock). A simple interrupt disabling is ok as the "end of bus reset" irq is non maskable and ok to resume the USB device IP. Signed-off-by: Nicolas Ferre <nicolas.ferre@rfo.atmel.com> Acked-by: David Brownell <david-b@pacbell.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/at91_udc.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index a6adf7e0f6f8..cd62b029d176 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -887,6 +887,7 @@ static void pullup(struct at91_udc *udc, int is_on)
if (is_on) {
clk_on(udc);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
at91_udp_write(udc, AT91_UDP_TXVC, 0);
if (cpu_is_at91rm9200())
at91_set_gpio_value(udc->board.pullup_pin, 1);
@@ -904,6 +905,7 @@ static void pullup(struct at91_udc *udc, int is_on)
}
} else {
stop_activity(udc);
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
if (cpu_is_at91rm9200())
at91_set_gpio_value(udc->board.pullup_pin, 0);