diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex/wmm.c')
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 131 |
1 files changed, 87 insertions, 44 deletions
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 981cf6e7c73b..0a7cc742aed7 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -37,8 +37,8 @@ | |||
37 | /* Offset for TOS field in the IP header */ | 37 | /* Offset for TOS field in the IP header */ |
38 | #define IPTOS_OFFSET 5 | 38 | #define IPTOS_OFFSET 5 |
39 | 39 | ||
40 | static bool enable_tx_amsdu; | 40 | static bool disable_tx_amsdu; |
41 | module_param(enable_tx_amsdu, bool, 0644); | 41 | module_param(disable_tx_amsdu, bool, 0644); |
42 | 42 | ||
43 | /* WMM information IE */ | 43 | /* WMM information IE */ |
44 | static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, | 44 | static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, |
@@ -64,21 +64,6 @@ static u8 tos_to_tid[] = { | |||
64 | 0x07 /* 1 1 1 AC_VO */ | 64 | 0x07 /* 1 1 1 AC_VO */ |
65 | }; | 65 | }; |
66 | 66 | ||
67 | /* | ||
68 | * This table inverses the tos_to_tid operation to get a priority | ||
69 | * which is in sequential order, and can be compared. | ||
70 | * Use this to compare the priority of two different TIDs. | ||
71 | */ | ||
72 | static u8 tos_to_tid_inv[] = { | ||
73 | 0x02, /* from tos_to_tid[2] = 0 */ | ||
74 | 0x00, /* from tos_to_tid[0] = 1 */ | ||
75 | 0x01, /* from tos_to_tid[1] = 2 */ | ||
76 | 0x03, | ||
77 | 0x04, | ||
78 | 0x05, | ||
79 | 0x06, | ||
80 | 0x07}; | ||
81 | |||
82 | static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; | 67 | static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; |
83 | 68 | ||
84 | /* | 69 | /* |
@@ -175,8 +160,15 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) | |||
175 | break; | 160 | break; |
176 | 161 | ||
177 | ra_list->is_11n_enabled = 0; | 162 | ra_list->is_11n_enabled = 0; |
163 | ra_list->tdls_link = false; | ||
178 | if (!mwifiex_queuing_ra_based(priv)) { | 164 | if (!mwifiex_queuing_ra_based(priv)) { |
179 | ra_list->is_11n_enabled = IS_11N_ENABLED(priv); | 165 | if (mwifiex_get_tdls_link_status(priv, ra) == |
166 | TDLS_SETUP_COMPLETE) { | ||
167 | ra_list->is_11n_enabled = | ||
168 | mwifiex_tdls_peer_11n_enabled(priv, ra); | ||
169 | } else { | ||
170 | ra_list->is_11n_enabled = IS_11N_ENABLED(priv); | ||
171 | } | ||
180 | } else { | 172 | } else { |
181 | ra_list->is_11n_enabled = | 173 | ra_list->is_11n_enabled = |
182 | mwifiex_is_sta_11n_enabled(priv, node); | 174 | mwifiex_is_sta_11n_enabled(priv, node); |
@@ -213,8 +205,9 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) | |||
213 | * This function map ACs to TIDs. | 205 | * This function map ACs to TIDs. |
214 | */ | 206 | */ |
215 | static void | 207 | static void |
216 | mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm) | 208 | mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv) |
217 | { | 209 | { |
210 | struct mwifiex_wmm_desc *wmm = &priv->wmm; | ||
218 | u8 *queue_priority = wmm->queue_priority; | 211 | u8 *queue_priority = wmm->queue_priority; |
219 | int i; | 212 | int i; |
220 | 213 | ||
@@ -224,7 +217,7 @@ mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm) | |||
224 | } | 217 | } |
225 | 218 | ||
226 | for (i = 0; i < MAX_NUM_TID; ++i) | 219 | for (i = 0; i < MAX_NUM_TID; ++i) |
227 | tos_to_tid_inv[tos_to_tid[i]] = (u8)i; | 220 | priv->tos_to_tid_inv[tos_to_tid[i]] = (u8)i; |
228 | 221 | ||
229 | atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); | 222 | atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); |
230 | } | 223 | } |
@@ -285,7 +278,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, | |||
285 | } | 278 | } |
286 | } | 279 | } |
287 | 280 | ||
288 | mwifiex_wmm_queue_priorities_tid(&priv->wmm); | 281 | mwifiex_wmm_queue_priorities_tid(priv); |
289 | } | 282 | } |
290 | 283 | ||
291 | /* | 284 | /* |
@@ -388,8 +381,7 @@ mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos) | |||
388 | * AP is disabled (due to call admission control (ACM bit). Mapping | 381 | * AP is disabled (due to call admission control (ACM bit). Mapping |
389 | * of TID to AC is taken care of internally. | 382 | * of TID to AC is taken care of internally. |
390 | */ | 383 | */ |
391 | static u8 | 384 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) |
392 | mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) | ||
393 | { | 385 | { |
394 | enum mwifiex_wmm_ac_e ac, ac_down; | 386 | enum mwifiex_wmm_ac_e ac, ac_down; |
395 | u8 new_tid; | 387 | u8 new_tid; |
@@ -421,9 +413,17 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) | |||
421 | continue; | 413 | continue; |
422 | 414 | ||
423 | for (i = 0; i < MAX_NUM_TID; ++i) { | 415 | for (i = 0; i < MAX_NUM_TID; ++i) { |
424 | priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i]; | 416 | if (!disable_tx_amsdu && |
425 | priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i]; | 417 | adapter->tx_buf_size > MWIFIEX_TX_DATA_BUF_SIZE_2K) |
426 | priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; | 418 | priv->aggr_prio_tbl[i].amsdu = |
419 | priv->tos_to_tid_inv[i]; | ||
420 | else | ||
421 | priv->aggr_prio_tbl[i].amsdu = | ||
422 | BA_STREAM_NOT_ALLOWED; | ||
423 | priv->aggr_prio_tbl[i].ampdu_ap = | ||
424 | priv->tos_to_tid_inv[i]; | ||
425 | priv->aggr_prio_tbl[i].ampdu_user = | ||
426 | priv->tos_to_tid_inv[i]; | ||
427 | } | 427 | } |
428 | 428 | ||
429 | priv->aggr_prio_tbl[6].amsdu | 429 | priv->aggr_prio_tbl[6].amsdu |
@@ -546,6 +546,7 @@ void | |||
546 | mwifiex_clean_txrx(struct mwifiex_private *priv) | 546 | mwifiex_clean_txrx(struct mwifiex_private *priv) |
547 | { | 547 | { |
548 | unsigned long flags; | 548 | unsigned long flags; |
549 | struct sk_buff *skb, *tmp; | ||
549 | 550 | ||
550 | mwifiex_11n_cleanup_reorder_tbl(priv); | 551 | mwifiex_11n_cleanup_reorder_tbl(priv); |
551 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); | 552 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); |
@@ -563,6 +564,9 @@ mwifiex_clean_txrx(struct mwifiex_private *priv) | |||
563 | !priv->adapter->surprise_removed) | 564 | !priv->adapter->surprise_removed) |
564 | priv->adapter->if_ops.clean_pcie_ring(priv->adapter); | 565 | priv->adapter->if_ops.clean_pcie_ring(priv->adapter); |
565 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); | 566 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); |
567 | |||
568 | skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) | ||
569 | mwifiex_write_data_complete(priv->adapter, skb, 0, -1); | ||
566 | } | 570 | } |
567 | 571 | ||
568 | /* | 572 | /* |
@@ -591,7 +595,7 @@ mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, | |||
591 | * If no such node is found, a new node is added first and then | 595 | * If no such node is found, a new node is added first and then |
592 | * retrieved. | 596 | * retrieved. |
593 | */ | 597 | */ |
594 | static struct mwifiex_ra_list_tbl * | 598 | struct mwifiex_ra_list_tbl * |
595 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) | 599 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) |
596 | { | 600 | { |
597 | struct mwifiex_ra_list_tbl *ra_list; | 601 | struct mwifiex_ra_list_tbl *ra_list; |
@@ -641,6 +645,21 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | |||
641 | struct mwifiex_ra_list_tbl *ra_list; | 645 | struct mwifiex_ra_list_tbl *ra_list; |
642 | u8 ra[ETH_ALEN], tid_down; | 646 | u8 ra[ETH_ALEN], tid_down; |
643 | unsigned long flags; | 647 | unsigned long flags; |
648 | struct list_head list_head; | ||
649 | int tdls_status = TDLS_NOT_SETUP; | ||
650 | struct ethhdr *eth_hdr = (struct ethhdr *)skb->data; | ||
651 | struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); | ||
652 | |||
653 | memcpy(ra, eth_hdr->h_dest, ETH_ALEN); | ||
654 | |||
655 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA && | ||
656 | ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) { | ||
657 | if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS) | ||
658 | dev_dbg(adapter->dev, | ||
659 | "TDLS setup packet for %pM. Don't block\n", ra); | ||
660 | else | ||
661 | tdls_status = mwifiex_get_tdls_link_status(priv, ra); | ||
662 | } | ||
644 | 663 | ||
645 | if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) { | 664 | if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) { |
646 | dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); | 665 | dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); |
@@ -659,12 +678,27 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | |||
659 | have only 1 raptr for a tid in case of infra */ | 678 | have only 1 raptr for a tid in case of infra */ |
660 | if (!mwifiex_queuing_ra_based(priv) && | 679 | if (!mwifiex_queuing_ra_based(priv) && |
661 | !mwifiex_is_skb_mgmt_frame(skb)) { | 680 | !mwifiex_is_skb_mgmt_frame(skb)) { |
662 | if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list)) | 681 | switch (tdls_status) { |
663 | ra_list = list_first_entry( | 682 | case TDLS_SETUP_COMPLETE: |
664 | &priv->wmm.tid_tbl_ptr[tid_down].ra_list, | 683 | ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, |
665 | struct mwifiex_ra_list_tbl, list); | 684 | ra); |
666 | else | 685 | tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; |
667 | ra_list = NULL; | 686 | break; |
687 | case TDLS_SETUP_INPROGRESS: | ||
688 | skb_queue_tail(&priv->tdls_txq, skb); | ||
689 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | ||
690 | flags); | ||
691 | return; | ||
692 | default: | ||
693 | list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list; | ||
694 | if (!list_empty(&list_head)) | ||
695 | ra_list = list_first_entry( | ||
696 | &list_head, struct mwifiex_ra_list_tbl, | ||
697 | list); | ||
698 | else | ||
699 | ra_list = NULL; | ||
700 | break; | ||
701 | } | ||
668 | } else { | 702 | } else { |
669 | memcpy(ra, skb->data, ETH_ALEN); | 703 | memcpy(ra, skb->data, ETH_ALEN); |
670 | if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb)) | 704 | if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb)) |
@@ -684,9 +718,9 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | |||
684 | ra_list->total_pkt_count++; | 718 | ra_list->total_pkt_count++; |
685 | 719 | ||
686 | if (atomic_read(&priv->wmm.highest_queued_prio) < | 720 | if (atomic_read(&priv->wmm.highest_queued_prio) < |
687 | tos_to_tid_inv[tid_down]) | 721 | priv->tos_to_tid_inv[tid_down]) |
688 | atomic_set(&priv->wmm.highest_queued_prio, | 722 | atomic_set(&priv->wmm.highest_queued_prio, |
689 | tos_to_tid_inv[tid_down]); | 723 | priv->tos_to_tid_inv[tid_down]); |
690 | 724 | ||
691 | atomic_inc(&priv->wmm.tx_pkts_queued); | 725 | atomic_inc(&priv->wmm.tx_pkts_queued); |
692 | 726 | ||
@@ -1219,15 +1253,24 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) | |||
1219 | 1253 | ||
1220 | if (!ptr->is_11n_enabled || | 1254 | if (!ptr->is_11n_enabled || |
1221 | mwifiex_is_ba_stream_setup(priv, ptr, tid) || | 1255 | mwifiex_is_ba_stream_setup(priv, ptr, tid) || |
1222 | priv->wps.session_enable || | 1256 | priv->wps.session_enable) { |
1223 | ((priv->sec_info.wpa_enabled || | 1257 | if (ptr->is_11n_enabled && |
1224 | priv->sec_info.wpa2_enabled) && | 1258 | mwifiex_is_ba_stream_setup(priv, ptr, tid) && |
1225 | !priv->wpa_is_gtk_set)) { | 1259 | mwifiex_is_amsdu_in_ampdu_allowed(priv, ptr, tid) && |
1226 | mwifiex_send_single_packet(priv, ptr, ptr_index, flags); | 1260 | mwifiex_is_amsdu_allowed(priv, tid) && |
1227 | /* ra_list_spinlock has been freed in | 1261 | mwifiex_is_11n_aggragation_possible(priv, ptr, |
1228 | mwifiex_send_single_packet() */ | 1262 | adapter->tx_buf_size)) |
1263 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); | ||
1264 | /* ra_list_spinlock has been freed in | ||
1265 | * mwifiex_11n_aggregate_pkt() | ||
1266 | */ | ||
1267 | else | ||
1268 | mwifiex_send_single_packet(priv, ptr, ptr_index, flags); | ||
1269 | /* ra_list_spinlock has been freed in | ||
1270 | * mwifiex_send_single_packet() | ||
1271 | */ | ||
1229 | } else { | 1272 | } else { |
1230 | if (mwifiex_is_ampdu_allowed(priv, tid) && | 1273 | if (mwifiex_is_ampdu_allowed(priv, ptr, tid) && |
1231 | ptr->ba_pkt_count > ptr->ba_packet_thr) { | 1274 | ptr->ba_pkt_count > ptr->ba_packet_thr) { |
1232 | if (mwifiex_space_avail_for_new_ba_stream(adapter)) { | 1275 | if (mwifiex_space_avail_for_new_ba_stream(adapter)) { |
1233 | mwifiex_create_ba_tbl(priv, ptr->ra, tid, | 1276 | mwifiex_create_ba_tbl(priv, ptr->ra, tid, |
@@ -1240,7 +1283,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) | |||
1240 | mwifiex_send_delba(priv, tid_del, ra, 1); | 1283 | mwifiex_send_delba(priv, tid_del, ra, 1); |
1241 | } | 1284 | } |
1242 | } | 1285 | } |
1243 | if (enable_tx_amsdu && mwifiex_is_amsdu_allowed(priv, tid) && | 1286 | if (mwifiex_is_amsdu_allowed(priv, tid) && |
1244 | mwifiex_is_11n_aggragation_possible(priv, ptr, | 1287 | mwifiex_is_11n_aggragation_possible(priv, ptr, |
1245 | adapter->tx_buf_size)) | 1288 | adapter->tx_buf_size)) |
1246 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); | 1289 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); |