kfree(tid_rx);
}
-static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
- u16 initiator, u16 reason,
- bool from_timer)
+void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
+ u16 initiator, u16 reason)
{
struct ieee80211_local *local = sta->local;
struct tid_ampdu_rx *tid_rx;
- spin_lock_bh(&sta->lock);
+ lockdep_assert_held(&sta->lock);
tid_rx = sta->ampdu_mlme.tid_rx[tid];
- if (!tid_rx) {
- spin_unlock_bh(&sta->lock);
+ if (!tid_rx)
return;
- }
rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], NULL);
ieee80211_send_delba(sta->sdata, sta->sta.addr,
tid, 0, reason);
- spin_unlock_bh(&sta->lock);
-
- if (!from_timer)
- del_timer_sync(&tid_rx->session_timer);
+ del_timer_sync(&tid_rx->session_timer);
call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
}
void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
u16 initiator, u16 reason)
{
- ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, false);
+ spin_lock_bh(&sta->lock);
+ ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason);
+ spin_unlock_bh(&sta->lock);
}
/*
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
#endif
- ___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT,
- WLAN_REASON_QSTA_TIMEOUT, true);
+ set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired);
+ ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
}
static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
spin_lock_bh(&sta->lock);
for (tid = 0; tid < STA_TID_NUM; tid++) {
+ if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired))
+ ___ieee80211_stop_rx_ba_session(
+ sta, tid, WLAN_BACK_RECIPIENT,
+ WLAN_REASON_QSTA_TIMEOUT);
+
tid_tx = sta->ampdu_mlme.tid_tx[tid];
if (!tid_tx)
continue;
enum ieee80211_smps_mode smps, const u8 *da,
const u8 *bssid);
+void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
+ u16 initiator, u16 reason);
void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
u16 initiator, u16 reason);
void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta);
* @addba_req_num: number of times addBA request has been sent.
* @dialog_token_allocator: dialog token enumerator for each new session;
* @work: work struct for starting/stopping aggregation
+ * @tid_rx_timer_expired: bitmap indicating on which TIDs the
+ * RX timer expired until the work for it runs
*/
struct sta_ampdu_mlme {
/* rx */
struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
+ unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)];
/* tx */
struct work_struct work;
struct tid_ampdu_tx *tid_tx[STA_TID_NUM];