]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/usb/gadget/ether.c
usb-gadget-ether: prevent oops caused by error interrupt race
[karo-tx-linux.git] / drivers / usb / gadget / ether.c
index 593e23507b1a79cff9b63fc0986d0ae088ac3d93..d57de878a5f0c0abb4a0b6098596606a106b556d 100644 (file)
@@ -1989,8 +1989,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);