diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2010-03-29 06:37:15 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-03-31 14:46:39 -0400 |
commit | 6335ed0ff8670e6378da41191ab8bda33d1b7ac8 (patch) | |
tree | 345a5ba1c2bb8c602343d196f577b2d714d4f711 /drivers/net/wireless | |
parent | d5a4c5e3afb9697c8f627b2563f4b8583ef88498 (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.c | 125 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hif_usb.h | 7 |
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 | ||
416 | err: | 417 | err: |
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: | |||
426 | static void ath9k_hif_usb_rx_cb(struct urb *urb) | 425 | static 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 | ||
472 | resubmit: | 455 | resubmit: |
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; |
481 | free: | 467 | free: |
@@ -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; |
541 | free: | 530 | free: |
542 | dev_kfree_skb_any(skb); | 531 | dev_kfree_skb_any(skb); |
532 | urb->context = NULL; | ||
543 | } | 533 | } |
544 | 534 | ||
545 | static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) | 535 | static 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 | ||
612 | static 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 | |||
625 | static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) | 602 | static 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 | |||
638 | static 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 | ||
654 | static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) | 607 | static 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 | ||
682 | err_rx_urb: | 650 | err_submit: |
683 | ath9k_hif_usb_dealloc_rx_skbs(hif_dev); | 651 | dev_kfree_skb_any(skb); |
652 | err_skb: | ||
653 | usb_free_urb(urb); | ||
654 | err_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 | ||
719 | err_skb: | ||
720 | dev_kfree_skb_any(skb); | ||
721 | err: | 692 | err: |
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 | ||
102 | int ath9k_hif_usb_init(void); | 99 | int ath9k_hif_usb_init(void); |