Messages in this thread | | | Subject | Re: [PATCH] usb-gadget-ether: Prevent oops caused by error interrupt race -V2 (comments update) | From | Thomas Gleixner <> | Date | Sat, 22 Sep 2007 22:23:00 +0200 |
| |
On Sat, 2007-09-22 at 13:14 -0700, David Brownell wrote: > How's this? Note that the queue should already have been stopped, > so I removed what should be an extra call (as well as fixing the > comments).
Yeah, stop queue should be not necessary.
> - Dave > > ======== > From: Thomas Gleixner <tglx@linutronix.de>
Please change to:
From: Benedikt Spranger <bene@linutronix.de>
He did all the grump work of figuring out what's going wrong. I was just the messenger.
> This patch fixes a longstanding race in the Ethernet gadget driver, > which can cause an oops on device disconnect. The fix is just to > make the TX path check whether its freelist is empty. That check > is otherwise not necessary, since the queue is always stopped when > that list empties (and restarted when request completion puts an > entry back on that freelist).
Sigh. I need a real deep look inside that code to understand, why tx_reqs is not a requestlist but a freelist. Very intuitive naming :)
> The race window starts when the network code decides to transmit a > packet, and ends when hard_start_xmit() grabs the freelist lock. > If disconnect() is called inside that window, it shuts down the > TX queue and breaks the otherwise-solid assumption that packets are > never sent when the TX queue is stopped.
Please add our signed offs as well
Signed-off-by: Benedikt Spranger <bene@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Thanks, tglx
> --- a/drivers/usb/gadget/ether.c > +++ b/drivers/usb/gadget/ether.c > @@ -1989,8 +1989,20 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) > } > > spin_lock_irqsave(&dev->req_lock, flags); > + /* > + * the freelist can be empty if an interrupt triggered disconnect() > + * and reconfigured the gadget (shutting down this queue) after the > + * network stack decided to xmit but before we got the spinlock. > + */ > + if (list_empty(&dev->tx_reqs)) { > + spin_unlock_irqrestore(&dev->req_lock, flags); > + return 1; > + } > + > req = container_of (dev->tx_reqs.next, struct usb_request, list); > list_del (&req->list); > + > + /* temporarily stop TX queue when the freelist empties */ > if (list_empty (&dev->tx_reqs)) > netif_stop_queue (net); > spin_unlock_irqrestore(&dev->req_lock, flags); > >
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |