blob: 00320dd413872952cd0204573ed26bc7e767699d [file] [log] [blame]
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001/*
Vivek Natarajaned3bf792019-01-06 07:05:43 +05302 * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08003 *
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08004 * 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
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080019#include "htc_debug.h"
20#include "htc_internal.h"
Rachit Kankane1bc11492018-01-24 18:48:17 +053021#include "htc_credit_history.h"
Yue Mab16cf302016-03-08 18:30:25 -080022#include <qdf_mem.h> /* qdf_mem_malloc */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053023#include <qdf_nbuf.h> /* qdf_nbuf_t */
Pratik Gandhidc82a772018-01-30 18:57:05 +053024#include "qdf_module.h"
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080025
26/* #define USB_HIF_SINGLE_PIPE_DATA_SCHED */
27/* #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED */
28#define DATA_EP_SIZE 4
29/* #endif */
30#define HTC_DATA_RESOURCE_THRS 256
31#define HTC_DATA_MINDESC_PERPACKET 2
32
Manikandan Mohane3e209e2017-04-13 20:19:26 -070033enum HTC_SEND_QUEUE_RESULT {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080034 HTC_SEND_QUEUE_OK = 0, /* packet was queued */
Manikandan Mohane3e209e2017-04-13 20:19:26 -070035 HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */
36};
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080037
38#ifndef DEBUG_CREDIT
39#define DEBUG_CREDIT 0
40#endif
41
42#if DEBUG_CREDIT
43/* bit mask to enable debug certain endpoint */
Manikandan Mohane3e209e2017-04-13 20:19:26 -070044static unsigned int ep_debug_mask =
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080045 (1 << ENDPOINT_0) | (1 << ENDPOINT_1) | (1 << ENDPOINT_2);
46#endif
47
Alok Kumar967af272016-12-02 16:32:53 -080048#ifdef QCA_WIFI_NAPIER_EMULATION
49#define HTC_EMULATION_DELAY_IN_MS 20
50/**
51 * htc_add_delay(): Adds a delay in before proceeding, only for emulation
52 *
53 * Return: None
54 */
55static inline void htc_add_emulation_delay(void)
56{
57 qdf_mdelay(HTC_EMULATION_DELAY_IN_MS);
58}
59#else
60static inline void htc_add_emulation_delay(void)
61{
62}
63#endif
64
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080065void htc_dump_counter_info(HTC_HANDLE HTCHandle)
66{
67 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
68
69 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
70 ("\n%s: ce_send_cnt = %d, TX_comp_cnt = %d\n",
71 __func__, target->ce_send_cnt, target->TX_comp_cnt));
72}
73
Himanshu Batra032d3522019-07-10 12:36:06 +053074int htc_get_tx_queue_depth(HTC_HANDLE htc_handle, HTC_ENDPOINT_ID endpoint_id)
Houston Hoffmanadc31472017-03-14 16:15:29 -070075{
76 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
77 HTC_ENDPOINT *endpoint = &target->endpoint[endpoint_id];
78
79 return HTC_PACKET_QUEUE_DEPTH(&endpoint->TxQueue);
80}
Pratik Gandhidc82a772018-01-30 18:57:05 +053081qdf_export_symbol(htc_get_tx_queue_depth);
Houston Hoffmanadc31472017-03-14 16:15:29 -070082
Manikandan Mohane3e209e2017-04-13 20:19:26 -070083void htc_get_control_endpoint_tx_host_credits(HTC_HANDLE HTCHandle,
84 int *credits)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080085{
86 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
87 HTC_ENDPOINT *pEndpoint;
88 int i;
89
90 if (!credits || !target) {
91 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: invalid args", __func__));
92 return;
93 }
94
95 *credits = 0;
96 LOCK_HTC_TX(target);
97 for (i = 0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -070098 pEndpoint = &target->endpoint[i];
Houston Hoffman4f2f4592015-10-20 18:00:29 -070099 if (pEndpoint->service_id == WMI_CONTROL_SVC) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800100 *credits = pEndpoint->TxCredits;
101 break;
102 }
103 }
104 UNLOCK_HTC_TX(target);
105}
106
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530107static inline void restore_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800108{
Dustin Brownbc9718f2017-12-11 12:15:27 -0800109 qdf_nbuf_t netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700110
Dustin Brownbc9718f2017-12-11 12:15:27 -0800111 if (pPacket->PktInfo.AsTx.Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530112 qdf_nbuf_unmap(target->osdev, netbuf, QDF_DMA_TO_DEVICE);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800113 pPacket->PktInfo.AsTx.Flags &= ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
114 }
Nirav Shah31435bb2019-08-05 17:51:19 +0530115 if (pPacket->PktInfo.AsTx.Flags &
116 HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA) {
117 qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR));
118 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800119}
120
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800121static void send_packet_completion(HTC_TARGET *target, HTC_PACKET *pPacket)
122{
Houston Hoffman29573d92015-10-20 17:49:44 -0700123 HTC_ENDPOINT *pEndpoint = &target->endpoint[pPacket->Endpoint];
Yun Park88e0b952017-10-11 23:08:34 -0700124 HTC_EP_SEND_PKT_COMPLETE EpTxComplete;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800125
126 restore_tx_packet(target, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800127
128 /* do completion */
Yun Park88e0b952017-10-11 23:08:34 -0700129 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
130 ("HTC calling ep %d send complete callback on packet %pK\n",
131 pEndpoint->Id, pPacket));
132
133 EpTxComplete = pEndpoint->EpCallBacks.EpTxComplete;
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700134 if (EpTxComplete)
Yun Park88e0b952017-10-11 23:08:34 -0700135 EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket);
136 else
137 qdf_nbuf_free(pPacket->pPktContext);
138
139
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800140}
141
Yue Ma4986b252019-07-23 15:57:48 -0700142#ifdef FEATURE_RUNTIME_PM
143/**
144 * log_packet_info() - Log HTC packet information
145 *
146 * @target: handle of HTC context
147 * @pPacket: handle of HTC packet
148 *
149 * Return: None
150 */
151static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket)
152{
153 HTC_ENDPOINT *pEndpoint = &target->endpoint[pPacket->Endpoint];
154 HTC_EP_LOG_PKT ep_log_pkt;
155 qdf_nbuf_t netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
156
157 ep_log_pkt = pEndpoint->EpCallBacks.ep_log_pkt;
158 if (ep_log_pkt) {
159 qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR));
160 ep_log_pkt(pEndpoint->EpCallBacks.pContext, pPacket);
161 qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR));
162 }
163}
164#else
165static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket)
166{
167}
168#endif
169
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800170void htc_send_complete_check_cleanup(void *context)
171{
172 HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *) context;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700173
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800174 htc_send_complete_check(pEndpoint, 1);
175}
176
177HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target)
178{
179 HTC_PACKET *pPacket;
180 HTC_PACKET_QUEUE *pQueueSave;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530181 qdf_nbuf_t netbuf;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700182
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800183 LOCK_HTC_TX(target);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700184 if (!target->pBundleFreeList) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800185 UNLOCK_HTC_TX(target);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530186 netbuf = qdf_nbuf_alloc(NULL,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800187 target->MaxMsgsPerHTCBundle *
188 target->TargetCreditSize, 0, 4, false);
189 AR_DEBUG_ASSERT(netbuf);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700190 if (!netbuf)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800191 return NULL;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530192 pPacket = qdf_mem_malloc(sizeof(HTC_PACKET));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800193 AR_DEBUG_ASSERT(pPacket);
194 if (!pPacket) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530195 qdf_nbuf_free(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800196 return NULL;
197 }
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530198 pQueueSave = qdf_mem_malloc(sizeof(HTC_PACKET_QUEUE));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800199 AR_DEBUG_ASSERT(pQueueSave);
200 if (!pQueueSave) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530201 qdf_nbuf_free(netbuf);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530202 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800203 return NULL;
204 }
205 INIT_HTC_PACKET_QUEUE(pQueueSave);
206 pPacket->pContext = pQueueSave;
207 SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530208 pPacket->pBuffer = qdf_nbuf_data(netbuf);
209 pPacket->BufferLength = qdf_nbuf_len(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800210
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700211 /* store the original head room so that we can restore this
212 * when we "free" the packet.
213 * free packet puts the packet back on the free list
214 */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530215 pPacket->netbufOrigHeadRoom = qdf_nbuf_headroom(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800216 return pPacket;
217 }
218 /* already done malloc - restore from free list */
219 pPacket = target->pBundleFreeList;
220 AR_DEBUG_ASSERT(pPacket);
221 if (!pPacket) {
222 UNLOCK_HTC_TX(target);
223 return NULL;
224 }
225 target->pBundleFreeList = (HTC_PACKET *) pPacket->ListLink.pNext;
226 UNLOCK_HTC_TX(target);
227 pPacket->ListLink.pNext = NULL;
228
229 return pPacket;
230}
231
232void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
233{
Yue Mab16cf302016-03-08 18:30:25 -0800234 uint32_t curentHeadRoom;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530235 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800236 HTC_PACKET_QUEUE *pQueueSave;
237
238 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
239 AR_DEBUG_ASSERT(netbuf);
240 if (!netbuf) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700241 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
242 ("\n%s: Invalid netbuf in HTC Packet\n",
243 __func__));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800244 return;
245 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700246 /* HIF adds data to the headroom section of the nbuf, restore thei
247 * original size. If this is not done, headroom keeps shrinking with
248 * every HIF send and eventually HIF ends up doing another malloc big
249 * enough to store the data + its header
250 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800251
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530252 curentHeadRoom = qdf_nbuf_headroom(netbuf);
253 qdf_nbuf_pull_head(netbuf,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800254 pPacket->netbufOrigHeadRoom - curentHeadRoom);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530255 qdf_nbuf_trim_tail(netbuf, qdf_nbuf_len(netbuf));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800256
257 /* restore the pBuffer pointer. HIF changes this */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530258 pPacket->pBuffer = qdf_nbuf_data(netbuf);
259 pPacket->BufferLength = qdf_nbuf_len(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800260
261 /* restore queue */
262 pQueueSave = (HTC_PACKET_QUEUE *) pPacket->pContext;
jitiphilfcc24882018-05-11 16:14:38 +0530263 if (qdf_unlikely(!pQueueSave)) {
264 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
265 ("\n%s: Invalid pQueueSave in HTC Packet\n",
266 __func__));
267 AR_DEBUG_ASSERT(pQueueSave);
268 } else
269 INIT_HTC_PACKET_QUEUE(pQueueSave);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800270
271 LOCK_HTC_TX(target);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700272 if (!target->pBundleFreeList) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800273 target->pBundleFreeList = pPacket;
274 pPacket->ListLink.pNext = NULL;
275 } else {
276 pPacket->ListLink.pNext = (DL_LIST *) target->pBundleFreeList;
277 target->pBundleFreeList = pPacket;
278 }
279 UNLOCK_HTC_TX(target);
280}
281
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530282#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
283
284/**
285 * htc_send_update_tx_bundle_stats() - update tx bundle stats depends
286 * on max bundle size
287 * @target: hif context
288 * @data_len: tx data len
289 * @TxCreditSize: endpoint tx credit size
290 *
291 * Return: None
292 */
293static inline void
294htc_send_update_tx_bundle_stats(HTC_TARGET *target,
295 qdf_size_t data_len,
296 int TxCreditSize)
297{
298 if ((data_len / TxCreditSize) <= HTC_MAX_MSG_PER_BUNDLE_TX)
299 target->tx_bundle_stats[(data_len / TxCreditSize) - 1]++;
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530300}
301
302/**
303 * htc_issue_tx_bundle_stats_inc() - increment in tx bundle stats
304 * on max bundle size
305 * @target: hif context
306 *
307 * Return: None
308 */
309static inline void
310htc_issue_tx_bundle_stats_inc(HTC_TARGET *target)
311{
312 target->tx_bundle_stats[0]++;
313}
314#else
315
316static inline void
317htc_send_update_tx_bundle_stats(HTC_TARGET *target,
318 qdf_size_t data_len,
319 int TxCreditSize)
320{
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530321}
322
323static inline void
324htc_issue_tx_bundle_stats_inc(HTC_TARGET *target)
325{
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530326}
327#endif
328
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800329#if defined(HIF_USB) || defined(HIF_SDIO)
330#ifdef ENABLE_BUNDLE_TX
Rakesh Pillai13146452017-06-22 12:52:31 +0530331static QDF_STATUS htc_send_bundled_netbuf(HTC_TARGET *target,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800332 HTC_ENDPOINT *pEndpoint,
333 unsigned char *pBundleBuffer,
334 HTC_PACKET *pPacketTx)
335{
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530336 qdf_size_t data_len;
Rakesh Pillai13146452017-06-22 12:52:31 +0530337 QDF_STATUS status;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530338 qdf_nbuf_t bundleBuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800339 uint32_t data_attr = 0;
340
341 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530342 data_len = pBundleBuffer - qdf_nbuf_data(bundleBuf);
343 qdf_nbuf_put_tail(bundleBuf, data_len);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800344 SET_HTC_PACKET_INFO_TX(pPacketTx,
345 target,
346 pBundleBuffer,
347 data_len,
348 pEndpoint->Id, HTC_TX_PACKET_TAG_BUNDLED);
349 LOCK_HTC_TX(target);
350 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacketTx);
tfyu052b32a2017-09-20 18:48:33 +0800351 pEndpoint->ul_outstanding_cnt++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800352 UNLOCK_HTC_TX(target);
353#if DEBUG_BUNDLE
Aditya Sathish648ce112018-07-02 16:41:39 +0530354 qdf_print(" Send bundle EP%d buffer size:0x%x, total:0x%x, count:%d.",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800355 pEndpoint->Id,
356 pEndpoint->TxCreditSize,
357 data_len, data_len / pEndpoint->TxCreditSize);
358#endif
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530359
360 htc_send_update_tx_bundle_stats(target, data_len,
361 pEndpoint->TxCreditSize);
362
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800363 status = hif_send_head(target->hif_dev,
364 pEndpoint->UL_PipeID,
Poddar, Siddarth416b7062016-04-29 11:02:13 +0530365 pEndpoint->Id, data_len,
366 bundleBuf, data_attr);
Nirav Shah03c409d2019-06-10 23:23:11 +0530367 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
368 HTC_PACKET_QUEUE requeue;
369
370 qdf_print("hif_send_head failed(len=%zu).", data_len);
371 INIT_HTC_PACKET_QUEUE(&requeue);
372 LOCK_HTC_TX(target);
373 pEndpoint->ul_outstanding_cnt--;
374 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacketTx);
375
376 if (pPacketTx->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) {
377 HTC_PACKET *temp_packet;
378 HTC_PACKET_QUEUE *packet_queue =
379 (HTC_PACKET_QUEUE *)pPacketTx->pContext;
380
381 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(packet_queue,
382 temp_packet) {
383 HTC_PACKET_ENQUEUE(&requeue, temp_packet);
384 } HTC_PACKET_QUEUE_ITERATE_END;
385
386 UNLOCK_HTC_TX(target);
387 free_htc_bundle_packet(target, pPacketTx);
388 LOCK_HTC_TX(target);
389
390 } else {
391 HTC_PACKET_ENQUEUE(&requeue, pPacketTx);
392 }
393
394 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
395 &requeue);
396 UNLOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800397 }
398 return status;
399}
400
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530401#ifdef QCA_TX_PADDING_CREDIT_SUPPORT
402#define SDIO_BLOCK_SIZE 512
403static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep)
404{
405 int ret = 0;
406
407 if (!ep || !ep->EpCallBacks.pContext ||
408 !ep->EpCallBacks.ep_padding_credit_update)
409 return 1;
410
411 ret = ep->EpCallBacks.ep_padding_credit_update(ep->EpCallBacks.pContext,
412 0);
413
414 if (ret < 2)
415 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s ret %d\n", __func__, ret));
416
417 return ret;
418}
419
420static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
421 HTC_PACKET *p_last_htc_pkt,
422 unsigned char *p_last_pkt_bundle_buffer,
423 unsigned char **p_bundle_buffer,
424 int tot_data_len)
425{
426 bool extra_tx_credit = FALSE;
427 HTC_FRAME_HDR *p_htc_hdr;
428 int first_buf_bundled_len = 0, last_buf_len = 0;
429 int sdio_pad = 0, free_space = 0;
430 int (*update_ep_padding_credit)(void *, int);
431
432 update_ep_padding_credit = ep->EpCallBacks.ep_padding_credit_update;
433
434 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
435 ("%s Tot data_len = %d\n", __func__, tot_data_len));
436
437 if (!p_last_htc_pkt)
438 return extra_tx_credit;
439
440 last_buf_len = (p_last_htc_pkt->ActualLength + HTC_HDR_LENGTH);
441 if (tot_data_len != last_buf_len) {
442 first_buf_bundled_len = tot_data_len - ep->TxCreditSize;
443 free_space = tot_data_len -
444 (first_buf_bundled_len + last_buf_len);
445 } else {
446 free_space = ep->TxCreditSize - tot_data_len;
447 }
448
449 sdio_pad = SDIO_BLOCK_SIZE - ((first_buf_bundled_len + last_buf_len) %
450 SDIO_BLOCK_SIZE);
451
452 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
453 ("%s first_buf_bundled_len = %d last_buf_len = %d\n",
454 __func__, first_buf_bundled_len, last_buf_len));
455
456 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
457 ("%s sdio_pad = %d free_space = %d\n", __func__,
458 sdio_pad, free_space));
459
460 if (sdio_pad <= free_space) {
461 if (p_bundle_buffer && *p_bundle_buffer) {
462 /* Align Tx bundled buf to avoid a extra Padding buf */
463 *p_bundle_buffer -= (free_space - sdio_pad);
464 }
465 } else {
466 /* Extra Padding Buffer needed, consume extra tx credit */
467 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
468 ("%s Used a Tx credit for Padding Buffer\n",
469 __func__));
470 p_htc_hdr = (HTC_FRAME_HDR *)(p_last_pkt_bundle_buffer);
471 p_htc_hdr->Flags |= HTC_FLAGS_PADDING_CHECK;
472 extra_tx_credit = TRUE;
473 if (ep->EpCallBacks.ep_padding_credit_update) {
474 /* Decrement 1 credit at host,
475 * due to extra tx credit consumed by padding buffer
476 */
477 update_ep_padding_credit(ep->EpCallBacks.pContext, -1);
478 }
479 }
480 return extra_tx_credit;
481}
482#else
483static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep)
484{
485 return 1;
486}
487
488static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
489 HTC_PACKET *p_last_htc_pkt,
490 unsigned char *p_last_pkt_bundle_buffer,
491 unsigned char **p_bundle_buffer,
492 int tot_data_len)
493{
494 return FALSE;
495}
496#endif
497
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700498/**
499 * htc_issue_packets_bundle() - HTC function to send bundle packets from a queue
500 * @target: HTC target on which packets need to be sent
501 * @pEndpoint: logical endpoint on which packets needs to be sent
502 * @pPktQueue: HTC packet queue containing the list of packets to be sent
503 *
504 * Return: void
505 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800506static void htc_issue_packets_bundle(HTC_TARGET *target,
507 HTC_ENDPOINT *pEndpoint,
508 HTC_PACKET_QUEUE *pPktQueue)
509{
510 int i, frag_count, nbytes;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530511 qdf_nbuf_t netbuf, bundleBuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800512 unsigned char *pBundleBuffer = NULL;
513 HTC_PACKET *pPacket = NULL, *pPacketTx = NULL;
514 HTC_FRAME_HDR *pHtcHdr;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700515 int last_credit_pad = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800516 int creditPad, creditRemainder, transferLength, bundlesSpaceRemaining =
517 0;
518 HTC_PACKET_QUEUE *pQueueSave = NULL;
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530519 HTC_PACKET *p_last_htc_pkt = NULL;
520 unsigned char *p_last_pkt_bundle_buffer = NULL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800521
522 bundlesSpaceRemaining =
523 target->MaxMsgsPerHTCBundle * pEndpoint->TxCreditSize;
524 pPacketTx = allocate_htc_bundle_packet(target);
525 if (!pPacketTx) {
526 /* good time to panic */
527 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700528 ("allocate_htc_bundle_packet failed\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800529 AR_DEBUG_ASSERT(false);
530 return;
531 }
532 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530533 pBundleBuffer = qdf_nbuf_data(bundleBuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800534 pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext;
535 while (1) {
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530536 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
537 if (htc_tx_pad_credit_avail(pEndpoint) < 1)
538 break;
539 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800540 pPacket = htc_packet_dequeue(pPktQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700541 if (!pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800542 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800543 creditPad = 0;
544 transferLength = pPacket->ActualLength + HTC_HDR_LENGTH;
545 creditRemainder = transferLength % pEndpoint->TxCreditSize;
546 if (creditRemainder != 0) {
547 if (transferLength < pEndpoint->TxCreditSize) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700548 creditPad = pEndpoint->TxCreditSize -
549 transferLength;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800550 } else {
551 creditPad = creditRemainder;
552 }
553 transferLength += creditPad;
554 }
555
556 if (bundlesSpaceRemaining < transferLength) {
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530557 htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt,
558 p_last_pkt_bundle_buffer,
559 &pBundleBuffer,
560 pBundleBuffer -
561 qdf_nbuf_data(bundleBuf));
562
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800563 /* send out previous buffer */
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700564 htc_send_bundled_netbuf(target, pEndpoint,
565 pBundleBuffer - last_credit_pad,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800566 pPacketTx);
tfyu60c2c982017-06-09 15:50:03 +0800567 /* One packet has been dequeued from sending queue when enter
568 * this loop, so need to add 1 back for this checking.
569 */
570 if ((HTC_PACKET_QUEUE_DEPTH(pPktQueue) + 1) <
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800571 HTC_MIN_MSG_PER_BUNDLE) {
tfyu60c2c982017-06-09 15:50:03 +0800572 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800573 return;
574 }
575 bundlesSpaceRemaining =
576 target->MaxMsgsPerHTCBundle *
577 pEndpoint->TxCreditSize;
578 pPacketTx = allocate_htc_bundle_packet(target);
579 if (!pPacketTx) {
tfyu60c2c982017-06-09 15:50:03 +0800580 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800581 /* good time to panic */
582 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700583 ("allocate_htc_bundle_packet failed\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800584 AR_DEBUG_ASSERT(false);
585 return;
586 }
587 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530588 pBundleBuffer = qdf_nbuf_data(bundleBuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800589 pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext;
590 }
591
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530592 p_last_htc_pkt = pPacket;
593 p_last_pkt_bundle_buffer = pBundleBuffer;
594
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800595 bundlesSpaceRemaining -= transferLength;
596 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700597
598 if (hif_get_bus_type(target->hif_dev) != QDF_BUS_TYPE_USB) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700599 pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(
600 netbuf, 0);
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700601 HTC_WRITE32(pHtcHdr,
602 SM(pPacket->ActualLength,
603 HTC_FRAME_HDR_PAYLOADLEN) |
604 SM(pPacket->PktInfo.AsTx.SendFlags |
Visweswara Tanuku68f18632019-08-19 16:35:11 +0530605#ifdef QCA_TX_PADDING_CREDIT_SUPPORT
606 /*
607 * This is a WAR to avoid FW Crash,
608 * to be removed once fixed in FW
609 */
610 0,
611#else
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700612 HTC_FLAGS_SEND_BUNDLE,
Visweswara Tanuku68f18632019-08-19 16:35:11 +0530613#endif
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700614 HTC_FRAME_HDR_FLAGS) |
615 SM(pPacket->Endpoint,
616 HTC_FRAME_HDR_ENDPOINTID));
617 HTC_WRITE32((uint32_t *) pHtcHdr + 1,
618 SM(pPacket->PktInfo.AsTx.SeqNo,
619 HTC_FRAME_HDR_CONTROLBYTES1) | SM(creditPad,
620 HTC_FRAME_HDR_RESERVED));
621 pHtcHdr->reserved = creditPad;
622 }
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530623 frag_count = qdf_nbuf_get_num_frags(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800624 nbytes = pPacket->ActualLength + HTC_HDR_LENGTH;
625 for (i = 0; i < frag_count && nbytes > 0; i++) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530626 int frag_len = qdf_nbuf_get_frag_len(netbuf, i);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800627 unsigned char *frag_addr =
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530628 qdf_nbuf_get_frag_vaddr(netbuf, i);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700629 if (frag_len > nbytes)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800630 frag_len = nbytes;
Yue Mab16cf302016-03-08 18:30:25 -0800631 qdf_mem_copy(pBundleBuffer, frag_addr, frag_len);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800632 nbytes -= frag_len;
633 pBundleBuffer += frag_len;
634 }
635 HTC_PACKET_ENQUEUE(pQueueSave, pPacket);
636 pBundleBuffer += creditPad;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700637
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700638 /* last one can't be packed. */
639 if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700640 last_credit_pad = creditPad;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800641 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700642 /* send out remaining buffer */
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530643 if (pBundleBuffer != qdf_nbuf_data(bundleBuf)) {
644 htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt,
645 p_last_pkt_bundle_buffer,
646 &pBundleBuffer,
647 pBundleBuffer -
648 qdf_nbuf_data(bundleBuf));
649
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700650 htc_send_bundled_netbuf(target, pEndpoint,
651 pBundleBuffer - last_credit_pad,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800652 pPacketTx);
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530653 } else {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800654 free_htc_bundle_packet(target, pPacketTx);
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530655 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800656}
657#endif /* ENABLE_BUNDLE_TX */
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700658#else
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530659static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep)
660{
661 return 1;
662}
663
664bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
665 HTC_PACKET *p_last_htc_pkt,
666 unsigned char *p_last_pkt_bundle_buffer,
667 unsigned char **p_bundle_buffer,
668 int tot_data_len);
669bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
670 HTC_PACKET *p_last_htc_pkt,
671 unsigned char *p_last_pkt_bundle_buffer,
672 unsigned char **p_bundle_buffer,
673 int tot_data_len)
674{
675 return FALSE;
676}
677
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700678static void htc_issue_packets_bundle(HTC_TARGET *target,
679 HTC_ENDPOINT *pEndpoint,
680 HTC_PACKET_QUEUE *pPktQueue)
681{
682}
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800683#endif
684
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700685/**
686 * htc_issue_packets() - HTC function to send packets from a queue
687 * @target: HTC target on which packets need to be sent
688 * @pEndpoint: logical endpoint on which packets needs to be sent
689 * @pPktQueue: HTC packet queue containing the list of packets to be sent
690 *
691 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
692 */
Rakesh Pillai13146452017-06-22 12:52:31 +0530693static QDF_STATUS htc_issue_packets(HTC_TARGET *target,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800694 HTC_ENDPOINT *pEndpoint,
695 HTC_PACKET_QUEUE *pPktQueue)
696{
Rakesh Pillai13146452017-06-22 12:52:31 +0530697 QDF_STATUS status = QDF_STATUS_SUCCESS;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530698 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800699 HTC_PACKET *pPacket = NULL;
700 uint16_t payloadLen;
701 HTC_FRAME_HDR *pHtcHdr;
702 uint32_t data_attr = 0;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700703 enum qdf_bus_type bus_type;
Himanshu Agarwalfa594d92017-04-04 12:36:33 +0530704 QDF_STATUS ret;
wadesong4b3f37d2018-01-25 16:08:05 +0800705 bool rt_put = false;
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530706 bool used_extra_tx_credit = false;
707 uint8_t *buf = NULL;
708 int (*update_ep_padding_credit)(void *, int);
709 void *ctx = NULL;
710
711 update_ep_padding_credit =
712 pEndpoint->EpCallBacks.ep_padding_credit_update;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700713
714 bus_type = hif_get_bus_type(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800715
716 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700717 ("+htc_issue_packets: Queue: %pK, Pkts %d\n", pPktQueue,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800718 HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
719 while (true) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700720 if (HTC_TX_BUNDLE_ENABLED(target) &&
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800721 HTC_PACKET_QUEUE_DEPTH(pPktQueue) >=
722 HTC_MIN_MSG_PER_BUNDLE) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700723 switch (bus_type) {
724 case QDF_BUS_TYPE_SDIO:
725 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint))
726 break;
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530727 if (update_ep_padding_credit) {
728 if (htc_tx_pad_credit_avail
729 (pEndpoint) < 1)
730 break;
731 }
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700732 case QDF_BUS_TYPE_USB:
733 htc_issue_packets_bundle(target,
734 pEndpoint,
735 pPktQueue);
736 break;
737 default:
738 break;
739 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800740 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700741 /* if not bundling or there was a packet that could not be
742 * placed in a bundle, and send it by normal way
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800743 */
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530744 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
745 if (htc_tx_pad_credit_avail(pEndpoint) < 1) {
746 status = QDF_STATUS_E_FAILURE;
747 break;
748 }
749 }
750
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800751 pPacket = htc_packet_dequeue(pPktQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700752 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800753 /* local queue is fully drained */
754 break;
755 }
756
757 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
758 AR_DEBUG_ASSERT(netbuf);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700759 /* Non-credit enabled endpoints have been mapped and setup by
760 * now, so no need to revisit the HTC headers
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800761 */
762 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
763
764 payloadLen = pPacket->ActualLength;
765 /* setup HTC frame header */
766
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530767 pHtcHdr = (HTC_FRAME_HDR *)
768 qdf_nbuf_get_frag_vaddr(netbuf, 0);
jitiphil4a8f66f2018-05-31 13:15:20 +0530769 if (qdf_unlikely(!pHtcHdr)) {
770 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
771 ("%s Invalid pHtcHdr\n",
772 __func__));
773 AR_DEBUG_ASSERT(pHtcHdr);
774 status = QDF_STATUS_E_FAILURE;
775 break;
776 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800777
778 HTC_WRITE32(pHtcHdr,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700779 SM(payloadLen,
780 HTC_FRAME_HDR_PAYLOADLEN) |
781 SM(pPacket->PktInfo.AsTx.SendFlags,
782 HTC_FRAME_HDR_FLAGS) |
783 SM(pPacket->Endpoint,
784 HTC_FRAME_HDR_ENDPOINTID));
Yue Mab16cf302016-03-08 18:30:25 -0800785 HTC_WRITE32(((uint32_t *) pHtcHdr) + 1,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800786 SM(pPacket->PktInfo.AsTx.SeqNo,
787 HTC_FRAME_HDR_CONTROLBYTES1));
788
789 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700790 * Now that the HTC frame header has been added, the
791 * netbuf can be mapped. This only applies to non-data
792 * frames, since data frames were already mapped as they
Dustin Brownbc9718f2017-12-11 12:15:27 -0800793 * entered into the driver.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800794 */
Dustin Brownbc9718f2017-12-11 12:15:27 -0800795 pPacket->PktInfo.AsTx.Flags |=
796 HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
797
798 ret = qdf_nbuf_map(target->osdev,
799 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
800 QDF_DMA_TO_DEVICE);
801 if (ret != QDF_STATUS_SUCCESS) {
802 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
803 ("%s nbuf Map Fail Endpnt %pK\n",
804 __func__, pEndpoint));
805 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
806 status = QDF_STATUS_E_FAILURE;
807 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800808 }
809 }
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530810
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530811 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530812 LOCK_HTC_TX(target);
813 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800814 /* store in look up queue to match completions */
815 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket);
816 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
817 pEndpoint->ul_outstanding_cnt++;
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530818 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530819 UNLOCK_HTC_TX(target);
820 hif_send_complete_check(target->hif_dev,
821 pEndpoint->UL_PipeID, false);
822 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800823
Himanshu Agarwal974d0a52017-03-08 21:13:51 +0530824 htc_packet_set_magic_cookie(pPacket, HTC_PACKET_MAGIC_COOKIE);
wadesong4b3f37d2018-01-25 16:08:05 +0800825 /*
826 * For HTT messages without a response from fw,
827 * do the runtime put here.
828 * otherwise runtime put will be done when the fw response comes
829 */
830 if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_RUNTIME_PUT)
831 rt_put = true;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800832#if DEBUG_BUNDLE
Aditya Sathish648ce112018-07-02 16:41:39 +0530833 qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800834 pEndpoint->Id,
835 pEndpoint->TxCreditSize,
836 HTC_HDR_LENGTH + pPacket->ActualLength);
837#endif
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530838 buf = (uint8_t *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
839 used_extra_tx_credit =
840 htc_handle_extra_tx_credit(pEndpoint, pPacket, buf,
841 NULL, pPacket->ActualLength +
842 HTC_HDR_LENGTH);
843
wadesong4b3f37d2018-01-25 16:08:05 +0800844 status = hif_send_head(target->hif_dev,
845 pEndpoint->UL_PipeID, pEndpoint->Id,
846 HTC_HDR_LENGTH + pPacket->ActualLength,
847 netbuf, data_attr);
848
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530849 if (status != QDF_STATUS_SUCCESS) {
850 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
851 if (used_extra_tx_credit) {
852 ctx = pEndpoint->EpCallBacks.pContext;
853 update_ep_padding_credit(ctx, 1);
854 }
855 }
856 }
857
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530858 htc_issue_tx_bundle_stats_inc(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800859
860 target->ce_send_cnt++;
861
Rakesh Pillai13146452017-06-22 12:52:31 +0530862 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
863 if (status != QDF_STATUS_E_RESOURCES) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700864 /* TODO : if more than 1 endpoint maps to the
865 * same PipeID it is possible to run out of
866 * resources in the HIF layer. Don't emit the
867 * error
868 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800869 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700870 ("hif_send Failed status:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800871 status));
872 }
Dustin Brown942f9392018-06-25 14:34:45 -0700873
874 /* only unmap if we mapped in this function */
Nirav Shah0811d822019-04-13 22:43:29 +0530875 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
Dustin Brown942f9392018-06-25 14:34:45 -0700876 qdf_nbuf_unmap(target->osdev,
877 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
878 QDF_DMA_TO_DEVICE);
Nirav Shah0811d822019-04-13 22:43:29 +0530879 pPacket->PktInfo.AsTx.Flags &=
880 ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
881 }
Dustin Brown942f9392018-06-25 14:34:45 -0700882
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530883 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530884 LOCK_HTC_TX(target);
885 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800886 target->ce_send_cnt--;
887 pEndpoint->ul_outstanding_cnt--;
888 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket);
Himanshu Agarwal974d0a52017-03-08 21:13:51 +0530889 htc_packet_set_magic_cookie(pPacket, 0);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800890 /* put it back into the callers queue */
891 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
Frank Liud2cc13e2018-12-06 16:03:26 +0800892 /* reclaim credits */
893 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,
894 pPacket) {
895 pEndpoint->TxCredits +=
896 pPacket->PktInfo.AsTx.CreditsUsed;
897 } HTC_PACKET_QUEUE_ITERATE_END;
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530898 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530899 UNLOCK_HTC_TX(target);
900 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800901 break;
902 }
wadesong4b3f37d2018-01-25 16:08:05 +0800903 if (rt_put) {
Houston Hoffman1dd22762015-11-10 11:35:49 -0800904 hif_pm_runtime_put(target->hif_dev);
wadesong4b3f37d2018-01-25 16:08:05 +0800905 rt_put = false;
906 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800907 }
Rakesh Pillai13146452017-06-22 12:52:31 +0530908 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -0800909 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700910 ("htc_issue_packets, failed pkt:0x%pK status:%d",
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -0800911 pPacket, status));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800912 }
913
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700914 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_issue_packets\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800915
916 return status;
917}
918
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800919#ifdef FEATURE_RUNTIME_PM
920/**
Jeff Johnson4b253f02018-05-12 11:34:43 -0700921 * extract_htc_pm_packets(): move pm packets from endpoint into queue
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800922 * @endpoint: which enpoint to extract packets from
923 * @queue: a queue to store extracted packets in.
924 *
925 * remove pm packets from the endpoint's tx queue.
926 * queue them into a queue
927 */
928static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
929 HTC_PACKET_QUEUE *queue)
930{
931 HTC_PACKET *packet;
932
933 /* only WMI endpoint has power management packets */
934 if (endpoint->service_id != WMI_CONTROL_SVC)
935 return;
936
937 ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet,
938 HTC_PACKET, ListLink) {
939 if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_AUTO_PM) {
940 HTC_PACKET_REMOVE(&endpoint->TxQueue, packet);
941 HTC_PACKET_ENQUEUE(queue, packet);
942 }
943 } ITERATE_END
944}
945
946/**
947 * queue_htc_pm_packets(): queue pm packets with priority
948 * @endpoint: enpoint to queue packets to
949 * @queue: queue of pm packets to enque
950 *
951 * suspend resume packets get special treatment & priority.
952 * need to queue them at the front of the queue.
953 */
954static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
955 HTC_PACKET_QUEUE *queue)
956{
957 if (endpoint->service_id != WMI_CONTROL_SVC)
958 return;
959
960 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&endpoint->TxQueue, queue);
961}
962#else
963static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
964 HTC_PACKET_QUEUE *queue)
965{}
966
967static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
968 HTC_PACKET_QUEUE *queue)
969{}
970#endif
971
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700972/**
973 * get_htc_send_packets_credit_based() - get packets based on available credits
974 * @target: HTC target on which packets need to be sent
975 * @pEndpoint: logical endpoint on which packets needs to be sent
976 * @pQueue: HTC packet queue containing the list of packets to be sent
977 *
978 * Get HTC send packets from TX queue on an endpoint based on available credits.
979 * The function moves the packets from TX queue of the endpoint to pQueue.
980 *
981 * Return: None
982 */
Jeff Johnsonc66399a2016-10-07 13:01:33 -0700983static void get_htc_send_packets_credit_based(HTC_TARGET *target,
984 HTC_ENDPOINT *pEndpoint,
985 HTC_PACKET_QUEUE *pQueue)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800986{
987 int creditsRequired;
988 int remainder;
Yue Mab16cf302016-03-08 18:30:25 -0800989 uint8_t sendFlags;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800990 HTC_PACKET *pPacket;
991 unsigned int transferLength;
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800992 HTC_PACKET_QUEUE *tx_queue;
993 HTC_PACKET_QUEUE pm_queue;
994 bool do_pm_get = false;
Yue Ma4986b252019-07-23 15:57:48 -0700995 int ret;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800996
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700997 /*** NOTE : the TX lock is held when this function is called ***/
998 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
999 ("+get_htc_send_packets_credit_based\n"));
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001000
1001 INIT_HTC_PACKET_QUEUE(&pm_queue);
1002 extract_htc_pm_packets(pEndpoint, &pm_queue);
1003 if (HTC_QUEUE_EMPTY(&pm_queue)) {
1004 tx_queue = &pEndpoint->TxQueue;
1005 do_pm_get = true;
1006 } else {
1007 tx_queue = &pm_queue;
1008 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001009
1010 /* loop until we can grab as many packets out of the queue as we can */
1011 while (true) {
Yue Ma4986b252019-07-23 15:57:48 -07001012 if (do_pm_get) {
1013 ret = hif_pm_runtime_get(target->hif_dev);
1014 if (ret) {
1015 /* bus suspended, runtime resume issued */
1016 QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
1017 if (ret == -EAGAIN) {
1018 pPacket = htc_get_pkt_at_head(tx_queue);
1019 if (!pPacket)
1020 break;
1021 log_packet_info(target, pPacket);
1022 }
1023 break;
1024 }
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001025 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001026
1027 sendFlags = 0;
1028 /* get packet at head, but don't remove it */
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001029 pPacket = htc_get_pkt_at_head(tx_queue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001030 if (!pPacket) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001031 if (do_pm_get)
1032 hif_pm_runtime_put(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001033 break;
1034 }
1035
1036 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001037 (" Got head packet:%pK , Queue Depth: %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001038 pPacket,
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001039 HTC_PACKET_QUEUE_DEPTH(tx_queue)));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001040
1041 transferLength = pPacket->ActualLength + HTC_HDR_LENGTH;
1042
1043 if (transferLength <= pEndpoint->TxCreditSize) {
1044 creditsRequired = 1;
1045 } else {
1046 /* figure out how many credits this message requires */
1047 creditsRequired =
1048 transferLength / pEndpoint->TxCreditSize;
1049 remainder = transferLength % pEndpoint->TxCreditSize;
1050
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001051 if (remainder)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001052 creditsRequired++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001053 }
1054
1055 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1056 (" Credits Required:%d Got:%d\n",
1057 creditsRequired, pEndpoint->TxCredits));
1058
1059 if (pEndpoint->Id == ENDPOINT_0) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001060 /*
1061 * endpoint 0 is special, it always has a credit and
1062 * does not require credit based flow control
1063 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001064 creditsRequired = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001065 } else {
1066
1067 if (pEndpoint->TxCredits < creditsRequired) {
1068#if DEBUG_CREDIT
1069 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001070 ("EP%d,No Credit now.%d < %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001071 pEndpoint->Id,
1072 pEndpoint->TxCredits,
1073 creditsRequired));
1074#endif
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001075 if (do_pm_get)
1076 hif_pm_runtime_put(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001077 break;
1078 }
1079
1080 pEndpoint->TxCredits -= creditsRequired;
1081 INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed,
1082 creditsRequired);
1083
1084 /* check if we need credits back from the target */
1085 if (pEndpoint->TxCredits <=
1086 pEndpoint->TxCreditsPerMaxMsg) {
1087 /* tell the target we need credits ASAP! */
1088 sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
Houston Hoffman4f2f4592015-10-20 18:00:29 -07001089 if (pEndpoint->service_id == WMI_CONTROL_SVC) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001090 htc_credit_record(HTC_REQUEST_CREDIT,
1091 pEndpoint->TxCredits,
1092 HTC_PACKET_QUEUE_DEPTH
Rachit Kankane1bc11492018-01-24 18:48:17 +05301093 (tx_queue));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001094 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001095 INC_HTC_EP_STAT(pEndpoint,
1096 TxCreditLowIndications, 1);
1097#if DEBUG_CREDIT
1098 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1099 (" EP%d Needs Credits\n",
1100 pEndpoint->Id));
1101#endif
1102 }
1103 }
1104
1105 /* now we can fully dequeue */
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001106 pPacket = htc_packet_dequeue(tx_queue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001107 if (pPacket) {
1108 /* save the number of credits this packet consumed */
1109 pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired;
1110 /* save send flags */
1111 pPacket->PktInfo.AsTx.SendFlags = sendFlags;
1112
1113 /* queue this packet into the caller's queue */
1114 HTC_PACKET_ENQUEUE(pQueue, pPacket);
1115 }
1116 }
1117
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001118 if (!HTC_QUEUE_EMPTY(&pm_queue))
1119 queue_htc_pm_packets(pEndpoint, &pm_queue);
1120
1121 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1122 ("-get_htc_send_packets_credit_based\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001123
1124}
1125
Jeff Johnsonc66399a2016-10-07 13:01:33 -07001126static void get_htc_send_packets(HTC_TARGET *target,
1127 HTC_ENDPOINT *pEndpoint,
1128 HTC_PACKET_QUEUE *pQueue, int Resources)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001129{
1130
1131 HTC_PACKET *pPacket;
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001132 HTC_PACKET_QUEUE *tx_queue;
1133 HTC_PACKET_QUEUE pm_queue;
Tiger Yu054a6a42018-03-30 14:58:02 +08001134 bool do_pm_get = false;
Yue Ma4986b252019-07-23 15:57:48 -07001135 int ret;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001136
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001137 /*** NOTE : the TX lock is held when this function is called ***/
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001138 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1139 ("+get_htc_send_packets %d resources\n", Resources));
1140
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001141 INIT_HTC_PACKET_QUEUE(&pm_queue);
1142 extract_htc_pm_packets(pEndpoint, &pm_queue);
1143 if (HTC_QUEUE_EMPTY(&pm_queue)) {
1144 tx_queue = &pEndpoint->TxQueue;
1145 do_pm_get = true;
1146 } else {
1147 tx_queue = &pm_queue;
1148 }
1149
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001150 /* loop until we can grab as many packets out of the queue as we can */
1151 while (Resources > 0) {
1152 int num_frags;
1153
Yue Ma4986b252019-07-23 15:57:48 -07001154 if (do_pm_get) {
1155 ret = hif_pm_runtime_get(target->hif_dev);
1156 if (ret) {
1157 /* bus suspended, runtime resume issued */
1158 QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
1159 if (ret == -EAGAIN) {
1160 pPacket = htc_get_pkt_at_head(tx_queue);
1161 if (!pPacket)
1162 break;
1163 log_packet_info(target, pPacket);
1164 }
1165 break;
1166 }
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001167 }
1168
1169 pPacket = htc_packet_dequeue(tx_queue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001170 if (!pPacket) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001171 if (do_pm_get)
1172 hif_pm_runtime_put(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001173 break;
1174 }
1175 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001176 (" Got packet:%pK , New Queue Depth: %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001177 pPacket,
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001178 HTC_PACKET_QUEUE_DEPTH(tx_queue)));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001179 /* For non-credit path the sequence number is already embedded
1180 * in the constructed HTC header
1181 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001182 pPacket->PktInfo.AsTx.SendFlags = 0;
1183 pPacket->PktInfo.AsTx.CreditsUsed = 0;
1184 /* queue this packet into the caller's queue */
1185 HTC_PACKET_ENQUEUE(pQueue, pPacket);
1186
1187 /*
1188 * FIX THIS:
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301189 * For now, avoid calling qdf_nbuf_get_num_frags before calling
1190 * qdf_nbuf_map, because the MacOS version of qdf_nbuf_t doesn't
1191 * support qdf_nbuf_get_num_frags until after qdf_nbuf_map has
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001192 * been done.
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001193 * Assume that the non-data netbufs, i.e. WMI message netbufs,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001194 * consist of a single fragment.
1195 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001196 /* WMI messages are in a single-fragment network buf */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001197 num_frags =
1198 (pPacket->PktInfo.AsTx.
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001199 Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) ? 1 :
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301200 qdf_nbuf_get_num_frags(GET_HTC_PACKET_NET_BUF_CONTEXT
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001201 (pPacket));
1202 Resources -= num_frags;
1203 }
1204
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001205 if (!HTC_QUEUE_EMPTY(&pm_queue))
1206 queue_htc_pm_packets(pEndpoint, &pm_queue);
1207
1208 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001209
1210}
1211
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001212/**
1213 * htc_try_send() - Send packets in a queue on an endpoint
1214 * @target: HTC target on which packets need to be sent
1215 * @pEndpoint: logical endpoint on which packets needs to be sent
1216 * @pCallersSendQueue: packet queue containing the list of packets to be sent
1217 *
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001218 * Return: enum HTC_SEND_QUEUE_RESULT indicates whether the packet was queued to
1219 * be sent or the packet should be dropped by the upper layer
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001220 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001221static enum HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001222 HTC_ENDPOINT *pEndpoint,
1223 HTC_PACKET_QUEUE *pCallersSendQueue)
1224{
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001225 /* temp queue to hold packets at various stages */
1226 HTC_PACKET_QUEUE sendQueue;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001227 HTC_PACKET *pPacket;
1228 int tx_resources;
1229 int overflow;
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001230 enum HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001231
Jeff Johnsona79b1112017-09-18 10:12:02 -07001232 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+htc_try_send (Queue:%pK Depth:%d)\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001233 pCallersSendQueue,
1234 (pCallersSendQueue ==
1235 NULL) ? 0 :
1236 HTC_PACKET_QUEUE_DEPTH
1237 (pCallersSendQueue)));
1238
1239 /* init the local send queue */
1240 INIT_HTC_PACKET_QUEUE(&sendQueue);
1241
1242 do {
1243
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001244 /* caller didn't provide a queue, just wants us to check
1245 * queues and send
1246 */
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001247 if (!pCallersSendQueue)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001248 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001249
1250 if (HTC_QUEUE_EMPTY(pCallersSendQueue)) {
1251 /* empty queue */
1252 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,
1253 HTC_PKT_Q_EMPTY);
1254 result = HTC_SEND_QUEUE_DROP;
1255 break;
1256 }
1257
1258 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >=
1259 pEndpoint->MaxTxQueueDepth) {
1260 /* we've already overflowed */
1261 overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
1262 } else {
1263 /* figure out how much we will overflow by */
1264 overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
1265 overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001266 /* get how much we will overflow the TX queue by */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001267 overflow -= pEndpoint->MaxTxQueueDepth;
1268 }
1269
1270 /* if overflow is negative or zero, we are okay */
1271 if (overflow > 0) {
1272 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001273 ("Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001274 pEndpoint->Id, overflow,
1275 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->
1276 TxQueue),
1277 pEndpoint->MaxTxQueueDepth));
1278 }
1279 if ((overflow <= 0)
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001280 || (!pEndpoint->EpCallBacks.EpSendFull)) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001281 /* all packets will fit or caller did not provide send
1282 * full indication handler
1283 * just move all of them to local sendQueue object
1284 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001285 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue,
1286 pCallersSendQueue);
1287 } else {
1288 int i;
1289 int goodPkts =
1290 HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) -
1291 overflow;
1292
1293 A_ASSERT(goodPkts >= 0);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001294 /* we have overflowed and callback is provided. Dequeue
1295 * all non-overflow packets into the sendqueue
1296 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001297 for (i = 0; i < goodPkts; i++) {
1298 /* pop off caller's queue */
1299 pPacket = htc_packet_dequeue(pCallersSendQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001300 A_ASSERT(pPacket);
Alok Kumar5d4c6f22019-06-24 16:31:59 +05301301 if (pPacket)
1302 /* insert into local queue */
1303 HTC_PACKET_ENQUEUE(&sendQueue,
1304 pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001305 }
1306
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001307 /* the caller's queue has all the packets that won't fit
1308 * walk through the caller's queue and indicate each one
1309 * to the send full handler
1310 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001311 ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->
1312 QueueHead, pPacket,
1313 HTC_PACKET, ListLink) {
1314
1315 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001316 ("Indicating overflowed TX packet: %pK\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001317 pPacket));
1318 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001319 * Remove headroom reserved for HTC_FRAME_HDR
1320 * before giving the packet back to the user via
1321 * the EpSendFull callback.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001322 */
1323 restore_tx_packet(target, pPacket);
1324
1325 if (pEndpoint->EpCallBacks.
1326 EpSendFull(pEndpoint->EpCallBacks.pContext,
1327 pPacket) == HTC_SEND_FULL_DROP) {
1328 /* callback wants the packet dropped */
1329 INC_HTC_EP_STAT(pEndpoint, TxDropped,
1330 1);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001331 /* leave this one in the caller's queue
1332 * for cleanup
1333 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001334 } else {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001335 /* callback wants to keep this packet,
1336 * remove from caller's queue
1337 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001338 HTC_PACKET_REMOVE(pCallersSendQueue,
1339 pPacket);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001340 /* put it in the send queue
1341 * add HTC_FRAME_HDR space reservation
1342 * again
1343 */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301344 qdf_nbuf_push_head
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001345 (GET_HTC_PACKET_NET_BUF_CONTEXT
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001346 (pPacket),
1347 sizeof(HTC_FRAME_HDR));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001348
1349 HTC_PACKET_ENQUEUE(&sendQueue, pPacket);
1350 }
1351
1352 }
1353 ITERATE_END;
1354
1355 if (HTC_QUEUE_EMPTY(&sendQueue)) {
1356 /* no packets made it in, caller will cleanup */
1357 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001358 HTC_SEND_Q_EMPTY);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001359 result = HTC_SEND_QUEUE_DROP;
1360 break;
1361 }
1362 }
1363
1364 } while (false);
1365
1366 if (result != HTC_SEND_QUEUE_OK) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001367 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send: %d\n",
1368 result));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001369 return result;
1370 }
1371
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001372 LOCK_HTC_TX(target);
1373
1374 if (!HTC_QUEUE_EMPTY(&sendQueue)) {
gbianb417db22016-09-30 17:01:07 +08001375 if (target->is_nodrop_pkt) {
1376 /*
1377 * nodrop pkts have higher priority than normal pkts,
1378 * insert nodrop pkt to head for proper
1379 * start/termination of test.
1380 */
1381 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
1382 &sendQueue);
1383 target->is_nodrop_pkt = false;
1384 } else {
1385 /* transfer packets to tail */
1386 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,
1387 &sendQueue);
1388 A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue));
1389 INIT_HTC_PACKET_QUEUE(&sendQueue);
1390 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001391 }
1392
1393 /* increment tx processing count on entry */
Rajeev Kumare37820e2016-04-14 17:30:56 -07001394 if (qdf_atomic_inc_return(&pEndpoint->TxProcessCount) > 1) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001395 /* another thread or task is draining the TX queues on this
1396 * endpoint that thread will reset the tx processing count when
1397 * the queue is drained
1398 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301399 qdf_atomic_dec(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001400 UNLOCK_HTC_TX(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001401 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send (busy)\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001402 return HTC_SEND_QUEUE_OK;
1403 }
1404
1405 /***** beyond this point only 1 thread may enter ******/
1406
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001407 /* now drain the endpoint TX queue for transmission as long as we have
1408 * enough transmit resources
1409 */
Ajit Pal Singh5c3ba892019-06-04 13:24:57 +05301410 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1411 tx_resources =
1412 hif_get_free_queue_number(target->hif_dev,
1413 pEndpoint->UL_PipeID);
1414 } else {
1415 tx_resources = 0;
1416 }
1417
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001418 while (true) {
1419
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301420 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0)
1421 break;
1422
1423 if (pEndpoint->async_update &&
1424 (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) &&
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001425 (!tx_resources))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001426 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001427
1428 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1429#if DEBUG_CREDIT
1430 int cred = pEndpoint->TxCredits;
1431#endif
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001432 /* credit based mechanism provides flow control based on
1433 * target transmit resource availability, we assume that
1434 * the HIF layer will always have bus resources greater
1435 * than target transmit resources
1436 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001437 get_htc_send_packets_credit_based(target, pEndpoint,
1438 &sendQueue);
1439#if DEBUG_CREDIT
1440 if (ep_debug_mask & (1 << pEndpoint->Id)) {
1441 if (cred - pEndpoint->TxCredits > 0) {
1442 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001443 (" <HTC> Decrease EP%d %d - %d = %d credits.\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001444 pEndpoint->Id, cred,
1445 cred -
1446 pEndpoint->TxCredits,
1447 pEndpoint->TxCredits));
1448 }
1449 }
1450#endif
1451 } else {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001452
1453 /*
1454 * Header and payload belongs to the different fragments and
1455 * consume 2 resource for one HTC package but USB combine into
Liangwei Dong2c73be82016-09-29 03:35:59 -04001456 * one transfer.And one WMI message only consumes one single
1457 * resource.
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001458 */
Liangwei Dong2c73be82016-09-29 03:35:59 -04001459 if (HTC_TX_BUNDLE_ENABLED(target) && tx_resources &&
1460 hif_get_bus_type(target->hif_dev) ==
1461 QDF_BUS_TYPE_USB) {
1462 if (pEndpoint->service_id ==
1463 WMI_CONTROL_SVC)
1464 tx_resources =
1465 HTC_MAX_MSG_PER_BUNDLE_TX;
1466 else
1467 tx_resources =
1468 (HTC_MAX_MSG_PER_BUNDLE_TX * 2);
1469 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001470 /* get all the packets for this endpoint that we can for
1471 * this pass
1472 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001473 get_htc_send_packets(target, pEndpoint, &sendQueue,
1474 tx_resources);
1475 }
1476
1477 if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001478 /* didn't get any packets due to a lack of resources or
1479 * TX queue was drained
1480 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001481 break;
1482 }
1483
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001484 if (!pEndpoint->async_update)
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05301485 UNLOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001486
1487 /* send what we can */
Rakesh Pillai13146452017-06-22 12:52:31 +05301488 if (htc_issue_packets(target, pEndpoint, &sendQueue)) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001489 int i;
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001490
Rakesh Pillai13146452017-06-22 12:52:31 +05301491 result = HTC_SEND_QUEUE_DROP;
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -08001492 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1493 ("htc_issue_packets, failed status:%d put it back to head of callersSendQueue",
1494 result));
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001495
1496 for (i = HTC_PACKET_QUEUE_DEPTH(&sendQueue); i > 0; i--)
1497 hif_pm_runtime_put(target->hif_dev);
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301498 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandarub3c810b2016-11-02 17:12:34 +05301499 LOCK_HTC_TX(target);
1500 }
Liangwei Dong6c5e3322016-11-07 00:27:50 -05001501 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
1502 &sendQueue);
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -08001503 break;
1504 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001505
1506 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1507 tx_resources =
1508 hif_get_free_queue_number(target->hif_dev,
1509 pEndpoint->UL_PipeID);
1510 }
1511
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301512 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05301513 LOCK_HTC_TX(target);
1514 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001515
1516 }
1517
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001518 /* done with this endpoint, we can clear the count */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301519 qdf_atomic_init(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001520
Rajeev Kumare37820e2016-04-14 17:30:56 -07001521 UNLOCK_HTC_TX(target);
1522
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001523 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send:\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001524
1525 return HTC_SEND_QUEUE_OK;
1526}
1527
1528#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001529static uint16_t htc_send_pkts_sched_check(HTC_HANDLE HTCHandle,
1530 HTC_ENDPOINT_ID id)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001531{
1532 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1533 HTC_ENDPOINT *pEndpoint;
1534 HTC_ENDPOINT_ID eid;
1535 HTC_PACKET_QUEUE *pTxQueue;
Yue Mab16cf302016-03-08 18:30:25 -08001536 uint16_t resources;
1537 uint16_t acQueueStatus[DATA_EP_SIZE] = { 0, 0, 0, 0 };
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001538
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001539 if (id < ENDPOINT_2 || id > ENDPOINT_5)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001540 return 1;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001541
1542 for (eid = ENDPOINT_2; eid <= ENDPOINT_5; eid++) {
Houston Hoffman29573d92015-10-20 17:49:44 -07001543 pEndpoint = &target->endpoint[eid];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001544 pTxQueue = &pEndpoint->TxQueue;
1545
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001546 if (HTC_QUEUE_EMPTY(pTxQueue))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001547 acQueueStatus[eid - 2] = 1;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001548 }
1549
1550 switch (id) {
1551 case ENDPOINT_2: /* BE */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301552 return acQueueStatus[0] && acQueueStatus[2]
1553 && acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001554 case ENDPOINT_3: /* BK */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301555 return acQueueStatus[0] && acQueueStatus[1] && acQueueStatus[2]
1556 && acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001557 case ENDPOINT_4: /* VI */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301558 return acQueueStatus[2] && acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001559 case ENDPOINT_5: /* VO */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301560 return acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001561 default:
1562 return 0;
1563 }
1564
1565}
1566
1567static A_STATUS htc_send_pkts_sched_queue(HTC_TARGET *target,
1568 HTC_PACKET_QUEUE *pPktQueue,
1569 HTC_ENDPOINT_ID eid)
1570{
1571 HTC_ENDPOINT *pEndpoint;
1572 HTC_PACKET_QUEUE *pTxQueue;
1573 HTC_PACKET *pPacket;
1574 int goodPkts;
1575
Houston Hoffman29573d92015-10-20 17:49:44 -07001576 pEndpoint = &target->endpoint[eid];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001577 pTxQueue = &pEndpoint->TxQueue;
1578
1579 LOCK_HTC_TX(target);
1580
1581 goodPkts =
1582 pEndpoint->MaxTxQueueDepth -
1583 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
1584
1585 if (goodPkts > 0) {
1586 while (!HTC_QUEUE_EMPTY(pPktQueue)) {
1587 pPacket = htc_packet_dequeue(pPktQueue);
1588 HTC_PACKET_ENQUEUE(pTxQueue, pPacket);
1589 goodPkts--;
1590
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001591 if (goodPkts <= 0)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001592 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001593 }
1594 }
1595
1596 if (HTC_PACKET_QUEUE_DEPTH(pPktQueue)) {
1597 ITERATE_OVER_LIST_ALLOW_REMOVE(&pPktQueue->QueueHead, pPacket,
1598 HTC_PACKET, ListLink) {
1599
1600 if (pEndpoint->EpCallBacks.
1601 EpSendFull(pEndpoint->EpCallBacks.pContext,
1602 pPacket) == HTC_SEND_FULL_DROP) {
1603 INC_HTC_EP_STAT(pEndpoint, TxDropped, 1);
1604 } else {
1605 HTC_PACKET_REMOVE(pPktQueue, pPacket);
1606 HTC_PACKET_ENQUEUE(pTxQueue, pPacket);
1607 }
1608 }
1609 ITERATE_END;
1610 }
1611
1612 UNLOCK_HTC_TX(target);
1613
1614 return A_OK;
1615}
1616
1617#endif
1618
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001619static inline QDF_STATUS __htc_send_pkt(HTC_HANDLE HTCHandle,
1620 HTC_PACKET *pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001621{
1622 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1623 HTC_ENDPOINT *pEndpoint;
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001624 HTC_PACKET_QUEUE pPktQueue;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301625 qdf_nbuf_t netbuf;
Yun Parkc353d6b2018-06-05 11:58:30 -07001626 HTC_FRAME_HDR *htc_hdr;
Himanshu Agarwalfa594d92017-04-04 12:36:33 +05301627 QDF_STATUS status;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001628
1629 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001630 ("+__htc_send_pkt\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001631
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001632 /* get packet at head to figure out which endpoint these packets will
1633 * go into
1634 */
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001635 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001636 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target, GET_HTC_PKT_Q_FAIL);
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001637 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n"));
Rakesh Pillai13146452017-06-22 12:52:31 +05301638 return QDF_STATUS_E_INVAL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001639 }
1640
Jiachao Wu15a94742017-11-10 10:13:38 +08001641 if ((pPacket->Endpoint >= ENDPOINT_MAX) ||
1642 (pPacket->Endpoint <= ENDPOINT_UNUSED)) {
1643 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1644 ("%s endpoint is invalid\n", __func__));
1645 AR_DEBUG_ASSERT(0);
1646 return QDF_STATUS_E_INVAL;
1647 }
Houston Hoffman29573d92015-10-20 17:49:44 -07001648 pEndpoint = &target->endpoint[pPacket->Endpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001649
Houston Hoffman4f2f4592015-10-20 18:00:29 -07001650 if (!pEndpoint->service_id) {
1651 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("%s service_id is invalid\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001652 __func__));
Rakesh Pillai13146452017-06-22 12:52:31 +05301653 return QDF_STATUS_E_INVAL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001654 }
1655
1656#ifdef HTC_EP_STAT_PROFILING
1657 LOCK_HTC_TX(target);
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001658 INC_HTC_EP_STAT(pEndpoint, TxPosted, 1);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001659 UNLOCK_HTC_TX(target);
1660#endif
1661
1662 /* provide room in each packet's netbuf for the HTC frame header */
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001663 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
1664 AR_DEBUG_ASSERT(netbuf);
Yun Parkc353d6b2018-06-05 11:58:30 -07001665 if (!netbuf)
1666 return QDF_STATUS_E_INVAL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001667
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001668 qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR));
Nirav Shah31435bb2019-08-05 17:51:19 +05301669 pPacket->PktInfo.AsTx.Flags |=
1670 HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA;
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001671 /* setup HTC frame header */
Yun Parkc353d6b2018-06-05 11:58:30 -07001672 htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
1673 AR_DEBUG_ASSERT(htc_hdr);
1674 if (!htc_hdr)
1675 return QDF_STATUS_E_INVAL;
1676
1677 HTC_WRITE32(htc_hdr,
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001678 SM(pPacket->ActualLength,
1679 HTC_FRAME_HDR_PAYLOADLEN) |
1680 SM(pPacket->Endpoint,
1681 HTC_FRAME_HDR_ENDPOINTID));
1682 LOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001683
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001684 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
1685 pEndpoint->SeqNo++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001686
Yun Parkc353d6b2018-06-05 11:58:30 -07001687 HTC_WRITE32(((uint32_t *)htc_hdr) + 1,
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001688 SM(pPacket->PktInfo.AsTx.SeqNo,
1689 HTC_FRAME_HDR_CONTROLBYTES1));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001690
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001691 UNLOCK_HTC_TX(target);
Dustin Brownbc9718f2017-12-11 12:15:27 -08001692
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001693 /*
Dustin Brown8969ad72017-12-02 22:43:26 -08001694 * For flow control enabled endpoints mapping is done in
1695 * htc_issue_packets and for non flow control enabled endpoints
1696 * its done here.
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001697 */
Dustin Brown8969ad72017-12-02 22:43:26 -08001698 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
Dustin Brownbc9718f2017-12-11 12:15:27 -08001699 pPacket->PktInfo.AsTx.Flags |= HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
Dustin Brown8969ad72017-12-02 22:43:26 -08001700 status = qdf_nbuf_map(target->osdev,
1701 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
1702 QDF_DMA_TO_DEVICE);
1703 if (status != QDF_STATUS_SUCCESS) {
1704 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1705 ("%s: nbuf map failed, endpoint %pK, seq_no. %d\n",
1706 __func__, pEndpoint, pEndpoint->SeqNo));
1707 return status;
1708 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001709 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001710
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001711 INIT_HTC_PACKET_QUEUE_AND_ADD(&pPktQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001712#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001713 if (!htc_send_pkts_sched_check(HTCHandle, pEndpoint->Id))
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001714 htc_send_pkts_sched_queue(HTCHandle, &pPktQueue, pEndpoint->Id);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001715 else
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001716 htc_try_send(target, pEndpoint, &pPktQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001717#else
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001718 htc_try_send(target, pEndpoint, &pPktQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001719#endif
1720
1721 /* do completion on any packets that couldn't get in */
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001722 while (!HTC_QUEUE_EMPTY(&pPktQueue)) {
1723 pPacket = htc_packet_dequeue(&pPktQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001724
Yun Park88e0b952017-10-11 23:08:34 -07001725 if (HTC_STOPPING(target))
1726 pPacket->Status = QDF_STATUS_E_CANCELED;
1727 else
1728 pPacket->Status = QDF_STATUS_E_RESOURCES;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001729
Yun Park88e0b952017-10-11 23:08:34 -07001730 send_packet_completion(target, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001731 }
1732
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001733 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001734
Rakesh Pillai13146452017-06-22 12:52:31 +05301735 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001736}
1737
1738/* HTC API - htc_send_pkt */
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001739QDF_STATUS htc_send_pkt(HTC_HANDLE htc_handle, HTC_PACKET *htc_packet)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001740{
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001741 if (!htc_handle) {
1742 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1743 ("%s: HTCHandle is NULL \n", __func__));
Rakesh Pillai13146452017-06-22 12:52:31 +05301744 return QDF_STATUS_E_FAILURE;
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001745 }
1746
1747 if (!htc_packet) {
1748 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1749 ("%s: pPacket is NULL \n", __func__));
1750 return QDF_STATUS_E_FAILURE;
1751 }
Karthick Sdc40a352015-10-14 18:14:15 +05301752
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001753 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001754 ("+-htc_send_pkt: Enter endPointId: %d, buffer: %pK, length: %d\n",
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001755 htc_packet->Endpoint, htc_packet->pBuffer,
1756 htc_packet->ActualLength));
1757 return __htc_send_pkt(htc_handle, htc_packet);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001758}
Pratik Gandhidc82a772018-01-30 18:57:05 +05301759qdf_export_symbol(htc_send_pkt);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001760
1761#ifdef ATH_11AC_TXCOMPACT
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001762/**
1763 * htc_send_data_pkt() - send single data packet on an endpoint
1764 * @HTCHandle: pointer to HTC handle
1765 * @netbuf: network buffer containing the data to be sent
1766 * @ActualLength: length of data that needs to be transmitted
1767 *
Rakesh Pillai13146452017-06-22 12:52:31 +05301768 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001769 */
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301770QDF_STATUS htc_send_data_pkt(HTC_HANDLE htc_hdl, qdf_nbuf_t netbuf, int ep_id,
1771 int actual_length)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001772{
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301773 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001774 HTC_ENDPOINT *pEndpoint;
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301775 HTC_FRAME_HDR *p_htc_hdr;
Rakesh Pillai13146452017-06-22 12:52:31 +05301776 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001777 int tx_resources;
1778 uint32_t data_attr = 0;
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301779 int htc_payload_len = actual_length;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001780
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301781 pEndpoint = &target->endpoint[ep_id];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001782
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001783 tx_resources = hif_get_free_queue_number(target->hif_dev,
1784 pEndpoint->UL_PipeID);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001785
1786 if (tx_resources < HTC_DATA_RESOURCE_THRS) {
1787 if (pEndpoint->ul_is_polled) {
1788 hif_send_complete_check(pEndpoint->target->hif_dev,
1789 pEndpoint->UL_PipeID, 1);
1790 tx_resources =
1791 hif_get_free_queue_number(target->hif_dev,
1792 pEndpoint->UL_PipeID);
1793 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001794 if (tx_resources < HTC_DATA_MINDESC_PERPACKET)
Rakesh Pillai13146452017-06-22 12:52:31 +05301795 return QDF_STATUS_E_FAILURE;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001796 }
1797
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001798 if (hif_pm_runtime_get(target->hif_dev))
Rakesh Pillai13146452017-06-22 12:52:31 +05301799 return QDF_STATUS_E_FAILURE;
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001800
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301801 p_htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
1802 AR_DEBUG_ASSERT(p_htc_hdr);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001803
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301804 data_attr = qdf_nbuf_data_attr_get(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001805
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301806 if (target->htc_hdr_length_check)
1807 htc_payload_len = actual_length - HTC_HEADER_LEN;
1808
1809 HTC_WRITE32(p_htc_hdr, SM(htc_payload_len, HTC_FRAME_HDR_PAYLOADLEN)
1810 | SM(ep_id, HTC_FRAME_HDR_ENDPOINTID));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001811 /*
1812 * If the HIF pipe for the data endpoint is polled rather than
1813 * interrupt-driven, this is a good point to check whether any
1814 * data previously sent through the HIF pipe have finished being
1815 * sent.
1816 * Since this may result in callbacks to htc_tx_completion_handler,
1817 * which can take the HTC tx lock, make the hif_send_complete_check
1818 * call before acquiring the HTC tx lock.
1819 * Call hif_send_complete_check directly, rather than calling
1820 * htc_send_complete_check, and call the PollTimerStart separately
1821 * after calling hif_send_head, so the timer will be started to
1822 * check for completion of the new outstanding download (in the
1823 * unexpected event that other polling calls don't catch it).
1824 */
1825
1826 LOCK_HTC_TX(target);
1827
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301828 HTC_WRITE32(((uint32_t *)p_htc_hdr) + 1,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001829 SM(pEndpoint->SeqNo, HTC_FRAME_HDR_CONTROLBYTES1));
1830
1831 pEndpoint->SeqNo++;
1832
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301833 QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301834 DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
Nandha Kishore Easwarane43583f2017-05-15 21:01:13 +05301835 QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf),
1836 sizeof(qdf_nbuf_data(netbuf)), QDF_TX));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001837 status = hif_send_head(target->hif_dev,
1838 pEndpoint->UL_PipeID,
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301839 pEndpoint->Id, actual_length, netbuf, data_attr);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001840
1841 UNLOCK_HTC_TX(target);
1842 return status;
1843}
1844#else /*ATH_11AC_TXCOMPACT */
1845
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001846/**
1847 * htc_send_data_pkt() - htc_send_data_pkt
1848 * @HTCHandle: pointer to HTC handle
1849 * @pPacket: pointer to HTC_PACKET
1850 * @more_data: indicates whether more data is to follow
1851 *
Rakesh Pillai13146452017-06-22 12:52:31 +05301852 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001853 */
Rakesh Pillai13146452017-06-22 12:52:31 +05301854QDF_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket,
Yue Mab16cf302016-03-08 18:30:25 -08001855 uint8_t more_data)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001856{
1857 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1858 HTC_ENDPOINT *pEndpoint;
1859 HTC_FRAME_HDR *pHtcHdr;
1860 HTC_PACKET_QUEUE sendQueue;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301861 qdf_nbuf_t netbuf = NULL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001862 int tx_resources;
Rakesh Pillai13146452017-06-22 12:52:31 +05301863 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001864 uint32_t data_attr = 0;
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05301865 bool used_extra_tx_credit = false;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001866
1867 if (pPacket) {
Jiachao Wu15a94742017-11-10 10:13:38 +08001868 if ((pPacket->Endpoint >= ENDPOINT_MAX) ||
1869 (pPacket->Endpoint <= ENDPOINT_UNUSED)) {
1870 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1871 ("%s endpoint is invalid\n", __func__));
1872 AR_DEBUG_ASSERT(0);
1873 return QDF_STATUS_E_INVAL;
1874 }
Houston Hoffman29573d92015-10-20 17:49:44 -07001875 pEndpoint = &target->endpoint[pPacket->Endpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001876
1877 /* add HTC_FRAME_HDR in the initial fragment */
1878 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301879 pHtcHdr = (HTC_FRAME_HDR *) qdf_nbuf_get_frag_vaddr(netbuf, 0);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001880 AR_DEBUG_ASSERT(pHtcHdr);
1881
1882 HTC_WRITE32(pHtcHdr,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001883 SM(pPacket->ActualLength,
1884 HTC_FRAME_HDR_PAYLOADLEN) |
1885 SM(pPacket->PktInfo.AsTx.SendFlags,
1886 HTC_FRAME_HDR_FLAGS) |
1887 SM(pPacket->Endpoint,
1888 HTC_FRAME_HDR_ENDPOINTID));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001889 /*
1890 * If the HIF pipe for the data endpoint is polled rather than
1891 * interrupt-driven, this is a good point to check whether any
1892 * data previously sent through the HIF pipe have finished being
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001893 * sent. Since this may result in callbacks to
1894 * htc_tx_completion_handler, which can take the HTC tx lock,
1895 * make the hif_send_complete_check call before acquiring the
1896 * HTC tx lock.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001897 * Call hif_send_complete_check directly, rather than calling
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001898 * htc_send_complete_check, and call the PollTimerStart
1899 * separately after calling hif_send_head, so the timer will be
1900 * started to check for completion of the new outstanding
1901 * download (in the unexpected event that other polling calls
1902 * don't catch it).
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001903 */
1904 if (pEndpoint->ul_is_polled) {
1905 htc_send_complete_poll_timer_stop(pEndpoint);
1906 hif_send_complete_check(pEndpoint->target->hif_dev,
1907 pEndpoint->UL_PipeID, 0);
1908 }
1909
1910 LOCK_HTC_TX(target);
1911
1912 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
1913 pEndpoint->SeqNo++;
1914
Yue Mab16cf302016-03-08 18:30:25 -08001915 HTC_WRITE32(((uint32_t *) pHtcHdr) + 1,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001916 SM(pPacket->PktInfo.AsTx.SeqNo,
1917 HTC_FRAME_HDR_CONTROLBYTES1));
1918
1919 /* append new packet to pEndpoint->TxQueue */
1920 HTC_PACKET_ENQUEUE(&pEndpoint->TxQueue, pPacket);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001921 if (HTC_TX_BUNDLE_ENABLED(target) && (more_data)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001922 UNLOCK_HTC_TX(target);
Rakesh Pillai13146452017-06-22 12:52:31 +05301923 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001924 }
wadesong31d77bc2017-05-28 14:45:21 +08001925
1926 QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
1927 DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
Nirav Shahd9dce6e2018-02-26 14:50:25 +05301928 QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf),
wadesong31d77bc2017-05-28 14:45:21 +08001929 sizeof(qdf_nbuf_data(netbuf)), QDF_TX));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001930 } else {
1931 LOCK_HTC_TX(target);
Houston Hoffman29573d92015-10-20 17:49:44 -07001932 pEndpoint = &target->endpoint[1];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001933 }
1934
1935 /* increment tx processing count on entry */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301936 qdf_atomic_inc(&pEndpoint->TxProcessCount);
1937 if (qdf_atomic_read(&pEndpoint->TxProcessCount) > 1) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001938 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001939 * Another thread or task is draining the TX queues on this
1940 * endpoint. That thread will reset the tx processing count when
1941 * the queue is drained.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001942 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301943 qdf_atomic_dec(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001944 UNLOCK_HTC_TX(target);
Rakesh Pillai13146452017-06-22 12:52:31 +05301945 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001946 }
1947
1948 /***** beyond this point only 1 thread may enter ******/
1949
1950 INIT_HTC_PACKET_QUEUE(&sendQueue);
1951 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1952#if DEBUG_CREDIT
1953 int cred = pEndpoint->TxCredits;
1954#endif
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001955 get_htc_send_packets_credit_based(target, pEndpoint,
1956 &sendQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001957#if DEBUG_CREDIT
1958 if (ep_debug_mask & (1 << pEndpoint->Id)) {
1959 if (cred - pEndpoint->TxCredits > 0) {
1960 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1961 (" <HTC> Decrease EP%d %d - %d = %d credits.\n",
1962 pEndpoint->Id, cred,
1963 cred - pEndpoint->TxCredits,
1964 pEndpoint->TxCredits));
1965 }
1966 }
1967#endif
1968 UNLOCK_HTC_TX(target);
1969 }
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001970
1971 else if (HTC_TX_BUNDLE_ENABLED(target)) {
Ajit Pal Singh3fcc0822019-03-21 17:35:22 +05301972 if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB) {
1973 if (hif_get_free_queue_number(target->hif_dev,
1974 pEndpoint->UL_PipeID))
1975 /*
1976 * Header and payload belongs to the different
1977 * fragments and consume 2 resource for one HTC
1978 * package but USB combine into one transfer.
1979 */
1980 get_htc_send_packets(target, pEndpoint,
1981 &sendQueue,
1982 HTC_MAX_MSG_PER_BUNDLE_TX
1983 * 2);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001984 } else {
Ajit Pal Singh3fcc0822019-03-21 17:35:22 +05301985 /* Dequeue max packets from endpoint tx queue */
1986 get_htc_send_packets(target, pEndpoint, &sendQueue,
1987 HTC_MAX_TX_BUNDLE_SEND_LIMIT);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001988 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001989 UNLOCK_HTC_TX(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001990 } else {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001991 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001992 * Now drain the endpoint TX queue for transmission as long as
1993 * we have enough transmit resources
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001994 */
1995 tx_resources =
1996 hif_get_free_queue_number(target->hif_dev,
1997 pEndpoint->UL_PipeID);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001998 get_htc_send_packets(target, pEndpoint, &sendQueue,
1999 tx_resources);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002000 UNLOCK_HTC_TX(target);
2001 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002002
2003 /* send what we can */
2004 while (true) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002005 if (HTC_TX_BUNDLE_ENABLED(target) &&
2006 (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >=
2007 HTC_MIN_MSG_PER_BUNDLE) &&
2008 (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO ||
2009 hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)) {
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302010 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
2011 if (htc_tx_pad_credit_avail(pEndpoint) < 1) {
2012 status = QDF_STATUS_E_RESOURCES;
2013 /* put the sendQueue back at the front
2014 * of pEndpoint->TxQueue
2015 */
2016 LOCK_HTC_TX(target);
2017 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(
2018 &pEndpoint->TxQueue,
2019 &sendQueue);
2020 UNLOCK_HTC_TX(target);
2021 break;
2022 }
2023 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002024 htc_issue_packets_bundle(target, pEndpoint, &sendQueue);
2025 }
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302026 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
2027 if (htc_tx_pad_credit_avail(pEndpoint) < 1) {
2028 status = QDF_STATUS_E_RESOURCES;
2029 /* put the sendQueue back at the front
2030 * of pEndpoint->TxQueue
2031 */
2032 LOCK_HTC_TX(target);
2033 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(
2034 &pEndpoint->TxQueue,
2035 &sendQueue);
2036 UNLOCK_HTC_TX(target);
2037 break;
2038 }
2039 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002040 pPacket = htc_packet_dequeue(&sendQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07002041 if (!pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002042 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002043 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302044 pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002045
2046 LOCK_HTC_TX(target);
2047 /* store in look up queue to match completions */
2048 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket);
2049 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
2050 pEndpoint->ul_outstanding_cnt++;
2051 UNLOCK_HTC_TX(target);
2052
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302053 used_extra_tx_credit =
2054 htc_handle_extra_tx_credit(pEndpoint, pPacket,
2055 (uint8_t *)pHtcHdr,
2056 NULL,
2057 pPacket->ActualLength
2058 + HTC_HDR_LENGTH);
2059
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002060 status = hif_send_head(target->hif_dev,
2061 pEndpoint->UL_PipeID,
2062 pEndpoint->Id,
2063 HTC_HDR_LENGTH + pPacket->ActualLength,
2064 netbuf, data_attr);
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302065 if (status != QDF_STATUS_SUCCESS) {
2066 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
2067 if (used_extra_tx_credit) {
2068 pEndpoint->EpCallBacks.
2069 ep_padding_credit_update
2070 (pEndpoint->EpCallBacks.pContext, 1);
2071 }
2072 }
2073 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002074#if DEBUG_BUNDLE
Aditya Sathish648ce112018-07-02 16:41:39 +05302075 qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002076 pEndpoint->Id,
2077 pEndpoint->TxCreditSize,
2078 HTC_HDR_LENGTH + pPacket->ActualLength);
2079#endif
2080
Poddar, Siddarthdf030092016-04-28 11:41:57 +05302081 htc_issue_tx_bundle_stats_inc(target);
2082
Rakesh Pillai13146452017-06-22 12:52:31 +05302083 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002084 LOCK_HTC_TX(target);
2085 pEndpoint->ul_outstanding_cnt--;
2086 /* remove this packet from the tx completion queue */
2087 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket);
2088
2089 /*
2090 * Don't bother reclaiming credits - HTC flow control
2091 * is not applicable to tx data.
2092 * In LL systems, there is no download flow control,
2093 * since there's virtually no download delay.
2094 * In HL systems, the txrx SW explicitly performs the
2095 * tx flow control.
2096 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002097 /* pEndpoint->TxCredits +=
2098 * pPacket->PktInfo.AsTx.CreditsUsed;
2099 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002100
2101 /* put this frame back at the front of the sendQueue */
2102 HTC_PACKET_ENQUEUE_TO_HEAD(&sendQueue, pPacket);
2103
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002104 /* put the sendQueue back at the front of
2105 * pEndpoint->TxQueue
2106 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002107 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
2108 &sendQueue);
2109 UNLOCK_HTC_TX(target);
2110 break; /* still need to reset TxProcessCount */
2111 }
2112 }
2113 /* done with this endpoint, we can clear the count */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302114 qdf_atomic_init(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002115
2116 if (pEndpoint->ul_is_polled) {
2117 /*
2118 * Start a cleanup timer to poll for download completion.
2119 * The download completion should be noticed promptly from
2120 * other polling calls, but the timer provides a safety net
2121 * in case other polling calls don't occur as expected.
2122 */
2123 htc_send_complete_poll_timer_start(pEndpoint);
2124 }
2125
2126 return status;
2127}
2128#endif /*ATH_11AC_TXCOMPACT */
Pratik Gandhidc82a772018-01-30 18:57:05 +05302129qdf_export_symbol(htc_send_data_pkt);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002130
2131/*
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302132 * In the adapted HIF layer, qdf_nbuf_t are passed between HIF and HTC,
2133 * since upper layers expects HTC_PACKET containers we use the completed netbuf
2134 * and lookup its corresponding HTC packet buffer from a lookup list.
2135 * This is extra overhead that can be fixed by re-aligning HIF interfaces
2136 * with HTC.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002137 *
2138 */
2139static HTC_PACKET *htc_lookup_tx_packet(HTC_TARGET *target,
2140 HTC_ENDPOINT *pEndpoint,
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302141 qdf_nbuf_t netbuf)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002142{
2143 HTC_PACKET *pPacket = NULL;
2144 HTC_PACKET *pFoundPacket = NULL;
2145 HTC_PACKET_QUEUE lookupQueue;
2146
2147 INIT_HTC_PACKET_QUEUE(&lookupQueue);
Govind Singhc505cdc2017-05-16 12:15:51 +05302148 LOCK_HTC_EP_TX_LOOKUP(pEndpoint);
2149
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002150 LOCK_HTC_TX(target);
2151
2152 /* mark that HIF has indicated the send complete for another packet */
2153 pEndpoint->ul_outstanding_cnt--;
2154
2155 /* Dequeue first packet directly because of in-order completion */
2156 pPacket = htc_packet_dequeue(&pEndpoint->TxLookupQueue);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302157 if (qdf_unlikely(!pPacket)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002158 UNLOCK_HTC_TX(target);
Govind Singhc505cdc2017-05-16 12:15:51 +05302159 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002160 return NULL;
2161 }
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302162 if (netbuf == (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002163 UNLOCK_HTC_TX(target);
Govind Singhc505cdc2017-05-16 12:15:51 +05302164 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002165 return pPacket;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002166 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002167 HTC_PACKET_ENQUEUE(&lookupQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002168
2169 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002170 * Move TX lookup queue to temp queue because most of packets that are
2171 * not index 0 are not top 10 packets.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002172 */
2173 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&lookupQueue,
2174 &pEndpoint->TxLookupQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002175
2176 ITERATE_OVER_LIST_ALLOW_REMOVE(&lookupQueue.QueueHead, pPacket,
2177 HTC_PACKET, ListLink) {
2178
Jeff Johnson5a6cc792019-03-18 09:47:18 -07002179 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002180 pFoundPacket = pPacket;
2181 break;
2182 }
2183 /* check for removal */
2184 if (netbuf ==
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302185 (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002186 /* found it */
2187 HTC_PACKET_REMOVE(&lookupQueue, pPacket);
2188 pFoundPacket = pPacket;
2189 break;
2190 }
2191
2192 }
2193 ITERATE_END;
2194
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002195 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxLookupQueue,
2196 &lookupQueue);
2197 UNLOCK_HTC_TX(target);
Govind Singhc505cdc2017-05-16 12:15:51 +05302198 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002199
2200 return pFoundPacket;
2201}
2202
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002203/**
2204 * htc_tx_completion_handler() - htc tx completion handler
2205 * @Context: pointer to HTC_TARGET structure
2206 * @netbuf: pointer to netbuf for which completion handler is being called
2207 * @EpID: end point Id on which the packet was sent
2208 * @toeplitz_hash_result: toeplitz hash result
2209 *
2210 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
2211 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302212QDF_STATUS htc_tx_completion_handler(void *Context,
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302213 qdf_nbuf_t netbuf, unsigned int EpID,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002214 uint32_t toeplitz_hash_result)
2215{
2216 HTC_TARGET *target = (HTC_TARGET *) Context;
2217 HTC_ENDPOINT *pEndpoint;
2218 HTC_PACKET *pPacket;
2219#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302220 HTC_ENDPOINT_ID eid[DATA_EP_SIZE] = { ENDPOINT_5, ENDPOINT_4,
2221 ENDPOINT_2, ENDPOINT_3 };
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002222 int epidIdx;
Yue Mab16cf302016-03-08 18:30:25 -08002223 uint16_t resourcesThresh[DATA_EP_SIZE]; /* urb resources */
2224 uint16_t resources;
2225 uint16_t resourcesMax;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002226#endif
2227
Houston Hoffman29573d92015-10-20 17:49:44 -07002228 pEndpoint = &target->endpoint[EpID];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002229 target->TX_comp_cnt++;
2230
2231 do {
2232 pPacket = htc_lookup_tx_packet(target, pEndpoint, netbuf);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07002233 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002234 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2235 ("HTC TX lookup failed!\n"));
2236 /* may have already been flushed and freed */
2237 netbuf = NULL;
2238 break;
2239 }
Houston Hoffmanc5141b02015-11-18 02:36:30 -08002240 if (pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_AUTO_PM)
2241 hif_pm_runtime_put(target->hif_dev);
2242
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002243 if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) {
2244 HTC_PACKET *pPacketTemp;
2245 HTC_PACKET_QUEUE *pQueueSave =
2246 (HTC_PACKET_QUEUE *) pPacket->pContext;
2247 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQueueSave,
2248 pPacketTemp) {
Rakesh Pillai13146452017-06-22 12:52:31 +05302249 pPacket->Status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002250 send_packet_completion(target, pPacketTemp);
2251 }
2252 HTC_PACKET_QUEUE_ITERATE_END;
2253 free_htc_bundle_packet(target, pPacket);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002254
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002255 if (hif_get_bus_type(target->hif_dev) ==
2256 QDF_BUS_TYPE_USB) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002257 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint))
2258 htc_try_send(target, pEndpoint, NULL);
2259 }
2260
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302261 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002262 }
2263 /* will be giving this buffer back to upper layers */
2264 netbuf = NULL;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302265 pPacket->Status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002266 send_packet_completion(target, pPacket);
2267
2268 } while (false);
2269
2270 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002271 /* note: when using TX credit flow, the re-checking of queues
2272 * happens when credits flow back from the target. In the non-TX
2273 * credit case, we recheck after the packet completes
2274 */
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05302275 if ((qdf_atomic_read(&pEndpoint->TxProcessCount) == 0) ||
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05302276 (!pEndpoint->async_update)) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05302277 htc_try_send(target, pEndpoint, NULL);
2278 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002279 }
2280
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302281 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002282}
2283
Poddar, Siddarthdf030092016-04-28 11:41:57 +05302284#ifdef WLAN_FEATURE_FASTPATH
Houston Hoffman93481862016-05-05 18:49:59 -07002285/**
2286 * htc_ctrl_msg_cmpl(): checks for tx completion for the endpoint specified
2287 * @HTC_HANDLE : pointer to the htc target context
2288 * @htc_ep_id : end point id
2289 *
2290 * checks HTC tx completion
2291 *
2292 * Return: none
2293 */
2294void htc_ctrl_msg_cmpl(HTC_HANDLE htc_pdev, HTC_ENDPOINT_ID htc_ep_id)
2295{
2296 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_pdev);
2297 HTC_ENDPOINT *pendpoint = &target->endpoint[htc_ep_id];
2298
2299 htc_send_complete_check(pendpoint, 1);
2300}
Pratik Gandhidc82a772018-01-30 18:57:05 +05302301qdf_export_symbol(htc_ctrl_msg_cmpl);
Houston Hoffman93481862016-05-05 18:49:59 -07002302#endif
2303
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002304/* callback when TX resources become available */
Yue Mab16cf302016-03-08 18:30:25 -08002305void htc_tx_resource_avail_handler(void *context, uint8_t pipeID)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002306{
2307 int i;
2308 HTC_TARGET *target = (HTC_TARGET *) context;
2309 HTC_ENDPOINT *pEndpoint = NULL;
2310
2311 for (i = 0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -07002312 pEndpoint = &target->endpoint[i];
Houston Hoffman4f2f4592015-10-20 18:00:29 -07002313 if (pEndpoint->service_id != 0) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002314 if (pEndpoint->UL_PipeID == pipeID)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002315 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002316 }
2317 }
2318
2319 if (i >= ENDPOINT_MAX) {
2320 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2321 ("Invalid pipe indicated for TX resource avail : %d!\n",
2322 pipeID));
2323 return;
2324 }
2325
2326 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002327 ("HIF indicated more resources for pipe:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002328 pipeID));
2329
2330 htc_try_send(target, pEndpoint, NULL);
2331}
2332
Yue Maec9e71c2016-02-26 18:52:20 -08002333#ifdef FEATURE_RUNTIME_PM
Houston Hoffman47e387b2015-10-20 17:04:42 -07002334/**
2335 * htc_kick_queues(): resumes tx transactions of suspended endpoints
2336 * @context: pointer to the htc target context
2337 *
Jeff Johnson4b253f02018-05-12 11:34:43 -07002338 * Iterates through the enpoints and provides a context to empty queues
Houston Hoffman47e387b2015-10-20 17:04:42 -07002339 * int the hif layer when they are stalled due to runtime suspend.
2340 *
2341 * Return: none
2342 */
2343void htc_kick_queues(void *context)
2344{
2345 int i;
2346 HTC_TARGET *target = (HTC_TARGET *)context;
2347 HTC_ENDPOINT *endpoint = NULL;
2348
2349 for (i = 0; i < ENDPOINT_MAX; i++) {
2350 endpoint = &target->endpoint[i];
2351
2352 if (endpoint->service_id == 0)
2353 continue;
2354
2355 if (endpoint->EpCallBacks.ep_resume_tx_queue)
2356 endpoint->EpCallBacks.ep_resume_tx_queue(
2357 endpoint->EpCallBacks.pContext);
2358
2359 htc_try_send(target, endpoint, NULL);
2360 }
Yue Ma9c6f84d2017-02-17 10:45:55 -08002361
2362 hif_fastpath_resume(target->hif_dev);
Houston Hoffman47e387b2015-10-20 17:04:42 -07002363}
Yue Maec9e71c2016-02-26 18:52:20 -08002364#endif
Houston Hoffman47e387b2015-10-20 17:04:42 -07002365
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002366/* flush endpoint TX queue */
2367void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint,
2368 HTC_TX_TAG Tag)
2369{
2370 HTC_PACKET *pPacket;
2371
2372 LOCK_HTC_TX(target);
2373 while (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) {
2374 pPacket = htc_packet_dequeue(&pEndpoint->TxQueue);
2375
2376 if (pPacket) {
2377 /* let the sender know the packet was not delivered */
Rakesh Pillai13146452017-06-22 12:52:31 +05302378 pPacket->Status = QDF_STATUS_E_CANCELED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002379 send_packet_completion(target, pPacket);
2380 }
2381 }
2382 UNLOCK_HTC_TX(target);
2383}
2384
Alok Kumar9bd81522018-05-30 13:07:13 +05302385/* flush pending entries in endpoint TX Lookup queue */
2386void htc_flush_endpoint_txlookupQ(HTC_TARGET *target,
Zhang Qianedaa3872018-07-04 20:02:53 +08002387 HTC_ENDPOINT_ID endpoint_id,
2388 bool call_ep_callback)
Alok Kumar9bd81522018-05-30 13:07:13 +05302389{
2390 HTC_PACKET *packet;
2391 HTC_ENDPOINT *endpoint;
2392
2393 endpoint = &target->endpoint[endpoint_id];
2394
2395 if (!endpoint && endpoint->service_id == 0)
2396 return;
2397
Debasis Das5e2539c2018-11-16 14:43:26 +05302398 LOCK_HTC_TX(target);
Alok Kumar9bd81522018-05-30 13:07:13 +05302399 while (HTC_PACKET_QUEUE_DEPTH(&endpoint->TxLookupQueue)) {
2400 packet = htc_packet_dequeue(&endpoint->TxLookupQueue);
2401
2402 if (packet) {
Zhang Qianedaa3872018-07-04 20:02:53 +08002403 if (call_ep_callback == true) {
2404 packet->Status = QDF_STATUS_E_CANCELED;
2405 send_packet_completion(target, packet);
2406 } else {
2407 qdf_mem_free(packet);
2408 }
Alok Kumar9bd81522018-05-30 13:07:13 +05302409 }
2410 }
Debasis Das5e2539c2018-11-16 14:43:26 +05302411 UNLOCK_HTC_TX(target);
Alok Kumar9bd81522018-05-30 13:07:13 +05302412}
2413
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002414/* HTC API to flush an endpoint's TX queue*/
2415void htc_flush_endpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint,
2416 HTC_TX_TAG Tag)
2417{
2418 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Houston Hoffman29573d92015-10-20 17:49:44 -07002419 HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002420
Houston Hoffman4f2f4592015-10-20 18:00:29 -07002421 if (pEndpoint->service_id == 0) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002422 AR_DEBUG_ASSERT(false);
2423 /* not in use.. */
2424 return;
2425 }
2426
2427 htc_flush_endpoint_tx(target, pEndpoint, Tag);
2428}
2429
2430/* HTC API to indicate activity to the credit distribution function */
2431void htc_indicate_activity_change(HTC_HANDLE HTCHandle,
Yue Mab16cf302016-03-08 18:30:25 -08002432 HTC_ENDPOINT_ID Endpoint, bool Active)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002433{
2434 /* TODO */
2435}
2436
Yue Mab16cf302016-03-08 18:30:25 -08002437bool htc_is_endpoint_active(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002438{
2439 return true;
2440}
2441
gbianb417db22016-09-30 17:01:07 +08002442void htc_set_nodrop_pkt(HTC_HANDLE HTCHandle, A_BOOL isNodropPkt)
2443{
2444 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002445
gbianb417db22016-09-30 17:01:07 +08002446 target->is_nodrop_pkt = isNodropPkt;
2447}
2448
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05302449void htc_enable_hdr_length_check(HTC_HANDLE htc_hdl, bool htc_hdr_length_check)
2450{
2451 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl);
2452
2453 target->htc_hdr_length_check = htc_hdr_length_check;
2454}
2455
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002456/**
2457 * htc_process_credit_rpt() - process credit report, call distribution function
2458 * @target: pointer to HTC_TARGET
2459 * @pRpt: pointer to HTC_CREDIT_REPORT
2460 * @NumEntries: number of entries in credit report
2461 * @FromEndpoint: endpoint for which credit report is received
2462 *
2463 * Return: A_OK for success or an appropriate A_STATUS error
2464 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002465void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt,
2466 int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
2467{
2468 int i;
2469 HTC_ENDPOINT *pEndpoint;
2470 int totalCredits = 0;
Yue Mab16cf302016-03-08 18:30:25 -08002471 uint8_t rpt_credits, rpt_ep_id;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002472
2473 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002474 ("+htc_process_credit_rpt, Credit Report Entries:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002475 NumEntries));
2476
2477 /* lock out TX while we update credits */
2478 LOCK_HTC_TX(target);
2479
2480 for (i = 0; i < NumEntries; i++, pRpt++) {
2481
2482 rpt_ep_id = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, ENDPOINTID);
2483
2484 if (rpt_ep_id >= ENDPOINT_MAX) {
2485 AR_DEBUG_ASSERT(false);
2486 break;
2487 }
2488
2489 rpt_credits = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, CREDITS);
2490
Houston Hoffman29573d92015-10-20 17:49:44 -07002491 pEndpoint = &target->endpoint[rpt_ep_id];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002492#if DEBUG_CREDIT
2493 if (ep_debug_mask & (1 << pEndpoint->Id)) {
2494 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2495 (" <HTC> Increase EP%d %d + %d = %d credits\n",
2496 rpt_ep_id, pEndpoint->TxCredits,
2497 rpt_credits,
2498 pEndpoint->TxCredits + rpt_credits));
2499 }
2500#endif
2501
2502#ifdef HTC_EP_STAT_PROFILING
2503
2504 INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
2505 INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, rpt_credits);
2506
2507 if (FromEndpoint == rpt_ep_id) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002508 /* this credit report arrived on the same endpoint
2509 * indicating it arrived in an RX packet
2510 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002511 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx,
2512 rpt_credits);
2513 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
2514 } else if (FromEndpoint == ENDPOINT_0) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002515 /* this credit arrived on endpoint 0 as a NULL msg */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002516 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0,
2517 rpt_credits);
2518 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
2519 } else {
2520 /* arrived on another endpoint */
2521 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther,
2522 rpt_credits);
2523 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
2524 }
2525
2526#endif
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002527
Houston Hoffman4f2f4592015-10-20 18:00:29 -07002528 if (pEndpoint->service_id == WMI_CONTROL_SVC) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002529 htc_credit_record(HTC_PROCESS_CREDIT_REPORT,
Dustin Brownf74576c2018-03-12 14:22:51 -07002530 pEndpoint->TxCredits + rpt_credits,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002531 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->
Rachit Kankane1bc11492018-01-24 18:48:17 +05302532 TxQueue));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002533 }
Dustin Brownf74576c2018-03-12 14:22:51 -07002534
2535 pEndpoint->TxCredits += rpt_credits;
2536
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002537 if (pEndpoint->TxCredits
2538 && HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) {
2539 UNLOCK_HTC_TX(target);
2540#ifdef ATH_11AC_TXCOMPACT
2541 htc_try_send(target, pEndpoint, NULL);
2542#else
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002543 if (pEndpoint->service_id == HTT_DATA_MSG_SVC)
Himanshu Batra032d3522019-07-10 12:36:06 +05302544 htc_send_data_pkt((HTC_HANDLE)target, NULL, 0);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002545 else
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002546 htc_try_send(target, pEndpoint, NULL);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002547#endif
2548 LOCK_HTC_TX(target);
2549 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002550 totalCredits += rpt_credits;
2551 }
2552
2553 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002554 (" Report indicated %d credits to distribute\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002555 totalCredits));
2556
2557 UNLOCK_HTC_TX(target);
2558
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002559 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_process_credit_rpt\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002560}
2561
2562/* function to fetch stats from htc layer*/
2563struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE HTCHandle)
2564{
2565 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
2566
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302567 return &(target->htc_pkt_stats);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002568}