Commit 7c3b1dd8 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

mac80211: defer RX agg session teardown to work

Since we want the code to be able to sleep
in the future, it must not be called from
the timer directly. To prepare, move it out
into the aggregation work.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 67c282c0
...@@ -32,21 +32,18 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) ...@@ -32,21 +32,18 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
kfree(tid_rx); kfree(tid_rx);
} }
static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
u16 initiator, u16 reason, u16 initiator, u16 reason)
bool from_timer)
{ {
struct ieee80211_local *local = sta->local; struct ieee80211_local *local = sta->local;
struct tid_ampdu_rx *tid_rx; struct tid_ampdu_rx *tid_rx;
spin_lock_bh(&sta->lock); lockdep_assert_held(&sta->lock);
tid_rx = sta->ampdu_mlme.tid_rx[tid]; tid_rx = sta->ampdu_mlme.tid_rx[tid];
if (!tid_rx) { if (!tid_rx)
spin_unlock_bh(&sta->lock);
return; return;
}
rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], NULL); rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], NULL);
...@@ -65,10 +62,7 @@ static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, ...@@ -65,10 +62,7 @@ static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
ieee80211_send_delba(sta->sdata, sta->sta.addr, ieee80211_send_delba(sta->sdata, sta->sta.addr,
tid, 0, reason); tid, 0, reason);
spin_unlock_bh(&sta->lock); del_timer_sync(&tid_rx->session_timer);
if (!from_timer)
del_timer_sync(&tid_rx->session_timer);
call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
} }
...@@ -76,7 +70,9 @@ static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, ...@@ -76,7 +70,9 @@ static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
u16 initiator, u16 reason) 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);
} }
/* /*
...@@ -97,8 +93,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) ...@@ -97,8 +93,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
#endif #endif
___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired);
WLAN_REASON_QSTA_TIMEOUT, true); 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, static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
......
...@@ -132,6 +132,11 @@ void ieee80211_ba_session_work(struct work_struct *work) ...@@ -132,6 +132,11 @@ void ieee80211_ba_session_work(struct work_struct *work)
spin_lock_bh(&sta->lock); spin_lock_bh(&sta->lock);
for (tid = 0; tid < STA_TID_NUM; tid++) { 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]; tid_tx = sta->ampdu_mlme.tid_tx[tid];
if (!tid_tx) if (!tid_tx)
continue; continue;
......
...@@ -1096,6 +1096,8 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, ...@@ -1096,6 +1096,8 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode smps, const u8 *da, enum ieee80211_smps_mode smps, const u8 *da,
const u8 *bssid); 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, void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
u16 initiator, u16 reason); u16 initiator, u16 reason);
void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta);
......
...@@ -140,10 +140,13 @@ struct tid_ampdu_rx { ...@@ -140,10 +140,13 @@ struct tid_ampdu_rx {
* @addba_req_num: number of times addBA request has been sent. * @addba_req_num: number of times addBA request has been sent.
* @dialog_token_allocator: dialog token enumerator for each new session; * @dialog_token_allocator: dialog token enumerator for each new session;
* @work: work struct for starting/stopping aggregation * @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 { struct sta_ampdu_mlme {
/* rx */ /* rx */
struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)];
/* tx */ /* tx */
struct work_struct work; struct work_struct work;
struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment