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