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