aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXinming Hu <huxm@marvell.com>2016-04-05 04:04:39 -0400
committerKalle Valo <kvalo@codeaurora.org>2016-04-07 12:42:25 -0400
commitbf00dc22bc7a72d58fd1945814321b30948dc83b (patch)
tree55945622e909dafed3cd7fe4837d7896b27a4cf5
parentad5ca845e3d194703be82ad4a2f3042f2e198e2b (diff)
mwifiex: AMSDU Rx frame handling in AP mode
This patch processes sub AMSDU frame received in AP mode. If a packet is multicast/broadcast, it is sent to kernel/upper layer as well as queued back to AP TX queue so that it can be sent to other associated stations. If a packet is unicast and RA is present in associated station list, it is again requeued into AP TX queue. If a packet is unicast and RA is not in associated station list, packet is forwarded to kernel to handle routing logic. Signed-off-by: Xinming Hu <huxm@marvell.com> Signed-off-by: Cathy Luo <cluo@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c5
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_txrx.c90
3 files changed, 96 insertions, 1 deletions
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index 09578c6cde59..a74cc43b1953 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -59,7 +59,10 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
59 skb->len); 59 skb->len);
60 } 60 }
61 61
62 ret = mwifiex_recv_packet(priv, rx_skb); 62 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
63 ret = mwifiex_uap_recv_packet(priv, rx_skb);
64 else
65 ret = mwifiex_recv_packet(priv, rx_skb);
63 if (ret == -1) 66 if (ret == -1)
64 mwifiex_dbg(priv->adapter, ERROR, 67 mwifiex_dbg(priv->adapter, ERROR,
65 "Rx of A-MSDU failed"); 68 "Rx of A-MSDU failed");
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index aafc4ab4e5ae..a159fbef20cd 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1019,6 +1019,8 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter);
1019int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); 1019int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *);
1020 1020
1021int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb); 1021int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb);
1022int mwifiex_uap_recv_packet(struct mwifiex_private *priv,
1023 struct sk_buff *skb);
1022 1024
1023int mwifiex_process_mgmt_packet(struct mwifiex_private *priv, 1025int mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
1024 struct sk_buff *skb); 1026 struct sk_buff *skb);
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
index ee7fe58dd266..c95b61dc87c2 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
@@ -265,6 +265,96 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
265 return mwifiex_process_rx_packet(priv, skb); 265 return mwifiex_process_rx_packet(priv, skb);
266} 266}
267 267
268int mwifiex_uap_recv_packet(struct mwifiex_private *priv,
269 struct sk_buff *skb)
270{
271 struct mwifiex_adapter *adapter = adapter;
272 struct mwifiex_sta_node *src_node;
273 struct ethhdr *p_ethhdr;
274 struct sk_buff *skb_uap;
275 struct mwifiex_txinfo *tx_info;
276
277 if (!skb)
278 return -1;
279
280 p_ethhdr = (void *)skb->data;
281 src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source);
282 if (src_node) {
283 src_node->stats.last_rx = jiffies;
284 src_node->stats.rx_bytes += skb->len;
285 src_node->stats.rx_packets++;
286 }
287
288 skb->dev = priv->netdev;
289 skb->protocol = eth_type_trans(skb, priv->netdev);
290 skb->ip_summed = CHECKSUM_NONE;
291
292 /* This is required only in case of 11n and USB/PCIE as we alloc
293 * a buffer of 4K only if its 11N (to be able to receive 4K
294 * AMSDU packets). In case of SD we allocate buffers based
295 * on the size of packet and hence this is not needed.
296 *
297 * Modifying the truesize here as our allocation for each
298 * skb is 4K but we only receive 2K packets and this cause
299 * the kernel to start dropping packets in case where
300 * application has allocated buffer based on 2K size i.e.
301 * if there a 64K packet received (in IP fragments and
302 * application allocates 64K to receive this packet but
303 * this packet would almost double up because we allocate
304 * each 1.5K fragment in 4K and pass it up. As soon as the
305 * 64K limit hits kernel will start to drop rest of the
306 * fragments. Currently we fail the Filesndl-ht.scr script
307 * for UDP, hence this fix
308 */
309 if ((adapter->iface_type == MWIFIEX_USB ||
310 adapter->iface_type == MWIFIEX_PCIE) &&
311 (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
312 skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
313
314 if (is_multicast_ether_addr(p_ethhdr->h_dest) ||
315 mwifiex_get_sta_entry(priv, p_ethhdr->h_dest)) {
316 if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN)
317 skb_uap =
318 skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
319 else
320 skb_uap = skb_copy(skb, GFP_ATOMIC);
321
322 if (likely(skb_uap)) {
323 tx_info = MWIFIEX_SKB_TXCB(skb_uap);
324 memset(tx_info, 0, sizeof(*tx_info));
325 tx_info->bss_num = priv->bss_num;
326 tx_info->bss_type = priv->bss_type;
327 tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
328 __net_timestamp(skb_uap);
329 mwifiex_wmm_add_buf_txqueue(priv, skb_uap);
330 atomic_inc(&adapter->tx_pending);
331 atomic_inc(&adapter->pending_bridged_pkts);
332 if ((atomic_read(&adapter->pending_bridged_pkts) >=
333 MWIFIEX_BRIDGED_PKTS_THR_HIGH)) {
334 mwifiex_dbg(adapter, ERROR,
335 "Tx: Bridge packet limit reached. Drop packet!\n");
336 mwifiex_uap_cleanup_tx_queues(priv);
337 }
338
339 } else {
340 mwifiex_dbg(adapter, ERROR, "failed to allocate skb_uap");
341 }
342
343 mwifiex_queue_main_work(adapter);
344 /* Don't forward Intra-BSS unicast packet to upper layer*/
345 if (mwifiex_get_sta_entry(priv, p_ethhdr->h_dest))
346 return 0;
347 }
348
349 /* Forward multicast/broadcast packet to upper layer*/
350 if (in_interrupt())
351 netif_rx(skb);
352 else
353 netif_rx_ni(skb);
354
355 return 0;
356}
357
268/* 358/*
269 * This function processes the packet received on AP interface. 359 * This function processes the packet received on AP interface.
270 * 360 *