Commit 5e23e90f authored by Robert Jarzmik's avatar Robert Jarzmik Committed by Greg Kroah-Hartman

USB: pxa27x_udc: Fix deadlocks on request queueing

As reported by Antonio, there are cases where the ep->lock
can be taken twice, triggering a deadlock.
The typical sequence is :
 irq_handler
   \
    -> gadget.complete()
       \
        -> pxa27x_udc.pxa_ep_queue() : ep->lock is taken
           \
            -> gadget.complete()
               \
                -> pxa27x_udc.pxa_ep_queue() : ep->lock is taken
                                               ==> *deadlock*
The patch fixes this by :
 - releasing the lock each time gadget.complete() is called
 - adding a check in handle_ep() to detect a recursive call,
   in which case the function becomes on no-op.

The patch is still not good enough for ep0. For this unique
endpoint, another well thought over patch will be needed.
Reported-by: default avatarAntonio Ospite <ospite@studenti.unina.it>
Tested-by: default avatarAntonio Ospite <ospite@studenti.unina.it>
Signed-off-by: default avatarRobert Jarzmik <robert.jarzmik@free.fr>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Eric Miao <eric.y.miao@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent fb088e33
This diff is collapsed.
...@@ -318,6 +318,11 @@ struct udc_usb_ep { ...@@ -318,6 +318,11 @@ struct udc_usb_ep {
* @queue: requests queue * @queue: requests queue
* @lock: lock to pxa_ep data (queues and stats) * @lock: lock to pxa_ep data (queues and stats)
* @enabled: true when endpoint enabled (not stopped by gadget layer) * @enabled: true when endpoint enabled (not stopped by gadget layer)
* @in_handle_ep: number of recursions of handle_ep() function
* Prevents deadlocks or infinite recursions of types :
* irq->handle_ep()->req_done()->req.complete()->pxa_ep_queue()->handle_ep()
* or
* pxa_ep_queue()->handle_ep()->req_done()->req.complete()->pxa_ep_queue()
* @idx: endpoint index (1 => epA, 2 => epB, ..., 24 => epX) * @idx: endpoint index (1 => epA, 2 => epB, ..., 24 => epX)
* @name: endpoint name (for trace/debug purpose) * @name: endpoint name (for trace/debug purpose)
* @dir_in: 1 if IN endpoint, 0 if OUT endpoint * @dir_in: 1 if IN endpoint, 0 if OUT endpoint
...@@ -346,6 +351,7 @@ struct pxa_ep { ...@@ -346,6 +351,7 @@ struct pxa_ep {
spinlock_t lock; /* Protects this structure */ spinlock_t lock; /* Protects this structure */
/* (queues, stats) */ /* (queues, stats) */
unsigned enabled:1; unsigned enabled:1;
unsigned in_handle_ep:1;
unsigned idx:5; unsigned idx:5;
char *name; char *name;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment