aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/usb.c
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2012-09-11 15:18:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-09-12 14:19:15 -0400
commitc6ab42948d7727e9efb2e29d9a0e68b88150f319 (patch)
tree806e63a6ffa2d8d2a04dba2431a193d0462865ef /drivers/net/wireless/brcm80211/brcmfmac/usb.c
parentc4fdb05696f315f43eb44c2a44fec1677ba47b31 (diff)
brcmfmac: Add tx flow control on net if queue for USB.
Enable tx flow control for USB host interface. Reviewed-by: Arend Van Spriel <arend@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>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/usb.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c61
1 files changed, 36 insertions, 25 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 7fe68aa69dfd..8aab2a22d6a1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -119,9 +119,8 @@ struct brcmf_usbdev_info {
119 int rx_low_watermark; 119 int rx_low_watermark;
120 int tx_low_watermark; 120 int tx_low_watermark;
121 int tx_high_watermark; 121 int tx_high_watermark;
122 bool txoff; 122 int tx_freecount;
123 bool rxoff; 123 bool tx_flowblock;
124 bool txoverride;
125 124
126 struct brcmf_usbreq *tx_reqs; 125 struct brcmf_usbreq *tx_reqs;
127 struct brcmf_usbreq *rx_reqs; 126 struct brcmf_usbreq *rx_reqs;
@@ -179,14 +178,6 @@ static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev)
179 return brcmf_usb_get_buspub(dev)->devinfo; 178 return brcmf_usb_get_buspub(dev)->devinfo;
180} 179}
181 180
182#if 0
183static void
184brcmf_usb_txflowcontrol(struct brcmf_usbdev_info *devinfo, bool onoff)
185{
186 dhd_txflowcontrol(devinfo->bus_pub.netdev, 0, onoff);
187}
188#endif
189
190static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo, 181static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo,
191 uint *condition, bool *pending) 182 uint *condition, bool *pending)
192{ 183{
@@ -420,7 +411,7 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
420} 411}
421 412
422static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo, 413static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo,
423 struct list_head *q) 414 struct list_head *q, int *counter)
424{ 415{
425 unsigned long flags; 416 unsigned long flags;
426 struct brcmf_usbreq *req; 417 struct brcmf_usbreq *req;
@@ -431,17 +422,22 @@ static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo,
431 } 422 }
432 req = list_entry(q->next, struct brcmf_usbreq, list); 423 req = list_entry(q->next, struct brcmf_usbreq, list);
433 list_del_init(q->next); 424 list_del_init(q->next);
425 if (counter)
426 (*counter)--;
434 spin_unlock_irqrestore(&devinfo->qlock, flags); 427 spin_unlock_irqrestore(&devinfo->qlock, flags);
435 return req; 428 return req;
436 429
437} 430}
438 431
439static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo, 432static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo,
440 struct list_head *q, struct brcmf_usbreq *req) 433 struct list_head *q, struct brcmf_usbreq *req,
434 int *counter)
441{ 435{
442 unsigned long flags; 436 unsigned long flags;
443 spin_lock_irqsave(&devinfo->qlock, flags); 437 spin_lock_irqsave(&devinfo->qlock, flags);
444 list_add_tail(&req->list, q); 438 list_add_tail(&req->list, q);
439 if (counter)
440 (*counter)++;
445 spin_unlock_irqrestore(&devinfo->qlock, flags); 441 spin_unlock_irqrestore(&devinfo->qlock, flags);
446} 442}
447 443
@@ -523,8 +519,12 @@ static void brcmf_usb_tx_complete(struct urb *urb)
523 519
524 brcmu_pkt_buf_free_skb(req->skb); 520 brcmu_pkt_buf_free_skb(req->skb);
525 req->skb = NULL; 521 req->skb = NULL;
526 brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); 522 brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount);
527 523 if (devinfo->tx_freecount > devinfo->tx_high_watermark &&
524 devinfo->tx_flowblock) {
525 brcmf_txflowblock(devinfo->dev, false);
526 devinfo->tx_flowblock = false;
527 }
528} 528}
529 529
530static void brcmf_usb_rx_complete(struct urb *urb) 530static void brcmf_usb_rx_complete(struct urb *urb)
@@ -543,7 +543,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
543 } else { 543 } else {
544 devinfo->bus_pub.bus->dstats.rx_errors++; 544 devinfo->bus_pub.bus->dstats.rx_errors++;
545 brcmu_pkt_buf_free_skb(skb); 545 brcmu_pkt_buf_free_skb(skb);
546 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); 546 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
547 return; 547 return;
548 } 548 }
549 549
@@ -552,7 +552,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
552 if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) { 552 if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
553 brcmf_dbg(ERROR, "rx protocol error\n"); 553 brcmf_dbg(ERROR, "rx protocol error\n");
554 brcmu_pkt_buf_free_skb(skb); 554 brcmu_pkt_buf_free_skb(skb);
555 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); 555 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
556 devinfo->bus_pub.bus->dstats.rx_errors++; 556 devinfo->bus_pub.bus->dstats.rx_errors++;
557 } else { 557 } else {
558 brcmf_rx_packet(devinfo->dev, ifidx, skb); 558 brcmf_rx_packet(devinfo->dev, ifidx, skb);
@@ -560,7 +560,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
560 } 560 }
561 } else { 561 } else {
562 brcmu_pkt_buf_free_skb(skb); 562 brcmu_pkt_buf_free_skb(skb);
563 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); 563 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
564 } 564 }
565 return; 565 return;
566 566
@@ -577,7 +577,7 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
577 577
578 skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu); 578 skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu);
579 if (!skb) { 579 if (!skb) {
580 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); 580 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
581 return; 581 return;
582 } 582 }
583 req->skb = skb; 583 req->skb = skb;
@@ -586,14 +586,14 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
586 skb->data, skb_tailroom(skb), brcmf_usb_rx_complete, 586 skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
587 req); 587 req);
588 req->devinfo = devinfo; 588 req->devinfo = devinfo;
589 brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); 589 brcmf_usb_enq(devinfo, &devinfo->rx_postq, req, NULL);
590 590
591 ret = usb_submit_urb(req->urb, GFP_ATOMIC); 591 ret = usb_submit_urb(req->urb, GFP_ATOMIC);
592 if (ret) { 592 if (ret) {
593 brcmf_usb_del_fromq(devinfo, req); 593 brcmf_usb_del_fromq(devinfo, req);
594 brcmu_pkt_buf_free_skb(req->skb); 594 brcmu_pkt_buf_free_skb(req->skb);
595 req->skb = NULL; 595 req->skb = NULL;
596 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); 596 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
597 } 597 }
598 return; 598 return;
599} 599}
@@ -606,7 +606,7 @@ static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
606 brcmf_dbg(ERROR, "bus is not up\n"); 606 brcmf_dbg(ERROR, "bus is not up\n");
607 return; 607 return;
608 } 608 }
609 while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq)) != NULL) 609 while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq, NULL)) != NULL)
610 brcmf_usb_rx_refill(devinfo, req); 610 brcmf_usb_rx_refill(devinfo, req);
611} 611}
612 612
@@ -684,7 +684,8 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
684 return -EIO; 684 return -EIO;
685 } 685 }
686 686
687 req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq); 687 req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
688 &devinfo->tx_freecount);
688 if (!req) { 689 if (!req) {
689 brcmu_pkt_buf_free_skb(skb); 690 brcmu_pkt_buf_free_skb(skb);
690 brcmf_dbg(ERROR, "no req to send\n"); 691 brcmf_dbg(ERROR, "no req to send\n");
@@ -696,14 +697,21 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
696 usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe, 697 usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
697 skb->data, skb->len, brcmf_usb_tx_complete, req); 698 skb->data, skb->len, brcmf_usb_tx_complete, req);
698 req->urb->transfer_flags |= URB_ZERO_PACKET; 699 req->urb->transfer_flags |= URB_ZERO_PACKET;
699 brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); 700 brcmf_usb_enq(devinfo, &devinfo->tx_postq, req, NULL);
700 ret = usb_submit_urb(req->urb, GFP_ATOMIC); 701 ret = usb_submit_urb(req->urb, GFP_ATOMIC);
701 if (ret) { 702 if (ret) {
702 brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n"); 703 brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n");
703 brcmf_usb_del_fromq(devinfo, req); 704 brcmf_usb_del_fromq(devinfo, req);
704 brcmu_pkt_buf_free_skb(req->skb); 705 brcmu_pkt_buf_free_skb(req->skb);
705 req->skb = NULL; 706 req->skb = NULL;
706 brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); 707 brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
708 &devinfo->tx_freecount);
709 } else {
710 if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
711 !devinfo->tx_flowblock) {
712 brcmf_txflowblock(dev, true);
713 devinfo->tx_flowblock = true;
714 }
707 } 715 }
708 716
709 return ret; 717 return ret;
@@ -1316,6 +1324,8 @@ struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev)
1316 INIT_LIST_HEAD(&devinfo->tx_freeq); 1324 INIT_LIST_HEAD(&devinfo->tx_freeq);
1317 INIT_LIST_HEAD(&devinfo->tx_postq); 1325 INIT_LIST_HEAD(&devinfo->tx_postq);
1318 1326
1327 devinfo->tx_flowblock = false;
1328
1319 devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq); 1329 devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq);
1320 if (!devinfo->rx_reqs) 1330 if (!devinfo->rx_reqs)
1321 goto error; 1331 goto error;
@@ -1323,6 +1333,7 @@ struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev)
1323 devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq); 1333 devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq);
1324 if (!devinfo->tx_reqs) 1334 if (!devinfo->tx_reqs)
1325 goto error; 1335 goto error;
1336 devinfo->tx_freecount = ntxq;
1326 1337
1327 devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC); 1338 devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC);
1328 if (!devinfo->intr_urb) { 1339 if (!devinfo->intr_urb) {