diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex/wmm.c')
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index faa09e32902e..91634daec306 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -177,14 +177,20 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) | |||
177 | * This function map ACs to TIDs. | 177 | * This function map ACs to TIDs. |
178 | */ | 178 | */ |
179 | static void | 179 | static void |
180 | mwifiex_wmm_queue_priorities_tid(u8 queue_priority[]) | 180 | mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm) |
181 | { | 181 | { |
182 | u8 *queue_priority = wmm->queue_priority; | ||
182 | int i; | 183 | int i; |
183 | 184 | ||
184 | for (i = 0; i < 4; ++i) { | 185 | for (i = 0; i < 4; ++i) { |
185 | tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; | 186 | tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; |
186 | tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; | 187 | tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; |
187 | } | 188 | } |
189 | |||
190 | for (i = 0; i < MAX_NUM_TID; ++i) | ||
191 | tos_to_tid_inv[tos_to_tid[i]] = (u8)i; | ||
192 | |||
193 | atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); | ||
188 | } | 194 | } |
189 | 195 | ||
190 | /* | 196 | /* |
@@ -246,7 +252,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, | |||
246 | } | 252 | } |
247 | } | 253 | } |
248 | 254 | ||
249 | mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority); | 255 | mwifiex_wmm_queue_priorities_tid(&priv->wmm); |
250 | } | 256 | } |
251 | 257 | ||
252 | /* | 258 | /* |
@@ -399,6 +405,9 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) | |||
399 | priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; | 405 | priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; |
400 | priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; | 406 | priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; |
401 | priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; | 407 | priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; |
408 | |||
409 | atomic_set(&priv->wmm.tx_pkts_queued, 0); | ||
410 | atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); | ||
402 | } | 411 | } |
403 | } | 412 | } |
404 | 413 | ||
@@ -408,17 +417,13 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) | |||
408 | int | 417 | int |
409 | mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) | 418 | mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) |
410 | { | 419 | { |
411 | int i, j; | 420 | int i; |
412 | struct mwifiex_private *priv; | 421 | struct mwifiex_private *priv; |
413 | 422 | ||
414 | for (j = 0; j < adapter->priv_num; ++j) { | 423 | for (i = 0; i < adapter->priv_num; ++i) { |
415 | priv = adapter->priv[j]; | 424 | priv = adapter->priv[i]; |
416 | if (priv) { | 425 | if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) |
417 | for (i = 0; i < MAX_NUM_TID; i++) | 426 | return false; |
418 | if (!mwifiex_wmm_is_ra_list_empty( | ||
419 | &priv->wmm.tid_tbl_ptr[i].ra_list)) | ||
420 | return false; | ||
421 | } | ||
422 | } | 427 | } |
423 | 428 | ||
424 | return true; | 429 | return true; |
@@ -468,6 +473,9 @@ static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) | |||
468 | for (i = 0; i < MAX_NUM_TID; i++) | 473 | for (i = 0; i < MAX_NUM_TID; i++) |
469 | mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. | 474 | mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. |
470 | ra_list); | 475 | ra_list); |
476 | |||
477 | atomic_set(&priv->wmm.tx_pkts_queued, 0); | ||
478 | atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); | ||
471 | } | 479 | } |
472 | 480 | ||
473 | /* | 481 | /* |
@@ -638,6 +646,13 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, | |||
638 | 646 | ||
639 | ra_list->total_pkts_size += skb->len; | 647 | ra_list->total_pkts_size += skb->len; |
640 | 648 | ||
649 | atomic_inc(&priv->wmm.tx_pkts_queued); | ||
650 | |||
651 | if (atomic_read(&priv->wmm.highest_queued_prio) < | ||
652 | tos_to_tid_inv[tid_down]) | ||
653 | atomic_set(&priv->wmm.highest_queued_prio, | ||
654 | tos_to_tid_inv[tid_down]); | ||
655 | |||
641 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); | 656 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); |
642 | } | 657 | } |
643 | 658 | ||
@@ -863,9 +878,14 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
863 | } | 878 | } |
864 | 879 | ||
865 | do { | 880 | do { |
881 | atomic_t *hqp; | ||
882 | spinlock_t *lock; | ||
883 | |||
866 | priv_tmp = bssprio_node->priv; | 884 | priv_tmp = bssprio_node->priv; |
885 | hqp = &priv_tmp->wmm.highest_queued_prio; | ||
886 | lock = &priv_tmp->wmm.ra_list_spinlock; | ||
867 | 887 | ||
868 | for (i = HIGH_PRIO_TID; i >= LOW_PRIO_TID; --i) { | 888 | for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { |
869 | 889 | ||
870 | tid_ptr = &(priv_tmp)->wmm. | 890 | tid_ptr = &(priv_tmp)->wmm. |
871 | tid_tbl_ptr[tos_to_tid[i]]; | 891 | tid_tbl_ptr[tos_to_tid[i]]; |
@@ -903,6 +923,11 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
903 | is_list_empty = | 923 | is_list_empty = |
904 | skb_queue_empty(&ptr->skb_head); | 924 | skb_queue_empty(&ptr->skb_head); |
905 | if (!is_list_empty) { | 925 | if (!is_list_empty) { |
926 | spin_lock_irqsave(lock, flags); | ||
927 | if (atomic_read(hqp) > i) | ||
928 | atomic_set(hqp, i); | ||
929 | spin_unlock_irqrestore(lock, | ||
930 | flags); | ||
906 | *priv = priv_tmp; | 931 | *priv = priv_tmp; |
907 | *tid = tos_to_tid[i]; | 932 | *tid = tos_to_tid[i]; |
908 | return ptr; | 933 | return ptr; |
@@ -921,6 +946,12 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
921 | } while (ptr != head); | 946 | } while (ptr != head); |
922 | } | 947 | } |
923 | 948 | ||
949 | /* No packet at any TID for this priv. Mark as such | ||
950 | * to skip checking TIDs for this priv (until pkt is | ||
951 | * added). | ||
952 | */ | ||
953 | atomic_set(hqp, NO_PKT_PRIO_TID); | ||
954 | |||
924 | /* Get next bss priority node */ | 955 | /* Get next bss priority node */ |
925 | bssprio_node = list_first_entry(&bssprio_node->list, | 956 | bssprio_node = list_first_entry(&bssprio_node->list, |
926 | struct mwifiex_bss_prio_node, | 957 | struct mwifiex_bss_prio_node, |
@@ -1028,6 +1059,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, | |||
1028 | .bss_prio_cur->list, | 1059 | .bss_prio_cur->list, |
1029 | struct mwifiex_bss_prio_node, | 1060 | struct mwifiex_bss_prio_node, |
1030 | list); | 1061 | list); |
1062 | atomic_dec(&priv->wmm.tx_pkts_queued); | ||
1031 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 1063 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
1032 | ra_list_flags); | 1064 | ra_list_flags); |
1033 | } | 1065 | } |
@@ -1134,6 +1166,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, | |||
1134 | .bss_prio_cur->list, | 1166 | .bss_prio_cur->list, |
1135 | struct mwifiex_bss_prio_node, | 1167 | struct mwifiex_bss_prio_node, |
1136 | list); | 1168 | list); |
1169 | atomic_dec(&priv->wmm.tx_pkts_queued); | ||
1137 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 1170 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
1138 | ra_list_flags); | 1171 | ra_list_flags); |
1139 | } | 1172 | } |
@@ -1227,5 +1260,5 @@ mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) | |||
1227 | 1260 | ||
1228 | if (mwifiex_dequeue_tx_packet(adapter)) | 1261 | if (mwifiex_dequeue_tx_packet(adapter)) |
1229 | break; | 1262 | break; |
1230 | } while (true); | 1263 | } while (!mwifiex_wmm_lists_empty(adapter)); |
1231 | } | 1264 | } |