ath9k_htc: Increase URB count for REG_IN pipe
authorSujith Manoharan <Sujith.Manoharan@atheros.com>
Wed, 13 Apr 2011 05:55:23 +0000 (11:25 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 13 Apr 2011 19:23:35 +0000 (15:23 -0400)
Using a single URB for receiving WMI events is
insufficient, increase it to 64 to not lose
WMI events in high throughput situations.

Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/hif_usb.h

index e252576760d1c8e127b4d617f34054abfce9a496..0b63a48462c7d8cabb73c601800dc2829a83bc12 100644 (file)
@@ -566,6 +566,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
        case -ESHUTDOWN:
                goto free;
        default:
+               skb_reset_tail_pointer(skb);
+               skb_trim(skb, 0);
+
                goto resubmit;
        }
 
@@ -590,23 +593,15 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
                                                 USB_REG_IN_PIPE),
                                 nskb->data, MAX_REG_IN_BUF_SIZE,
                                 ath9k_hif_usb_reg_in_cb, nskb);
-
-               ret = usb_submit_urb(urb, GFP_ATOMIC);
-               if (ret) {
-                       kfree_skb(nskb);
-                       urb->context = NULL;
-               }
-
-               return;
        }
 
 resubmit:
-       skb_reset_tail_pointer(skb);
-       skb_trim(skb, 0);
-
+       usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
        ret = usb_submit_urb(urb, GFP_ATOMIC);
-       if (ret)
+       if (ret) {
+               usb_unanchor_urb(urb);
                goto free;
+       }
 
        return;
 free:
@@ -747,43 +742,67 @@ err_urb:
        return ret;
 }
 
-static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev)
+static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev)
 {
-       if (hif_dev->reg_in_urb) {
-               usb_kill_urb(hif_dev->reg_in_urb);
-               if (hif_dev->reg_in_urb->context)
-                       kfree_skb((void *)hif_dev->reg_in_urb->context);
-               usb_free_urb(hif_dev->reg_in_urb);
-               hif_dev->reg_in_urb = NULL;
-       }
+       usb_kill_anchored_urbs(&hif_dev->reg_in_submitted);
 }
 
-static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev)
+static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)
 {
-       struct sk_buff *skb;
+       struct urb *urb = NULL;
+       struct sk_buff *skb = NULL;
+       int i, ret;
 
-       hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (hif_dev->reg_in_urb == NULL)
-               return -ENOMEM;
+       init_usb_anchor(&hif_dev->reg_in_submitted);
 
-       skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
-       if (!skb)
-               goto err;
+       for (i = 0; i < MAX_REG_IN_URB_NUM; i++) {
 
-       usb_fill_bulk_urb(hif_dev->reg_in_urb, hif_dev->udev,
-                        usb_rcvbulkpipe(hif_dev->udev,
-                                        USB_REG_IN_PIPE),
-                        skb->data, MAX_REG_IN_BUF_SIZE,
-                        ath9k_hif_usb_reg_in_cb, skb);
+               /* Allocate URB */
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (urb == NULL) {
+                       ret = -ENOMEM;
+                       goto err_urb;
+               }
 
-       if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0)
-               goto err;
+               /* Allocate buffer */
+               skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
+               if (!skb) {
+                       ret = -ENOMEM;
+                       goto err_skb;
+               }
+
+               usb_fill_bulk_urb(urb, hif_dev->udev,
+                                 usb_rcvbulkpipe(hif_dev->udev,
+                                                 USB_REG_IN_PIPE),
+                                 skb->data, MAX_REG_IN_BUF_SIZE,
+                                 ath9k_hif_usb_reg_in_cb, skb);
+
+               /* Anchor URB */
+               usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
+
+               /* Submit URB */
+               ret = usb_submit_urb(urb, GFP_KERNEL);
+               if (ret) {
+                       usb_unanchor_urb(urb);
+                       goto err_submit;
+               }
+
+               /*
+                * Drop reference count.
+                * This ensures that the URB is freed when killing them.
+                */
+               usb_free_urb(urb);
+       }
 
        return 0;
 
-err:
-       ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
-       return -ENOMEM;
+err_submit:
+       kfree_skb(skb);
+err_skb:
+       usb_free_urb(urb);
+err_urb:
+       ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
+       return ret;
 }
 
 static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
@@ -800,7 +819,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
                goto err_rx;
 
        /* Register Read */
-       if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0)
+       if (ath9k_hif_usb_alloc_reg_in_urbs(hif_dev) < 0)
                goto err_reg;
 
        return 0;
@@ -815,7 +834,7 @@ err:
 static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
 {
        usb_kill_anchored_urbs(&hif_dev->regout_submitted);
-       ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
+       ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
        ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
        ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
 }
index f82b32bbf4e24dc7f17d855f7bb0561a6405d543..8b98d646e91abb17397218a7ab0abb13b55e87dd 100644 (file)
@@ -40,7 +40,7 @@
 #define MAX_PKT_NUM_IN_TRANSFER 10
 
 #define MAX_REG_OUT_URB_NUM  1
-#define MAX_REG_OUT_BUF_NUM  8
+#define MAX_REG_IN_URB_NUM   64
 
 #define MAX_REG_IN_BUF_SIZE 64
 
@@ -90,9 +90,9 @@ struct hif_device_usb {
        const struct firmware *firmware;
        struct htc_target *htc_handle;
        struct hif_usb_tx tx;
-       struct urb *reg_in_urb;
        struct usb_anchor regout_submitted;
        struct usb_anchor rx_submitted;
+       struct usb_anchor reg_in_submitted;
        struct sk_buff *remain_skb;
        const char *fw_name;
        int rx_remain_len;