Return-path: Received: from mx0b-0016f401.pphosted.com ([67.231.156.173]:33736 "EHLO mx0b-0016f401.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755763AbcDEILI (ORCPT ); Tue, 5 Apr 2016 04:11:08 -0400 Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u3586bJk013891 for ; Tue, 5 Apr 2016 01:11:07 -0700 Received: from sc-exch01.marvell.com ([199.233.58.181]) by mx0b-0016f401.pphosted.com with ESMTP id 222dkfh9h7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Apr 2016 01:11:07 -0700 From: Amitkumar Karwar To: CC: Nishant Sarmukadam , Xinming Hu , Cathy Luo , Amitkumar Karwar Subject: [PATCH RESEND 6/7] mwifiex: AMSDU Rx frame handling in AP mode Date: Tue, 5 Apr 2016 01:04:39 -0700 Message-ID: <1459843480-25956-6-git-send-email-akarwar@marvell.com> (sfid-20160405_101119_814952_AA65C1FD) In-Reply-To: <1459843480-25956-1-git-send-email-akarwar@marvell.com> References: <1459843480-25956-1-git-send-email-akarwar@marvell.com> MIME-Version: 1.0 Content-Type: text/plain Sender: linux-wireless-owner@vger.kernel.org List-ID: From: Xinming Hu 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 Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar --- .../net/wireless/marvell/mwifiex/11n_rxreorder.c | 5 +- drivers/net/wireless/marvell/mwifiex/main.h | 2 + drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 90 ++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index 09578c6..a74cc43 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, skb->len); } - ret = mwifiex_recv_packet(priv, rx_skb); + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) + ret = mwifiex_uap_recv_packet(priv, rx_skb); + else + ret = mwifiex_recv_packet(priv, rx_skb); if (ret == -1) mwifiex_dbg(priv->adapter, ERROR, "Rx of A-MSDU failed"); diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index eb2c90c..63069dd 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); int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb); +int mwifiex_uap_recv_packet(struct mwifiex_private *priv, + struct sk_buff *skb); int mwifiex_process_mgmt_packet(struct mwifiex_private *priv, 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 305589e..666e91a 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -269,6 +269,96 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, return mwifiex_process_rx_packet(priv, skb); } +int mwifiex_uap_recv_packet(struct mwifiex_private *priv, + struct sk_buff *skb) +{ + struct mwifiex_adapter *adapter = adapter; + struct mwifiex_sta_node *src_node; + struct ethhdr *p_ethhdr; + struct sk_buff *skb_uap; + struct mwifiex_txinfo *tx_info; + + if (!skb) + return -1; + + p_ethhdr = (void *)skb->data; + src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source); + if (src_node) { + src_node->stats.last_rx = jiffies; + src_node->stats.rx_bytes += skb->len; + src_node->stats.rx_packets++; + } + + skb->dev = priv->netdev; + skb->protocol = eth_type_trans(skb, priv->netdev); + skb->ip_summed = CHECKSUM_NONE; + + /* This is required only in case of 11n and USB/PCIE as we alloc + * a buffer of 4K only if its 11N (to be able to receive 4K + * AMSDU packets). In case of SD we allocate buffers based + * on the size of packet and hence this is not needed. + * + * Modifying the truesize here as our allocation for each + * skb is 4K but we only receive 2K packets and this cause + * the kernel to start dropping packets in case where + * application has allocated buffer based on 2K size i.e. + * if there a 64K packet received (in IP fragments and + * application allocates 64K to receive this packet but + * this packet would almost double up because we allocate + * each 1.5K fragment in 4K and pass it up. As soon as the + * 64K limit hits kernel will start to drop rest of the + * fragments. Currently we fail the Filesndl-ht.scr script + * for UDP, hence this fix + */ + if ((adapter->iface_type == MWIFIEX_USB || + adapter->iface_type == MWIFIEX_PCIE) && + (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) + skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); + + if (is_multicast_ether_addr(p_ethhdr->h_dest) || + mwifiex_get_sta_entry(priv, p_ethhdr->h_dest)) { + if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) + skb_uap = + skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); + else + skb_uap = skb_copy(skb, GFP_ATOMIC); + + if (likely(skb_uap)) { + tx_info = MWIFIEX_SKB_TXCB(skb_uap); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->bss_num = priv->bss_num; + tx_info->bss_type = priv->bss_type; + tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT; + __net_timestamp(skb_uap); + mwifiex_wmm_add_buf_txqueue(priv, skb_uap); + atomic_inc(&adapter->tx_pending); + atomic_inc(&adapter->pending_bridged_pkts); + if ((atomic_read(&adapter->pending_bridged_pkts) >= + MWIFIEX_BRIDGED_PKTS_THR_HIGH)) { + mwifiex_dbg(adapter, ERROR, + "Tx: Bridge packet limit reached. Drop packet!\n"); + mwifiex_uap_cleanup_tx_queues(priv); + } + + } else { + mwifiex_dbg(adapter, ERROR, "failed to allocate skb_uap"); + } + + mwifiex_queue_main_work(adapter); + /* Don't forward Intra-BSS unicast packet to upper layer*/ + if (mwifiex_get_sta_entry(priv, p_ethhdr->h_dest)) + return 0; + } + + /* Forward multicast/broadcast packet to upper layer*/ + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); + + return 0; +} + /* * This function processes the packet received on AP interface. * -- 1.8.1.4