aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2012-08-03 21:06:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-08-06 15:12:55 -0400
commitd1cf3b958cb6940cb4e0a71697458035dad9e5b9 (patch)
tree5a097894dd322dd303a04e1118ec9832e4f01be8 /drivers/net
parent838e4f44929782a2163c7bc95a7cd2da5d8b47f9 (diff)
mwifiex: support RX AMSDU aggregation for uAP
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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c26
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.h2
-rw-r--r--drivers/net/wireless/mwifiex/uap_event.c13
-rw-r--r--drivers/net/wireless/mwifiex/uap_txrx.c56
4 files changed, 88 insertions, 9 deletions
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 591ccd33f83c..20367fe1de44 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -54,8 +54,13 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
54 tbl->rx_reorder_ptr[i] = NULL; 54 tbl->rx_reorder_ptr[i] = NULL;
55 } 55 }
56 spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); 56 spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
57 if (rx_tmp_ptr) 57 if (rx_tmp_ptr) {
58 mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); 58 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
59 mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
60 else
61 mwifiex_process_rx_packet(priv->adapter,
62 rx_tmp_ptr);
63 }
59 } 64 }
60 65
61 spin_lock_irqsave(&priv->rx_pkt_lock, flags); 66 spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -97,7 +102,11 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
97 rx_tmp_ptr = tbl->rx_reorder_ptr[i]; 102 rx_tmp_ptr = tbl->rx_reorder_ptr[i];
98 tbl->rx_reorder_ptr[i] = NULL; 103 tbl->rx_reorder_ptr[i] = NULL;
99 spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); 104 spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
100 mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); 105
106 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
107 mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
108 else
109 mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
101 } 110 }
102 111
103 spin_lock_irqsave(&priv->rx_pkt_lock, flags); 112 spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -148,7 +157,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
148 * This function returns the pointer to an entry in Rx reordering 157 * This function returns the pointer to an entry in Rx reordering
149 * table which matches the given TA/TID pair. 158 * table which matches the given TA/TID pair.
150 */ 159 */
151static struct mwifiex_rx_reorder_tbl * 160struct mwifiex_rx_reorder_tbl *
152mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta) 161mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
153{ 162{
154 struct mwifiex_rx_reorder_tbl *tbl; 163 struct mwifiex_rx_reorder_tbl *tbl;
@@ -396,8 +405,13 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
396 405
397 tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); 406 tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
398 if (!tbl) { 407 if (!tbl) {
399 if (pkt_type != PKT_TYPE_BAR) 408 if (pkt_type != PKT_TYPE_BAR) {
400 mwifiex_process_rx_packet(priv->adapter, payload); 409 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
410 mwifiex_handle_uap_rx_forward(priv, payload);
411 else
412 mwifiex_process_rx_packet(priv->adapter,
413 payload);
414 }
401 return 0; 415 return 0;
402 } 416 }
403 start_win = tbl->start_win; 417 start_win = tbl->start_win;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 6c9815a0f5d8..1cd51d86fa57 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -68,5 +68,7 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
68 mwifiex_private 68 mwifiex_private
69 *priv, int tid, 69 *priv, int tid,
70 u8 *ta); 70 u8 *ta);
71struct mwifiex_rx_reorder_tbl *
72mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta);
71 73
72#endif /* _MWIFIEX_11N_RXREORDER_H_ */ 74#endif /* _MWIFIEX_11N_RXREORDER_H_ */
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 37cc642a1b83..6270c809130a 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -242,6 +242,19 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
242 /* For future development */ 242 /* For future development */
243 dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); 243 dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
244 break; 244 break;
245 case EVENT_AMSDU_AGGR_CTRL:
246 dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n",
247 *(u16 *)adapter->event_body);
248
249 if (priv->media_connected) {
250 adapter->tx_buf_size =
251 min(adapter->curr_tx_buf_size,
252 le16_to_cpu(*(__le16 *)adapter->event_body));
253
254 dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
255 adapter->tx_buf_size);
256 }
257 break;
245 default: 258 default:
246 dev_dbg(adapter->dev, "event: unknown event id: %#x\n", 259 dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
247 eventcause); 260 eventcause);
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index f55c5ac3e5e0..6d814f0f07f2 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -21,6 +21,8 @@
21#include "ioctl.h" 21#include "ioctl.h"
22#include "main.h" 22#include "main.h"
23#include "wmm.h" 23#include "wmm.h"
24#include "11n_aggr.h"
25#include "11n_rxreorder.h"
24 26
25static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, 27static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
26 struct sk_buff *skb) 28 struct sk_buff *skb)
@@ -165,6 +167,9 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
165 struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); 167 struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
166 struct rx_packet_hdr *rx_pkt_hdr; 168 struct rx_packet_hdr *rx_pkt_hdr;
167 u16 rx_pkt_type; 169 u16 rx_pkt_type;
170 u8 ta[ETH_ALEN], pkt_type;
171 struct mwifiex_sta_node *node;
172
168 struct mwifiex_private *priv = 173 struct mwifiex_private *priv =
169 mwifiex_get_priv_by_id(adapter, rx_info->bss_num, 174 mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
170 rx_info->bss_type); 175 rx_info->bss_type);
@@ -191,15 +196,60 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
191 196
192 return 0; 197 return 0;
193 } 198 }
194 ret = mwifiex_handle_uap_rx_forward(priv, skb);
195 199
196 if (ret) { 200 if (le16_to_cpu(uap_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) {
197 priv->stats.rx_dropped++; 201 struct sk_buff_head list;
202 struct sk_buff *rx_skb;
203
204 __skb_queue_head_init(&list);
205 skb_pull(skb, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
206 skb_trim(skb, le16_to_cpu(uap_rx_pd->rx_pkt_length));
207
208 ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
209 priv->wdev->iftype, 0, false);
210
211 while (!skb_queue_empty(&list)) {
212 rx_skb = __skb_dequeue(&list);
213 ret = mwifiex_recv_packet(adapter, rx_skb);
214 if (ret)
215 dev_err(adapter->dev,
216 "AP:Rx A-MSDU failed");
217 }
218
219 return 0;
220 }
221
222 memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
223
224 if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
225 node = mwifiex_get_sta_entry(priv, ta);
226 if (node)
227 node->rx_seq[uap_rx_pd->priority] =
228 le16_to_cpu(uap_rx_pd->seq_num);
229 }
230
231 if (!priv->ap_11n_enabled ||
232 (!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) &&
233 (le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) {
234 ret = mwifiex_handle_uap_rx_forward(priv, skb);
235 return ret;
236 }
237
238 /* Reorder and send to kernel */
239 pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type);
240 ret = mwifiex_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num),
241 uap_rx_pd->priority, ta, pkt_type,
242 skb);
243
244 if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
198 if (adapter->if_ops.data_complete) 245 if (adapter->if_ops.data_complete)
199 adapter->if_ops.data_complete(adapter, skb); 246 adapter->if_ops.data_complete(adapter, skb);
200 else 247 else
201 dev_kfree_skb_any(skb); 248 dev_kfree_skb_any(skb);
202 } 249 }
203 250
251 if (ret)
252 priv->stats.rx_dropped++;
253
204 return ret; 254 return ret;
205} 255}