15e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 25e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Marvell Wireless LAN device driver: generic TX/RX data handling 35e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 45e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Copyright (C) 2011, Marvell International Ltd. 55e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 65e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This software file (the "File") is distributed by Marvell International 75e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Ltd. under the terms of the GNU General Public License Version 2, June 1991 85e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * (the "License"). You may use, redistribute and/or modify this File in 95e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * accordance with the terms and conditions of the License, a copy of which 105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * is available by writing to the Free Software Foundation, Inc., 115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * this warranty disclaimer. 185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "decl.h" 215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "ioctl.h" 225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "util.h" 235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "fw.h" 245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "main.h" 255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "wmm.h" 265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function processes the received buffer. 295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Main responsibility of this function is to parse the RxPD to 315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * identify the correct interface this packet is headed for and 325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * forwarding it to the associated handling function, where the 335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * packet will be further processed and sent to kernel/upper layer 345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * if required. 355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, 375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb) 385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv = 405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct rxpd *local_rx_pd; 425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); 435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao local_rx_pd = (struct rxpd *) (skb->data); 455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Get the BSS number from rxpd, get corresponding priv */ 465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num & 475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao BSS_NUM_MASK, local_rx_pd->bss_type); 485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!priv) 495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); 505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 519da9a3b29ba6a9a98e437f24576f13cbe259997bYogesh Ashok Powar rx_info->bss_num = priv->bss_num; 529da9a3b29ba6a9a98e437f24576f13cbe259997bYogesh Ashok Powar rx_info->bss_type = priv->bss_type; 535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 54636c4598499eeacce0893dc8d91113b904bd531eYogesh Ashok Powar return mwifiex_process_sta_rx_packet(adapter, skb); 555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing ZhaoEXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); 575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function sends a packet to device. 605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * It processes the packet to add the TxPD, checks condition and 625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * sends the processed packet to firmware for transmission. 635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * On successful completion, the function calls the completion callback 655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * and logs the time. 665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, 685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_tx_param *tx_param) 695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int ret = -1; 715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_adapter *adapter = priv->adapter; 72270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar u8 *head_ptr; 735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct txpd *local_tx_pd = NULL; 745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 75a5ffddb70c5cab29fa00e2fdf12217b64b940796Amitkumar Karwar head_ptr = mwifiex_process_sta_txpd(priv, skb); 765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (head_ptr) { 775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) 785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao local_tx_pd = 795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct txpd *) (head_ptr + INTF_HEADER_LEN); 805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, 82d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar skb, tx_param); 835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao switch (ret) { 865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case -EBUSY: 875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && 88c65a30f35f938b421ac67c34a9e70b0e49e6019aYogesh Ashok Powar (adapter->pps_uapsd_mode) && (adapter->tx_lock_flag)) { 895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->adapter->tx_lock_flag = false; 903d82de0fa584fbe73cf74a3bbc906c8710c523b8Yogesh Ashok Powar if (local_tx_pd) 913d82de0fa584fbe73cf74a3bbc906c8710c523b8Yogesh Ashok Powar local_tx_pd->flags = 0; 925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); 945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case -1: 965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->data_sent = false; 975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", 98c65a30f35f938b421ac67c34a9e70b0e49e6019aYogesh Ashok Powar ret); 995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->dbg.num_tx_host_to_card_failure++; 1005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, ret); 1015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 1025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case -EINPROGRESS: 1035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->data_sent = false; 1045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 1055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case 0: 1065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, ret); 1075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 1085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao default: 1095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 1105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 1115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ret; 1135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 1165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Packet send completion callback handler. 1175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 1185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * It either frees the buffer directly or forwards it to another 1195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * completion callback which checks conditions, updates statistics, 1205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * wakes up stalled traffic queue if required, and then frees the buffer. 1215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 1225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint mwifiex_write_data_complete(struct mwifiex_adapter *adapter, 1235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb, int status) 1245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 125270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar struct mwifiex_private *priv, *tpriv; 126270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar struct mwifiex_txinfo *tx_info; 1275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i; 1285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!skb) 1305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 1315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info = MWIFIEX_SKB_TXCB(skb); 1339da9a3b29ba6a9a98e437f24576f13cbe259997bYogesh Ashok Powar priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num, 134c65a30f35f938b421ac67c34a9e70b0e49e6019aYogesh Ashok Powar tx_info->bss_type); 1355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!priv) 1365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao goto done; 1375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 138bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil mwifiex_set_trans_start(priv->netdev); 1395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!status) { 1405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->stats.tx_packets++; 1415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->stats.tx_bytes += skb->len; 1425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 1435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->stats.tx_errors++; 1445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 14562a5b7dcee00c8e64e61ed98541c95fd38583116Marc Yang 14662a5b7dcee00c8e64e61ed98541c95fd38583116Marc Yang if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING) 14762a5b7dcee00c8e64e61ed98541c95fd38583116Marc Yang goto done; 1485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < adapter->priv_num; i++) { 1505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tpriv = adapter->priv[i]; 1525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 153c65a30f35f938b421ac67c34a9e70b0e49e6019aYogesh Ashok Powar if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA) && 154c65a30f35f938b421ac67c34a9e70b0e49e6019aYogesh Ashok Powar (tpriv->media_connected)) { 1555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (netif_queue_stopped(tpriv->netdev)) 156bbea3bc432dc5c08d09ca5c80afdd82515470688Avinash Patil mwifiex_wake_up_net_dev_queue(tpriv->netdev, 157c65a30f35f938b421ac67c34a9e70b0e49e6019aYogesh Ashok Powar adapter); 1585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 1595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 1605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaodone: 1615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_kfree_skb_any(skb); 1625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 1645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 166