blob: 5b13c6ef11681df0efdff6922d3e334045712f65 [file] [log] [blame]
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001/*
Rajeev Kumar885f2752018-01-18 14:55:17 -08002 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08003 *
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08004 * 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
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080019#include "htc_debug.h"
20#include "htc_internal.h"
Rachit Kankane1bc11492018-01-24 18:48:17 +053021#include "htc_credit_history.h"
Yue Mab16cf302016-03-08 18:30:25 -080022#include <hif.h>
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053023#include <qdf_nbuf.h> /* qdf_nbuf_t */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053024#include <qdf_types.h> /* qdf_print */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080025
Poddar, Siddarthf1763402016-11-21 15:55:27 +053026#define MAX_HTC_RX_BUNDLE 2
27
Srinivas Girigowda8a0b6652016-10-19 16:01:31 -070028#if defined(WLAN_DEBUG) || defined(DEBUG)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080029static ATH_DEBUG_MASK_DESCRIPTION g_htc_debug_description[] = {
30 {ATH_DEBUG_SEND, "Send"},
31 {ATH_DEBUG_RECV, "Recv"},
32 {ATH_DEBUG_SYNC, "Sync"},
33 {ATH_DEBUG_DUMP, "Dump Data (RX or TX)"},
34 {ATH_DEBUG_SETUP, "Setup"},
35};
36
37ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc,
38 "htc",
39 "Host Target Communications",
40 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO |
41 ATH_DEBUG_SETUP,
42 ATH_DEBUG_DESCRIPTION_COUNT
43 (g_htc_debug_description),
44 g_htc_debug_description);
45
46#endif
47
Pratik Gandhi78461502018-02-05 17:22:41 +053048#if (defined(CONFIG_MCL) || (QCA_WIFI_QCA8074))
49static const uint32_t svc_id[] = {WMI_CONTROL_SVC, WMI_CONTROL_SVC_WMAC1,
50 WMI_CONTROL_SVC_WMAC2};
51#else
52static const uint32_t svc_id[] = {WMI_CONTROL_SVC};
53#endif
54
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080055extern unsigned int htc_credit_flow;
56
57static void reset_endpoint_states(HTC_TARGET *target);
58
59static void destroy_htc_tx_ctrl_packet(HTC_PACKET *pPacket)
60{
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053061 qdf_nbuf_t netbuf;
Manikandan Mohane3e209e2017-04-13 20:19:26 -070062
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053063 netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Jeff Johnsona79b1112017-09-18 10:12:02 -070064 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("free ctrl netbuf :0x%pK\n", netbuf));
Manikandan Mohane3e209e2017-04-13 20:19:26 -070065 if (netbuf != NULL)
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053066 qdf_nbuf_free(netbuf);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053067 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080068}
69
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053070static HTC_PACKET *build_htc_tx_ctrl_packet(qdf_device_t osdev)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080071{
72 HTC_PACKET *pPacket = NULL;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053073 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080074
75 do {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053076 pPacket = (HTC_PACKET *) qdf_mem_malloc(sizeof(HTC_PACKET));
Manikandan Mohane3e209e2017-04-13 20:19:26 -070077 if (pPacket == NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080078 break;
Yue Mab16cf302016-03-08 18:30:25 -080079 netbuf = qdf_nbuf_alloc(osdev, HTC_CONTROL_BUFFER_SIZE,
80 20, 4, true);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080081 if (NULL == netbuf) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053082 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080083 pPacket = NULL;
Aditya Sathish648ce112018-07-02 16:41:39 +053084 qdf_print("%s: nbuf alloc failed", __func__);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080085 break;
86 }
87 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
Jeff Johnsona79b1112017-09-18 10:12:02 -070088 ("alloc ctrl netbuf :0x%pK\n", netbuf));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080089 SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
90 } while (false);
91
92 return pPacket;
93}
94
95void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
96{
97
98#ifdef TODO_FIXME
99 LOCK_HTC(target);
100 HTC_PACKET_ENQUEUE(&target->ControlBufferTXFreeList, pPacket);
101 UNLOCK_HTC(target);
102 /* TODO_FIXME netbufs cannot be RESET! */
103#else
104 destroy_htc_tx_ctrl_packet(pPacket);
105#endif
106
107}
108
109HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target)
110{
111#ifdef TODO_FIXME
112 HTC_PACKET *pPacket;
113
114 LOCK_HTC(target);
115 pPacket = htc_packet_dequeue(&target->ControlBufferTXFreeList);
116 UNLOCK_HTC(target);
117
118 return pPacket;
119#else
120 return build_htc_tx_ctrl_packet(target->osdev);
121#endif
122}
123
124/* Set the target failure handling callback */
125void htc_set_target_failure_callback(HTC_HANDLE HTCHandle,
126 HTC_TARGET_FAILURE Callback)
127{
128 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700129
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800130 target->HTCInitInfo.TargetFailure = Callback;
131}
132
133void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start)
134{
135 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700136
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800137 hif_dump(target->hif_dev, CmdId, start);
138}
139
140/* cleanup the HTC instance */
141static void htc_cleanup(HTC_TARGET *target)
142{
143 HTC_PACKET *pPacket;
Govind Singhc505cdc2017-05-16 12:15:51 +0530144 int i;
145 HTC_ENDPOINT *endpoint;
wadesongfbf643a2017-10-14 09:11:34 +0800146 HTC_PACKET_QUEUE *pkt_queue;
147 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800148
149 if (target->hif_dev != NULL) {
150 hif_detach_htc(target->hif_dev);
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530151 hif_mask_interrupt_call(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800152 target->hif_dev = NULL;
153 }
154
155 while (true) {
156 pPacket = allocate_htc_packet_container(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700157 if (pPacket == NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800158 break;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530159 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800160 }
161
wadesongfbf643a2017-10-14 09:11:34 +0800162 LOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800163 pPacket = target->pBundleFreeList;
wadesongfbf643a2017-10-14 09:11:34 +0800164 target->pBundleFreeList = NULL;
165 UNLOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800166 while (pPacket) {
167 HTC_PACKET *pPacketTmp = (HTC_PACKET *) pPacket->ListLink.pNext;
wadesongfbf643a2017-10-14 09:11:34 +0800168 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
169 if (netbuf)
170 qdf_nbuf_free(netbuf);
171 pkt_queue = pPacket->pContext;
172 if (pkt_queue)
173 qdf_mem_free(pkt_queue);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530174 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800175 pPacket = pPacketTmp;
176 }
wadesongfbf643a2017-10-14 09:11:34 +0800177
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800178#ifdef TODO_FIXME
179 while (true) {
180 pPacket = htc_alloc_control_tx_packet(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700181 if (pPacket == NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800182 break;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530183 netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700184 if (netbuf != NULL)
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530185 qdf_nbuf_free(netbuf);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530186 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800187 }
188#endif
189
Zhang Qianedaa3872018-07-04 20:02:53 +0800190 htc_flush_endpoint_txlookupQ(target, ENDPOINT_0, true);
Alok Kumar9bd81522018-05-30 13:07:13 +0530191
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530192 qdf_spinlock_destroy(&target->HTCLock);
193 qdf_spinlock_destroy(&target->HTCRxLock);
194 qdf_spinlock_destroy(&target->HTCTxLock);
195 qdf_spinlock_destroy(&target->HTCCreditLock);
Govind Singhc505cdc2017-05-16 12:15:51 +0530196 for (i = 0; i < ENDPOINT_MAX; i++) {
197 endpoint = &target->endpoint[i];
198 qdf_spinlock_destroy(&endpoint->lookup_queue_lock);
199 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800200
201 /* free our instance */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530202 qdf_mem_free(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800203}
204
Yue Maec9e71c2016-02-26 18:52:20 -0800205#ifdef FEATURE_RUNTIME_PM
206/**
207 * htc_runtime_pm_init(): runtime pm related intialization
208 *
209 * need to initialize a work item.
210 */
211static void htc_runtime_pm_init(HTC_TARGET *target)
212{
213 qdf_create_work(0, &target->queue_kicker, htc_kick_queues, target);
214}
215
216/**
217 * htc_runtime_suspend() - runtime suspend HTC
218 *
219 * @htc_ctx: HTC context pointer
220 *
221 * This is a dummy function for symmetry.
222 *
223 * Return: 0 for success
224 */
225int htc_runtime_suspend(HTC_HANDLE htc_ctx)
226{
227 return 0;
228}
229
230/**
231 * htc_runtime_resume(): resume htc
232 *
233 * The htc message queue needs to be kicked off after
234 * a runtime resume. Otherwise messages would get stuck.
235 *
236 * @htc_ctx: HTC context pointer
237 *
238 * Return: 0 for success;
239 */
240int htc_runtime_resume(HTC_HANDLE htc_ctx)
241{
242 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_ctx);
243
244 if (target == NULL)
245 return 0;
246
247 qdf_sched_work(0, &target->queue_kicker);
248 return 0;
249}
250#else
251static inline void htc_runtime_pm_init(HTC_TARGET *target) { }
252#endif
253
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800254/* registered target arrival callback from the HIF layer */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700255HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo,
256 qdf_device_t osdev, uint32_t con_mode)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800257{
258 struct hif_msg_callbacks htcCallbacks;
259 HTC_ENDPOINT *pEndpoint = NULL;
260 HTC_TARGET *target = NULL;
261 int i;
262
263 if (ol_sc == NULL) {
264 HTC_ERROR("%s: ol_sc = NULL", __func__);
265 return NULL;
266 }
Jeff Johnsona79b1112017-09-18 10:12:02 -0700267 HTC_TRACE("+htc_create .. HIF :%pK", ol_sc);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800268
269 A_REGISTER_MODULE_DEBUG_INFO(htc);
270
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530271 target = (HTC_TARGET *) qdf_mem_malloc(sizeof(HTC_TARGET));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800272 if (target == NULL) {
273 HTC_ERROR("%s: Unable to allocate memory", __func__);
274 return NULL;
275 }
276
Houston Hoffman47e387b2015-10-20 17:04:42 -0700277 htc_runtime_pm_init(target);
Rachit Kankane1bc11492018-01-24 18:48:17 +0530278 htc_credit_history_init();
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530279 qdf_spinlock_create(&target->HTCLock);
280 qdf_spinlock_create(&target->HTCRxLock);
281 qdf_spinlock_create(&target->HTCTxLock);
Govind Singhc505cdc2017-05-16 12:15:51 +0530282 for (i = 0; i < ENDPOINT_MAX; i++) {
283 pEndpoint = &target->endpoint[i];
284 qdf_spinlock_create(&pEndpoint->lookup_queue_lock);
285 }
gbianb417db22016-09-30 17:01:07 +0800286 target->is_nodrop_pkt = false;
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530287 target->wmi_ep_count = 1;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800288
289 do {
Yue Mab16cf302016-03-08 18:30:25 -0800290 qdf_mem_copy(&target->HTCInitInfo, pInfo,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700291 sizeof(struct htc_init_info));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800292 target->host_handle = pInfo->pContext;
293 target->osdev = osdev;
Yue Maec9e71c2016-02-26 18:52:20 -0800294 target->con_mode = con_mode;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800295
296 reset_endpoint_states(target);
297
298 INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList);
299
300 for (i = 0; i < HTC_PACKET_CONTAINER_ALLOCATION; i++) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700301 HTC_PACKET *pPacket = (HTC_PACKET *)
302 qdf_mem_malloc(sizeof(HTC_PACKET));
303 if (pPacket != NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800304 free_htc_packet_container(target, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800305 }
306
307#ifdef TODO_FIXME
308 for (i = 0; i < NUM_CONTROL_TX_BUFFERS; i++) {
309 pPacket = build_htc_tx_ctrl_packet();
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700310 if (pPacket == NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800311 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800312 htc_free_control_tx_packet(target, pPacket);
313 }
314#endif
315
316 /* setup HIF layer callbacks */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530317 qdf_mem_zero(&htcCallbacks, sizeof(struct hif_msg_callbacks));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800318 htcCallbacks.Context = target;
319 htcCallbacks.rxCompletionHandler = htc_rx_completion_handler;
320 htcCallbacks.txCompletionHandler = htc_tx_completion_handler;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700321 htcCallbacks.txResourceAvailHandler =
322 htc_tx_resource_avail_handler;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800323 htcCallbacks.fwEventHandler = htc_fw_event_handler;
324 target->hif_dev = ol_sc;
325
326 /* Get HIF default pipe for HTC message exchange */
Houston Hoffman29573d92015-10-20 17:49:44 -0700327 pEndpoint = &target->endpoint[ENDPOINT_0];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800328
329 hif_post_init(target->hif_dev, target, &htcCallbacks);
330 hif_get_default_pipe(target->hif_dev, &pEndpoint->UL_PipeID,
331 &pEndpoint->DL_PipeID);
Dustin Brownbbba9172017-10-04 17:03:56 -0700332 hif_set_initial_wakeup_cb(target->hif_dev,
333 pInfo->target_initial_wakeup_cb,
334 pInfo->target_psoc);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800335
336 } while (false);
337
338 htc_recv_init(target);
339
Jeff Johnsona79b1112017-09-18 10:12:02 -0700340 HTC_TRACE("-htc_create: (0x%pK)", target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800341
342 return (HTC_HANDLE) target;
343}
344
345void htc_destroy(HTC_HANDLE HTCHandle)
346{
347 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700348
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800349 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700350 ("+htc_destroy .. Destroying :0x%pK\n", target));
Karthick Sc3a7a0c2015-10-14 17:56:55 +0530351 hif_stop(htc_get_hif_device(HTCHandle));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800352 if (target)
353 htc_cleanup(target);
354 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n"));
355}
356
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700357/* get the low level HIF device for the caller , the caller may wish to do low
358 * level HIF requests
359 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800360void *htc_get_hif_device(HTC_HANDLE HTCHandle)
361{
362 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700363
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800364 return target->hif_dev;
365}
366
Jeff Johnsonc66399a2016-10-07 13:01:33 -0700367static void htc_control_tx_complete(void *Context, HTC_PACKET *pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800368{
369 HTC_TARGET *target = (HTC_TARGET *) Context;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700370
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800371 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700372 ("+-htc_control_tx_complete 0x%pK (l:%d)\n", pPacket,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800373 pPacket->ActualLength));
374 htc_free_control_tx_packet(target, pPacket);
375}
376
377/* TODO, this is just a temporary max packet size */
378#define MAX_MESSAGE_SIZE 1536
379
380/**
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530381 * htc_setup_epping_credit_allocation() - allocate credits/HTC buffers to WMI
382 * @scn: pointer to hif_opaque_softc
383 * @pEntry: pointer to tx credit allocation entry
384 * @credits: number of credits
385 *
386 * Return: None
387 */
388static void
389htc_setup_epping_credit_allocation(struct hif_opaque_softc *scn,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700390 struct htc_service_tx_credit_allocation *pEntry,
391 int credits)
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530392{
393 switch (hif_get_bus_type(scn)) {
394 case QDF_BUS_TYPE_PCI:
395 pEntry++;
396 pEntry->service_id = WMI_DATA_BE_SVC;
397 pEntry->CreditAllocation = (credits >> 1);
398
399 pEntry++;
400 pEntry->service_id = WMI_DATA_BK_SVC;
401 pEntry->CreditAllocation = (credits >> 1);
402 break;
403 case QDF_BUS_TYPE_SDIO:
404 pEntry++;
405 pEntry->service_id = WMI_DATA_BE_SVC;
406 pEntry->CreditAllocation = credits;
407 break;
408 default:
409 break;
410 }
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530411}
412
413/**
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800414 * htc_setup_target_buffer_assignments() - setup target buffer assignments
415 * @target: HTC Target Pointer
416 *
417 * Return: A_STATUS
418 */
Jeff Johnsonc66399a2016-10-07 13:01:33 -0700419static
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800420A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target)
421{
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700422 struct htc_service_tx_credit_allocation *pEntry;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800423 A_STATUS status;
424 int credits;
425 int creditsPerMaxMsg;
426
427 creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700428 if (MAX_MESSAGE_SIZE % target->TargetCreditSize)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800429 creditsPerMaxMsg++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800430
431 /* TODO, this should be configured by the caller! */
432
433 credits = target->TotalTransmitCredits;
434 pEntry = &target->ServiceTxAllocTable[0];
435
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530436 status = A_OK;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800437 /*
438 * Allocate all credists/HTC buffers to WMI.
439 * no buffers are used/required for data. data always
440 * remains on host.
441 */
Yue Maec9e71c2016-02-26 18:52:20 -0800442 if (HTC_IS_EPPING_ENABLED(target->con_mode)) {
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530443 pEntry++;
444 pEntry->service_id = WMI_CONTROL_SVC;
445 pEntry->CreditAllocation = credits;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800446 /* endpoint ping is a testing tool directly on top of HTC in
447 * both target and host sides.
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700448 * In target side, the endppint ping fw has no wlan stack and
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800449 * FW mboxping app directly sits on HTC and it simply drops
450 * or loops back TX packets. For rx perf, FW mboxping app
451 * generates packets and passes packets to HTC to send to host.
Jeff Johnson4b253f02018-05-12 11:34:43 -0700452 * There is no WMI message exchanges between host and target
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800453 * in endpoint ping case.
454 * In host side, the endpoint ping driver is a Ethernet driver
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530455 * and it directly sits on HTC. Only HIF, HTC, QDF, ADF are
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800456 * used by the endpoint ping driver. There is no wifi stack
457 * at all in host side also. For tx perf use case,
458 * the user space mboxping app sends the raw packets to endpoint
459 * ping driver and it directly forwards to HTC for transmission
460 * to stress the bus. For the rx perf, HTC passes the received
461 * packets to endpoint ping driver and it is passed to the user
462 * space through the Ethernet interface.
463 * For credit allocation, in SDIO bus case, only BE service is
464 * used for tx/rx perf testing so that all credits are given
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700465 * to BE service. In PCIe and USB bus case, endpoint ping uses
466 * both BE and BK services to stress the bus so that the total
467 * credits are equally distributed to BE and BK services.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800468 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800469
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530470 htc_setup_epping_credit_allocation(target->hif_dev,
471 pEntry, credits);
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530472 } else {
473 int i;
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530474 uint32_t max_wmi_svc = (sizeof(svc_id) / sizeof(uint32_t));
475
476 if ((target->wmi_ep_count == 0) ||
477 (target->wmi_ep_count > max_wmi_svc))
478 return A_ERROR;
479
480 /*
481 * Divide credit among number of endpoints for WMI
482 */
483 credits = credits / target->wmi_ep_count;
484 for (i = 0; i < target->wmi_ep_count; i++) {
485 status = A_OK;
486 pEntry++;
487 pEntry->service_id = svc_id[i];
488 pEntry->CreditAllocation = credits;
489 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800490 }
491
492 if (A_SUCCESS(status)) {
493 int i;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700494
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800495 for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700496 if (target->ServiceTxAllocTable[i].service_id != 0) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800497 AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
Rajeev Kumar885f2752018-01-18 14:55:17 -0800498 ("SVS Index : %d TX : 0x%2.2X : alloc:%d",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800499 i,
500 target->ServiceTxAllocTable[i].
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700501 service_id,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800502 target->ServiceTxAllocTable[i].
503 CreditAllocation));
504 }
505 }
506 }
507
508 return status;
509}
510
Yue Mab16cf302016-03-08 18:30:25 -0800511uint8_t htc_get_credit_allocation(HTC_TARGET *target, uint16_t service_id)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800512{
Yue Mab16cf302016-03-08 18:30:25 -0800513 uint8_t allocation = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800514 int i;
515
516 for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700517 if (target->ServiceTxAllocTable[i].service_id == service_id) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800518 allocation =
519 target->ServiceTxAllocTable[i].CreditAllocation;
520 }
521 }
522
523 if (0 == allocation) {
Srinivas Girigowda38ee3052017-03-10 16:00:40 -0800524 AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700525 ("HTC Service TX : 0x%2.2X : allocation is zero!\n",
526 service_id));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800527 }
528
529 return allocation;
530}
531
Rakesh Pillai13146452017-06-22 12:52:31 +0530532QDF_STATUS htc_wait_target(HTC_HANDLE HTCHandle)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800533{
Rakesh Pillai13146452017-06-22 12:52:31 +0530534 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800535 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
536 HTC_READY_EX_MSG *pReadyMsg;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700537 struct htc_service_connect_req connect;
538 struct htc_service_connect_resp resp;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800539 HTC_READY_MSG *rdy_msg;
Yue Mab16cf302016-03-08 18:30:25 -0800540 uint16_t htc_rdy_msg_id;
Poddar, Siddarthf1763402016-11-21 15:55:27 +0530541 uint8_t i = 0;
542 HTC_PACKET *rx_bundle_packet, *temp_bundle_packet;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800543
544 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700545 ("htc_wait_target - Enter (target:0x%pK)\n", HTCHandle));
Srinivas Girigowda38ee3052017-03-10 16:00:40 -0800546 AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("+HWT\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800547
548 do {
549
550 status = hif_start(target->hif_dev);
Rakesh Pillai13146452017-06-22 12:52:31 +0530551 if (QDF_IS_STATUS_ERROR(status)) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700552 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
553 ("hif_start failed\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800554 break;
555 }
556
557 status = htc_wait_recv_ctrl_message(target);
558
Rakesh Pillai13146452017-06-22 12:52:31 +0530559 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800560 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800561
562 if (target->CtrlResponseLength < (sizeof(HTC_READY_EX_MSG))) {
563 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700564 ("Invalid HTC Ready Msg Len:%d!\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800565 target->CtrlResponseLength));
Rakesh Pillai13146452017-06-22 12:52:31 +0530566 status = QDF_STATUS_E_BADMSG;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800567 break;
568 }
569
570 pReadyMsg = (HTC_READY_EX_MSG *) target->CtrlResponseBuffer;
571
572 rdy_msg = &pReadyMsg->Version2_0_Info;
573 htc_rdy_msg_id =
574 HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, MESSAGEID);
575 if (htc_rdy_msg_id != HTC_MSG_READY_ID) {
576 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700577 ("Invalid HTC Ready Msg : 0x%X!\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800578 htc_rdy_msg_id));
Rakesh Pillai13146452017-06-22 12:52:31 +0530579 status = QDF_STATUS_E_BADMSG;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800580 break;
581 }
582
583 target->TotalTransmitCredits =
584 HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITCOUNT);
585 target->TargetCreditSize =
586 (int)HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITSIZE);
587 target->MaxMsgsPerHTCBundle =
Yue Mab16cf302016-03-08 18:30:25 -0800588 (uint8_t) pReadyMsg->MaxMsgsPerHTCBundle;
Chris Guo37cf36d2017-07-06 18:56:32 +0800589 UPDATE_ALT_CREDIT(target, pReadyMsg->AltDataCreditSize);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700590 /* for old fw this value is set to 0. But the minimum value
591 * should be 1, i.e., no bundling
592 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800593 if (target->MaxMsgsPerHTCBundle < 1)
594 target->MaxMsgsPerHTCBundle = 1;
595
596 AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
Rajeev Kumar885f2752018-01-18 14:55:17 -0800597 ("Target Ready! TX resource : %d size:%d, MaxMsgsPerHTCBundle = %d",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800598 target->TotalTransmitCredits,
599 target->TargetCreditSize,
600 target->MaxMsgsPerHTCBundle));
601
602 if ((0 == target->TotalTransmitCredits)
603 || (0 == target->TargetCreditSize)) {
Rakesh Pillai13146452017-06-22 12:52:31 +0530604 status = QDF_STATUS_E_ABORTED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800605 break;
606 }
Poddar, Siddarthf1763402016-11-21 15:55:27 +0530607
608 /* Allocate expected number of RX bundle buffer allocation */
609 if (HTC_RX_BUNDLE_ENABLED(target)) {
610 temp_bundle_packet = NULL;
611 for (i = 0; i < MAX_HTC_RX_BUNDLE; i++) {
612 rx_bundle_packet =
613 allocate_htc_bundle_packet(target);
614 if (rx_bundle_packet != NULL)
615 rx_bundle_packet->ListLink.pNext =
616 (DL_LIST *)temp_bundle_packet;
617 else
618 break;
619
620 temp_bundle_packet = rx_bundle_packet;
621 }
wadesongfbf643a2017-10-14 09:11:34 +0800622 LOCK_HTC_TX(target);
Poddar, Siddarthf1763402016-11-21 15:55:27 +0530623 target->pBundleFreeList = temp_bundle_packet;
wadesongfbf643a2017-10-14 09:11:34 +0800624 UNLOCK_HTC_TX(target);
Poddar, Siddarthf1763402016-11-21 15:55:27 +0530625 }
626
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800627 /* done processing */
628 target->CtrlResponseProcessing = false;
629
630 htc_setup_target_buffer_assignments(target);
631
632 /* setup our pseudo HTC control endpoint connection */
Yue Mab16cf302016-03-08 18:30:25 -0800633 qdf_mem_zero(&connect, sizeof(connect));
634 qdf_mem_zero(&resp, sizeof(resp));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800635 connect.EpCallbacks.pContext = target;
636 connect.EpCallbacks.EpTxComplete = htc_control_tx_complete;
637 connect.EpCallbacks.EpRecv = htc_control_rx_complete;
638 connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS;
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700639 connect.service_id = HTC_CTRL_RSVD_SVC;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800640
641 /* connect fake service */
642 status = htc_connect_service((HTC_HANDLE) target,
643 &connect, &resp);
644
645 } while (false);
646
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700647 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_wait_target - Exit (%d)\n",
648 status));
Srinivas Girigowda38ee3052017-03-10 16:00:40 -0800649 AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("-HWT\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800650 return status;
651}
652
653/* start HTC, this is called after all services are connected */
654static A_STATUS htc_config_target_hif_pipe(HTC_TARGET *target)
655{
656
657 return A_OK;
658}
659
660static void reset_endpoint_states(HTC_TARGET *target)
661{
662 HTC_ENDPOINT *pEndpoint;
663 int i;
664
665 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -0700666 pEndpoint = &target->endpoint[i];
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700667 pEndpoint->service_id = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800668 pEndpoint->MaxMsgLength = 0;
669 pEndpoint->MaxTxQueueDepth = 0;
670 pEndpoint->Id = i;
671 INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue);
672 INIT_HTC_PACKET_QUEUE(&pEndpoint->TxLookupQueue);
673 INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBufferHoldQueue);
674 pEndpoint->target = target;
Yue Mab16cf302016-03-08 18:30:25 -0800675 pEndpoint->TxCreditFlowEnabled = (bool)htc_credit_flow;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530676 qdf_atomic_init(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800677 }
678}
679
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700680/**
681 * htc_start() - Main HTC function to trigger HTC start
682 * @HTCHandle: pointer to HTC handle
683 *
Rakesh Pillai13146452017-06-22 12:52:31 +0530684 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700685 */
Rakesh Pillai13146452017-06-22 12:52:31 +0530686QDF_STATUS htc_start(HTC_HANDLE HTCHandle)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800687{
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530688 qdf_nbuf_t netbuf;
Rakesh Pillai13146452017-06-22 12:52:31 +0530689 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800690 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
691 HTC_SETUP_COMPLETE_EX_MSG *pSetupComp;
692 HTC_PACKET *pSendPacket;
693
694 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Enter\n"));
695
696 do {
697
698 htc_config_target_hif_pipe(target);
699
700 /* allocate a buffer to send */
701 pSendPacket = htc_alloc_control_tx_packet(target);
702 if (NULL == pSendPacket) {
703 AR_DEBUG_ASSERT(false);
Aditya Sathish648ce112018-07-02 16:41:39 +0530704 qdf_print("%s: allocControlTxPacket failed",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800705 __func__);
Rakesh Pillai13146452017-06-22 12:52:31 +0530706 status = QDF_STATUS_E_NOMEM;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800707 break;
708 }
709
710 netbuf =
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530711 (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800712 /* assemble setup complete message */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530713 qdf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800714 pSetupComp =
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530715 (HTC_SETUP_COMPLETE_EX_MSG *) qdf_nbuf_data(netbuf);
Yue Mab16cf302016-03-08 18:30:25 -0800716 qdf_mem_zero(pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800717
718 HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG,
719 MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID);
720
721 if (!htc_credit_flow) {
722 AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
Rajeev Kumar885f2752018-01-18 14:55:17 -0800723 ("HTC will not use TX credit flow control"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800724 pSetupComp->SetupFlags |=
725 HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW;
726 } else {
727 AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
Rajeev Kumar885f2752018-01-18 14:55:17 -0800728 ("HTC using TX credit flow control"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800729 }
730
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700731 if ((hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO) ||
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700732 (hif_get_bus_type(target->hif_dev) ==
733 QDF_BUS_TYPE_USB)) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700734 if (HTC_RX_BUNDLE_ENABLED(target))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800735 pSetupComp->SetupFlags |=
736 HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700737 hif_set_bundle_mode(target->hif_dev, true,
738 HTC_MAX_MSG_PER_BUNDLE_RX);
739 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800740
741 SET_HTC_PACKET_INFO_TX(pSendPacket,
742 NULL,
Yue Mab16cf302016-03-08 18:30:25 -0800743 (uint8_t *) pSetupComp,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800744 sizeof(HTC_SETUP_COMPLETE_EX_MSG),
745 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
746
747 status = htc_send_pkt((HTC_HANDLE) target, pSendPacket);
Rakesh Pillai13146452017-06-22 12:52:31 +0530748 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800749 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800750 } while (false);
751
752 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Exit\n"));
753 return status;
754}
755
756/*flush all queued buffers for surpriseremove case*/
757void htc_flush_surprise_remove(HTC_HANDLE HTCHandle)
758{
759 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
760 int i;
761 HTC_ENDPOINT *pEndpoint;
762#ifdef RX_SG_SUPPORT
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530763 qdf_nbuf_t netbuf;
764 qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800765#endif
766
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530767 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800768
769 /* cleanup endpoints */
770 for (i = 0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -0700771 pEndpoint = &target->endpoint[i];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800772 htc_flush_rx_hold_queue(target, pEndpoint);
773 htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
774 }
775
776 hif_flush_surprise_remove(target->hif_dev);
777
778#ifdef RX_SG_SUPPORT
779 LOCK_HTC_RX(target);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530780 while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
781 qdf_nbuf_free(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800782 RESET_RX_SG_CONFIG(target);
783 UNLOCK_HTC_RX(target);
784#endif
785
786 reset_endpoint_states(target);
787
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700788 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800789}
790
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700791/* stop HTC communications, i.e. stop interrupt reception, and flush all queued
792 * buffers
793 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800794void htc_stop(HTC_HANDLE HTCHandle)
795{
796 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
797 int i;
798 HTC_ENDPOINT *pEndpoint;
799#ifdef RX_SG_SUPPORT
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530800 qdf_nbuf_t netbuf;
801 qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800802#endif
803
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530804 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800805
806 /* cleanup endpoints */
807 for (i = 0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -0700808 pEndpoint = &target->endpoint[i];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800809 htc_flush_rx_hold_queue(target, pEndpoint);
810 htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
811 if (pEndpoint->ul_is_polled) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530812 qdf_timer_stop(&pEndpoint->ul_poll_timer);
813 qdf_timer_free(&pEndpoint->ul_poll_timer);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800814 }
815 }
816
817 /* Note: htc_flush_endpoint_tx for all endpoints should be called before
818 * hif_stop - otherwise htc_tx_completion_handler called from
819 * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer,
820 * might queue the packet again to HIF Layer - which could cause tx
821 * buffer leak
822 */
823
824 hif_stop(target->hif_dev);
825
826#ifdef RX_SG_SUPPORT
827 LOCK_HTC_RX(target);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530828 while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
829 qdf_nbuf_free(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800830 RESET_RX_SG_CONFIG(target);
831 UNLOCK_HTC_RX(target);
832#endif
833
Zhang Qianedaa3872018-07-04 20:02:53 +0800834 /**
835 * In SSR case, HTC tx completion callback for wmi will be blocked
836 * by TARGET_STATUS_RESET and HTC packets will be left unfreed on
837 * lookup queue.
838 */
839 for (i = 0; i < ENDPOINT_MAX; i++) {
840 pEndpoint = &target->endpoint[i];
841 if (pEndpoint->service_id == WMI_CONTROL_SVC)
842 htc_flush_endpoint_txlookupQ(target, i, false);
843 }
844
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800845 reset_endpoint_states(target);
846
Houston Hoffman47e387b2015-10-20 17:04:42 -0700847 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop\n"));
848}
849
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800850void htc_dump_credit_states(HTC_HANDLE HTCHandle)
851{
852 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
853 HTC_ENDPOINT *pEndpoint;
854 int i;
855
856 for (i = 0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -0700857 pEndpoint = &target->endpoint[i];
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700858 if (0 == pEndpoint->service_id)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800859 continue;
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700860
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800861 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700862 ("--- EP : %d service_id: 0x%X --------------\n",
863 pEndpoint->Id, pEndpoint->service_id));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800864 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700865 (" TxCredits : %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800866 pEndpoint->TxCredits));
867 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700868 (" TxCreditSize : %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800869 pEndpoint->TxCreditSize));
870 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700871 (" TxCreditsPerMaxMsg : %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800872 pEndpoint->TxCreditsPerMaxMsg));
873 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700874 (" TxQueueDepth : %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800875 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
876 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700877 ("----------------------------------------\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800878 }
879}
880
Yue Mab16cf302016-03-08 18:30:25 -0800881bool htc_get_endpoint_statistics(HTC_HANDLE HTCHandle,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800882 HTC_ENDPOINT_ID Endpoint,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700883 enum htc_endpoint_stat_action Action,
884 struct htc_endpoint_stats *pStats)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800885{
886#ifdef HTC_EP_STAT_PROFILING
887 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Yue Mab16cf302016-03-08 18:30:25 -0800888 bool clearStats = false;
889 bool sample = false;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800890
891 switch (Action) {
892 case HTC_EP_STAT_SAMPLE:
893 sample = true;
894 break;
895 case HTC_EP_STAT_SAMPLE_AND_CLEAR:
896 sample = true;
897 clearStats = true;
898 break;
899 case HTC_EP_STAT_CLEAR:
900 clearStats = true;
901 break;
902 default:
903 break;
904 }
905
906 A_ASSERT(Endpoint < ENDPOINT_MAX);
907
908 /* lock out TX and RX while we sample and/or clear */
909 LOCK_HTC_TX(target);
910 LOCK_HTC_RX(target);
911
912 if (sample) {
913 A_ASSERT(pStats != NULL);
914 /* return the stats to the caller */
Yue Mab16cf302016-03-08 18:30:25 -0800915 qdf_mem_copy(pStats, &target->endpoint[Endpoint].endpoint_stats,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700916 sizeof(struct htc_endpoint_stats));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800917 }
918
919 if (clearStats) {
920 /* reset stats */
Yue Mab16cf302016-03-08 18:30:25 -0800921 qdf_mem_zero(&target->endpoint[Endpoint].endpoint_stats,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700922 sizeof(struct htc_endpoint_stats));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800923 }
924
925 UNLOCK_HTC_RX(target);
926 UNLOCK_HTC_TX(target);
927
928 return true;
929#else
930 return false;
931#endif
932}
933
934void *htc_get_targetdef(HTC_HANDLE htc_handle)
935{
936 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
937
938 return hif_get_targetdef(target->hif_dev);
939}
940
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800941#ifdef IPA_OFFLOAD
Leo Changd85f78d2015-11-13 10:55:34 -0800942/**
943 * htc_ipa_get_ce_resource() - get uc resource on lower layer
944 * @htc_handle: htc context
945 * @ce_sr_base_paddr: copyengine source ring base physical address
946 * @ce_sr_ring_size: copyengine source ring size
947 * @ce_reg_paddr: copyengine register physical address
948 *
949 * Return: None
950 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800951void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle,
Sravan Kumar Kairam58e0adf2018-02-27 18:37:40 +0530952 qdf_shared_mem_t **ce_sr,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800953 uint32_t *ce_sr_ring_size,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530954 qdf_dma_addr_t *ce_reg_paddr)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800955{
956 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
957
Sravan Kumar Kairam58e0adf2018-02-27 18:37:40 +0530958 if (target->hif_dev)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800959 hif_ipa_get_ce_resource(target->hif_dev,
Sravan Kumar Kairam58e0adf2018-02-27 18:37:40 +0530960 ce_sr, ce_sr_ring_size, ce_reg_paddr);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800961}
962#endif /* IPA_OFFLOAD */
Komal Seelamf8600682016-02-02 18:17:13 +0530963
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530964#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
965
966void htc_dump_bundle_stats(HTC_HANDLE HTCHandle)
967{
968 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
969 int total, i;
970
971 total = 0;
972 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++)
973 total += target->rx_bundle_stats[i];
974
975 if (total) {
976 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("RX Bundle stats:\n"));
977 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total RX packets: %d\n",
978 total));
979 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (
980 "Number of bundle: Number of packets\n"));
981 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++)
982 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
983 ("%10d:%10d(%2d%s)\n", (i+1),
984 target->rx_bundle_stats[i],
985 ((target->rx_bundle_stats[i]*100)/
986 total), "%"));
987 }
988
989
990 total = 0;
991 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++)
992 total += target->tx_bundle_stats[i];
993
994 if (total) {
995 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("TX Bundle stats:\n"));
996 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total TX packets: %d\n",
997 total));
998 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
999 ("Number of bundle: Number of packets\n"));
1000 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++)
1001 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
1002 ("%10d:%10d(%2d%s)\n", (i+1),
1003 target->tx_bundle_stats[i],
1004 ((target->tx_bundle_stats[i]*100)/
1005 total), "%"));
1006 }
1007}
1008
1009void htc_clear_bundle_stats(HTC_HANDLE HTCHandle)
1010{
1011 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1012
1013 qdf_mem_zero(&target->rx_bundle_stats, sizeof(target->rx_bundle_stats));
1014 qdf_mem_zero(&target->tx_bundle_stats, sizeof(target->tx_bundle_stats));
1015}
1016#endif
1017
Komal Seelamf8600682016-02-02 18:17:13 +05301018/**
1019 * htc_vote_link_down - API to vote for link down
1020 * @htc_handle: HTC handle
1021 *
1022 * API for upper layers to call HIF to vote for link down
1023 *
1024 * Return: void
1025 */
1026void htc_vote_link_down(HTC_HANDLE htc_handle)
1027{
1028 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1029
1030 if (!target->hif_dev)
1031 return;
1032
1033 hif_vote_link_down(target->hif_dev);
1034}
1035
1036/**
1037 * htc_vote_link_up - API to vote for link up
1038 * @htc_handle: HTC Handle
1039 *
1040 * API for upper layers to call HIF to vote for link up
1041 *
1042 * Return: void
1043 */
1044void htc_vote_link_up(HTC_HANDLE htc_handle)
1045{
1046 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1047
1048 if (!target->hif_dev)
1049 return;
1050
1051 hif_vote_link_up(target->hif_dev);
1052}
1053
1054/**
1055 * htc_can_suspend_link - API to query HIF for link status
1056 * @htc_handle: HTC Handle
1057 *
1058 * API for upper layers to call HIF to query if the link can suspend
1059 *
1060 * Return: void
1061 */
1062bool htc_can_suspend_link(HTC_HANDLE htc_handle)
1063{
1064 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1065
1066 if (!target->hif_dev)
1067 return false;
1068
1069 return hif_can_suspend_link(target->hif_dev);
1070}
Houston Hoffman4d9b0802016-07-20 10:10:35 -07001071
1072#ifdef FEATURE_RUNTIME_PM
1073int htc_pm_runtime_get(HTC_HANDLE htc_handle)
1074{
1075 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1076
Houston Hoffman4d9b0802016-07-20 10:10:35 -07001077 return hif_pm_runtime_get(target->hif_dev);
1078}
1079
1080int htc_pm_runtime_put(HTC_HANDLE htc_handle)
1081{
1082 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1083
Houston Hoffman4d9b0802016-07-20 10:10:35 -07001084 return hif_pm_runtime_put(target->hif_dev);
1085}
1086#endif
Kiran Venkatappae17e3b62017-02-10 16:31:49 +05301087
1088/**
1089 * htc_set_wmi_endpoint_count: Set number of WMI endpoint
1090 * @htc_handle: HTC handle
1091 * @wmi_ep_count: WMI enpoint count
1092 *
1093 * return: None
1094 */
1095void htc_set_wmi_endpoint_count(HTC_HANDLE htc_handle, uint8_t wmi_ep_count)
1096{
1097 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1098
1099 target->wmi_ep_count = wmi_ep_count;
1100}
1101
1102/**
1103 * htc_get_wmi_endpoint_count: Get number of WMI endpoint
1104 * @htc_handle: HTC handle
1105 *
1106 * return: WMI enpoint count
1107 */
1108uint8_t htc_get_wmi_endpoint_count(HTC_HANDLE htc_handle)
1109{
1110 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1111
1112 return target->wmi_ep_count;
1113}