diff options
author | Andreas Fenkart <[andreas.fenkart@streamunlimited.com]> | 2013-04-18 16:33:45 -0700 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-23 15:18:40 -0400 |
commit | 2e23731954d3641a418455e8e0c37c9b8aa7f567 (patch) | |
tree | 661b631bebb8b89c6d8d207e3d5f722fe31a4ce9 | |
parent | 1aac1e91171586e4d0981e40484a7c93d9b1f289 (diff) |
mwifiex: replace ra_list_curr by list rotation.
After a packet is successfully transmitted, ra list is rotated, so the ra
next to the one transmitted, will be the first in the list. This way we
pick the ra' in a round robin fashion. This significantly simplifies
iteration in mwifiex_wmm_get_highest_priolist_ptr to a call to
list_for_each_entry.
List rotation is done via list_move, where the head itself is temporarily
removed and then re-inserted after the item just transferred.
Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com>
Acked-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/mwifiex/11n_aggr.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 97 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.h | 3 |
4 files changed, 40 insertions, 69 deletions
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index af8fe6352ee..c6d74518aaa 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -296,19 +296,13 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, break; } if (ret != -EBUSY) { - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - if (mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { - priv->wmm.packets_out[ptrindex]++; - priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list; - } + mwifiex_rotate_priolists(priv, pra_list, ptrindex); /* Now bss_prio_cur pointer points to next node */ adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = list_first_entry( &adapter->bss_prio_tbl[priv->bss_priority] .bss_prio_cur->list, struct mwifiex_bss_prio_node, list); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); } return 0; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index b7484efc944..4ef67fca06d 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -213,7 +213,6 @@ struct mwifiex_ra_list_tbl { struct mwifiex_tid_tbl { struct list_head ra_list; - struct mwifiex_ra_list_tbl *ra_list_curr; }; #define WMM_HIGHEST_PRIORITY 7 diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 2cc81ba590e..b48e03cde23 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -191,9 +191,6 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) } list_add_tail(&ra_list->list, &priv->wmm.tid_tbl_ptr[i].ra_list); - - if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr) - priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list; } } @@ -424,7 +421,6 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i]; priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i]; priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; - priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; } priv->aggr_prio_tbl[6].amsdu @@ -530,8 +526,6 @@ static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv) } INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list); - - priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; } } @@ -883,7 +877,7 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, struct mwifiex_private **priv, int *tid) { struct mwifiex_private *priv_tmp; - struct mwifiex_ra_list_tbl *ptr, *head; + struct mwifiex_ra_list_tbl *ptr; struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; struct mwifiex_tid_tbl *tid_ptr; atomic_t *hqp; @@ -926,51 +920,15 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, tid_ptr = &(priv_tmp)->wmm. tid_tbl_ptr[tos_to_tid[i]]; - /* For non-STA ra_list_curr may be NULL */ - if (!tid_ptr->ra_list_curr) - goto skip_wmm_queue; - - if (list_empty(&tid_ptr->ra_list)) - goto skip_wmm_queue; - - /* - * Always choose the next ra we transmitted - * last time, this way we pick the ra's in - * round robin fashion. - */ - ptr = list_first_entry( - &tid_ptr->ra_list_curr->list, - struct mwifiex_ra_list_tbl, - list); + /* iterate over receiver addresses */ + list_for_each_entry(ptr, &tid_ptr->ra_list, + list) { - head = ptr; - if (ptr == (struct mwifiex_ra_list_tbl *) - &tid_ptr->ra_list) { - /* Get next ra */ - ptr = list_first_entry(&ptr->list, - struct mwifiex_ra_list_tbl, list); - head = ptr; - } - - do { if (!skb_queue_empty(&ptr->skb_head)) /* holds both locks */ goto found; + } - /* Get next ra */ - ptr = list_first_entry(&ptr->list, - struct mwifiex_ra_list_tbl, - list); - if (ptr == - (struct mwifiex_ra_list_tbl *) - &tid_ptr->ra_list) - ptr = list_first_entry( - &ptr->list, - struct mwifiex_ra_list_tbl, - list); - } while (ptr != head); - -skip_wmm_queue: spin_unlock_irqrestore(&priv_tmp->wmm. ra_list_spinlock, flags_ra); @@ -1013,6 +971,35 @@ found: return ptr; } +/* This functions rotates ra lists so packets are picked in round robin + * fashion. + * + * After a packet is successfully transmitted, rotate the ra list, so the ra + * next to the one transmitted, will come first in the list. This way we pick + * the ra in a round robin fashion. + * + * Function also increments wmm.packets_out counter. + */ +void mwifiex_rotate_priolists(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ra, + int tid) +{ + struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid]; + unsigned long flags; + + spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + if (mwifiex_is_ralist_valid(priv, ra, tid)) { + priv->wmm.packets_out[tid]++; + /* + * dirty trick: we remove 'head' temporarily and reinsert it + * after curr bss node. imagine list to stay fixed while only + * head is moved + */ + list_move(&tid_ptr->ra_list, &ra->list); + } + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); +} + /* * This function checks if 11n aggregation is possible. */ @@ -1099,11 +1086,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); } else { - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - priv->wmm.packets_out[ptr_index]++; - priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; - } + mwifiex_rotate_priolists(priv, ptr, ptr_index); adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = list_first_entry( &adapter->bss_prio_tbl[priv->bss_priority] @@ -1111,8 +1094,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, struct mwifiex_bss_prio_node, list); atomic_dec(&priv->wmm.tx_pkts_queued); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); } } @@ -1216,11 +1197,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, break; } if (ret != -EBUSY) { - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - priv->wmm.packets_out[ptr_index]++; - priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; - } + mwifiex_rotate_priolists(priv, ptr, ptr_index); adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = list_first_entry( &adapter->bss_prio_tbl[priv->bss_priority] @@ -1228,8 +1205,6 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, struct mwifiex_bss_prio_node, list); atomic_dec(&priv->wmm.tx_pkts_queued); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); } } diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h index b92f39d8963..644d6e0c51c 100644 --- a/drivers/net/wireless/mwifiex/wmm.h +++ b/drivers/net/wireless/mwifiex/wmm.h @@ -85,6 +85,9 @@ mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead) void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, struct sk_buff *skb); void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra); +void mwifiex_rotate_priolists(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ra, + int tid); int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter); void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter); |