Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2171abc5 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

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: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e55ea2b1
Loading
Loading
Loading
Loading
+12 −7
Original line number Original line Diff line number Diff line
@@ -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);
}
}