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