xref: /wlan-dirver/qca-wifi-host-cmn/htc/htc.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
1 /*
2  * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
3  *
4  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5  *
6  *
7  * Permission to use, copy, modify, and/or distribute this software for
8  * any purpose with or without fee is hereby granted, provided that the
9  * above copyright notice and this permission notice appear in all
10  * copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19  * PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 /*
23  * This file was originally distributed by Qualcomm Atheros, Inc.
24  * under proprietary terms before Copyright ownership was assigned
25  * to the Linux Foundation.
26  */
27 
28 #include "htc_debug.h"
29 #include "htc_internal.h"
30 #include "htc_credit_history.h"
31 #include <hif.h>
32 #include <qdf_nbuf.h>           /* qdf_nbuf_t */
33 #include <qdf_types.h>          /* qdf_print */
34 
35 #define MAX_HTC_RX_BUNDLE  2
36 
37 #if defined(WLAN_DEBUG) || defined(DEBUG)
38 static ATH_DEBUG_MASK_DESCRIPTION g_htc_debug_description[] = {
39 	{ATH_DEBUG_SEND, "Send"},
40 	{ATH_DEBUG_RECV, "Recv"},
41 	{ATH_DEBUG_SYNC, "Sync"},
42 	{ATH_DEBUG_DUMP, "Dump Data (RX or TX)"},
43 	{ATH_DEBUG_SETUP, "Setup"},
44 };
45 
46 ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc,
47 				 "htc",
48 				 "Host Target Communications",
49 				 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO |
50 				 ATH_DEBUG_SETUP,
51 				 ATH_DEBUG_DESCRIPTION_COUNT
52 					 (g_htc_debug_description),
53 				 g_htc_debug_description);
54 
55 #endif
56 
57 #if (defined(CONFIG_MCL) || (QCA_WIFI_QCA8074))
58 static const uint32_t svc_id[] = {WMI_CONTROL_SVC, WMI_CONTROL_SVC_WMAC1,
59 						WMI_CONTROL_SVC_WMAC2};
60 #else
61 static const uint32_t svc_id[] = {WMI_CONTROL_SVC};
62 #endif
63 
64 extern unsigned int htc_credit_flow;
65 
66 static void reset_endpoint_states(HTC_TARGET *target);
67 
68 static void destroy_htc_tx_ctrl_packet(HTC_PACKET *pPacket)
69 {
70 	qdf_nbuf_t netbuf;
71 
72 	netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
73 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("free ctrl netbuf :0x%pK\n", netbuf));
74 	if (netbuf != NULL)
75 		qdf_nbuf_free(netbuf);
76 	qdf_mem_free(pPacket);
77 }
78 
79 static HTC_PACKET *build_htc_tx_ctrl_packet(qdf_device_t osdev)
80 {
81 	HTC_PACKET *pPacket = NULL;
82 	qdf_nbuf_t netbuf;
83 
84 	do {
85 		pPacket = (HTC_PACKET *) qdf_mem_malloc(sizeof(HTC_PACKET));
86 		if (pPacket == NULL)
87 			break;
88 		netbuf = qdf_nbuf_alloc(osdev, HTC_CONTROL_BUFFER_SIZE,
89 					20, 4, true);
90 		if (NULL == netbuf) {
91 			qdf_mem_free(pPacket);
92 			pPacket = NULL;
93 			qdf_print("%s: nbuf alloc failed\n", __func__);
94 			break;
95 		}
96 		AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
97 				("alloc ctrl netbuf :0x%pK\n", netbuf));
98 		SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
99 	} while (false);
100 
101 	return pPacket;
102 }
103 
104 void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
105 {
106 
107 #ifdef TODO_FIXME
108 	LOCK_HTC(target);
109 	HTC_PACKET_ENQUEUE(&target->ControlBufferTXFreeList, pPacket);
110 	UNLOCK_HTC(target);
111 	/* TODO_FIXME netbufs cannot be RESET! */
112 #else
113 	destroy_htc_tx_ctrl_packet(pPacket);
114 #endif
115 
116 }
117 
118 HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target)
119 {
120 #ifdef TODO_FIXME
121 	HTC_PACKET *pPacket;
122 
123 	LOCK_HTC(target);
124 	pPacket = htc_packet_dequeue(&target->ControlBufferTXFreeList);
125 	UNLOCK_HTC(target);
126 
127 	return pPacket;
128 #else
129 	return build_htc_tx_ctrl_packet(target->osdev);
130 #endif
131 }
132 
133 /* Set the target failure handling callback */
134 void htc_set_target_failure_callback(HTC_HANDLE HTCHandle,
135 				     HTC_TARGET_FAILURE Callback)
136 {
137 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
138 
139 	target->HTCInitInfo.TargetFailure = Callback;
140 }
141 
142 void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start)
143 {
144 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
145 
146 	hif_dump(target->hif_dev, CmdId, start);
147 }
148 
149 /* cleanup the HTC instance */
150 static void htc_cleanup(HTC_TARGET *target)
151 {
152 	HTC_PACKET *pPacket;
153 	int i;
154 	HTC_ENDPOINT *endpoint;
155 	HTC_PACKET_QUEUE *pkt_queue;
156 	qdf_nbuf_t netbuf;
157 
158 	if (target->hif_dev != NULL) {
159 		hif_detach_htc(target->hif_dev);
160 		hif_mask_interrupt_call(target->hif_dev);
161 		target->hif_dev = NULL;
162 	}
163 
164 	while (true) {
165 		pPacket = allocate_htc_packet_container(target);
166 		if (pPacket == NULL)
167 			break;
168 		qdf_mem_free(pPacket);
169 	}
170 
171 	LOCK_HTC_TX(target);
172 	pPacket = target->pBundleFreeList;
173 	target->pBundleFreeList = NULL;
174 	UNLOCK_HTC_TX(target);
175 	while (pPacket) {
176 		HTC_PACKET *pPacketTmp = (HTC_PACKET *) pPacket->ListLink.pNext;
177 		netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
178 		if (netbuf)
179 			qdf_nbuf_free(netbuf);
180 		pkt_queue = pPacket->pContext;
181 		if (pkt_queue)
182 			qdf_mem_free(pkt_queue);
183 		qdf_mem_free(pPacket);
184 		pPacket = pPacketTmp;
185 	}
186 
187 #ifdef TODO_FIXME
188 	while (true) {
189 		pPacket = htc_alloc_control_tx_packet(target);
190 		if (pPacket == NULL)
191 			break;
192 		netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
193 		if (netbuf != NULL)
194 			qdf_nbuf_free(netbuf);
195 		qdf_mem_free(pPacket);
196 	}
197 #endif
198 
199 	qdf_spinlock_destroy(&target->HTCLock);
200 	qdf_spinlock_destroy(&target->HTCRxLock);
201 	qdf_spinlock_destroy(&target->HTCTxLock);
202 	qdf_spinlock_destroy(&target->HTCCreditLock);
203 	for (i = 0; i < ENDPOINT_MAX; i++) {
204 		endpoint = &target->endpoint[i];
205 		qdf_spinlock_destroy(&endpoint->lookup_queue_lock);
206 	}
207 
208 	/* free our instance */
209 	qdf_mem_free(target);
210 }
211 
212 #ifdef FEATURE_RUNTIME_PM
213 /**
214  * htc_runtime_pm_init(): runtime pm related intialization
215  *
216  * need to initialize a work item.
217  */
218 static void htc_runtime_pm_init(HTC_TARGET *target)
219 {
220 	qdf_create_work(0, &target->queue_kicker, htc_kick_queues, target);
221 }
222 
223 /**
224  * htc_runtime_suspend() - runtime suspend HTC
225  *
226  * @htc_ctx: HTC context pointer
227  *
228  * This is a dummy function for symmetry.
229  *
230  * Return: 0 for success
231  */
232 int htc_runtime_suspend(HTC_HANDLE htc_ctx)
233 {
234 	return 0;
235 }
236 
237 /**
238  * htc_runtime_resume(): resume htc
239  *
240  * The htc message queue needs to be kicked off after
241  * a runtime resume.  Otherwise messages would get stuck.
242  *
243  * @htc_ctx: HTC context pointer
244  *
245  * Return: 0 for success;
246  */
247 int htc_runtime_resume(HTC_HANDLE htc_ctx)
248 {
249 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_ctx);
250 
251 	if (target == NULL)
252 		return 0;
253 
254 	qdf_sched_work(0, &target->queue_kicker);
255 	return 0;
256 }
257 #else
258 static inline void htc_runtime_pm_init(HTC_TARGET *target) { }
259 #endif
260 
261 /* registered target arrival callback from the HIF layer */
262 HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo,
263 			qdf_device_t osdev, uint32_t con_mode)
264 {
265 	struct hif_msg_callbacks htcCallbacks;
266 	HTC_ENDPOINT *pEndpoint = NULL;
267 	HTC_TARGET *target = NULL;
268 	int i;
269 
270 	if (ol_sc == NULL) {
271 		HTC_ERROR("%s: ol_sc = NULL", __func__);
272 		return NULL;
273 	}
274 	HTC_TRACE("+htc_create ..  HIF :%pK", ol_sc);
275 
276 	A_REGISTER_MODULE_DEBUG_INFO(htc);
277 
278 	target = (HTC_TARGET *) qdf_mem_malloc(sizeof(HTC_TARGET));
279 	if (target == NULL) {
280 		HTC_ERROR("%s: Unable to allocate memory", __func__);
281 		return NULL;
282 	}
283 
284 	htc_runtime_pm_init(target);
285 	htc_credit_history_init();
286 	qdf_spinlock_create(&target->HTCLock);
287 	qdf_spinlock_create(&target->HTCRxLock);
288 	qdf_spinlock_create(&target->HTCTxLock);
289 	for (i = 0; i < ENDPOINT_MAX; i++) {
290 		pEndpoint = &target->endpoint[i];
291 		qdf_spinlock_create(&pEndpoint->lookup_queue_lock);
292 	}
293 	target->is_nodrop_pkt = false;
294 	target->wmi_ep_count = 1;
295 
296 	do {
297 		qdf_mem_copy(&target->HTCInitInfo, pInfo,
298 			     sizeof(struct htc_init_info));
299 		target->host_handle = pInfo->pContext;
300 		target->osdev = osdev;
301 		target->con_mode = con_mode;
302 
303 		reset_endpoint_states(target);
304 
305 		INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList);
306 
307 		for (i = 0; i < HTC_PACKET_CONTAINER_ALLOCATION; i++) {
308 			HTC_PACKET *pPacket = (HTC_PACKET *)
309 					qdf_mem_malloc(sizeof(HTC_PACKET));
310 			if (pPacket != NULL)
311 				free_htc_packet_container(target, pPacket);
312 		}
313 
314 #ifdef TODO_FIXME
315 		for (i = 0; i < NUM_CONTROL_TX_BUFFERS; i++) {
316 			pPacket = build_htc_tx_ctrl_packet();
317 			if (pPacket == NULL)
318 				break;
319 			htc_free_control_tx_packet(target, pPacket);
320 		}
321 #endif
322 
323 		/* setup HIF layer callbacks */
324 		qdf_mem_zero(&htcCallbacks, sizeof(struct hif_msg_callbacks));
325 		htcCallbacks.Context = target;
326 		htcCallbacks.rxCompletionHandler = htc_rx_completion_handler;
327 		htcCallbacks.txCompletionHandler = htc_tx_completion_handler;
328 		htcCallbacks.txResourceAvailHandler =
329 						 htc_tx_resource_avail_handler;
330 		htcCallbacks.fwEventHandler = htc_fw_event_handler;
331 		target->hif_dev = ol_sc;
332 
333 		/* Get HIF default pipe for HTC message exchange */
334 		pEndpoint = &target->endpoint[ENDPOINT_0];
335 
336 		hif_post_init(target->hif_dev, target, &htcCallbacks);
337 		hif_get_default_pipe(target->hif_dev, &pEndpoint->UL_PipeID,
338 				     &pEndpoint->DL_PipeID);
339 		hif_set_initial_wakeup_cb(target->hif_dev,
340 					  pInfo->target_initial_wakeup_cb,
341 					  pInfo->target_psoc);
342 
343 	} while (false);
344 
345 	htc_recv_init(target);
346 
347 	HTC_TRACE("-htc_create: (0x%pK)", target);
348 
349 	return (HTC_HANDLE) target;
350 }
351 
352 void htc_destroy(HTC_HANDLE HTCHandle)
353 {
354 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
355 
356 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
357 			("+htc_destroy ..  Destroying :0x%pK\n", target));
358 	hif_stop(htc_get_hif_device(HTCHandle));
359 	if (target)
360 		htc_cleanup(target);
361 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n"));
362 }
363 
364 /* get the low level HIF device for the caller , the caller may wish to do low
365  * level HIF requests
366  */
367 void *htc_get_hif_device(HTC_HANDLE HTCHandle)
368 {
369 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
370 
371 	return target->hif_dev;
372 }
373 
374 static void htc_control_tx_complete(void *Context, HTC_PACKET *pPacket)
375 {
376 	HTC_TARGET *target = (HTC_TARGET *) Context;
377 
378 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
379 			("+-htc_control_tx_complete 0x%pK (l:%d)\n", pPacket,
380 			 pPacket->ActualLength));
381 	htc_free_control_tx_packet(target, pPacket);
382 }
383 
384 /* TODO, this is just a temporary max packet size */
385 #define MAX_MESSAGE_SIZE 1536
386 
387 /**
388  * htc_setup_epping_credit_allocation() - allocate credits/HTC buffers to WMI
389  * @scn: pointer to hif_opaque_softc
390  * @pEntry: pointer to tx credit allocation entry
391  * @credits: number of credits
392  *
393  * Return: None
394  */
395 static void
396 htc_setup_epping_credit_allocation(struct hif_opaque_softc *scn,
397 			   struct htc_service_tx_credit_allocation *pEntry,
398 			   int credits)
399 {
400 	switch (hif_get_bus_type(scn)) {
401 	case QDF_BUS_TYPE_PCI:
402 		pEntry++;
403 		pEntry->service_id = WMI_DATA_BE_SVC;
404 		pEntry->CreditAllocation = (credits >> 1);
405 
406 		pEntry++;
407 		pEntry->service_id = WMI_DATA_BK_SVC;
408 		pEntry->CreditAllocation = (credits >> 1);
409 		break;
410 	case QDF_BUS_TYPE_SDIO:
411 		pEntry++;
412 		pEntry->service_id = WMI_DATA_BE_SVC;
413 		pEntry->CreditAllocation = credits;
414 		break;
415 	default:
416 		break;
417 	}
418 }
419 
420 /**
421  * htc_setup_target_buffer_assignments() - setup target buffer assignments
422  * @target: HTC Target Pointer
423  *
424  * Return: A_STATUS
425  */
426 static
427 A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target)
428 {
429 	struct htc_service_tx_credit_allocation *pEntry;
430 	A_STATUS status;
431 	int credits;
432 	int creditsPerMaxMsg;
433 
434 	creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize;
435 	if (MAX_MESSAGE_SIZE % target->TargetCreditSize)
436 		creditsPerMaxMsg++;
437 
438 	/* TODO, this should be configured by the caller! */
439 
440 	credits = target->TotalTransmitCredits;
441 	pEntry = &target->ServiceTxAllocTable[0];
442 
443 	status = A_OK;
444 	/*
445 	 * Allocate all credists/HTC buffers to WMI.
446 	 * no buffers are used/required for data. data always
447 	 * remains on host.
448 	 */
449 	if (HTC_IS_EPPING_ENABLED(target->con_mode)) {
450 		pEntry++;
451 		pEntry->service_id = WMI_CONTROL_SVC;
452 		pEntry->CreditAllocation = credits;
453 		/* endpoint ping is a testing tool directly on top of HTC in
454 		 * both target and host sides.
455 		 * In target side, the endppint ping fw has no wlan stack and
456 		 * FW mboxping app directly sits on HTC and it simply drops
457 		 * or loops back TX packets. For rx perf, FW mboxping app
458 		 * generates packets and passes packets to HTC to send to host.
459 		 * There is no WMI mesage exchanges between host and target
460 		 * in endpoint ping case.
461 		 * In host side, the endpoint ping driver is a Ethernet driver
462 		 * and it directly sits on HTC. Only HIF, HTC, QDF, ADF are
463 		 * used by the endpoint ping driver. There is no wifi stack
464 		 * at all in host side also. For tx perf use case,
465 		 * the user space mboxping app sends the raw packets to endpoint
466 		 * ping driver and it directly forwards to HTC for transmission
467 		 * to stress the bus. For the rx perf, HTC passes the received
468 		 * packets to endpoint ping driver and it is passed to the user
469 		 * space through the Ethernet interface.
470 		 * For credit allocation, in SDIO bus case, only BE service is
471 		 * used for tx/rx perf testing so that all credits are given
472 		 * to BE service. In PCIe and USB bus case, endpoint ping uses
473 		 * both BE and BK services to stress the bus so that the total
474 		 * credits are equally distributed to BE and BK services.
475 		 */
476 
477 		htc_setup_epping_credit_allocation(target->hif_dev,
478 						   pEntry, credits);
479 	} else {
480 		int i;
481 		uint32_t max_wmi_svc = (sizeof(svc_id) / sizeof(uint32_t));
482 
483 		if ((target->wmi_ep_count == 0) ||
484 				(target->wmi_ep_count > max_wmi_svc))
485 			return A_ERROR;
486 
487 		/*
488 		 * Divide credit among number of endpoints for WMI
489 		 */
490 		credits = credits / target->wmi_ep_count;
491 		for (i = 0; i < target->wmi_ep_count; i++) {
492 			status = A_OK;
493 			pEntry++;
494 			pEntry->service_id = svc_id[i];
495 			pEntry->CreditAllocation = credits;
496 		}
497 	}
498 
499 	if (A_SUCCESS(status)) {
500 		int i;
501 
502 		for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
503 			if (target->ServiceTxAllocTable[i].service_id != 0) {
504 				AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
505 						("SVS Index : %d TX : 0x%2.2X : alloc:%d",
506 						 i,
507 						 target->ServiceTxAllocTable[i].
508 						 service_id,
509 						 target->ServiceTxAllocTable[i].
510 						 CreditAllocation));
511 			}
512 		}
513 	}
514 
515 	return status;
516 }
517 
518 uint8_t htc_get_credit_allocation(HTC_TARGET *target, uint16_t service_id)
519 {
520 	uint8_t allocation = 0;
521 	int i;
522 
523 	for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
524 		if (target->ServiceTxAllocTable[i].service_id == service_id) {
525 			allocation =
526 				target->ServiceTxAllocTable[i].CreditAllocation;
527 		}
528 	}
529 
530 	if (0 == allocation) {
531 		AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1,
532 			("HTC Service TX : 0x%2.2X : allocation is zero!\n",
533 				 service_id));
534 	}
535 
536 	return allocation;
537 }
538 
539 QDF_STATUS htc_wait_target(HTC_HANDLE HTCHandle)
540 {
541 	QDF_STATUS status = QDF_STATUS_SUCCESS;
542 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
543 	HTC_READY_EX_MSG *pReadyMsg;
544 	struct htc_service_connect_req connect;
545 	struct htc_service_connect_resp resp;
546 	HTC_READY_MSG *rdy_msg;
547 	uint16_t htc_rdy_msg_id;
548 	uint8_t i = 0;
549 	HTC_PACKET *rx_bundle_packet, *temp_bundle_packet;
550 
551 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
552 			("htc_wait_target - Enter (target:0x%pK)\n", HTCHandle));
553 	AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("+HWT\n"));
554 
555 	do {
556 
557 		status = hif_start(target->hif_dev);
558 		if (QDF_IS_STATUS_ERROR(status)) {
559 			AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
560 					("hif_start failed\n"));
561 			break;
562 		}
563 
564 		status = htc_wait_recv_ctrl_message(target);
565 
566 		if (QDF_IS_STATUS_ERROR(status))
567 			break;
568 
569 		if (target->CtrlResponseLength < (sizeof(HTC_READY_EX_MSG))) {
570 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
571 					("Invalid HTC Ready Msg Len:%d!\n",
572 					 target->CtrlResponseLength));
573 			status = QDF_STATUS_E_BADMSG;
574 			break;
575 		}
576 
577 		pReadyMsg = (HTC_READY_EX_MSG *) target->CtrlResponseBuffer;
578 
579 		rdy_msg = &pReadyMsg->Version2_0_Info;
580 		htc_rdy_msg_id =
581 			HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, MESSAGEID);
582 		if (htc_rdy_msg_id != HTC_MSG_READY_ID) {
583 			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
584 					("Invalid HTC Ready Msg : 0x%X!\n",
585 					 htc_rdy_msg_id));
586 			status = QDF_STATUS_E_BADMSG;
587 			break;
588 		}
589 
590 		target->TotalTransmitCredits =
591 			HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITCOUNT);
592 		target->TargetCreditSize =
593 			(int)HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITSIZE);
594 		target->MaxMsgsPerHTCBundle =
595 			(uint8_t) pReadyMsg->MaxMsgsPerHTCBundle;
596 		UPDATE_ALT_CREDIT(target, pReadyMsg->AltDataCreditSize);
597 		/* for old fw this value is set to 0. But the minimum value
598 		 * should be 1, i.e., no bundling
599 		 */
600 		if (target->MaxMsgsPerHTCBundle < 1)
601 			target->MaxMsgsPerHTCBundle = 1;
602 
603 		AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
604 				("Target Ready! TX resource : %d size:%d, MaxMsgsPerHTCBundle = %d",
605 				 target->TotalTransmitCredits,
606 				 target->TargetCreditSize,
607 				 target->MaxMsgsPerHTCBundle));
608 
609 		if ((0 == target->TotalTransmitCredits)
610 		    || (0 == target->TargetCreditSize)) {
611 			status = QDF_STATUS_E_ABORTED;
612 			break;
613 		}
614 
615 		/* Allocate expected number of RX bundle buffer allocation */
616 		if (HTC_RX_BUNDLE_ENABLED(target)) {
617 			temp_bundle_packet = NULL;
618 			for (i = 0; i < MAX_HTC_RX_BUNDLE; i++) {
619 				rx_bundle_packet =
620 					allocate_htc_bundle_packet(target);
621 				if (rx_bundle_packet != NULL)
622 					rx_bundle_packet->ListLink.pNext =
623 						(DL_LIST *)temp_bundle_packet;
624 				else
625 					break;
626 
627 				temp_bundle_packet = rx_bundle_packet;
628 			}
629 			LOCK_HTC_TX(target);
630 			target->pBundleFreeList = temp_bundle_packet;
631 			UNLOCK_HTC_TX(target);
632 		}
633 
634 		/* done processing */
635 		target->CtrlResponseProcessing = false;
636 
637 		htc_setup_target_buffer_assignments(target);
638 
639 		/* setup our pseudo HTC control endpoint connection */
640 		qdf_mem_zero(&connect, sizeof(connect));
641 		qdf_mem_zero(&resp, sizeof(resp));
642 		connect.EpCallbacks.pContext = target;
643 		connect.EpCallbacks.EpTxComplete = htc_control_tx_complete;
644 		connect.EpCallbacks.EpRecv = htc_control_rx_complete;
645 		connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS;
646 		connect.service_id = HTC_CTRL_RSVD_SVC;
647 
648 		/* connect fake service */
649 		status = htc_connect_service((HTC_HANDLE) target,
650 					     &connect, &resp);
651 
652 	} while (false);
653 
654 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_wait_target - Exit (%d)\n",
655 			status));
656 	AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("-HWT\n"));
657 	return status;
658 }
659 
660 /* start HTC, this is called after all services are connected */
661 static A_STATUS htc_config_target_hif_pipe(HTC_TARGET *target)
662 {
663 
664 	return A_OK;
665 }
666 
667 static void reset_endpoint_states(HTC_TARGET *target)
668 {
669 	HTC_ENDPOINT *pEndpoint;
670 	int i;
671 
672 	for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
673 		pEndpoint = &target->endpoint[i];
674 		pEndpoint->service_id = 0;
675 		pEndpoint->MaxMsgLength = 0;
676 		pEndpoint->MaxTxQueueDepth = 0;
677 		pEndpoint->Id = i;
678 		INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue);
679 		INIT_HTC_PACKET_QUEUE(&pEndpoint->TxLookupQueue);
680 		INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBufferHoldQueue);
681 		pEndpoint->target = target;
682 		pEndpoint->TxCreditFlowEnabled = (bool)htc_credit_flow;
683 		qdf_atomic_init(&pEndpoint->TxProcessCount);
684 	}
685 }
686 
687 /**
688  * htc_start() - Main HTC function to trigger HTC start
689  * @HTCHandle: pointer to HTC handle
690  *
691  * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
692  */
693 QDF_STATUS htc_start(HTC_HANDLE HTCHandle)
694 {
695 	qdf_nbuf_t netbuf;
696 	QDF_STATUS status = QDF_STATUS_SUCCESS;
697 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
698 	HTC_SETUP_COMPLETE_EX_MSG *pSetupComp;
699 	HTC_PACKET *pSendPacket;
700 
701 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Enter\n"));
702 
703 	do {
704 
705 		htc_config_target_hif_pipe(target);
706 
707 		/* allocate a buffer to send */
708 		pSendPacket = htc_alloc_control_tx_packet(target);
709 		if (NULL == pSendPacket) {
710 			AR_DEBUG_ASSERT(false);
711 			qdf_print("%s: allocControlTxPacket failed\n",
712 				  __func__);
713 			status = QDF_STATUS_E_NOMEM;
714 			break;
715 		}
716 
717 		netbuf =
718 		   (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket);
719 		/* assemble setup complete message */
720 		qdf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
721 		pSetupComp =
722 			(HTC_SETUP_COMPLETE_EX_MSG *) qdf_nbuf_data(netbuf);
723 		qdf_mem_zero(pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
724 
725 		HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG,
726 			      MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID);
727 
728 		if (!htc_credit_flow) {
729 			AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
730 					("HTC will not use TX credit flow control"));
731 			pSetupComp->SetupFlags |=
732 				HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW;
733 		} else {
734 			AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
735 					("HTC using TX credit flow control"));
736 		}
737 
738 		if ((hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO) ||
739 					(hif_get_bus_type(target->hif_dev) ==
740 							 QDF_BUS_TYPE_USB)) {
741 			if (HTC_RX_BUNDLE_ENABLED(target))
742 			pSetupComp->SetupFlags |=
743 				HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV;
744 			hif_set_bundle_mode(target->hif_dev, true,
745 				HTC_MAX_MSG_PER_BUNDLE_RX);
746 		}
747 
748 		SET_HTC_PACKET_INFO_TX(pSendPacket,
749 				       NULL,
750 				       (uint8_t *) pSetupComp,
751 				       sizeof(HTC_SETUP_COMPLETE_EX_MSG),
752 				       ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
753 
754 		status = htc_send_pkt((HTC_HANDLE) target, pSendPacket);
755 		if (QDF_IS_STATUS_ERROR(status))
756 			break;
757 	} while (false);
758 
759 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Exit\n"));
760 	return status;
761 }
762 
763 /*flush all queued buffers for surpriseremove case*/
764 void htc_flush_surprise_remove(HTC_HANDLE HTCHandle)
765 {
766 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
767 	int i;
768 	HTC_ENDPOINT *pEndpoint;
769 #ifdef RX_SG_SUPPORT
770 	qdf_nbuf_t netbuf;
771 	qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
772 #endif
773 
774 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove\n"));
775 
776 	/* cleanup endpoints */
777 	for (i = 0; i < ENDPOINT_MAX; i++) {
778 		pEndpoint = &target->endpoint[i];
779 		htc_flush_rx_hold_queue(target, pEndpoint);
780 		htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
781 	}
782 
783 	hif_flush_surprise_remove(target->hif_dev);
784 
785 #ifdef RX_SG_SUPPORT
786 	LOCK_HTC_RX(target);
787 	while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
788 		qdf_nbuf_free(netbuf);
789 	RESET_RX_SG_CONFIG(target);
790 	UNLOCK_HTC_RX(target);
791 #endif
792 
793 	reset_endpoint_states(target);
794 
795 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove\n"));
796 }
797 
798 /* stop HTC communications, i.e. stop interrupt reception, and flush all queued
799  * buffers
800  */
801 void htc_stop(HTC_HANDLE HTCHandle)
802 {
803 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
804 	int i;
805 	HTC_ENDPOINT *pEndpoint;
806 #ifdef RX_SG_SUPPORT
807 	qdf_nbuf_t netbuf;
808 	qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
809 #endif
810 
811 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop\n"));
812 
813 	/* cleanup endpoints */
814 	for (i = 0; i < ENDPOINT_MAX; i++) {
815 		pEndpoint = &target->endpoint[i];
816 		htc_flush_rx_hold_queue(target, pEndpoint);
817 		htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
818 		if (pEndpoint->ul_is_polled) {
819 			qdf_timer_stop(&pEndpoint->ul_poll_timer);
820 			qdf_timer_free(&pEndpoint->ul_poll_timer);
821 		}
822 	}
823 
824 	/* Note: htc_flush_endpoint_tx for all endpoints should be called before
825 	 * hif_stop - otherwise htc_tx_completion_handler called from
826 	 * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer,
827 	 * might queue the packet again to HIF Layer - which could cause tx
828 	 * buffer leak
829 	 */
830 
831 	hif_stop(target->hif_dev);
832 
833 #ifdef RX_SG_SUPPORT
834 	LOCK_HTC_RX(target);
835 	while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
836 		qdf_nbuf_free(netbuf);
837 	RESET_RX_SG_CONFIG(target);
838 	UNLOCK_HTC_RX(target);
839 #endif
840 
841 	reset_endpoint_states(target);
842 
843 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop\n"));
844 }
845 
846 void htc_dump_credit_states(HTC_HANDLE HTCHandle)
847 {
848 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
849 	HTC_ENDPOINT *pEndpoint;
850 	int i;
851 
852 	for (i = 0; i < ENDPOINT_MAX; i++) {
853 		pEndpoint = &target->endpoint[i];
854 		if (0 == pEndpoint->service_id)
855 			continue;
856 
857 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
858 			("--- EP : %d  service_id: 0x%X    --------------\n",
859 				 pEndpoint->Id, pEndpoint->service_id));
860 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
861 				(" TxCredits          : %d\n",
862 				 pEndpoint->TxCredits));
863 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
864 				(" TxCreditSize       : %d\n",
865 				 pEndpoint->TxCreditSize));
866 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
867 				(" TxCreditsPerMaxMsg : %d\n",
868 				 pEndpoint->TxCreditsPerMaxMsg));
869 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
870 				(" TxQueueDepth       : %d\n",
871 				 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
872 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
873 				("----------------------------------------\n"));
874 	}
875 }
876 
877 bool htc_get_endpoint_statistics(HTC_HANDLE HTCHandle,
878 				   HTC_ENDPOINT_ID Endpoint,
879 				   enum htc_endpoint_stat_action Action,
880 				   struct htc_endpoint_stats *pStats)
881 {
882 #ifdef HTC_EP_STAT_PROFILING
883 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
884 	bool clearStats = false;
885 	bool sample = false;
886 
887 	switch (Action) {
888 	case HTC_EP_STAT_SAMPLE:
889 		sample = true;
890 		break;
891 	case HTC_EP_STAT_SAMPLE_AND_CLEAR:
892 		sample = true;
893 		clearStats = true;
894 		break;
895 	case HTC_EP_STAT_CLEAR:
896 		clearStats = true;
897 		break;
898 	default:
899 		break;
900 	}
901 
902 	A_ASSERT(Endpoint < ENDPOINT_MAX);
903 
904 	/* lock out TX and RX while we sample and/or clear */
905 	LOCK_HTC_TX(target);
906 	LOCK_HTC_RX(target);
907 
908 	if (sample) {
909 		A_ASSERT(pStats != NULL);
910 		/* return the stats to the caller */
911 		qdf_mem_copy(pStats, &target->endpoint[Endpoint].endpoint_stats,
912 			 sizeof(struct htc_endpoint_stats));
913 	}
914 
915 	if (clearStats) {
916 		/* reset stats */
917 		qdf_mem_zero(&target->endpoint[Endpoint].endpoint_stats,
918 			  sizeof(struct htc_endpoint_stats));
919 	}
920 
921 	UNLOCK_HTC_RX(target);
922 	UNLOCK_HTC_TX(target);
923 
924 	return true;
925 #else
926 	return false;
927 #endif
928 }
929 
930 void *htc_get_targetdef(HTC_HANDLE htc_handle)
931 {
932 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
933 
934 	return hif_get_targetdef(target->hif_dev);
935 }
936 
937 #ifdef IPA_OFFLOAD
938 /**
939  * htc_ipa_get_ce_resource() - get uc resource on lower layer
940  * @htc_handle: htc context
941  * @ce_sr_base_paddr: copyengine source ring base physical address
942  * @ce_sr_ring_size: copyengine source ring size
943  * @ce_reg_paddr: copyengine register physical address
944  *
945  * Return: None
946  */
947 void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle,
948 			     qdf_dma_addr_t *ce_sr_base_paddr,
949 			     uint32_t *ce_sr_ring_size,
950 			     qdf_dma_addr_t *ce_reg_paddr)
951 {
952 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
953 
954 	if (target->hif_dev != NULL) {
955 		hif_ipa_get_ce_resource(target->hif_dev,
956 					ce_sr_base_paddr,
957 					ce_sr_ring_size, ce_reg_paddr);
958 	}
959 }
960 #endif /* IPA_OFFLOAD */
961 
962 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
963 
964 void htc_dump_bundle_stats(HTC_HANDLE HTCHandle)
965 {
966 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
967 	int total, i;
968 
969 	total = 0;
970 	for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++)
971 		total += target->rx_bundle_stats[i];
972 
973 	if (total) {
974 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("RX Bundle stats:\n"));
975 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total RX packets: %d\n",
976 						total));
977 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (
978 				"Number of bundle: Number of packets\n"));
979 		for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++)
980 			AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
981 					("%10d:%10d(%2d%s)\n", (i+1),
982 					 target->rx_bundle_stats[i],
983 					 ((target->rx_bundle_stats[i]*100)/
984 					  total), "%"));
985 	}
986 
987 
988 	total = 0;
989 	for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++)
990 		total += target->tx_bundle_stats[i];
991 
992 	if (total) {
993 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("TX Bundle stats:\n"));
994 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total TX packets: %d\n",
995 						total));
996 		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
997 				("Number of bundle: Number of packets\n"));
998 		for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++)
999 			AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
1000 					("%10d:%10d(%2d%s)\n", (i+1),
1001 					 target->tx_bundle_stats[i],
1002 					 ((target->tx_bundle_stats[i]*100)/
1003 					  total), "%"));
1004 	}
1005 }
1006 
1007 void htc_clear_bundle_stats(HTC_HANDLE HTCHandle)
1008 {
1009 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1010 
1011 	qdf_mem_zero(&target->rx_bundle_stats, sizeof(target->rx_bundle_stats));
1012 	qdf_mem_zero(&target->tx_bundle_stats, sizeof(target->tx_bundle_stats));
1013 }
1014 #endif
1015 
1016 /**
1017  * htc_vote_link_down - API to vote for link down
1018  * @htc_handle: HTC handle
1019  *
1020  * API for upper layers to call HIF to vote for link down
1021  *
1022  * Return: void
1023  */
1024 void htc_vote_link_down(HTC_HANDLE htc_handle)
1025 {
1026 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1027 
1028 	if (!target->hif_dev)
1029 		return;
1030 
1031 	hif_vote_link_down(target->hif_dev);
1032 }
1033 
1034 /**
1035  * htc_vote_link_up - API to vote for link up
1036  * @htc_handle: HTC Handle
1037  *
1038  * API for upper layers to call HIF to vote for link up
1039  *
1040  * Return: void
1041  */
1042 void htc_vote_link_up(HTC_HANDLE htc_handle)
1043 {
1044 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1045 
1046 	if (!target->hif_dev)
1047 		return;
1048 
1049 	hif_vote_link_up(target->hif_dev);
1050 }
1051 
1052 /**
1053  * htc_can_suspend_link - API to query HIF for link status
1054  * @htc_handle: HTC Handle
1055  *
1056  * API for upper layers to call HIF to query if the link can suspend
1057  *
1058  * Return: void
1059  */
1060 bool htc_can_suspend_link(HTC_HANDLE htc_handle)
1061 {
1062 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1063 
1064 	if (!target->hif_dev)
1065 		return false;
1066 
1067 	return hif_can_suspend_link(target->hif_dev);
1068 }
1069 
1070 #ifdef FEATURE_RUNTIME_PM
1071 int htc_pm_runtime_get(HTC_HANDLE htc_handle)
1072 {
1073 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1074 
1075 	return hif_pm_runtime_get(target->hif_dev);
1076 }
1077 
1078 int htc_pm_runtime_put(HTC_HANDLE htc_handle)
1079 {
1080 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1081 
1082 	return hif_pm_runtime_put(target->hif_dev);
1083 }
1084 #endif
1085 
1086 /**
1087  * htc_set_wmi_endpoint_count: Set number of WMI endpoint
1088  * @htc_handle: HTC handle
1089  * @wmi_ep_count: WMI enpoint count
1090  *
1091  * return: None
1092  */
1093 void htc_set_wmi_endpoint_count(HTC_HANDLE htc_handle, uint8_t wmi_ep_count)
1094 {
1095 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1096 
1097 	target->wmi_ep_count = wmi_ep_count;
1098 }
1099 
1100 /**
1101  * htc_get_wmi_endpoint_count: Get number of WMI endpoint
1102  * @htc_handle: HTC handle
1103  *
1104  * return: WMI enpoint count
1105  */
1106 uint8_t htc_get_wmi_endpoint_count(HTC_HANDLE htc_handle)
1107 {
1108 	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1109 
1110 	return target->wmi_ep_count;
1111 }
1112