diff options
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r-- | net/mac80211/agg-tx.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 9cc472c6a6a5..42f7c9007331 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -190,7 +190,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
190 | 190 | ||
191 | ret = drv_ampdu_action(local, sta->sdata, | 191 | ret = drv_ampdu_action(local, sta->sdata, |
192 | IEEE80211_AMPDU_TX_STOP, | 192 | IEEE80211_AMPDU_TX_STOP, |
193 | &sta->sta, tid, NULL); | 193 | &sta->sta, tid, NULL, 0); |
194 | 194 | ||
195 | /* HW shall not deny going back to legacy */ | 195 | /* HW shall not deny going back to legacy */ |
196 | if (WARN_ON(ret)) { | 196 | if (WARN_ON(ret)) { |
@@ -311,7 +311,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
311 | start_seq_num = sta->tid_seq[tid] >> 4; | 311 | start_seq_num = sta->tid_seq[tid] >> 4; |
312 | 312 | ||
313 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, | 313 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, |
314 | &sta->sta, tid, &start_seq_num); | 314 | &sta->sta, tid, &start_seq_num, 0); |
315 | if (ret) { | 315 | if (ret) { |
316 | #ifdef CONFIG_MAC80211_HT_DEBUG | 316 | #ifdef CONFIG_MAC80211_HT_DEBUG |
317 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | 317 | printk(KERN_DEBUG "BA request denied - HW unavailable for" |
@@ -487,7 +487,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
487 | 487 | ||
488 | drv_ampdu_action(local, sta->sdata, | 488 | drv_ampdu_action(local, sta->sdata, |
489 | IEEE80211_AMPDU_TX_OPERATIONAL, | 489 | IEEE80211_AMPDU_TX_OPERATIONAL, |
490 | &sta->sta, tid, NULL); | 490 | &sta->sta, tid, NULL, |
491 | sta->ampdu_mlme.tid_tx[tid]->buf_size); | ||
491 | 492 | ||
492 | /* | 493 | /* |
493 | * synchronize with TX path, while splicing the TX path | 494 | * synchronize with TX path, while splicing the TX path |
@@ -742,9 +743,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
742 | { | 743 | { |
743 | struct tid_ampdu_tx *tid_tx; | 744 | struct tid_ampdu_tx *tid_tx; |
744 | u16 capab, tid; | 745 | u16 capab, tid; |
746 | u8 buf_size; | ||
745 | 747 | ||
746 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 748 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
747 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 749 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
750 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
748 | 751 | ||
749 | mutex_lock(&sta->ampdu_mlme.mtx); | 752 | mutex_lock(&sta->ampdu_mlme.mtx); |
750 | 753 | ||
@@ -767,12 +770,23 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
767 | 770 | ||
768 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 771 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
769 | == WLAN_STATUS_SUCCESS) { | 772 | == WLAN_STATUS_SUCCESS) { |
773 | /* | ||
774 | * IEEE 802.11-2007 7.3.1.14: | ||
775 | * In an ADDBA Response frame, when the Status Code field | ||
776 | * is set to 0, the Buffer Size subfield is set to a value | ||
777 | * of at least 1. | ||
778 | */ | ||
779 | if (!buf_size) | ||
780 | goto out; | ||
781 | |||
770 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, | 782 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, |
771 | &tid_tx->state)) { | 783 | &tid_tx->state)) { |
772 | /* ignore duplicate response */ | 784 | /* ignore duplicate response */ |
773 | goto out; | 785 | goto out; |
774 | } | 786 | } |
775 | 787 | ||
788 | tid_tx->buf_size = buf_size; | ||
789 | |||
776 | if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) | 790 | if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) |
777 | ieee80211_agg_tx_operational(local, sta, tid); | 791 | ieee80211_agg_tx_operational(local, sta, tid); |
778 | 792 | ||