Skip to content

Commit

Permalink
mwifiex: support RX AMSDU aggregation for uAP
Browse files Browse the repository at this point in the history
This patch adds support for reception and decoding of AMSDU
aggregation frames for AP interface.
Patch also adds support for handling AMSDU aggregation event.

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 838e4f4 commit d1cf3b9
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 9 deletions.
26 changes: 20 additions & 6 deletions drivers/net/wireless/mwifiex/11n_rxreorder.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,13 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
tbl->rx_reorder_ptr[i] = NULL;
}
spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
if (rx_tmp_ptr)
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
if (rx_tmp_ptr) {
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
else
mwifiex_process_rx_packet(priv->adapter,
rx_tmp_ptr);
}
}

spin_lock_irqsave(&priv->rx_pkt_lock, flags);
Expand Down Expand Up @@ -97,7 +102,11 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
rx_tmp_ptr = tbl->rx_reorder_ptr[i];
tbl->rx_reorder_ptr[i] = NULL;
spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);

if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
else
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
}

spin_lock_irqsave(&priv->rx_pkt_lock, flags);
Expand Down Expand Up @@ -148,7 +157,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
* This function returns the pointer to an entry in Rx reordering
* table which matches the given TA/TID pair.
*/
static struct mwifiex_rx_reorder_tbl *
struct mwifiex_rx_reorder_tbl *
mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
{
struct mwifiex_rx_reorder_tbl *tbl;
Expand Down Expand Up @@ -396,8 +405,13 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,

tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
if (!tbl) {
if (pkt_type != PKT_TYPE_BAR)
mwifiex_process_rx_packet(priv->adapter, payload);
if (pkt_type != PKT_TYPE_BAR) {
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
mwifiex_handle_uap_rx_forward(priv, payload);
else
mwifiex_process_rx_packet(priv->adapter,
payload);
}
return 0;
}
start_win = tbl->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 @@ -68,5 +68,7 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
mwifiex_private
*priv, int tid,
u8 *ta);
struct mwifiex_rx_reorder_tbl *
mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta);

#endif /* _MWIFIEX_11N_RXREORDER_H_ */
13 changes: 13 additions & 0 deletions drivers/net/wireless/mwifiex/uap_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,19 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
/* For future development */
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
break;
case EVENT_AMSDU_AGGR_CTRL:
dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n",
*(u16 *)adapter->event_body);

if (priv->media_connected) {
adapter->tx_buf_size =
min(adapter->curr_tx_buf_size,
le16_to_cpu(*(__le16 *)adapter->event_body));

dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
adapter->tx_buf_size);
}
break;
default:
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
eventcause);
Expand Down
56 changes: 53 additions & 3 deletions drivers/net/wireless/mwifiex/uap_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "ioctl.h"
#include "main.h"
#include "wmm.h"
#include "11n_aggr.h"
#include "11n_rxreorder.h"

static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
struct sk_buff *skb)
Expand Down Expand Up @@ -165,6 +167,9 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
struct rx_packet_hdr *rx_pkt_hdr;
u16 rx_pkt_type;
u8 ta[ETH_ALEN], pkt_type;
struct mwifiex_sta_node *node;

struct mwifiex_private *priv =
mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
rx_info->bss_type);
Expand All @@ -191,15 +196,60 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,

return 0;
}
ret = mwifiex_handle_uap_rx_forward(priv, skb);

if (ret) {
priv->stats.rx_dropped++;
if (le16_to_cpu(uap_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) {
struct sk_buff_head list;
struct sk_buff *rx_skb;

__skb_queue_head_init(&list);
skb_pull(skb, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
skb_trim(skb, le16_to_cpu(uap_rx_pd->rx_pkt_length));

ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
priv->wdev->iftype, 0, false);

while (!skb_queue_empty(&list)) {
rx_skb = __skb_dequeue(&list);
ret = mwifiex_recv_packet(adapter, rx_skb);
if (ret)
dev_err(adapter->dev,
"AP:Rx A-MSDU failed");
}

return 0;
}

memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);

if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
node = mwifiex_get_sta_entry(priv, ta);
if (node)
node->rx_seq[uap_rx_pd->priority] =
le16_to_cpu(uap_rx_pd->seq_num);
}

if (!priv->ap_11n_enabled ||
(!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) &&
(le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) {
ret = mwifiex_handle_uap_rx_forward(priv, skb);
return ret;
}

/* Reorder and send to kernel */
pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type);
ret = mwifiex_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num),
uap_rx_pd->priority, ta, pkt_type,
skb);

if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
if (adapter->if_ops.data_complete)
adapter->if_ops.data_complete(adapter, skb);
else
dev_kfree_skb_any(skb);
}

if (ret)
priv->stats.rx_dropped++;

return ret;
}

0 comments on commit d1cf3b9

Please sign in to comment.