1 /* 2 * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /*======================================================================== 20 21 \file epping_rx.c 22 23 \brief WLAN End Point Ping test tool implementation 24 25 ========================================================================*/ 26 27 /*-------------------------------------------------------------------------- 28 Include Files 29 ------------------------------------------------------------------------*/ 30 #include <cds_api.h> 31 #include <cds_sched.h> 32 #include <linux/etherdevice.h> 33 #include <linux/firmware.h> 34 #include <wni_api.h> 35 #include <wlan_ptt_sock_svc.h> 36 #include <linux/wireless.h> 37 #include <net/cfg80211.h> 38 #include <linux/rtnetlink.h> 39 #include <linux/semaphore.h> 40 #include <linux/ctype.h> 41 #include "epping_main.h" 42 #include "epping_internal.h" 43 #include "epping_test.h" 44 #include <wlan_hdd_napi.h> 45 46 #define AR6000_MAX_RX_BUFFERS 16 47 #define AR6000_BUFFER_SIZE 1664 48 #define AR6000_MIN_HEAD_ROOM 64 49 50 static bool enb_rx_dump; 51 52 #ifdef HIF_SDIO 53 void epping_refill(void *ctx, HTC_ENDPOINT_ID Endpoint) 54 { 55 epping_context_t *pEpping_ctx = (epping_context_t *) ctx; 56 void *osBuf; 57 int RxBuffers; 58 int buffersToRefill; 59 HTC_PACKET *pPacket; 60 HTC_PACKET_QUEUE queue; 61 62 buffersToRefill = (int)AR6000_MAX_RX_BUFFERS - 63 htc_get_num_recv_buffers(pEpping_ctx->HTCHandle, Endpoint); 64 65 if (buffersToRefill <= 0) { 66 /* fast return, nothing to fill */ 67 return; 68 } 69 70 INIT_HTC_PACKET_QUEUE(&queue); 71 72 EPPING_LOG(QDF_TRACE_LEVEL_INFO, 73 "%s: providing htc with %d buffers at eid=%d\n", 74 __func__, buffersToRefill, Endpoint); 75 76 for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) { 77 osBuf = qdf_nbuf_alloc(NULL, AR6000_BUFFER_SIZE, 78 AR6000_MIN_HEAD_ROOM, 4, false); 79 if (NULL == osBuf) { 80 break; 81 } 82 /* the HTC packet wrapper is at the head of the reserved area 83 * in the skb */ 84 pPacket = (HTC_PACKET *) (A_NETBUF_HEAD(osBuf)); 85 /* set re-fill info */ 86 SET_HTC_PACKET_INFO_RX_REFILL(pPacket, osBuf, 87 qdf_nbuf_data(osBuf), 88 AR6000_BUFFER_SIZE, Endpoint); 89 SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, osBuf); 90 /* add to queue */ 91 HTC_PACKET_ENQUEUE(&queue, pPacket); 92 } 93 94 if (!HTC_QUEUE_EMPTY(&queue)) { 95 /* add packets */ 96 htc_add_receive_pkt_multiple(pEpping_ctx->HTCHandle, &queue); 97 } 98 } 99 #endif /* HIF_SDIO */ 100 101 void epping_rx(void *ctx, HTC_PACKET *pPacket) 102 { 103 epping_context_t *pEpping_ctx = (epping_context_t *) ctx; 104 epping_adapter_t *adapter = pEpping_ctx->epping_adapter; 105 struct net_device *dev = adapter->dev; 106 QDF_STATUS status = pPacket->Status; 107 HTC_ENDPOINT_ID eid = pPacket->Endpoint; 108 struct sk_buff *pktSkb = (struct sk_buff *)pPacket->pPktContext; 109 110 EPPING_LOG(QDF_TRACE_LEVEL_INFO, 111 "%s: adapter = 0x%pK eid=%d, skb=0x%pK, data=0x%pK, len=0x%x status:%d", 112 __func__, adapter, eid, pktSkb, pPacket->pBuffer, 113 pPacket->ActualLength, status); 114 115 if (status != QDF_STATUS_SUCCESS) { 116 if (status != QDF_STATUS_E_CANCELED) { 117 printk("%s: RX ERR (%d)\n", __func__, status); 118 } 119 qdf_nbuf_free(pktSkb); 120 return; 121 } 122 123 /* deliver to up layer */ 124 if (pktSkb) { 125 if (EPPING_ALIGNMENT_PAD > 0) { 126 A_NETBUF_PULL(pktSkb, EPPING_ALIGNMENT_PAD); 127 } 128 if (enb_rx_dump) 129 epping_hex_dump((void *)qdf_nbuf_data(pktSkb), 130 pktSkb->len, __func__); 131 pktSkb->dev = dev; 132 if ((pktSkb->dev->flags & IFF_UP) == IFF_UP) { 133 pktSkb->protocol = eth_type_trans(pktSkb, pktSkb->dev); 134 ++adapter->stats.rx_packets; 135 adapter->stats.rx_bytes += pktSkb->len; 136 qdf_net_buf_debug_release_skb(pktSkb); 137 if (hdd_napi_enabled(HDD_NAPI_ANY)) 138 netif_receive_skb(pktSkb); 139 else 140 netif_rx_ni(pktSkb); 141 if ((adapter->stats.rx_packets % 142 EPPING_STATS_LOG_COUNT) == 0) { 143 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 144 "%s: total_rx_pkts = %lu", 145 __func__, 146 adapter->stats.rx_packets); 147 } 148 } else { 149 ++adapter->stats.rx_dropped; 150 qdf_nbuf_free(pktSkb); 151 } 152 } 153 } 154