aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r--net/mac80211/sta_info.c75
1 files changed, 21 insertions, 54 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index fb12cec4d333..ff0eb948917b 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -250,9 +250,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
250 * enable session_timer's data differentiation. refer to 250 * enable session_timer's data differentiation. refer to
251 * sta_rx_agg_session_timer_expired for useage */ 251 * sta_rx_agg_session_timer_expired for useage */
252 sta->timer_to_tid[i] = i; 252 sta->timer_to_tid[i] = i;
253 /* rx */
254 sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE;
255 sta->ampdu_mlme.tid_rx[i] = NULL;
256 /* tx */ 253 /* tx */
257 sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; 254 sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE;
258 sta->ampdu_mlme.tid_tx[i] = NULL; 255 sta->ampdu_mlme.tid_tx[i] = NULL;
@@ -619,7 +616,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
619 struct ieee80211_sub_if_data *sdata; 616 struct ieee80211_sub_if_data *sdata;
620 struct sk_buff *skb; 617 struct sk_buff *skb;
621 unsigned long flags; 618 unsigned long flags;
622 int ret, i; 619 int ret;
623 620
624 might_sleep(); 621 might_sleep();
625 622
@@ -629,6 +626,15 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
629 local = sta->local; 626 local = sta->local;
630 sdata = sta->sdata; 627 sdata = sta->sdata;
631 628
629 /*
630 * Before removing the station from the driver and
631 * rate control, it might still start new aggregation
632 * sessions -- block that to make sure the tear-down
633 * will be sufficient.
634 */
635 set_sta_flags(sta, WLAN_STA_BLOCK_BA);
636 ieee80211_sta_tear_down_BA_sessions(sta);
637
632 spin_lock_irqsave(&local->sta_lock, flags); 638 spin_lock_irqsave(&local->sta_lock, flags);
633 ret = sta_info_hash_del(local, sta); 639 ret = sta_info_hash_del(local, sta);
634 /* this might still be the pending list ... which is fine */ 640 /* this might still be the pending list ... which is fine */
@@ -645,9 +651,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
645 * may mean it is removed from hardware which requires that 651 * may mean it is removed from hardware which requires that
646 * the key->sta pointer is still valid, so flush the key todo 652 * the key->sta pointer is still valid, so flush the key todo
647 * list here. 653 * list here.
648 *
649 * ieee80211_key_todo() will synchronize_rcu() so after this
650 * nothing can reference this sta struct any more.
651 */ 654 */
652 ieee80211_key_todo(); 655 ieee80211_key_todo();
653 656
@@ -679,11 +682,17 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
679 sdata = sta->sdata; 682 sdata = sta->sdata;
680 } 683 }
681 684
685 /*
686 * At this point, after we wait for an RCU grace period,
687 * neither mac80211 nor the driver can reference this
688 * sta struct any more except by still existing timers
689 * associated with this station that we clean up below.
690 */
691 synchronize_rcu();
692
682#ifdef CONFIG_MAC80211_MESH 693#ifdef CONFIG_MAC80211_MESH
683 if (ieee80211_vif_is_mesh(&sdata->vif)) { 694 if (ieee80211_vif_is_mesh(&sdata->vif))
684 mesh_accept_plinks_update(sdata); 695 mesh_accept_plinks_update(sdata);
685 del_timer(&sta->plink_timer);
686 }
687#endif 696#endif
688 697
689#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 698#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -710,50 +719,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
710 while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) 719 while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL)
711 dev_kfree_skb_any(skb); 720 dev_kfree_skb_any(skb);
712 721
713 for (i = 0; i < STA_TID_NUM; i++) {
714 struct tid_ampdu_rx *tid_rx;
715 struct tid_ampdu_tx *tid_tx;
716
717 spin_lock_bh(&sta->lock);
718 tid_rx = sta->ampdu_mlme.tid_rx[i];
719 /* Make sure timer won't free the tid_rx struct, see below */
720 if (tid_rx)
721 tid_rx->shutdown = true;
722
723 spin_unlock_bh(&sta->lock);
724
725 /*
726 * Outside spinlock - shutdown is true now so that the timer
727 * won't free tid_rx, we have to do that now. Can't let the
728 * timer do it because we have to sync the timer outside the
729 * lock that it takes itself.
730 */
731 if (tid_rx) {
732 del_timer_sync(&tid_rx->session_timer);
733 kfree(tid_rx);
734 }
735
736 /*
737 * No need to do such complications for TX agg sessions, the
738 * path leading to freeing the tid_tx struct goes via a call
739 * from the driver, and thus needs to look up the sta struct
740 * again, which cannot be found when we get here. Hence, we
741 * just need to delete the timer and free the aggregation
742 * info; we won't be telling the peer about it then but that
743 * doesn't matter if we're not talking to it again anyway.
744 */
745 tid_tx = sta->ampdu_mlme.tid_tx[i];
746 if (tid_tx) {
747 del_timer_sync(&tid_tx->addba_resp_timer);
748 /*
749 * STA removed while aggregation session being
750 * started? Bit odd, but purge frames anyway.
751 */
752 skb_queue_purge(&tid_tx->pending);
753 kfree(tid_tx);
754 }
755 }
756
757 __sta_info_free(local, sta); 722 __sta_info_free(local, sta);
758 723
759 return 0; 724 return 0;
@@ -992,6 +957,8 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
992{ 957{
993 struct sta_info *sta = container_of(pubsta, struct sta_info, sta); 958 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
994 959
960 trace_api_sta_block_awake(sta->local, pubsta, block);
961
995 if (block) 962 if (block)
996 set_sta_flags(sta, WLAN_STA_PS_DRIVER); 963 set_sta_flags(sta, WLAN_STA_PS_DRIVER);
997 else 964 else