Commit b006ed54 authored by Andreas Fenkart's avatar Andreas Fenkart Committed by John W. Linville

mwifiex: rework round robin scheduling of bss nodes.

Rotate bss prio list, so the bss next to the one served, will come first
in the list of bss' with equal priority. This way we pick bss nodes in a
round robin fashion. Using list rotation instead of a cur ptr simplifies
iteration to calling list_for_each_entry. List rotation is done via
list_move, where the head itself is temporarily removed and then
re-inserted after the bss just served.
Signed-off-by: default avatarAndreas Fenkart <andreas.fenkart@streamunlimited.com>
Acked-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2e237319
...@@ -297,12 +297,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, ...@@ -297,12 +297,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
} }
if (ret != -EBUSY) { if (ret != -EBUSY) {
mwifiex_rotate_priolists(priv, pra_list, ptrindex); 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);
} }
return 0; return 0;
......
...@@ -44,8 +44,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) ...@@ -44,8 +44,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
bss_prio->priv = priv; bss_prio->priv = priv;
INIT_LIST_HEAD(&bss_prio->list); INIT_LIST_HEAD(&bss_prio->list);
if (!tbl[priv->bss_priority].bss_prio_cur)
tbl[priv->bss_priority].bss_prio_cur = bss_prio;
spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags); spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head); list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
...@@ -525,7 +523,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) ...@@ -525,7 +523,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
for (i = 0; i < adapter->priv_num; ++i) { for (i = 0; i < adapter->priv_num; ++i) {
INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
adapter->bss_prio_tbl[i].bss_prio_cur = NULL;
spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock); spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock);
} }
...@@ -625,42 +622,36 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) ...@@ -625,42 +622,36 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
{ {
int i; int i;
struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_bss_prio_node *bssprio_node, *tmp_node, **cur; struct mwifiex_bss_prio_node *bssprio_node, *tmp_node;
struct list_head *head; struct list_head *head;
spinlock_t *lock; /* bss priority lock */ spinlock_t *lock; /* bss priority lock */
unsigned long flags; unsigned long flags;
for (i = 0; i < adapter->priv_num; ++i) { for (i = 0; i < adapter->priv_num; ++i) {
head = &adapter->bss_prio_tbl[i].bss_prio_head; head = &adapter->bss_prio_tbl[i].bss_prio_head;
cur = &adapter->bss_prio_tbl[i].bss_prio_cur;
lock = &adapter->bss_prio_tbl[i].bss_prio_lock; lock = &adapter->bss_prio_tbl[i].bss_prio_lock;
dev_dbg(adapter->dev, "info: delete BSS priority table," dev_dbg(adapter->dev, "info: delete BSS priority table,"
" bss_type = %d, bss_num = %d, i = %d," " bss_type = %d, bss_num = %d, i = %d,"
" head = %p, cur = %p\n", " head = %p\n",
priv->bss_type, priv->bss_num, i, head, *cur); priv->bss_type, priv->bss_num, i, head);
if (*cur) {
{
spin_lock_irqsave(lock, flags); spin_lock_irqsave(lock, flags);
if (list_empty(head)) { if (list_empty(head)) {
spin_unlock_irqrestore(lock, flags); spin_unlock_irqrestore(lock, flags);
continue; continue;
} }
bssprio_node = list_first_entry(head,
struct mwifiex_bss_prio_node, list);
spin_unlock_irqrestore(lock, flags);
list_for_each_entry_safe(bssprio_node, tmp_node, head, list_for_each_entry_safe(bssprio_node, tmp_node, head,
list) { list) {
if (bssprio_node->priv == priv) { if (bssprio_node->priv == priv) {
dev_dbg(adapter->dev, "info: Delete " dev_dbg(adapter->dev, "info: Delete "
"node %p, next = %p\n", "node %p, next = %p\n",
bssprio_node, tmp_node); bssprio_node, tmp_node);
spin_lock_irqsave(lock, flags);
list_del(&bssprio_node->list); list_del(&bssprio_node->list);
spin_unlock_irqrestore(lock, flags);
kfree(bssprio_node); kfree(bssprio_node);
} }
} }
*cur = (struct mwifiex_bss_prio_node *)head; spin_unlock_irqrestore(lock, flags);
} }
} }
} }
......
...@@ -878,37 +878,25 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, ...@@ -878,37 +878,25 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
{ {
struct mwifiex_private *priv_tmp; struct mwifiex_private *priv_tmp;
struct mwifiex_ra_list_tbl *ptr; struct mwifiex_ra_list_tbl *ptr;
struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head;
struct mwifiex_tid_tbl *tid_ptr; struct mwifiex_tid_tbl *tid_ptr;
atomic_t *hqp; atomic_t *hqp;
unsigned long flags_bss, flags_ra; unsigned long flags_bss, flags_ra;
int i, j; int i, j;
/* check the BSS with highest priority first */
for (j = adapter->priv_num - 1; j >= 0; --j) { for (j = adapter->priv_num - 1; j >= 0; --j) {
spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock,
flags_bss); flags_bss);
if (list_empty(&adapter->bss_prio_tbl[j].bss_prio_head)) /* iterate over BSS with the equal priority */
goto skip_prio_tbl; list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur,
&adapter->bss_prio_tbl[j].bss_prio_head,
if (adapter->bss_prio_tbl[j].bss_prio_cur == list) {
(struct mwifiex_bss_prio_node *)
&adapter->bss_prio_tbl[j].bss_prio_head) {
adapter->bss_prio_tbl[j].bss_prio_cur =
list_first_entry(&adapter->bss_prio_tbl[j]
.bss_prio_head,
struct mwifiex_bss_prio_node,
list);
}
bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur;
bssprio_head = bssprio_node;
do { priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv;
priv_tmp = bssprio_node->priv;
if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0) if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)
goto skip_bss; continue;
/* iterate over the WMM queues of the BSS */ /* iterate over the WMM queues of the BSS */
hqp = &priv_tmp->wmm.highest_queued_prio; hqp = &priv_tmp->wmm.highest_queued_prio;
...@@ -933,24 +921,8 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, ...@@ -933,24 +921,8 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
ra_list_spinlock, ra_list_spinlock,
flags_ra); flags_ra);
} }
}
skip_bss:
/* Get next bss priority node */
bssprio_node = list_first_entry(&bssprio_node->list,
struct mwifiex_bss_prio_node,
list);
if (bssprio_node ==
(struct mwifiex_bss_prio_node *)
&adapter->bss_prio_tbl[j].bss_prio_head)
/* Get next bss priority node */
bssprio_node = list_first_entry(
&bssprio_node->list,
struct mwifiex_bss_prio_node,
list);
} while (bssprio_node != bssprio_head);
skip_prio_tbl:
spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock,
flags_bss); flags_bss);
} }
...@@ -971,12 +943,12 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, ...@@ -971,12 +943,12 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
return ptr; return ptr;
} }
/* This functions rotates ra lists so packets are picked in round robin /* This functions rotates ra and bss lists so packets are picked round robin.
* fashion.
* *
* After a packet is successfully transmitted, rotate the ra list, so the ra * 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 * next to the one transmitted, will come first in the list. This way we pick
* the ra in a round robin fashion. * the ra' in a round robin fashion. Same applies to bss nodes of equal
* priority.
* *
* Function also increments wmm.packets_out counter. * Function also increments wmm.packets_out counter.
*/ */
...@@ -984,17 +956,24 @@ void mwifiex_rotate_priolists(struct mwifiex_private *priv, ...@@ -984,17 +956,24 @@ void mwifiex_rotate_priolists(struct mwifiex_private *priv,
struct mwifiex_ra_list_tbl *ra, struct mwifiex_ra_list_tbl *ra,
int tid) int tid)
{ {
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid]; struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid];
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
/*
* dirty trick: we remove 'head' temporarily and reinsert it after
* curr bss node. imagine list to stay fixed while head is moved
*/
list_move(&tbl[priv->bss_priority].bss_prio_head,
&tbl[priv->bss_priority].bss_prio_cur->list);
spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
if (mwifiex_is_ralist_valid(priv, ra, tid)) { if (mwifiex_is_ralist_valid(priv, ra, tid)) {
priv->wmm.packets_out[tid]++; priv->wmm.packets_out[tid]++;
/* /* same as above */
* 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); list_move(&tid_ptr->ra_list, &ra->list);
} }
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
...@@ -1087,12 +1066,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, ...@@ -1087,12 +1066,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
ra_list_flags); ra_list_flags);
} else { } else {
mwifiex_rotate_priolists(priv, ptr, ptr_index); 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]
.bss_prio_cur->list,
struct mwifiex_bss_prio_node,
list);
atomic_dec(&priv->wmm.tx_pkts_queued); atomic_dec(&priv->wmm.tx_pkts_queued);
} }
} }
...@@ -1198,12 +1171,6 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, ...@@ -1198,12 +1171,6 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
} }
if (ret != -EBUSY) { if (ret != -EBUSY) {
mwifiex_rotate_priolists(priv, ptr, ptr_index); 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]
.bss_prio_cur->list,
struct mwifiex_bss_prio_node,
list);
atomic_dec(&priv->wmm.tx_pkts_queued); atomic_dec(&priv->wmm.tx_pkts_queued);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment