1 /*
2  * Copyright (c) 2014-2017, 2019 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
epping_refill(void * ctx,HTC_ENDPOINT_ID Endpoint)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 (!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 
epping_rx(void * ctx,HTC_PACKET * pPacket)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 			EPPING_LOG(QDF_TRACE_LEVEL_ERROR, "%s: RX ERR (%d)",
118 				   __func__, status);
119 		}
120 		qdf_nbuf_free(pktSkb);
121 		return;
122 	}
123 
124 	/* deliver to up layer */
125 	if (pktSkb) {
126 		if (EPPING_ALIGNMENT_PAD > 0) {
127 			A_NETBUF_PULL(pktSkb, EPPING_ALIGNMENT_PAD);
128 		}
129 		if (enb_rx_dump)
130 			epping_hex_dump((void *)qdf_nbuf_data(pktSkb),
131 					pktSkb->len, __func__);
132 		pktSkb->dev = dev;
133 		if ((pktSkb->dev->flags & IFF_UP) == IFF_UP) {
134 			pktSkb->protocol = eth_type_trans(pktSkb, pktSkb->dev);
135 			++adapter->stats.rx_packets;
136 			adapter->stats.rx_bytes += pktSkb->len;
137 			qdf_net_buf_debug_release_skb(pktSkb);
138 			if (hdd_napi_enabled(HDD_NAPI_ANY))
139 				netif_receive_skb(pktSkb);
140 			else
141 				netif_rx_ni(pktSkb);
142 			if ((adapter->stats.rx_packets %
143 				 EPPING_STATS_LOG_COUNT) == 0) {
144 				EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
145 					   "%s: total_rx_pkts = %lu",
146 					   __func__,
147 					   adapter->stats.rx_packets);
148 			}
149 		} else {
150 			++adapter->stats.rx_dropped;
151 			qdf_nbuf_free(pktSkb);
152 		}
153 	}
154 }
155