]> Pileus Git - ~andy/linux/blobdiff - drivers/usb/gadget/ether.c
usb-gadget-ether: prevent oops caused by error interrupt race
[~andy/linux] / drivers / usb / gadget / ether.c
index ff244f42723fd265be1b39d27f1c796732194f5a..9f4fd7e849a0194862bf1ba1285730967baf7bcd 100644 (file)
@@ -1957,8 +1957,20 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
        }
 
        spin_lock_irqsave(&dev->req_lock, flags);
+       /*
+        * this 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);