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