aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-01-18 07:51:05 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-01-19 11:36:11 -0500
commit0b01f030d38e00650e2db42da083d8647aad40a5 (patch)
tree14519750d9b6cdb046624dd87d5323a4826821e2 /net/mac80211/agg-tx.c
parentac1bd8464f161ed1475ef73c431b926256c6b5bb (diff)
mac80211: track receiver's aggregation reorder buffer size
The aggregation code currently doesn't implement the buffer size negotiation. It will always request a max buffer size (which is fine, if a little pointless, as the mac80211 code doesn't know and might just use 0 instead), but if the peer requests a smaller size it isn't possible to honour this request. In order to fix this, look at the buffer size in the addBA response frame, keep track of it and pass it to the driver in the ampdu_action callback when called with the IEEE80211_AMPDU_TX_OPERATIONAL action. That way the driver can limit the number of subframes in aggregates appropriately. Note that this doesn't fix any drivers apart from the addition of the new argument -- they all need to be updated separately to use this variable! Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r--net/mac80211/agg-tx.c20
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