summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mwifiex/wmm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mwifiex/wmm.c')
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c208
1 files changed, 74 insertions, 134 deletions
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 32adc878041d..4be3d33ceae8 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
@@ -436,10 +432,7 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
= priv->aggr_prio_tbl[7].ampdu_user
= BA_STREAM_NOT_ALLOWED;
- priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
- priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE;
- priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE;
-
+ mwifiex_set_ba_params(priv);
mwifiex_reset_11n_rx_seq_num(priv);
atomic_set(&priv->wmm.tx_pkts_queued, 0);
@@ -533,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;
}
}
@@ -688,13 +679,13 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
ra_list->total_pkts_size += skb->len;
ra_list->pkt_count++;
- atomic_inc(&priv->wmm.tx_pkts_queued);
-
if (atomic_read(&priv->wmm.highest_queued_prio) <
tos_to_tid_inv[tid_down])
atomic_set(&priv->wmm.highest_queued_prio,
tos_to_tid_inv[tid_down]);
+ atomic_inc(&priv->wmm.tx_pkts_queued);
+
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
}
@@ -886,128 +877,65 @@ 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_bss_prio_node *bssprio_node, *bssprio_head;
+ struct mwifiex_ra_list_tbl *ptr;
struct mwifiex_tid_tbl *tid_ptr;
atomic_t *hqp;
- int is_list_empty;
- unsigned long flags;
+ unsigned long flags_bss, flags_ra;
int i, j;
+ /* check the BSS with highest priority first */
for (j = adapter->priv_num - 1; j >= 0; --j) {
spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock,
- flags);
- is_list_empty = list_empty(&adapter->bss_prio_tbl[j]
- .bss_prio_head);
- spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock,
- flags);
- if (is_list_empty)
- continue;
+ flags_bss);
- if (adapter->bss_prio_tbl[j].bss_prio_cur ==
- (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);
- }
+ /* iterate over BSS with the equal priority */
+ list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur,
+ &adapter->bss_prio_tbl[j].bss_prio_head,
+ list) {
- bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur;
- bssprio_head = bssprio_node;
+ priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv;
- do {
- priv_tmp = bssprio_node->priv;
- hqp = &priv_tmp->wmm.highest_queued_prio;
+ if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)
+ continue;
+ /* iterate over the WMM queues of the BSS */
+ hqp = &priv_tmp->wmm.highest_queued_prio;
for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) {
+ spin_lock_irqsave(&priv_tmp->wmm.
+ ra_list_spinlock, flags_ra);
+
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)
- continue;
-
- spin_lock_irqsave(&tid_ptr->tid_tbl_lock,
- flags);
- is_list_empty =
- list_empty(&adapter->bss_prio_tbl[j]
- .bss_prio_head);
- spin_unlock_irqrestore(&tid_ptr->tid_tbl_lock,
- flags);
- if (is_list_empty)
- continue;
-
- /*
- * 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);
-
- 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 {
- is_list_empty =
- skb_queue_empty(&ptr->skb_head);
+ /* iterate over receiver addresses */
+ list_for_each_entry(ptr, &tid_ptr->ra_list,
+ list) {
- if (!is_list_empty)
+ 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);
+ spin_unlock_irqrestore(&priv_tmp->wmm.
+ ra_list_spinlock,
+ flags_ra);
}
+ }
- /* No packet at any TID for this priv. Mark as such
- * to skip checking TIDs for this priv (until pkt is
- * added).
- */
- atomic_set(hqp, NO_PKT_PRIO_TID);
-
- /* 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);
+ spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock,
+ flags_bss);
}
+
return NULL;
found:
- spin_lock_irqsave(&priv_tmp->wmm.ra_list_spinlock, flags);
+ /* holds bss_prio_lock / ra_list_spinlock */
if (atomic_read(hqp) > i)
atomic_set(hqp, i);
- spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags);
+ spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra);
+ spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock,
+ flags_bss);
*priv = priv_tmp;
*tid = tos_to_tid[i];
@@ -1015,6 +943,42 @@ found:
return ptr;
}
+/* This functions rotates ra and bss lists so packets are picked round robin.
+ *
+ * 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. Same applies to bss nodes of equal
+ * priority.
+ *
+ * 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_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];
+ 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);
+ if (mwifiex_is_ralist_valid(priv, ra, tid)) {
+ priv->wmm.packets_out[tid]++;
+ /* same as above */
+ 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.
*/
@@ -1101,20 +1065,8 @@ 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;
- }
- 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);
+ mwifiex_rotate_priolists(priv, ptr, ptr_index);
atomic_dec(&priv->wmm.tx_pkts_queued);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
- ra_list_flags);
}
}
@@ -1218,20 +1170,8 @@ 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;
- }
- 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);
+ mwifiex_rotate_priolists(priv, ptr, ptr_index);
atomic_dec(&priv->wmm.tx_pkts_queued);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
- ra_list_flags);
}
}