diff options
Diffstat (limited to 'drivers/net/wireless/ath/ar9170/usb.c')
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 122 |
1 files changed, 97 insertions, 25 deletions
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index f752698669d2..754b1f8d8da9 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
@@ -96,7 +96,49 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
96 | }; | 96 | }; |
97 | MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); | 97 | MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); |
98 | 98 | ||
99 | static void ar9170_usb_tx_urb_complete_free(struct urb *urb) | 99 | static void ar9170_usb_submit_urb(struct ar9170_usb *aru) |
100 | { | ||
101 | struct urb *urb; | ||
102 | unsigned long flags; | ||
103 | int err; | ||
104 | |||
105 | if (unlikely(!IS_STARTED(&aru->common))) | ||
106 | return ; | ||
107 | |||
108 | spin_lock_irqsave(&aru->tx_urb_lock, flags); | ||
109 | if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) { | ||
110 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | ||
111 | return ; | ||
112 | } | ||
113 | aru->tx_submitted_urbs++; | ||
114 | |||
115 | urb = usb_get_from_anchor(&aru->tx_pending); | ||
116 | if (!urb) { | ||
117 | aru->tx_submitted_urbs--; | ||
118 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | ||
119 | |||
120 | return ; | ||
121 | } | ||
122 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | ||
123 | |||
124 | aru->tx_pending_urbs--; | ||
125 | usb_anchor_urb(urb, &aru->tx_submitted); | ||
126 | |||
127 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
128 | if (unlikely(err)) { | ||
129 | if (ar9170_nag_limiter(&aru->common)) | ||
130 | dev_err(&aru->udev->dev, "submit_urb failed (%d).\n", | ||
131 | err); | ||
132 | |||
133 | usb_unanchor_urb(urb); | ||
134 | aru->tx_submitted_urbs--; | ||
135 | ar9170_tx_callback(&aru->common, urb->context); | ||
136 | } | ||
137 | |||
138 | usb_free_urb(urb); | ||
139 | } | ||
140 | |||
141 | static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) | ||
100 | { | 142 | { |
101 | struct sk_buff *skb = urb->context; | 143 | struct sk_buff *skb = urb->context; |
102 | struct ar9170_usb *aru = (struct ar9170_usb *) | 144 | struct ar9170_usb *aru = (struct ar9170_usb *) |
@@ -107,8 +149,11 @@ static void ar9170_usb_tx_urb_complete_free(struct urb *urb) | |||
107 | return ; | 149 | return ; |
108 | } | 150 | } |
109 | 151 | ||
110 | ar9170_handle_tx_status(&aru->common, skb, false, | 152 | aru->tx_submitted_urbs--; |
111 | AR9170_TX_STATUS_COMPLETE); | 153 | |
154 | ar9170_tx_callback(&aru->common, skb); | ||
155 | |||
156 | ar9170_usb_submit_urb(aru); | ||
112 | } | 157 | } |
113 | 158 | ||
114 | static void ar9170_usb_tx_urb_complete(struct urb *urb) | 159 | static void ar9170_usb_tx_urb_complete(struct urb *urb) |
@@ -290,21 +335,47 @@ err_out: | |||
290 | return err; | 335 | return err; |
291 | } | 336 | } |
292 | 337 | ||
293 | static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) | 338 | static int ar9170_usb_flush(struct ar9170 *ar) |
294 | { | 339 | { |
295 | int ret; | 340 | struct ar9170_usb *aru = (void *) ar; |
341 | struct urb *urb; | ||
342 | int ret, err = 0; | ||
296 | 343 | ||
297 | aru->common.state = AR9170_UNKNOWN_STATE; | 344 | if (IS_STARTED(ar)) |
345 | aru->common.state = AR9170_IDLE; | ||
298 | 346 | ||
299 | usb_unlink_anchored_urbs(&aru->tx_submitted); | 347 | usb_wait_anchor_empty_timeout(&aru->tx_pending, |
348 | msecs_to_jiffies(800)); | ||
349 | while ((urb = usb_get_from_anchor(&aru->tx_pending))) { | ||
350 | ar9170_tx_callback(&aru->common, (void *) urb->context); | ||
351 | usb_free_urb(urb); | ||
352 | } | ||
300 | 353 | ||
301 | /* give the LED OFF command and the deauth frame a chance to air. */ | 354 | /* lets wait a while until the tx - queues are dried out */ |
302 | ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, | 355 | ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, |
303 | msecs_to_jiffies(100)); | 356 | msecs_to_jiffies(100)); |
304 | if (ret == 0) | 357 | if (ret == 0) |
305 | dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); | 358 | err = -ETIMEDOUT; |
306 | usb_poison_anchored_urbs(&aru->tx_submitted); | 359 | |
360 | usb_kill_anchored_urbs(&aru->tx_submitted); | ||
361 | |||
362 | if (IS_ACCEPTING_CMD(ar)) | ||
363 | aru->common.state = AR9170_STARTED; | ||
364 | |||
365 | return err; | ||
366 | } | ||
367 | |||
368 | static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) | ||
369 | { | ||
370 | int err; | ||
307 | 371 | ||
372 | aru->common.state = AR9170_UNKNOWN_STATE; | ||
373 | |||
374 | err = ar9170_usb_flush(&aru->common); | ||
375 | if (err) | ||
376 | dev_err(&aru->udev->dev, "stuck tx urbs!\n"); | ||
377 | |||
378 | usb_poison_anchored_urbs(&aru->tx_submitted); | ||
308 | usb_poison_anchored_urbs(&aru->rx_submitted); | 379 | usb_poison_anchored_urbs(&aru->rx_submitted); |
309 | } | 380 | } |
310 | 381 | ||
@@ -388,12 +459,10 @@ err_free: | |||
388 | return err; | 459 | return err; |
389 | } | 460 | } |
390 | 461 | ||
391 | static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb, | 462 | static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) |
392 | bool txstatus_needed, unsigned int extra_len) | ||
393 | { | 463 | { |
394 | struct ar9170_usb *aru = (struct ar9170_usb *) ar; | 464 | struct ar9170_usb *aru = (struct ar9170_usb *) ar; |
395 | struct urb *urb; | 465 | struct urb *urb; |
396 | int err; | ||
397 | 466 | ||
398 | if (unlikely(!IS_STARTED(ar))) { | 467 | if (unlikely(!IS_STARTED(ar))) { |
399 | /* Seriously, what were you drink... err... thinking!? */ | 468 | /* Seriously, what were you drink... err... thinking!? */ |
@@ -406,18 +475,17 @@ static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb, | |||
406 | 475 | ||
407 | usb_fill_bulk_urb(urb, aru->udev, | 476 | usb_fill_bulk_urb(urb, aru->udev, |
408 | usb_sndbulkpipe(aru->udev, AR9170_EP_TX), | 477 | usb_sndbulkpipe(aru->udev, AR9170_EP_TX), |
409 | skb->data, skb->len + extra_len, (txstatus_needed ? | 478 | skb->data, skb->len, |
410 | ar9170_usb_tx_urb_complete : | 479 | ar9170_usb_tx_urb_complete_frame, skb); |
411 | ar9170_usb_tx_urb_complete_free), skb); | ||
412 | urb->transfer_flags |= URB_ZERO_PACKET; | 480 | urb->transfer_flags |= URB_ZERO_PACKET; |
413 | 481 | ||
414 | usb_anchor_urb(urb, &aru->tx_submitted); | 482 | usb_anchor_urb(urb, &aru->tx_pending); |
415 | err = usb_submit_urb(urb, GFP_ATOMIC); | 483 | aru->tx_pending_urbs++; |
416 | if (unlikely(err)) | ||
417 | usb_unanchor_urb(urb); | ||
418 | 484 | ||
419 | usb_free_urb(urb); | 485 | usb_free_urb(urb); |
420 | return err; | 486 | |
487 | ar9170_usb_submit_urb(aru); | ||
488 | return 0; | ||
421 | } | 489 | } |
422 | 490 | ||
423 | static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) | 491 | static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) |
@@ -617,10 +685,8 @@ static void ar9170_usb_stop(struct ar9170 *ar) | |||
617 | if (IS_ACCEPTING_CMD(ar)) | 685 | if (IS_ACCEPTING_CMD(ar)) |
618 | aru->common.state = AR9170_STOPPED; | 686 | aru->common.state = AR9170_STOPPED; |
619 | 687 | ||
620 | /* lets wait a while until the tx - queues are dried out */ | 688 | ret = ar9170_usb_flush(ar); |
621 | ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, | 689 | if (ret) |
622 | msecs_to_jiffies(1000)); | ||
623 | if (ret == 0) | ||
624 | dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); | 690 | dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); |
625 | 691 | ||
626 | usb_poison_anchored_urbs(&aru->tx_submitted); | 692 | usb_poison_anchored_urbs(&aru->tx_submitted); |
@@ -716,10 +782,16 @@ static int ar9170_usb_probe(struct usb_interface *intf, | |||
716 | SET_IEEE80211_DEV(ar->hw, &udev->dev); | 782 | SET_IEEE80211_DEV(ar->hw, &udev->dev); |
717 | 783 | ||
718 | init_usb_anchor(&aru->rx_submitted); | 784 | init_usb_anchor(&aru->rx_submitted); |
785 | init_usb_anchor(&aru->tx_pending); | ||
719 | init_usb_anchor(&aru->tx_submitted); | 786 | init_usb_anchor(&aru->tx_submitted); |
720 | init_completion(&aru->cmd_wait); | 787 | init_completion(&aru->cmd_wait); |
788 | spin_lock_init(&aru->tx_urb_lock); | ||
789 | |||
790 | aru->tx_pending_urbs = 0; | ||
791 | aru->tx_submitted_urbs = 0; | ||
721 | 792 | ||
722 | aru->common.stop = ar9170_usb_stop; | 793 | aru->common.stop = ar9170_usb_stop; |
794 | aru->common.flush = ar9170_usb_flush; | ||
723 | aru->common.open = ar9170_usb_open; | 795 | aru->common.open = ar9170_usb_open; |
724 | aru->common.tx = ar9170_usb_tx; | 796 | aru->common.tx = ar9170_usb_tx; |
725 | aru->common.exec_cmd = ar9170_usb_exec_cmd; | 797 | aru->common.exec_cmd = ar9170_usb_exec_cmd; |