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