mac80211: fix addba timer
The addba timer function acquires the sta spinlock, but at the same time we try to del_timer_sync() it under the spinlock which can produce deadlocks. To fix this, always del_timer_sync() the timer in ieee80211_process_addba_resp() and add it again after checking the conditions, if necessary. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
e55ea2b152
commit
2171abc586
1 changed files with 12 additions and 7 deletions
|
@ -666,26 +666,25 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
|
||||||
|
|
||||||
state = &sta->ampdu_mlme.tid_state_tx[tid];
|
state = &sta->ampdu_mlme.tid_state_tx[tid];
|
||||||
|
|
||||||
|
del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
|
||||||
|
|
||||||
spin_lock_bh(&sta->lock);
|
spin_lock_bh(&sta->lock);
|
||||||
|
|
||||||
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
|
if (!(*state & HT_ADDBA_REQUESTED_MSK))
|
||||||
spin_unlock_bh(&sta->lock);
|
goto timer_still_needed;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mgmt->u.action.u.addba_resp.dialog_token !=
|
if (mgmt->u.action.u.addba_resp.dialog_token !=
|
||||||
sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
|
sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
|
||||||
spin_unlock_bh(&sta->lock);
|
|
||||||
#ifdef CONFIG_MAC80211_HT_DEBUG
|
#ifdef CONFIG_MAC80211_HT_DEBUG
|
||||||
printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
|
printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
|
||||||
#endif /* CONFIG_MAC80211_HT_DEBUG */
|
#endif /* CONFIG_MAC80211_HT_DEBUG */
|
||||||
return;
|
goto timer_still_needed;
|
||||||
}
|
}
|
||||||
|
|
||||||
del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
|
|
||||||
#ifdef CONFIG_MAC80211_HT_DEBUG
|
#ifdef CONFIG_MAC80211_HT_DEBUG
|
||||||
printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
|
printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
|
||||||
#endif /* CONFIG_MAC80211_HT_DEBUG */
|
#endif /* CONFIG_MAC80211_HT_DEBUG */
|
||||||
|
|
||||||
if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
|
if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
|
||||||
== WLAN_STATUS_SUCCESS) {
|
== WLAN_STATUS_SUCCESS) {
|
||||||
u8 curstate = *state;
|
u8 curstate = *state;
|
||||||
|
@ -699,5 +698,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
|
||||||
} else {
|
} else {
|
||||||
___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
|
___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
timer_still_needed:
|
||||||
|
add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
|
||||||
|
out:
|
||||||
spin_unlock_bh(&sta->lock);
|
spin_unlock_bh(&sta->lock);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue