On Wed, 19 Feb 2014, Stanislaw Gruszka wrote: > ehci_irq() and ehci_hrtimer_func() can deadlock on ehci->lock when > threadirqs option is used. To prevent the deadlock use > spin_lock_irqsave() in ehci_irq(). > > This change can be reverted when hrtimer callbacks become threaded. > > Signed-off-by: Stanislaw Gruszka <sgruszka@xxxxxxxxxx> > --- > drivers/usb/host/ehci-hcd.c | 13 ++++++++++--- > 1 file changed, 10 insertions(+), 3 deletions(-) > > diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c > index 4711427..0bc6410 100644 > --- a/drivers/usb/host/ehci-hcd.c > +++ b/drivers/usb/host/ehci-hcd.c > @@ -685,8 +685,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) > struct ehci_hcd *ehci = hcd_to_ehci (hcd); > u32 status, masked_status, pcd_status = 0, cmd; > int bh; > + unsigned long flags; > > - spin_lock (&ehci->lock); > + /* > + * For threadirqs option we use spin_lock_irqsave() variant to prevent > + * deadlock with ehci hrtimer callback, because hrtimer callbacks run > + * in interrupt context even when threadirqs is specified. We can go > + * back to spin_lock() variant when hrtimer callbacks become threaded. > + */ > + spin_lock_irqsave(&ehci->lock, flags); > > status = ehci_readl(ehci, &ehci->regs->status); > > @@ -704,7 +711,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) > > /* Shared IRQ? */ > if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) { > - spin_unlock(&ehci->lock); > + spin_unlock_irqrestore(&ehci->lock, flags); > return IRQ_NONE; > } > > @@ -815,7 +822,7 @@ dead: > > if (bh) > ehci_work (ehci); > - spin_unlock (&ehci->lock); > + spin_unlock_irqrestore(&ehci->lock, flags); > if (pcd_status) > usb_hcd_poll_rh_status(hcd); > return IRQ_HANDLED; Acked-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html