From 2e23731954d3641a418455e8e0c37c9b8aa7f567 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart <[andreas.fenkart@streamunlimited.com]> Date: Thu, 18 Apr 2013 16:33:45 -0700 Subject: 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 Acked-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/wmm.c | 97 ++++++++++++++------------------------ 1 file changed, 36 insertions(+), 61 deletions(-) (limited to 'drivers/net/wireless/mwifiex/wmm.c') diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 2cc81ba590e3..b48e03cde23f 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); } } -- cgit v1.2.3