diff options
author | Eugeny S. Mints <emints@ru.mvista.com> | 2006-09-02 06:59:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 14:58:56 -0400 |
commit | 80f8af0c59385b41564a3ae670f94a1b4caa43b2 (patch) | |
tree | c2721898c3db66f743639a8446d72c48ebd11950 /drivers/usb/gadget | |
parent | 0e3c8c26c7013b9d34929857598fd86ff1c22a6c (diff) |
USB: usb serial gadget smp related bug
Adjust dev->dev_lock spinlock lock/unlock calls to be safe for SMP case.
Otherwise the following sequence may lead to a deadlock in SMP case:
gs_send()->usb_ep_queue()
->(in case a request is satisfied immediatly) gs_write_complete()
for ex for pxa2xx_udc.c:
usb_ep_queue()->pxa2xx_ep_queue()->write_fifo()->done()->gs_write_complete()
(through req.complete pointer)
Signed-off-by: Eugeny S. Mints <emints@ru.mvista.com>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/serial.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index e762aa19ab0a..b893e3118e1b 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -1120,12 +1120,15 @@ static int gs_send(struct gs_dev *dev) | |||
1120 | gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2)); | 1120 | gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2)); |
1121 | list_del(&req_entry->re_entry); | 1121 | list_del(&req_entry->re_entry); |
1122 | req->length = len; | 1122 | req->length = len; |
1123 | spin_unlock_irqrestore(&dev->dev_lock, flags); | ||
1123 | if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { | 1124 | if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { |
1124 | printk(KERN_ERR | 1125 | printk(KERN_ERR |
1125 | "gs_send: cannot queue read request, ret=%d\n", | 1126 | "gs_send: cannot queue read request, ret=%d\n", |
1126 | ret); | 1127 | ret); |
1128 | spin_lock_irqsave(&dev->dev_lock, flags); | ||
1127 | break; | 1129 | break; |
1128 | } | 1130 | } |
1131 | spin_lock_irqsave(&dev->dev_lock, flags); | ||
1129 | } else { | 1132 | } else { |
1130 | break; | 1133 | break; |
1131 | } | 1134 | } |