aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-03-23 12:28:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-27 20:13:23 -0400
commite4e72fb4de93e3d4047a4ee3f08778422e17ed0d (patch)
treedd133a749e6fa6960c9aa708041d996110f6440e
parentcd8ffc800ce18e558335c4946b2217864fc16045 (diff)
mac80211/iwlwifi: move virtual A-MDPU queue bookkeeping to iwlwifi
This patch removes all the virtual A-MPDU-queue bookkeeping from mac80211. Curiously, iwlwifi already does its own bookkeeping, so it doesn't require much changes except where it needs to handle starting and stopping the queues in mac80211. To handle the queue stop/wake properly, we rewrite the software queue number for aggregation frames and internally to iwlwifi keep track of the queues that map into the same AC queue, and only talk to mac80211 about the AC queue. The implementation requires calling two new functions, iwl_stop_queue and iwl_wake_queue instead of the mac80211 counterparts. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Cc: Reinette Chattre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h52
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c1
-rw-r--r--include/net/mac80211.h14
-rw-r--r--net/mac80211/agg-tx.c44
-rw-r--r--net/mac80211/ieee80211_i.h7
-rw-r--r--net/mac80211/main.c9
-rw-r--r--net/mac80211/sta_info.c12
-rw-r--r--net/mac80211/sta_info.h2
-rw-r--r--net/mac80211/tx.c19
-rw-r--r--net/mac80211/util.c58
17 files changed, 84 insertions, 169 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index d03f5534afee..2399328e8de7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -293,7 +293,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
293 if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && 293 if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
294 (txq_id != IWL_CMD_QUEUE_NUM) && 294 (txq_id != IWL_CMD_QUEUE_NUM) &&
295 priv->mac80211_registered) 295 priv->mac80211_registered)
296 ieee80211_wake_queue(priv->hw, txq_id); 296 iwl_wake_queue(priv, txq_id);
297} 297}
298 298
299/** 299/**
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index bd0140be774e..847a6220c5e6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2178,10 +2178,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2178 (iwl_queue_space(&txq->q) > txq->q.low_mark) && 2178 (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
2179 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { 2179 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
2180 if (agg->state == IWL_AGG_OFF) 2180 if (agg->state == IWL_AGG_OFF)
2181 ieee80211_wake_queue(priv->hw, txq_id); 2181 iwl_wake_queue(priv, txq_id);
2182 else 2182 else
2183 ieee80211_wake_queue(priv->hw, 2183 iwl_wake_queue(priv, txq->swq_id);
2184 txq->swq_id);
2185 } 2184 }
2186 } 2185 }
2187 } else { 2186 } else {
@@ -2205,7 +2204,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2205 2204
2206 if (priv->mac80211_registered && 2205 if (priv->mac80211_registered &&
2207 (iwl_queue_space(&txq->q) > txq->q.low_mark)) 2206 (iwl_queue_space(&txq->q) > txq->q.low_mark))
2208 ieee80211_wake_queue(priv->hw, txq_id); 2207 iwl_wake_queue(priv, txq_id);
2209 } 2208 }
2210 2209
2211 if (qc && likely(sta_id != IWL_INVALID_STATION)) 2210 if (qc && likely(sta_id != IWL_INVALID_STATION))
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index a3d9a95a9b37..e5ca2511a81a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1295,10 +1295,9 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
1295 (iwl_queue_space(&txq->q) > txq->q.low_mark) && 1295 (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
1296 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { 1296 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
1297 if (agg->state == IWL_AGG_OFF) 1297 if (agg->state == IWL_AGG_OFF)
1298 ieee80211_wake_queue(priv->hw, txq_id); 1298 iwl_wake_queue(priv, txq_id);
1299 else 1299 else
1300 ieee80211_wake_queue(priv->hw, 1300 iwl_wake_queue(priv, txq->swq_id);
1301 txq->swq_id);
1302 } 1301 }
1303 } 1302 }
1304 } else { 1303 } else {
@@ -1324,7 +1323,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
1324 1323
1325 if (priv->mac80211_registered && 1324 if (priv->mac80211_registered &&
1326 (iwl_queue_space(&txq->q) > txq->q.low_mark)) 1325 (iwl_queue_space(&txq->q) > txq->q.low_mark))
1327 ieee80211_wake_queue(priv->hw, txq_id); 1326 iwl_wake_queue(priv, txq_id);
1328 } 1327 }
1329 1328
1330 if (ieee80211_is_data_qos(tx_resp->frame_ctrl)) 1329 if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 4b1298c2b0da..c54fb93e9d72 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1309,9 +1309,6 @@ int iwl_setup_mac(struct iwl_priv *priv)
1309 1309
1310 /* Default value; 4 EDCA QOS priorities */ 1310 /* Default value; 4 EDCA QOS priorities */
1311 hw->queues = 4; 1311 hw->queues = 4;
1312 /* queues to support 11n aggregation */
1313 if (priv->cfg->sku & IWL_SKU_N)
1314 hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues;
1315 1312
1316 hw->conf.beacon_int = 100; 1313 hw->conf.beacon_int = 100;
1317 hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; 1314 hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 0baae8022824..ec9a13846edd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -996,6 +996,12 @@ struct iwl_priv {
996 u8 key_mapping_key; 996 u8 key_mapping_key;
997 unsigned long ucode_key_table; 997 unsigned long ucode_key_table;
998 998
999 /* queue refcounts */
1000#define IWL_MAX_HW_QUEUES 32
1001 unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
1002 /* for each AC */
1003 atomic_t queue_stop_count[4];
1004
999 /* Indication if ieee80211_ops->open has been called */ 1005 /* Indication if ieee80211_ops->open has been called */
1000 u8 is_open; 1006 u8 is_open;
1001 1007
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index fb64d297dd4e..a1328c3c81ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -93,4 +93,56 @@ static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev,
93 return (desc->v_addr != NULL) ? 0 : -ENOMEM; 93 return (desc->v_addr != NULL) ? 0 : -ENOMEM;
94} 94}
95 95
96/*
97 * we have 8 bits used like this:
98 *
99 * 7 6 5 4 3 2 1 0
100 * | | | | | | | |
101 * | | | | | | +-+-------- AC queue (0-3)
102 * | | | | | |
103 * | +-+-+-+-+------------ HW A-MPDU queue
104 * |
105 * +---------------------- indicates agg queue
106 */
107static inline u8 iwl_virtual_agg_queue_num(u8 ac, u8 hwq)
108{
109 BUG_ON(ac > 3); /* only have 2 bits */
110 BUG_ON(hwq > 31); /* only have 5 bits */
111
112 return 0x80 | (hwq << 2) | ac;
113}
114
115static inline void iwl_wake_queue(struct iwl_priv *priv, u8 queue)
116{
117 u8 ac = queue;
118 u8 hwq = queue;
119
120 if (queue & 0x80) {
121 ac = queue & 3;
122 hwq = (queue >> 2) & 0x1f;
123 }
124
125 if (test_and_clear_bit(hwq, priv->queue_stopped))
126 if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0)
127 ieee80211_wake_queue(priv->hw, ac);
128}
129
130static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue)
131{
132 u8 ac = queue;
133 u8 hwq = queue;
134
135 if (queue & 0x80) {
136 ac = queue & 3;
137 hwq = (queue >> 2) & 0x1f;
138 }
139
140 if (!test_and_set_bit(hwq, priv->queue_stopped))
141 if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0)
142 ieee80211_stop_queue(priv->hw, ac);
143}
144
145#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
146#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
147
96#endif /* __iwl_helpers_h__ */ 148#endif /* __iwl_helpers_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index b13862a598ef..1f117a49c569 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -763,8 +763,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
763 hdr->seq_ctrl |= cpu_to_le16(seq_number); 763 hdr->seq_ctrl |= cpu_to_le16(seq_number);
764 seq_number += 0x10; 764 seq_number += 0x10;
765 /* aggregation is on for this <sta,tid> */ 765 /* aggregation is on for this <sta,tid> */
766 if (info->flags & IEEE80211_TX_CTL_AMPDU) 766 if (info->flags & IEEE80211_TX_CTL_AMPDU) {
767 txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; 767 txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
768 swq_id = iwl_virtual_agg_queue_num(swq_id, txq_id);
769 }
768 priv->stations[sta_id].tid[tid].tfds_in_queue++; 770 priv->stations[sta_id].tid[tid].tfds_in_queue++;
769 } 771 }
770 772
@@ -895,7 +897,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
895 iwl_txq_update_write_ptr(priv, txq); 897 iwl_txq_update_write_ptr(priv, txq);
896 spin_unlock_irqrestore(&priv->lock, flags); 898 spin_unlock_irqrestore(&priv->lock, flags);
897 } else { 899 } else {
898 ieee80211_stop_queue(priv->hw, txq->swq_id); 900 iwl_stop_queue(priv, txq->swq_id);
899 } 901 }
900 } 902 }
901 903
@@ -1433,7 +1435,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
1433 if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && 1435 if ((iwl_queue_space(&txq->q) > txq->q.low_mark) &&
1434 priv->mac80211_registered && 1436 priv->mac80211_registered &&
1435 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) 1437 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
1436 ieee80211_wake_queue(priv->hw, txq->swq_id); 1438 iwl_wake_queue(priv, txq->swq_id);
1437 1439
1438 iwl_txq_check_empty(priv, sta_id, tid, scd_flow); 1440 iwl_txq_check_empty(priv, sta_id, tid, scd_flow);
1439 } 1441 }
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index ede29b6c4dc8..a71b08ca7c71 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1168,7 +1168,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
1168 spin_unlock_irqrestore(&priv->lock, flags); 1168 spin_unlock_irqrestore(&priv->lock, flags);
1169 } 1169 }
1170 1170
1171 ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb)); 1171 iwl_stop_queue(priv, skb_get_queue_mapping(skb));
1172 } 1172 }
1173 1173
1174 return 0; 1174 return 0;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 551161024756..d4fdc8b7d7d8 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -933,7 +933,6 @@ static int __init init_mac80211_hwsim(void)
933 BIT(NL80211_IFTYPE_STATION) | 933 BIT(NL80211_IFTYPE_STATION) |
934 BIT(NL80211_IFTYPE_AP) | 934 BIT(NL80211_IFTYPE_AP) |
935 BIT(NL80211_IFTYPE_MESH_POINT); 935 BIT(NL80211_IFTYPE_MESH_POINT);
936 hw->ampdu_queues = 1;
937 936
938 hw->flags = IEEE80211_HW_MFP_CAPABLE; 937 hw->flags = IEEE80211_HW_MFP_CAPABLE;
939 938
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 841f7f804bb6..3b83a80e3fe0 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -93,12 +93,9 @@ struct ieee80211_ht_bss_info {
93 * enum ieee80211_max_queues - maximum number of queues 93 * enum ieee80211_max_queues - maximum number of queues
94 * 94 *
95 * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. 95 * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
96 * @IEEE80211_MAX_AMPDU_QUEUES: Maximum number of queues usable
97 * for A-MPDU operation.
98 */ 96 */
99enum ieee80211_max_queues { 97enum ieee80211_max_queues {
100 IEEE80211_MAX_QUEUES = 4, 98 IEEE80211_MAX_QUEUES = 4,
101 IEEE80211_MAX_AMPDU_QUEUES = 16,
102}; 99};
103 100
104/** 101/**
@@ -952,12 +949,6 @@ enum ieee80211_hw_flags {
952 * data packets. WMM/QoS requires at least four, these 949 * data packets. WMM/QoS requires at least four, these
953 * queues need to have configurable access parameters. 950 * queues need to have configurable access parameters.
954 * 951 *
955 * @ampdu_queues: number of available hardware transmit queues
956 * for A-MPDU packets, these have no access parameters
957 * because they're used only for A-MPDU frames. Note that
958 * mac80211 will not currently use any of the regular queues
959 * for aggregation.
960 *
961 * @rate_control_algorithm: rate control algorithm for this hardware. 952 * @rate_control_algorithm: rate control algorithm for this hardware.
962 * If unset (NULL), the default algorithm will be used. Must be 953 * If unset (NULL), the default algorithm will be used. Must be
963 * set before calling ieee80211_register_hw(). 954 * set before calling ieee80211_register_hw().
@@ -982,7 +973,6 @@ struct ieee80211_hw {
982 int vif_data_size; 973 int vif_data_size;
983 int sta_data_size; 974 int sta_data_size;
984 u16 queues; 975 u16 queues;
985 u16 ampdu_queues;
986 u16 max_listen_interval; 976 u16 max_listen_interval;
987 s8 max_signal; 977 s8 max_signal;
988 u8 max_rates; 978 u8 max_rates;
@@ -1372,8 +1362,8 @@ enum ieee80211_ampdu_mlme_action {
1372 * @get_tx_stats: Get statistics of the current TX queue status. This is used 1362 * @get_tx_stats: Get statistics of the current TX queue status. This is used
1373 * to get number of currently queued packets (queue length), maximum queue 1363 * to get number of currently queued packets (queue length), maximum queue
1374 * size (limit), and total number of packets sent using each TX queue 1364 * size (limit), and total number of packets sent using each TX queue
1375 * (count). The 'stats' pointer points to an array that has hw->queues + 1365 * (count). The 'stats' pointer points to an array that has hw->queues
1376 * hw->ampdu_queues items. 1366 * items.
1377 * 1367 *
1378 * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, 1368 * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently,
1379 * this is only used for IBSS mode BSSID merging and debugging. Is not a 1369 * this is only used for IBSS mode BSSID merging and debugging. Is not a
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 64b839bfbf17..947aaaad35d2 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -131,14 +131,6 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
131 131
132 state = &sta->ampdu_mlme.tid_state_tx[tid]; 132 state = &sta->ampdu_mlme.tid_state_tx[tid];
133 133
134 if (local->hw.ampdu_queues) {
135 /*
136 * Pretend the driver woke the queue, just in case
137 * it disabled it before the session was stopped.
138 */
139 ieee80211_wake_queue(
140 &local->hw, local->hw.queues + sta->tid_to_tx_q[tid]);
141 }
142 *state = HT_AGG_STATE_REQ_STOP_BA_MSK | 134 *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
143 (initiator << HT_AGG_STATE_INITIATOR_SHIFT); 135 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
144 136
@@ -206,7 +198,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
206 struct sta_info *sta; 198 struct sta_info *sta;
207 struct ieee80211_sub_if_data *sdata; 199 struct ieee80211_sub_if_data *sdata;
208 u8 *state; 200 u8 *state;
209 int i, qn = -1, ret = 0; 201 int ret = 0;
210 u16 start_seq_num; 202 u16 start_seq_num;
211 203
212 if (WARN_ON(!local->ops->ampdu_action)) 204 if (WARN_ON(!local->ops->ampdu_action))
@@ -275,29 +267,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
275 goto err_unlock_sta; 267 goto err_unlock_sta;
276 } 268 }
277 269
278 if (hw->ampdu_queues) {
279 spin_lock(&local->queue_stop_reason_lock);
280 /* reserve a new queue for this session */
281 for (i = 0; i < local->hw.ampdu_queues; i++) {
282 if (local->ampdu_ac_queue[i] < 0) {
283 qn = i;
284 local->ampdu_ac_queue[qn] =
285 ieee80211_ac_from_tid(tid);
286 break;
287 }
288 }
289 spin_unlock(&local->queue_stop_reason_lock);
290
291 if (qn < 0) {
292#ifdef CONFIG_MAC80211_HT_DEBUG
293 printk(KERN_DEBUG "BA request denied - "
294 "queue unavailable for tid %d\n", tid);
295#endif /* CONFIG_MAC80211_HT_DEBUG */
296 ret = -ENOSPC;
297 goto err_unlock_sta;
298 }
299 }
300
301 /* 270 /*
302 * While we're asking the driver about the aggregation, 271 * While we're asking the driver about the aggregation,
303 * stop the AC queue so that we don't have to worry 272 * stop the AC queue so that we don't have to worry
@@ -319,7 +288,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
319 tid); 288 tid);
320#endif 289#endif
321 ret = -ENOMEM; 290 ret = -ENOMEM;
322 goto err_return_queue; 291 goto err_wake_queue;
323 } 292 }
324 293
325 skb_queue_head_init(&sta->ampdu_mlme.tid_tx[tid]->pending); 294 skb_queue_head_init(&sta->ampdu_mlme.tid_tx[tid]->pending);
@@ -348,7 +317,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
348 *state = HT_AGG_STATE_IDLE; 317 *state = HT_AGG_STATE_IDLE;
349 goto err_free; 318 goto err_free;
350 } 319 }
351 sta->tid_to_tx_q[tid] = qn;
352 320
353 /* Driver vetoed or OKed, but we can take packets again now */ 321 /* Driver vetoed or OKed, but we can take packets again now */
354 ieee80211_wake_queue_by_reason( 322 ieee80211_wake_queue_by_reason(
@@ -380,13 +348,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
380 err_free: 348 err_free:
381 kfree(sta->ampdu_mlme.tid_tx[tid]); 349 kfree(sta->ampdu_mlme.tid_tx[tid]);
382 sta->ampdu_mlme.tid_tx[tid] = NULL; 350 sta->ampdu_mlme.tid_tx[tid] = NULL;
383 err_return_queue: 351 err_wake_queue:
384 if (qn >= 0) {
385 /* give queue back to pool */
386 spin_lock(&local->queue_stop_reason_lock);
387 local->ampdu_ac_queue[qn] = -1;
388 spin_unlock(&local->queue_stop_reason_lock);
389 }
390 ieee80211_wake_queue_by_reason( 352 ieee80211_wake_queue_by_reason(
391 &local->hw, ieee80211_ac_from_tid(tid), 353 &local->hw, ieee80211_ac_from_tid(tid),
392 IEEE80211_QUEUE_STOP_REASON_AGGREGATION); 354 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 32345b479adb..e6ed78cb16b3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -594,12 +594,7 @@ struct ieee80211_local {
594 594
595 const struct ieee80211_ops *ops; 595 const struct ieee80211_ops *ops;
596 596
597 /* AC queue corresponding to each AMPDU queue */ 597 unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
598 s8 ampdu_ac_queue[IEEE80211_MAX_AMPDU_QUEUES];
599 unsigned int amdpu_ac_stop_refcnt[IEEE80211_MAX_AMPDU_QUEUES];
600
601 unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES +
602 IEEE80211_MAX_AMPDU_QUEUES];
603 /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ 598 /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
604 spinlock_t queue_stop_reason_lock; 599 spinlock_t queue_stop_reason_lock;
605 600
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 756284e0bbd3..a6f1d8a869bc 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -774,11 +774,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
774 setup_timer(&local->dynamic_ps_timer, 774 setup_timer(&local->dynamic_ps_timer,
775 ieee80211_dynamic_ps_timer, (unsigned long) local); 775 ieee80211_dynamic_ps_timer, (unsigned long) local);
776 776
777 for (i = 0; i < IEEE80211_MAX_AMPDU_QUEUES; i++)
778 local->ampdu_ac_queue[i] = -1;
779 /* using an s8 won't work with more than that */
780 BUILD_BUG_ON(IEEE80211_MAX_AMPDU_QUEUES > 127);
781
782 sta_info_init(local); 777 sta_info_init(local);
783 778
784 for (i = 0; i < IEEE80211_MAX_QUEUES; i++) 779 for (i = 0; i < IEEE80211_MAX_QUEUES; i++)
@@ -874,10 +869,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
874 */ 869 */
875 if (hw->queues > IEEE80211_MAX_QUEUES) 870 if (hw->queues > IEEE80211_MAX_QUEUES)
876 hw->queues = IEEE80211_MAX_QUEUES; 871 hw->queues = IEEE80211_MAX_QUEUES;
877 if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES)
878 hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES;
879 if (hw->queues < 4)
880 hw->ampdu_queues = 0;
881 872
882 mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), 873 mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv),
883 "wmaster%d", ieee80211_master_setup, 874 "wmaster%d", ieee80211_master_setup,
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index dd3593c1fd23..c5f14e6bbde2 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -203,17 +203,6 @@ void sta_info_destroy(struct sta_info *sta)
203 if (tid_rx) 203 if (tid_rx)
204 tid_rx->shutdown = true; 204 tid_rx->shutdown = true;
205 205
206 /*
207 * The stop callback cannot find this station any more, but
208 * it didn't complete its work -- start the queue if necessary
209 */
210 if (sta->ampdu_mlme.tid_state_tx[i] & HT_AGG_STATE_INITIATOR_MSK &&
211 sta->ampdu_mlme.tid_state_tx[i] & HT_AGG_STATE_REQ_STOP_BA_MSK &&
212 local->hw.ampdu_queues)
213 ieee80211_wake_queue_by_reason(&local->hw,
214 local->hw.queues + sta->tid_to_tx_q[i],
215 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
216
217 spin_unlock_bh(&sta->lock); 206 spin_unlock_bh(&sta->lock);
218 207
219 /* 208 /*
@@ -292,7 +281,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
292 * enable session_timer's data differentiation. refer to 281 * enable session_timer's data differentiation. refer to
293 * sta_rx_agg_session_timer_expired for useage */ 282 * sta_rx_agg_session_timer_expired for useage */
294 sta->timer_to_tid[i] = i; 283 sta->timer_to_tid[i] = i;
295 sta->tid_to_tx_q[i] = -1;
296 /* rx */ 284 /* rx */
297 sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; 285 sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE;
298 sta->ampdu_mlme.tid_rx[i] = NULL; 286 sta->ampdu_mlme.tid_rx[i] = NULL;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 18fd5d1a4422..5534d489f506 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -206,7 +206,6 @@ struct sta_ampdu_mlme {
206 * @tid_seq: per-TID sequence numbers for sending to this STA 206 * @tid_seq: per-TID sequence numbers for sending to this STA
207 * @ampdu_mlme: A-MPDU state machine state 207 * @ampdu_mlme: A-MPDU state machine state
208 * @timer_to_tid: identity mapping to ID timers 208 * @timer_to_tid: identity mapping to ID timers
209 * @tid_to_tx_q: map tid to tx queue (invalid == negative values)
210 * @llid: Local link ID 209 * @llid: Local link ID
211 * @plid: Peer link ID 210 * @plid: Peer link ID
212 * @reason: Cancel reason on PLINK_HOLDING state 211 * @reason: Cancel reason on PLINK_HOLDING state
@@ -281,7 +280,6 @@ struct sta_info {
281 */ 280 */
282 struct sta_ampdu_mlme ampdu_mlme; 281 struct sta_ampdu_mlme ampdu_mlme;
283 u8 timer_to_tid[STA_TID_NUM]; 282 u8 timer_to_tid[STA_TID_NUM];
284 s8 tid_to_tx_q[STA_TID_NUM];
285 283
286#ifdef CONFIG_MAC80211_MESH 284#ifdef CONFIG_MAC80211_MESH
287 /* 285 /*
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 906ab785db40..3fb04a86444d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1145,25 +1145,6 @@ static int __ieee80211_tx(struct ieee80211_local *local,
1145 info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | 1145 info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
1146 IEEE80211_TX_CTL_FIRST_FRAGMENT); 1146 IEEE80211_TX_CTL_FIRST_FRAGMENT);
1147 1147
1148 /*
1149 * Internally, we need to have the queue mapping point to
1150 * the real AC queue, not the virtual A-MPDU queue. This
1151 * now finally sets the queue to what the driver wants.
1152 * We will later move this down into the only driver that
1153 * needs it, iwlwifi.
1154 */
1155 if (sta && local->hw.ampdu_queues &&
1156 info->flags & IEEE80211_TX_CTL_AMPDU) {
1157 unsigned long flags;
1158 u8 *qc = ieee80211_get_qos_ctl((void *) skb->data);
1159 int tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
1160
1161 spin_lock_irqsave(&sta->lock, flags);
1162 skb_set_queue_mapping(skb, local->hw.queues +
1163 sta->tid_to_tx_q[tid]);
1164 spin_unlock_irqrestore(&sta->lock, flags);
1165 }
1166
1167 next = skb->next; 1148 next = skb->next;
1168 len = skb->len; 1149 len = skb->len;
1169 ret = local->ops->tx(local_to_hw(local), skb); 1150 ret = local->ops->tx(local_to_hw(local), skb);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0247d8022f5f..fdf432f14554 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -339,29 +339,8 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
339{ 339{
340 struct ieee80211_local *local = hw_to_local(hw); 340 struct ieee80211_local *local = hw_to_local(hw);
341 341
342 if (queue >= hw->queues) { 342 if (WARN_ON(queue >= hw->queues))
343 if (local->ampdu_ac_queue[queue - hw->queues] < 0) 343 return;
344 return;
345
346 /*
347 * for virtual aggregation queues, we need to refcount the
348 * internal mac80211 disable (multiple times!), keep track of
349 * driver disable _and_ make sure the regular queue is
350 * actually enabled.
351 */
352 if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION)
353 local->amdpu_ac_stop_refcnt[queue - hw->queues]--;
354 else
355 __clear_bit(reason, &local->queue_stop_reasons[queue]);
356
357 if (local->queue_stop_reasons[queue] ||
358 local->amdpu_ac_stop_refcnt[queue - hw->queues])
359 return;
360
361 /* now go on to treat the corresponding regular queue */
362 queue = local->ampdu_ac_queue[queue - hw->queues];
363 reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION;
364 }
365 344
366 __clear_bit(reason, &local->queue_stop_reasons[queue]); 345 __clear_bit(reason, &local->queue_stop_reasons[queue]);
367 346
@@ -400,25 +379,8 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
400{ 379{
401 struct ieee80211_local *local = hw_to_local(hw); 380 struct ieee80211_local *local = hw_to_local(hw);
402 381
403 if (queue >= hw->queues) { 382 if (WARN_ON(queue >= hw->queues))
404 if (local->ampdu_ac_queue[queue - hw->queues] < 0) 383 return;
405 return;
406
407 /*
408 * for virtual aggregation queues, we need to refcount the
409 * internal mac80211 disable (multiple times!), keep track of
410 * driver disable _and_ make sure the regular queue is
411 * actually enabled.
412 */
413 if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION)
414 local->amdpu_ac_stop_refcnt[queue - hw->queues]++;
415 else
416 __set_bit(reason, &local->queue_stop_reasons[queue]);
417
418 /* now go on to treat the corresponding regular queue */
419 queue = local->ampdu_ac_queue[queue - hw->queues];
420 reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION;
421 }
422 384
423 /* 385 /*
424 * Only stop if it was previously running, this is necessary 386 * Only stop if it was previously running, this is necessary
@@ -474,15 +436,9 @@ EXPORT_SYMBOL(ieee80211_stop_queues);
474int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) 436int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
475{ 437{
476 struct ieee80211_local *local = hw_to_local(hw); 438 struct ieee80211_local *local = hw_to_local(hw);
477 unsigned long flags;
478 439
479 if (queue >= hw->queues) { 440 if (WARN_ON(queue >= hw->queues))
480 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 441 return true;
481 queue = local->ampdu_ac_queue[queue - hw->queues];
482 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
483 if (queue < 0)
484 return true;
485 }
486 442
487 return __netif_subqueue_stopped(local->mdev, queue); 443 return __netif_subqueue_stopped(local->mdev, queue);
488} 444}
@@ -497,7 +453,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
497 453
498 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 454 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
499 455
500 for (i = 0; i < hw->queues + hw->ampdu_queues; i++) 456 for (i = 0; i < hw->queues; i++)
501 __ieee80211_wake_queue(hw, i, reason); 457 __ieee80211_wake_queue(hw, i, reason);
502 458
503 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 459 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);