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