Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 1 | /* |
Anurag Chouhan | 754fbd8 | 2016-02-19 17:00:08 +0530 | [diff] [blame] | 2 | * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 3 | * |
| 4 | * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| 5 | * |
| 6 | * |
| 7 | * Permission to use, copy, modify, and/or distribute this software for |
| 8 | * any purpose with or without fee is hereby granted, provided that the |
| 9 | * above copyright notice and this permission notice appear in all |
| 10 | * copies. |
| 11 | * |
| 12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| 13 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| 14 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| 15 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| 16 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| 17 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| 18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 19 | * PERFORMANCE OF THIS SOFTWARE. |
| 20 | */ |
| 21 | |
| 22 | /* |
| 23 | * This file was originally distributed by Qualcomm Atheros, Inc. |
| 24 | * under proprietary terms before Copyright ownership was assigned |
| 25 | * to the Linux Foundation. |
| 26 | */ |
| 27 | |
| 28 | /*======================================================================== |
| 29 | |
| 30 | \file epping_main.c |
| 31 | |
| 32 | \brief WLAN End Point Ping test tool implementation |
| 33 | |
| 34 | ========================================================================*/ |
| 35 | |
| 36 | /*-------------------------------------------------------------------------- |
| 37 | Include Files |
| 38 | ------------------------------------------------------------------------*/ |
| 39 | #include <cds_api.h> |
| 40 | #include <cds_sched.h> |
| 41 | #include <linux/etherdevice.h> |
| 42 | #include <linux/firmware.h> |
| 43 | #include <wni_api.h> |
| 44 | #include <wlan_ptt_sock_svc.h> |
| 45 | #include <linux/wireless.h> |
| 46 | #include <net/cfg80211.h> |
| 47 | #include <linux/rtnetlink.h> |
| 48 | #include <linux/semaphore.h> |
| 49 | #include <linux/ctype.h> |
| 50 | #include "epping_main.h" |
| 51 | #include "epping_internal.h" |
| 52 | #include "epping_test.h" |
| 53 | |
| 54 | #define TX_RETRY_TIMEOUT_IN_MS 1 |
| 55 | |
Anurag Chouhan | 754fbd8 | 2016-02-19 17:00:08 +0530 | [diff] [blame] | 56 | static bool enb_tx_dump; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 57 | |
| 58 | void epping_tx_dup_pkt(epping_adapter_t *pAdapter, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 59 | HTC_ENDPOINT_ID eid, qdf_nbuf_t skb) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 60 | { |
| 61 | struct epping_cookie *cookie = NULL; |
| 62 | int skb_len, ret; |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 63 | qdf_nbuf_t new_skb; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 64 | |
| 65 | cookie = epping_alloc_cookie(pAdapter->pEpping_ctx); |
| 66 | if (cookie == NULL) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 67 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 68 | "%s: epping_alloc_cookie returns no resource\n", |
| 69 | __func__); |
| 70 | return; |
| 71 | } |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 72 | new_skb = qdf_nbuf_copy(skb); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 73 | if (!new_skb) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 74 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 75 | "%s: qdf_nbuf_copy returns no resource\n", __func__); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 76 | epping_free_cookie(pAdapter->pEpping_ctx, cookie); |
| 77 | return; |
| 78 | } |
| 79 | SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 80 | cookie, qdf_nbuf_data(skb), |
| 81 | qdf_nbuf_len(new_skb), eid, 0); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 82 | SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, new_skb); |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 83 | skb_len = (int)qdf_nbuf_len(new_skb); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 84 | /* send the packet */ |
| 85 | ret = htc_send_pkt(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt); |
| 86 | if (ret != A_OK) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 87 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 88 | "%s: htc_send_pkt failed, ret = %d\n", __func__, ret); |
| 89 | epping_free_cookie(pAdapter->pEpping_ctx, cookie); |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 90 | qdf_nbuf_free(new_skb); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 91 | return; |
| 92 | } |
| 93 | pAdapter->stats.tx_bytes += skb_len; |
| 94 | ++pAdapter->stats.tx_packets; |
| 95 | if (((pAdapter->stats.tx_packets + |
| 96 | pAdapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 && |
| 97 | (pAdapter->stats.tx_packets || pAdapter->stats.tx_dropped)) { |
| 98 | epping_log_stats(pAdapter, __func__); |
| 99 | } |
| 100 | } |
| 101 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 102 | static int epping_tx_send_int(qdf_nbuf_t skb, epping_adapter_t *pAdapter) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 103 | { |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 104 | EPPING_HEADER *eppingHdr = (EPPING_HEADER *) qdf_nbuf_data(skb); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 105 | HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; |
| 106 | struct epping_cookie *cookie = NULL; |
| 107 | A_UINT8 ac = 0; |
| 108 | A_STATUS ret = A_OK; |
| 109 | int skb_len; |
| 110 | EPPING_HEADER tmpHdr = *eppingHdr; |
| 111 | |
| 112 | /* allocate resource for this packet */ |
| 113 | cookie = epping_alloc_cookie(pAdapter->pEpping_ctx); |
| 114 | /* no resource */ |
| 115 | if (cookie == NULL) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 116 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 117 | "%s: epping_alloc_cookie returns no resource\n", |
| 118 | __func__); |
| 119 | return -1; |
| 120 | } |
| 121 | |
| 122 | if (enb_tx_dump) |
| 123 | epping_hex_dump((void *)eppingHdr, skb->len, __func__); |
| 124 | /* |
| 125 | * a quirk of linux, the payload of the frame is 32-bit aligned and thus |
| 126 | * the addition of the HTC header will mis-align the start of the HTC |
| 127 | * frame, so we add some padding which will be stripped off in the target |
| 128 | */ |
| 129 | if (EPPING_ALIGNMENT_PAD > 0) { |
| 130 | A_NETBUF_PUSH(skb, EPPING_ALIGNMENT_PAD); |
| 131 | } |
| 132 | /* prepare ep/HTC information */ |
| 133 | ac = eppingHdr->StreamNo_h; |
| 134 | eid = pAdapter->pEpping_ctx->EppingEndpoint[ac]; |
| 135 | if (eid < 0 || eid >= EPPING_MAX_NUM_EPIDS) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 136 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 137 | "%s: invalid eid = %d, ac = %d\n", __func__, eid, |
| 138 | ac); |
| 139 | return -1; |
| 140 | } |
| 141 | if (tmpHdr.Cmd_h == EPPING_CMD_RESET_RECV_CNT || |
| 142 | tmpHdr.Cmd_h == EPPING_CMD_CONT_RX_START) { |
| 143 | epping_set_kperf_flag(pAdapter, eid, tmpHdr.CmdBuffer_t[0]); |
| 144 | } |
| 145 | SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 146 | cookie, qdf_nbuf_data(skb), qdf_nbuf_len(skb), |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 147 | eid, 0); |
| 148 | SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, skb); |
| 149 | skb_len = skb->len; |
| 150 | /* send the packet */ |
| 151 | ret = htc_send_pkt(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt); |
| 152 | epping_log_packet(pAdapter, &tmpHdr, ret, __func__); |
| 153 | if (ret != A_OK) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 154 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 155 | "%s: htc_send_pkt failed, status = %d\n", __func__, |
| 156 | ret); |
| 157 | epping_free_cookie(pAdapter->pEpping_ctx, cookie); |
| 158 | return -1; |
| 159 | } |
| 160 | pAdapter->stats.tx_bytes += skb_len; |
| 161 | ++pAdapter->stats.tx_packets; |
| 162 | if (((pAdapter->stats.tx_packets + |
| 163 | pAdapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 && |
| 164 | (pAdapter->stats.tx_packets || pAdapter->stats.tx_dropped)) { |
| 165 | epping_log_stats(pAdapter, __func__); |
| 166 | } |
| 167 | |
| 168 | return 0; |
| 169 | } |
| 170 | |
| 171 | void epping_tx_timer_expire(epping_adapter_t *pAdapter) |
| 172 | { |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 173 | qdf_nbuf_t nodrop_skb; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 174 | |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 175 | EPPING_LOG(QDF_TRACE_LEVEL_INFO, "%s: queue len: %d\n", __func__, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 176 | qdf_nbuf_queue_len(&pAdapter->nodrop_queue)); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 177 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 178 | if (!qdf_nbuf_queue_len(&pAdapter->nodrop_queue)) { |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 179 | /* nodrop queue is empty so no need to arm timer */ |
| 180 | pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; |
| 181 | return; |
| 182 | } |
| 183 | |
| 184 | /* try to flush nodrop queue */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 185 | while ((nodrop_skb = qdf_nbuf_queue_remove(&pAdapter->nodrop_queue))) { |
gbian | 7288cf5 | 2016-09-30 16:58:31 +0800 | [diff] [blame] | 186 | htc_set_nodrop_pkt(pAdapter->pEpping_ctx->HTCHandle, true); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 187 | if (epping_tx_send_int(nodrop_skb, pAdapter)) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 188 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 189 | "%s: nodrop: %p xmit fail in timer\n", |
| 190 | __func__, nodrop_skb); |
| 191 | /* fail to xmit so put the nodrop packet to the nodrop queue */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 192 | qdf_nbuf_queue_insert_head(&pAdapter->nodrop_queue, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 193 | nodrop_skb); |
| 194 | break; |
| 195 | } else { |
gbian | 7288cf5 | 2016-09-30 16:58:31 +0800 | [diff] [blame] | 196 | htc_set_nodrop_pkt(pAdapter->pEpping_ctx->HTCHandle, false); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 197 | EPPING_LOG(QDF_TRACE_LEVEL_INFO, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 198 | "%s: nodrop: %p xmit ok in timer\n", |
| 199 | __func__, nodrop_skb); |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | /* if nodrop queue is not empty, continue to arm timer */ |
| 204 | if (nodrop_skb) { |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 205 | qdf_spin_lock_bh(&pAdapter->data_lock); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 206 | /* if nodrop queue is not empty, continue to arm timer */ |
| 207 | if (pAdapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) { |
| 208 | pAdapter->epping_timer_state = EPPING_TX_TIMER_RUNNING; |
Anurag Chouhan | 754fbd8 | 2016-02-19 17:00:08 +0530 | [diff] [blame] | 209 | qdf_timer_mod(&pAdapter->epping_timer, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 210 | TX_RETRY_TIMEOUT_IN_MS); |
| 211 | } |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 212 | qdf_spin_unlock_bh(&pAdapter->data_lock); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 213 | } else { |
| 214 | pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; |
| 215 | } |
| 216 | } |
| 217 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 218 | int epping_tx_send(qdf_nbuf_t skb, epping_adapter_t *pAdapter) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 219 | { |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 220 | qdf_nbuf_t nodrop_skb; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 221 | EPPING_HEADER *eppingHdr; |
| 222 | A_UINT8 ac = 0; |
| 223 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 224 | eppingHdr = (EPPING_HEADER *) qdf_nbuf_data(skb); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 225 | |
| 226 | if (!IS_EPPING_PACKET(eppingHdr)) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 227 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 228 | "%s: Recived non endpoint ping packets\n", __func__); |
| 229 | /* no packet to send, cleanup */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 230 | qdf_nbuf_free(skb); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 231 | return -ENOMEM; |
| 232 | } |
| 233 | |
| 234 | /* the stream ID is mapped to an access class */ |
| 235 | ac = eppingHdr->StreamNo_h; |
| 236 | /* hard coded two ep ids */ |
| 237 | if (ac != 0 && ac != 1) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 238 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 239 | "%s: ac %d is not mapped to mboxping service\n", |
| 240 | __func__, ac); |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 241 | qdf_nbuf_free(skb); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 242 | return -ENOMEM; |
| 243 | } |
| 244 | |
| 245 | /* |
| 246 | * some EPPING packets cannot be dropped no matter what access class |
| 247 | * it was sent on. A special care has been taken: |
| 248 | * 1. when there is no TX resource, queue the control packets to |
| 249 | * a special queue |
| 250 | * 2. when there is TX resource, send the queued control packets first |
| 251 | * and then other packets |
| 252 | * 3. a timer launches to check if there is queued control packets and |
| 253 | * flush them |
| 254 | */ |
| 255 | |
| 256 | /* check the nodrop queue first */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 257 | while ((nodrop_skb = qdf_nbuf_queue_remove(&pAdapter->nodrop_queue))) { |
gbian | 7288cf5 | 2016-09-30 16:58:31 +0800 | [diff] [blame] | 258 | htc_set_nodrop_pkt(pAdapter->pEpping_ctx->HTCHandle, true); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 259 | if (epping_tx_send_int(nodrop_skb, pAdapter)) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 260 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 261 | "%s: nodrop: %p xmit fail\n", __func__, |
| 262 | nodrop_skb); |
| 263 | /* fail to xmit so put the nodrop packet to the nodrop queue */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 264 | qdf_nbuf_queue_insert_head(&pAdapter->nodrop_queue, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 265 | nodrop_skb); |
| 266 | /* no cookie so free the current skb */ |
| 267 | goto tx_fail; |
| 268 | } else { |
gbian | 7288cf5 | 2016-09-30 16:58:31 +0800 | [diff] [blame] | 269 | htc_set_nodrop_pkt(pAdapter->pEpping_ctx->HTCHandle, false); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 270 | EPPING_LOG(QDF_TRACE_LEVEL_INFO, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 271 | "%s: nodrop: %p xmit ok\n", __func__, |
| 272 | nodrop_skb); |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | /* send the original packet */ |
| 277 | if (epping_tx_send_int(skb, pAdapter)) |
| 278 | goto tx_fail; |
| 279 | |
| 280 | return 0; |
| 281 | |
| 282 | tx_fail: |
| 283 | if (!IS_EPING_PACKET_NO_DROP(eppingHdr)) { |
| 284 | /* allow to drop the skb so drop it */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 285 | qdf_nbuf_free(skb); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 286 | ++pAdapter->stats.tx_dropped; |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 287 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 288 | "%s: Tx skb %p dropped, stats.tx_dropped = %ld\n", |
| 289 | __func__, skb, pAdapter->stats.tx_dropped); |
| 290 | return -ENOMEM; |
| 291 | } else { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 292 | EPPING_LOG(QDF_TRACE_LEVEL_FATAL, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 293 | "%s: nodrop: %p queued\n", __func__, skb); |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 294 | qdf_nbuf_queue_add(&pAdapter->nodrop_queue, skb); |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 295 | qdf_spin_lock_bh(&pAdapter->data_lock); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 296 | if (pAdapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) { |
| 297 | pAdapter->epping_timer_state = EPPING_TX_TIMER_RUNNING; |
Anurag Chouhan | 754fbd8 | 2016-02-19 17:00:08 +0530 | [diff] [blame] | 298 | qdf_timer_mod(&pAdapter->epping_timer, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 299 | TX_RETRY_TIMEOUT_IN_MS); |
| 300 | } |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 301 | qdf_spin_unlock_bh(&pAdapter->data_lock); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 302 | } |
| 303 | |
| 304 | return 0; |
| 305 | } |
| 306 | |
| 307 | #ifdef HIF_SDIO |
| 308 | HTC_SEND_FULL_ACTION epping_tx_queue_full(void *Context, HTC_PACKET *pPacket) |
| 309 | { |
gbian | 7288cf5 | 2016-09-30 16:58:31 +0800 | [diff] [blame] | 310 | /* |
| 311 | * Call netif_stop_queue frequently will impact the mboxping tx t-put. |
| 312 | * Return HTC_SEND_FULL_KEEP directly in epping_tx_queue_full to avoid. |
| 313 | */ |
| 314 | return HTC_SEND_FULL_KEEP; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 315 | } |
| 316 | #endif /* HIF_SDIO */ |
| 317 | void epping_tx_complete_multiple(void *ctx, HTC_PACKET_QUEUE *pPacketQueue) |
| 318 | { |
| 319 | epping_context_t *pEpping_ctx = (epping_context_t *) ctx; |
| 320 | epping_adapter_t *pAdapter = pEpping_ctx->epping_adapter; |
| 321 | struct net_device *dev = pAdapter->dev; |
| 322 | A_STATUS status; |
| 323 | HTC_ENDPOINT_ID eid; |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 324 | qdf_nbuf_t pktSkb; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 325 | struct epping_cookie *cookie; |
| 326 | A_BOOL flushing = false; |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 327 | qdf_nbuf_queue_t skb_queue; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 328 | HTC_PACKET *htc_pkt; |
| 329 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 330 | qdf_nbuf_queue_init(&skb_queue); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 331 | |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 332 | qdf_spin_lock_bh(&pAdapter->data_lock); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 333 | |
| 334 | while (!HTC_QUEUE_EMPTY(pPacketQueue)) { |
| 335 | htc_pkt = htc_packet_dequeue(pPacketQueue); |
| 336 | if (htc_pkt == NULL) |
| 337 | break; |
| 338 | status = htc_pkt->Status; |
| 339 | eid = htc_pkt->Endpoint; |
| 340 | pktSkb = GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt); |
| 341 | cookie = htc_pkt->pPktContext; |
| 342 | |
Himanshu Agarwal | 5e302a7 | 2016-07-19 16:27:21 +0530 | [diff] [blame] | 343 | if (!pktSkb) { |
| 344 | EPPING_LOG(QDF_TRACE_LEVEL_ERROR, |
Himanshu Agarwal | f03f810 | 2016-09-08 18:54:47 +0530 | [diff] [blame] | 345 | "%s: NULL skb from hc packet", __func__); |
| 346 | QDF_BUG(0); |
Himanshu Agarwal | 5e302a7 | 2016-07-19 16:27:21 +0530 | [diff] [blame] | 347 | } else { |
| 348 | if (htc_pkt->pBuffer != qdf_nbuf_data(pktSkb)) { |
| 349 | EPPING_LOG(QDF_TRACE_LEVEL_ERROR, |
| 350 | "%s: htc_pkt buffer not equal to skb->data", |
| 351 | __func__); |
Himanshu Agarwal | f03f810 | 2016-09-08 18:54:47 +0530 | [diff] [blame] | 352 | QDF_BUG(0); |
Himanshu Agarwal | 5e302a7 | 2016-07-19 16:27:21 +0530 | [diff] [blame] | 353 | } |
| 354 | /* add this to the list, use faster non-lock API */ |
| 355 | qdf_nbuf_queue_add(&skb_queue, pktSkb); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 356 | |
Himanshu Agarwal | 5e302a7 | 2016-07-19 16:27:21 +0530 | [diff] [blame] | 357 | if (A_SUCCESS(status)) { |
| 358 | if (htc_pkt->ActualLength != |
| 359 | qdf_nbuf_len(pktSkb)) { |
| 360 | EPPING_LOG(QDF_TRACE_LEVEL_ERROR, |
| 361 | "%s: htc_pkt length not equal to skb->len", |
| 362 | __func__); |
Himanshu Agarwal | f03f810 | 2016-09-08 18:54:47 +0530 | [diff] [blame] | 363 | QDF_BUG(0); |
Himanshu Agarwal | 5e302a7 | 2016-07-19 16:27:21 +0530 | [diff] [blame] | 364 | } |
| 365 | } |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 366 | } |
Himanshu Agarwal | 5e302a7 | 2016-07-19 16:27:21 +0530 | [diff] [blame] | 367 | |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 368 | EPPING_LOG(QDF_TRACE_LEVEL_INFO, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 369 | "%s skb=%p data=%p len=0x%x eid=%d ", |
| 370 | __func__, pktSkb, htc_pkt->pBuffer, |
| 371 | htc_pkt->ActualLength, eid); |
| 372 | |
| 373 | if (A_FAILED(status)) { |
| 374 | if (status == A_ECANCELED) { |
| 375 | /* a packet was flushed */ |
| 376 | flushing = true; |
| 377 | } |
| 378 | if (status != A_NO_RESOURCE) { |
| 379 | printk("%s() -TX ERROR, status: 0x%x\n", |
| 380 | __func__, status); |
| 381 | } |
| 382 | } else { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 383 | EPPING_LOG(QDF_TRACE_LEVEL_INFO, "%s: OK\n", __func__); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 384 | flushing = false; |
| 385 | } |
| 386 | |
| 387 | epping_free_cookie(pAdapter->pEpping_ctx, cookie); |
| 388 | } |
| 389 | |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 390 | qdf_spin_unlock_bh(&pAdapter->data_lock); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 391 | |
| 392 | /* free all skbs in our local list */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 393 | while (qdf_nbuf_queue_len(&skb_queue)) { |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 394 | /* use non-lock version */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame] | 395 | pktSkb = qdf_nbuf_queue_remove(&skb_queue); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 396 | if (pktSkb == NULL) |
| 397 | break; |
Rajeev Kumar | 8044ede | 2016-04-14 16:08:05 -0700 | [diff] [blame] | 398 | qdf_nbuf_tx_free(pktSkb, QDF_NBUF_PKT_ERROR); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 399 | pEpping_ctx->total_tx_acks++; |
| 400 | } |
| 401 | |
| 402 | if (!flushing) { |
| 403 | netif_wake_queue(dev); |
| 404 | } |
| 405 | } |