aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/carl9170
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2010-10-29 17:41:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:25:33 -0500
commit2a6cef513fab525399e484edc9bfb39b6d462f76 (patch)
tree3397cf07534825de557e53630eafda5ebc2193b8 /drivers/net/wireless/ath/carl9170
parente4a668c59080f862af3ecc28b359533027cbe434 (diff)
carl9170: stop stale uplink BA sessions
This patch fixes a possible lengthy stall if the device is operating as an experimental 11n AP and an STA [during heavy txrx action] suddenly signalized to go off-channel (old NetworkManager), or (sleep - which is unlikely, because then it wouldn't be *active* at all!?). Because the driver has to manage the BA Window, the sudden PSM transition can leave active uplink BA sessions to the STA in a bad state and a proper cleanup is needed. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/carl9170')
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index b575c865142d..b27969c41812 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -524,6 +524,59 @@ next:
524 } 524 }
525} 525}
526 526
527static void carl9170_tx_ampdu_timeout(struct ar9170 *ar)
528{
529 struct carl9170_sta_tid *iter;
530 struct sk_buff *skb;
531 struct ieee80211_tx_info *txinfo;
532 struct carl9170_tx_info *arinfo;
533 struct _carl9170_tx_superframe *super;
534 struct ieee80211_sta *sta;
535 struct ieee80211_vif *vif;
536 struct ieee80211_hdr *hdr;
537 unsigned int vif_id;
538
539 rcu_read_lock();
540 list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
541 if (iter->state < CARL9170_TID_STATE_IDLE)
542 continue;
543
544 spin_lock_bh(&iter->lock);
545 skb = skb_peek(&iter->queue);
546 if (!skb)
547 goto unlock;
548
549 txinfo = IEEE80211_SKB_CB(skb);
550 arinfo = (void *)txinfo->rate_driver_data;
551 if (time_is_after_jiffies(arinfo->timeout +
552 msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)))
553 goto unlock;
554
555 super = (void *) skb->data;
556 hdr = (void *) super->frame_data;
557
558 vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >>
559 CARL9170_TX_SUPER_MISC_VIF_ID_S;
560
561 if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC))
562 goto unlock;
563
564 vif = rcu_dereference(ar->vif_priv[vif_id].vif);
565 if (WARN_ON(!vif))
566 goto unlock;
567
568 sta = ieee80211_find_sta(vif, hdr->addr1);
569 if (WARN_ON(!sta))
570 goto unlock;
571
572 ieee80211_stop_tx_ba_session(sta, iter->tid);
573unlock:
574 spin_unlock_bh(&iter->lock);
575
576 }
577 rcu_read_unlock();
578}
579
527void carl9170_tx_janitor(struct work_struct *work) 580void carl9170_tx_janitor(struct work_struct *work)
528{ 581{
529 struct ar9170 *ar = container_of(work, struct ar9170, 582 struct ar9170 *ar = container_of(work, struct ar9170,
@@ -534,6 +587,7 @@ void carl9170_tx_janitor(struct work_struct *work)
534 ar->tx_janitor_last_run = jiffies; 587 ar->tx_janitor_last_run = jiffies;
535 588
536 carl9170_check_queue_stop_timeout(ar); 589 carl9170_check_queue_stop_timeout(ar);
590 carl9170_tx_ampdu_timeout(ar);
537 591
538 if (!atomic_read(&ar->tx_total_queued)) 592 if (!atomic_read(&ar->tx_total_queued))
539 return; 593 return;