aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-02-11 18:51:53 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-02-27 14:51:42 -0500
commit96f5e66e8a79810e2982cdcfa28e554f3d97da21 (patch)
treed16a0e083b83ab488f20b995c56a496a4ec2c9c8 /net/mac80211/tx.c
parentf3734ee6df3ac57151e02d091f47d5e52e646539 (diff)
mac80211: fix aggregation for hardware with ampdu queues
Hardware with AMPDU queues currently has broken aggregation. This patch fixes it by making all A-MPDUs go over the regular AC queues, but keeping track of the hardware queues in mac80211. As a first rough version, it actually stops the AC queue for extended periods of time, which can be removed by adding buffering internal to mac80211, but is currently not a huge problem because people rarely use multiple TIDs that are in the same AC (and iwlwifi currently doesn't operate as AP). This is a short-term fix, my current medium-term plan, which I hope to execute soon as well, but am not sure can finish before .30, looks like this: 1) rework the internal queuing layer in mac80211 that we use for fragments if the driver stopped queue in the middle of a fragmented frame to be able to queue more frames at once (rather than just a single frame with its fragments) 2) instead of stopping the entire AC queue, queue up the frames in a per-station/per-TID queue during aggregation session initiation, when the session has come up take all those frames and put them onto the queue from 1) 3) push the ampdu queue layer abstraction this patch introduces in mac80211 into the driver, and remove the virtual queue stuff from mac80211 again This plan will probably also affect ath9k in that mac80211 queues the frames instead of passing them down, even when there are no ampdu queues. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 33926831c648..6aca49897d55 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -876,7 +876,6 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
876 return TX_CONTINUE; 876 return TX_CONTINUE;
877} 877}
878 878
879
880/* actual transmit path */ 879/* actual transmit path */
881 880
882/* 881/*
@@ -1016,12 +1015,20 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
1016 tx->sta = sta_info_get(local, hdr->addr1); 1015 tx->sta = sta_info_get(local, hdr->addr1);
1017 1016
1018 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) { 1017 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) {
1018 unsigned long flags;
1019 qc = ieee80211_get_qos_ctl(hdr); 1019 qc = ieee80211_get_qos_ctl(hdr);
1020 tid = *qc & IEEE80211_QOS_CTL_TID_MASK; 1020 tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
1021 1021
1022 spin_lock_irqsave(&tx->sta->lock, flags);
1022 state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; 1023 state = &tx->sta->ampdu_mlme.tid_state_tx[tid];
1023 if (*state == HT_AGG_STATE_OPERATIONAL) 1024 if (*state == HT_AGG_STATE_OPERATIONAL) {
1024 info->flags |= IEEE80211_TX_CTL_AMPDU; 1025 info->flags |= IEEE80211_TX_CTL_AMPDU;
1026 if (local->hw.ampdu_queues)
1027 skb_set_queue_mapping(
1028 skb, tx->local->hw.queues +
1029 tx->sta->tid_to_tx_q[tid]);
1030 }
1031 spin_unlock_irqrestore(&tx->sta->lock, flags);
1025 } 1032 }
1026 1033
1027 if (is_multicast_ether_addr(hdr->addr1)) { 1034 if (is_multicast_ether_addr(hdr->addr1)) {
@@ -1085,7 +1092,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
1085 int ret, i; 1092 int ret, i;
1086 1093
1087 if (skb) { 1094 if (skb) {
1088 if (netif_subqueue_stopped(local->mdev, skb)) 1095 if (ieee80211_queue_stopped(&local->hw,
1096 skb_get_queue_mapping(skb)))
1089 return IEEE80211_TX_PENDING; 1097 return IEEE80211_TX_PENDING;
1090 1098
1091 ret = local->ops->tx(local_to_hw(local), skb); 1099 ret = local->ops->tx(local_to_hw(local), skb);
@@ -1101,8 +1109,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
1101 info = IEEE80211_SKB_CB(tx->extra_frag[i]); 1109 info = IEEE80211_SKB_CB(tx->extra_frag[i]);
1102 info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | 1110 info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
1103 IEEE80211_TX_CTL_FIRST_FRAGMENT); 1111 IEEE80211_TX_CTL_FIRST_FRAGMENT);
1104 if (netif_subqueue_stopped(local->mdev, 1112 if (ieee80211_queue_stopped(&local->hw,
1105 tx->extra_frag[i])) 1113 skb_get_queue_mapping(tx->extra_frag[i])))
1106 return IEEE80211_TX_FRAG_AGAIN; 1114 return IEEE80211_TX_FRAG_AGAIN;
1107 1115
1108 ret = local->ops->tx(local_to_hw(local), 1116 ret = local->ops->tx(local_to_hw(local),