brcmfmac: assure brcmf_txcomplete() is called in failure paths
authorArend van Spriel <arend@broadcom.com>
Sun, 3 Mar 2013 11:45:30 +0000 (12:45 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 6 Mar 2013 21:28:46 +0000 (16:28 -0500)
For transmit packets the function brcmf_txcomplete() must be
called. This should be done as well when for some reason the
transmit fails to assure proper tx post processing. This patch
fixes the code paths in brcmf_usb_tx() that forgot to do so.

Reviewed-by: Piotr Haber <phaber@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/brcm80211/brcmfmac/usb.c

index bf5bb87..01aed7a 100644 (file)
@@ -570,15 +570,17 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
        int ret;
 
        brcmf_dbg(USB, "Enter, skb=%p\n", skb);
-       if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
-               return -EIO;
+       if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
+               ret = -EIO;
+               goto fail;
+       }
 
        req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
                                        &devinfo->tx_freecount);
        if (!req) {
-               brcmu_pkt_buf_free_skb(skb);
                brcmf_err("no req to send\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail;
        }
 
        req->skb = skb;
@@ -591,18 +593,21 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
        if (ret) {
                brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n");
                brcmf_usb_del_fromq(devinfo, req);
-               brcmu_pkt_buf_free_skb(req->skb);
                req->skb = NULL;
                brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
-                                               &devinfo->tx_freecount);
-       } else {
-               if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
-                       !devinfo->tx_flowblock) {
-                       brcmf_txflowblock(dev, true);
-                       devinfo->tx_flowblock = true;
-               }
+                             &devinfo->tx_freecount);
+               goto fail;
        }
 
+       if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
+           !devinfo->tx_flowblock) {
+               brcmf_txflowblock(dev, true);
+               devinfo->tx_flowblock = true;
+       }
+       return 0;
+
+fail:
+       brcmf_txcomplete(dev, skb, false);
        return ret;
 }