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