aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2010-03-29 06:37:15 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-03-31 14:46:39 -0400
commit6335ed0ff8670e6378da41191ab8bda33d1b7ac8 (patch)
tree345a5ba1c2bb8c602343d196f577b2d714d4f711 /drivers/net/wireless
parentd5a4c5e3afb9697c8f627b2563f4b8583ef88498 (diff)
ath9k_htc: Simplify RX URB management
This patch introduces the usage of URB anchors, thus reducing a large amount of code dealing with URB maintenance within the driver. The RX callback now takes care of freeing the SKB associated with each URB. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c125
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.h7
2 files changed, 50 insertions, 82 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index fc4f6e8c9ef3..e584a2912993 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -299,6 +299,8 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
299 ret = hif_usb_send_regout(hif_dev, skb); 299 ret = hif_usb_send_regout(hif_dev, skb);
300 break; 300 break;
301 default: 301 default:
302 dev_err(&hif_dev->udev->dev,
303 "ath9k_htc: Invalid TX pipe: %d\n", pipe_id);
302 ret = -EINVAL; 304 ret = -EINVAL;
303 break; 305 break;
304 } 306 }
@@ -408,14 +410,11 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
408 } 410 }
409 } else { 411 } else {
410 RX_STAT_INC(skb_dropped); 412 RX_STAT_INC(skb_dropped);
411 dev_kfree_skb_any(skb);
412 return; 413 return;
413 } 414 }
414 } 415 }
415 416
416err: 417err:
417 dev_kfree_skb_any(skb);
418
419 for (i = 0; i < pool_index; i++) { 418 for (i = 0; i < pool_index; i++) {
420 ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], 419 ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
421 skb_pool[i]->len, USB_WLAN_RX_PIPE); 420 skb_pool[i]->len, USB_WLAN_RX_PIPE);
@@ -426,11 +425,13 @@ err:
426static void ath9k_hif_usb_rx_cb(struct urb *urb) 425static void ath9k_hif_usb_rx_cb(struct urb *urb)
427{ 426{
428 struct sk_buff *skb = (struct sk_buff *) urb->context; 427 struct sk_buff *skb = (struct sk_buff *) urb->context;
429 struct sk_buff *nskb;
430 struct hif_device_usb *hif_dev = (struct hif_device_usb *) 428 struct hif_device_usb *hif_dev = (struct hif_device_usb *)
431 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); 429 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
432 int ret; 430 int ret;
433 431
432 if (!skb)
433 return;
434
434 if (!hif_dev) 435 if (!hif_dev)
435 goto free; 436 goto free;
436 437
@@ -448,34 +449,19 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
448 449
449 if (likely(urb->actual_length != 0)) { 450 if (likely(urb->actual_length != 0)) {
450 skb_put(skb, urb->actual_length); 451 skb_put(skb, urb->actual_length);
451
452 nskb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_ATOMIC);
453 if (!nskb)
454 goto resubmit;
455
456 usb_fill_bulk_urb(urb, hif_dev->udev,
457 usb_rcvbulkpipe(hif_dev->udev,
458 USB_WLAN_RX_PIPE),
459 nskb->data, MAX_RX_BUF_SIZE,
460 ath9k_hif_usb_rx_cb, nskb);
461
462 ret = usb_submit_urb(urb, GFP_ATOMIC);
463 if (ret) {
464 dev_kfree_skb_any(nskb);
465 goto free;
466 }
467
468 ath9k_hif_usb_rx_stream(hif_dev, skb); 452 ath9k_hif_usb_rx_stream(hif_dev, skb);
469 return;
470 } 453 }
471 454
472resubmit: 455resubmit:
473 skb_reset_tail_pointer(skb); 456 skb_reset_tail_pointer(skb);
474 skb_trim(skb, 0); 457 skb_trim(skb, 0);
475 458
459 usb_anchor_urb(urb, &hif_dev->rx_submitted);
476 ret = usb_submit_urb(urb, GFP_ATOMIC); 460 ret = usb_submit_urb(urb, GFP_ATOMIC);
477 if (ret) 461 if (ret) {
462 usb_unanchor_urb(urb);
478 goto free; 463 goto free;
464 }
479 465
480 return; 466 return;
481free: 467free:
@@ -490,6 +476,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
490 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); 476 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
491 int ret; 477 int ret;
492 478
479 if (!skb)
480 return;
481
493 if (!hif_dev) 482 if (!hif_dev)
494 goto free; 483 goto free;
495 484
@@ -540,6 +529,7 @@ resubmit:
540 return; 529 return;
541free: 530free:
542 dev_kfree_skb_any(skb); 531 dev_kfree_skb_any(skb);
532 urb->context = NULL;
543} 533}
544 534
545static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) 535static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
@@ -609,78 +599,59 @@ err:
609 return -ENOMEM; 599 return -ENOMEM;
610} 600}
611 601
612static void ath9k_hif_usb_dealloc_rx_skbs(struct hif_device_usb *hif_dev)
613{
614 int i;
615
616 for (i = 0; i < MAX_RX_URB_NUM; i++) {
617 if (hif_dev->wlan_rx_data_urb[i]) {
618 if (hif_dev->wlan_rx_data_urb[i]->transfer_buffer)
619 dev_kfree_skb_any((void *)
620 hif_dev->wlan_rx_data_urb[i]->context);
621 }
622 }
623}
624
625static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) 602static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
626{ 603{
627 int i; 604 usb_kill_anchored_urbs(&hif_dev->rx_submitted);
628
629 for (i = 0; i < MAX_RX_URB_NUM; i++) {
630 if (hif_dev->wlan_rx_data_urb[i]) {
631 usb_kill_urb(hif_dev->wlan_rx_data_urb[i]);
632 usb_free_urb(hif_dev->wlan_rx_data_urb[i]);
633 hif_dev->wlan_rx_data_urb[i] = NULL;
634 }
635 }
636}
637
638static int ath9k_hif_usb_prep_rx_urb(struct hif_device_usb *hif_dev,
639 struct urb *urb)
640{
641 struct sk_buff *skb;
642
643 skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL);
644 if (!skb)
645 return -ENOMEM;
646
647 usb_fill_bulk_urb(urb, hif_dev->udev,
648 usb_rcvbulkpipe(hif_dev->udev, USB_WLAN_RX_PIPE),
649 skb->data, MAX_RX_BUF_SIZE,
650 ath9k_hif_usb_rx_cb, skb);
651 return 0;
652} 605}
653 606
654static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) 607static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
655{ 608{
609 struct urb *urb = NULL;
610 struct sk_buff *skb = NULL;
656 int i, ret; 611 int i, ret;
657 612
613 init_usb_anchor(&hif_dev->rx_submitted);
614
658 for (i = 0; i < MAX_RX_URB_NUM; i++) { 615 for (i = 0; i < MAX_RX_URB_NUM; i++) {
659 616
660 /* Allocate URB */ 617 /* Allocate URB */
661 hif_dev->wlan_rx_data_urb[i] = usb_alloc_urb(0, GFP_KERNEL); 618 urb = usb_alloc_urb(0, GFP_KERNEL);
662 if (hif_dev->wlan_rx_data_urb[i] == NULL) { 619 if (urb == NULL) {
663 ret = -ENOMEM; 620 ret = -ENOMEM;
664 goto err_rx_urb; 621 goto err_urb;
665 } 622 }
666 623
667 /* Allocate buffer */ 624 /* Allocate buffer */
668 ret = ath9k_hif_usb_prep_rx_urb(hif_dev, 625 skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL);
669 hif_dev->wlan_rx_data_urb[i]); 626 if (!skb) {
670 if (ret) 627 ret = -ENOMEM;
671 goto err_rx_urb; 628 goto err_skb;
629 }
672 630
673 /* Submit URB */ 631 usb_fill_bulk_urb(urb, hif_dev->udev,
674 ret = usb_submit_urb(hif_dev->wlan_rx_data_urb[i], GFP_KERNEL); 632 usb_rcvbulkpipe(hif_dev->udev,
675 if (ret) 633 USB_WLAN_RX_PIPE),
676 goto err_rx_urb; 634 skb->data, MAX_RX_BUF_SIZE,
635 ath9k_hif_usb_rx_cb, skb);
677 636
637 /* Anchor URB */
638 usb_anchor_urb(urb, &hif_dev->rx_submitted);
639
640 /* Submit URB */
641 ret = usb_submit_urb(urb, GFP_KERNEL);
642 if (ret) {
643 usb_unanchor_urb(urb);
644 goto err_submit;
645 }
678 } 646 }
679 647
680 return 0; 648 return 0;
681 649
682err_rx_urb: 650err_submit:
683 ath9k_hif_usb_dealloc_rx_skbs(hif_dev); 651 dev_kfree_skb_any(skb);
652err_skb:
653 usb_free_urb(urb);
654err_urb:
684 ath9k_hif_usb_dealloc_rx_urbs(hif_dev); 655 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
685 return ret; 656 return ret;
686} 657}
@@ -689,6 +660,8 @@ static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev)
689{ 660{
690 if (hif_dev->reg_in_urb) { 661 if (hif_dev->reg_in_urb) {
691 usb_kill_urb(hif_dev->reg_in_urb); 662 usb_kill_urb(hif_dev->reg_in_urb);
663 if (hif_dev->reg_in_urb->context)
664 dev_kfree_skb_any((void *)hif_dev->reg_in_urb->context);
692 usb_free_urb(hif_dev->reg_in_urb); 665 usb_free_urb(hif_dev->reg_in_urb);
693 hif_dev->reg_in_urb = NULL; 666 hif_dev->reg_in_urb = NULL;
694 } 667 }
@@ -712,12 +685,10 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev)
712 ath9k_hif_usb_reg_in_cb, skb, 1); 685 ath9k_hif_usb_reg_in_cb, skb, 1);
713 686
714 if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) 687 if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0)
715 goto err_skb; 688 goto err;
716 689
717 return 0; 690 return 0;
718 691
719err_skb:
720 dev_kfree_skb_any(skb);
721err: 692err:
722 ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); 693 ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
723 return -ENOMEM; 694 return -ENOMEM;
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 7cc3762a6789..ea9257bdc411 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -85,18 +85,15 @@ struct hif_device_usb {
85 struct usb_interface *interface; 85 struct usb_interface *interface;
86 const struct firmware *firmware; 86 const struct firmware *firmware;
87 struct htc_target *htc_handle; 87 struct htc_target *htc_handle;
88 u8 flags;
89
90 struct hif_usb_tx tx; 88 struct hif_usb_tx tx;
91
92 struct urb *wlan_rx_data_urb[MAX_RX_URB_NUM];
93 struct urb *reg_in_urb; 89 struct urb *reg_in_urb;
94 90 struct usb_anchor rx_submitted;
95 struct sk_buff *remain_skb; 91 struct sk_buff *remain_skb;
96 int rx_remain_len; 92 int rx_remain_len;
97 int rx_pkt_len; 93 int rx_pkt_len;
98 int rx_transfer_len; 94 int rx_transfer_len;
99 int rx_pad_len; 95 int rx_pad_len;
96 u8 flags; /* HIF_USB_* */
100}; 97};
101 98
102int ath9k_hif_usb_init(void); 99int ath9k_hif_usb_init(void);