xref: /wlan-dirver/qca-wifi-host-cmn/htc/htc_send.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "htc_debug.h"
21 #include "htc_internal.h"
22 #include "htc_credit_history.h"
23 #include <qdf_mem.h>            /* qdf_mem_malloc */
24 #include <qdf_nbuf.h>           /* qdf_nbuf_t */
25 #include "qdf_module.h"
26 
27 /* #define USB_HIF_SINGLE_PIPE_DATA_SCHED */
28 /* #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED */
29 #define DATA_EP_SIZE 4
30 /* #endif */
31 #define HTC_DATA_RESOURCE_THRS 256
32 #define HTC_DATA_MINDESC_PERPACKET 2
33 
34 /* maximum number of requeue attempts before print */
35 #define MAX_REQUEUE_WARN 5
36 
37 enum HTC_SEND_QUEUE_RESULT {
38 	HTC_SEND_QUEUE_OK = 0,  /* packet was queued */
39 	HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */
40 };
41 
42 #ifndef DEBUG_CREDIT
43 #define DEBUG_CREDIT 0
44 #endif
45 
46 #if DEBUG_CREDIT
47 /* bit mask to enable debug certain endpoint */
48 static unsigned int ep_debug_mask =
49 	(1 << ENDPOINT_0) | (1 << ENDPOINT_1) | (1 << ENDPOINT_2);
50 #endif
51 
52 #ifdef QCA_WIFI_EMULATION
53 #define HTC_EMULATION_DELAY_IN_MS 20
54 /**
55  * htc_add_delay(): Adds a delay in before proceeding, only for emulation
56  *
57  * Return: None
58  */
59 static inline void htc_add_emulation_delay(void)
60 {
61 	qdf_mdelay(HTC_EMULATION_DELAY_IN_MS);
62 }
63 #else
64 static inline void htc_add_emulation_delay(void)
65 {
66 }
67 #endif
68 
69 void htc_dump_counter_info(HTC_HANDLE HTCHandle)
70 {
71 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
72 
73 	if (!target)
74 		return;
75 
76 	AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
77 			("\n%s: ce_send_cnt = %d, TX_comp_cnt = %d\n",
78 			 __func__, target->ce_send_cnt, target->TX_comp_cnt));
79 }
80 
81 int htc_get_tx_queue_depth(HTC_HANDLE htc_handle, HTC_ENDPOINT_ID endpoint_id)
82 {
83 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
84 	HTC_ENDPOINT *endpoint = &target->endpoint[endpoint_id];
85 
86 	return HTC_PACKET_QUEUE_DEPTH(&endpoint->TxQueue);
87 }
88 qdf_export_symbol(htc_get_tx_queue_depth);
89 
90 void htc_get_control_endpoint_tx_host_credits(HTC_HANDLE HTCHandle,
91 					      int *credits)
92 {
93 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
94 	HTC_ENDPOINT *pEndpoint;
95 	int i;
96 
97 	if (!credits || !target) {
98 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: invalid args", __func__));
99 		return;
100 	}
101 
102 	*credits = 0;
103 	LOCK_HTC_TX(target);
104 	for (i = 0; i < ENDPOINT_MAX; i++) {
105 		pEndpoint = &target->endpoint[i];
106 		if (pEndpoint->service_id == WMI_CONTROL_SVC) {
107 			*credits = pEndpoint->TxCredits;
108 			break;
109 		}
110 	}
111 	UNLOCK_HTC_TX(target);
112 }
113 
114 static inline void restore_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
115 {
116 	qdf_nbuf_t netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
117 
118 	if (pPacket->PktInfo.AsTx.Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) {
119 		qdf_nbuf_unmap(target->osdev, netbuf, QDF_DMA_TO_DEVICE);
120 		pPacket->PktInfo.AsTx.Flags &= ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
121 	}
122 	if (pPacket->PktInfo.AsTx.Flags &
123 		HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA) {
124 		qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR));
125 		pPacket->PktInfo.AsTx.Flags &=
126 			~HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA;
127 	}
128 }
129 
130 static void send_packet_completion(HTC_TARGET *target, HTC_PACKET *pPacket)
131 {
132 	HTC_ENDPOINT *pEndpoint = &target->endpoint[pPacket->Endpoint];
133 	HTC_EP_SEND_PKT_COMPLETE EpTxComplete;
134 
135 	if ((pPacket->PktInfo.AsTx.Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) &&
136 	    (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)))
137 		target->nbuf_nfc_unmap_count++;
138 
139 	restore_tx_packet(target, pPacket);
140 
141 	/*
142 	 * In case of SSR, we cannot call the upper layer completion
143 	 * callbacks, hence just free the nbuf and HTC packet here.
144 	 */
145 	if (target->hif_dev && hif_get_target_status(target->hif_dev)) {
146 		htc_free_control_tx_packet(target, pPacket);
147 		return;
148 	}
149 
150 	/* do completion */
151 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
152 			("HTC calling ep %d send complete callback on packet %pK\n",
153 			 pEndpoint->Id, pPacket));
154 
155 	EpTxComplete = pEndpoint->EpCallBacks.EpTxComplete;
156 	if (EpTxComplete)
157 		EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket);
158 	else
159 		qdf_nbuf_free(pPacket->pPktContext);
160 
161 
162 }
163 
164 #ifdef FEATURE_RUNTIME_PM
165 /**
166  * log_packet_info() - Log HTC packet information
167  *
168  * @target: handle of HTC context
169  * @pPacket: handle of HTC packet
170  *
171  * Return: None
172  */
173 static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket)
174 {
175 	HTC_ENDPOINT *pEndpoint = &target->endpoint[pPacket->Endpoint];
176 	HTC_EP_LOG_PKT ep_log_pkt;
177 	qdf_nbuf_t netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
178 
179 	ep_log_pkt = pEndpoint->EpCallBacks.ep_log_pkt;
180 	if (ep_log_pkt) {
181 		qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR));
182 		ep_log_pkt(pEndpoint->EpCallBacks.pContext, pPacket);
183 		qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR));
184 	}
185 }
186 
187 /**
188  * htc_inc_htt_runtime_cnt: Increment htc htt runtime count
189  * @target: handle of HTC context
190  *
191  * Return: None
192  */
193 static inline
194 void htc_inc_htt_runtime_cnt(HTC_TARGET *target)
195 {
196 	qdf_atomic_inc(&target->htc_htt_runtime_cnt);
197 }
198 #else
199 static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket)
200 {
201 }
202 
203 static inline
204 void htc_inc_htt_runtime_cnt(HTC_TARGET *target)
205 {
206 }
207 #endif
208 
209 void htc_send_complete_check_cleanup(void *context)
210 {
211 	HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *) context;
212 
213 	htc_send_complete_check(pEndpoint, 1);
214 }
215 
216 HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target)
217 {
218 	HTC_PACKET *pPacket;
219 	HTC_PACKET_QUEUE *pQueueSave;
220 	qdf_nbuf_t netbuf;
221 
222 	LOCK_HTC_TX(target);
223 	if (!target->pBundleFreeList) {
224 		UNLOCK_HTC_TX(target);
225 		netbuf = qdf_nbuf_alloc(NULL,
226 					target->MaxMsgsPerHTCBundle *
227 					target->TargetCreditSize, 0, 4, false);
228 		AR_DEBUG_ASSERT(netbuf);
229 		if (!netbuf)
230 			return NULL;
231 		pPacket = qdf_mem_malloc(sizeof(HTC_PACKET));
232 		AR_DEBUG_ASSERT(pPacket);
233 		if (!pPacket) {
234 			qdf_nbuf_free(netbuf);
235 			return NULL;
236 		}
237 		pQueueSave = qdf_mem_malloc(sizeof(HTC_PACKET_QUEUE));
238 		AR_DEBUG_ASSERT(pQueueSave);
239 		if (!pQueueSave) {
240 			qdf_nbuf_free(netbuf);
241 			qdf_mem_free(pPacket);
242 			return NULL;
243 		}
244 		INIT_HTC_PACKET_QUEUE(pQueueSave);
245 		pPacket->pContext = pQueueSave;
246 		SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
247 		pPacket->pBuffer = qdf_nbuf_data(netbuf);
248 		pPacket->BufferLength = qdf_nbuf_len(netbuf);
249 
250 		/* store the original head room so that we can restore this
251 		 * when we "free" the packet.
252 		 * free packet puts the packet back on the free list
253 		 */
254 		pPacket->netbufOrigHeadRoom = qdf_nbuf_headroom(netbuf);
255 		return pPacket;
256 	}
257 	/* already done malloc - restore from free list */
258 	pPacket = target->pBundleFreeList;
259 	AR_DEBUG_ASSERT(pPacket);
260 	if (!pPacket) {
261 		UNLOCK_HTC_TX(target);
262 		return NULL;
263 	}
264 	target->pBundleFreeList = (HTC_PACKET *) pPacket->ListLink.pNext;
265 	UNLOCK_HTC_TX(target);
266 	pPacket->ListLink.pNext = NULL;
267 
268 	return pPacket;
269 }
270 
271 void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
272 {
273 	uint32_t curentHeadRoom;
274 	qdf_nbuf_t netbuf;
275 	HTC_PACKET_QUEUE *pQueueSave;
276 
277 	netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
278 	AR_DEBUG_ASSERT(netbuf);
279 	if (!netbuf) {
280 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
281 				("\n%s: Invalid netbuf in HTC Packet\n",
282 				__func__));
283 		return;
284 	}
285 	/* HIF adds data to the headroom section of the nbuf, restore their
286 	 * original size. If this is not done, headroom keeps shrinking with
287 	 * every HIF send and eventually HIF ends up doing another malloc big
288 	 * enough to store the data + its header
289 	 */
290 
291 	curentHeadRoom = qdf_nbuf_headroom(netbuf);
292 	qdf_nbuf_pull_head(netbuf,
293 			   pPacket->netbufOrigHeadRoom - curentHeadRoom);
294 	qdf_nbuf_trim_tail(netbuf, qdf_nbuf_len(netbuf));
295 
296 	/* restore the pBuffer pointer. HIF changes this */
297 	pPacket->pBuffer = qdf_nbuf_data(netbuf);
298 	pPacket->BufferLength = qdf_nbuf_len(netbuf);
299 
300 	/* restore queue */
301 	pQueueSave = (HTC_PACKET_QUEUE *) pPacket->pContext;
302 	if (qdf_unlikely(!pQueueSave)) {
303 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
304 				("\n%s: Invalid pQueueSave in HTC Packet\n",
305 				__func__));
306 		AR_DEBUG_ASSERT(pQueueSave);
307 	} else
308 		INIT_HTC_PACKET_QUEUE(pQueueSave);
309 
310 	LOCK_HTC_TX(target);
311 	if (!target->pBundleFreeList) {
312 		target->pBundleFreeList = pPacket;
313 		pPacket->ListLink.pNext = NULL;
314 	} else {
315 		pPacket->ListLink.pNext = (DL_LIST *) target->pBundleFreeList;
316 		target->pBundleFreeList = pPacket;
317 	}
318 	UNLOCK_HTC_TX(target);
319 }
320 
321 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
322 
323 /**
324  * htc_send_update_tx_bundle_stats() - update tx bundle stats depends
325  *				on max bundle size
326  * @target: hif context
327  * @data_len: tx data len
328  * @TxCreditSize: endpoint tx credit size
329  *
330  * Return: None
331  */
332 static inline void
333 htc_send_update_tx_bundle_stats(HTC_TARGET *target,
334 				qdf_size_t data_len,
335 				int TxCreditSize)
336 {
337 	int index = ((data_len + TxCreditSize - 1) / TxCreditSize) - 1;
338 
339 	if (index < HTC_MAX_MSG_PER_BUNDLE_TX)
340 		target->tx_bundle_stats[index]++;
341 }
342 
343 /**
344  * htc_issue_tx_bundle_stats_inc() - increment in tx bundle stats
345  *				on max bundle size
346  * @target: hif context
347  *
348  * Return: None
349  */
350 static inline void
351 htc_issue_tx_bundle_stats_inc(HTC_TARGET *target)
352 {
353 	target->tx_bundle_stats[0]++;
354 }
355 #else
356 
357 static inline void
358 htc_send_update_tx_bundle_stats(HTC_TARGET *target,
359 				qdf_size_t data_len,
360 				int TxCreditSize)
361 {
362 }
363 
364 static inline void
365 htc_issue_tx_bundle_stats_inc(HTC_TARGET *target)
366 {
367 }
368 #endif
369 
370 #if defined(HIF_USB) || defined(HIF_SDIO)
371 #ifdef ENABLE_BUNDLE_TX
372 static QDF_STATUS htc_send_bundled_netbuf(HTC_TARGET *target,
373 					HTC_ENDPOINT *pEndpoint,
374 					unsigned char *pBundleBuffer,
375 					HTC_PACKET *pPacketTx)
376 {
377 	qdf_size_t data_len;
378 	QDF_STATUS status;
379 	qdf_nbuf_t bundleBuf;
380 	uint32_t data_attr = 0;
381 
382 	bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
383 	data_len = pBundleBuffer - qdf_nbuf_data(bundleBuf);
384 	qdf_nbuf_put_tail(bundleBuf, data_len);
385 	SET_HTC_PACKET_INFO_TX(pPacketTx,
386 			       target,
387 			       pBundleBuffer,
388 			       data_len,
389 			       pEndpoint->Id, HTC_TX_PACKET_TAG_BUNDLED);
390 	LOCK_HTC_TX(target);
391 	HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacketTx);
392 	pEndpoint->ul_outstanding_cnt++;
393 	UNLOCK_HTC_TX(target);
394 #if DEBUG_BUNDLE
395 	qdf_print(" Send bundle EP%d buffer size:0x%x, total:0x%x, count:%d.",
396 		  pEndpoint->Id,
397 		  pEndpoint->TxCreditSize,
398 		  data_len, data_len / pEndpoint->TxCreditSize);
399 #endif
400 
401 	htc_send_update_tx_bundle_stats(target, data_len,
402 					pEndpoint->TxCreditSize);
403 
404 	status = hif_send_head(target->hif_dev,
405 			       pEndpoint->UL_PipeID,
406 			       pEndpoint->Id, data_len,
407 			       bundleBuf, data_attr);
408 	if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
409 		HTC_PACKET_QUEUE requeue;
410 
411 		qdf_print("hif_send_head failed(len=%zu).", data_len);
412 		INIT_HTC_PACKET_QUEUE(&requeue);
413 		LOCK_HTC_TX(target);
414 		pEndpoint->ul_outstanding_cnt--;
415 		HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacketTx);
416 
417 		if (pPacketTx->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) {
418 			HTC_PACKET *temp_packet;
419 			HTC_PACKET_QUEUE *packet_queue =
420 				(HTC_PACKET_QUEUE *)pPacketTx->pContext;
421 
422 			HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(packet_queue,
423 							      temp_packet) {
424 				HTC_PACKET_ENQUEUE(&requeue, temp_packet);
425 			} HTC_PACKET_QUEUE_ITERATE_END;
426 
427 			UNLOCK_HTC_TX(target);
428 			free_htc_bundle_packet(target, pPacketTx);
429 			LOCK_HTC_TX(target);
430 
431 		} else {
432 			HTC_PACKET_ENQUEUE(&requeue, pPacketTx);
433 		}
434 
435 		HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
436 						  &requeue);
437 		UNLOCK_HTC_TX(target);
438 	}
439 	return status;
440 }
441 
442 #ifdef QCA_TX_PADDING_CREDIT_SUPPORT
443 #define SDIO_BLOCK_SIZE		512
444 static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep)
445 {
446 	int ret = 0;
447 
448 	if (!ep || !ep->EpCallBacks.pContext ||
449 	    !ep->EpCallBacks.ep_padding_credit_update)
450 		return 1;
451 
452 	ret = ep->EpCallBacks.ep_padding_credit_update(ep->EpCallBacks.pContext,
453 						       0);
454 
455 	if (ret < 2)
456 		AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s ret %d\n", __func__, ret));
457 
458 	return ret;
459 }
460 
461 static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
462 				       HTC_PACKET *p_last_htc_pkt,
463 				       unsigned char *p_last_pkt_bundle_buffer,
464 				       unsigned char **p_bundle_buffer,
465 				       int tot_data_len)
466 {
467 	bool extra_tx_credit = FALSE;
468 	HTC_FRAME_HDR *p_htc_hdr;
469 	int first_buf_bundled_len = 0, last_buf_len = 0;
470 	int sdio_pad = 0, free_space = 0;
471 	int (*update_ep_padding_credit)(void *, int);
472 
473 	update_ep_padding_credit = ep->EpCallBacks.ep_padding_credit_update;
474 
475 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
476 			("%s Tot data_len = %d\n", __func__, tot_data_len));
477 
478 	if (!p_last_htc_pkt)
479 		return extra_tx_credit;
480 
481 	last_buf_len = (p_last_htc_pkt->ActualLength + HTC_HDR_LENGTH);
482 	if (tot_data_len != last_buf_len) {
483 		first_buf_bundled_len = tot_data_len - ep->TxCreditSize;
484 		free_space = tot_data_len -
485 					(first_buf_bundled_len + last_buf_len);
486 	} else {
487 		free_space = ep->TxCreditSize - tot_data_len;
488 	}
489 
490 	sdio_pad = SDIO_BLOCK_SIZE - ((first_buf_bundled_len + last_buf_len) %
491 			SDIO_BLOCK_SIZE);
492 
493 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
494 			("%s first_buf_bundled_len = %d last_buf_len = %d\n",
495 			__func__, first_buf_bundled_len, last_buf_len));
496 
497 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
498 			("%s sdio_pad = %d free_space = %d\n", __func__,
499 			sdio_pad, free_space));
500 
501 	if (sdio_pad <= free_space) {
502 		if (p_bundle_buffer && *p_bundle_buffer) {
503 			/* Align Tx bundled buf to avoid a extra Padding buf */
504 			*p_bundle_buffer -= (free_space - sdio_pad);
505 		}
506 	} else {
507 		/* Extra Padding Buffer needed, consume extra tx credit */
508 		AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
509 				("%s Used a Tx credit for Padding Buffer\n",
510 				 __func__));
511 		p_htc_hdr = (HTC_FRAME_HDR *)(p_last_pkt_bundle_buffer);
512 		p_htc_hdr->Flags |= HTC_FLAGS_PADDING_CHECK;
513 		extra_tx_credit = TRUE;
514 		if (ep->EpCallBacks.ep_padding_credit_update) {
515 			/* Decrement 1 credit at host,
516 			 * due to extra tx credit consumed by padding buffer
517 			 */
518 			update_ep_padding_credit(ep->EpCallBacks.pContext, -1);
519 		}
520 	}
521 	return extra_tx_credit;
522 }
523 #else
524 static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep)
525 {
526 	return 1;
527 }
528 
529 static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
530 				       HTC_PACKET *p_last_htc_pkt,
531 				       unsigned char *p_last_pkt_bundle_buffer,
532 				       unsigned char **p_bundle_buffer,
533 				       int tot_data_len)
534 {
535 	return FALSE;
536 }
537 #endif
538 
539 /**
540  * htc_issue_packets_bundle() - HTC function to send bundle packets from a queue
541  * @target: HTC target on which packets need to be sent
542  * @pEndpoint: logical endpoint on which packets needs to be sent
543  * @pPktQueue: HTC packet queue containing the list of packets to be sent
544  *
545  * Return: void
546  */
547 static void htc_issue_packets_bundle(HTC_TARGET *target,
548 				     HTC_ENDPOINT *pEndpoint,
549 				     HTC_PACKET_QUEUE *pPktQueue)
550 {
551 	int i, frag_count, nbytes;
552 	qdf_nbuf_t netbuf, bundleBuf;
553 	unsigned char *pBundleBuffer = NULL;
554 	HTC_PACKET *pPacket = NULL, *pPacketTx = NULL;
555 	HTC_FRAME_HDR *pHtcHdr;
556 	int last_credit_pad = 0;
557 	int creditPad, creditRemainder, transferLength, bundlesSpaceRemaining =
558 		0;
559 	HTC_PACKET_QUEUE *pQueueSave = NULL;
560 	HTC_PACKET *p_last_htc_pkt = NULL;
561 	unsigned char *p_last_pkt_bundle_buffer = NULL;
562 
563 	bundlesSpaceRemaining =
564 		target->MaxMsgsPerHTCBundle * pEndpoint->TxCreditSize;
565 	pPacketTx = allocate_htc_bundle_packet(target);
566 	if (!pPacketTx) {
567 		/* good time to panic */
568 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
569 				("allocate_htc_bundle_packet failed\n"));
570 		AR_DEBUG_ASSERT(false);
571 		return;
572 	}
573 	bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
574 	pBundleBuffer = qdf_nbuf_data(bundleBuf);
575 	pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext;
576 	while (1) {
577 		if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
578 			if (htc_tx_pad_credit_avail(pEndpoint) < 1)
579 				break;
580 		}
581 		pPacket = htc_packet_dequeue(pPktQueue);
582 		if (!pPacket)
583 			break;
584 		creditPad = 0;
585 		transferLength = pPacket->ActualLength + HTC_HDR_LENGTH;
586 		creditRemainder = transferLength % pEndpoint->TxCreditSize;
587 		if (creditRemainder != 0) {
588 			if (transferLength < pEndpoint->TxCreditSize) {
589 				creditPad = pEndpoint->TxCreditSize -
590 					    transferLength;
591 			} else {
592 				creditPad = creditRemainder;
593 			}
594 			transferLength += creditPad;
595 		}
596 
597 		if (bundlesSpaceRemaining < transferLength) {
598 			htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt,
599 						   p_last_pkt_bundle_buffer,
600 						   &pBundleBuffer,
601 						   pBundleBuffer -
602 						   qdf_nbuf_data(bundleBuf));
603 
604 			/* send out previous buffer */
605 			htc_send_bundled_netbuf(target, pEndpoint,
606 						pBundleBuffer - last_credit_pad,
607 						pPacketTx);
608 			/* One packet has been dequeued from sending queue when enter
609 			 * this loop, so need to add 1 back for this checking.
610 			 */
611 			if ((HTC_PACKET_QUEUE_DEPTH(pPktQueue) + 1) <
612 			    HTC_MIN_MSG_PER_BUNDLE) {
613 				HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
614 				return;
615 			}
616 			bundlesSpaceRemaining =
617 				target->MaxMsgsPerHTCBundle *
618 				pEndpoint->TxCreditSize;
619 			pPacketTx = allocate_htc_bundle_packet(target);
620 			if (!pPacketTx) {
621 				HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
622 				/* good time to panic */
623 				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
624 						("allocate_htc_bundle_packet failed\n"));
625 				AR_DEBUG_ASSERT(false);
626 				return;
627 			}
628 			bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx);
629 			pBundleBuffer = qdf_nbuf_data(bundleBuf);
630 			pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext;
631 		}
632 
633 		p_last_htc_pkt = pPacket;
634 		p_last_pkt_bundle_buffer = pBundleBuffer;
635 
636 		bundlesSpaceRemaining -= transferLength;
637 		netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
638 
639 		if (hif_get_bus_type(target->hif_dev) != QDF_BUS_TYPE_USB) {
640 			pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(
641 								netbuf, 0);
642 			HTC_WRITE32(pHtcHdr,
643 				SM(pPacket->ActualLength,
644 				HTC_FRAME_HDR_PAYLOADLEN) |
645 				SM(pPacket->PktInfo.AsTx.SendFlags |
646 				HTC_FLAGS_SEND_BUNDLE,
647 				HTC_FRAME_HDR_FLAGS) |
648 				SM(pPacket->Endpoint,
649 				HTC_FRAME_HDR_ENDPOINTID));
650 			HTC_WRITE32((uint32_t *) pHtcHdr + 1,
651 				SM(pPacket->PktInfo.AsTx.SeqNo,
652 				HTC_FRAME_HDR_CONTROLBYTES1) | SM(creditPad,
653 				HTC_FRAME_HDR_RESERVED));
654 			pHtcHdr->reserved = creditPad;
655 		}
656 		frag_count = qdf_nbuf_get_num_frags(netbuf);
657 		nbytes = pPacket->ActualLength + HTC_HDR_LENGTH;
658 		for (i = 0; i < frag_count && nbytes > 0; i++) {
659 			int frag_len = qdf_nbuf_get_frag_len(netbuf, i);
660 			unsigned char *frag_addr =
661 				qdf_nbuf_get_frag_vaddr(netbuf, i);
662 			if (frag_len > nbytes)
663 				frag_len = nbytes;
664 			qdf_mem_copy(pBundleBuffer, frag_addr, frag_len);
665 			nbytes -= frag_len;
666 			pBundleBuffer += frag_len;
667 		}
668 		HTC_PACKET_ENQUEUE(pQueueSave, pPacket);
669 		pBundleBuffer += creditPad;
670 
671 		/* last one can't be packed. */
672 		if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)
673 			last_credit_pad = creditPad;
674 	}
675 	/* send out remaining buffer */
676 	if (pBundleBuffer != qdf_nbuf_data(bundleBuf)) {
677 		htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt,
678 					   p_last_pkt_bundle_buffer,
679 					   &pBundleBuffer,
680 					   pBundleBuffer -
681 					   qdf_nbuf_data(bundleBuf));
682 
683 		htc_send_bundled_netbuf(target, pEndpoint,
684 					pBundleBuffer - last_credit_pad,
685 					pPacketTx);
686 	} else {
687 		free_htc_bundle_packet(target, pPacketTx);
688 	}
689 }
690 #endif /* ENABLE_BUNDLE_TX */
691 #else
692 static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep)
693 {
694 	return 1;
695 }
696 
697 bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
698 				HTC_PACKET *p_last_htc_pkt,
699 				unsigned char *p_last_pkt_bundle_buffer,
700 				unsigned char **p_bundle_buffer,
701 				int tot_data_len);
702 bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep,
703 				HTC_PACKET *p_last_htc_pkt,
704 				unsigned char *p_last_pkt_bundle_buffer,
705 				unsigned char **p_bundle_buffer,
706 				int tot_data_len)
707 {
708 	return FALSE;
709 }
710 
711 static void htc_issue_packets_bundle(HTC_TARGET *target,
712 				     HTC_ENDPOINT *pEndpoint,
713 				     HTC_PACKET_QUEUE *pPktQueue)
714 {
715 }
716 #endif
717 
718 /**
719  * htc_issue_packets() - HTC function to send packets from a queue
720  * @target: HTC target on which packets need to be sent
721  * @pEndpoint: logical endpoint on which packets needs to be sent
722  * @pPktQueue: HTC packet queue containing the list of packets to be sent
723  *
724  * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
725  */
726 static QDF_STATUS htc_issue_packets(HTC_TARGET *target,
727 				  HTC_ENDPOINT *pEndpoint,
728 				  HTC_PACKET_QUEUE *pPktQueue)
729 {
730 	QDF_STATUS status = QDF_STATUS_SUCCESS;
731 	qdf_nbuf_t netbuf;
732 	HTC_PACKET *pPacket = NULL;
733 	uint16_t payloadLen;
734 	HTC_FRAME_HDR *pHtcHdr;
735 	uint32_t data_attr = 0;
736 	enum qdf_bus_type bus_type;
737 	QDF_STATUS ret;
738 	bool rt_put = false;
739 	bool used_extra_tx_credit = false;
740 	uint8_t *buf = NULL;
741 	int (*update_ep_padding_credit)(void *, int);
742 	void *ctx = NULL;
743 	bool rt_put_in_resp;
744 	int32_t sys_state = HIF_SYSTEM_PM_STATE_ON;
745 
746 	update_ep_padding_credit =
747 			pEndpoint->EpCallBacks.ep_padding_credit_update;
748 
749 	bus_type = hif_get_bus_type(target->hif_dev);
750 
751 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
752 			("+htc_issue_packets: Queue: %pK, Pkts %d\n", pPktQueue,
753 			 HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
754 	while (true) {
755 		rt_put_in_resp = false;
756 		if (HTC_TX_BUNDLE_ENABLED(target) &&
757 		    HTC_PACKET_QUEUE_DEPTH(pPktQueue) >=
758 		    HTC_MIN_MSG_PER_BUNDLE) {
759 			switch (bus_type) {
760 			case QDF_BUS_TYPE_SDIO:
761 				if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint))
762 					break;
763 				if (update_ep_padding_credit) {
764 					if (htc_tx_pad_credit_avail
765 					    (pEndpoint) < 1)
766 						break;
767 				}
768 				fallthrough;
769 			case QDF_BUS_TYPE_USB:
770 				htc_issue_packets_bundle(target,
771 							pEndpoint,
772 							pPktQueue);
773 				break;
774 			default:
775 				break;
776 			}
777 		}
778 		/* if not bundling or there was a packet that could not be
779 		 * placed in a bundle, and send it by normal way
780 		 */
781 		if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
782 			if (htc_tx_pad_credit_avail(pEndpoint) < 1) {
783 				status = QDF_STATUS_E_FAILURE;
784 				break;
785 			}
786 		}
787 
788 		pPacket = htc_packet_dequeue(pPktQueue);
789 		if (!pPacket) {
790 			/* local queue is fully drained */
791 			break;
792 		}
793 
794 		netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
795 		AR_DEBUG_ASSERT(netbuf);
796 		/* Non-credit enabled endpoints have been mapped and setup by
797 		 * now, so no need to revisit the HTC headers
798 		 */
799 		if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
800 
801 			payloadLen = pPacket->ActualLength;
802 			/* setup HTC frame header */
803 
804 			pHtcHdr = (HTC_FRAME_HDR *)
805 				qdf_nbuf_get_frag_vaddr(netbuf, 0);
806 			if (qdf_unlikely(!pHtcHdr)) {
807 				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
808 						("%s Invalid pHtcHdr\n",
809 						 __func__));
810 				AR_DEBUG_ASSERT(pHtcHdr);
811 				status = QDF_STATUS_E_FAILURE;
812 				break;
813 			}
814 
815 			HTC_WRITE32(pHtcHdr,
816 					SM(payloadLen,
817 						HTC_FRAME_HDR_PAYLOADLEN) |
818 					SM(pPacket->PktInfo.AsTx.SendFlags,
819 						HTC_FRAME_HDR_FLAGS) |
820 					SM(pPacket->Endpoint,
821 						HTC_FRAME_HDR_ENDPOINTID));
822 			HTC_WRITE32(((uint32_t *) pHtcHdr) + 1,
823 				    SM(pPacket->PktInfo.AsTx.SeqNo,
824 				       HTC_FRAME_HDR_CONTROLBYTES1));
825 
826 			/*
827 			 * Now that the HTC frame header has been added, the
828 			 * netbuf can be mapped.  This only applies to non-data
829 			 * frames, since data frames were already mapped as they
830 			 * entered into the driver.
831 			 */
832 			ret = qdf_nbuf_map(target->osdev,
833 				GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
834 				QDF_DMA_TO_DEVICE);
835 			if (ret != QDF_STATUS_SUCCESS) {
836 				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
837 					("%s nbuf Map Fail Endpnt %pK\n",
838 					__func__, pEndpoint));
839 				HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
840 				status = QDF_STATUS_E_FAILURE;
841 				break;
842 			}
843 			pPacket->PktInfo.AsTx.Flags |=
844 				HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
845 		}
846 
847 		if (!pEndpoint->async_update) {
848 			LOCK_HTC_TX(target);
849 		}
850 		/* store in look up queue to match completions */
851 		HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket);
852 		INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
853 		pEndpoint->ul_outstanding_cnt++;
854 		if (!pEndpoint->async_update) {
855 			UNLOCK_HTC_TX(target);
856 			hif_send_complete_check(target->hif_dev,
857 					pEndpoint->UL_PipeID, false);
858 		}
859 
860 		if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_SYSTEM_SUSPEND) {
861 			sys_state = hif_system_pm_get_state(target->hif_dev);
862 			hif_system_pm_set_state_suspending(target->hif_dev);
863 		}
864 
865 		htc_packet_set_magic_cookie(pPacket, HTC_PACKET_MAGIC_COOKIE);
866 		/*
867 		 * For HTT messages without a response from fw,
868 		 *   do the runtime put here.
869 		 * otherwise runtime put will be done when the fw response comes
870 		 */
871 		if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_RUNTIME_PUT) {
872 			rt_put = true;
873 		} else if (pPacket->PktInfo.AsTx.Tag ==
874 			 HTC_TX_PACKET_TAG_RTPM_PUT_RC) {
875 			rt_put_in_resp = true;
876 			htc_inc_htt_runtime_cnt(target);
877 		}
878 
879 #if DEBUG_BUNDLE
880 		qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.",
881 			  pEndpoint->Id,
882 			  pEndpoint->TxCreditSize,
883 			  HTC_HDR_LENGTH + pPacket->ActualLength);
884 #endif
885 		buf = (uint8_t *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
886 		used_extra_tx_credit =
887 			htc_handle_extra_tx_credit(pEndpoint, pPacket, buf,
888 						   NULL, pPacket->ActualLength +
889 						   HTC_HDR_LENGTH);
890 
891 		status = hif_send_head(target->hif_dev,
892 				       pEndpoint->UL_PipeID, pEndpoint->Id,
893 				       HTC_HDR_LENGTH + pPacket->ActualLength,
894 				       netbuf, data_attr);
895 
896 		if (status != QDF_STATUS_SUCCESS) {
897 			if (rt_put_in_resp)
898 				htc_dec_return_htt_runtime_cnt((void *)target);
899 
900 			if (pPacket->PktInfo.AsTx.Tag ==
901 			    HTC_TX_PACKET_SYSTEM_SUSPEND)
902 				__hif_system_pm_set_state(target->hif_dev,
903 							  sys_state);
904 
905 			if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
906 				if (used_extra_tx_credit) {
907 					ctx = pEndpoint->EpCallBacks.pContext;
908 					update_ep_padding_credit(ctx, 1);
909 				}
910 			}
911 		}
912 
913 		htc_issue_tx_bundle_stats_inc(target);
914 
915 		target->ce_send_cnt++;
916 		pEndpoint->htc_send_cnt++;
917 
918 		if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
919 			if (status != QDF_STATUS_E_RESOURCES) {
920 				/* TODO : if more than 1 endpoint maps to the
921 				 * same PipeID it is possible to run out of
922 				 * resources in the HIF layer. Don't emit the
923 				 * error
924 				 */
925 				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
926 						("hif_send Failed status:%d\n",
927 						 status));
928 			} else {
929 				if (target->htc_pkt_dbg) {
930 					if (pEndpoint->num_requeues_warn >
931 						MAX_REQUEUE_WARN) {
932 						hif_print_napi_stats(target->hif_dev);
933 					}
934 				}
935 			}
936 
937 			/* only unmap if we mapped in this function */
938 			if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
939 				qdf_nbuf_unmap(target->osdev,
940 					GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
941 					QDF_DMA_TO_DEVICE);
942 				pPacket->PktInfo.AsTx.Flags &=
943 					~HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
944 			}
945 
946 			if (!pEndpoint->async_update) {
947 				LOCK_HTC_TX(target);
948 			}
949 			target->ce_send_cnt--;
950 			pEndpoint->htc_send_cnt--;
951 			pEndpoint->ul_outstanding_cnt--;
952 			HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket);
953 			htc_packet_set_magic_cookie(pPacket, 0);
954 			/* put it back into the callers queue */
955 			HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket);
956 			/* reclaim credits */
957 			HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,
958 							      pPacket) {
959 			    pEndpoint->TxCredits +=
960 				pPacket->PktInfo.AsTx.CreditsUsed;
961 			} HTC_PACKET_QUEUE_ITERATE_END;
962 			if (!pEndpoint->async_update) {
963 				UNLOCK_HTC_TX(target);
964 			}
965 			break;
966 		}
967 		if (rt_put) {
968 			hif_rtpm_put(HIF_RTPM_PUT_ASYNC, HIF_RTPM_ID_HTT);
969 			rt_put = false;
970 		}
971 	}
972 
973 	if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
974 		if (((status == QDF_STATUS_E_RESOURCES) &&
975 		     (pEndpoint->num_requeues_warn > MAX_REQUEUE_WARN)) ||
976 		     (status != QDF_STATUS_E_RESOURCES)) {
977 			QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_INFO,
978 				  "failed pkt:0x%pK status:%d endpoint:%d",
979 				  pPacket, status, pEndpoint->Id);
980 		}
981 
982 	}
983 
984 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_issue_packets\n"));
985 
986 	return status;
987 }
988 
989 #ifdef FEATURE_RUNTIME_PM
990 /**
991  * extract_htc_pm_packets(): move pm packets from endpoint into queue
992  * @endpoint: which endpoint to extract packets from
993  * @queue: a queue to store extracted packets in.
994  *
995  * remove pm packets from the endpoint's tx queue.
996  * queue them into a queue
997  */
998 static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
999 				HTC_PACKET_QUEUE *queue)
1000 {
1001 	HTC_PACKET *packet;
1002 
1003 	/* only WMI endpoint has power management packets */
1004 	if (endpoint->service_id != WMI_CONTROL_SVC)
1005 		return;
1006 
1007 	ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet,
1008 			HTC_PACKET, ListLink) {
1009 		if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_AUTO_PM) {
1010 			HTC_PACKET_REMOVE(&endpoint->TxQueue, packet);
1011 			HTC_PACKET_ENQUEUE(queue, packet);
1012 		}
1013 	} ITERATE_END
1014 }
1015 
1016 /**
1017  * queue_htc_pm_packets(): queue pm packets with priority
1018  * @endpoint: endpoint to queue packets to
1019  * @queue: queue of pm packets to enqueue
1020  *
1021  * suspend resume packets get special treatment & priority.
1022  * need to queue them at the front of the queue.
1023  */
1024 static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
1025 				 HTC_PACKET_QUEUE *queue)
1026 {
1027 	if (endpoint->service_id != WMI_CONTROL_SVC)
1028 		return;
1029 
1030 	HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&endpoint->TxQueue, queue);
1031 }
1032 
1033 /**
1034  * htc_dec_wmi_runtime_cnt: Decrement htc wmi runtime count
1035  * @target: HTC target
1036  * @rtpm_code: RTPM code
1037  *
1038  * Return: None
1039  */
1040 static inline
1041 void htc_dec_wmi_runtime_cnt(HTC_TARGET *target, uint8_t rtpm_code)
1042 {
1043 	if (rtpm_code == HIF_RTPM_ID_WMI)
1044 		qdf_atomic_dec(&target->htc_wmi_runtime_cnt);
1045 }
1046 
1047 /**
1048  * htc_inc_wmi_runtime_cnt: Increment htc wmi runtime count
1049  * @target: HTC target
1050  * @rtpm_code: RTPM code
1051  *
1052  * Return: None
1053  */
1054 static inline
1055 void htc_inc_wmi_runtime_cnt(HTC_TARGET *target, uint8_t rtpm_code)
1056 {
1057 	if (rtpm_code == HIF_RTPM_ID_WMI)
1058 		qdf_atomic_inc(&target->htc_wmi_runtime_cnt);
1059 }
1060 #else
1061 static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
1062 		HTC_PACKET_QUEUE *queue)
1063 {}
1064 
1065 static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
1066 		HTC_PACKET_QUEUE *queue)
1067 {}
1068 
1069 static inline
1070 void htc_dec_wmi_runtime_cnt(HTC_TARGET *target, uint8_t rtpm_code)
1071 {
1072 }
1073 
1074 static inline
1075 void htc_inc_wmi_runtime_cnt(HTC_TARGET *target, uint8_t rtpm_code)
1076 {
1077 }
1078 #endif
1079 
1080 /**
1081  * htc_send_pkts_get_rtpm_id() - get runtime pm dbgid by service_id
1082  * @service_id: service for endpoint
1083  *
1084  * For service_id HTT_DATA_MSG_SVC, HTT message donot have a tx complete
1085  * from CE level, so they need runtime put which only can happen in fw
1086  * response. runtime put will happens at 2 ways.
1087  *    1 if packet tag HTC_TX_PACKET_TAG_RUNTIME_PUT, runtime put
1088  *      will be just in htc_issue_packets. as such pkt doesn't have
1089  *      a response from fw.
1090  *    2 other pkt must have a response from fw, it will be handled
1091  *      by fw response using htc_pm_runtime_put.
1092  *
1093  * For other service_id, they have tx_completion from CE, so they will be
1094  * handled in htc_tx_completion_handler, except packet tag as
1095  * HTC_TX_PACKET_TAG_AUTO_PM, pm related wmi cmd don't need a runtime
1096  * put/get.
1097  *
1098  *
1099  * Return: rtpm id to trace who used it
1100  */
1101 static unsigned int
1102 htc_send_pkts_get_rtpm_id(HTC_SERVICE_ID service_id)
1103 {
1104 	if (service_id == HTT_DATA_MSG_SVC)
1105 		return HIF_RTPM_ID_HTT;
1106 	else
1107 		return HIF_RTPM_ID_WMI;
1108 }
1109 
1110 #ifdef SYSTEM_PM_CHECK
1111 /**
1112  * extract_htc_system_resume_pkts(): Move system pm resume packets from endpoint
1113  *  into queue
1114  * @endpoint: which endpoint to extract packets from
1115  * @queue: a queue to store extracted packets in.
1116  *
1117  * Remove pm packets from the endpoint's tx queue and enqueue
1118  * them into a queue
1119  */
1120 static void extract_htc_system_resume_pkts(HTC_ENDPOINT *endpoint,
1121 					   HTC_PACKET_QUEUE *queue)
1122 {
1123 	HTC_PACKET *packet;
1124 
1125 	/* only WMI endpoint has power management packets */
1126 	if (endpoint->service_id != WMI_CONTROL_SVC)
1127 		return;
1128 
1129 	ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet,
1130 				       HTC_PACKET, ListLink) {
1131 		if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_SYSTEM_RESUME) {
1132 			HTC_PACKET_REMOVE(&endpoint->TxQueue, packet);
1133 			HTC_PACKET_ENQUEUE(queue, packet);
1134 		}
1135 	} ITERATE_END
1136 }
1137 #else
1138 static inline
1139 void extract_htc_system_resume_pkts(HTC_ENDPOINT *endpoint,
1140 				    HTC_PACKET_QUEUE *queue)
1141 {
1142 }
1143 #endif
1144 
1145 /**
1146  * get_htc_send_packets_credit_based() - get packets based on available credits
1147  * @target: HTC target on which packets need to be sent
1148  * @pEndpoint: logical endpoint on which packets needs to be sent
1149  * @pQueue: HTC packet queue containing the list of packets to be sent
1150  *
1151  * Get HTC send packets from TX queue on an endpoint based on available credits.
1152  * The function moves the packets from TX queue of the endpoint to pQueue.
1153  *
1154  * Return: None
1155  */
1156 static void get_htc_send_packets_credit_based(HTC_TARGET *target,
1157 					      HTC_ENDPOINT *pEndpoint,
1158 					      HTC_PACKET_QUEUE *pQueue)
1159 {
1160 	int creditsRequired;
1161 	int remainder;
1162 	uint8_t sendFlags;
1163 	HTC_PACKET *pPacket;
1164 	unsigned int transferLength;
1165 	HTC_PACKET_QUEUE *tx_queue;
1166 	HTC_PACKET_QUEUE pm_queue;
1167 	bool do_pm_get = false;
1168 	unsigned int rtpm_code = 0;
1169 	int ret;
1170 	HTC_PACKET_QUEUE sys_pm_queue;
1171 	bool sys_pm_check = false;
1172 
1173 	/*** NOTE : the TX lock is held when this function is called ***/
1174 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1175 			("+get_htc_send_packets_credit_based\n"));
1176 
1177 	INIT_HTC_PACKET_QUEUE(&pm_queue);
1178 	extract_htc_pm_packets(pEndpoint, &pm_queue);
1179 	if (HTC_QUEUE_EMPTY(&pm_queue)) {
1180 		do_pm_get = true;
1181 
1182 		INIT_HTC_PACKET_QUEUE(&sys_pm_queue);
1183 		extract_htc_system_resume_pkts(pEndpoint, &sys_pm_queue);
1184 		if (HTC_QUEUE_EMPTY(&sys_pm_queue)) {
1185 			tx_queue = &pEndpoint->TxQueue;
1186 			sys_pm_check = true;
1187 		} else {
1188 			tx_queue = &sys_pm_queue;
1189 		}
1190 	} else {
1191 		tx_queue = &pm_queue;
1192 	}
1193 
1194 	/* loop until we can grab as many packets out of the queue as we can */
1195 	while (true) {
1196 		if (do_pm_get) {
1197 			rtpm_code = htc_send_pkts_get_rtpm_id(
1198 							pEndpoint->service_id);
1199 			ret = hif_rtpm_get(HIF_RTPM_GET_ASYNC, rtpm_code);
1200 			if (ret) {
1201 				/* bus suspended, runtime resume issued */
1202 				QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
1203 				pPacket = htc_get_pkt_at_head(tx_queue);
1204 				if (!pPacket)
1205 					break;
1206 				log_packet_info(target, pPacket);
1207 				break;
1208 			}
1209 			htc_inc_wmi_runtime_cnt(target, rtpm_code);
1210 		}
1211 
1212 		sendFlags = 0;
1213 		/* get packet at head, but don't remove it */
1214 		pPacket = htc_get_pkt_at_head(tx_queue);
1215 		if (!pPacket) {
1216 			if (do_pm_get) {
1217 				hif_rtpm_put(HIF_RTPM_PUT_ASYNC, rtpm_code);
1218 				htc_dec_wmi_runtime_cnt(target, rtpm_code);
1219 			}
1220 			break;
1221 		}
1222 
1223 		if (sys_pm_check &&
1224 		    hif_system_pm_state_check(target->hif_dev)) {
1225 			if (do_pm_get) {
1226 				hif_rtpm_put(HIF_RTPM_PUT_ASYNC, rtpm_code);
1227 				htc_dec_wmi_runtime_cnt(target, rtpm_code);
1228 			}
1229 			break;
1230 		}
1231 
1232 		AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1233 				(" Got head packet:%pK , Queue Depth: %d\n",
1234 				 pPacket,
1235 				 HTC_PACKET_QUEUE_DEPTH(tx_queue)));
1236 
1237 		transferLength = pPacket->ActualLength + HTC_HDR_LENGTH;
1238 
1239 		if (transferLength <= pEndpoint->TxCreditSize) {
1240 			creditsRequired = 1;
1241 		} else {
1242 			/* figure out how many credits this message requires */
1243 			creditsRequired =
1244 				transferLength / pEndpoint->TxCreditSize;
1245 			remainder = transferLength % pEndpoint->TxCreditSize;
1246 
1247 			if (remainder)
1248 				creditsRequired++;
1249 		}
1250 
1251 		AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1252 				(" Credits Required:%d   Got:%d\n",
1253 				 creditsRequired, pEndpoint->TxCredits));
1254 
1255 		if (pEndpoint->Id == ENDPOINT_0) {
1256 			/*
1257 			 * endpoint 0 is special, it always has a credit and
1258 			 * does not require credit based flow control
1259 			 */
1260 			creditsRequired = 0;
1261 		} else {
1262 
1263 			if (pEndpoint->TxCredits < creditsRequired) {
1264 #if DEBUG_CREDIT
1265 				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1266 						("EP%d,No Credit now.%d < %d\n",
1267 						 pEndpoint->Id,
1268 						 pEndpoint->TxCredits,
1269 						 creditsRequired));
1270 #endif
1271 				if (do_pm_get) {
1272 					hif_rtpm_put(HIF_RTPM_PUT_ASYNC,
1273 						     rtpm_code);
1274 					htc_dec_wmi_runtime_cnt(target,
1275 								rtpm_code);
1276 				}
1277 
1278 				break;
1279 			}
1280 
1281 			pEndpoint->TxCredits -= creditsRequired;
1282 			INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed,
1283 					creditsRequired);
1284 
1285 			/* check if we need credits back from the target */
1286 			if (pEndpoint->TxCredits <=
1287 			    pEndpoint->TxCreditsPerMaxMsg) {
1288 				/* tell the target we need credits ASAP! */
1289 				sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
1290 				if (pEndpoint->service_id == WMI_CONTROL_SVC) {
1291 					htc_credit_record(HTC_REQUEST_CREDIT,
1292 							  pEndpoint->TxCredits,
1293 							  HTC_PACKET_QUEUE_DEPTH
1294 							  (tx_queue));
1295 					hif_latency_detect_credit_record_time(
1296 						HIF_REQUEST_CREDIT,
1297 						target->hif_dev);
1298 				}
1299 				INC_HTC_EP_STAT(pEndpoint,
1300 						TxCreditLowIndications, 1);
1301 #if DEBUG_CREDIT
1302 				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1303 						(" EP%d Needs Credits\n",
1304 						 pEndpoint->Id));
1305 #endif
1306 			}
1307 		}
1308 
1309 		/* now we can fully dequeue */
1310 		pPacket = htc_packet_dequeue(tx_queue);
1311 		if (pPacket) {
1312 			/* save the number of credits this packet consumed */
1313 			pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired;
1314 			/* save send flags */
1315 			pPacket->PktInfo.AsTx.SendFlags = sendFlags;
1316 
1317 			/* queue this packet into the caller's queue */
1318 			HTC_PACKET_ENQUEUE(pQueue, pPacket);
1319 		}
1320 	}
1321 
1322 	if (!HTC_QUEUE_EMPTY(&pm_queue))
1323 		queue_htc_pm_packets(pEndpoint, &pm_queue);
1324 
1325 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1326 			("-get_htc_send_packets_credit_based\n"));
1327 
1328 }
1329 
1330 static void get_htc_send_packets(HTC_TARGET *target,
1331 				 HTC_ENDPOINT *pEndpoint,
1332 				 HTC_PACKET_QUEUE *pQueue, int Resources)
1333 {
1334 
1335 	HTC_PACKET *pPacket;
1336 	HTC_PACKET_QUEUE *tx_queue;
1337 	HTC_PACKET_QUEUE pm_queue;
1338 	bool do_pm_get = false;
1339 	unsigned int rtpm_code = 0;
1340 	int ret;
1341 
1342 	/*** NOTE : the TX lock is held when this function is called ***/
1343 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1344 			("+get_htc_send_packets %d resources\n", Resources));
1345 
1346 	INIT_HTC_PACKET_QUEUE(&pm_queue);
1347 	extract_htc_pm_packets(pEndpoint, &pm_queue);
1348 	if (HTC_QUEUE_EMPTY(&pm_queue)) {
1349 		tx_queue = &pEndpoint->TxQueue;
1350 		do_pm_get = true;
1351 	} else {
1352 		tx_queue = &pm_queue;
1353 	}
1354 
1355 	/* loop until we can grab as many packets out of the queue as we can */
1356 	while (Resources > 0) {
1357 		int num_frags;
1358 
1359 		if (do_pm_get) {
1360 			rtpm_code =
1361 				htc_send_pkts_get_rtpm_id(
1362 							pEndpoint->service_id);
1363 			ret = hif_rtpm_get(HIF_RTPM_GET_ASYNC, rtpm_code);
1364 			if (ret) {
1365 				/* bus suspended, runtime resume issued */
1366 				QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
1367 				pPacket = htc_get_pkt_at_head(tx_queue);
1368 				if (!pPacket)
1369 					break;
1370 				log_packet_info(target, pPacket);
1371 				break;
1372 			}
1373 			htc_inc_wmi_runtime_cnt(target, rtpm_code);
1374 
1375 		}
1376 
1377 		ret = hif_system_pm_state_check(target->hif_dev);
1378 		if (ret) {
1379 			if (do_pm_get) {
1380 				hif_rtpm_put(HIF_RTPM_PUT_ASYNC, rtpm_code);
1381 				htc_dec_wmi_runtime_cnt(target, rtpm_code);
1382 			}
1383 			break;
1384 		}
1385 
1386 		pPacket = htc_packet_dequeue(tx_queue);
1387 		if (!pPacket) {
1388 			if (do_pm_get) {
1389 				hif_rtpm_put(HIF_RTPM_PUT_ASYNC, rtpm_code);
1390 				htc_dec_wmi_runtime_cnt(target, rtpm_code);
1391 			}
1392 			break;
1393 		}
1394 
1395 		AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1396 				(" Got packet:%pK , New Queue Depth: %d\n",
1397 				 pPacket,
1398 				 HTC_PACKET_QUEUE_DEPTH(tx_queue)));
1399 		/* For non-credit path the sequence number is already embedded
1400 		 * in the constructed HTC header
1401 		 */
1402 		pPacket->PktInfo.AsTx.SendFlags = 0;
1403 		pPacket->PktInfo.AsTx.CreditsUsed = 0;
1404 		/* queue this packet into the caller's queue */
1405 		HTC_PACKET_ENQUEUE(pQueue, pPacket);
1406 
1407 		/*
1408 		 * FIX THIS:
1409 		 * For now, avoid calling qdf_nbuf_get_num_frags before calling
1410 		 * qdf_nbuf_map, because the MacOS version of qdf_nbuf_t doesn't
1411 		 * support qdf_nbuf_get_num_frags until after qdf_nbuf_map has
1412 		 * been done.
1413 		 * Assume that the non-data netbufs, i.e. WMI message netbufs,
1414 		 * consist of a single fragment.
1415 		 */
1416 		/* WMI messages are in a single-fragment network buf */
1417 		num_frags =
1418 			(pPacket->PktInfo.AsTx.
1419 			 Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) ? 1 :
1420 			qdf_nbuf_get_num_frags(GET_HTC_PACKET_NET_BUF_CONTEXT
1421 						       (pPacket));
1422 		Resources -= num_frags;
1423 	}
1424 
1425 	if (!HTC_QUEUE_EMPTY(&pm_queue))
1426 		queue_htc_pm_packets(pEndpoint, &pm_queue);
1427 
1428 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets\n"));
1429 
1430 }
1431 
1432 /**
1433  * htc_try_send() - Send packets in a queue on an endpoint
1434  * @target: HTC target on which packets need to be sent
1435  * @pEndpoint: logical endpoint on which packets needs to be sent
1436  * @pCallersSendQueue: packet queue containing the list of packets to be sent
1437  *
1438  * Return: enum HTC_SEND_QUEUE_RESULT indicates whether the packet was queued to
1439  *         be sent or the packet should be dropped by the upper layer
1440  */
1441 static enum HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target,
1442 					  HTC_ENDPOINT *pEndpoint,
1443 					  HTC_PACKET_QUEUE *pCallersSendQueue)
1444 {
1445 	/* temp queue to hold packets at various stages */
1446 	HTC_PACKET_QUEUE sendQueue;
1447 	HTC_PACKET *pPacket;
1448 	int tx_resources;
1449 	int overflow;
1450 	enum HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK;
1451 	QDF_STATUS status;
1452 
1453 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+htc_try_send (Queue:%pK Depth:%d)\n",
1454 					 pCallersSendQueue,
1455 					 (pCallersSendQueue ==
1456 					  NULL) ? 0 :
1457 					 HTC_PACKET_QUEUE_DEPTH
1458 						 (pCallersSendQueue)));
1459 
1460 	/* init the local send queue */
1461 	INIT_HTC_PACKET_QUEUE(&sendQueue);
1462 
1463 	do {
1464 
1465 		/* caller didn't provide a queue, just wants us to check
1466 		 * queues and send
1467 		 */
1468 		if (!pCallersSendQueue)
1469 			break;
1470 
1471 		if (HTC_QUEUE_EMPTY(pCallersSendQueue)) {
1472 			/* empty queue */
1473 			OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,
1474 							HTC_PKT_Q_EMPTY);
1475 			result = HTC_SEND_QUEUE_DROP;
1476 			break;
1477 		}
1478 
1479 		if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >=
1480 		    pEndpoint->MaxTxQueueDepth) {
1481 			/* we've already overflowed */
1482 			overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
1483 		} else {
1484 			/* figure out how much we will overflow by */
1485 			overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
1486 			overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
1487 			/* get how much we will overflow the TX queue by */
1488 			overflow -= pEndpoint->MaxTxQueueDepth;
1489 		}
1490 
1491 		/* if overflow is negative or zero, we are okay */
1492 		if (overflow > 0) {
1493 			AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1494 					("Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d\n",
1495 					 pEndpoint->Id, overflow,
1496 					 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->
1497 								TxQueue),
1498 					 pEndpoint->MaxTxQueueDepth));
1499 		}
1500 		if ((overflow <= 0)
1501 		    || (!pEndpoint->EpCallBacks.EpSendFull)) {
1502 			/* all packets will fit or caller did not provide send
1503 			 * full indication handler
1504 			 * just move all of them to local sendQueue object
1505 			 */
1506 			HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue,
1507 							  pCallersSendQueue);
1508 		} else {
1509 			int i;
1510 			int goodPkts =
1511 				HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) -
1512 				overflow;
1513 
1514 			A_ASSERT(goodPkts >= 0);
1515 			/* we have overflowed and callback is provided. Dequeue
1516 			 * all non-overflow packets into the sendqueue
1517 			 */
1518 			for (i = 0; i < goodPkts; i++) {
1519 				/* pop off caller's queue */
1520 				pPacket = htc_packet_dequeue(pCallersSendQueue);
1521 				A_ASSERT(pPacket);
1522 				if (pPacket)
1523 					/* insert into local queue */
1524 					HTC_PACKET_ENQUEUE(&sendQueue,
1525 							   pPacket);
1526 			}
1527 
1528 			/* the caller's queue has all the packets that won't fit
1529 			 * walk through the caller's queue and indicate each one
1530 			 * to the send full handler
1531 			 */
1532 			ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->
1533 						       QueueHead, pPacket,
1534 						       HTC_PACKET, ListLink) {
1535 
1536 				AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1537 						("Indicating overflowed TX packet: %pK\n",
1538 						 pPacket));
1539 				/*
1540 				 * Remove headroom reserved for HTC_FRAME_HDR
1541 				 * before giving the packet back to the user via
1542 				 * the EpSendFull callback.
1543 				 */
1544 				qdf_nbuf_pull_head
1545 					(GET_HTC_PACKET_NET_BUF_CONTEXT
1546 						(pPacket),
1547 					sizeof(HTC_FRAME_HDR));
1548 				pPacket->PktInfo.AsTx.Flags &=
1549 					~HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA;
1550 
1551 				if (pEndpoint->EpCallBacks.
1552 				    EpSendFull(pEndpoint->EpCallBacks.pContext,
1553 					       pPacket) == HTC_SEND_FULL_DROP) {
1554 					/* callback wants the packet dropped */
1555 					INC_HTC_EP_STAT(pEndpoint, TxDropped,
1556 							1);
1557 					/* leave this one in the caller's queue
1558 					 * for cleanup
1559 					 */
1560 				} else {
1561 					/* callback wants to keep this packet,
1562 					 * remove from caller's queue
1563 					 */
1564 					HTC_PACKET_REMOVE(pCallersSendQueue,
1565 							  pPacket);
1566 					/* put it in the send queue
1567 					 * add HTC_FRAME_HDR space reservation
1568 					 * again
1569 					 */
1570 					qdf_nbuf_push_head
1571 						(GET_HTC_PACKET_NET_BUF_CONTEXT
1572 							(pPacket),
1573 						sizeof(HTC_FRAME_HDR));
1574 					pPacket->PktInfo.AsTx.Flags |=
1575 						HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA;
1576 
1577 					HTC_PACKET_ENQUEUE(&sendQueue, pPacket);
1578 				}
1579 
1580 			}
1581 			ITERATE_END;
1582 
1583 			if (HTC_QUEUE_EMPTY(&sendQueue)) {
1584 				/* no packets made it in, caller will cleanup */
1585 				OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,
1586 							HTC_SEND_Q_EMPTY);
1587 				result = HTC_SEND_QUEUE_DROP;
1588 				break;
1589 			}
1590 		}
1591 
1592 	} while (false);
1593 
1594 	if (result != HTC_SEND_QUEUE_OK) {
1595 		AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send: %d\n",
1596 			result));
1597 		return result;
1598 	}
1599 
1600 	LOCK_HTC_TX(target);
1601 
1602 	if (!HTC_QUEUE_EMPTY(&sendQueue)) {
1603 		if (target->is_nodrop_pkt) {
1604 			/*
1605 			 * nodrop pkts have higher priority than normal pkts,
1606 			 * insert nodrop pkt to head for proper
1607 			 * start/termination of test.
1608 			 */
1609 			HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
1610 					&sendQueue);
1611 			target->is_nodrop_pkt = false;
1612 		} else {
1613 			/* transfer packets to tail */
1614 			HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,
1615 					&sendQueue);
1616 			A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue));
1617 			INIT_HTC_PACKET_QUEUE(&sendQueue);
1618 		}
1619 	}
1620 
1621 	/* increment tx processing count on entry */
1622 	if (qdf_atomic_inc_return(&pEndpoint->TxProcessCount) > 1) {
1623 		/* another thread or task is draining the TX queues on this
1624 		 * endpoint that thread will reset the tx processing count when
1625 		 * the queue is drained
1626 		 */
1627 		qdf_atomic_dec(&pEndpoint->TxProcessCount);
1628 		UNLOCK_HTC_TX(target);
1629 		AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send (busy)\n"));
1630 		return HTC_SEND_QUEUE_OK;
1631 	}
1632 
1633 	/***** beyond this point only 1 thread may enter ******/
1634 
1635 	/* now drain the endpoint TX queue for transmission as long as we have
1636 	 * enough transmit resources
1637 	 */
1638 	if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1639 		tx_resources =
1640 			hif_get_free_queue_number(target->hif_dev,
1641 						  pEndpoint->UL_PipeID);
1642 	} else {
1643 		tx_resources = 0;
1644 	}
1645 
1646 	while (true) {
1647 
1648 		if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0)
1649 			break;
1650 
1651 		if (pEndpoint->async_update &&
1652 			(!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) &&
1653 			(!tx_resources)) {
1654 			hif_schedule_ce_tasklet(target->hif_dev,
1655 						pEndpoint->UL_PipeID);
1656 			break;
1657 		}
1658 
1659 		if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1660 #if DEBUG_CREDIT
1661 			int cred = pEndpoint->TxCredits;
1662 #endif
1663 			/* credit based mechanism provides flow control based on
1664 			 * target transmit resource availability, we assume that
1665 			 * the HIF layer will always have bus resources greater
1666 			 * than target transmit resources
1667 			 */
1668 			get_htc_send_packets_credit_based(target, pEndpoint,
1669 							  &sendQueue);
1670 #if DEBUG_CREDIT
1671 			if (ep_debug_mask & (1 << pEndpoint->Id)) {
1672 				if (cred - pEndpoint->TxCredits > 0) {
1673 					AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1674 						(" <HTC> Decrease EP%d %d - %d = %d credits.\n",
1675 							 pEndpoint->Id, cred,
1676 							 cred -
1677 							 pEndpoint->TxCredits,
1678 							 pEndpoint->TxCredits));
1679 				}
1680 			}
1681 #endif
1682 		} else {
1683 
1684 		/*
1685 		* Header and payload belongs to the different fragments and
1686 		* consume 2 resource for one HTC package but USB combine into
1687 		* one transfer.And one WMI message only consumes one single
1688 		* resource.
1689 		*/
1690 			if (HTC_TX_BUNDLE_ENABLED(target) && tx_resources &&
1691 				hif_get_bus_type(target->hif_dev) ==
1692 						QDF_BUS_TYPE_USB) {
1693 				if (pEndpoint->service_id ==
1694 					WMI_CONTROL_SVC)
1695 					tx_resources =
1696 					    HTC_MAX_MSG_PER_BUNDLE_TX;
1697 				else
1698 					tx_resources =
1699 					    (HTC_MAX_MSG_PER_BUNDLE_TX * 2);
1700 			}
1701 			/* get all the packets for this endpoint that we can for
1702 			 * this pass
1703 			 */
1704 			get_htc_send_packets(target, pEndpoint, &sendQueue,
1705 					     tx_resources);
1706 		}
1707 
1708 		if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) {
1709 			/* didn't get any packets due to a lack of resources or
1710 			 * TX queue was drained
1711 			 */
1712 			break;
1713 		}
1714 
1715 		if (!pEndpoint->async_update)
1716 			UNLOCK_HTC_TX(target);
1717 
1718 		/* send what we can */
1719 		status = htc_issue_packets(target, pEndpoint, &sendQueue);
1720 		if (status) {
1721 			int i;
1722 			unsigned int rtpm_code;
1723 
1724 			result = HTC_SEND_QUEUE_DROP;
1725 
1726 			switch (status) {
1727 			case  QDF_STATUS_E_RESOURCES:
1728 				if (pEndpoint->num_requeues_warn <= MAX_REQUEUE_WARN) {
1729 					pEndpoint->num_requeues_warn++;
1730 					pEndpoint->total_num_requeues++;
1731 					break;
1732 				} else {
1733 					pEndpoint->total_num_requeues++;
1734 					pEndpoint->num_requeues_warn = 0;
1735 				}
1736 				fallthrough;
1737 			default:
1738 				QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_INFO,
1739 					  "htc_issue_packets, failed status:%d"
1740 					  "endpoint:%d, put it back to head of"
1741 					  "callersSendQueue", result, pEndpoint->Id);
1742 				break;
1743 			}
1744 
1745 			rtpm_code = htc_send_pkts_get_rtpm_id(
1746 							pEndpoint->service_id);
1747 			for (i = HTC_PACKET_QUEUE_DEPTH(&sendQueue); i > 0; i--) {
1748 				hif_rtpm_put(HIF_RTPM_PUT_ASYNC, rtpm_code);
1749 				htc_dec_wmi_runtime_cnt(target, rtpm_code);
1750 			}
1751 
1752 			if (!pEndpoint->async_update) {
1753 				LOCK_HTC_TX(target);
1754 			}
1755 			HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
1756 							  &sendQueue);
1757 			break;
1758 		}  else {
1759 			if (pEndpoint->num_requeues_warn)
1760 				pEndpoint->num_requeues_warn = 0;
1761 		}
1762 
1763 		if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1764 			tx_resources =
1765 				hif_get_free_queue_number(target->hif_dev,
1766 							  pEndpoint->UL_PipeID);
1767 		}
1768 
1769 		if (!pEndpoint->async_update) {
1770 			LOCK_HTC_TX(target);
1771 		}
1772 
1773 	}
1774 
1775 	/* done with this endpoint, we can clear the count */
1776 	qdf_atomic_init(&pEndpoint->TxProcessCount);
1777 
1778 	UNLOCK_HTC_TX(target);
1779 
1780 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send:\n"));
1781 
1782 	return HTC_SEND_QUEUE_OK;
1783 }
1784 
1785 #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
1786 static uint16_t htc_send_pkts_sched_check(HTC_HANDLE HTCHandle,
1787 					  HTC_ENDPOINT_ID id)
1788 {
1789 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1790 	HTC_ENDPOINT *pEndpoint;
1791 	HTC_ENDPOINT_ID eid;
1792 	HTC_PACKET_QUEUE *pTxQueue;
1793 	uint16_t resources;
1794 	uint16_t acQueueStatus[DATA_EP_SIZE] = { 0, 0, 0, 0 };
1795 
1796 	if (id < ENDPOINT_2 || id > ENDPOINT_5)
1797 		return 1;
1798 
1799 	for (eid = ENDPOINT_2; eid <= ENDPOINT_5; eid++) {
1800 		pEndpoint = &target->endpoint[eid];
1801 		pTxQueue = &pEndpoint->TxQueue;
1802 
1803 		if (HTC_QUEUE_EMPTY(pTxQueue))
1804 			acQueueStatus[eid - 2] = 1;
1805 	}
1806 
1807 	switch (id) {
1808 	case ENDPOINT_2:        /* BE */
1809 		return acQueueStatus[0] && acQueueStatus[2]
1810 			&& acQueueStatus[3];
1811 	case ENDPOINT_3:        /* BK */
1812 		return acQueueStatus[0] && acQueueStatus[1] && acQueueStatus[2]
1813 			&& acQueueStatus[3];
1814 	case ENDPOINT_4:        /* VI */
1815 		return acQueueStatus[2] && acQueueStatus[3];
1816 	case ENDPOINT_5:        /* VO */
1817 		return acQueueStatus[3];
1818 	default:
1819 		return 0;
1820 	}
1821 
1822 }
1823 
1824 static A_STATUS htc_send_pkts_sched_queue(HTC_TARGET *target,
1825 					  HTC_PACKET_QUEUE *pPktQueue,
1826 					  HTC_ENDPOINT_ID eid)
1827 {
1828 	HTC_ENDPOINT *pEndpoint;
1829 	HTC_PACKET_QUEUE *pTxQueue;
1830 	HTC_PACKET *pPacket;
1831 	int goodPkts;
1832 
1833 	pEndpoint = &target->endpoint[eid];
1834 	pTxQueue = &pEndpoint->TxQueue;
1835 
1836 	LOCK_HTC_TX(target);
1837 
1838 	goodPkts =
1839 		pEndpoint->MaxTxQueueDepth -
1840 		HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
1841 
1842 	if (goodPkts > 0) {
1843 		while (!HTC_QUEUE_EMPTY(pPktQueue)) {
1844 			pPacket = htc_packet_dequeue(pPktQueue);
1845 			HTC_PACKET_ENQUEUE(pTxQueue, pPacket);
1846 			goodPkts--;
1847 
1848 			if (goodPkts <= 0)
1849 				break;
1850 		}
1851 	}
1852 
1853 	if (HTC_PACKET_QUEUE_DEPTH(pPktQueue)) {
1854 		ITERATE_OVER_LIST_ALLOW_REMOVE(&pPktQueue->QueueHead, pPacket,
1855 					       HTC_PACKET, ListLink) {
1856 
1857 			if (pEndpoint->EpCallBacks.
1858 			    EpSendFull(pEndpoint->EpCallBacks.pContext,
1859 				       pPacket) == HTC_SEND_FULL_DROP) {
1860 				INC_HTC_EP_STAT(pEndpoint, TxDropped, 1);
1861 			} else {
1862 				HTC_PACKET_REMOVE(pPktQueue, pPacket);
1863 				HTC_PACKET_ENQUEUE(pTxQueue, pPacket);
1864 			}
1865 		}
1866 		ITERATE_END;
1867 	}
1868 
1869 	UNLOCK_HTC_TX(target);
1870 
1871 	return A_OK;
1872 }
1873 
1874 #endif
1875 
1876 static inline QDF_STATUS __htc_send_pkt(HTC_HANDLE HTCHandle,
1877 				HTC_PACKET *pPacket)
1878 {
1879 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1880 	HTC_ENDPOINT *pEndpoint;
1881 	HTC_PACKET_QUEUE pPktQueue;
1882 	qdf_nbuf_t netbuf;
1883 	HTC_FRAME_HDR *htc_hdr;
1884 	QDF_STATUS status;
1885 
1886 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1887 			("+__htc_send_pkt\n"));
1888 
1889 	/* get packet at head to figure out which endpoint these packets will
1890 	 * go into
1891 	 */
1892 	if (!pPacket) {
1893 		OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target, GET_HTC_PKT_Q_FAIL);
1894 		AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n"));
1895 		return QDF_STATUS_E_INVAL;
1896 	}
1897 
1898 	if ((pPacket->Endpoint >= ENDPOINT_MAX) ||
1899 	    (pPacket->Endpoint <= ENDPOINT_UNUSED)) {
1900 		AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
1901 			("%s endpoint is invalid\n", __func__));
1902 		AR_DEBUG_ASSERT(0);
1903 		return QDF_STATUS_E_INVAL;
1904 	}
1905 	pEndpoint = &target->endpoint[pPacket->Endpoint];
1906 
1907 	if (!pEndpoint->service_id) {
1908 		AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("%s service_id is invalid\n",
1909 								__func__));
1910 		return QDF_STATUS_E_INVAL;
1911 	}
1912 
1913 #ifdef HTC_EP_STAT_PROFILING
1914 	LOCK_HTC_TX(target);
1915 	INC_HTC_EP_STAT(pEndpoint, TxPosted, 1);
1916 	UNLOCK_HTC_TX(target);
1917 #endif
1918 
1919 	/* provide room in each packet's netbuf for the HTC frame header */
1920 	netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
1921 	AR_DEBUG_ASSERT(netbuf);
1922 	if (!netbuf)
1923 		return QDF_STATUS_E_INVAL;
1924 
1925 	qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR));
1926 	pPacket->PktInfo.AsTx.Flags |=
1927 		HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA;
1928 	/* setup HTC frame header */
1929 	htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
1930 	AR_DEBUG_ASSERT(htc_hdr);
1931 	if (!htc_hdr)
1932 		return QDF_STATUS_E_INVAL;
1933 
1934 	HTC_WRITE32(htc_hdr,
1935 		    SM(pPacket->ActualLength,
1936 		       HTC_FRAME_HDR_PAYLOADLEN) |
1937 		    SM(pPacket->Endpoint,
1938 		       HTC_FRAME_HDR_ENDPOINTID));
1939 	LOCK_HTC_TX(target);
1940 
1941 	pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
1942 	pEndpoint->SeqNo++;
1943 
1944 	HTC_WRITE32(((uint32_t *)htc_hdr) + 1,
1945 		    SM(pPacket->PktInfo.AsTx.SeqNo,
1946 		       HTC_FRAME_HDR_CONTROLBYTES1));
1947 
1948 	UNLOCK_HTC_TX(target);
1949 
1950 	/*
1951 	 * For flow control enabled endpoints mapping is done in
1952 	 * htc_issue_packets and for non flow control enabled endpoints
1953 	 * its done here.
1954 	 */
1955 	if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
1956 		pPacket->PktInfo.AsTx.Flags |= HTC_TX_PACKET_FLAG_FIXUP_NETBUF;
1957 		status = qdf_nbuf_map(target->osdev,
1958 				      GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
1959 				      QDF_DMA_TO_DEVICE);
1960 		if (status == QDF_STATUS_SUCCESS) {
1961 			target->nbuf_nfc_map_count++;
1962 		} else {
1963 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1964 					("%s: nbuf map failed, endpoint %pK, seq_no. %d\n",
1965 					 __func__, pEndpoint, pEndpoint->SeqNo));
1966 			return status;
1967 		}
1968 	}
1969 
1970 	INIT_HTC_PACKET_QUEUE_AND_ADD(&pPktQueue, pPacket);
1971 #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
1972 	if (!htc_send_pkts_sched_check(HTCHandle, pEndpoint->Id))
1973 		htc_send_pkts_sched_queue(HTCHandle, &pPktQueue, pEndpoint->Id);
1974 	else
1975 		htc_try_send(target, pEndpoint, &pPktQueue);
1976 #else
1977 	htc_try_send(target, pEndpoint, &pPktQueue);
1978 #endif
1979 
1980 	/* do completion on any packets that couldn't get in */
1981 	while (!HTC_QUEUE_EMPTY(&pPktQueue)) {
1982 		pPacket = htc_packet_dequeue(&pPktQueue);
1983 
1984 		if (HTC_STOPPING(target))
1985 			pPacket->Status = QDF_STATUS_E_CANCELED;
1986 		else
1987 			pPacket->Status = QDF_STATUS_E_RESOURCES;
1988 
1989 		send_packet_completion(target, pPacket);
1990 	}
1991 
1992 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n"));
1993 
1994 	return QDF_STATUS_SUCCESS;
1995 }
1996 
1997 /* HTC API - htc_send_pkt */
1998 QDF_STATUS htc_send_pkt(HTC_HANDLE htc_handle, HTC_PACKET *htc_packet)
1999 {
2000 	if (!htc_handle) {
2001 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2002 				("%s: HTCHandle is NULL \n", __func__));
2003 		return QDF_STATUS_E_FAILURE;
2004 	}
2005 
2006 	if (!htc_packet) {
2007 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2008 				("%s: pPacket is NULL \n", __func__));
2009 		return QDF_STATUS_E_FAILURE;
2010 	}
2011 
2012 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
2013 			("+-htc_send_pkt: Enter endPointId: %d, buffer: %pK, length: %d\n",
2014 			 htc_packet->Endpoint, htc_packet->pBuffer,
2015 			 htc_packet->ActualLength));
2016 	return __htc_send_pkt(htc_handle, htc_packet);
2017 }
2018 qdf_export_symbol(htc_send_pkt);
2019 
2020 #ifdef ATH_11AC_TXCOMPACT
2021 /**
2022  * htc_send_data_pkt() - send single data packet on an endpoint
2023  * @HTCHandle: pointer to HTC handle
2024  * @netbuf: network buffer containing the data to be sent
2025  * @ActualLength: length of data that needs to be transmitted
2026  *
2027  * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
2028  */
2029 QDF_STATUS htc_send_data_pkt(HTC_HANDLE htc_hdl, qdf_nbuf_t netbuf, int ep_id,
2030 			     int actual_length)
2031 {
2032 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl);
2033 	HTC_ENDPOINT *pEndpoint;
2034 	HTC_FRAME_HDR *p_htc_hdr;
2035 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2036 	int tx_resources;
2037 	uint32_t data_attr = 0;
2038 	int htc_payload_len = actual_length;
2039 	unsigned int rtpm_code;
2040 
2041 	pEndpoint = &target->endpoint[ep_id];
2042 
2043 	tx_resources = hif_get_free_queue_number(target->hif_dev,
2044 						 pEndpoint->UL_PipeID);
2045 
2046 	if (tx_resources < HTC_DATA_RESOURCE_THRS) {
2047 		if (pEndpoint->ul_is_polled) {
2048 			hif_send_complete_check(pEndpoint->target->hif_dev,
2049 						pEndpoint->UL_PipeID, 1);
2050 			tx_resources =
2051 				hif_get_free_queue_number(target->hif_dev,
2052 							  pEndpoint->UL_PipeID);
2053 		}
2054 		if (tx_resources < HTC_DATA_MINDESC_PERPACKET)
2055 			return QDF_STATUS_E_FAILURE;
2056 	}
2057 
2058 	rtpm_code = htc_send_pkts_get_rtpm_id(
2059 					pEndpoint->service_id);
2060 	if (hif_rtpm_get(HIF_RTPM_GET_ASYNC, rtpm_code))
2061 		return QDF_STATUS_E_FAILURE;
2062 
2063 	p_htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
2064 	AR_DEBUG_ASSERT(p_htc_hdr);
2065 
2066 	data_attr = qdf_nbuf_data_attr_get(netbuf);
2067 
2068 	if (target->htc_hdr_length_check)
2069 		htc_payload_len = actual_length - HTC_HEADER_LEN;
2070 
2071 	HTC_WRITE32(p_htc_hdr, SM(htc_payload_len, HTC_FRAME_HDR_PAYLOADLEN)
2072 		    | SM(ep_id, HTC_FRAME_HDR_ENDPOINTID));
2073 	/*
2074 	 * If the HIF pipe for the data endpoint is polled rather than
2075 	 * interrupt-driven, this is a good point to check whether any
2076 	 * data previously sent through the HIF pipe have finished being
2077 	 * sent.
2078 	 * Since this may result in callbacks to htc_tx_completion_handler,
2079 	 * which can take the HTC tx lock, make the hif_send_complete_check
2080 	 * call before acquiring the HTC tx lock.
2081 	 * Call hif_send_complete_check directly, rather than calling
2082 	 * htc_send_complete_check, and call the PollTimerStart separately
2083 	 * after calling hif_send_head, so the timer will be started to
2084 	 * check for completion of the new outstanding download (in the
2085 	 * unexpected event that other polling calls don't catch it).
2086 	 */
2087 
2088 	LOCK_HTC_TX(target);
2089 
2090 	HTC_WRITE32(((uint32_t *)p_htc_hdr) + 1,
2091 		    SM(pEndpoint->SeqNo, HTC_FRAME_HDR_CONTROLBYTES1));
2092 
2093 	pEndpoint->SeqNo++;
2094 
2095 	QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
2096 	DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
2097 		QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf),
2098 		sizeof(qdf_nbuf_data(netbuf)), QDF_TX));
2099 	status = hif_send_head(target->hif_dev,
2100 			       pEndpoint->UL_PipeID,
2101 			       pEndpoint->Id, actual_length, netbuf, data_attr);
2102 
2103 	UNLOCK_HTC_TX(target);
2104 	return status;
2105 }
2106 #else                           /*ATH_11AC_TXCOMPACT */
2107 
2108 /**
2109  * htc_send_data_pkt() - htc_send_data_pkt
2110  * @HTCHandle: pointer to HTC handle
2111  * @pPacket: pointer to HTC_PACKET
2112  * @more_data: indicates whether more data is to follow
2113  *
2114  * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
2115  */
2116 QDF_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket,
2117 			   uint8_t more_data)
2118 {
2119 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
2120 	HTC_ENDPOINT *pEndpoint;
2121 	HTC_FRAME_HDR *pHtcHdr;
2122 	HTC_PACKET_QUEUE sendQueue;
2123 	qdf_nbuf_t netbuf = NULL;
2124 	int tx_resources;
2125 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2126 	uint32_t data_attr = 0;
2127 	bool used_extra_tx_credit = false;
2128 
2129 	if (pPacket) {
2130 		if ((pPacket->Endpoint >= ENDPOINT_MAX) ||
2131 		   (pPacket->Endpoint <= ENDPOINT_UNUSED)) {
2132 			AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
2133 				("%s endpoint is invalid\n", __func__));
2134 			AR_DEBUG_ASSERT(0);
2135 			return QDF_STATUS_E_INVAL;
2136 		}
2137 		pEndpoint = &target->endpoint[pPacket->Endpoint];
2138 
2139 		/* add HTC_FRAME_HDR in the initial fragment */
2140 		netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
2141 		pHtcHdr = (HTC_FRAME_HDR *) qdf_nbuf_get_frag_vaddr(netbuf, 0);
2142 		AR_DEBUG_ASSERT(pHtcHdr);
2143 
2144 		HTC_WRITE32(pHtcHdr,
2145 				SM(pPacket->ActualLength,
2146 				       HTC_FRAME_HDR_PAYLOADLEN) |
2147 				SM(pPacket->PktInfo.AsTx.SendFlags,
2148 					HTC_FRAME_HDR_FLAGS) |
2149 				SM(pPacket->Endpoint,
2150 					HTC_FRAME_HDR_ENDPOINTID));
2151 		/*
2152 		 * If the HIF pipe for the data endpoint is polled rather than
2153 		 * interrupt-driven, this is a good point to check whether any
2154 		 * data previously sent through the HIF pipe have finished being
2155 		 * sent. Since this may result in callbacks to
2156 		 * htc_tx_completion_handler, which can take the HTC tx lock,
2157 		 * make the hif_send_complete_check call before acquiring the
2158 		 * HTC tx lock.
2159 		 * Call hif_send_complete_check directly, rather than calling
2160 		 * htc_send_complete_check, and call the PollTimerStart
2161 		 * separately after calling hif_send_head, so the timer will be
2162 		 * started to check for completion of the new outstanding
2163 		 * download (in the unexpected event that other polling calls
2164 		 * don't catch it).
2165 		 */
2166 		if (pEndpoint->ul_is_polled) {
2167 			htc_send_complete_poll_timer_stop(pEndpoint);
2168 			hif_send_complete_check(pEndpoint->target->hif_dev,
2169 						pEndpoint->UL_PipeID, 0);
2170 		}
2171 
2172 		LOCK_HTC_TX(target);
2173 
2174 		pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
2175 		pEndpoint->SeqNo++;
2176 
2177 		HTC_WRITE32(((uint32_t *) pHtcHdr) + 1,
2178 			    SM(pPacket->PktInfo.AsTx.SeqNo,
2179 			       HTC_FRAME_HDR_CONTROLBYTES1));
2180 
2181 		/* append new packet to pEndpoint->TxQueue */
2182 		HTC_PACKET_ENQUEUE(&pEndpoint->TxQueue, pPacket);
2183 		if (HTC_TX_BUNDLE_ENABLED(target) && (more_data)) {
2184 			UNLOCK_HTC_TX(target);
2185 			return QDF_STATUS_SUCCESS;
2186 		}
2187 
2188 		QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC);
2189 		DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
2190 			  QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf),
2191 				sizeof(qdf_nbuf_data(netbuf)), QDF_TX));
2192 	} else {
2193 		LOCK_HTC_TX(target);
2194 		pEndpoint = &target->endpoint[1];
2195 	}
2196 
2197 	/* increment tx processing count on entry */
2198 	qdf_atomic_inc(&pEndpoint->TxProcessCount);
2199 	if (qdf_atomic_read(&pEndpoint->TxProcessCount) > 1) {
2200 		/*
2201 		 * Another thread or task is draining the TX queues on this
2202 		 * endpoint. That thread will reset the tx processing count when
2203 		 * the queue is drained.
2204 		 */
2205 		qdf_atomic_dec(&pEndpoint->TxProcessCount);
2206 		UNLOCK_HTC_TX(target);
2207 		return QDF_STATUS_SUCCESS;
2208 	}
2209 
2210 	/***** beyond this point only 1 thread may enter ******/
2211 
2212 	INIT_HTC_PACKET_QUEUE(&sendQueue);
2213 	if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
2214 #if DEBUG_CREDIT
2215 		int cred = pEndpoint->TxCredits;
2216 #endif
2217 		get_htc_send_packets_credit_based(target, pEndpoint,
2218 						 &sendQueue);
2219 #if DEBUG_CREDIT
2220 		if (ep_debug_mask & (1 << pEndpoint->Id)) {
2221 			if (cred - pEndpoint->TxCredits > 0) {
2222 				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2223 						(" <HTC> Decrease EP%d %d - %d = %d credits.\n",
2224 						 pEndpoint->Id, cred,
2225 						 cred - pEndpoint->TxCredits,
2226 						 pEndpoint->TxCredits));
2227 			}
2228 		}
2229 #endif
2230 		UNLOCK_HTC_TX(target);
2231 	}
2232 
2233 	else if (HTC_TX_BUNDLE_ENABLED(target)) {
2234 		if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB) {
2235 			if (hif_get_free_queue_number(target->hif_dev,
2236 						      pEndpoint->UL_PipeID))
2237 				/*
2238 				 * Header and payload belongs to the different
2239 				 * fragments and consume 2 resource for one HTC
2240 				 * package but USB combine into one transfer.
2241 				 */
2242 				get_htc_send_packets(target, pEndpoint,
2243 						     &sendQueue,
2244 						     HTC_MAX_MSG_PER_BUNDLE_TX
2245 						     * 2);
2246 		} else {
2247 			/* Dequeue max packets from endpoint tx queue */
2248 			get_htc_send_packets(target, pEndpoint, &sendQueue,
2249 					     HTC_MAX_TX_BUNDLE_SEND_LIMIT);
2250 		}
2251 		UNLOCK_HTC_TX(target);
2252 	} else {
2253 		/*
2254 		 * Now drain the endpoint TX queue for transmission as long as
2255 		 * we have enough transmit resources
2256 		 */
2257 		tx_resources =
2258 			hif_get_free_queue_number(target->hif_dev,
2259 						  pEndpoint->UL_PipeID);
2260 		get_htc_send_packets(target, pEndpoint, &sendQueue,
2261 				     tx_resources);
2262 		UNLOCK_HTC_TX(target);
2263 	}
2264 
2265 	/* send what we can */
2266 	while (true) {
2267 		if (HTC_TX_BUNDLE_ENABLED(target) &&
2268 		    (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >=
2269 		     HTC_MIN_MSG_PER_BUNDLE) &&
2270 		    (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO ||
2271 		     hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)) {
2272 			if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
2273 				if (htc_tx_pad_credit_avail(pEndpoint) < 1) {
2274 					status = QDF_STATUS_E_RESOURCES;
2275 					/* put the sendQueue back at the front
2276 					 * of pEndpoint->TxQueue
2277 					 */
2278 					LOCK_HTC_TX(target);
2279 					HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(
2280 							&pEndpoint->TxQueue,
2281 							&sendQueue);
2282 					UNLOCK_HTC_TX(target);
2283 					break;
2284 				}
2285 			}
2286 			htc_issue_packets_bundle(target, pEndpoint, &sendQueue);
2287 		}
2288 		if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
2289 			if (htc_tx_pad_credit_avail(pEndpoint) < 1) {
2290 				status = QDF_STATUS_E_RESOURCES;
2291 				/* put the sendQueue back at the front
2292 				 * of pEndpoint->TxQueue
2293 				 */
2294 				LOCK_HTC_TX(target);
2295 				HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(
2296 							&pEndpoint->TxQueue,
2297 							&sendQueue);
2298 				UNLOCK_HTC_TX(target);
2299 				break;
2300 			}
2301 		}
2302 		pPacket = htc_packet_dequeue(&sendQueue);
2303 		if (!pPacket)
2304 			break;
2305 		netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
2306 		pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0);
2307 
2308 		LOCK_HTC_TX(target);
2309 		/* store in look up queue to match completions */
2310 		HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket);
2311 		INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
2312 		pEndpoint->ul_outstanding_cnt++;
2313 		UNLOCK_HTC_TX(target);
2314 
2315 		used_extra_tx_credit =
2316 				htc_handle_extra_tx_credit(pEndpoint, pPacket,
2317 							   (uint8_t *)pHtcHdr,
2318 							   NULL,
2319 							   pPacket->ActualLength
2320 							   + HTC_HDR_LENGTH);
2321 
2322 		status = hif_send_head(target->hif_dev,
2323 				       pEndpoint->UL_PipeID,
2324 				       pEndpoint->Id,
2325 				       HTC_HDR_LENGTH + pPacket->ActualLength,
2326 				       netbuf, data_attr);
2327 		if (status != QDF_STATUS_SUCCESS) {
2328 			if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
2329 				if (used_extra_tx_credit) {
2330 					pEndpoint->EpCallBacks.
2331 					ep_padding_credit_update
2332 					(pEndpoint->EpCallBacks.pContext, 1);
2333 				}
2334 			}
2335 		}
2336 #if DEBUG_BUNDLE
2337 		qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.",
2338 			  pEndpoint->Id,
2339 			  pEndpoint->TxCreditSize,
2340 			  HTC_HDR_LENGTH + pPacket->ActualLength);
2341 #endif
2342 
2343 		htc_issue_tx_bundle_stats_inc(target);
2344 
2345 		if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
2346 			LOCK_HTC_TX(target);
2347 			pEndpoint->ul_outstanding_cnt--;
2348 			/* remove this packet from the tx completion queue */
2349 			HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket);
2350 
2351 			/*
2352 			 * Don't bother reclaiming credits - HTC flow control
2353 			 * is not applicable to tx data.
2354 			 * In LL systems, there is no download flow control,
2355 			 * since there's virtually no download delay.
2356 			 * In HL systems, the txrx SW explicitly performs the
2357 			 * tx flow control.
2358 			 */
2359 			/* pEndpoint->TxCredits +=
2360 			 * pPacket->PktInfo.AsTx.CreditsUsed;
2361 			 */
2362 
2363 			/* put this frame back at the front of the sendQueue */
2364 			HTC_PACKET_ENQUEUE_TO_HEAD(&sendQueue, pPacket);
2365 
2366 			/* put the sendQueue back at the front of
2367 			 * pEndpoint->TxQueue
2368 			 */
2369 			HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
2370 							  &sendQueue);
2371 			UNLOCK_HTC_TX(target);
2372 			break;  /* still need to reset TxProcessCount */
2373 		}
2374 	}
2375 	/* done with this endpoint, we can clear the count */
2376 	qdf_atomic_init(&pEndpoint->TxProcessCount);
2377 
2378 	if (pEndpoint->ul_is_polled) {
2379 		/*
2380 		 * Start a cleanup timer to poll for download completion.
2381 		 * The download completion should be noticed promptly from
2382 		 * other polling calls, but the timer provides a safety net
2383 		 * in case other polling calls don't occur as expected.
2384 		 */
2385 		htc_send_complete_poll_timer_start(pEndpoint);
2386 	}
2387 
2388 	return status;
2389 }
2390 #endif /*ATH_11AC_TXCOMPACT */
2391 qdf_export_symbol(htc_send_data_pkt);
2392 
2393 /*
2394  * In the adapted HIF layer, qdf_nbuf_t are passed between HIF and HTC,
2395  * since upper layers expects HTC_PACKET containers we use the completed netbuf
2396  * and lookup its corresponding HTC packet buffer from a lookup list.
2397  * This is extra overhead that can be fixed by re-aligning HIF interfaces
2398  * with HTC.
2399  *
2400  */
2401 static HTC_PACKET *htc_lookup_tx_packet(HTC_TARGET *target,
2402 					HTC_ENDPOINT *pEndpoint,
2403 					qdf_nbuf_t netbuf)
2404 {
2405 	HTC_PACKET *pPacket = NULL;
2406 	HTC_PACKET *pFoundPacket = NULL;
2407 	HTC_PACKET_QUEUE lookupQueue;
2408 
2409 	INIT_HTC_PACKET_QUEUE(&lookupQueue);
2410 	LOCK_HTC_EP_TX_LOOKUP(pEndpoint);
2411 
2412 	LOCK_HTC_TX(target);
2413 	/* mark that HIF has indicated the send complete for another packet */
2414 	pEndpoint->ul_outstanding_cnt--;
2415 
2416 	/* Dequeue first packet directly because of in-order completion */
2417 	pPacket = htc_packet_dequeue(&pEndpoint->TxLookupQueue);
2418 	if (qdf_unlikely(!pPacket)) {
2419 		UNLOCK_HTC_TX(target);
2420 		UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
2421 		return NULL;
2422 	}
2423 	if (netbuf == (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) {
2424 		UNLOCK_HTC_TX(target);
2425 		UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
2426 		return pPacket;
2427 	}
2428 	HTC_PACKET_ENQUEUE(&lookupQueue, pPacket);
2429 
2430 	/*
2431 	 * Move TX lookup queue to temp queue because most of packets that are
2432 	 * not index 0 are not top 10 packets.
2433 	 */
2434 	HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&lookupQueue,
2435 					  &pEndpoint->TxLookupQueue);
2436 
2437 	ITERATE_OVER_LIST_ALLOW_REMOVE(&lookupQueue.QueueHead, pPacket,
2438 				       HTC_PACKET, ListLink) {
2439 
2440 		if (!pPacket) {
2441 			pFoundPacket = pPacket;
2442 			break;
2443 		}
2444 		/* check for removal */
2445 		if (netbuf ==
2446 		    (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) {
2447 			/* found it */
2448 			HTC_PACKET_REMOVE(&lookupQueue, pPacket);
2449 			pFoundPacket = pPacket;
2450 			break;
2451 		}
2452 
2453 	}
2454 	ITERATE_END;
2455 
2456 	HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxLookupQueue,
2457 					  &lookupQueue);
2458 	UNLOCK_HTC_TX(target);
2459 	UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
2460 
2461 	return pFoundPacket;
2462 }
2463 
2464 /**
2465  * htc_tx_completion_handler() - htc tx completion handler
2466  * @Context: pointer to HTC_TARGET structure
2467  * @netbuf: pointer to netbuf for which completion handler is being called
2468  * @EpID: end point Id on which the packet was sent
2469  * @toeplitz_hash_result: toeplitz hash result
2470  *
2471  * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
2472  */
2473 QDF_STATUS htc_tx_completion_handler(void *Context,
2474 				   qdf_nbuf_t netbuf, unsigned int EpID,
2475 				   uint32_t toeplitz_hash_result)
2476 {
2477 	HTC_TARGET *target = (HTC_TARGET *) Context;
2478 	HTC_ENDPOINT *pEndpoint;
2479 	HTC_PACKET *pPacket;
2480 #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED
2481 	HTC_ENDPOINT_ID eid[DATA_EP_SIZE] = { ENDPOINT_5, ENDPOINT_4,
2482 		ENDPOINT_2, ENDPOINT_3 };
2483 	int epidIdx;
2484 	uint16_t resourcesThresh[DATA_EP_SIZE]; /* urb resources */
2485 	uint16_t resources;
2486 	uint16_t resourcesMax;
2487 #endif
2488 
2489 	pEndpoint = &target->endpoint[EpID];
2490 	target->TX_comp_cnt++;
2491 	pEndpoint->htc_comp_cnt++;
2492 
2493 	do {
2494 		pPacket = htc_lookup_tx_packet(target, pEndpoint, netbuf);
2495 		if (!pPacket) {
2496 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2497 					("HTC TX lookup failed!\n"));
2498 			/* may have already been flushed and freed */
2499 			netbuf = NULL;
2500 			break;
2501 		}
2502 		if (pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_AUTO_PM &&
2503 		    pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_RUNTIME_PUT &&
2504 		    pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_RTPM_PUT_RC) {
2505 			hif_rtpm_put(HIF_RTPM_PUT_ASYNC, HIF_RTPM_ID_WMI);
2506 			htc_dec_wmi_runtime_cnt(target, HIF_RTPM_ID_WMI);
2507 		}
2508 
2509 
2510 		if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) {
2511 			HTC_PACKET *pPacketTemp;
2512 			HTC_PACKET_QUEUE *pQueueSave =
2513 				(HTC_PACKET_QUEUE *) pPacket->pContext;
2514 			HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQueueSave,
2515 							      pPacketTemp) {
2516 				pPacket->Status = QDF_STATUS_SUCCESS;
2517 				send_packet_completion(target, pPacketTemp);
2518 			}
2519 			HTC_PACKET_QUEUE_ITERATE_END;
2520 			free_htc_bundle_packet(target, pPacket);
2521 
2522 			if (hif_get_bus_type(target->hif_dev) ==
2523 					     QDF_BUS_TYPE_USB) {
2524 				if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint))
2525 					htc_try_send(target, pEndpoint, NULL);
2526 			}
2527 
2528 			return QDF_STATUS_SUCCESS;
2529 		}
2530 		/* will be giving this buffer back to upper layers */
2531 		netbuf = NULL;
2532 		pPacket->Status = QDF_STATUS_SUCCESS;
2533 		send_packet_completion(target, pPacket);
2534 
2535 	} while (false);
2536 
2537 	if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
2538 		/* note: when using TX credit flow, the re-checking of queues
2539 		 * happens when credits flow back from the target. In the non-TX
2540 		 * credit case, we recheck after the packet completes
2541 		 */
2542 		if ((qdf_atomic_read(&pEndpoint->TxProcessCount) == 0) ||
2543 				(!pEndpoint->async_update)) {
2544 			htc_try_send(target, pEndpoint, NULL);
2545 		}
2546 	}
2547 
2548 	return QDF_STATUS_SUCCESS;
2549 }
2550 
2551 #ifdef WLAN_FEATURE_FASTPATH
2552 /**
2553  * htc_ctrl_msg_cmpl(): checks for tx completion for the endpoint specified
2554  * @HTC_HANDLE : pointer to the htc target context
2555  * @htc_ep_id  : end point id
2556  *
2557  * checks HTC tx completion
2558  *
2559  * Return: none
2560  */
2561 void htc_ctrl_msg_cmpl(HTC_HANDLE htc_pdev, HTC_ENDPOINT_ID htc_ep_id)
2562 {
2563 	HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(htc_pdev);
2564 	HTC_ENDPOINT    *pendpoint = &target->endpoint[htc_ep_id];
2565 
2566 	htc_send_complete_check(pendpoint, 1);
2567 }
2568 qdf_export_symbol(htc_ctrl_msg_cmpl);
2569 #endif
2570 
2571 /* callback when TX resources become available */
2572 void htc_tx_resource_avail_handler(void *context, uint8_t pipeID)
2573 {
2574 	int i;
2575 	HTC_TARGET *target = (HTC_TARGET *) context;
2576 	HTC_ENDPOINT *pEndpoint = NULL;
2577 
2578 	for (i = 0; i < ENDPOINT_MAX; i++) {
2579 		pEndpoint = &target->endpoint[i];
2580 		if (pEndpoint->service_id != 0) {
2581 			if (pEndpoint->UL_PipeID == pipeID)
2582 				break;
2583 		}
2584 	}
2585 
2586 	if (i >= ENDPOINT_MAX) {
2587 		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2588 				("Invalid pipe indicated for TX resource avail : %d!\n",
2589 				 pipeID));
2590 		return;
2591 	}
2592 
2593 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
2594 			("HIF indicated more resources for pipe:%d\n",
2595 			 pipeID));
2596 
2597 	htc_try_send(target, pEndpoint, NULL);
2598 }
2599 
2600 #ifdef FEATURE_RUNTIME_PM
2601 /**
2602  * htc_kick_queues(): resumes tx transactions of suspended endpoints
2603  * @context: pointer to the htc target context
2604  *
2605  * Iterates through the endpoints and provides a context to empty queues
2606  * int the hif layer when they are stalled due to runtime suspend.
2607  *
2608  * Return: none
2609  */
2610 void htc_kick_queues(void *context)
2611 {
2612 	int i;
2613 	HTC_TARGET *target = (HTC_TARGET *)context;
2614 	HTC_ENDPOINT *endpoint = NULL;
2615 
2616 	if (hif_rtpm_get(HIF_RTPM_GET_SYNC, HIF_RTPM_ID_HTT))
2617 		return;
2618 
2619 	for (i = 0; i < ENDPOINT_MAX; i++) {
2620 		endpoint = &target->endpoint[i];
2621 
2622 		if (endpoint->service_id == 0)
2623 			continue;
2624 
2625 		if (endpoint->EpCallBacks.ep_resume_tx_queue)
2626 			endpoint->EpCallBacks.ep_resume_tx_queue(
2627 					endpoint->EpCallBacks.pContext);
2628 
2629 		htc_try_send(target, endpoint, NULL);
2630 	}
2631 
2632 	hif_fastpath_resume(target->hif_dev);
2633 
2634 	hif_rtpm_put(HIF_RTPM_PUT_ASYNC, HIF_RTPM_ID_HTT);
2635 }
2636 #endif
2637 
2638 /* flush endpoint TX queue */
2639 void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint,
2640 			   HTC_TX_TAG Tag)
2641 {
2642 	HTC_PACKET *pPacket;
2643 
2644 	LOCK_HTC_TX(target);
2645 	while (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) {
2646 		pPacket = htc_packet_dequeue(&pEndpoint->TxQueue);
2647 
2648 		if (pPacket) {
2649 			/* let the sender know the packet was not delivered */
2650 			pPacket->Status = QDF_STATUS_E_CANCELED;
2651 			send_packet_completion(target, pPacket);
2652 		}
2653 	}
2654 	UNLOCK_HTC_TX(target);
2655 }
2656 
2657 /* flush pending entries in endpoint TX Lookup queue */
2658 void htc_flush_endpoint_txlookupQ(HTC_TARGET *target,
2659 				  HTC_ENDPOINT_ID endpoint_id,
2660 				  bool call_ep_callback)
2661 {
2662 	HTC_PACKET *packet;
2663 	HTC_ENDPOINT *endpoint;
2664 
2665 	endpoint = &target->endpoint[endpoint_id];
2666 
2667 	if (!endpoint && endpoint->service_id == 0)
2668 		return;
2669 
2670 	LOCK_HTC_TX(target);
2671 	while (HTC_PACKET_QUEUE_DEPTH(&endpoint->TxLookupQueue)) {
2672 		packet = htc_packet_dequeue(&endpoint->TxLookupQueue);
2673 
2674 		if (packet) {
2675 			if (call_ep_callback == true) {
2676 				packet->Status = QDF_STATUS_E_CANCELED;
2677 				send_packet_completion(target, packet);
2678 			} else {
2679 				qdf_mem_free(packet);
2680 			}
2681 		}
2682 	}
2683 	UNLOCK_HTC_TX(target);
2684 }
2685 
2686 /* HTC API to flush an endpoint's TX queue*/
2687 void htc_flush_endpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint,
2688 			HTC_TX_TAG Tag)
2689 {
2690 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
2691 	HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint];
2692 
2693 	if (pEndpoint->service_id == 0) {
2694 		AR_DEBUG_ASSERT(false);
2695 		/* not in use.. */
2696 		return;
2697 	}
2698 
2699 	htc_flush_endpoint_tx(target, pEndpoint, Tag);
2700 }
2701 
2702 /* HTC API to indicate activity to the credit distribution function */
2703 void htc_indicate_activity_change(HTC_HANDLE HTCHandle,
2704 				  HTC_ENDPOINT_ID Endpoint, bool Active)
2705 {
2706 	/*  TODO */
2707 }
2708 
2709 bool htc_is_endpoint_active(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint)
2710 {
2711 	return true;
2712 }
2713 
2714 void htc_set_pkt_dbg(HTC_HANDLE handle, A_BOOL dbg_flag)
2715 {
2716 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(handle);
2717 
2718 	target->htc_pkt_dbg = dbg_flag;
2719 }
2720 
2721 void htc_set_nodrop_pkt(HTC_HANDLE HTCHandle, A_BOOL isNodropPkt)
2722 {
2723 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
2724 
2725 	target->is_nodrop_pkt = isNodropPkt;
2726 }
2727 
2728 void htc_enable_hdr_length_check(HTC_HANDLE htc_hdl, bool htc_hdr_length_check)
2729 {
2730 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl);
2731 
2732 	target->htc_hdr_length_check = htc_hdr_length_check;
2733 }
2734 
2735 /**
2736  * htc_process_credit_rpt() - process credit report, call distribution function
2737  * @target: pointer to HTC_TARGET
2738  * @pRpt: pointer to HTC_CREDIT_REPORT
2739  * @NumEntries: number of entries in credit report
2740  * @FromEndpoint: endpoint for which  credit report is received
2741  *
2742  * Return: A_OK for success or an appropriate A_STATUS error
2743  */
2744 void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt,
2745 			    int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
2746 {
2747 	int i;
2748 	HTC_ENDPOINT *pEndpoint;
2749 	int totalCredits = 0;
2750 	uint8_t rpt_credits, rpt_ep_id;
2751 
2752 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
2753 			("+htc_process_credit_rpt, Credit Report Entries:%d\n",
2754 			 NumEntries));
2755 
2756 	/* lock out TX while we update credits */
2757 	LOCK_HTC_TX(target);
2758 
2759 	for (i = 0; i < NumEntries; i++, pRpt++) {
2760 
2761 		rpt_ep_id = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, ENDPOINTID);
2762 
2763 		if (rpt_ep_id >= ENDPOINT_MAX) {
2764 			AR_DEBUG_ASSERT(false);
2765 			break;
2766 		}
2767 
2768 		rpt_credits = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, CREDITS);
2769 
2770 		pEndpoint = &target->endpoint[rpt_ep_id];
2771 #if DEBUG_CREDIT
2772 		if (ep_debug_mask & (1 << pEndpoint->Id)) {
2773 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
2774 					(" <HTC> Increase EP%d %d + %d = %d credits\n",
2775 					 rpt_ep_id, pEndpoint->TxCredits,
2776 					 rpt_credits,
2777 					 pEndpoint->TxCredits + rpt_credits));
2778 		}
2779 #endif
2780 
2781 #ifdef HTC_EP_STAT_PROFILING
2782 
2783 		INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
2784 		INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, rpt_credits);
2785 
2786 		if (FromEndpoint == rpt_ep_id) {
2787 			/* this credit report arrived on the same endpoint
2788 			 * indicating it arrived in an RX packet
2789 			 */
2790 			INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx,
2791 					rpt_credits);
2792 			INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
2793 		} else if (FromEndpoint == ENDPOINT_0) {
2794 			/* this credit arrived on endpoint 0 as a NULL msg */
2795 			INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0,
2796 					rpt_credits);
2797 			INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
2798 		} else {
2799 			/* arrived on another endpoint */
2800 			INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther,
2801 					rpt_credits);
2802 			INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
2803 		}
2804 
2805 #endif
2806 
2807 		if (pEndpoint->service_id == WMI_CONTROL_SVC) {
2808 			htc_credit_record(HTC_PROCESS_CREDIT_REPORT,
2809 					  pEndpoint->TxCredits + rpt_credits,
2810 					  HTC_PACKET_QUEUE_DEPTH(&pEndpoint->
2811 							TxQueue));
2812 			hif_latency_detect_credit_record_time(
2813 					HIF_PROCESS_CREDIT_REPORT,
2814 					target->hif_dev);
2815 		}
2816 
2817 		pEndpoint->TxCredits += rpt_credits;
2818 
2819 		if (pEndpoint->TxCredits
2820 		    && HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) {
2821 			UNLOCK_HTC_TX(target);
2822 #ifdef ATH_11AC_TXCOMPACT
2823 			htc_try_send(target, pEndpoint, NULL);
2824 #else
2825 			if (pEndpoint->service_id == HTT_DATA_MSG_SVC)
2826 				htc_send_data_pkt((HTC_HANDLE)target, NULL, 0);
2827 			else
2828 				htc_try_send(target, pEndpoint, NULL);
2829 #endif
2830 			LOCK_HTC_TX(target);
2831 		}
2832 		totalCredits += rpt_credits;
2833 	}
2834 
2835 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
2836 			("  Report indicated %d credits to distribute\n",
2837 			 totalCredits));
2838 
2839 	UNLOCK_HTC_TX(target);
2840 
2841 	AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_process_credit_rpt\n"));
2842 }
2843 
2844 /* function to fetch stats from htc layer*/
2845 struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE HTCHandle)
2846 {
2847 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
2848 
2849 	return &(target->htc_pkt_stats);
2850 }
2851 
2852 #ifdef SYSTEM_PM_CHECK
2853 void htc_system_resume(HTC_HANDLE htc)
2854 {
2855 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc);
2856 	HTC_ENDPOINT *endpoint = NULL;
2857 	int i;
2858 
2859 	if (!target)
2860 		return;
2861 
2862 	for (i = 0; i < ENDPOINT_MAX; i++) {
2863 		endpoint = &target->endpoint[i];
2864 
2865 		if (endpoint->service_id == 0)
2866 			continue;
2867 
2868 		htc_try_send(target, endpoint, NULL);
2869 	}
2870 }
2871 #endif
2872