blob: 57106b7148322f06b7667f868c29d502b6d8a827 [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
Houston Hoffmanadc31472017-03-14 16:15:29 -070074int htc_get_tx_queue_depth(HTC_HANDLE *htc_handle, HTC_ENDPOINT_ID endpoint_id)
75{
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 }
115
Dustin Brownbc9718f2017-12-11 12:15:27 -0800116 qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800117}
118
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800119static void send_packet_completion(HTC_TARGET *target, HTC_PACKET *pPacket)
120{
Houston Hoffman29573d92015-10-20 17:49:44 -0700121 HTC_ENDPOINT *pEndpoint = &target->endpoint[pPacket->Endpoint];
Yun Park88e0b952017-10-11 23:08:34 -0700122 HTC_EP_SEND_PKT_COMPLETE EpTxComplete;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800123
124 restore_tx_packet(target, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800125
126 /* do completion */
Yun Park88e0b952017-10-11 23:08:34 -0700127 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
128 ("HTC calling ep %d send complete callback on packet %pK\n",
129 pEndpoint->Id, pPacket));
130
131 EpTxComplete = pEndpoint->EpCallBacks.EpTxComplete;
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700132 if (EpTxComplete)
Yun Park88e0b952017-10-11 23:08:34 -0700133 EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket);
134 else
135 qdf_nbuf_free(pPacket->pPktContext);
136
137
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800138}
139
140void htc_send_complete_check_cleanup(void *context)
141{
142 HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *) context;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700143
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800144 htc_send_complete_check(pEndpoint, 1);
145}
146
147HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target)
148{
149 HTC_PACKET *pPacket;
150 HTC_PACKET_QUEUE *pQueueSave;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530151 qdf_nbuf_t netbuf;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700152
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800153 LOCK_HTC_TX(target);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700154 if (!target->pBundleFreeList) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800155 UNLOCK_HTC_TX(target);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530156 netbuf = qdf_nbuf_alloc(NULL,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800157 target->MaxMsgsPerHTCBundle *
158 target->TargetCreditSize, 0, 4, false);
159 AR_DEBUG_ASSERT(netbuf);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700160 if (!netbuf)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800161 return NULL;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530162 pPacket = qdf_mem_malloc(sizeof(HTC_PACKET));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800163 AR_DEBUG_ASSERT(pPacket);
164 if (!pPacket) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530165 qdf_nbuf_free(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800166 return NULL;
167 }
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530168 pQueueSave = qdf_mem_malloc(sizeof(HTC_PACKET_QUEUE));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800169 AR_DEBUG_ASSERT(pQueueSave);
170 if (!pQueueSave) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530171 qdf_nbuf_free(netbuf);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530172 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800173 return NULL;
174 }
175 INIT_HTC_PACKET_QUEUE(pQueueSave);
176 pPacket->pContext = pQueueSave;
177 SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530178 pPacket->pBuffer = qdf_nbuf_data(netbuf);
179 pPacket->BufferLength = qdf_nbuf_len(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800180
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700181 /* store the original head room so that we can restore this
182 * when we "free" the packet.
183 * free packet puts the packet back on the free list
184 */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530185 pPacket->netbufOrigHeadRoom = qdf_nbuf_headroom(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800186 return pPacket;
187 }
188 /* already done malloc - restore from free list */
189 pPacket = target->pBundleFreeList;
190 AR_DEBUG_ASSERT(pPacket);
191 if (!pPacket) {
192 UNLOCK_HTC_TX(target);
193 return NULL;
194 }
195 target->pBundleFreeList = (HTC_PACKET *) pPacket->ListLink.pNext;
196 UNLOCK_HTC_TX(target);
197 pPacket->ListLink.pNext = NULL;
198
199 return pPacket;
200}
201
202void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
203{
Yue Mab16cf302016-03-08 18:30:25 -0800204 uint32_t curentHeadRoom;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530205 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800206 HTC_PACKET_QUEUE *pQueueSave;
207
208 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
209 AR_DEBUG_ASSERT(netbuf);
210 if (!netbuf) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700211 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
212 ("\n%s: Invalid netbuf in HTC Packet\n",
213 __func__));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800214 return;
215 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700216 /* HIF adds data to the headroom section of the nbuf, restore thei
217 * original size. If this is not done, headroom keeps shrinking with
218 * every HIF send and eventually HIF ends up doing another malloc big
219 * enough to store the data + its header
220 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800221
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530222 curentHeadRoom = qdf_nbuf_headroom(netbuf);
223 qdf_nbuf_pull_head(netbuf,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800224 pPacket->netbufOrigHeadRoom - curentHeadRoom);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530225 qdf_nbuf_trim_tail(netbuf, qdf_nbuf_len(netbuf));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800226
227 /* restore the pBuffer pointer. HIF changes this */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530228 pPacket->pBuffer = qdf_nbuf_data(netbuf);
229 pPacket->BufferLength = qdf_nbuf_len(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800230
231 /* restore queue */
232 pQueueSave = (HTC_PACKET_QUEUE *) pPacket->pContext;
jitiphilfcc24882018-05-11 16:14:38 +0530233 if (qdf_unlikely(!pQueueSave)) {
234 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
235 ("\n%s: Invalid pQueueSave in HTC Packet\n",
236 __func__));
237 AR_DEBUG_ASSERT(pQueueSave);
238 } else
239 INIT_HTC_PACKET_QUEUE(pQueueSave);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800240
241 LOCK_HTC_TX(target);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700242 if (!target->pBundleFreeList) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800243 target->pBundleFreeList = pPacket;
244 pPacket->ListLink.pNext = NULL;
245 } else {
246 pPacket->ListLink.pNext = (DL_LIST *) target->pBundleFreeList;
247 target->pBundleFreeList = pPacket;
248 }
249 UNLOCK_HTC_TX(target);
250}
251
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530252#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
253
254/**
255 * htc_send_update_tx_bundle_stats() - update tx bundle stats depends
256 * on max bundle size
257 * @target: hif context
258 * @data_len: tx data len
259 * @TxCreditSize: endpoint tx credit size
260 *
261 * Return: None
262 */
263static inline void
264htc_send_update_tx_bundle_stats(HTC_TARGET *target,
265 qdf_size_t data_len,
266 int TxCreditSize)
267{
268 if ((data_len / TxCreditSize) <= HTC_MAX_MSG_PER_BUNDLE_TX)
269 target->tx_bundle_stats[(data_len / TxCreditSize) - 1]++;
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530270}
271
272/**
273 * htc_issue_tx_bundle_stats_inc() - increment in tx bundle stats
274 * on max bundle size
275 * @target: hif context
276 *
277 * Return: None
278 */
279static inline void
280htc_issue_tx_bundle_stats_inc(HTC_TARGET *target)
281{
282 target->tx_bundle_stats[0]++;
283}
284#else
285
286static inline void
287htc_send_update_tx_bundle_stats(HTC_TARGET *target,
288 qdf_size_t data_len,
289 int TxCreditSize)
290{
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530291}
292
293static inline void
294htc_issue_tx_bundle_stats_inc(HTC_TARGET *target)
295{
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530296}
297#endif
298
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800299#if defined(HIF_USB) || defined(HIF_SDIO)
300#ifdef ENABLE_BUNDLE_TX
Rakesh Pillai13146452017-06-22 12:52:31 +0530301static QDF_STATUS htc_send_bundled_netbuf(HTC_TARGET *target,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800302 HTC_ENDPOINT *pEndpoint,
303 unsigned char *pBundleBuffer,
304 HTC_PACKET *pPacketTx)
305{
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530306 qdf_size_t data_len;
Rakesh Pillai13146452017-06-22 12:52:31 +0530307 QDF_STATUS status;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530308 qdf_nbuf_t bundleBuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800309 uint32_t data_attr = 0;
310
311 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530312 data_len = pBundleBuffer - qdf_nbuf_data(bundleBuf);
313 qdf_nbuf_put_tail(bundleBuf, data_len);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800314 SET_HTC_PACKET_INFO_TX(pPacketTx,
315 target,
316 pBundleBuffer,
317 data_len,
318 pEndpoint->Id, HTC_TX_PACKET_TAG_BUNDLED);
319 LOCK_HTC_TX(target);
320 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacketTx);
tfyu052b32a2017-09-20 18:48:33 +0800321 pEndpoint->ul_outstanding_cnt++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800322 UNLOCK_HTC_TX(target);
323#if DEBUG_BUNDLE
Aditya Sathish648ce112018-07-02 16:41:39 +0530324 qdf_print(" Send bundle EP%d buffer size:0x%x, total:0x%x, count:%d.",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800325 pEndpoint->Id,
326 pEndpoint->TxCreditSize,
327 data_len, data_len / pEndpoint->TxCreditSize);
328#endif
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530329
330 htc_send_update_tx_bundle_stats(target, data_len,
331 pEndpoint->TxCreditSize);
332
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800333 status = hif_send_head(target->hif_dev,
334 pEndpoint->UL_PipeID,
Poddar, Siddarth416b7062016-04-29 11:02:13 +0530335 pEndpoint->Id, data_len,
336 bundleBuf, data_attr);
Rakesh Pillai13146452017-06-22 12:52:31 +0530337 if (status != QDF_STATUS_SUCCESS) {
Aditya Sathish648ce112018-07-02 16:41:39 +0530338 qdf_print("%s:hif_send_head failed(len=%zu).", __func__,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800339 data_len);
340 }
341 return status;
342}
343
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700344/**
345 * htc_issue_packets_bundle() - HTC function to send bundle packets from a queue
346 * @target: HTC target on which packets need to be sent
347 * @pEndpoint: logical endpoint on which packets needs to be sent
348 * @pPktQueue: HTC packet queue containing the list of packets to be sent
349 *
350 * Return: void
351 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800352static void htc_issue_packets_bundle(HTC_TARGET *target,
353 HTC_ENDPOINT *pEndpoint,
354 HTC_PACKET_QUEUE *pPktQueue)
355{
356 int i, frag_count, nbytes;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530357 qdf_nbuf_t netbuf, bundleBuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800358 unsigned char *pBundleBuffer = NULL;
359 HTC_PACKET *pPacket = NULL, *pPacketTx = NULL;
360 HTC_FRAME_HDR *pHtcHdr;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700361 int last_credit_pad = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800362 int creditPad, creditRemainder, transferLength, bundlesSpaceRemaining =
363 0;
364 HTC_PACKET_QUEUE *pQueueSave = NULL;
365
366 bundlesSpaceRemaining =
367 target->MaxMsgsPerHTCBundle * pEndpoint->TxCreditSize;
368 pPacketTx = allocate_htc_bundle_packet(target);
369 if (!pPacketTx) {
370 /* good time to panic */
371 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700372 ("allocate_htc_bundle_packet failed\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800373 AR_DEBUG_ASSERT(false);
374 return;
375 }
376 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530377 pBundleBuffer = qdf_nbuf_data(bundleBuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800378 pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext;
379 while (1) {
380 pPacket = htc_packet_dequeue(pPktQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700381 if (!pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800382 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800383 creditPad = 0;
384 transferLength = pPacket->ActualLength + HTC_HDR_LENGTH;
385 creditRemainder = transferLength % pEndpoint->TxCreditSize;
386 if (creditRemainder != 0) {
387 if (transferLength < pEndpoint->TxCreditSize) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700388 creditPad = pEndpoint->TxCreditSize -
389 transferLength;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800390 } else {
391 creditPad = creditRemainder;
392 }
393 transferLength += creditPad;
394 }
395
396 if (bundlesSpaceRemaining < transferLength) {
397 /* send out previous buffer */
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700398 htc_send_bundled_netbuf(target, pEndpoint,
399 pBundleBuffer - last_credit_pad,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800400 pPacketTx);
tfyu60c2c982017-06-09 15:50:03 +0800401 /* One packet has been dequeued from sending queue when enter
402 * this loop, so need to add 1 back for this checking.
403 */
404 if ((HTC_PACKET_QUEUE_DEPTH(pPktQueue) + 1) <
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800405 HTC_MIN_MSG_PER_BUNDLE) {
tfyu60c2c982017-06-09 15:50:03 +0800406 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800407 return;
408 }
409 bundlesSpaceRemaining =
410 target->MaxMsgsPerHTCBundle *
411 pEndpoint->TxCreditSize;
412 pPacketTx = allocate_htc_bundle_packet(target);
413 if (!pPacketTx) {
tfyu60c2c982017-06-09 15:50:03 +0800414 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800415 /* good time to panic */
416 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700417 ("allocate_htc_bundle_packet failed\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800418 AR_DEBUG_ASSERT(false);
419 return;
420 }
421 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530422 pBundleBuffer = qdf_nbuf_data(bundleBuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800423 pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext;
424 }
425
426 bundlesSpaceRemaining -= transferLength;
427 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700428
429 if (hif_get_bus_type(target->hif_dev) != QDF_BUS_TYPE_USB) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700430 pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(
431 netbuf, 0);
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700432 HTC_WRITE32(pHtcHdr,
433 SM(pPacket->ActualLength,
434 HTC_FRAME_HDR_PAYLOADLEN) |
435 SM(pPacket->PktInfo.AsTx.SendFlags |
436 HTC_FLAGS_SEND_BUNDLE,
437 HTC_FRAME_HDR_FLAGS) |
438 SM(pPacket->Endpoint,
439 HTC_FRAME_HDR_ENDPOINTID));
440 HTC_WRITE32((uint32_t *) pHtcHdr + 1,
441 SM(pPacket->PktInfo.AsTx.SeqNo,
442 HTC_FRAME_HDR_CONTROLBYTES1) | SM(creditPad,
443 HTC_FRAME_HDR_RESERVED));
444 pHtcHdr->reserved = creditPad;
445 }
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530446 frag_count = qdf_nbuf_get_num_frags(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800447 nbytes = pPacket->ActualLength + HTC_HDR_LENGTH;
448 for (i = 0; i < frag_count && nbytes > 0; i++) {
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530449 int frag_len = qdf_nbuf_get_frag_len(netbuf, i);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800450 unsigned char *frag_addr =
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530451 qdf_nbuf_get_frag_vaddr(netbuf, i);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700452 if (frag_len > nbytes)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800453 frag_len = nbytes;
Yue Mab16cf302016-03-08 18:30:25 -0800454 qdf_mem_copy(pBundleBuffer, frag_addr, frag_len);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800455 nbytes -= frag_len;
456 pBundleBuffer += frag_len;
457 }
458 HTC_PACKET_ENQUEUE(pQueueSave, pPacket);
459 pBundleBuffer += creditPad;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700460
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700461 /* last one can't be packed. */
462 if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700463 last_credit_pad = creditPad;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800464 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700465 /* send out remaining buffer */
466 if (pBundleBuffer != qdf_nbuf_data(bundleBuf))
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700467 htc_send_bundled_netbuf(target, pEndpoint,
468 pBundleBuffer - last_credit_pad,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800469 pPacketTx);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700470 else
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800471 free_htc_bundle_packet(target, pPacketTx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800472}
473#endif /* ENABLE_BUNDLE_TX */
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700474#else
475static void htc_issue_packets_bundle(HTC_TARGET *target,
476 HTC_ENDPOINT *pEndpoint,
477 HTC_PACKET_QUEUE *pPktQueue)
478{
479}
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800480#endif
481
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700482/**
483 * htc_issue_packets() - HTC function to send packets from a queue
484 * @target: HTC target on which packets need to be sent
485 * @pEndpoint: logical endpoint on which packets needs to be sent
486 * @pPktQueue: HTC packet queue containing the list of packets to be sent
487 *
488 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
489 */
Rakesh Pillai13146452017-06-22 12:52:31 +0530490static QDF_STATUS htc_issue_packets(HTC_TARGET *target,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800491 HTC_ENDPOINT *pEndpoint,
492 HTC_PACKET_QUEUE *pPktQueue)
493{
Rakesh Pillai13146452017-06-22 12:52:31 +0530494 QDF_STATUS status = QDF_STATUS_SUCCESS;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530495 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800496 HTC_PACKET *pPacket = NULL;
497 uint16_t payloadLen;
498 HTC_FRAME_HDR *pHtcHdr;
499 uint32_t data_attr = 0;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700500 enum qdf_bus_type bus_type;
Himanshu Agarwalfa594d92017-04-04 12:36:33 +0530501 QDF_STATUS ret;
wadesong4b3f37d2018-01-25 16:08:05 +0800502 bool rt_put = false;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700503
504 bus_type = hif_get_bus_type(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800505
506 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700507 ("+htc_issue_packets: Queue: %pK, Pkts %d\n", pPktQueue,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800508 HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
509 while (true) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700510 if (HTC_TX_BUNDLE_ENABLED(target) &&
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800511 HTC_PACKET_QUEUE_DEPTH(pPktQueue) >=
512 HTC_MIN_MSG_PER_BUNDLE) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700513 switch (bus_type) {
514 case QDF_BUS_TYPE_SDIO:
515 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint))
516 break;
517 case QDF_BUS_TYPE_USB:
518 htc_issue_packets_bundle(target,
519 pEndpoint,
520 pPktQueue);
521 break;
522 default:
523 break;
524 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800525 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700526 /* if not bundling or there was a packet that could not be
527 * placed in a bundle, and send it by normal way
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800528 */
529 pPacket = htc_packet_dequeue(pPktQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700530 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800531 /* local queue is fully drained */
532 break;
533 }
534
535 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
536 AR_DEBUG_ASSERT(netbuf);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700537 /* Non-credit enabled endpoints have been mapped and setup by
538 * now, so no need to revisit the HTC headers
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800539 */
540 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
541
542 payloadLen = pPacket->ActualLength;
543 /* setup HTC frame header */
544
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530545 pHtcHdr = (HTC_FRAME_HDR *)
546 qdf_nbuf_get_frag_vaddr(netbuf, 0);
jitiphil4a8f66f2018-05-31 13:15:20 +0530547 if (qdf_unlikely(!pHtcHdr)) {
548 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
549 ("%s Invalid pHtcHdr\n",
550 __func__));
551 AR_DEBUG_ASSERT(pHtcHdr);
552 status = QDF_STATUS_E_FAILURE;
553 break;
554 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800555
556 HTC_WRITE32(pHtcHdr,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700557 SM(payloadLen,
558 HTC_FRAME_HDR_PAYLOADLEN) |
559 SM(pPacket->PktInfo.AsTx.SendFlags,
560 HTC_FRAME_HDR_FLAGS) |
561 SM(pPacket->Endpoint,
562 HTC_FRAME_HDR_ENDPOINTID));
Yue Mab16cf302016-03-08 18:30:25 -0800563 HTC_WRITE32(((uint32_t *) pHtcHdr) + 1,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800564 SM(pPacket->PktInfo.AsTx.SeqNo,
565 HTC_FRAME_HDR_CONTROLBYTES1));
566
567 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700568 * Now that the HTC frame header has been added, the
569 * netbuf can be mapped. This only applies to non-data
570 * frames, since data frames were already mapped as they
Dustin Brownbc9718f2017-12-11 12:15:27 -0800571 * entered into the driver.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800572 */
Dustin Brownbc9718f2017-12-11 12:15:27 -0800573 pPacket->PktInfo.AsTx.Flags |=
574 HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
575
576 ret = qdf_nbuf_map(target->osdev,
577 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
578 QDF_DMA_TO_DEVICE);
579 if (ret != QDF_STATUS_SUCCESS) {
580 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
581 ("%s nbuf Map Fail Endpnt %pK\n",
582 __func__, pEndpoint));
583 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
584 status = QDF_STATUS_E_FAILURE;
585 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800586 }
587 }
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530588
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530589 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530590 LOCK_HTC_TX(target);
591 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800592 /* store in look up queue to match completions */
593 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket);
594 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
595 pEndpoint->ul_outstanding_cnt++;
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530596 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530597 UNLOCK_HTC_TX(target);
598 hif_send_complete_check(target->hif_dev,
599 pEndpoint->UL_PipeID, false);
600 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800601
Himanshu Agarwal974d0a52017-03-08 21:13:51 +0530602 htc_packet_set_magic_cookie(pPacket, HTC_PACKET_MAGIC_COOKIE);
wadesong4b3f37d2018-01-25 16:08:05 +0800603 /*
604 * For HTT messages without a response from fw,
605 * do the runtime put here.
606 * otherwise runtime put will be done when the fw response comes
607 */
608 if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_RUNTIME_PUT)
609 rt_put = true;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800610#if DEBUG_BUNDLE
Aditya Sathish648ce112018-07-02 16:41:39 +0530611 qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800612 pEndpoint->Id,
613 pEndpoint->TxCreditSize,
614 HTC_HDR_LENGTH + pPacket->ActualLength);
615#endif
wadesong4b3f37d2018-01-25 16:08:05 +0800616 status = hif_send_head(target->hif_dev,
617 pEndpoint->UL_PipeID, pEndpoint->Id,
618 HTC_HDR_LENGTH + pPacket->ActualLength,
619 netbuf, data_attr);
620
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530621 htc_issue_tx_bundle_stats_inc(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800622
623 target->ce_send_cnt++;
624
Rakesh Pillai13146452017-06-22 12:52:31 +0530625 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
626 if (status != QDF_STATUS_E_RESOURCES) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700627 /* TODO : if more than 1 endpoint maps to the
628 * same PipeID it is possible to run out of
629 * resources in the HIF layer. Don't emit the
630 * error
631 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800632 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700633 ("hif_send Failed status:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800634 status));
635 }
Dustin Brown942f9392018-06-25 14:34:45 -0700636
637 /* only unmap if we mapped in this function */
Nirav Shah0811d822019-04-13 22:43:29 +0530638 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
Dustin Brown942f9392018-06-25 14:34:45 -0700639 qdf_nbuf_unmap(target->osdev,
640 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
641 QDF_DMA_TO_DEVICE);
Nirav Shah0811d822019-04-13 22:43:29 +0530642 pPacket->PktInfo.AsTx.Flags &=
643 ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
644 }
Dustin Brown942f9392018-06-25 14:34:45 -0700645
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530646 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530647 LOCK_HTC_TX(target);
648 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800649 target->ce_send_cnt--;
650 pEndpoint->ul_outstanding_cnt--;
651 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket);
Himanshu Agarwal974d0a52017-03-08 21:13:51 +0530652 htc_packet_set_magic_cookie(pPacket, 0);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800653 /* put it back into the callers queue */
654 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
Frank Liud2cc13e2018-12-06 16:03:26 +0800655 /* reclaim credits */
656 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,
657 pPacket) {
658 pEndpoint->TxCredits +=
659 pPacket->PktInfo.AsTx.CreditsUsed;
660 } HTC_PACKET_QUEUE_ITERATE_END;
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +0530661 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +0530662 UNLOCK_HTC_TX(target);
663 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800664 break;
665 }
wadesong4b3f37d2018-01-25 16:08:05 +0800666 if (rt_put) {
Houston Hoffman1dd22762015-11-10 11:35:49 -0800667 hif_pm_runtime_put(target->hif_dev);
wadesong4b3f37d2018-01-25 16:08:05 +0800668 rt_put = false;
669 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800670 }
Rakesh Pillai13146452017-06-22 12:52:31 +0530671 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -0800672 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700673 ("htc_issue_packets, failed pkt:0x%pK status:%d",
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -0800674 pPacket, status));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800675 }
676
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700677 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_issue_packets\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800678
679 return status;
680}
681
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800682#ifdef FEATURE_RUNTIME_PM
683/**
Jeff Johnson4b253f02018-05-12 11:34:43 -0700684 * extract_htc_pm_packets(): move pm packets from endpoint into queue
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800685 * @endpoint: which enpoint to extract packets from
686 * @queue: a queue to store extracted packets in.
687 *
688 * remove pm packets from the endpoint's tx queue.
689 * queue them into a queue
690 */
691static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
692 HTC_PACKET_QUEUE *queue)
693{
694 HTC_PACKET *packet;
695
696 /* only WMI endpoint has power management packets */
697 if (endpoint->service_id != WMI_CONTROL_SVC)
698 return;
699
700 ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet,
701 HTC_PACKET, ListLink) {
702 if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_AUTO_PM) {
703 HTC_PACKET_REMOVE(&endpoint->TxQueue, packet);
704 HTC_PACKET_ENQUEUE(queue, packet);
705 }
706 } ITERATE_END
707}
708
709/**
710 * queue_htc_pm_packets(): queue pm packets with priority
711 * @endpoint: enpoint to queue packets to
712 * @queue: queue of pm packets to enque
713 *
714 * suspend resume packets get special treatment & priority.
715 * need to queue them at the front of the queue.
716 */
717static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
718 HTC_PACKET_QUEUE *queue)
719{
720 if (endpoint->service_id != WMI_CONTROL_SVC)
721 return;
722
723 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&endpoint->TxQueue, queue);
724}
725#else
726static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
727 HTC_PACKET_QUEUE *queue)
728{}
729
730static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
731 HTC_PACKET_QUEUE *queue)
732{}
733#endif
734
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700735/**
736 * get_htc_send_packets_credit_based() - get packets based on available credits
737 * @target: HTC target on which packets need to be sent
738 * @pEndpoint: logical endpoint on which packets needs to be sent
739 * @pQueue: HTC packet queue containing the list of packets to be sent
740 *
741 * Get HTC send packets from TX queue on an endpoint based on available credits.
742 * The function moves the packets from TX queue of the endpoint to pQueue.
743 *
744 * Return: None
745 */
Jeff Johnsonc66399a2016-10-07 13:01:33 -0700746static void get_htc_send_packets_credit_based(HTC_TARGET *target,
747 HTC_ENDPOINT *pEndpoint,
748 HTC_PACKET_QUEUE *pQueue)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800749{
750 int creditsRequired;
751 int remainder;
Yue Mab16cf302016-03-08 18:30:25 -0800752 uint8_t sendFlags;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800753 HTC_PACKET *pPacket;
754 unsigned int transferLength;
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800755 HTC_PACKET_QUEUE *tx_queue;
756 HTC_PACKET_QUEUE pm_queue;
757 bool do_pm_get = false;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800758
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700759 /*** NOTE : the TX lock is held when this function is called ***/
760 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
761 ("+get_htc_send_packets_credit_based\n"));
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800762
763 INIT_HTC_PACKET_QUEUE(&pm_queue);
764 extract_htc_pm_packets(pEndpoint, &pm_queue);
765 if (HTC_QUEUE_EMPTY(&pm_queue)) {
766 tx_queue = &pEndpoint->TxQueue;
767 do_pm_get = true;
768 } else {
769 tx_queue = &pm_queue;
770 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800771
772 /* loop until we can grab as many packets out of the queue as we can */
773 while (true) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800774 if (do_pm_get && hif_pm_runtime_get(target->hif_dev)) {
775 /* bus suspended, runtime resume issued */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530776 QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800777 break;
778 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800779
780 sendFlags = 0;
781 /* get packet at head, but don't remove it */
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800782 pPacket = htc_get_pkt_at_head(tx_queue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700783 if (!pPacket) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800784 if (do_pm_get)
785 hif_pm_runtime_put(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800786 break;
787 }
788
789 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700790 (" Got head packet:%pK , Queue Depth: %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800791 pPacket,
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800792 HTC_PACKET_QUEUE_DEPTH(tx_queue)));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800793
794 transferLength = pPacket->ActualLength + HTC_HDR_LENGTH;
795
796 if (transferLength <= pEndpoint->TxCreditSize) {
797 creditsRequired = 1;
798 } else {
799 /* figure out how many credits this message requires */
800 creditsRequired =
801 transferLength / pEndpoint->TxCreditSize;
802 remainder = transferLength % pEndpoint->TxCreditSize;
803
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700804 if (remainder)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800805 creditsRequired++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800806 }
807
808 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
809 (" Credits Required:%d Got:%d\n",
810 creditsRequired, pEndpoint->TxCredits));
811
812 if (pEndpoint->Id == ENDPOINT_0) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700813 /*
814 * endpoint 0 is special, it always has a credit and
815 * does not require credit based flow control
816 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800817 creditsRequired = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800818 } else {
819
820 if (pEndpoint->TxCredits < creditsRequired) {
821#if DEBUG_CREDIT
822 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700823 ("EP%d,No Credit now.%d < %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800824 pEndpoint->Id,
825 pEndpoint->TxCredits,
826 creditsRequired));
827#endif
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800828 if (do_pm_get)
829 hif_pm_runtime_put(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800830 break;
831 }
832
833 pEndpoint->TxCredits -= creditsRequired;
834 INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed,
835 creditsRequired);
836
837 /* check if we need credits back from the target */
838 if (pEndpoint->TxCredits <=
839 pEndpoint->TxCreditsPerMaxMsg) {
840 /* tell the target we need credits ASAP! */
841 sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700842 if (pEndpoint->service_id == WMI_CONTROL_SVC) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800843 htc_credit_record(HTC_REQUEST_CREDIT,
844 pEndpoint->TxCredits,
845 HTC_PACKET_QUEUE_DEPTH
Rachit Kankane1bc11492018-01-24 18:48:17 +0530846 (tx_queue));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800847 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800848 INC_HTC_EP_STAT(pEndpoint,
849 TxCreditLowIndications, 1);
850#if DEBUG_CREDIT
851 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
852 (" EP%d Needs Credits\n",
853 pEndpoint->Id));
854#endif
855 }
856 }
857
858 /* now we can fully dequeue */
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800859 pPacket = htc_packet_dequeue(tx_queue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800860 if (pPacket) {
861 /* save the number of credits this packet consumed */
862 pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired;
863 /* save send flags */
864 pPacket->PktInfo.AsTx.SendFlags = sendFlags;
865
866 /* queue this packet into the caller's queue */
867 HTC_PACKET_ENQUEUE(pQueue, pPacket);
868 }
869 }
870
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800871 if (!HTC_QUEUE_EMPTY(&pm_queue))
872 queue_htc_pm_packets(pEndpoint, &pm_queue);
873
874 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
875 ("-get_htc_send_packets_credit_based\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800876
877}
878
Jeff Johnsonc66399a2016-10-07 13:01:33 -0700879static void get_htc_send_packets(HTC_TARGET *target,
880 HTC_ENDPOINT *pEndpoint,
881 HTC_PACKET_QUEUE *pQueue, int Resources)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800882{
883
884 HTC_PACKET *pPacket;
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800885 HTC_PACKET_QUEUE *tx_queue;
886 HTC_PACKET_QUEUE pm_queue;
Tiger Yu054a6a42018-03-30 14:58:02 +0800887 bool do_pm_get = false;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800888
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700889 /*** NOTE : the TX lock is held when this function is called ***/
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800890 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
891 ("+get_htc_send_packets %d resources\n", Resources));
892
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800893 INIT_HTC_PACKET_QUEUE(&pm_queue);
894 extract_htc_pm_packets(pEndpoint, &pm_queue);
895 if (HTC_QUEUE_EMPTY(&pm_queue)) {
896 tx_queue = &pEndpoint->TxQueue;
897 do_pm_get = true;
898 } else {
899 tx_queue = &pm_queue;
900 }
901
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800902 /* loop until we can grab as many packets out of the queue as we can */
903 while (Resources > 0) {
904 int num_frags;
905
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800906 if (do_pm_get && hif_pm_runtime_get(target->hif_dev)) {
907 /* bus suspended, runtime resume issued */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530908 QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800909 break;
910 }
911
912 pPacket = htc_packet_dequeue(tx_queue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700913 if (!pPacket) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800914 if (do_pm_get)
915 hif_pm_runtime_put(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800916 break;
917 }
918 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700919 (" Got packet:%pK , New Queue Depth: %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800920 pPacket,
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800921 HTC_PACKET_QUEUE_DEPTH(tx_queue)));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800922 /* For non-credit path the sequence number is already embedded
923 * in the constructed HTC header
924 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800925 pPacket->PktInfo.AsTx.SendFlags = 0;
926 pPacket->PktInfo.AsTx.CreditsUsed = 0;
927 /* queue this packet into the caller's queue */
928 HTC_PACKET_ENQUEUE(pQueue, pPacket);
929
930 /*
931 * FIX THIS:
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530932 * For now, avoid calling qdf_nbuf_get_num_frags before calling
933 * qdf_nbuf_map, because the MacOS version of qdf_nbuf_t doesn't
934 * support qdf_nbuf_get_num_frags until after qdf_nbuf_map has
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800935 * been done.
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700936 * Assume that the non-data netbufs, i.e. WMI message netbufs,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800937 * consist of a single fragment.
938 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700939 /* WMI messages are in a single-fragment network buf */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800940 num_frags =
941 (pPacket->PktInfo.AsTx.
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700942 Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) ? 1 :
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530943 qdf_nbuf_get_num_frags(GET_HTC_PACKET_NET_BUF_CONTEXT
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800944 (pPacket));
945 Resources -= num_frags;
946 }
947
Houston Hoffmanc5141b02015-11-18 02:36:30 -0800948 if (!HTC_QUEUE_EMPTY(&pm_queue))
949 queue_htc_pm_packets(pEndpoint, &pm_queue);
950
951 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800952
953}
954
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700955/**
956 * htc_try_send() - Send packets in a queue on an endpoint
957 * @target: HTC target on which packets need to be sent
958 * @pEndpoint: logical endpoint on which packets needs to be sent
959 * @pCallersSendQueue: packet queue containing the list of packets to be sent
960 *
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700961 * Return: enum HTC_SEND_QUEUE_RESULT indicates whether the packet was queued to
962 * be sent or the packet should be dropped by the upper layer
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700963 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700964static enum HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800965 HTC_ENDPOINT *pEndpoint,
966 HTC_PACKET_QUEUE *pCallersSendQueue)
967{
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700968 /* temp queue to hold packets at various stages */
969 HTC_PACKET_QUEUE sendQueue;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800970 HTC_PACKET *pPacket;
971 int tx_resources;
972 int overflow;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700973 enum HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800974
Jeff Johnsona79b1112017-09-18 10:12:02 -0700975 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+htc_try_send (Queue:%pK Depth:%d)\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800976 pCallersSendQueue,
977 (pCallersSendQueue ==
978 NULL) ? 0 :
979 HTC_PACKET_QUEUE_DEPTH
980 (pCallersSendQueue)));
981
982 /* init the local send queue */
983 INIT_HTC_PACKET_QUEUE(&sendQueue);
984
985 do {
986
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700987 /* caller didn't provide a queue, just wants us to check
988 * queues and send
989 */
Jeff Johnson5a6cc792019-03-18 09:47:18 -0700990 if (!pCallersSendQueue)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800991 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800992
993 if (HTC_QUEUE_EMPTY(pCallersSendQueue)) {
994 /* empty queue */
995 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,
996 HTC_PKT_Q_EMPTY);
997 result = HTC_SEND_QUEUE_DROP;
998 break;
999 }
1000
1001 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >=
1002 pEndpoint->MaxTxQueueDepth) {
1003 /* we've already overflowed */
1004 overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
1005 } else {
1006 /* figure out how much we will overflow by */
1007 overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
1008 overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001009 /* get how much we will overflow the TX queue by */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001010 overflow -= pEndpoint->MaxTxQueueDepth;
1011 }
1012
1013 /* if overflow is negative or zero, we are okay */
1014 if (overflow > 0) {
1015 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001016 ("Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001017 pEndpoint->Id, overflow,
1018 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->
1019 TxQueue),
1020 pEndpoint->MaxTxQueueDepth));
1021 }
1022 if ((overflow <= 0)
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001023 || (!pEndpoint->EpCallBacks.EpSendFull)) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001024 /* all packets will fit or caller did not provide send
1025 * full indication handler
1026 * just move all of them to local sendQueue object
1027 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001028 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue,
1029 pCallersSendQueue);
1030 } else {
1031 int i;
1032 int goodPkts =
1033 HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) -
1034 overflow;
1035
1036 A_ASSERT(goodPkts >= 0);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001037 /* we have overflowed and callback is provided. Dequeue
1038 * all non-overflow packets into the sendqueue
1039 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001040 for (i = 0; i < goodPkts; i++) {
1041 /* pop off caller's queue */
1042 pPacket = htc_packet_dequeue(pCallersSendQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001043 A_ASSERT(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001044 /* insert into local queue */
1045 HTC_PACKET_ENQUEUE(&sendQueue, pPacket);
1046 }
1047
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001048 /* the caller's queue has all the packets that won't fit
1049 * walk through the caller's queue and indicate each one
1050 * to the send full handler
1051 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001052 ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->
1053 QueueHead, pPacket,
1054 HTC_PACKET, ListLink) {
1055
1056 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001057 ("Indicating overflowed TX packet: %pK\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001058 pPacket));
1059 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001060 * Remove headroom reserved for HTC_FRAME_HDR
1061 * before giving the packet back to the user via
1062 * the EpSendFull callback.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001063 */
1064 restore_tx_packet(target, pPacket);
1065
1066 if (pEndpoint->EpCallBacks.
1067 EpSendFull(pEndpoint->EpCallBacks.pContext,
1068 pPacket) == HTC_SEND_FULL_DROP) {
1069 /* callback wants the packet dropped */
1070 INC_HTC_EP_STAT(pEndpoint, TxDropped,
1071 1);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001072 /* leave this one in the caller's queue
1073 * for cleanup
1074 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001075 } else {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001076 /* callback wants to keep this packet,
1077 * remove from caller's queue
1078 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001079 HTC_PACKET_REMOVE(pCallersSendQueue,
1080 pPacket);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001081 /* put it in the send queue
1082 * add HTC_FRAME_HDR space reservation
1083 * again
1084 */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301085 qdf_nbuf_push_head
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001086 (GET_HTC_PACKET_NET_BUF_CONTEXT
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001087 (pPacket),
1088 sizeof(HTC_FRAME_HDR));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001089
1090 HTC_PACKET_ENQUEUE(&sendQueue, pPacket);
1091 }
1092
1093 }
1094 ITERATE_END;
1095
1096 if (HTC_QUEUE_EMPTY(&sendQueue)) {
1097 /* no packets made it in, caller will cleanup */
1098 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001099 HTC_SEND_Q_EMPTY);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001100 result = HTC_SEND_QUEUE_DROP;
1101 break;
1102 }
1103 }
1104
1105 } while (false);
1106
1107 if (result != HTC_SEND_QUEUE_OK) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001108 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send: %d\n",
1109 result));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001110 return result;
1111 }
1112
1113 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1114 tx_resources =
1115 hif_get_free_queue_number(target->hif_dev,
1116 pEndpoint->UL_PipeID);
1117 } else {
1118 tx_resources = 0;
1119 }
1120
1121 LOCK_HTC_TX(target);
1122
1123 if (!HTC_QUEUE_EMPTY(&sendQueue)) {
gbianb417db22016-09-30 17:01:07 +08001124 if (target->is_nodrop_pkt) {
1125 /*
1126 * nodrop pkts have higher priority than normal pkts,
1127 * insert nodrop pkt to head for proper
1128 * start/termination of test.
1129 */
1130 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
1131 &sendQueue);
1132 target->is_nodrop_pkt = false;
1133 } else {
1134 /* transfer packets to tail */
1135 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,
1136 &sendQueue);
1137 A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue));
1138 INIT_HTC_PACKET_QUEUE(&sendQueue);
1139 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001140 }
1141
1142 /* increment tx processing count on entry */
Rajeev Kumare37820e2016-04-14 17:30:56 -07001143 if (qdf_atomic_inc_return(&pEndpoint->TxProcessCount) > 1) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001144 /* another thread or task is draining the TX queues on this
1145 * endpoint that thread will reset the tx processing count when
1146 * the queue is drained
1147 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301148 qdf_atomic_dec(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001149 UNLOCK_HTC_TX(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001150 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send (busy)\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001151 return HTC_SEND_QUEUE_OK;
1152 }
1153
1154 /***** beyond this point only 1 thread may enter ******/
1155
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001156 /* now drain the endpoint TX queue for transmission as long as we have
1157 * enough transmit resources
1158 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001159 while (true) {
1160
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301161 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0)
1162 break;
1163
1164 if (pEndpoint->async_update &&
1165 (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) &&
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001166 (!tx_resources))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001167 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001168
1169 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1170#if DEBUG_CREDIT
1171 int cred = pEndpoint->TxCredits;
1172#endif
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001173 /* credit based mechanism provides flow control based on
1174 * target transmit resource availability, we assume that
1175 * the HIF layer will always have bus resources greater
1176 * than target transmit resources
1177 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001178 get_htc_send_packets_credit_based(target, pEndpoint,
1179 &sendQueue);
1180#if DEBUG_CREDIT
1181 if (ep_debug_mask & (1 << pEndpoint->Id)) {
1182 if (cred - pEndpoint->TxCredits > 0) {
1183 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001184 (" <HTC> Decrease EP%d %d - %d = %d credits.\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001185 pEndpoint->Id, cred,
1186 cred -
1187 pEndpoint->TxCredits,
1188 pEndpoint->TxCredits));
1189 }
1190 }
1191#endif
1192 } else {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001193
1194 /*
1195 * Header and payload belongs to the different fragments and
1196 * consume 2 resource for one HTC package but USB combine into
Liangwei Dong2c73be82016-09-29 03:35:59 -04001197 * one transfer.And one WMI message only consumes one single
1198 * resource.
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001199 */
Liangwei Dong2c73be82016-09-29 03:35:59 -04001200 if (HTC_TX_BUNDLE_ENABLED(target) && tx_resources &&
1201 hif_get_bus_type(target->hif_dev) ==
1202 QDF_BUS_TYPE_USB) {
1203 if (pEndpoint->service_id ==
1204 WMI_CONTROL_SVC)
1205 tx_resources =
1206 HTC_MAX_MSG_PER_BUNDLE_TX;
1207 else
1208 tx_resources =
1209 (HTC_MAX_MSG_PER_BUNDLE_TX * 2);
1210 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001211 /* get all the packets for this endpoint that we can for
1212 * this pass
1213 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001214 get_htc_send_packets(target, pEndpoint, &sendQueue,
1215 tx_resources);
1216 }
1217
1218 if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001219 /* didn't get any packets due to a lack of resources or
1220 * TX queue was drained
1221 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001222 break;
1223 }
1224
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001225 if (!pEndpoint->async_update)
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05301226 UNLOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001227
1228 /* send what we can */
Rakesh Pillai13146452017-06-22 12:52:31 +05301229 if (htc_issue_packets(target, pEndpoint, &sendQueue)) {
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001230 int i;
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001231
Rakesh Pillai13146452017-06-22 12:52:31 +05301232 result = HTC_SEND_QUEUE_DROP;
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -08001233 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1234 ("htc_issue_packets, failed status:%d put it back to head of callersSendQueue",
1235 result));
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001236
1237 for (i = HTC_PACKET_QUEUE_DEPTH(&sendQueue); i > 0; i--)
1238 hif_pm_runtime_put(target->hif_dev);
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301239 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandarub3c810b2016-11-02 17:12:34 +05301240 LOCK_HTC_TX(target);
1241 }
Liangwei Dong6c5e3322016-11-07 00:27:50 -05001242 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
1243 &sendQueue);
Manjunathappa Prakash3044c6e2015-12-04 00:08:58 -08001244 break;
1245 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001246
1247 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1248 tx_resources =
1249 hif_get_free_queue_number(target->hif_dev,
1250 pEndpoint->UL_PipeID);
1251 }
1252
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301253 if (!pEndpoint->async_update) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05301254 LOCK_HTC_TX(target);
1255 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001256
1257 }
1258
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001259 /* done with this endpoint, we can clear the count */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301260 qdf_atomic_init(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001261
Rajeev Kumare37820e2016-04-14 17:30:56 -07001262 UNLOCK_HTC_TX(target);
1263
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001264 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send:\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001265
1266 return HTC_SEND_QUEUE_OK;
1267}
1268
1269#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001270static uint16_t htc_send_pkts_sched_check(HTC_HANDLE HTCHandle,
1271 HTC_ENDPOINT_ID id)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001272{
1273 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1274 HTC_ENDPOINT *pEndpoint;
1275 HTC_ENDPOINT_ID eid;
1276 HTC_PACKET_QUEUE *pTxQueue;
Yue Mab16cf302016-03-08 18:30:25 -08001277 uint16_t resources;
1278 uint16_t acQueueStatus[DATA_EP_SIZE] = { 0, 0, 0, 0 };
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001279
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001280 if (id < ENDPOINT_2 || id > ENDPOINT_5)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001281 return 1;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001282
1283 for (eid = ENDPOINT_2; eid <= ENDPOINT_5; eid++) {
Houston Hoffman29573d92015-10-20 17:49:44 -07001284 pEndpoint = &target->endpoint[eid];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001285 pTxQueue = &pEndpoint->TxQueue;
1286
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001287 if (HTC_QUEUE_EMPTY(pTxQueue))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001288 acQueueStatus[eid - 2] = 1;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001289 }
1290
1291 switch (id) {
1292 case ENDPOINT_2: /* BE */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301293 return acQueueStatus[0] && acQueueStatus[2]
1294 && acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001295 case ENDPOINT_3: /* BK */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301296 return acQueueStatus[0] && acQueueStatus[1] && acQueueStatus[2]
1297 && acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001298 case ENDPOINT_4: /* VI */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301299 return acQueueStatus[2] && acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001300 case ENDPOINT_5: /* VO */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301301 return acQueueStatus[3];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001302 default:
1303 return 0;
1304 }
1305
1306}
1307
1308static A_STATUS htc_send_pkts_sched_queue(HTC_TARGET *target,
1309 HTC_PACKET_QUEUE *pPktQueue,
1310 HTC_ENDPOINT_ID eid)
1311{
1312 HTC_ENDPOINT *pEndpoint;
1313 HTC_PACKET_QUEUE *pTxQueue;
1314 HTC_PACKET *pPacket;
1315 int goodPkts;
1316
Houston Hoffman29573d92015-10-20 17:49:44 -07001317 pEndpoint = &target->endpoint[eid];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001318 pTxQueue = &pEndpoint->TxQueue;
1319
1320 LOCK_HTC_TX(target);
1321
1322 goodPkts =
1323 pEndpoint->MaxTxQueueDepth -
1324 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
1325
1326 if (goodPkts > 0) {
1327 while (!HTC_QUEUE_EMPTY(pPktQueue)) {
1328 pPacket = htc_packet_dequeue(pPktQueue);
1329 HTC_PACKET_ENQUEUE(pTxQueue, pPacket);
1330 goodPkts--;
1331
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001332 if (goodPkts <= 0)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001333 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001334 }
1335 }
1336
1337 if (HTC_PACKET_QUEUE_DEPTH(pPktQueue)) {
1338 ITERATE_OVER_LIST_ALLOW_REMOVE(&pPktQueue->QueueHead, pPacket,
1339 HTC_PACKET, ListLink) {
1340
1341 if (pEndpoint->EpCallBacks.
1342 EpSendFull(pEndpoint->EpCallBacks.pContext,
1343 pPacket) == HTC_SEND_FULL_DROP) {
1344 INC_HTC_EP_STAT(pEndpoint, TxDropped, 1);
1345 } else {
1346 HTC_PACKET_REMOVE(pPktQueue, pPacket);
1347 HTC_PACKET_ENQUEUE(pTxQueue, pPacket);
1348 }
1349 }
1350 ITERATE_END;
1351 }
1352
1353 UNLOCK_HTC_TX(target);
1354
1355 return A_OK;
1356}
1357
1358#endif
1359
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001360static inline QDF_STATUS __htc_send_pkt(HTC_HANDLE HTCHandle,
1361 HTC_PACKET *pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001362{
1363 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1364 HTC_ENDPOINT *pEndpoint;
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001365 HTC_PACKET_QUEUE pPktQueue;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301366 qdf_nbuf_t netbuf;
Yun Parkc353d6b2018-06-05 11:58:30 -07001367 HTC_FRAME_HDR *htc_hdr;
Himanshu Agarwalfa594d92017-04-04 12:36:33 +05301368 QDF_STATUS status;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001369
1370 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001371 ("+__htc_send_pkt\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001372
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001373 /* get packet at head to figure out which endpoint these packets will
1374 * go into
1375 */
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001376 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001377 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target, GET_HTC_PKT_Q_FAIL);
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001378 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n"));
Rakesh Pillai13146452017-06-22 12:52:31 +05301379 return QDF_STATUS_E_INVAL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001380 }
1381
Jiachao Wu15a94742017-11-10 10:13:38 +08001382 if ((pPacket->Endpoint >= ENDPOINT_MAX) ||
1383 (pPacket->Endpoint <= ENDPOINT_UNUSED)) {
1384 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1385 ("%s endpoint is invalid\n", __func__));
1386 AR_DEBUG_ASSERT(0);
1387 return QDF_STATUS_E_INVAL;
1388 }
Houston Hoffman29573d92015-10-20 17:49:44 -07001389 pEndpoint = &target->endpoint[pPacket->Endpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001390
Houston Hoffman4f2f4592015-10-20 18:00:29 -07001391 if (!pEndpoint->service_id) {
1392 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("%s service_id is invalid\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001393 __func__));
Rakesh Pillai13146452017-06-22 12:52:31 +05301394 return QDF_STATUS_E_INVAL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001395 }
1396
1397#ifdef HTC_EP_STAT_PROFILING
1398 LOCK_HTC_TX(target);
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001399 INC_HTC_EP_STAT(pEndpoint, TxPosted, 1);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001400 UNLOCK_HTC_TX(target);
1401#endif
1402
1403 /* provide room in each packet's netbuf for the HTC frame header */
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001404 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
1405 AR_DEBUG_ASSERT(netbuf);
Yun Parkc353d6b2018-06-05 11:58:30 -07001406 if (!netbuf)
1407 return QDF_STATUS_E_INVAL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001408
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001409 qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR));
1410 /* setup HTC frame header */
Yun Parkc353d6b2018-06-05 11:58:30 -07001411 htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
1412 AR_DEBUG_ASSERT(htc_hdr);
1413 if (!htc_hdr)
1414 return QDF_STATUS_E_INVAL;
1415
1416 HTC_WRITE32(htc_hdr,
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001417 SM(pPacket->ActualLength,
1418 HTC_FRAME_HDR_PAYLOADLEN) |
1419 SM(pPacket->Endpoint,
1420 HTC_FRAME_HDR_ENDPOINTID));
1421 LOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001422
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001423 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
1424 pEndpoint->SeqNo++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001425
Yun Parkc353d6b2018-06-05 11:58:30 -07001426 HTC_WRITE32(((uint32_t *)htc_hdr) + 1,
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001427 SM(pPacket->PktInfo.AsTx.SeqNo,
1428 HTC_FRAME_HDR_CONTROLBYTES1));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001429
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001430 UNLOCK_HTC_TX(target);
Dustin Brownbc9718f2017-12-11 12:15:27 -08001431
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001432 /*
Dustin Brown8969ad72017-12-02 22:43:26 -08001433 * For flow control enabled endpoints mapping is done in
1434 * htc_issue_packets and for non flow control enabled endpoints
1435 * its done here.
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001436 */
Dustin Brown8969ad72017-12-02 22:43:26 -08001437 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
Dustin Brownbc9718f2017-12-11 12:15:27 -08001438 pPacket->PktInfo.AsTx.Flags |= HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
Dustin Brown8969ad72017-12-02 22:43:26 -08001439 status = qdf_nbuf_map(target->osdev,
1440 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
1441 QDF_DMA_TO_DEVICE);
1442 if (status != QDF_STATUS_SUCCESS) {
1443 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1444 ("%s: nbuf map failed, endpoint %pK, seq_no. %d\n",
1445 __func__, pEndpoint, pEndpoint->SeqNo));
1446 return status;
1447 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001448 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001449
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001450 INIT_HTC_PACKET_QUEUE_AND_ADD(&pPktQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001451#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001452 if (!htc_send_pkts_sched_check(HTCHandle, pEndpoint->Id))
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001453 htc_send_pkts_sched_queue(HTCHandle, &pPktQueue, pEndpoint->Id);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001454 else
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001455 htc_try_send(target, pEndpoint, &pPktQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001456#else
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001457 htc_try_send(target, pEndpoint, &pPktQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001458#endif
1459
1460 /* do completion on any packets that couldn't get in */
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001461 while (!HTC_QUEUE_EMPTY(&pPktQueue)) {
1462 pPacket = htc_packet_dequeue(&pPktQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001463
Yun Park88e0b952017-10-11 23:08:34 -07001464 if (HTC_STOPPING(target))
1465 pPacket->Status = QDF_STATUS_E_CANCELED;
1466 else
1467 pPacket->Status = QDF_STATUS_E_RESOURCES;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001468
Yun Park88e0b952017-10-11 23:08:34 -07001469 send_packet_completion(target, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001470 }
1471
Houston Hoffmanb899cf82017-10-06 14:44:13 -07001472 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001473
Rakesh Pillai13146452017-06-22 12:52:31 +05301474 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001475}
1476
1477/* HTC API - htc_send_pkt */
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001478QDF_STATUS htc_send_pkt(HTC_HANDLE htc_handle, HTC_PACKET *htc_packet)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001479{
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001480 if (!htc_handle) {
1481 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1482 ("%s: HTCHandle is NULL \n", __func__));
Rakesh Pillai13146452017-06-22 12:52:31 +05301483 return QDF_STATUS_E_FAILURE;
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001484 }
1485
1486 if (!htc_packet) {
1487 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1488 ("%s: pPacket is NULL \n", __func__));
1489 return QDF_STATUS_E_FAILURE;
1490 }
Karthick Sdc40a352015-10-14 18:14:15 +05301491
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001492 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Jeff Johnsona79b1112017-09-18 10:12:02 -07001493 ("+-htc_send_pkt: Enter endPointId: %d, buffer: %pK, length: %d\n",
Kabilan Kannan2c0da262018-02-21 13:41:00 -08001494 htc_packet->Endpoint, htc_packet->pBuffer,
1495 htc_packet->ActualLength));
1496 return __htc_send_pkt(htc_handle, htc_packet);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001497}
Pratik Gandhidc82a772018-01-30 18:57:05 +05301498qdf_export_symbol(htc_send_pkt);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001499
1500#ifdef ATH_11AC_TXCOMPACT
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001501/**
1502 * htc_send_data_pkt() - send single data packet on an endpoint
1503 * @HTCHandle: pointer to HTC handle
1504 * @netbuf: network buffer containing the data to be sent
1505 * @ActualLength: length of data that needs to be transmitted
1506 *
Rakesh Pillai13146452017-06-22 12:52:31 +05301507 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001508 */
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301509QDF_STATUS htc_send_data_pkt(HTC_HANDLE htc_hdl, qdf_nbuf_t netbuf, int ep_id,
1510 int actual_length)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001511{
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301512 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001513 HTC_ENDPOINT *pEndpoint;
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301514 HTC_FRAME_HDR *p_htc_hdr;
Rakesh Pillai13146452017-06-22 12:52:31 +05301515 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001516 int tx_resources;
1517 uint32_t data_attr = 0;
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301518 int htc_payload_len = actual_length;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001519
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301520 pEndpoint = &target->endpoint[ep_id];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001521
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001522 tx_resources = hif_get_free_queue_number(target->hif_dev,
1523 pEndpoint->UL_PipeID);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001524
1525 if (tx_resources < HTC_DATA_RESOURCE_THRS) {
1526 if (pEndpoint->ul_is_polled) {
1527 hif_send_complete_check(pEndpoint->target->hif_dev,
1528 pEndpoint->UL_PipeID, 1);
1529 tx_resources =
1530 hif_get_free_queue_number(target->hif_dev,
1531 pEndpoint->UL_PipeID);
1532 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001533 if (tx_resources < HTC_DATA_MINDESC_PERPACKET)
Rakesh Pillai13146452017-06-22 12:52:31 +05301534 return QDF_STATUS_E_FAILURE;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001535 }
1536
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001537 if (hif_pm_runtime_get(target->hif_dev))
Rakesh Pillai13146452017-06-22 12:52:31 +05301538 return QDF_STATUS_E_FAILURE;
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001539
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301540 p_htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
1541 AR_DEBUG_ASSERT(p_htc_hdr);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001542
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301543 data_attr = qdf_nbuf_data_attr_get(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001544
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301545 if (target->htc_hdr_length_check)
1546 htc_payload_len = actual_length - HTC_HEADER_LEN;
1547
1548 HTC_WRITE32(p_htc_hdr, SM(htc_payload_len, HTC_FRAME_HDR_PAYLOADLEN)
1549 | SM(ep_id, HTC_FRAME_HDR_ENDPOINTID));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001550 /*
1551 * If the HIF pipe for the data endpoint is polled rather than
1552 * interrupt-driven, this is a good point to check whether any
1553 * data previously sent through the HIF pipe have finished being
1554 * sent.
1555 * Since this may result in callbacks to htc_tx_completion_handler,
1556 * which can take the HTC tx lock, make the hif_send_complete_check
1557 * call before acquiring the HTC tx lock.
1558 * Call hif_send_complete_check directly, rather than calling
1559 * htc_send_complete_check, and call the PollTimerStart separately
1560 * after calling hif_send_head, so the timer will be started to
1561 * check for completion of the new outstanding download (in the
1562 * unexpected event that other polling calls don't catch it).
1563 */
1564
1565 LOCK_HTC_TX(target);
1566
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301567 HTC_WRITE32(((uint32_t *)p_htc_hdr) + 1,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001568 SM(pEndpoint->SeqNo, HTC_FRAME_HDR_CONTROLBYTES1));
1569
1570 pEndpoint->SeqNo++;
1571
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301572 QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301573 DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
Nandha Kishore Easwarane43583f2017-05-15 21:01:13 +05301574 QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf),
1575 sizeof(qdf_nbuf_data(netbuf)), QDF_TX));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001576 status = hif_send_head(target->hif_dev,
1577 pEndpoint->UL_PipeID,
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05301578 pEndpoint->Id, actual_length, netbuf, data_attr);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001579
1580 UNLOCK_HTC_TX(target);
1581 return status;
1582}
1583#else /*ATH_11AC_TXCOMPACT */
1584
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001585/**
1586 * htc_send_data_pkt() - htc_send_data_pkt
1587 * @HTCHandle: pointer to HTC handle
1588 * @pPacket: pointer to HTC_PACKET
1589 * @more_data: indicates whether more data is to follow
1590 *
Rakesh Pillai13146452017-06-22 12:52:31 +05301591 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001592 */
Rakesh Pillai13146452017-06-22 12:52:31 +05301593QDF_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket,
Yue Mab16cf302016-03-08 18:30:25 -08001594 uint8_t more_data)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001595{
1596 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1597 HTC_ENDPOINT *pEndpoint;
1598 HTC_FRAME_HDR *pHtcHdr;
1599 HTC_PACKET_QUEUE sendQueue;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301600 qdf_nbuf_t netbuf = NULL;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001601 int tx_resources;
Rakesh Pillai13146452017-06-22 12:52:31 +05301602 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001603 uint32_t data_attr = 0;
1604
1605 if (pPacket) {
Jiachao Wu15a94742017-11-10 10:13:38 +08001606 if ((pPacket->Endpoint >= ENDPOINT_MAX) ||
1607 (pPacket->Endpoint <= ENDPOINT_UNUSED)) {
1608 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1609 ("%s endpoint is invalid\n", __func__));
1610 AR_DEBUG_ASSERT(0);
1611 return QDF_STATUS_E_INVAL;
1612 }
Houston Hoffman29573d92015-10-20 17:49:44 -07001613 pEndpoint = &target->endpoint[pPacket->Endpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001614
1615 /* add HTC_FRAME_HDR in the initial fragment */
1616 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301617 pHtcHdr = (HTC_FRAME_HDR *) qdf_nbuf_get_frag_vaddr(netbuf, 0);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001618 AR_DEBUG_ASSERT(pHtcHdr);
1619
1620 HTC_WRITE32(pHtcHdr,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001621 SM(pPacket->ActualLength,
1622 HTC_FRAME_HDR_PAYLOADLEN) |
1623 SM(pPacket->PktInfo.AsTx.SendFlags,
1624 HTC_FRAME_HDR_FLAGS) |
1625 SM(pPacket->Endpoint,
1626 HTC_FRAME_HDR_ENDPOINTID));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001627 /*
1628 * If the HIF pipe for the data endpoint is polled rather than
1629 * interrupt-driven, this is a good point to check whether any
1630 * data previously sent through the HIF pipe have finished being
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001631 * sent. Since this may result in callbacks to
1632 * htc_tx_completion_handler, which can take the HTC tx lock,
1633 * make the hif_send_complete_check call before acquiring the
1634 * HTC tx lock.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001635 * Call hif_send_complete_check directly, rather than calling
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001636 * htc_send_complete_check, and call the PollTimerStart
1637 * separately after calling hif_send_head, so the timer will be
1638 * started to check for completion of the new outstanding
1639 * download (in the unexpected event that other polling calls
1640 * don't catch it).
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001641 */
1642 if (pEndpoint->ul_is_polled) {
1643 htc_send_complete_poll_timer_stop(pEndpoint);
1644 hif_send_complete_check(pEndpoint->target->hif_dev,
1645 pEndpoint->UL_PipeID, 0);
1646 }
1647
1648 LOCK_HTC_TX(target);
1649
1650 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
1651 pEndpoint->SeqNo++;
1652
Yue Mab16cf302016-03-08 18:30:25 -08001653 HTC_WRITE32(((uint32_t *) pHtcHdr) + 1,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001654 SM(pPacket->PktInfo.AsTx.SeqNo,
1655 HTC_FRAME_HDR_CONTROLBYTES1));
1656
1657 /* append new packet to pEndpoint->TxQueue */
1658 HTC_PACKET_ENQUEUE(&pEndpoint->TxQueue, pPacket);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001659 if (HTC_TX_BUNDLE_ENABLED(target) && (more_data)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001660 UNLOCK_HTC_TX(target);
Rakesh Pillai13146452017-06-22 12:52:31 +05301661 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001662 }
wadesong31d77bc2017-05-28 14:45:21 +08001663
1664 QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
1665 DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
Nirav Shahd9dce6e2018-02-26 14:50:25 +05301666 QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf),
wadesong31d77bc2017-05-28 14:45:21 +08001667 sizeof(qdf_nbuf_data(netbuf)), QDF_TX));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001668 } else {
1669 LOCK_HTC_TX(target);
Houston Hoffman29573d92015-10-20 17:49:44 -07001670 pEndpoint = &target->endpoint[1];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001671 }
1672
1673 /* increment tx processing count on entry */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301674 qdf_atomic_inc(&pEndpoint->TxProcessCount);
1675 if (qdf_atomic_read(&pEndpoint->TxProcessCount) > 1) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001676 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001677 * Another thread or task is draining the TX queues on this
1678 * endpoint. That thread will reset the tx processing count when
1679 * the queue is drained.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001680 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301681 qdf_atomic_dec(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001682 UNLOCK_HTC_TX(target);
Rakesh Pillai13146452017-06-22 12:52:31 +05301683 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001684 }
1685
1686 /***** beyond this point only 1 thread may enter ******/
1687
1688 INIT_HTC_PACKET_QUEUE(&sendQueue);
1689 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1690#if DEBUG_CREDIT
1691 int cred = pEndpoint->TxCredits;
1692#endif
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001693 get_htc_send_packets_credit_based(target, pEndpoint,
1694 &sendQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001695#if DEBUG_CREDIT
1696 if (ep_debug_mask & (1 << pEndpoint->Id)) {
1697 if (cred - pEndpoint->TxCredits > 0) {
1698 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1699 (" <HTC> Decrease EP%d %d - %d = %d credits.\n",
1700 pEndpoint->Id, cred,
1701 cred - pEndpoint->TxCredits,
1702 pEndpoint->TxCredits));
1703 }
1704 }
1705#endif
1706 UNLOCK_HTC_TX(target);
1707 }
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001708
1709 else if (HTC_TX_BUNDLE_ENABLED(target)) {
Ajit Pal Singh3fcc0822019-03-21 17:35:22 +05301710 if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB) {
1711 if (hif_get_free_queue_number(target->hif_dev,
1712 pEndpoint->UL_PipeID))
1713 /*
1714 * Header and payload belongs to the different
1715 * fragments and consume 2 resource for one HTC
1716 * package but USB combine into one transfer.
1717 */
1718 get_htc_send_packets(target, pEndpoint,
1719 &sendQueue,
1720 HTC_MAX_MSG_PER_BUNDLE_TX
1721 * 2);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001722 } else {
Ajit Pal Singh3fcc0822019-03-21 17:35:22 +05301723 /* Dequeue max packets from endpoint tx queue */
1724 get_htc_send_packets(target, pEndpoint, &sendQueue,
1725 HTC_MAX_TX_BUNDLE_SEND_LIMIT);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001726 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001727 UNLOCK_HTC_TX(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001728 } else {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001729 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001730 * Now drain the endpoint TX queue for transmission as long as
1731 * we have enough transmit resources
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001732 */
1733 tx_resources =
1734 hif_get_free_queue_number(target->hif_dev,
1735 pEndpoint->UL_PipeID);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001736 get_htc_send_packets(target, pEndpoint, &sendQueue,
1737 tx_resources);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001738 UNLOCK_HTC_TX(target);
1739 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001740
1741 /* send what we can */
1742 while (true) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001743 if (HTC_TX_BUNDLE_ENABLED(target) &&
1744 (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >=
1745 HTC_MIN_MSG_PER_BUNDLE) &&
1746 (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO ||
1747 hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001748 htc_issue_packets_bundle(target, pEndpoint, &sendQueue);
1749 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001750 pPacket = htc_packet_dequeue(&sendQueue);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001751 if (!pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001752 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001753 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
1754
1755 LOCK_HTC_TX(target);
1756 /* store in look up queue to match completions */
1757 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket);
1758 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
1759 pEndpoint->ul_outstanding_cnt++;
1760 UNLOCK_HTC_TX(target);
1761
1762 status = hif_send_head(target->hif_dev,
1763 pEndpoint->UL_PipeID,
1764 pEndpoint->Id,
1765 HTC_HDR_LENGTH + pPacket->ActualLength,
1766 netbuf, data_attr);
1767#if DEBUG_BUNDLE
Aditya Sathish648ce112018-07-02 16:41:39 +05301768 qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001769 pEndpoint->Id,
1770 pEndpoint->TxCreditSize,
1771 HTC_HDR_LENGTH + pPacket->ActualLength);
1772#endif
1773
Poddar, Siddarthdf030092016-04-28 11:41:57 +05301774 htc_issue_tx_bundle_stats_inc(target);
1775
Rakesh Pillai13146452017-06-22 12:52:31 +05301776 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001777 LOCK_HTC_TX(target);
1778 pEndpoint->ul_outstanding_cnt--;
1779 /* remove this packet from the tx completion queue */
1780 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket);
1781
1782 /*
1783 * Don't bother reclaiming credits - HTC flow control
1784 * is not applicable to tx data.
1785 * In LL systems, there is no download flow control,
1786 * since there's virtually no download delay.
1787 * In HL systems, the txrx SW explicitly performs the
1788 * tx flow control.
1789 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001790 /* pEndpoint->TxCredits +=
1791 * pPacket->PktInfo.AsTx.CreditsUsed;
1792 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001793
1794 /* put this frame back at the front of the sendQueue */
1795 HTC_PACKET_ENQUEUE_TO_HEAD(&sendQueue, pPacket);
1796
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001797 /* put the sendQueue back at the front of
1798 * pEndpoint->TxQueue
1799 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001800 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
1801 &sendQueue);
1802 UNLOCK_HTC_TX(target);
1803 break; /* still need to reset TxProcessCount */
1804 }
1805 }
1806 /* done with this endpoint, we can clear the count */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301807 qdf_atomic_init(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001808
1809 if (pEndpoint->ul_is_polled) {
1810 /*
1811 * Start a cleanup timer to poll for download completion.
1812 * The download completion should be noticed promptly from
1813 * other polling calls, but the timer provides a safety net
1814 * in case other polling calls don't occur as expected.
1815 */
1816 htc_send_complete_poll_timer_start(pEndpoint);
1817 }
1818
1819 return status;
1820}
1821#endif /*ATH_11AC_TXCOMPACT */
Pratik Gandhidc82a772018-01-30 18:57:05 +05301822qdf_export_symbol(htc_send_data_pkt);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001823
1824/*
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301825 * In the adapted HIF layer, qdf_nbuf_t are passed between HIF and HTC,
1826 * since upper layers expects HTC_PACKET containers we use the completed netbuf
1827 * and lookup its corresponding HTC packet buffer from a lookup list.
1828 * This is extra overhead that can be fixed by re-aligning HIF interfaces
1829 * with HTC.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001830 *
1831 */
1832static HTC_PACKET *htc_lookup_tx_packet(HTC_TARGET *target,
1833 HTC_ENDPOINT *pEndpoint,
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301834 qdf_nbuf_t netbuf)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001835{
1836 HTC_PACKET *pPacket = NULL;
1837 HTC_PACKET *pFoundPacket = NULL;
1838 HTC_PACKET_QUEUE lookupQueue;
1839
1840 INIT_HTC_PACKET_QUEUE(&lookupQueue);
Govind Singhc505cdc2017-05-16 12:15:51 +05301841 LOCK_HTC_EP_TX_LOOKUP(pEndpoint);
1842
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001843 LOCK_HTC_TX(target);
1844
1845 /* mark that HIF has indicated the send complete for another packet */
1846 pEndpoint->ul_outstanding_cnt--;
1847
1848 /* Dequeue first packet directly because of in-order completion */
1849 pPacket = htc_packet_dequeue(&pEndpoint->TxLookupQueue);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301850 if (qdf_unlikely(!pPacket)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001851 UNLOCK_HTC_TX(target);
Govind Singhc505cdc2017-05-16 12:15:51 +05301852 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001853 return NULL;
1854 }
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301855 if (netbuf == (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001856 UNLOCK_HTC_TX(target);
Govind Singhc505cdc2017-05-16 12:15:51 +05301857 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001858 return pPacket;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001859 }
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001860 HTC_PACKET_ENQUEUE(&lookupQueue, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001861
1862 /*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001863 * Move TX lookup queue to temp queue because most of packets that are
1864 * not index 0 are not top 10 packets.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001865 */
1866 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&lookupQueue,
1867 &pEndpoint->TxLookupQueue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001868
1869 ITERATE_OVER_LIST_ALLOW_REMOVE(&lookupQueue.QueueHead, pPacket,
1870 HTC_PACKET, ListLink) {
1871
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001872 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001873 pFoundPacket = pPacket;
1874 break;
1875 }
1876 /* check for removal */
1877 if (netbuf ==
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301878 (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001879 /* found it */
1880 HTC_PACKET_REMOVE(&lookupQueue, pPacket);
1881 pFoundPacket = pPacket;
1882 break;
1883 }
1884
1885 }
1886 ITERATE_END;
1887
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001888 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxLookupQueue,
1889 &lookupQueue);
1890 UNLOCK_HTC_TX(target);
Govind Singhc505cdc2017-05-16 12:15:51 +05301891 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001892
1893 return pFoundPacket;
1894}
1895
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001896/**
1897 * htc_tx_completion_handler() - htc tx completion handler
1898 * @Context: pointer to HTC_TARGET structure
1899 * @netbuf: pointer to netbuf for which completion handler is being called
1900 * @EpID: end point Id on which the packet was sent
1901 * @toeplitz_hash_result: toeplitz hash result
1902 *
1903 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
1904 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301905QDF_STATUS htc_tx_completion_handler(void *Context,
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +05301906 qdf_nbuf_t netbuf, unsigned int EpID,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001907 uint32_t toeplitz_hash_result)
1908{
1909 HTC_TARGET *target = (HTC_TARGET *) Context;
1910 HTC_ENDPOINT *pEndpoint;
1911 HTC_PACKET *pPacket;
1912#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301913 HTC_ENDPOINT_ID eid[DATA_EP_SIZE] = { ENDPOINT_5, ENDPOINT_4,
1914 ENDPOINT_2, ENDPOINT_3 };
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001915 int epidIdx;
Yue Mab16cf302016-03-08 18:30:25 -08001916 uint16_t resourcesThresh[DATA_EP_SIZE]; /* urb resources */
1917 uint16_t resources;
1918 uint16_t resourcesMax;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001919#endif
1920
Houston Hoffman29573d92015-10-20 17:49:44 -07001921 pEndpoint = &target->endpoint[EpID];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001922 target->TX_comp_cnt++;
1923
1924 do {
1925 pPacket = htc_lookup_tx_packet(target, pEndpoint, netbuf);
Jeff Johnson5a6cc792019-03-18 09:47:18 -07001926 if (!pPacket) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001927 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1928 ("HTC TX lookup failed!\n"));
1929 /* may have already been flushed and freed */
1930 netbuf = NULL;
1931 break;
1932 }
Houston Hoffmanc5141b02015-11-18 02:36:30 -08001933 if (pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_AUTO_PM)
1934 hif_pm_runtime_put(target->hif_dev);
1935
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001936 if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) {
1937 HTC_PACKET *pPacketTemp;
1938 HTC_PACKET_QUEUE *pQueueSave =
1939 (HTC_PACKET_QUEUE *) pPacket->pContext;
1940 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQueueSave,
1941 pPacketTemp) {
Rakesh Pillai13146452017-06-22 12:52:31 +05301942 pPacket->Status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001943 send_packet_completion(target, pPacketTemp);
1944 }
1945 HTC_PACKET_QUEUE_ITERATE_END;
1946 free_htc_bundle_packet(target, pPacket);
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001947
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001948 if (hif_get_bus_type(target->hif_dev) ==
1949 QDF_BUS_TYPE_USB) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -07001950 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint))
1951 htc_try_send(target, pEndpoint, NULL);
1952 }
1953
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301954 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001955 }
1956 /* will be giving this buffer back to upper layers */
1957 netbuf = NULL;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301958 pPacket->Status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001959 send_packet_completion(target, pPacket);
1960
1961 } while (false);
1962
1963 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07001964 /* note: when using TX credit flow, the re-checking of queues
1965 * happens when credits flow back from the target. In the non-TX
1966 * credit case, we recheck after the packet completes
1967 */
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05301968 if ((qdf_atomic_read(&pEndpoint->TxProcessCount) == 0) ||
Venkateswara Swamy Bandaruae41b9e2016-11-21 15:06:24 +05301969 (!pEndpoint->async_update)) {
Venkateswara Swamy Bandaru9e66f4f2016-10-29 17:13:52 +05301970 htc_try_send(target, pEndpoint, NULL);
1971 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001972 }
1973
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05301974 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001975}
1976
Poddar, Siddarthdf030092016-04-28 11:41:57 +05301977#ifdef WLAN_FEATURE_FASTPATH
Houston Hoffman93481862016-05-05 18:49:59 -07001978/**
1979 * htc_ctrl_msg_cmpl(): checks for tx completion for the endpoint specified
1980 * @HTC_HANDLE : pointer to the htc target context
1981 * @htc_ep_id : end point id
1982 *
1983 * checks HTC tx completion
1984 *
1985 * Return: none
1986 */
1987void htc_ctrl_msg_cmpl(HTC_HANDLE htc_pdev, HTC_ENDPOINT_ID htc_ep_id)
1988{
1989 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_pdev);
1990 HTC_ENDPOINT *pendpoint = &target->endpoint[htc_ep_id];
1991
1992 htc_send_complete_check(pendpoint, 1);
1993}
Pratik Gandhidc82a772018-01-30 18:57:05 +05301994qdf_export_symbol(htc_ctrl_msg_cmpl);
Houston Hoffman93481862016-05-05 18:49:59 -07001995#endif
1996
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001997/* callback when TX resources become available */
Yue Mab16cf302016-03-08 18:30:25 -08001998void htc_tx_resource_avail_handler(void *context, uint8_t pipeID)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001999{
2000 int i;
2001 HTC_TARGET *target = (HTC_TARGET *) context;
2002 HTC_ENDPOINT *pEndpoint = NULL;
2003
2004 for (i = 0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -07002005 pEndpoint = &target->endpoint[i];
Houston Hoffman4f2f4592015-10-20 18:00:29 -07002006 if (pEndpoint->service_id != 0) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002007 if (pEndpoint->UL_PipeID == pipeID)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002008 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002009 }
2010 }
2011
2012 if (i >= ENDPOINT_MAX) {
2013 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2014 ("Invalid pipe indicated for TX resource avail : %d!\n",
2015 pipeID));
2016 return;
2017 }
2018
2019 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002020 ("HIF indicated more resources for pipe:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002021 pipeID));
2022
2023 htc_try_send(target, pEndpoint, NULL);
2024}
2025
Yue Maec9e71c2016-02-26 18:52:20 -08002026#ifdef FEATURE_RUNTIME_PM
Houston Hoffman47e387b2015-10-20 17:04:42 -07002027/**
2028 * htc_kick_queues(): resumes tx transactions of suspended endpoints
2029 * @context: pointer to the htc target context
2030 *
Jeff Johnson4b253f02018-05-12 11:34:43 -07002031 * Iterates through the enpoints and provides a context to empty queues
Houston Hoffman47e387b2015-10-20 17:04:42 -07002032 * int the hif layer when they are stalled due to runtime suspend.
2033 *
2034 * Return: none
2035 */
2036void htc_kick_queues(void *context)
2037{
2038 int i;
2039 HTC_TARGET *target = (HTC_TARGET *)context;
2040 HTC_ENDPOINT *endpoint = NULL;
2041
2042 for (i = 0; i < ENDPOINT_MAX; i++) {
2043 endpoint = &target->endpoint[i];
2044
2045 if (endpoint->service_id == 0)
2046 continue;
2047
2048 if (endpoint->EpCallBacks.ep_resume_tx_queue)
2049 endpoint->EpCallBacks.ep_resume_tx_queue(
2050 endpoint->EpCallBacks.pContext);
2051
2052 htc_try_send(target, endpoint, NULL);
2053 }
Yue Ma9c6f84d2017-02-17 10:45:55 -08002054
2055 hif_fastpath_resume(target->hif_dev);
Houston Hoffman47e387b2015-10-20 17:04:42 -07002056}
Yue Maec9e71c2016-02-26 18:52:20 -08002057#endif
Houston Hoffman47e387b2015-10-20 17:04:42 -07002058
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002059/* flush endpoint TX queue */
2060void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint,
2061 HTC_TX_TAG Tag)
2062{
2063 HTC_PACKET *pPacket;
2064
2065 LOCK_HTC_TX(target);
2066 while (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) {
2067 pPacket = htc_packet_dequeue(&pEndpoint->TxQueue);
2068
2069 if (pPacket) {
2070 /* let the sender know the packet was not delivered */
Rakesh Pillai13146452017-06-22 12:52:31 +05302071 pPacket->Status = QDF_STATUS_E_CANCELED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002072 send_packet_completion(target, pPacket);
2073 }
2074 }
2075 UNLOCK_HTC_TX(target);
2076}
2077
Alok Kumar9bd81522018-05-30 13:07:13 +05302078/* flush pending entries in endpoint TX Lookup queue */
2079void htc_flush_endpoint_txlookupQ(HTC_TARGET *target,
Zhang Qianedaa3872018-07-04 20:02:53 +08002080 HTC_ENDPOINT_ID endpoint_id,
2081 bool call_ep_callback)
Alok Kumar9bd81522018-05-30 13:07:13 +05302082{
2083 HTC_PACKET *packet;
2084 HTC_ENDPOINT *endpoint;
2085
2086 endpoint = &target->endpoint[endpoint_id];
2087
2088 if (!endpoint && endpoint->service_id == 0)
2089 return;
2090
Debasis Das5e2539c2018-11-16 14:43:26 +05302091 LOCK_HTC_TX(target);
Alok Kumar9bd81522018-05-30 13:07:13 +05302092 while (HTC_PACKET_QUEUE_DEPTH(&endpoint->TxLookupQueue)) {
2093 packet = htc_packet_dequeue(&endpoint->TxLookupQueue);
2094
2095 if (packet) {
Zhang Qianedaa3872018-07-04 20:02:53 +08002096 if (call_ep_callback == true) {
2097 packet->Status = QDF_STATUS_E_CANCELED;
2098 send_packet_completion(target, packet);
2099 } else {
2100 qdf_mem_free(packet);
2101 }
Alok Kumar9bd81522018-05-30 13:07:13 +05302102 }
2103 }
Debasis Das5e2539c2018-11-16 14:43:26 +05302104 UNLOCK_HTC_TX(target);
Alok Kumar9bd81522018-05-30 13:07:13 +05302105}
2106
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002107/* HTC API to flush an endpoint's TX queue*/
2108void htc_flush_endpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint,
2109 HTC_TX_TAG Tag)
2110{
2111 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Houston Hoffman29573d92015-10-20 17:49:44 -07002112 HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002113
Houston Hoffman4f2f4592015-10-20 18:00:29 -07002114 if (pEndpoint->service_id == 0) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002115 AR_DEBUG_ASSERT(false);
2116 /* not in use.. */
2117 return;
2118 }
2119
2120 htc_flush_endpoint_tx(target, pEndpoint, Tag);
2121}
2122
2123/* HTC API to indicate activity to the credit distribution function */
2124void htc_indicate_activity_change(HTC_HANDLE HTCHandle,
Yue Mab16cf302016-03-08 18:30:25 -08002125 HTC_ENDPOINT_ID Endpoint, bool Active)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002126{
2127 /* TODO */
2128}
2129
Yue Mab16cf302016-03-08 18:30:25 -08002130bool htc_is_endpoint_active(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002131{
2132 return true;
2133}
2134
gbianb417db22016-09-30 17:01:07 +08002135void htc_set_nodrop_pkt(HTC_HANDLE HTCHandle, A_BOOL isNodropPkt)
2136{
2137 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002138
gbianb417db22016-09-30 17:01:07 +08002139 target->is_nodrop_pkt = isNodropPkt;
2140}
2141
Rakshith Suresh Patkar5aeabd62018-12-04 21:12:00 +05302142void htc_enable_hdr_length_check(HTC_HANDLE htc_hdl, bool htc_hdr_length_check)
2143{
2144 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl);
2145
2146 target->htc_hdr_length_check = htc_hdr_length_check;
2147}
2148
Mohit Khanna0f6194e2016-05-17 15:30:44 -07002149/**
2150 * htc_process_credit_rpt() - process credit report, call distribution function
2151 * @target: pointer to HTC_TARGET
2152 * @pRpt: pointer to HTC_CREDIT_REPORT
2153 * @NumEntries: number of entries in credit report
2154 * @FromEndpoint: endpoint for which credit report is received
2155 *
2156 * Return: A_OK for success or an appropriate A_STATUS error
2157 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002158void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt,
2159 int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
2160{
2161 int i;
2162 HTC_ENDPOINT *pEndpoint;
2163 int totalCredits = 0;
Yue Mab16cf302016-03-08 18:30:25 -08002164 uint8_t rpt_credits, rpt_ep_id;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002165
2166 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002167 ("+htc_process_credit_rpt, Credit Report Entries:%d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002168 NumEntries));
2169
2170 /* lock out TX while we update credits */
2171 LOCK_HTC_TX(target);
2172
2173 for (i = 0; i < NumEntries; i++, pRpt++) {
2174
2175 rpt_ep_id = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, ENDPOINTID);
2176
2177 if (rpt_ep_id >= ENDPOINT_MAX) {
2178 AR_DEBUG_ASSERT(false);
2179 break;
2180 }
2181
2182 rpt_credits = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, CREDITS);
2183
Houston Hoffman29573d92015-10-20 17:49:44 -07002184 pEndpoint = &target->endpoint[rpt_ep_id];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002185#if DEBUG_CREDIT
2186 if (ep_debug_mask & (1 << pEndpoint->Id)) {
2187 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2188 (" <HTC> Increase EP%d %d + %d = %d credits\n",
2189 rpt_ep_id, pEndpoint->TxCredits,
2190 rpt_credits,
2191 pEndpoint->TxCredits + rpt_credits));
2192 }
2193#endif
2194
2195#ifdef HTC_EP_STAT_PROFILING
2196
2197 INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
2198 INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, rpt_credits);
2199
2200 if (FromEndpoint == rpt_ep_id) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002201 /* this credit report arrived on the same endpoint
2202 * indicating it arrived in an RX packet
2203 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002204 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx,
2205 rpt_credits);
2206 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
2207 } else if (FromEndpoint == ENDPOINT_0) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002208 /* this credit arrived on endpoint 0 as a NULL msg */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002209 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0,
2210 rpt_credits);
2211 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
2212 } else {
2213 /* arrived on another endpoint */
2214 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther,
2215 rpt_credits);
2216 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
2217 }
2218
2219#endif
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002220
Houston Hoffman4f2f4592015-10-20 18:00:29 -07002221 if (pEndpoint->service_id == WMI_CONTROL_SVC) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002222 htc_credit_record(HTC_PROCESS_CREDIT_REPORT,
Dustin Brownf74576c2018-03-12 14:22:51 -07002223 pEndpoint->TxCredits + rpt_credits,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002224 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->
Rachit Kankane1bc11492018-01-24 18:48:17 +05302225 TxQueue));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002226 }
Dustin Brownf74576c2018-03-12 14:22:51 -07002227
2228 pEndpoint->TxCredits += rpt_credits;
2229
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002230 if (pEndpoint->TxCredits
2231 && HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) {
2232 UNLOCK_HTC_TX(target);
2233#ifdef ATH_11AC_TXCOMPACT
2234 htc_try_send(target, pEndpoint, NULL);
2235#else
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002236 if (pEndpoint->service_id == HTT_DATA_MSG_SVC)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002237 htc_send_data_pkt(target, NULL, 0);
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002238 else
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002239 htc_try_send(target, pEndpoint, NULL);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002240#endif
2241 LOCK_HTC_TX(target);
2242 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002243 totalCredits += rpt_credits;
2244 }
2245
2246 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002247 (" Report indicated %d credits to distribute\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002248 totalCredits));
2249
2250 UNLOCK_HTC_TX(target);
2251
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002252 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_process_credit_rpt\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002253}
2254
2255/* function to fetch stats from htc layer*/
2256struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE HTCHandle)
2257{
2258 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
2259
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +05302260 return &(target->htc_pkt_stats);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08002261}