diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-03-23 12:28:42 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:13:23 -0400 |
commit | e4e72fb4de93e3d4047a4ee3f08778422e17ed0d (patch) | |
tree | dd133a749e6fa6960c9aa708041d996110f6440e | |
parent | cd8ffc800ce18e558335c4946b2217864fc16045 (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.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-helpers.h | 52 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 1 | ||||
-rw-r--r-- | include/net/mac80211.h | 14 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 44 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 7 | ||||
-rw-r--r-- | net/mac80211/main.c | 9 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 12 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 19 | ||||
-rw-r--r-- | net/mac80211/util.c | 58 |
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 | */ | ||
107 | static 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 | |||
115 | static 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 | |||
130 | static 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 | */ |
99 | enum ieee80211_max_queues { | 97 | enum 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); | |||
474 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | 436 | int 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); |