aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c116
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.h1
2 files changed, 108 insertions, 9 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 7fae79d16665..3b0efab65131 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -78,7 +78,7 @@ static void hif_usb_regout_cb(struct urb *urb)
78 78
79 if (cmd) { 79 if (cmd) {
80 ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, 80 ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
81 cmd->skb, 1); 81 cmd->skb, true);
82 kfree(cmd); 82 kfree(cmd);
83 } 83 }
84 84
@@ -124,6 +124,90 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
124 return ret; 124 return ret;
125} 125}
126 126
127static void hif_usb_mgmt_cb(struct urb *urb)
128{
129 struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
130 struct hif_device_usb *hif_dev = cmd->hif_dev;
131 bool txok = true;
132
133 if (!cmd || !cmd->skb || !cmd->hif_dev)
134 return;
135
136 switch (urb->status) {
137 case 0:
138 break;
139 case -ENOENT:
140 case -ECONNRESET:
141 case -ENODEV:
142 case -ESHUTDOWN:
143 txok = false;
144
145 /*
146 * If the URBs are being flushed, no need to complete
147 * this packet.
148 */
149 spin_lock(&hif_dev->tx.tx_lock);
150 if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
151 spin_unlock(&hif_dev->tx.tx_lock);
152 dev_kfree_skb_any(cmd->skb);
153 kfree(cmd);
154 return;
155 }
156 spin_unlock(&hif_dev->tx.tx_lock);
157
158 break;
159 default:
160 txok = false;
161 break;
162 }
163
164 skb_pull(cmd->skb, 4);
165 ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
166 cmd->skb, txok);
167 kfree(cmd);
168}
169
170static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev,
171 struct sk_buff *skb)
172{
173 struct urb *urb;
174 struct cmd_buf *cmd;
175 int ret = 0;
176 __le16 *hdr;
177
178 urb = usb_alloc_urb(0, GFP_ATOMIC);
179 if (urb == NULL)
180 return -ENOMEM;
181
182 cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
183 if (cmd == NULL) {
184 usb_free_urb(urb);
185 return -ENOMEM;
186 }
187
188 cmd->skb = skb;
189 cmd->hif_dev = hif_dev;
190
191 hdr = (__le16 *) skb_push(skb, 4);
192 *hdr++ = cpu_to_le16(skb->len - 4);
193 *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG);
194
195 usb_fill_bulk_urb(urb, hif_dev->udev,
196 usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE),
197 skb->data, skb->len,
198 hif_usb_mgmt_cb, cmd);
199
200 usb_anchor_urb(urb, &hif_dev->mgmt_submitted);
201 ret = usb_submit_urb(urb, GFP_ATOMIC);
202 if (ret) {
203 usb_unanchor_urb(urb);
204 kfree(cmd);
205 }
206 usb_free_urb(urb);
207
208 return ret;
209}
210
127static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, 211static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
128 struct sk_buff_head *list) 212 struct sk_buff_head *list)
129{ 213{
@@ -275,6 +359,7 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb)
275{ 359{
276 struct ath9k_htc_tx_ctl *tx_ctl; 360 struct ath9k_htc_tx_ctl *tx_ctl;
277 unsigned long flags; 361 unsigned long flags;
362 int ret = 0;
278 363
279 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); 364 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
280 365
@@ -289,25 +374,33 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb)
289 return -ENOMEM; 374 return -ENOMEM;
290 } 375 }
291 376
292 __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); 377 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
293 hif_dev->tx.tx_skb_cnt++;
294 378
295 tx_ctl = HTC_SKB_CB(skb); 379 tx_ctl = HTC_SKB_CB(skb);
296 380
297 /* Send normal/mgmt/beacon frames immediately */ 381 /* Mgmt/Beacon frames don't use the TX buffer pool */
298 if (tx_ctl->type != ATH9K_HTC_AMPDU) 382 if ((tx_ctl->type == ATH9K_HTC_MGMT) ||
299 __hif_usb_tx(hif_dev); 383 (tx_ctl->type == ATH9K_HTC_BEACON)) {
384 ret = hif_usb_send_mgmt(hif_dev, skb);
385 }
386
387 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
388
389 if ((tx_ctl->type == ATH9K_HTC_NORMAL) ||
390 (tx_ctl->type == ATH9K_HTC_AMPDU)) {
391 __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb);
392 hif_dev->tx.tx_skb_cnt++;
393 }
300 394
301 /* Check if AMPDUs have to be sent immediately */ 395 /* Check if AMPDUs have to be sent immediately */
302 if ((tx_ctl->type == ATH9K_HTC_AMPDU) && 396 if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
303 (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
304 (hif_dev->tx.tx_skb_cnt < 2)) { 397 (hif_dev->tx.tx_skb_cnt < 2)) {
305 __hif_usb_tx(hif_dev); 398 __hif_usb_tx(hif_dev);
306 } 399 }
307 400
308 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); 401 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
309 402
310 return 0; 403 return ret;
311} 404}
312 405
313static void hif_usb_start(void *hif_handle) 406static void hif_usb_start(void *hif_handle)
@@ -339,6 +432,8 @@ static void hif_usb_stop(void *hif_handle)
339 &hif_dev->tx.tx_pending, list) { 432 &hif_dev->tx.tx_pending, list) {
340 usb_kill_urb(tx_buf->urb); 433 usb_kill_urb(tx_buf->urb);
341 } 434 }
435
436 usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);
342} 437}
343 438
344static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) 439static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb)
@@ -657,6 +752,8 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
657 kfree(tx_buf->buf); 752 kfree(tx_buf->buf);
658 kfree(tx_buf); 753 kfree(tx_buf);
659 } 754 }
755
756 usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);
660} 757}
661 758
662static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) 759static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
@@ -668,6 +765,7 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
668 INIT_LIST_HEAD(&hif_dev->tx.tx_pending); 765 INIT_LIST_HEAD(&hif_dev->tx.tx_pending);
669 spin_lock_init(&hif_dev->tx.tx_lock); 766 spin_lock_init(&hif_dev->tx.tx_lock);
670 __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); 767 __skb_queue_head_init(&hif_dev->tx.tx_skb_queue);
768 init_usb_anchor(&hif_dev->mgmt_submitted);
671 769
672 for (i = 0; i < MAX_TX_URB_NUM; i++) { 770 for (i = 0; i < MAX_TX_URB_NUM; i++) {
673 tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); 771 tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL);
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 8b98d646e91a..f59df48a86e2 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -93,6 +93,7 @@ struct hif_device_usb {
93 struct usb_anchor regout_submitted; 93 struct usb_anchor regout_submitted;
94 struct usb_anchor rx_submitted; 94 struct usb_anchor rx_submitted;
95 struct usb_anchor reg_in_submitted; 95 struct usb_anchor reg_in_submitted;
96 struct usb_anchor mgmt_submitted;
96 struct sk_buff *remain_skb; 97 struct sk_buff *remain_skb;
97 const char *fw_name; 98 const char *fw_name;
98 int rx_remain_len; 99 int rx_remain_len;