diff options
| -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); |
