blob: 45363cc50a5bf4ed41b37241db60861f03d90860 [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
Rakesh Pillai48633522019-11-15 15:07:53 +0530128 /*
129 * In case of SSR, we cannot call the upper layer completion
130 * callbacks, hence just free the nbuf and HTC packet here.
131 */
132 if (hif_get_target_status(target->hif_dev)) {
133 htc_free_control_tx_packet(target, pPacket);
134 return;
135 }
136
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800137 /* do completion */
Yun Park88e0b952017-10-11 23:08:34 -0700138 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
139 ("HTC calling ep %d send complete callback on packet %pK\n",
140 pEndpoint->Id, pPacket));
141
142 EpTxComplete = pEndpoint->EpCallBacks.EpTxComplete;
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700143 if (EpTxComplete)
Yun Park88e0b952017-10-11 23:08:34 -0700144 EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket);
145 else
146 qdf_nbuf_free(pPacket->pPktContext);
147
148
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800149}
150
Yue Ma4986b252019-07-23 15:57:48 -0700151#ifdef FEATURE_RUNTIME_PM
152/**
153 * log_packet_info() - Log HTC packet information
154 *
155 * @target: handle of HTC context
156 * @pPacket: handle of HTC packet
157 *
158 * Return: None
159 */
160static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket)
161{
162 HTC_ENDPOINT *pEndpoint = &target->endpoint[pPacket->Endpoint];
163 HTC_EP_LOG_PKT ep_log_pkt;
164 qdf_nbuf_t netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
165
166 ep_log_pkt = pEndpoint->EpCallBacks.ep_log_pkt;
167 if (ep_log_pkt) {
168 qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR));
169 ep_log_pkt(pEndpoint->EpCallBacks.pContext, pPacket);
170 qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR));
171 }
172}
173#else
174static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket)
175{
176}
177#endif
178
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800179void htc_send_complete_check_cleanup(void *context)
180{
181 HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *) context;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700182
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800183 htc_send_complete_check(pEndpoint, 1);
184}
185
186HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target)
187{
188 HTC_PACKET *pPacket;
189 HTC_PACKET_QUEUE *pQueueSave;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530190 qdf_nbuf_t netbuf;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700191
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800192 LOCK_HTC_TX(target);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700193 if (!target->pBundleFreeList) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800194 UNLOCK_HTC_TX(target);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530195 netbuf = qdf_nbuf_alloc(NULL,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800196 target->MaxMsgsPerHTCBundle *
197 target->TargetCreditSize, 0, 4, false);
198 AR_DEBUG_ASSERT(netbuf);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700199 if (!netbuf)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800200 return NULL;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530201 pPacket = qdf_mem_malloc(sizeof(HTC_PACKET));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800202 AR_DEBUG_ASSERT(pPacket);
203 if (!pPacket) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530204 qdf_nbuf_free(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800205 return NULL;
206 }
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530207 pQueueSave = qdf_mem_malloc(sizeof(HTC_PACKET_QUEUE));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800208 AR_DEBUG_ASSERT(pQueueSave);
209 if (!pQueueSave) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530210 qdf_nbuf_free(netbuf);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530211 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800212 return NULL;
213 }
214 INIT_HTC_PACKET_QUEUE(pQueueSave);
215 pPacket->pContext = pQueueSave;
216 SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530217 pPacket->pBuffer = qdf_nbuf_data(netbuf);
218 pPacket->BufferLength = qdf_nbuf_len(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800219
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700220 /* store the original head room so that we can restore this
221 * when we "free" the packet.
222 * free packet puts the packet back on the free list
223 */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530224 pPacket->netbufOrigHeadRoom = qdf_nbuf_headroom(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800225 return pPacket;
226 }
227 /* already done malloc - restore from free list */
228 pPacket = target->pBundleFreeList;
229 AR_DEBUG_ASSERT(pPacket);
230 if (!pPacket) {
231 UNLOCK_HTC_TX(target);
232 return NULL;
233 }
234 target->pBundleFreeList = (HTC_PACKET *) pPacket->ListLink.pNext;
235 UNLOCK_HTC_TX(target);
236 pPacket->ListLink.pNext = NULL;
237
238 return pPacket;
239}
240
241void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
242{
Yue Mab16cf302016-03-08 18:30:25 -0800243 uint32_t curentHeadRoom;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530244 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800245 HTC_PACKET_QUEUE *pQueueSave;
246
247 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
248 AR_DEBUG_ASSERT(netbuf);
249 if (!netbuf) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700250 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
251 ("\n%s: Invalid netbuf in HTC Packet\n",
252 __func__));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800253 return;
254 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700255 /* HIF adds data to the headroom section of the nbuf, restore thei
256 * original size. If this is not done, headroom keeps shrinking with
257 * every HIF send and eventually HIF ends up doing another malloc big
258 * enough to store the data + its header
259 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800260
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530261 curentHeadRoom = qdf_nbuf_headroom(netbuf);
262 qdf_nbuf_pull_head(netbuf,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800263 pPacket->netbufOrigHeadRoom - curentHeadRoom);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530264 qdf_nbuf_trim_tail(netbuf, qdf_nbuf_len(netbuf));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800265
266 /* restore the pBuffer pointer. HIF changes this */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530267 pPacket->pBuffer = qdf_nbuf_data(netbuf);
268 pPacket->BufferLength = qdf_nbuf_len(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800269
270 /* restore queue */
271 pQueueSave = (HTC_PACKET_QUEUE *) pPacket->pContext;
jitiphilfcc24882018-05-11 16:14:38 +0530272 if (qdf_unlikely(!pQueueSave)) {
273 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
274 ("\n%s: Invalid pQueueSave in HTC Packet\n",
275 __func__));
276 AR_DEBUG_ASSERT(pQueueSave);
277 } else
278 INIT_HTC_PACKET_QUEUE(pQueueSave);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800279
280 LOCK_HTC_TX(target);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700281 if (!target->pBundleFreeList) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800282 target->pBundleFreeList = pPacket;
283 pPacket->ListLink.pNext = NULL;
284 } else {
285 pPacket->ListLink.pNext = (DL_LIST *) target->pBundleFreeList;
286 target->pBundleFreeList = pPacket;
287 }
288 UNLOCK_HTC_TX(target);
289}
290
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530291#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
292
293/**
294 * htc_send_update_tx_bundle_stats() - update tx bundle stats depends
295 * on max bundle size
296 * @target: hif context
297 * @data_len: tx data len
298 * @TxCreditSize: endpoint tx credit size
299 *
300 * Return: None
301 */
302static inline void
303htc_send_update_tx_bundle_stats(HTC_TARGET *target,
304 qdf_size_t data_len,
305 int TxCreditSize)
306{
Nirav Shaheb268312019-11-11 10:55:15 +0530307 int index = ((data_len + TxCreditSize - 1) / TxCreditSize) - 1;
308
309 if (index < HTC_MAX_MSG_PER_BUNDLE_TX)
310 target->tx_bundle_stats[index]++;
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530311}
312
313/**
314 * htc_issue_tx_bundle_stats_inc() - increment in tx bundle stats
315 * on max bundle size
316 * @target: hif context
317 *
318 * Return: None
319 */
320static inline void
321htc_issue_tx_bundle_stats_inc(HTC_TARGET *target)
322{
323 target->tx_bundle_stats[0]++;
324}
325#else
326
327static inline void
328htc_send_update_tx_bundle_stats(HTC_TARGET *target,
329 qdf_size_t data_len,
330 int TxCreditSize)
331{
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530332}
333
334static inline void
335htc_issue_tx_bundle_stats_inc(HTC_TARGET *target)
336{
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530337}
338#endif
339
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800340#if defined(HIF_USB) || defined(HIF_SDIO)
341#ifdef ENABLE_BUNDLE_TX
Rakesh Pillai13146452017-06-22 12:52:31 +0530342static QDF_STATUS htc_send_bundled_netbuf(HTC_TARGET *target,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800343 HTC_ENDPOINT *pEndpoint,
344 unsigned char *pBundleBuffer,
345 HTC_PACKET *pPacketTx)
346{
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530347 qdf_size_t data_len;
Rakesh Pillai13146452017-06-22 12:52:31 +0530348 QDF_STATUS status;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530349 qdf_nbuf_t bundleBuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800350 uint32_t data_attr = 0;
351
352 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530353 data_len = pBundleBuffer - qdf_nbuf_data(bundleBuf);
354 qdf_nbuf_put_tail(bundleBuf, data_len);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800355 SET_HTC_PACKET_INFO_TX(pPacketTx,
356 target,
357 pBundleBuffer,
358 data_len,
359 pEndpoint->Id, HTC_TX_PACKET_TAG_BUNDLED);
360 LOCK_HTC_TX(target);
361 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacketTx);
tfyu052b32a2017-09-20 18:48:33 +0800362 pEndpoint->ul_outstanding_cnt++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800363 UNLOCK_HTC_TX(target);
364#if DEBUG_BUNDLE
Aditya Sathish648ce112018-07-02 16:41:39 +0530365 qdf_print(" Send bundle EP%d buffer size:0x%x, total:0x%x, count:%d.",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800366 pEndpoint->Id,
367 pEndpoint->TxCreditSize,
368 data_len, data_len / pEndpoint->TxCreditSize);
369#endif
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530370
371 htc_send_update_tx_bundle_stats(target, data_len,
372 pEndpoint->TxCreditSize);
373
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800374 status = hif_send_head(target->hif_dev,
375 pEndpoint->UL_PipeID,
Poddar, Siddarth416b7062016-04-29 11:02:13 +0530376 pEndpoint->Id, data_len,
377 bundleBuf, data_attr);
Nirav Shah03c409d2019-06-10 23:23:11 +0530378 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
379 HTC_PACKET_QUEUE requeue;
380
381 qdf_print("hif_send_head failed(len=%zu).", data_len);
382 INIT_HTC_PACKET_QUEUE(&requeue);
383 LOCK_HTC_TX(target);
384 pEndpoint->ul_outstanding_cnt--;
385 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacketTx);
386
387 if (pPacketTx->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) {
388 HTC_PACKET *temp_packet;
389 HTC_PACKET_QUEUE *packet_queue =
390 (HTC_PACKET_QUEUE *)pPacketTx->pContext;
391
392 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(packet_queue,
393 temp_packet) {
394 HTC_PACKET_ENQUEUE(&requeue, temp_packet);
395 } HTC_PACKET_QUEUE_ITERATE_END;
396
397 UNLOCK_HTC_TX(target);
398 free_htc_bundle_packet(target, pPacketTx);
399 LOCK_HTC_TX(target);
400
401 } else {
402 HTC_PACKET_ENQUEUE(&requeue, pPacketTx);
403 }
404
405 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
406 &requeue);
407 UNLOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800408 }
409 return status;
410}
411
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530412#ifdef QCA_TX_PADDING_CREDIT_SUPPORT
413#define SDIO_BLOCK_SIZE 512
414static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep)
415{
416 int ret = 0;
417
418 if (!ep || !ep->EpCallBacks.pContext ||
419 !ep->EpCallBacks.ep_padding_credit_update)
420 return 1;
421
422 ret = ep->EpCallBacks.ep_padding_credit_update(ep->EpCallBacks.pContext,
423 0);
424
425 if (ret < 2)
426 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s ret %d\n", __func__, ret));
427
428 return ret;
429}
430
431static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
432 HTC_PACKET *p_last_htc_pkt,
433 unsigned char *p_last_pkt_bundle_buffer,
434 unsigned char **p_bundle_buffer,
435 int tot_data_len)
436{
437 bool extra_tx_credit = FALSE;
438 HTC_FRAME_HDR *p_htc_hdr;
439 int first_buf_bundled_len = 0, last_buf_len = 0;
440 int sdio_pad = 0, free_space = 0;
441 int (*update_ep_padding_credit)(void *, int);
442
443 update_ep_padding_credit = ep->EpCallBacks.ep_padding_credit_update;
444
445 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
446 ("%s Tot data_len = %d\n", __func__, tot_data_len));
447
448 if (!p_last_htc_pkt)
449 return extra_tx_credit;
450
451 last_buf_len = (p_last_htc_pkt->ActualLength + HTC_HDR_LENGTH);
452 if (tot_data_len != last_buf_len) {
453 first_buf_bundled_len = tot_data_len - ep->TxCreditSize;
454 free_space = tot_data_len -
455 (first_buf_bundled_len + last_buf_len);
456 } else {
457 free_space = ep->TxCreditSize - tot_data_len;
458 }
459
460 sdio_pad = SDIO_BLOCK_SIZE - ((first_buf_bundled_len + last_buf_len) %
461 SDIO_BLOCK_SIZE);
462
463 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
464 ("%s first_buf_bundled_len = %d last_buf_len = %d\n",
465 __func__, first_buf_bundled_len, last_buf_len));
466
467 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
468 ("%s sdio_pad = %d free_space = %d\n", __func__,
469 sdio_pad, free_space));
470
471 if (sdio_pad <= free_space) {
472 if (p_bundle_buffer && *p_bundle_buffer) {
473 /* Align Tx bundled buf to avoid a extra Padding buf */
474 *p_bundle_buffer -= (free_space - sdio_pad);
475 }
476 } else {
477 /* Extra Padding Buffer needed, consume extra tx credit */
478 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
479 ("%s Used a Tx credit for Padding Buffer\n",
480 __func__));
481 p_htc_hdr = (HTC_FRAME_HDR *)(p_last_pkt_bundle_buffer);
482 p_htc_hdr->Flags |= HTC_FLAGS_PADDING_CHECK;
483 extra_tx_credit = TRUE;
484 if (ep->EpCallBacks.ep_padding_credit_update) {
485 /* Decrement 1 credit at host,
486 * due to extra tx credit consumed by padding buffer
487 */
488 update_ep_padding_credit(ep->EpCallBacks.pContext, -1);
489 }
490 }
491 return extra_tx_credit;
492}
493#else
494static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep)
495{
496 return 1;
497}
498
499static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
500 HTC_PACKET *p_last_htc_pkt,
501 unsigned char *p_last_pkt_bundle_buffer,
502 unsigned char **p_bundle_buffer,
503 int tot_data_len)
504{
505 return FALSE;
506}
507#endif
508
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700509/**
510 * htc_issue_packets_bundle() - HTC function to send bundle packets from a queue
511 * @target: HTC target on which packets need to be sent
512 * @pEndpoint: logical endpoint on which packets needs to be sent
513 * @pPktQueue: HTC packet queue containing the list of packets to be sent
514 *
515 * Return: void
516 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800517static void htc_issue_packets_bundle(HTC_TARGET *target,
518 HTC_ENDPOINT *pEndpoint,
519 HTC_PACKET_QUEUE *pPktQueue)
520{
521 int i, frag_count, nbytes;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530522 qdf_nbuf_t netbuf, bundleBuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800523 unsigned char *pBundleBuffer = NULL;
524 HTC_PACKET *pPacket = NULL, *pPacketTx = NULL;
525 HTC_FRAME_HDR *pHtcHdr;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700526 int last_credit_pad = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800527 int creditPad, creditRemainder, transferLength, bundlesSpaceRemaining =
528 0;
529 HTC_PACKET_QUEUE *pQueueSave = NULL;
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530530 HTC_PACKET *p_last_htc_pkt = NULL;
531 unsigned char *p_last_pkt_bundle_buffer = NULL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800532
533 bundlesSpaceRemaining =
534 target->MaxMsgsPerHTCBundle * pEndpoint->TxCreditSize;
535 pPacketTx = allocate_htc_bundle_packet(target);
536 if (!pPacketTx) {
537 /* good time to panic */
538 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700539 ("allocate_htc_bundle_packet failed\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800540 AR_DEBUG_ASSERT(false);
541 return;
542 }
543 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530544 pBundleBuffer = qdf_nbuf_data(bundleBuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800545 pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext;
546 while (1) {
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530547 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
548 if (htc_tx_pad_credit_avail(pEndpoint) < 1)
549 break;
550 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800551 pPacket = htc_packet_dequeue(pPktQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700552 if (!pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800553 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800554 creditPad = 0;
555 transferLength = pPacket->ActualLength + HTC_HDR_LENGTH;
556 creditRemainder = transferLength % pEndpoint->TxCreditSize;
557 if (creditRemainder != 0) {
558 if (transferLength < pEndpoint->TxCreditSize) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700559 creditPad = pEndpoint->TxCreditSize -
560 transferLength;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800561 } else {
562 creditPad = creditRemainder;
563 }
564 transferLength += creditPad;
565 }
566
567 if (bundlesSpaceRemaining < transferLength) {
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530568 htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt,
569 p_last_pkt_bundle_buffer,
570 &pBundleBuffer,
571 pBundleBuffer -
572 qdf_nbuf_data(bundleBuf));
573
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800574 /* send out previous buffer */
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700575 htc_send_bundled_netbuf(target, pEndpoint,
576 pBundleBuffer - last_credit_pad,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800577 pPacketTx);
tfyu60c2c982017-06-09 15:50:03 +0800578 /* One packet has been dequeued from sending queue when enter
579 * this loop, so need to add 1 back for this checking.
580 */
581 if ((HTC_PACKET_QUEUE_DEPTH(pPktQueue) + 1) <
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800582 HTC_MIN_MSG_PER_BUNDLE) {
tfyu60c2c982017-06-09 15:50:03 +0800583 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800584 return;
585 }
586 bundlesSpaceRemaining =
587 target->MaxMsgsPerHTCBundle *
588 pEndpoint->TxCreditSize;
589 pPacketTx = allocate_htc_bundle_packet(target);
590 if (!pPacketTx) {
tfyu60c2c982017-06-09 15:50:03 +0800591 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800592 /* good time to panic */
593 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700594 ("allocate_htc_bundle_packet failed\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800595 AR_DEBUG_ASSERT(false);
596 return;
597 }
598 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530599 pBundleBuffer = qdf_nbuf_data(bundleBuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800600 pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext;
601 }
602
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530603 p_last_htc_pkt = pPacket;
604 p_last_pkt_bundle_buffer = pBundleBuffer;
605
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800606 bundlesSpaceRemaining -= transferLength;
607 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700608
609 if (hif_get_bus_type(target->hif_dev) != QDF_BUS_TYPE_USB) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700610 pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(
611 netbuf, 0);
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700612 HTC_WRITE32(pHtcHdr,
613 SM(pPacket->ActualLength,
614 HTC_FRAME_HDR_PAYLOADLEN) |
615 SM(pPacket->PktInfo.AsTx.SendFlags |
616 HTC_FLAGS_SEND_BUNDLE,
617 HTC_FRAME_HDR_FLAGS) |
618 SM(pPacket->Endpoint,
619 HTC_FRAME_HDR_ENDPOINTID));
620 HTC_WRITE32((uint32_t *) pHtcHdr + 1,
621 SM(pPacket->PktInfo.AsTx.SeqNo,
622 HTC_FRAME_HDR_CONTROLBYTES1) | SM(creditPad,
623 HTC_FRAME_HDR_RESERVED));
624 pHtcHdr->reserved = creditPad;
625 }
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530626 frag_count = qdf_nbuf_get_num_frags(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800627 nbytes = pPacket->ActualLength + HTC_HDR_LENGTH;
628 for (i = 0; i < frag_count && nbytes > 0; i++) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530629 int frag_len = qdf_nbuf_get_frag_len(netbuf, i);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800630 unsigned char *frag_addr =
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530631 qdf_nbuf_get_frag_vaddr(netbuf, i);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700632 if (frag_len > nbytes)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800633 frag_len = nbytes;
Yue Mab16cf302016-03-08 18:30:25 -0800634 qdf_mem_copy(pBundleBuffer, frag_addr, frag_len);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800635 nbytes -= frag_len;
636 pBundleBuffer += frag_len;
637 }
638 HTC_PACKET_ENQUEUE(pQueueSave, pPacket);
639 pBundleBuffer += creditPad;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700640
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700641 /* last one can't be packed. */
642 if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700643 last_credit_pad = creditPad;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800644 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700645 /* send out remaining buffer */
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530646 if (pBundleBuffer != qdf_nbuf_data(bundleBuf)) {
647 htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt,
648 p_last_pkt_bundle_buffer,
649 &pBundleBuffer,
650 pBundleBuffer -
651 qdf_nbuf_data(bundleBuf));
652
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700653 htc_send_bundled_netbuf(target, pEndpoint,
654 pBundleBuffer - last_credit_pad,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800655 pPacketTx);
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530656 } else {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800657 free_htc_bundle_packet(target, pPacketTx);
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530658 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800659}
660#endif /* ENABLE_BUNDLE_TX */
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700661#else
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530662static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep)
663{
664 return 1;
665}
666
667bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
668 HTC_PACKET *p_last_htc_pkt,
669 unsigned char *p_last_pkt_bundle_buffer,
670 unsigned char **p_bundle_buffer,
671 int tot_data_len);
672bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
673 HTC_PACKET *p_last_htc_pkt,
674 unsigned char *p_last_pkt_bundle_buffer,
675 unsigned char **p_bundle_buffer,
676 int tot_data_len)
677{
678 return FALSE;
679}
680
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700681static void htc_issue_packets_bundle(HTC_TARGET *target,
682 HTC_ENDPOINT *pEndpoint,
683 HTC_PACKET_QUEUE *pPktQueue)
684{
685}
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800686#endif
687
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700688/**
689 * htc_issue_packets() - HTC function to send packets from a queue
690 * @target: HTC target on which packets need to be sent
691 * @pEndpoint: logical endpoint on which packets needs to be sent
692 * @pPktQueue: HTC packet queue containing the list of packets to be sent
693 *
694 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
695 */
Rakesh Pillai13146452017-06-22 12:52:31 +0530696static QDF_STATUS htc_issue_packets(HTC_TARGET *target,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800697 HTC_ENDPOINT *pEndpoint,
698 HTC_PACKET_QUEUE *pPktQueue)
699{
Rakesh Pillai13146452017-06-22 12:52:31 +0530700 QDF_STATUS status = QDF_STATUS_SUCCESS;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530701 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800702 HTC_PACKET *pPacket = NULL;
703 uint16_t payloadLen;
704 HTC_FRAME_HDR *pHtcHdr;
705 uint32_t data_attr = 0;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700706 enum qdf_bus_type bus_type;
Himanshu Agarwalfa594d92017-04-04 12:36:33 +0530707 QDF_STATUS ret;
wadesong4b3f37d2018-01-25 16:08:05 +0800708 bool rt_put = false;
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530709 bool used_extra_tx_credit = false;
710 uint8_t *buf = NULL;
711 int (*update_ep_padding_credit)(void *, int);
712 void *ctx = NULL;
713
714 update_ep_padding_credit =
715 pEndpoint->EpCallBacks.ep_padding_credit_update;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700716
717 bus_type = hif_get_bus_type(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800718
719 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700720 ("+htc_issue_packets: Queue: %pK, Pkts %d\n", pPktQueue,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800721 HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
722 while (true) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700723 if (HTC_TX_BUNDLE_ENABLED(target) &&
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800724 HTC_PACKET_QUEUE_DEPTH(pPktQueue) >=
725 HTC_MIN_MSG_PER_BUNDLE) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700726 switch (bus_type) {
727 case QDF_BUS_TYPE_SDIO:
728 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint))
729 break;
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530730 if (update_ep_padding_credit) {
731 if (htc_tx_pad_credit_avail
732 (pEndpoint) < 1)
733 break;
734 }
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700735 case QDF_BUS_TYPE_USB:
736 htc_issue_packets_bundle(target,
737 pEndpoint,
738 pPktQueue);
739 break;
740 default:
741 break;
742 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800743 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700744 /* if not bundling or there was a packet that could not be
745 * placed in a bundle, and send it by normal way
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800746 */
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530747 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
748 if (htc_tx_pad_credit_avail(pEndpoint) < 1) {
749 status = QDF_STATUS_E_FAILURE;
750 break;
751 }
752 }
753
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800754 pPacket = htc_packet_dequeue(pPktQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700755 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800756 /* local queue is fully drained */
757 break;
758 }
759
760 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
761 AR_DEBUG_ASSERT(netbuf);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700762 /* Non-credit enabled endpoints have been mapped and setup by
763 * now, so no need to revisit the HTC headers
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800764 */
765 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
766
767 payloadLen = pPacket->ActualLength;
768 /* setup HTC frame header */
769
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530770 pHtcHdr = (HTC_FRAME_HDR *)
771 qdf_nbuf_get_frag_vaddr(netbuf, 0);
jitiphil4a8f66f2018-05-31 13:15:20 +0530772 if (qdf_unlikely(!pHtcHdr)) {
773 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
774 ("%s Invalid pHtcHdr\n",
775 __func__));
776 AR_DEBUG_ASSERT(pHtcHdr);
777 status = QDF_STATUS_E_FAILURE;
778 break;
779 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800780
781 HTC_WRITE32(pHtcHdr,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700782 SM(payloadLen,
783 HTC_FRAME_HDR_PAYLOADLEN) |
784 SM(pPacket->PktInfo.AsTx.SendFlags,
785 HTC_FRAME_HDR_FLAGS) |
786 SM(pPacket->Endpoint,
787 HTC_FRAME_HDR_ENDPOINTID));
Yue Mab16cf302016-03-08 18:30:25 -0800788 HTC_WRITE32(((uint32_t *) pHtcHdr) + 1,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800789 SM(pPacket->PktInfo.AsTx.SeqNo,
790 HTC_FRAME_HDR_CONTROLBYTES1));
791
792 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700793 * Now that the HTC frame header has been added, the
794 * netbuf can be mapped. This only applies to non-data
795 * frames, since data frames were already mapped as they
Dustin Brownbc9718f2017-12-11 12:15:27 -0800796 * entered into the driver.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800797 */
Dustin Brownbc9718f2017-12-11 12:15:27 -0800798 pPacket->PktInfo.AsTx.Flags |=
799 HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
800
801 ret = qdf_nbuf_map(target->osdev,
802 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
803 QDF_DMA_TO_DEVICE);
804 if (ret != QDF_STATUS_SUCCESS) {
805 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
806 ("%s nbuf Map Fail Endpnt %pK\n",
807 __func__, pEndpoint));
808 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
809 status = QDF_STATUS_E_FAILURE;
810 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800811 }
812 }
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530813
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530814 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530815 LOCK_HTC_TX(target);
816 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800817 /* store in look up queue to match completions */
818 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket);
819 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
820 pEndpoint->ul_outstanding_cnt++;
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530821 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530822 UNLOCK_HTC_TX(target);
823 hif_send_complete_check(target->hif_dev,
824 pEndpoint->UL_PipeID, false);
825 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800826
Himanshu Agarwal974d0a52017-03-08 21:13:51 +0530827 htc_packet_set_magic_cookie(pPacket, HTC_PACKET_MAGIC_COOKIE);
wadesong4b3f37d2018-01-25 16:08:05 +0800828 /*
829 * For HTT messages without a response from fw,
830 * do the runtime put here.
831 * otherwise runtime put will be done when the fw response comes
832 */
833 if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_RUNTIME_PUT)
834 rt_put = true;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800835#if DEBUG_BUNDLE
Aditya Sathish648ce112018-07-02 16:41:39 +0530836 qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800837 pEndpoint->Id,
838 pEndpoint->TxCreditSize,
839 HTC_HDR_LENGTH + pPacket->ActualLength);
840#endif
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530841 buf = (uint8_t *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
842 used_extra_tx_credit =
843 htc_handle_extra_tx_credit(pEndpoint, pPacket, buf,
844 NULL, pPacket->ActualLength +
845 HTC_HDR_LENGTH);
846
wadesong4b3f37d2018-01-25 16:08:05 +0800847 status = hif_send_head(target->hif_dev,
848 pEndpoint->UL_PipeID, pEndpoint->Id,
849 HTC_HDR_LENGTH + pPacket->ActualLength,
850 netbuf, data_attr);
851
Visweswara Tanuku957b63a2019-06-11 10:30:59 +0530852 if (status != QDF_STATUS_SUCCESS) {
853 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
854 if (used_extra_tx_credit) {
855 ctx = pEndpoint->EpCallBacks.pContext;
856 update_ep_padding_credit(ctx, 1);
857 }
858 }
859 }
860
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530861 htc_issue_tx_bundle_stats_inc(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800862
863 target->ce_send_cnt++;
864
Rakesh Pillai13146452017-06-22 12:52:31 +0530865 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
866 if (status != QDF_STATUS_E_RESOURCES) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700867 /* TODO : if more than 1 endpoint maps to the
868 * same PipeID it is possible to run out of
869 * resources in the HIF layer. Don't emit the
870 * error
871 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800872 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700873 ("hif_send Failed status:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800874 status));
875 }
Dustin Brown942f9392018-06-25 14:34:45 -0700876
877 /* only unmap if we mapped in this function */
Nirav Shah0811d822019-04-13 22:43:29 +0530878 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
Dustin Brown942f9392018-06-25 14:34:45 -0700879 qdf_nbuf_unmap(target->osdev,
880 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
881 QDF_DMA_TO_DEVICE);
Nirav Shah0811d822019-04-13 22:43:29 +0530882 pPacket->PktInfo.AsTx.Flags &=
883 ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
884 }
Dustin Brown942f9392018-06-25 14:34:45 -0700885
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530886 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530887 LOCK_HTC_TX(target);
888 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800889 target->ce_send_cnt--;
890 pEndpoint->ul_outstanding_cnt--;
891 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket);
Himanshu Agarwal974d0a52017-03-08 21:13:51 +0530892 htc_packet_set_magic_cookie(pPacket, 0);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800893 /* put it back into the callers queue */
894 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
Frank Liud2cc13e2018-12-06 16:03:26 +0800895 /* reclaim credits */
896 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,
897 pPacket) {
898 pEndpoint->TxCredits +=
899 pPacket->PktInfo.AsTx.CreditsUsed;
900 } HTC_PACKET_QUEUE_ITERATE_END;
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530901 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530902 UNLOCK_HTC_TX(target);
903 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800904 break;
905 }
wadesong4b3f37d2018-01-25 16:08:05 +0800906 if (rt_put) {
Houston Hoffman1dd22762015-11-10 11:35:49 -0800907 hif_pm_runtime_put(target->hif_dev);
wadesong4b3f37d2018-01-25 16:08:05 +0800908 rt_put = false;
909 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800910 }
Rakesh Pillai13146452017-06-22 12:52:31 +0530911 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -0800912 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700913 ("htc_issue_packets, failed pkt:0x%pK status:%d",
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -0800914 pPacket, status));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800915 }
916
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700917 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_issue_packets\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800918
919 return status;
920}
921
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800922#ifdef FEATURE_RUNTIME_PM
923/**
Jeff Johnson4b253f02018-05-12 11:34:43 -0700924 * extract_htc_pm_packets(): move pm packets from endpoint into queue
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800925 * @endpoint: which enpoint to extract packets from
926 * @queue: a queue to store extracted packets in.
927 *
928 * remove pm packets from the endpoint's tx queue.
929 * queue them into a queue
930 */
931static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
932 HTC_PACKET_QUEUE *queue)
933{
934 HTC_PACKET *packet;
935
936 /* only WMI endpoint has power management packets */
937 if (endpoint->service_id != WMI_CONTROL_SVC)
938 return;
939
940 ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet,
941 HTC_PACKET, ListLink) {
942 if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_AUTO_PM) {
943 HTC_PACKET_REMOVE(&endpoint->TxQueue, packet);
944 HTC_PACKET_ENQUEUE(queue, packet);
945 }
946 } ITERATE_END
947}
948
949/**
950 * queue_htc_pm_packets(): queue pm packets with priority
951 * @endpoint: enpoint to queue packets to
952 * @queue: queue of pm packets to enque
953 *
954 * suspend resume packets get special treatment & priority.
955 * need to queue them at the front of the queue.
956 */
957static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
958 HTC_PACKET_QUEUE *queue)
959{
960 if (endpoint->service_id != WMI_CONTROL_SVC)
961 return;
962
963 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&endpoint->TxQueue, queue);
964}
965#else
966static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
967 HTC_PACKET_QUEUE *queue)
968{}
969
970static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
971 HTC_PACKET_QUEUE *queue)
972{}
973#endif
974
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700975/**
976 * get_htc_send_packets_credit_based() - get packets based on available credits
977 * @target: HTC target on which packets need to be sent
978 * @pEndpoint: logical endpoint on which packets needs to be sent
979 * @pQueue: HTC packet queue containing the list of packets to be sent
980 *
981 * Get HTC send packets from TX queue on an endpoint based on available credits.
982 * The function moves the packets from TX queue of the endpoint to pQueue.
983 *
984 * Return: None
985 */
Jeff Johnsonc66399a2016-10-07 13:01:33 -0700986static void get_htc_send_packets_credit_based(HTC_TARGET *target,
987 HTC_ENDPOINT *pEndpoint,
988 HTC_PACKET_QUEUE *pQueue)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800989{
990 int creditsRequired;
991 int remainder;
Yue Mab16cf302016-03-08 18:30:25 -0800992 uint8_t sendFlags;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800993 HTC_PACKET *pPacket;
994 unsigned int transferLength;
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800995 HTC_PACKET_QUEUE *tx_queue;
996 HTC_PACKET_QUEUE pm_queue;
997 bool do_pm_get = false;
Yue Ma4986b252019-07-23 15:57:48 -0700998 int ret;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800999
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001000 /*** NOTE : the TX lock is held when this function is called ***/
1001 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1002 ("+get_htc_send_packets_credit_based\n"));
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001003
1004 INIT_HTC_PACKET_QUEUE(&pm_queue);
1005 extract_htc_pm_packets(pEndpoint, &pm_queue);
1006 if (HTC_QUEUE_EMPTY(&pm_queue)) {
1007 tx_queue = &pEndpoint->TxQueue;
1008 do_pm_get = true;
1009 } else {
1010 tx_queue = &pm_queue;
1011 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001012
1013 /* loop until we can grab as many packets out of the queue as we can */
1014 while (true) {
Yue Ma4986b252019-07-23 15:57:48 -07001015 if (do_pm_get) {
1016 ret = hif_pm_runtime_get(target->hif_dev);
1017 if (ret) {
1018 /* bus suspended, runtime resume issued */
1019 QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
1020 if (ret == -EAGAIN) {
1021 pPacket = htc_get_pkt_at_head(tx_queue);
1022 if (!pPacket)
1023 break;
1024 log_packet_info(target, pPacket);
1025 }
1026 break;
1027 }
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001028 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001029
1030 sendFlags = 0;
1031 /* get packet at head, but don't remove it */
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001032 pPacket = htc_get_pkt_at_head(tx_queue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001033 if (!pPacket) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001034 if (do_pm_get)
1035 hif_pm_runtime_put(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001036 break;
1037 }
1038
1039 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001040 (" Got head packet:%pK , Queue Depth: %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001041 pPacket,
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001042 HTC_PACKET_QUEUE_DEPTH(tx_queue)));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001043
1044 transferLength = pPacket->ActualLength + HTC_HDR_LENGTH;
1045
1046 if (transferLength <= pEndpoint->TxCreditSize) {
1047 creditsRequired = 1;
1048 } else {
1049 /* figure out how many credits this message requires */
1050 creditsRequired =
1051 transferLength / pEndpoint->TxCreditSize;
1052 remainder = transferLength % pEndpoint->TxCreditSize;
1053
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001054 if (remainder)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001055 creditsRequired++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001056 }
1057
1058 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1059 (" Credits Required:%d Got:%d\n",
1060 creditsRequired, pEndpoint->TxCredits));
1061
1062 if (pEndpoint->Id == ENDPOINT_0) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001063 /*
1064 * endpoint 0 is special, it always has a credit and
1065 * does not require credit based flow control
1066 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001067 creditsRequired = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001068 } else {
1069
1070 if (pEndpoint->TxCredits < creditsRequired) {
1071#if DEBUG_CREDIT
1072 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001073 ("EP%d,No Credit now.%d < %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001074 pEndpoint->Id,
1075 pEndpoint->TxCredits,
1076 creditsRequired));
1077#endif
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001078 if (do_pm_get)
1079 hif_pm_runtime_put(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001080 break;
1081 }
1082
1083 pEndpoint->TxCredits -= creditsRequired;
1084 INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed,
1085 creditsRequired);
1086
1087 /* check if we need credits back from the target */
1088 if (pEndpoint->TxCredits <=
1089 pEndpoint->TxCreditsPerMaxMsg) {
1090 /* tell the target we need credits ASAP! */
1091 sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
Houston Hoffman4f2f4592015-10-20 18:00:29 -07001092 if (pEndpoint->service_id == WMI_CONTROL_SVC) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001093 htc_credit_record(HTC_REQUEST_CREDIT,
1094 pEndpoint->TxCredits,
1095 HTC_PACKET_QUEUE_DEPTH
Rachit Kankane1bc11492018-01-24 18:48:17 +05301096 (tx_queue));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001097 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001098 INC_HTC_EP_STAT(pEndpoint,
1099 TxCreditLowIndications, 1);
1100#if DEBUG_CREDIT
1101 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1102 (" EP%d Needs Credits\n",
1103 pEndpoint->Id));
1104#endif
1105 }
1106 }
1107
1108 /* now we can fully dequeue */
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001109 pPacket = htc_packet_dequeue(tx_queue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001110 if (pPacket) {
1111 /* save the number of credits this packet consumed */
1112 pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired;
1113 /* save send flags */
1114 pPacket->PktInfo.AsTx.SendFlags = sendFlags;
1115
1116 /* queue this packet into the caller's queue */
1117 HTC_PACKET_ENQUEUE(pQueue, pPacket);
1118 }
1119 }
1120
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001121 if (!HTC_QUEUE_EMPTY(&pm_queue))
1122 queue_htc_pm_packets(pEndpoint, &pm_queue);
1123
1124 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1125 ("-get_htc_send_packets_credit_based\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001126
1127}
1128
Jeff Johnsonc66399a2016-10-07 13:01:33 -07001129static void get_htc_send_packets(HTC_TARGET *target,
1130 HTC_ENDPOINT *pEndpoint,
1131 HTC_PACKET_QUEUE *pQueue, int Resources)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001132{
1133
1134 HTC_PACKET *pPacket;
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001135 HTC_PACKET_QUEUE *tx_queue;
1136 HTC_PACKET_QUEUE pm_queue;
Tiger Yu054a6a42018-03-30 14:58:02 +08001137 bool do_pm_get = false;
Yue Ma4986b252019-07-23 15:57:48 -07001138 int ret;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001139
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001140 /*** NOTE : the TX lock is held when this function is called ***/
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001141 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1142 ("+get_htc_send_packets %d resources\n", Resources));
1143
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001144 INIT_HTC_PACKET_QUEUE(&pm_queue);
1145 extract_htc_pm_packets(pEndpoint, &pm_queue);
1146 if (HTC_QUEUE_EMPTY(&pm_queue)) {
1147 tx_queue = &pEndpoint->TxQueue;
1148 do_pm_get = true;
1149 } else {
1150 tx_queue = &pm_queue;
1151 }
1152
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001153 /* loop until we can grab as many packets out of the queue as we can */
1154 while (Resources > 0) {
1155 int num_frags;
1156
Yue Ma4986b252019-07-23 15:57:48 -07001157 if (do_pm_get) {
1158 ret = hif_pm_runtime_get(target->hif_dev);
1159 if (ret) {
1160 /* bus suspended, runtime resume issued */
1161 QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
1162 if (ret == -EAGAIN) {
1163 pPacket = htc_get_pkt_at_head(tx_queue);
1164 if (!pPacket)
1165 break;
1166 log_packet_info(target, pPacket);
1167 }
1168 break;
1169 }
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001170 }
1171
1172 pPacket = htc_packet_dequeue(tx_queue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001173 if (!pPacket) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001174 if (do_pm_get)
1175 hif_pm_runtime_put(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001176 break;
1177 }
1178 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001179 (" Got packet:%pK , New Queue Depth: %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001180 pPacket,
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001181 HTC_PACKET_QUEUE_DEPTH(tx_queue)));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001182 /* For non-credit path the sequence number is already embedded
1183 * in the constructed HTC header
1184 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001185 pPacket->PktInfo.AsTx.SendFlags = 0;
1186 pPacket->PktInfo.AsTx.CreditsUsed = 0;
1187 /* queue this packet into the caller's queue */
1188 HTC_PACKET_ENQUEUE(pQueue, pPacket);
1189
1190 /*
1191 * FIX THIS:
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301192 * For now, avoid calling qdf_nbuf_get_num_frags before calling
1193 * qdf_nbuf_map, because the MacOS version of qdf_nbuf_t doesn't
1194 * support qdf_nbuf_get_num_frags until after qdf_nbuf_map has
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001195 * been done.
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001196 * Assume that the non-data netbufs, i.e. WMI message netbufs,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001197 * consist of a single fragment.
1198 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001199 /* WMI messages are in a single-fragment network buf */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001200 num_frags =
1201 (pPacket->PktInfo.AsTx.
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001202 Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) ? 1 :
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301203 qdf_nbuf_get_num_frags(GET_HTC_PACKET_NET_BUF_CONTEXT
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001204 (pPacket));
1205 Resources -= num_frags;
1206 }
1207
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001208 if (!HTC_QUEUE_EMPTY(&pm_queue))
1209 queue_htc_pm_packets(pEndpoint, &pm_queue);
1210
1211 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001212
1213}
1214
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001215/**
1216 * htc_try_send() - Send packets in a queue on an endpoint
1217 * @target: HTC target on which packets need to be sent
1218 * @pEndpoint: logical endpoint on which packets needs to be sent
1219 * @pCallersSendQueue: packet queue containing the list of packets to be sent
1220 *
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001221 * Return: enum HTC_SEND_QUEUE_RESULT indicates whether the packet was queued to
1222 * be sent or the packet should be dropped by the upper layer
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001223 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001224static enum HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001225 HTC_ENDPOINT *pEndpoint,
1226 HTC_PACKET_QUEUE *pCallersSendQueue)
1227{
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001228 /* temp queue to hold packets at various stages */
1229 HTC_PACKET_QUEUE sendQueue;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001230 HTC_PACKET *pPacket;
1231 int tx_resources;
1232 int overflow;
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001233 enum HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001234
Jeff Johnsona79b1112017-09-18 10:12:02 -07001235 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+htc_try_send (Queue:%pK Depth:%d)\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001236 pCallersSendQueue,
1237 (pCallersSendQueue ==
1238 NULL) ? 0 :
1239 HTC_PACKET_QUEUE_DEPTH
1240 (pCallersSendQueue)));
1241
1242 /* init the local send queue */
1243 INIT_HTC_PACKET_QUEUE(&sendQueue);
1244
1245 do {
1246
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001247 /* caller didn't provide a queue, just wants us to check
1248 * queues and send
1249 */
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001250 if (!pCallersSendQueue)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001251 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001252
1253 if (HTC_QUEUE_EMPTY(pCallersSendQueue)) {
1254 /* empty queue */
1255 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,
1256 HTC_PKT_Q_EMPTY);
1257 result = HTC_SEND_QUEUE_DROP;
1258 break;
1259 }
1260
1261 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >=
1262 pEndpoint->MaxTxQueueDepth) {
1263 /* we've already overflowed */
1264 overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
1265 } else {
1266 /* figure out how much we will overflow by */
1267 overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
1268 overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001269 /* get how much we will overflow the TX queue by */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001270 overflow -= pEndpoint->MaxTxQueueDepth;
1271 }
1272
1273 /* if overflow is negative or zero, we are okay */
1274 if (overflow > 0) {
1275 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001276 ("Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001277 pEndpoint->Id, overflow,
1278 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->
1279 TxQueue),
1280 pEndpoint->MaxTxQueueDepth));
1281 }
1282 if ((overflow <= 0)
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001283 || (!pEndpoint->EpCallBacks.EpSendFull)) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001284 /* all packets will fit or caller did not provide send
1285 * full indication handler
1286 * just move all of them to local sendQueue object
1287 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001288 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue,
1289 pCallersSendQueue);
1290 } else {
1291 int i;
1292 int goodPkts =
1293 HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) -
1294 overflow;
1295
1296 A_ASSERT(goodPkts >= 0);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001297 /* we have overflowed and callback is provided. Dequeue
1298 * all non-overflow packets into the sendqueue
1299 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001300 for (i = 0; i < goodPkts; i++) {
1301 /* pop off caller's queue */
1302 pPacket = htc_packet_dequeue(pCallersSendQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001303 A_ASSERT(pPacket);
Alok Kumar5d4c6f22019-06-24 16:31:59 +05301304 if (pPacket)
1305 /* insert into local queue */
1306 HTC_PACKET_ENQUEUE(&sendQueue,
1307 pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001308 }
1309
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001310 /* the caller's queue has all the packets that won't fit
1311 * walk through the caller's queue and indicate each one
1312 * to the send full handler
1313 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001314 ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->
1315 QueueHead, pPacket,
1316 HTC_PACKET, ListLink) {
1317
1318 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001319 ("Indicating overflowed TX packet: %pK\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001320 pPacket));
1321 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001322 * Remove headroom reserved for HTC_FRAME_HDR
1323 * before giving the packet back to the user via
1324 * the EpSendFull callback.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001325 */
1326 restore_tx_packet(target, pPacket);
1327
1328 if (pEndpoint->EpCallBacks.
1329 EpSendFull(pEndpoint->EpCallBacks.pContext,
1330 pPacket) == HTC_SEND_FULL_DROP) {
1331 /* callback wants the packet dropped */
1332 INC_HTC_EP_STAT(pEndpoint, TxDropped,
1333 1);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001334 /* leave this one in the caller's queue
1335 * for cleanup
1336 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001337 } else {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001338 /* callback wants to keep this packet,
1339 * remove from caller's queue
1340 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001341 HTC_PACKET_REMOVE(pCallersSendQueue,
1342 pPacket);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001343 /* put it in the send queue
1344 * add HTC_FRAME_HDR space reservation
1345 * again
1346 */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301347 qdf_nbuf_push_head
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001348 (GET_HTC_PACKET_NET_BUF_CONTEXT
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001349 (pPacket),
1350 sizeof(HTC_FRAME_HDR));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001351
1352 HTC_PACKET_ENQUEUE(&sendQueue, pPacket);
1353 }
1354
1355 }
1356 ITERATE_END;
1357
1358 if (HTC_QUEUE_EMPTY(&sendQueue)) {
1359 /* no packets made it in, caller will cleanup */
1360 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001361 HTC_SEND_Q_EMPTY);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001362 result = HTC_SEND_QUEUE_DROP;
1363 break;
1364 }
1365 }
1366
1367 } while (false);
1368
1369 if (result != HTC_SEND_QUEUE_OK) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001370 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send: %d\n",
1371 result));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001372 return result;
1373 }
1374
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001375 LOCK_HTC_TX(target);
1376
1377 if (!HTC_QUEUE_EMPTY(&sendQueue)) {
gbianb417db22016-09-30 17:01:07 +08001378 if (target->is_nodrop_pkt) {
1379 /*
1380 * nodrop pkts have higher priority than normal pkts,
1381 * insert nodrop pkt to head for proper
1382 * start/termination of test.
1383 */
1384 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
1385 &sendQueue);
1386 target->is_nodrop_pkt = false;
1387 } else {
1388 /* transfer packets to tail */
1389 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,
1390 &sendQueue);
1391 A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue));
1392 INIT_HTC_PACKET_QUEUE(&sendQueue);
1393 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001394 }
1395
1396 /* increment tx processing count on entry */
Rajeev Kumare37820e2016-04-14 17:30:56 -07001397 if (qdf_atomic_inc_return(&pEndpoint->TxProcessCount) > 1) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001398 /* another thread or task is draining the TX queues on this
1399 * endpoint that thread will reset the tx processing count when
1400 * the queue is drained
1401 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301402 qdf_atomic_dec(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001403 UNLOCK_HTC_TX(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001404 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send (busy)\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001405 return HTC_SEND_QUEUE_OK;
1406 }
1407
1408 /***** beyond this point only 1 thread may enter ******/
1409
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001410 /* now drain the endpoint TX queue for transmission as long as we have
1411 * enough transmit resources
1412 */
Ajit Pal Singh5c3ba892019-06-04 13:24:57 +05301413 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1414 tx_resources =
1415 hif_get_free_queue_number(target->hif_dev,
1416 pEndpoint->UL_PipeID);
1417 } else {
1418 tx_resources = 0;
1419 }
1420
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001421 while (true) {
1422
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301423 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0)
1424 break;
1425
1426 if (pEndpoint->async_update &&
1427 (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) &&
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001428 (!tx_resources))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001429 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001430
1431 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1432#if DEBUG_CREDIT
1433 int cred = pEndpoint->TxCredits;
1434#endif
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001435 /* credit based mechanism provides flow control based on
1436 * target transmit resource availability, we assume that
1437 * the HIF layer will always have bus resources greater
1438 * than target transmit resources
1439 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001440 get_htc_send_packets_credit_based(target, pEndpoint,
1441 &sendQueue);
1442#if DEBUG_CREDIT
1443 if (ep_debug_mask & (1 << pEndpoint->Id)) {
1444 if (cred - pEndpoint->TxCredits > 0) {
1445 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001446 (" <HTC> Decrease EP%d %d - %d = %d credits.\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001447 pEndpoint->Id, cred,
1448 cred -
1449 pEndpoint->TxCredits,
1450 pEndpoint->TxCredits));
1451 }
1452 }
1453#endif
1454 } else {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001455
1456 /*
1457 * Header and payload belongs to the different fragments and
1458 * consume 2 resource for one HTC package but USB combine into
Liangwei Dong2c73be82016-09-29 03:35:59 -04001459 * one transfer.And one WMI message only consumes one single
1460 * resource.
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001461 */
Liangwei Dong2c73be82016-09-29 03:35:59 -04001462 if (HTC_TX_BUNDLE_ENABLED(target) && tx_resources &&
1463 hif_get_bus_type(target->hif_dev) ==
1464 QDF_BUS_TYPE_USB) {
1465 if (pEndpoint->service_id ==
1466 WMI_CONTROL_SVC)
1467 tx_resources =
1468 HTC_MAX_MSG_PER_BUNDLE_TX;
1469 else
1470 tx_resources =
1471 (HTC_MAX_MSG_PER_BUNDLE_TX * 2);
1472 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001473 /* get all the packets for this endpoint that we can for
1474 * this pass
1475 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001476 get_htc_send_packets(target, pEndpoint, &sendQueue,
1477 tx_resources);
1478 }
1479
1480 if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001481 /* didn't get any packets due to a lack of resources or
1482 * TX queue was drained
1483 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001484 break;
1485 }
1486
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001487 if (!pEndpoint->async_update)
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05301488 UNLOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001489
1490 /* send what we can */
Rakesh Pillai13146452017-06-22 12:52:31 +05301491 if (htc_issue_packets(target, pEndpoint, &sendQueue)) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001492 int i;
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001493
Rakesh Pillai13146452017-06-22 12:52:31 +05301494 result = HTC_SEND_QUEUE_DROP;
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -08001495 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1496 ("htc_issue_packets, failed status:%d put it back to head of callersSendQueue",
1497 result));
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001498
1499 for (i = HTC_PACKET_QUEUE_DEPTH(&sendQueue); i > 0; i--)
1500 hif_pm_runtime_put(target->hif_dev);
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301501 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandarub3c810b2016-11-02 17:12:34 +05301502 LOCK_HTC_TX(target);
1503 }
Liangwei Dong6c5e3322016-11-07 00:27:50 -05001504 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
1505 &sendQueue);
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -08001506 break;
1507 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001508
1509 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1510 tx_resources =
1511 hif_get_free_queue_number(target->hif_dev,
1512 pEndpoint->UL_PipeID);
1513 }
1514
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301515 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05301516 LOCK_HTC_TX(target);
1517 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001518
1519 }
1520
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001521 /* done with this endpoint, we can clear the count */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301522 qdf_atomic_init(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001523
Rajeev Kumare37820e2016-04-14 17:30:56 -07001524 UNLOCK_HTC_TX(target);
1525
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001526 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send:\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001527
1528 return HTC_SEND_QUEUE_OK;
1529}
1530
1531#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001532static uint16_t htc_send_pkts_sched_check(HTC_HANDLE HTCHandle,
1533 HTC_ENDPOINT_ID id)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001534{
1535 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1536 HTC_ENDPOINT *pEndpoint;
1537 HTC_ENDPOINT_ID eid;
1538 HTC_PACKET_QUEUE *pTxQueue;
Yue Mab16cf302016-03-08 18:30:25 -08001539 uint16_t resources;
1540 uint16_t acQueueStatus[DATA_EP_SIZE] = { 0, 0, 0, 0 };
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001541
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001542 if (id < ENDPOINT_2 || id > ENDPOINT_5)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001543 return 1;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001544
1545 for (eid = ENDPOINT_2; eid <= ENDPOINT_5; eid++) {
Houston Hoffman29573d92015-10-20 17:49:44 -07001546 pEndpoint = &target->endpoint[eid];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001547 pTxQueue = &pEndpoint->TxQueue;
1548
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001549 if (HTC_QUEUE_EMPTY(pTxQueue))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001550 acQueueStatus[eid - 2] = 1;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001551 }
1552
1553 switch (id) {
1554 case ENDPOINT_2: /* BE */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301555 return acQueueStatus[0] && acQueueStatus[2]
1556 && acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001557 case ENDPOINT_3: /* BK */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301558 return acQueueStatus[0] && acQueueStatus[1] && acQueueStatus[2]
1559 && acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001560 case ENDPOINT_4: /* VI */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301561 return acQueueStatus[2] && acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001562 case ENDPOINT_5: /* VO */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301563 return acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001564 default:
1565 return 0;
1566 }
1567
1568}
1569
1570static A_STATUS htc_send_pkts_sched_queue(HTC_TARGET *target,
1571 HTC_PACKET_QUEUE *pPktQueue,
1572 HTC_ENDPOINT_ID eid)
1573{
1574 HTC_ENDPOINT *pEndpoint;
1575 HTC_PACKET_QUEUE *pTxQueue;
1576 HTC_PACKET *pPacket;
1577 int goodPkts;
1578
Houston Hoffman29573d92015-10-20 17:49:44 -07001579 pEndpoint = &target->endpoint[eid];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001580 pTxQueue = &pEndpoint->TxQueue;
1581
1582 LOCK_HTC_TX(target);
1583
1584 goodPkts =
1585 pEndpoint->MaxTxQueueDepth -
1586 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
1587
1588 if (goodPkts > 0) {
1589 while (!HTC_QUEUE_EMPTY(pPktQueue)) {
1590 pPacket = htc_packet_dequeue(pPktQueue);
1591 HTC_PACKET_ENQUEUE(pTxQueue, pPacket);
1592 goodPkts--;
1593
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001594 if (goodPkts <= 0)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001595 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001596 }
1597 }
1598
1599 if (HTC_PACKET_QUEUE_DEPTH(pPktQueue)) {
1600 ITERATE_OVER_LIST_ALLOW_REMOVE(&pPktQueue->QueueHead, pPacket,
1601 HTC_PACKET, ListLink) {
1602
1603 if (pEndpoint->EpCallBacks.
1604 EpSendFull(pEndpoint->EpCallBacks.pContext,
1605 pPacket) == HTC_SEND_FULL_DROP) {
1606 INC_HTC_EP_STAT(pEndpoint, TxDropped, 1);
1607 } else {
1608 HTC_PACKET_REMOVE(pPktQueue, pPacket);
1609 HTC_PACKET_ENQUEUE(pTxQueue, pPacket);
1610 }
1611 }
1612 ITERATE_END;
1613 }
1614
1615 UNLOCK_HTC_TX(target);
1616
1617 return A_OK;
1618}
1619
1620#endif
1621
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001622static inline QDF_STATUS __htc_send_pkt(HTC_HANDLE HTCHandle,
1623 HTC_PACKET *pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001624{
1625 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1626 HTC_ENDPOINT *pEndpoint;
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001627 HTC_PACKET_QUEUE pPktQueue;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301628 qdf_nbuf_t netbuf;
Yun Parkc353d6b2018-06-05 11:58:30 -07001629 HTC_FRAME_HDR *htc_hdr;
Himanshu Agarwalfa594d92017-04-04 12:36:33 +05301630 QDF_STATUS status;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001631
1632 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001633 ("+__htc_send_pkt\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001634
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001635 /* get packet at head to figure out which endpoint these packets will
1636 * go into
1637 */
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001638 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001639 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target, GET_HTC_PKT_Q_FAIL);
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001640 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n"));
Rakesh Pillai13146452017-06-22 12:52:31 +05301641 return QDF_STATUS_E_INVAL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001642 }
1643
Jiachao Wu15a94742017-11-10 10:13:38 +08001644 if ((pPacket->Endpoint >= ENDPOINT_MAX) ||
1645 (pPacket->Endpoint <= ENDPOINT_UNUSED)) {
1646 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1647 ("%s endpoint is invalid\n", __func__));
1648 AR_DEBUG_ASSERT(0);
1649 return QDF_STATUS_E_INVAL;
1650 }
Houston Hoffman29573d92015-10-20 17:49:44 -07001651 pEndpoint = &target->endpoint[pPacket->Endpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001652
Houston Hoffman4f2f4592015-10-20 18:00:29 -07001653 if (!pEndpoint->service_id) {
1654 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("%s service_id is invalid\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001655 __func__));
Rakesh Pillai13146452017-06-22 12:52:31 +05301656 return QDF_STATUS_E_INVAL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001657 }
1658
1659#ifdef HTC_EP_STAT_PROFILING
1660 LOCK_HTC_TX(target);
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001661 INC_HTC_EP_STAT(pEndpoint, TxPosted, 1);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001662 UNLOCK_HTC_TX(target);
1663#endif
1664
1665 /* provide room in each packet's netbuf for the HTC frame header */
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001666 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
1667 AR_DEBUG_ASSERT(netbuf);
Yun Parkc353d6b2018-06-05 11:58:30 -07001668 if (!netbuf)
1669 return QDF_STATUS_E_INVAL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001670
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001671 qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR));
Nirav Shah31435bb2019-08-05 17:51:19 +05301672 pPacket->PktInfo.AsTx.Flags |=
1673 HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA;
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001674 /* setup HTC frame header */
Yun Parkc353d6b2018-06-05 11:58:30 -07001675 htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
1676 AR_DEBUG_ASSERT(htc_hdr);
1677 if (!htc_hdr)
1678 return QDF_STATUS_E_INVAL;
1679
1680 HTC_WRITE32(htc_hdr,
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001681 SM(pPacket->ActualLength,
1682 HTC_FRAME_HDR_PAYLOADLEN) |
1683 SM(pPacket->Endpoint,
1684 HTC_FRAME_HDR_ENDPOINTID));
1685 LOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001686
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001687 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
1688 pEndpoint->SeqNo++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001689
Yun Parkc353d6b2018-06-05 11:58:30 -07001690 HTC_WRITE32(((uint32_t *)htc_hdr) + 1,
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001691 SM(pPacket->PktInfo.AsTx.SeqNo,
1692 HTC_FRAME_HDR_CONTROLBYTES1));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001693
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001694 UNLOCK_HTC_TX(target);
Dustin Brownbc9718f2017-12-11 12:15:27 -08001695
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001696 /*
Dustin Brown8969ad72017-12-02 22:43:26 -08001697 * For flow control enabled endpoints mapping is done in
1698 * htc_issue_packets and for non flow control enabled endpoints
1699 * its done here.
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001700 */
Dustin Brown8969ad72017-12-02 22:43:26 -08001701 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
Dustin Brownbc9718f2017-12-11 12:15:27 -08001702 pPacket->PktInfo.AsTx.Flags |= HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
Dustin Brown8969ad72017-12-02 22:43:26 -08001703 status = qdf_nbuf_map(target->osdev,
1704 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
1705 QDF_DMA_TO_DEVICE);
1706 if (status != QDF_STATUS_SUCCESS) {
1707 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1708 ("%s: nbuf map failed, endpoint %pK, seq_no. %d\n",
1709 __func__, pEndpoint, pEndpoint->SeqNo));
1710 return status;
1711 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001712 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001713
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001714 INIT_HTC_PACKET_QUEUE_AND_ADD(&pPktQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001715#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001716 if (!htc_send_pkts_sched_check(HTCHandle, pEndpoint->Id))
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001717 htc_send_pkts_sched_queue(HTCHandle, &pPktQueue, pEndpoint->Id);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001718 else
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001719 htc_try_send(target, pEndpoint, &pPktQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001720#else
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001721 htc_try_send(target, pEndpoint, &pPktQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001722#endif
1723
1724 /* do completion on any packets that couldn't get in */
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001725 while (!HTC_QUEUE_EMPTY(&pPktQueue)) {
1726 pPacket = htc_packet_dequeue(&pPktQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001727
Yun Park88e0b952017-10-11 23:08:34 -07001728 if (HTC_STOPPING(target))
1729 pPacket->Status = QDF_STATUS_E_CANCELED;
1730 else
1731 pPacket->Status = QDF_STATUS_E_RESOURCES;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001732
Yun Park88e0b952017-10-11 23:08:34 -07001733 send_packet_completion(target, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001734 }
1735
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001736 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001737
Rakesh Pillai13146452017-06-22 12:52:31 +05301738 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001739}
1740
1741/* HTC API - htc_send_pkt */
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001742QDF_STATUS htc_send_pkt(HTC_HANDLE htc_handle, HTC_PACKET *htc_packet)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001743{
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001744 if (!htc_handle) {
1745 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1746 ("%s: HTCHandle is NULL \n", __func__));
Rakesh Pillai13146452017-06-22 12:52:31 +05301747 return QDF_STATUS_E_FAILURE;
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001748 }
1749
1750 if (!htc_packet) {
1751 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1752 ("%s: pPacket is NULL \n", __func__));
1753 return QDF_STATUS_E_FAILURE;
1754 }
Karthick Sdc40a352015-10-14 18:14:15 +05301755
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001756 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001757 ("+-htc_send_pkt: Enter endPointId: %d, buffer: %pK, length: %d\n",
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001758 htc_packet->Endpoint, htc_packet->pBuffer,
1759 htc_packet->ActualLength));
1760 return __htc_send_pkt(htc_handle, htc_packet);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001761}
Pratik Gandhidc82a772018-01-30 18:57:05 +05301762qdf_export_symbol(htc_send_pkt);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001763
1764#ifdef ATH_11AC_TXCOMPACT
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001765/**
1766 * htc_send_data_pkt() - send single data packet on an endpoint
1767 * @HTCHandle: pointer to HTC handle
1768 * @netbuf: network buffer containing the data to be sent
1769 * @ActualLength: length of data that needs to be transmitted
1770 *
Rakesh Pillai13146452017-06-22 12:52:31 +05301771 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001772 */
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301773QDF_STATUS htc_send_data_pkt(HTC_HANDLE htc_hdl, qdf_nbuf_t netbuf, int ep_id,
1774 int actual_length)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001775{
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301776 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001777 HTC_ENDPOINT *pEndpoint;
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301778 HTC_FRAME_HDR *p_htc_hdr;
Rakesh Pillai13146452017-06-22 12:52:31 +05301779 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001780 int tx_resources;
1781 uint32_t data_attr = 0;
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301782 int htc_payload_len = actual_length;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001783
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301784 pEndpoint = &target->endpoint[ep_id];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001785
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001786 tx_resources = hif_get_free_queue_number(target->hif_dev,
1787 pEndpoint->UL_PipeID);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001788
1789 if (tx_resources < HTC_DATA_RESOURCE_THRS) {
1790 if (pEndpoint->ul_is_polled) {
1791 hif_send_complete_check(pEndpoint->target->hif_dev,
1792 pEndpoint->UL_PipeID, 1);
1793 tx_resources =
1794 hif_get_free_queue_number(target->hif_dev,
1795 pEndpoint->UL_PipeID);
1796 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001797 if (tx_resources < HTC_DATA_MINDESC_PERPACKET)
Rakesh Pillai13146452017-06-22 12:52:31 +05301798 return QDF_STATUS_E_FAILURE;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001799 }
1800
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001801 if (hif_pm_runtime_get(target->hif_dev))
Rakesh Pillai13146452017-06-22 12:52:31 +05301802 return QDF_STATUS_E_FAILURE;
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001803
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301804 p_htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
1805 AR_DEBUG_ASSERT(p_htc_hdr);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001806
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301807 data_attr = qdf_nbuf_data_attr_get(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001808
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301809 if (target->htc_hdr_length_check)
1810 htc_payload_len = actual_length - HTC_HEADER_LEN;
1811
1812 HTC_WRITE32(p_htc_hdr, SM(htc_payload_len, HTC_FRAME_HDR_PAYLOADLEN)
1813 | SM(ep_id, HTC_FRAME_HDR_ENDPOINTID));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001814 /*
1815 * If the HIF pipe for the data endpoint is polled rather than
1816 * interrupt-driven, this is a good point to check whether any
1817 * data previously sent through the HIF pipe have finished being
1818 * sent.
1819 * Since this may result in callbacks to htc_tx_completion_handler,
1820 * which can take the HTC tx lock, make the hif_send_complete_check
1821 * call before acquiring the HTC tx lock.
1822 * Call hif_send_complete_check directly, rather than calling
1823 * htc_send_complete_check, and call the PollTimerStart separately
1824 * after calling hif_send_head, so the timer will be started to
1825 * check for completion of the new outstanding download (in the
1826 * unexpected event that other polling calls don't catch it).
1827 */
1828
1829 LOCK_HTC_TX(target);
1830
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301831 HTC_WRITE32(((uint32_t *)p_htc_hdr) + 1,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001832 SM(pEndpoint->SeqNo, HTC_FRAME_HDR_CONTROLBYTES1));
1833
1834 pEndpoint->SeqNo++;
1835
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301836 QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301837 DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
Nandha Kishore Easwarane43583f2017-05-15 21:01:13 +05301838 QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf),
1839 sizeof(qdf_nbuf_data(netbuf)), QDF_TX));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001840 status = hif_send_head(target->hif_dev,
1841 pEndpoint->UL_PipeID,
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301842 pEndpoint->Id, actual_length, netbuf, data_attr);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001843
1844 UNLOCK_HTC_TX(target);
1845 return status;
1846}
1847#else /*ATH_11AC_TXCOMPACT */
1848
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001849/**
1850 * htc_send_data_pkt() - htc_send_data_pkt
1851 * @HTCHandle: pointer to HTC handle
1852 * @pPacket: pointer to HTC_PACKET
1853 * @more_data: indicates whether more data is to follow
1854 *
Rakesh Pillai13146452017-06-22 12:52:31 +05301855 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001856 */
Rakesh Pillai13146452017-06-22 12:52:31 +05301857QDF_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket,
Yue Mab16cf302016-03-08 18:30:25 -08001858 uint8_t more_data)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001859{
1860 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1861 HTC_ENDPOINT *pEndpoint;
1862 HTC_FRAME_HDR *pHtcHdr;
1863 HTC_PACKET_QUEUE sendQueue;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301864 qdf_nbuf_t netbuf = NULL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001865 int tx_resources;
Rakesh Pillai13146452017-06-22 12:52:31 +05301866 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001867 uint32_t data_attr = 0;
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05301868 bool used_extra_tx_credit = false;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001869
1870 if (pPacket) {
Jiachao Wu15a94742017-11-10 10:13:38 +08001871 if ((pPacket->Endpoint >= ENDPOINT_MAX) ||
1872 (pPacket->Endpoint <= ENDPOINT_UNUSED)) {
1873 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1874 ("%s endpoint is invalid\n", __func__));
1875 AR_DEBUG_ASSERT(0);
1876 return QDF_STATUS_E_INVAL;
1877 }
Houston Hoffman29573d92015-10-20 17:49:44 -07001878 pEndpoint = &target->endpoint[pPacket->Endpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001879
1880 /* add HTC_FRAME_HDR in the initial fragment */
1881 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301882 pHtcHdr = (HTC_FRAME_HDR *) qdf_nbuf_get_frag_vaddr(netbuf, 0);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001883 AR_DEBUG_ASSERT(pHtcHdr);
1884
1885 HTC_WRITE32(pHtcHdr,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001886 SM(pPacket->ActualLength,
1887 HTC_FRAME_HDR_PAYLOADLEN) |
1888 SM(pPacket->PktInfo.AsTx.SendFlags,
1889 HTC_FRAME_HDR_FLAGS) |
1890 SM(pPacket->Endpoint,
1891 HTC_FRAME_HDR_ENDPOINTID));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001892 /*
1893 * If the HIF pipe for the data endpoint is polled rather than
1894 * interrupt-driven, this is a good point to check whether any
1895 * data previously sent through the HIF pipe have finished being
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001896 * sent. Since this may result in callbacks to
1897 * htc_tx_completion_handler, which can take the HTC tx lock,
1898 * make the hif_send_complete_check call before acquiring the
1899 * HTC tx lock.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001900 * Call hif_send_complete_check directly, rather than calling
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001901 * htc_send_complete_check, and call the PollTimerStart
1902 * separately after calling hif_send_head, so the timer will be
1903 * started to check for completion of the new outstanding
1904 * download (in the unexpected event that other polling calls
1905 * don't catch it).
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001906 */
1907 if (pEndpoint->ul_is_polled) {
1908 htc_send_complete_poll_timer_stop(pEndpoint);
1909 hif_send_complete_check(pEndpoint->target->hif_dev,
1910 pEndpoint->UL_PipeID, 0);
1911 }
1912
1913 LOCK_HTC_TX(target);
1914
1915 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
1916 pEndpoint->SeqNo++;
1917
Yue Mab16cf302016-03-08 18:30:25 -08001918 HTC_WRITE32(((uint32_t *) pHtcHdr) + 1,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001919 SM(pPacket->PktInfo.AsTx.SeqNo,
1920 HTC_FRAME_HDR_CONTROLBYTES1));
1921
1922 /* append new packet to pEndpoint->TxQueue */
1923 HTC_PACKET_ENQUEUE(&pEndpoint->TxQueue, pPacket);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001924 if (HTC_TX_BUNDLE_ENABLED(target) && (more_data)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001925 UNLOCK_HTC_TX(target);
Rakesh Pillai13146452017-06-22 12:52:31 +05301926 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001927 }
wadesong31d77bc2017-05-28 14:45:21 +08001928
1929 QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
1930 DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
Nirav Shahd9dce6e2018-02-26 14:50:25 +05301931 QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf),
wadesong31d77bc2017-05-28 14:45:21 +08001932 sizeof(qdf_nbuf_data(netbuf)), QDF_TX));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001933 } else {
1934 LOCK_HTC_TX(target);
Houston Hoffman29573d92015-10-20 17:49:44 -07001935 pEndpoint = &target->endpoint[1];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001936 }
1937
1938 /* increment tx processing count on entry */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301939 qdf_atomic_inc(&pEndpoint->TxProcessCount);
1940 if (qdf_atomic_read(&pEndpoint->TxProcessCount) > 1) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001941 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001942 * Another thread or task is draining the TX queues on this
1943 * endpoint. That thread will reset the tx processing count when
1944 * the queue is drained.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001945 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301946 qdf_atomic_dec(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001947 UNLOCK_HTC_TX(target);
Rakesh Pillai13146452017-06-22 12:52:31 +05301948 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001949 }
1950
1951 /***** beyond this point only 1 thread may enter ******/
1952
1953 INIT_HTC_PACKET_QUEUE(&sendQueue);
1954 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1955#if DEBUG_CREDIT
1956 int cred = pEndpoint->TxCredits;
1957#endif
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001958 get_htc_send_packets_credit_based(target, pEndpoint,
1959 &sendQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001960#if DEBUG_CREDIT
1961 if (ep_debug_mask & (1 << pEndpoint->Id)) {
1962 if (cred - pEndpoint->TxCredits > 0) {
1963 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1964 (" <HTC> Decrease EP%d %d - %d = %d credits.\n",
1965 pEndpoint->Id, cred,
1966 cred - pEndpoint->TxCredits,
1967 pEndpoint->TxCredits));
1968 }
1969 }
1970#endif
1971 UNLOCK_HTC_TX(target);
1972 }
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001973
1974 else if (HTC_TX_BUNDLE_ENABLED(target)) {
Ajit Pal Singh3fcc0822019-03-21 17:35:22 +05301975 if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB) {
1976 if (hif_get_free_queue_number(target->hif_dev,
1977 pEndpoint->UL_PipeID))
1978 /*
1979 * Header and payload belongs to the different
1980 * fragments and consume 2 resource for one HTC
1981 * package but USB combine into one transfer.
1982 */
1983 get_htc_send_packets(target, pEndpoint,
1984 &sendQueue,
1985 HTC_MAX_MSG_PER_BUNDLE_TX
1986 * 2);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001987 } else {
Ajit Pal Singh3fcc0822019-03-21 17:35:22 +05301988 /* Dequeue max packets from endpoint tx queue */
1989 get_htc_send_packets(target, pEndpoint, &sendQueue,
1990 HTC_MAX_TX_BUNDLE_SEND_LIMIT);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001991 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001992 UNLOCK_HTC_TX(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001993 } else {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001994 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001995 * Now drain the endpoint TX queue for transmission as long as
1996 * we have enough transmit resources
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001997 */
1998 tx_resources =
1999 hif_get_free_queue_number(target->hif_dev,
2000 pEndpoint->UL_PipeID);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002001 get_htc_send_packets(target, pEndpoint, &sendQueue,
2002 tx_resources);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002003 UNLOCK_HTC_TX(target);
2004 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002005
2006 /* send what we can */
2007 while (true) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002008 if (HTC_TX_BUNDLE_ENABLED(target) &&
2009 (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >=
2010 HTC_MIN_MSG_PER_BUNDLE) &&
2011 (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO ||
2012 hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)) {
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302013 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
2014 if (htc_tx_pad_credit_avail(pEndpoint) < 1) {
2015 status = QDF_STATUS_E_RESOURCES;
2016 /* put the sendQueue back at the front
2017 * of pEndpoint->TxQueue
2018 */
2019 LOCK_HTC_TX(target);
2020 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(
2021 &pEndpoint->TxQueue,
2022 &sendQueue);
2023 UNLOCK_HTC_TX(target);
2024 break;
2025 }
2026 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002027 htc_issue_packets_bundle(target, pEndpoint, &sendQueue);
2028 }
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302029 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
2030 if (htc_tx_pad_credit_avail(pEndpoint) < 1) {
2031 status = QDF_STATUS_E_RESOURCES;
2032 /* put the sendQueue back at the front
2033 * of pEndpoint->TxQueue
2034 */
2035 LOCK_HTC_TX(target);
2036 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(
2037 &pEndpoint->TxQueue,
2038 &sendQueue);
2039 UNLOCK_HTC_TX(target);
2040 break;
2041 }
2042 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002043 pPacket = htc_packet_dequeue(&sendQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07002044 if (!pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002045 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002046 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302047 pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002048
2049 LOCK_HTC_TX(target);
2050 /* store in look up queue to match completions */
2051 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket);
2052 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
2053 pEndpoint->ul_outstanding_cnt++;
2054 UNLOCK_HTC_TX(target);
2055
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302056 used_extra_tx_credit =
2057 htc_handle_extra_tx_credit(pEndpoint, pPacket,
2058 (uint8_t *)pHtcHdr,
2059 NULL,
2060 pPacket->ActualLength
2061 + HTC_HDR_LENGTH);
2062
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002063 status = hif_send_head(target->hif_dev,
2064 pEndpoint->UL_PipeID,
2065 pEndpoint->Id,
2066 HTC_HDR_LENGTH + pPacket->ActualLength,
2067 netbuf, data_attr);
Visweswara Tanuku957b63a2019-06-11 10:30:59 +05302068 if (status != QDF_STATUS_SUCCESS) {
2069 if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
2070 if (used_extra_tx_credit) {
2071 pEndpoint->EpCallBacks.
2072 ep_padding_credit_update
2073 (pEndpoint->EpCallBacks.pContext, 1);
2074 }
2075 }
2076 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002077#if DEBUG_BUNDLE
Aditya Sathish648ce112018-07-02 16:41:39 +05302078 qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002079 pEndpoint->Id,
2080 pEndpoint->TxCreditSize,
2081 HTC_HDR_LENGTH + pPacket->ActualLength);
2082#endif
2083
Poddar, Siddarthdf030092016-04-28 11:41:57 +05302084 htc_issue_tx_bundle_stats_inc(target);
2085
Rakesh Pillai13146452017-06-22 12:52:31 +05302086 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002087 LOCK_HTC_TX(target);
2088 pEndpoint->ul_outstanding_cnt--;
2089 /* remove this packet from the tx completion queue */
2090 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket);
2091
2092 /*
2093 * Don't bother reclaiming credits - HTC flow control
2094 * is not applicable to tx data.
2095 * In LL systems, there is no download flow control,
2096 * since there's virtually no download delay.
2097 * In HL systems, the txrx SW explicitly performs the
2098 * tx flow control.
2099 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002100 /* pEndpoint->TxCredits +=
2101 * pPacket->PktInfo.AsTx.CreditsUsed;
2102 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002103
2104 /* put this frame back at the front of the sendQueue */
2105 HTC_PACKET_ENQUEUE_TO_HEAD(&sendQueue, pPacket);
2106
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002107 /* put the sendQueue back at the front of
2108 * pEndpoint->TxQueue
2109 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002110 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
2111 &sendQueue);
2112 UNLOCK_HTC_TX(target);
2113 break; /* still need to reset TxProcessCount */
2114 }
2115 }
2116 /* done with this endpoint, we can clear the count */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302117 qdf_atomic_init(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002118
2119 if (pEndpoint->ul_is_polled) {
2120 /*
2121 * Start a cleanup timer to poll for download completion.
2122 * The download completion should be noticed promptly from
2123 * other polling calls, but the timer provides a safety net
2124 * in case other polling calls don't occur as expected.
2125 */
2126 htc_send_complete_poll_timer_start(pEndpoint);
2127 }
2128
2129 return status;
2130}
2131#endif /*ATH_11AC_TXCOMPACT */
Pratik Gandhidc82a772018-01-30 18:57:05 +05302132qdf_export_symbol(htc_send_data_pkt);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002133
2134/*
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302135 * In the adapted HIF layer, qdf_nbuf_t are passed between HIF and HTC,
2136 * since upper layers expects HTC_PACKET containers we use the completed netbuf
2137 * and lookup its corresponding HTC packet buffer from a lookup list.
2138 * This is extra overhead that can be fixed by re-aligning HIF interfaces
2139 * with HTC.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002140 *
2141 */
2142static HTC_PACKET *htc_lookup_tx_packet(HTC_TARGET *target,
2143 HTC_ENDPOINT *pEndpoint,
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302144 qdf_nbuf_t netbuf)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002145{
2146 HTC_PACKET *pPacket = NULL;
2147 HTC_PACKET *pFoundPacket = NULL;
2148 HTC_PACKET_QUEUE lookupQueue;
2149
2150 INIT_HTC_PACKET_QUEUE(&lookupQueue);
Govind Singhc505cdc2017-05-16 12:15:51 +05302151 LOCK_HTC_EP_TX_LOOKUP(pEndpoint);
2152
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002153 LOCK_HTC_TX(target);
2154
2155 /* mark that HIF has indicated the send complete for another packet */
2156 pEndpoint->ul_outstanding_cnt--;
2157
2158 /* Dequeue first packet directly because of in-order completion */
2159 pPacket = htc_packet_dequeue(&pEndpoint->TxLookupQueue);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302160 if (qdf_unlikely(!pPacket)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002161 UNLOCK_HTC_TX(target);
Govind Singhc505cdc2017-05-16 12:15:51 +05302162 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002163 return NULL;
2164 }
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302165 if (netbuf == (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002166 UNLOCK_HTC_TX(target);
Govind Singhc505cdc2017-05-16 12:15:51 +05302167 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002168 return pPacket;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002169 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002170 HTC_PACKET_ENQUEUE(&lookupQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002171
2172 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002173 * Move TX lookup queue to temp queue because most of packets that are
2174 * not index 0 are not top 10 packets.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002175 */
2176 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&lookupQueue,
2177 &pEndpoint->TxLookupQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002178
2179 ITERATE_OVER_LIST_ALLOW_REMOVE(&lookupQueue.QueueHead, pPacket,
2180 HTC_PACKET, ListLink) {
2181
Jeff Johnson5a6cc792019-03-18 09:47:18 -07002182 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002183 pFoundPacket = pPacket;
2184 break;
2185 }
2186 /* check for removal */
2187 if (netbuf ==
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302188 (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002189 /* found it */
2190 HTC_PACKET_REMOVE(&lookupQueue, pPacket);
2191 pFoundPacket = pPacket;
2192 break;
2193 }
2194
2195 }
2196 ITERATE_END;
2197
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002198 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxLookupQueue,
2199 &lookupQueue);
2200 UNLOCK_HTC_TX(target);
Govind Singhc505cdc2017-05-16 12:15:51 +05302201 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002202
2203 return pFoundPacket;
2204}
2205
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002206/**
2207 * htc_tx_completion_handler() - htc tx completion handler
2208 * @Context: pointer to HTC_TARGET structure
2209 * @netbuf: pointer to netbuf for which completion handler is being called
2210 * @EpID: end point Id on which the packet was sent
2211 * @toeplitz_hash_result: toeplitz hash result
2212 *
2213 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
2214 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302215QDF_STATUS htc_tx_completion_handler(void *Context,
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05302216 qdf_nbuf_t netbuf, unsigned int EpID,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002217 uint32_t toeplitz_hash_result)
2218{
2219 HTC_TARGET *target = (HTC_TARGET *) Context;
2220 HTC_ENDPOINT *pEndpoint;
2221 HTC_PACKET *pPacket;
2222#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302223 HTC_ENDPOINT_ID eid[DATA_EP_SIZE] = { ENDPOINT_5, ENDPOINT_4,
2224 ENDPOINT_2, ENDPOINT_3 };
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002225 int epidIdx;
Yue Mab16cf302016-03-08 18:30:25 -08002226 uint16_t resourcesThresh[DATA_EP_SIZE]; /* urb resources */
2227 uint16_t resources;
2228 uint16_t resourcesMax;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002229#endif
2230
Houston Hoffman29573d92015-10-20 17:49:44 -07002231 pEndpoint = &target->endpoint[EpID];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002232 target->TX_comp_cnt++;
2233
2234 do {
2235 pPacket = htc_lookup_tx_packet(target, pEndpoint, netbuf);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07002236 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002237 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2238 ("HTC TX lookup failed!\n"));
2239 /* may have already been flushed and freed */
2240 netbuf = NULL;
2241 break;
2242 }
Houston Hoffmanc5141b02015-11-18 02:36:30 -08002243 if (pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_AUTO_PM)
2244 hif_pm_runtime_put(target->hif_dev);
2245
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002246 if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) {
2247 HTC_PACKET *pPacketTemp;
2248 HTC_PACKET_QUEUE *pQueueSave =
2249 (HTC_PACKET_QUEUE *) pPacket->pContext;
2250 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQueueSave,
2251 pPacketTemp) {
Rakesh Pillai13146452017-06-22 12:52:31 +05302252 pPacket->Status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002253 send_packet_completion(target, pPacketTemp);
2254 }
2255 HTC_PACKET_QUEUE_ITERATE_END;
2256 free_htc_bundle_packet(target, pPacket);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002257
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002258 if (hif_get_bus_type(target->hif_dev) ==
2259 QDF_BUS_TYPE_USB) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002260 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint))
2261 htc_try_send(target, pEndpoint, NULL);
2262 }
2263
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302264 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002265 }
2266 /* will be giving this buffer back to upper layers */
2267 netbuf = NULL;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302268 pPacket->Status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002269 send_packet_completion(target, pPacket);
2270
2271 } while (false);
2272
2273 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002274 /* note: when using TX credit flow, the re-checking of queues
2275 * happens when credits flow back from the target. In the non-TX
2276 * credit case, we recheck after the packet completes
2277 */
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05302278 if ((qdf_atomic_read(&pEndpoint->TxProcessCount) == 0) ||
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05302279 (!pEndpoint->async_update)) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05302280 htc_try_send(target, pEndpoint, NULL);
2281 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002282 }
2283
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302284 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002285}
2286
Poddar, Siddarthdf030092016-04-28 11:41:57 +05302287#ifdef WLAN_FEATURE_FASTPATH
Houston Hoffman93481862016-05-05 18:49:59 -07002288/**
2289 * htc_ctrl_msg_cmpl(): checks for tx completion for the endpoint specified
2290 * @HTC_HANDLE : pointer to the htc target context
2291 * @htc_ep_id : end point id
2292 *
2293 * checks HTC tx completion
2294 *
2295 * Return: none
2296 */
2297void htc_ctrl_msg_cmpl(HTC_HANDLE htc_pdev, HTC_ENDPOINT_ID htc_ep_id)
2298{
2299 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_pdev);
2300 HTC_ENDPOINT *pendpoint = &target->endpoint[htc_ep_id];
2301
2302 htc_send_complete_check(pendpoint, 1);
2303}
Pratik Gandhidc82a772018-01-30 18:57:05 +05302304qdf_export_symbol(htc_ctrl_msg_cmpl);
Houston Hoffman93481862016-05-05 18:49:59 -07002305#endif
2306
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002307/* callback when TX resources become available */
Yue Mab16cf302016-03-08 18:30:25 -08002308void htc_tx_resource_avail_handler(void *context, uint8_t pipeID)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002309{
2310 int i;
2311 HTC_TARGET *target = (HTC_TARGET *) context;
2312 HTC_ENDPOINT *pEndpoint = NULL;
2313
2314 for (i = 0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -07002315 pEndpoint = &target->endpoint[i];
Houston Hoffman4f2f4592015-10-20 18:00:29 -07002316 if (pEndpoint->service_id != 0) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002317 if (pEndpoint->UL_PipeID == pipeID)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002318 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002319 }
2320 }
2321
2322 if (i >= ENDPOINT_MAX) {
2323 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2324 ("Invalid pipe indicated for TX resource avail : %d!\n",
2325 pipeID));
2326 return;
2327 }
2328
2329 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002330 ("HIF indicated more resources for pipe:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002331 pipeID));
2332
2333 htc_try_send(target, pEndpoint, NULL);
2334}
2335
Yue Maec9e71c2016-02-26 18:52:20 -08002336#ifdef FEATURE_RUNTIME_PM
Houston Hoffman47e387b2015-10-20 17:04:42 -07002337/**
2338 * htc_kick_queues(): resumes tx transactions of suspended endpoints
2339 * @context: pointer to the htc target context
2340 *
Jeff Johnson4b253f02018-05-12 11:34:43 -07002341 * Iterates through the enpoints and provides a context to empty queues
Houston Hoffman47e387b2015-10-20 17:04:42 -07002342 * int the hif layer when they are stalled due to runtime suspend.
2343 *
2344 * Return: none
2345 */
2346void htc_kick_queues(void *context)
2347{
2348 int i;
2349 HTC_TARGET *target = (HTC_TARGET *)context;
2350 HTC_ENDPOINT *endpoint = NULL;
2351
2352 for (i = 0; i < ENDPOINT_MAX; i++) {
2353 endpoint = &target->endpoint[i];
2354
2355 if (endpoint->service_id == 0)
2356 continue;
2357
2358 if (endpoint->EpCallBacks.ep_resume_tx_queue)
2359 endpoint->EpCallBacks.ep_resume_tx_queue(
2360 endpoint->EpCallBacks.pContext);
2361
2362 htc_try_send(target, endpoint, NULL);
2363 }
Yue Ma9c6f84d2017-02-17 10:45:55 -08002364
2365 hif_fastpath_resume(target->hif_dev);
Houston Hoffman47e387b2015-10-20 17:04:42 -07002366}
Yue Maec9e71c2016-02-26 18:52:20 -08002367#endif
Houston Hoffman47e387b2015-10-20 17:04:42 -07002368
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002369/* flush endpoint TX queue */
2370void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint,
2371 HTC_TX_TAG Tag)
2372{
2373 HTC_PACKET *pPacket;
2374
2375 LOCK_HTC_TX(target);
2376 while (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) {
2377 pPacket = htc_packet_dequeue(&pEndpoint->TxQueue);
2378
2379 if (pPacket) {
2380 /* let the sender know the packet was not delivered */
Rakesh Pillai13146452017-06-22 12:52:31 +05302381 pPacket->Status = QDF_STATUS_E_CANCELED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002382 send_packet_completion(target, pPacket);
2383 }
2384 }
2385 UNLOCK_HTC_TX(target);
2386}
2387
Alok Kumar9bd81522018-05-30 13:07:13 +05302388/* flush pending entries in endpoint TX Lookup queue */
2389void htc_flush_endpoint_txlookupQ(HTC_TARGET *target,
Zhang Qianedaa3872018-07-04 20:02:53 +08002390 HTC_ENDPOINT_ID endpoint_id,
2391 bool call_ep_callback)
Alok Kumar9bd81522018-05-30 13:07:13 +05302392{
2393 HTC_PACKET *packet;
2394 HTC_ENDPOINT *endpoint;
2395
2396 endpoint = &target->endpoint[endpoint_id];
2397
2398 if (!endpoint && endpoint->service_id == 0)
2399 return;
2400
Debasis Das5e2539c2018-11-16 14:43:26 +05302401 LOCK_HTC_TX(target);
Alok Kumar9bd81522018-05-30 13:07:13 +05302402 while (HTC_PACKET_QUEUE_DEPTH(&endpoint->TxLookupQueue)) {
2403 packet = htc_packet_dequeue(&endpoint->TxLookupQueue);
2404
2405 if (packet) {
Zhang Qianedaa3872018-07-04 20:02:53 +08002406 if (call_ep_callback == true) {
2407 packet->Status = QDF_STATUS_E_CANCELED;
2408 send_packet_completion(target, packet);
2409 } else {
2410 qdf_mem_free(packet);
2411 }
Alok Kumar9bd81522018-05-30 13:07:13 +05302412 }
2413 }
Debasis Das5e2539c2018-11-16 14:43:26 +05302414 UNLOCK_HTC_TX(target);
Alok Kumar9bd81522018-05-30 13:07:13 +05302415}
2416
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002417/* HTC API to flush an endpoint's TX queue*/
2418void htc_flush_endpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint,
2419 HTC_TX_TAG Tag)
2420{
2421 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Houston Hoffman29573d92015-10-20 17:49:44 -07002422 HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002423
Houston Hoffman4f2f4592015-10-20 18:00:29 -07002424 if (pEndpoint->service_id == 0) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002425 AR_DEBUG_ASSERT(false);
2426 /* not in use.. */
2427 return;
2428 }
2429
2430 htc_flush_endpoint_tx(target, pEndpoint, Tag);
2431}
2432
2433/* HTC API to indicate activity to the credit distribution function */
2434void htc_indicate_activity_change(HTC_HANDLE HTCHandle,
Yue Mab16cf302016-03-08 18:30:25 -08002435 HTC_ENDPOINT_ID Endpoint, bool Active)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002436{
2437 /* TODO */
2438}
2439
Yue Mab16cf302016-03-08 18:30:25 -08002440bool htc_is_endpoint_active(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002441{
2442 return true;
2443}
2444
gbianb417db22016-09-30 17:01:07 +08002445void htc_set_nodrop_pkt(HTC_HANDLE HTCHandle, A_BOOL isNodropPkt)
2446{
2447 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002448
gbianb417db22016-09-30 17:01:07 +08002449 target->is_nodrop_pkt = isNodropPkt;
2450}
2451
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05302452void htc_enable_hdr_length_check(HTC_HANDLE htc_hdl, bool htc_hdr_length_check)
2453{
2454 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl);
2455
2456 target->htc_hdr_length_check = htc_hdr_length_check;
2457}
2458
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002459/**
2460 * htc_process_credit_rpt() - process credit report, call distribution function
2461 * @target: pointer to HTC_TARGET
2462 * @pRpt: pointer to HTC_CREDIT_REPORT
2463 * @NumEntries: number of entries in credit report
2464 * @FromEndpoint: endpoint for which credit report is received
2465 *
2466 * Return: A_OK for success or an appropriate A_STATUS error
2467 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002468void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt,
2469 int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
2470{
2471 int i;
2472 HTC_ENDPOINT *pEndpoint;
2473 int totalCredits = 0;
Yue Mab16cf302016-03-08 18:30:25 -08002474 uint8_t rpt_credits, rpt_ep_id;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002475
2476 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002477 ("+htc_process_credit_rpt, Credit Report Entries:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002478 NumEntries));
2479
2480 /* lock out TX while we update credits */
2481 LOCK_HTC_TX(target);
2482
2483 for (i = 0; i < NumEntries; i++, pRpt++) {
2484
2485 rpt_ep_id = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, ENDPOINTID);
2486
2487 if (rpt_ep_id >= ENDPOINT_MAX) {
2488 AR_DEBUG_ASSERT(false);
2489 break;
2490 }
2491
2492 rpt_credits = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, CREDITS);
2493
Houston Hoffman29573d92015-10-20 17:49:44 -07002494 pEndpoint = &target->endpoint[rpt_ep_id];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002495#if DEBUG_CREDIT
2496 if (ep_debug_mask & (1 << pEndpoint->Id)) {
2497 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2498 (" <HTC> Increase EP%d %d + %d = %d credits\n",
2499 rpt_ep_id, pEndpoint->TxCredits,
2500 rpt_credits,
2501 pEndpoint->TxCredits + rpt_credits));
2502 }
2503#endif
2504
2505#ifdef HTC_EP_STAT_PROFILING
2506
2507 INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
2508 INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, rpt_credits);
2509
2510 if (FromEndpoint == rpt_ep_id) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002511 /* this credit report arrived on the same endpoint
2512 * indicating it arrived in an RX packet
2513 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002514 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx,
2515 rpt_credits);
2516 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
2517 } else if (FromEndpoint == ENDPOINT_0) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002518 /* this credit arrived on endpoint 0 as a NULL msg */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002519 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0,
2520 rpt_credits);
2521 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
2522 } else {
2523 /* arrived on another endpoint */
2524 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther,
2525 rpt_credits);
2526 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
2527 }
2528
2529#endif
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002530
Houston Hoffman4f2f4592015-10-20 18:00:29 -07002531 if (pEndpoint->service_id == WMI_CONTROL_SVC) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002532 htc_credit_record(HTC_PROCESS_CREDIT_REPORT,
Dustin Brownf74576c2018-03-12 14:22:51 -07002533 pEndpoint->TxCredits + rpt_credits,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002534 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->
Rachit Kankane1bc11492018-01-24 18:48:17 +05302535 TxQueue));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002536 }
Dustin Brownf74576c2018-03-12 14:22:51 -07002537
2538 pEndpoint->TxCredits += rpt_credits;
2539
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002540 if (pEndpoint->TxCredits
2541 && HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) {
2542 UNLOCK_HTC_TX(target);
2543#ifdef ATH_11AC_TXCOMPACT
2544 htc_try_send(target, pEndpoint, NULL);
2545#else
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002546 if (pEndpoint->service_id == HTT_DATA_MSG_SVC)
Himanshu Batra032d3522019-07-10 12:36:06 +05302547 htc_send_data_pkt((HTC_HANDLE)target, NULL, 0);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002548 else
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002549 htc_try_send(target, pEndpoint, NULL);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002550#endif
2551 LOCK_HTC_TX(target);
2552 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002553 totalCredits += rpt_credits;
2554 }
2555
2556 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002557 (" Report indicated %d credits to distribute\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002558 totalCredits));
2559
2560 UNLOCK_HTC_TX(target);
2561
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002562 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_process_credit_rpt\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002563}
2564
2565/* function to fetch stats from htc layer*/
2566struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE HTCHandle)
2567{
2568 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
2569
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302570 return &(target->htc_pkt_stats);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002571}