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