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