Skip to content

Commit

Permalink
brcmfmac: fix race condition for rx and tx data.
Browse files Browse the repository at this point in the history
On both rx and tx there is was a race condition on the queueing
of usb requests. When for example frame gets submitted it is
possible that complete function gets called even before
usb_submit_urb() returns. As a result it is possible that usb
requests get losts, which was noticed on OMAP4 pandaboard
platform. This patch fixes the race condition.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Hante Meuleman authored and John W. Linville committed Sep 5, 2012
1 parent 474ab7c commit 2e875ac
Showing 1 changed file with 11 additions and 10 deletions.
21 changes: 11 additions & 10 deletions drivers/net/wireless/brcm80211/brcmfmac/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,13 +550,15 @@ static void brcmf_usb_rx_complete(struct urb *urb)
if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
brcmf_dbg(ERROR, "rx protocol error\n");
brcmu_pkt_buf_free_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
devinfo->bus_pub.bus->dstats.rx_errors++;
} else {
brcmf_rx_packet(devinfo->dev, ifidx, skb);
brcmf_usb_rx_refill(devinfo, req);
}
} else {
brcmu_pkt_buf_free_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
}
return;

Expand All @@ -582,11 +584,11 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
req);
req->devinfo = devinfo;
brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);

ret = usb_submit_urb(req->urb, GFP_ATOMIC);
if (ret == 0) {
brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);
} else {
if (ret) {
brcmf_usb_del_fromq(devinfo, req);
brcmu_pkt_buf_free_skb(req->skb);
req->skb = NULL;
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
Expand Down Expand Up @@ -682,23 +684,22 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)

req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);
if (!req) {
brcmu_pkt_buf_free_skb(skb);
brcmf_dbg(ERROR, "no req to send\n");
return -ENOMEM;
}
if (!req->urb) {
brcmf_dbg(ERROR, "no urb for req %p\n", req);
return -ENOBUFS;
}

req->skb = skb;
req->devinfo = devinfo;
usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
skb->data, skb->len, brcmf_usb_tx_complete, req);
req->urb->transfer_flags |= URB_ZERO_PACKET;
brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
ret = usb_submit_urb(req->urb, GFP_ATOMIC);
if (!ret) {
brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
} else {
if (ret) {
brcmf_dbg(ERROR, "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);
}
Expand Down

0 comments on commit 2e875ac

Please sign in to comment.