aboutsummaryrefslogtreecommitdiffstats
path: root/net
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
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')
-rw-r--r--net/mac80211/agg-rx.c4
-rw-r--r--net/mac80211/agg-tx.c20
-rw-r--r--net/mac80211/driver-ops.h6
-rw-r--r--net/mac80211/driver-trace.h11
-rw-r--r--net/mac80211/sta_info.h2
5 files changed, 31 insertions, 12 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 002db5e86eb6..1f51f4162426 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -76,7 +76,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
76#endif /* CONFIG_MAC80211_HT_DEBUG */ 76#endif /* CONFIG_MAC80211_HT_DEBUG */
77 77
78 if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, 78 if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
79 &sta->sta, tid, NULL)) 79 &sta->sta, tid, NULL, 0))
80 printk(KERN_DEBUG "HW problem - can not stop rx " 80 printk(KERN_DEBUG "HW problem - can not stop rx "
81 "aggregation for tid %d\n", tid); 81 "aggregation for tid %d\n", tid);
82 82
@@ -297,7 +297,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
297 } 297 }
298 298
299 ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, 299 ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
300 &sta->sta, tid, &start_seq_num); 300 &sta->sta, tid, &start_seq_num, 0);
301#ifdef CONFIG_MAC80211_HT_DEBUG 301#ifdef CONFIG_MAC80211_HT_DEBUG
302 printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); 302 printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
303#endif /* CONFIG_MAC80211_HT_DEBUG */ 303#endif /* CONFIG_MAC80211_HT_DEBUG */
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
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 98d589960a49..78af32d4bc58 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -382,17 +382,17 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,
382 struct ieee80211_sub_if_data *sdata, 382 struct ieee80211_sub_if_data *sdata,
383 enum ieee80211_ampdu_mlme_action action, 383 enum ieee80211_ampdu_mlme_action action,
384 struct ieee80211_sta *sta, u16 tid, 384 struct ieee80211_sta *sta, u16 tid,
385 u16 *ssn) 385 u16 *ssn, u8 buf_size)
386{ 386{
387 int ret = -EOPNOTSUPP; 387 int ret = -EOPNOTSUPP;
388 388
389 might_sleep(); 389 might_sleep();
390 390
391 trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn); 391 trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
392 392
393 if (local->ops->ampdu_action) 393 if (local->ops->ampdu_action)
394 ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, 394 ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
395 sta, tid, ssn); 395 sta, tid, ssn, buf_size);
396 396
397 trace_drv_return_int(local, ret); 397 trace_drv_return_int(local, ret);
398 398
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 49c84218b2f4..fbabbc2f181a 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -784,9 +784,9 @@ TRACE_EVENT(drv_ampdu_action,
784 struct ieee80211_sub_if_data *sdata, 784 struct ieee80211_sub_if_data *sdata,
785 enum ieee80211_ampdu_mlme_action action, 785 enum ieee80211_ampdu_mlme_action action,
786 struct ieee80211_sta *sta, u16 tid, 786 struct ieee80211_sta *sta, u16 tid,
787 u16 *ssn), 787 u16 *ssn, u8 buf_size),
788 788
789 TP_ARGS(local, sdata, action, sta, tid, ssn), 789 TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size),
790 790
791 TP_STRUCT__entry( 791 TP_STRUCT__entry(
792 LOCAL_ENTRY 792 LOCAL_ENTRY
@@ -794,6 +794,7 @@ TRACE_EVENT(drv_ampdu_action,
794 __field(u32, action) 794 __field(u32, action)
795 __field(u16, tid) 795 __field(u16, tid)
796 __field(u16, ssn) 796 __field(u16, ssn)
797 __field(u8, buf_size)
797 VIF_ENTRY 798 VIF_ENTRY
798 ), 799 ),
799 800
@@ -804,11 +805,13 @@ TRACE_EVENT(drv_ampdu_action,
804 __entry->action = action; 805 __entry->action = action;
805 __entry->tid = tid; 806 __entry->tid = tid;
806 __entry->ssn = ssn ? *ssn : 0; 807 __entry->ssn = ssn ? *ssn : 0;
808 __entry->buf_size = buf_size;
807 ), 809 ),
808 810
809 TP_printk( 811 TP_printk(
810 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d", 812 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d",
811 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid 813 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action,
814 __entry->tid, __entry->buf_size
812 ) 815 )
813); 816);
814 817
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index bbdd2a86a94b..ca0b69060ef7 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags {
82 * @state: session state (see above) 82 * @state: session state (see above)
83 * @stop_initiator: initiator of a session stop 83 * @stop_initiator: initiator of a session stop
84 * @tx_stop: TX DelBA frame when stopping 84 * @tx_stop: TX DelBA frame when stopping
85 * @buf_size: reorder buffer size at receiver
85 * 86 *
86 * This structure's lifetime is managed by RCU, assignments to 87 * This structure's lifetime is managed by RCU, assignments to
87 * the array holding it must hold the aggregation mutex. 88 * the array holding it must hold the aggregation mutex.
@@ -101,6 +102,7 @@ struct tid_ampdu_tx {
101 u8 dialog_token; 102 u8 dialog_token;
102 u8 stop_initiator; 103 u8 stop_initiator;
103 bool tx_stop; 104 bool tx_stop;
105 u8 buf_size;
104}; 106};
105 107
106/** 108/**