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