Skip to content

Commit

Permalink
mwifiex: add 11n Block Ack support for uAP
Browse files Browse the repository at this point in the history
This patch adds support for handling BA request and BA setup
events for AP interface.

RA list is marked as either 11n enabled or disabled from station's
capabilities in association request. BA setup is initiated only
after some specific number of packets for particular RA list are
transmitted.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Avinash Patil authored and John W. Linville committed Aug 6, 2012
1 parent d1cf3b9 commit 5a009ad
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 9 deletions.
14 changes: 14 additions & 0 deletions drivers/net/wireless/mwifiex/11n.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,18 @@ mwifiex_is_ba_stream_setup(struct mwifiex_private *priv,

return false;
}

/*
* This function checks whether associated station is 11n enabled
*/
static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
struct mwifiex_sta_node *node)
{

if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) ||
!priv->ap_11n_enabled)
return 0;

return node->is_11n_enabled;
}
#endif /* !_MWIFIEX_11N_H_ */
15 changes: 11 additions & 4 deletions drivers/net/wireless/mwifiex/11n_rxreorder.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
struct mwifiex_rx_reorder_tbl *tbl, *new_node;
u16 last_seq = 0;
unsigned long flags;
struct mwifiex_sta_node *node;

/*
* If we get a TID, ta pair which is already present dispatch all the
Expand All @@ -257,13 +258,19 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
new_node->tid = tid;
memcpy(new_node->ta, ta, ETH_ALEN);
new_node->start_win = seq_num;
if (mwifiex_queuing_ra_based(priv))
/* TODO for adhoc */

if (mwifiex_queuing_ra_based(priv)) {
dev_dbg(priv->adapter->dev,
"info: ADHOC:last_seq=%d start_win=%d\n",
"info: AP/ADHOC:last_seq=%d start_win=%d\n",
last_seq, new_node->start_win);
else
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
node = mwifiex_get_sta_entry(priv, ta);
if (node)
last_seq = node->rx_seq[tid];
}
} else {
last_seq = priv->rx_seq[tid];
}

if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
last_seq >= new_node->start_win)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/mwifiex/11n_rxreorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#define ADDBA_RSP_STATUS_ACCEPT 0

#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff
#define BA_SETUP_MAX_PACKET_THRESHOLD 16
#define BA_SETUP_PACKET_OFFSET 16

static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
{
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/mwifiex/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ struct mwifiex_ra_list_tbl {
u8 ra[ETH_ALEN];
u32 total_pkts_size;
u32 is_11n_enabled;
u16 max_amsdu;
u16 pkt_count;
u8 ba_packet_thr;
};

struct mwifiex_tid_tbl {
Expand Down
21 changes: 21 additions & 0 deletions drivers/net/wireless/mwifiex/uap_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "decl.h"
#include "main.h"
#include "11n.h"

/*
* This function will return the pointer to station entry in station list
Expand Down Expand Up @@ -168,6 +169,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
struct mwifiex_assoc_event *event;
struct mwifiex_sta_node *node;
u8 *deauth_mac;
struct host_cmd_ds_11n_batimeout *ba_timeout;

switch (eventcause) {
case EVENT_UAP_STA_ASSOC:
Expand Down Expand Up @@ -255,6 +257,25 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
adapter->tx_buf_size);
}
break;
case EVENT_ADDBA:
dev_dbg(adapter->dev, "event: ADDBA Request\n");
if (priv->media_connected)
mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP,
HostCmd_ACT_GEN_SET, 0,
adapter->event_body);
break;
case EVENT_DELBA:
dev_dbg(adapter->dev, "event: DELBA Request\n");
if (priv->media_connected)
mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
break;
case EVENT_BA_STREAM_TIEMOUT:
dev_dbg(adapter->dev, "event: BA Stream timeout\n");
if (priv->media_connected) {
ba_timeout = (void *)adapter->event_body;
mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
}
break;
default:
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
eventcause);
Expand Down
59 changes: 54 additions & 5 deletions drivers/net/wireless/mwifiex/wmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,29 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
return ra_list;
}

/* This function returns random no between 16 and 32 to be used as threshold
* for no of packets after which BA setup is initiated.
*/
static u8 mwifiex_get_random_ba_threshold(void)
{
u32 sec, usec;
struct timeval ba_tstamp;
u8 ba_threshold;

/* setup ba_packet_threshold here random number between
* [BA_SETUP_PACKET_OFFSET,
* BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1]
*/

do_gettimeofday(&ba_tstamp);
sec = (ba_tstamp.tv_sec & 0xFFFF) + (ba_tstamp.tv_sec >> 16);
usec = (ba_tstamp.tv_usec & 0xFFFF) + (ba_tstamp.tv_usec >> 16);
ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD)
+ BA_SETUP_PACKET_OFFSET;

return ba_threshold;
}

/*
* This function allocates and adds a RA list for all TIDs
* with the given RA.
Expand All @@ -137,6 +160,12 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
int i;
struct mwifiex_ra_list_tbl *ra_list;
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_sta_node *node;
unsigned long flags;

spin_lock_irqsave(&priv->sta_list_spinlock, flags);
node = mwifiex_get_sta_entry(priv, ra);
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);

for (i = 0; i < MAX_NUM_TID; ++i) {
ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
Expand All @@ -145,14 +174,24 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
if (!ra_list)
break;

if (!mwifiex_queuing_ra_based(priv))
ra_list->is_11n_enabled = 0;
if (!mwifiex_queuing_ra_based(priv)) {
ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
else
ra_list->is_11n_enabled = false;
} else {
ra_list->is_11n_enabled =
mwifiex_is_sta_11n_enabled(priv, node);
if (ra_list->is_11n_enabled)
ra_list->max_amsdu = node->max_amsdu;
}

dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
ra_list, ra_list->is_11n_enabled);

if (ra_list->is_11n_enabled) {
ra_list->pkt_count = 0;
ra_list->ba_packet_thr =
mwifiex_get_random_ba_threshold();
}
list_add_tail(&ra_list->list,
&priv->wmm.tid_tbl_ptr[i].ra_list);

Expand Down Expand Up @@ -647,6 +686,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
skb_queue_tail(&ra_list->skb_head, skb);

ra_list->total_pkts_size += skb->len;
ra_list->pkt_count++;

atomic_inc(&priv->wmm.tx_pkts_queued);

Expand Down Expand Up @@ -986,10 +1026,17 @@ mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
{
int count = 0, total_size = 0;
struct sk_buff *skb, *tmp;
int max_amsdu_size;

if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP && priv->ap_11n_enabled &&
ptr->is_11n_enabled)
max_amsdu_size = min_t(int, ptr->max_amsdu, max_buf_size);
else
max_amsdu_size = max_buf_size;

skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
total_size += skb->len;
if (total_size >= max_buf_size)
if (total_size >= max_amsdu_size)
break;
if (++count >= MIN_NUM_AMSDU)
return true;
Expand Down Expand Up @@ -1050,6 +1097,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
skb_queue_tail(&ptr->skb_head, skb);

ptr->total_pkts_size += skb->len;
ptr->pkt_count++;
tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
Expand Down Expand Up @@ -1231,7 +1279,8 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
/* ra_list_spinlock has been freed in
mwifiex_send_single_packet() */
} else {
if (mwifiex_is_ampdu_allowed(priv, tid)) {
if (mwifiex_is_ampdu_allowed(priv, tid) &&
ptr->pkt_count > ptr->ba_packet_thr) {
if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
mwifiex_create_ba_tbl(priv, ptr->ra, tid,
BA_SETUP_INPROGRESS);
Expand Down

0 comments on commit 5a009ad

Please sign in to comment.