blob: 7de497a222331b6bc585fb8eec91fc3c01f96348 [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 *
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
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080028#include "htc_debug.h"
29#include "htc_internal.h"
Rachit Kankane1bc11492018-01-24 18:48:17 +053030#include "htc_credit_history.h"
Yue Mab16cf302016-03-08 18:30:25 -080031#include <hif.h>
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053032#include <qdf_nbuf.h> /* qdf_nbuf_t */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053033#include <qdf_types.h> /* qdf_print */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080034
Poddar, Siddarthf1763402016-11-21 15:55:27 +053035#define MAX_HTC_RX_BUNDLE 2
36
Srinivas Girigowda8a0b6652016-10-19 16:01:31 -070037#if defined(WLAN_DEBUG) || defined(DEBUG)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080038static 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
46ATH_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
Pratik Gandhi78461502018-02-05 17:22:41 +053057#if (defined(CONFIG_MCL) || (QCA_WIFI_QCA8074))
58static const uint32_t svc_id[] = {WMI_CONTROL_SVC, WMI_CONTROL_SVC_WMAC1,
59 WMI_CONTROL_SVC_WMAC2};
60#else
61static const uint32_t svc_id[] = {WMI_CONTROL_SVC};
62#endif
63
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080064extern unsigned int htc_credit_flow;
65
66static void reset_endpoint_states(HTC_TARGET *target);
67
68static void destroy_htc_tx_ctrl_packet(HTC_PACKET *pPacket)
69{
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053070 qdf_nbuf_t netbuf;
Manikandan Mohane3e209e2017-04-13 20:19:26 -070071
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053072 netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Jeff Johnsona79b1112017-09-18 10:12:02 -070073 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("free ctrl netbuf :0x%pK\n", netbuf));
Manikandan Mohane3e209e2017-04-13 20:19:26 -070074 if (netbuf != NULL)
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053075 qdf_nbuf_free(netbuf);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053076 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080077}
78
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053079static HTC_PACKET *build_htc_tx_ctrl_packet(qdf_device_t osdev)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080080{
81 HTC_PACKET *pPacket = NULL;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053082 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080083
84 do {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053085 pPacket = (HTC_PACKET *) qdf_mem_malloc(sizeof(HTC_PACKET));
Manikandan Mohane3e209e2017-04-13 20:19:26 -070086 if (pPacket == NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080087 break;
Yue Mab16cf302016-03-08 18:30:25 -080088 netbuf = qdf_nbuf_alloc(osdev, HTC_CONTROL_BUFFER_SIZE,
89 20, 4, true);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080090 if (NULL == netbuf) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053091 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080092 pPacket = NULL;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053093 qdf_print("%s: nbuf alloc failed\n", __func__);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080094 break;
95 }
96 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
Jeff Johnsona79b1112017-09-18 10:12:02 -070097 ("alloc ctrl netbuf :0x%pK\n", netbuf));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080098 SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
99 } while (false);
100
101 return pPacket;
102}
103
104void 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
118HTC_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 */
134void htc_set_target_failure_callback(HTC_HANDLE HTCHandle,
135 HTC_TARGET_FAILURE Callback)
136{
137 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700138
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800139 target->HTCInitInfo.TargetFailure = Callback;
140}
141
142void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start)
143{
144 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700145
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800146 hif_dump(target->hif_dev, CmdId, start);
147}
148
149/* cleanup the HTC instance */
150static void htc_cleanup(HTC_TARGET *target)
151{
152 HTC_PACKET *pPacket;
Govind Singhc505cdc2017-05-16 12:15:51 +0530153 int i;
154 HTC_ENDPOINT *endpoint;
wadesongfbf643a2017-10-14 09:11:34 +0800155 HTC_PACKET_QUEUE *pkt_queue;
156 qdf_nbuf_t netbuf;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800157
158 if (target->hif_dev != NULL) {
159 hif_detach_htc(target->hif_dev);
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530160 hif_mask_interrupt_call(target->hif_dev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800161 target->hif_dev = NULL;
162 }
163
164 while (true) {
165 pPacket = allocate_htc_packet_container(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700166 if (pPacket == NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800167 break;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530168 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800169 }
170
wadesongfbf643a2017-10-14 09:11:34 +0800171 LOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800172 pPacket = target->pBundleFreeList;
wadesongfbf643a2017-10-14 09:11:34 +0800173 target->pBundleFreeList = NULL;
174 UNLOCK_HTC_TX(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800175 while (pPacket) {
176 HTC_PACKET *pPacketTmp = (HTC_PACKET *) pPacket->ListLink.pNext;
wadesongfbf643a2017-10-14 09:11:34 +0800177 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);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530183 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800184 pPacket = pPacketTmp;
185 }
wadesongfbf643a2017-10-14 09:11:34 +0800186
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800187#ifdef TODO_FIXME
188 while (true) {
189 pPacket = htc_alloc_control_tx_packet(target);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700190 if (pPacket == NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800191 break;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530192 netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700193 if (netbuf != NULL)
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530194 qdf_nbuf_free(netbuf);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530195 qdf_mem_free(pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800196 }
197#endif
198
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530199 qdf_spinlock_destroy(&target->HTCLock);
200 qdf_spinlock_destroy(&target->HTCRxLock);
201 qdf_spinlock_destroy(&target->HTCTxLock);
202 qdf_spinlock_destroy(&target->HTCCreditLock);
Govind Singhc505cdc2017-05-16 12:15:51 +0530203 for (i = 0; i < ENDPOINT_MAX; i++) {
204 endpoint = &target->endpoint[i];
205 qdf_spinlock_destroy(&endpoint->lookup_queue_lock);
206 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800207
208 /* free our instance */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530209 qdf_mem_free(target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800210}
211
Yue Maec9e71c2016-02-26 18:52:20 -0800212#ifdef FEATURE_RUNTIME_PM
213/**
214 * htc_runtime_pm_init(): runtime pm related intialization
215 *
216 * need to initialize a work item.
217 */
218static 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 */
232int 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 */
247int 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
258static inline void htc_runtime_pm_init(HTC_TARGET *target) { }
259#endif
260
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800261/* registered target arrival callback from the HIF layer */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700262HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo,
263 qdf_device_t osdev, uint32_t con_mode)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800264{
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 }
Jeff Johnsona79b1112017-09-18 10:12:02 -0700274 HTC_TRACE("+htc_create .. HIF :%pK", ol_sc);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800275
276 A_REGISTER_MODULE_DEBUG_INFO(htc);
277
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530278 target = (HTC_TARGET *) qdf_mem_malloc(sizeof(HTC_TARGET));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800279 if (target == NULL) {
280 HTC_ERROR("%s: Unable to allocate memory", __func__);
281 return NULL;
282 }
283
Houston Hoffman47e387b2015-10-20 17:04:42 -0700284 htc_runtime_pm_init(target);
Rachit Kankane1bc11492018-01-24 18:48:17 +0530285 htc_credit_history_init();
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530286 qdf_spinlock_create(&target->HTCLock);
287 qdf_spinlock_create(&target->HTCRxLock);
288 qdf_spinlock_create(&target->HTCTxLock);
Govind Singhc505cdc2017-05-16 12:15:51 +0530289 for (i = 0; i < ENDPOINT_MAX; i++) {
290 pEndpoint = &target->endpoint[i];
291 qdf_spinlock_create(&pEndpoint->lookup_queue_lock);
292 }
gbianb417db22016-09-30 17:01:07 +0800293 target->is_nodrop_pkt = false;
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530294 target->wmi_ep_count = 1;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800295
296 do {
Yue Mab16cf302016-03-08 18:30:25 -0800297 qdf_mem_copy(&target->HTCInitInfo, pInfo,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700298 sizeof(struct htc_init_info));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800299 target->host_handle = pInfo->pContext;
300 target->osdev = osdev;
Yue Maec9e71c2016-02-26 18:52:20 -0800301 target->con_mode = con_mode;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800302
303 reset_endpoint_states(target);
304
305 INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList);
306
307 for (i = 0; i < HTC_PACKET_CONTAINER_ALLOCATION; i++) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700308 HTC_PACKET *pPacket = (HTC_PACKET *)
309 qdf_mem_malloc(sizeof(HTC_PACKET));
310 if (pPacket != NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800311 free_htc_packet_container(target, pPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800312 }
313
314#ifdef TODO_FIXME
315 for (i = 0; i < NUM_CONTROL_TX_BUFFERS; i++) {
316 pPacket = build_htc_tx_ctrl_packet();
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700317 if (pPacket == NULL)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800318 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800319 htc_free_control_tx_packet(target, pPacket);
320 }
321#endif
322
323 /* setup HIF layer callbacks */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530324 qdf_mem_zero(&htcCallbacks, sizeof(struct hif_msg_callbacks));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800325 htcCallbacks.Context = target;
326 htcCallbacks.rxCompletionHandler = htc_rx_completion_handler;
327 htcCallbacks.txCompletionHandler = htc_tx_completion_handler;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700328 htcCallbacks.txResourceAvailHandler =
329 htc_tx_resource_avail_handler;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800330 htcCallbacks.fwEventHandler = htc_fw_event_handler;
331 target->hif_dev = ol_sc;
332
333 /* Get HIF default pipe for HTC message exchange */
Houston Hoffman29573d92015-10-20 17:49:44 -0700334 pEndpoint = &target->endpoint[ENDPOINT_0];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800335
336 hif_post_init(target->hif_dev, target, &htcCallbacks);
337 hif_get_default_pipe(target->hif_dev, &pEndpoint->UL_PipeID,
338 &pEndpoint->DL_PipeID);
Dustin Brownbbba9172017-10-04 17:03:56 -0700339 hif_set_initial_wakeup_cb(target->hif_dev,
340 pInfo->target_initial_wakeup_cb,
341 pInfo->target_psoc);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800342
343 } while (false);
344
345 htc_recv_init(target);
346
Jeff Johnsona79b1112017-09-18 10:12:02 -0700347 HTC_TRACE("-htc_create: (0x%pK)", target);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800348
349 return (HTC_HANDLE) target;
350}
351
352void htc_destroy(HTC_HANDLE HTCHandle)
353{
354 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700355
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800356 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700357 ("+htc_destroy .. Destroying :0x%pK\n", target));
Karthick Sc3a7a0c2015-10-14 17:56:55 +0530358 hif_stop(htc_get_hif_device(HTCHandle));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800359 if (target)
360 htc_cleanup(target);
361 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n"));
362}
363
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700364/* get the low level HIF device for the caller , the caller may wish to do low
365 * level HIF requests
366 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800367void *htc_get_hif_device(HTC_HANDLE HTCHandle)
368{
369 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700370
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800371 return target->hif_dev;
372}
373
Jeff Johnsonc66399a2016-10-07 13:01:33 -0700374static void htc_control_tx_complete(void *Context, HTC_PACKET *pPacket)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800375{
376 HTC_TARGET *target = (HTC_TARGET *) Context;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700377
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800378 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700379 ("+-htc_control_tx_complete 0x%pK (l:%d)\n", pPacket,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800380 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/**
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530388 * 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 */
395static void
396htc_setup_epping_credit_allocation(struct hif_opaque_softc *scn,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700397 struct htc_service_tx_credit_allocation *pEntry,
398 int credits)
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530399{
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 }
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530418}
419
420/**
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800421 * htc_setup_target_buffer_assignments() - setup target buffer assignments
422 * @target: HTC Target Pointer
423 *
424 * Return: A_STATUS
425 */
Jeff Johnsonc66399a2016-10-07 13:01:33 -0700426static
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800427A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target)
428{
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700429 struct htc_service_tx_credit_allocation *pEntry;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800430 A_STATUS status;
431 int credits;
432 int creditsPerMaxMsg;
433
434 creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700435 if (MAX_MESSAGE_SIZE % target->TargetCreditSize)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800436 creditsPerMaxMsg++;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800437
438 /* TODO, this should be configured by the caller! */
439
440 credits = target->TotalTransmitCredits;
441 pEntry = &target->ServiceTxAllocTable[0];
442
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530443 status = A_OK;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800444 /*
445 * Allocate all credists/HTC buffers to WMI.
446 * no buffers are used/required for data. data always
447 * remains on host.
448 */
Yue Maec9e71c2016-02-26 18:52:20 -0800449 if (HTC_IS_EPPING_ENABLED(target->con_mode)) {
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530450 pEntry++;
451 pEntry->service_id = WMI_CONTROL_SVC;
452 pEntry->CreditAllocation = credits;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800453 /* endpoint ping is a testing tool directly on top of HTC in
454 * both target and host sides.
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700455 * In target side, the endppint ping fw has no wlan stack and
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800456 * 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
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530462 * and it directly sits on HTC. Only HIF, HTC, QDF, ADF are
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800463 * 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
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700472 * 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.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800475 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800476
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530477 htc_setup_epping_credit_allocation(target->hif_dev,
478 pEntry, credits);
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530479 } else {
480 int i;
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530481 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 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800497 }
498
499 if (A_SUCCESS(status)) {
500 int i;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700501
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800502 for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700503 if (target->ServiceTxAllocTable[i].service_id != 0) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800504 AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
Rajeev Kumar885f2752018-01-18 14:55:17 -0800505 ("SVS Index : %d TX : 0x%2.2X : alloc:%d",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800506 i,
507 target->ServiceTxAllocTable[i].
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700508 service_id,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800509 target->ServiceTxAllocTable[i].
510 CreditAllocation));
511 }
512 }
513 }
514
515 return status;
516}
517
Yue Mab16cf302016-03-08 18:30:25 -0800518uint8_t htc_get_credit_allocation(HTC_TARGET *target, uint16_t service_id)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800519{
Yue Mab16cf302016-03-08 18:30:25 -0800520 uint8_t allocation = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800521 int i;
522
523 for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700524 if (target->ServiceTxAllocTable[i].service_id == service_id) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800525 allocation =
526 target->ServiceTxAllocTable[i].CreditAllocation;
527 }
528 }
529
530 if (0 == allocation) {
Srinivas Girigowda38ee3052017-03-10 16:00:40 -0800531 AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700532 ("HTC Service TX : 0x%2.2X : allocation is zero!\n",
533 service_id));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800534 }
535
536 return allocation;
537}
538
Rakesh Pillai13146452017-06-22 12:52:31 +0530539QDF_STATUS htc_wait_target(HTC_HANDLE HTCHandle)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800540{
Rakesh Pillai13146452017-06-22 12:52:31 +0530541 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800542 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
543 HTC_READY_EX_MSG *pReadyMsg;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700544 struct htc_service_connect_req connect;
545 struct htc_service_connect_resp resp;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800546 HTC_READY_MSG *rdy_msg;
Yue Mab16cf302016-03-08 18:30:25 -0800547 uint16_t htc_rdy_msg_id;
Poddar, Siddarthf1763402016-11-21 15:55:27 +0530548 uint8_t i = 0;
549 HTC_PACKET *rx_bundle_packet, *temp_bundle_packet;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800550
551 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
Jeff Johnsona79b1112017-09-18 10:12:02 -0700552 ("htc_wait_target - Enter (target:0x%pK)\n", HTCHandle));
Srinivas Girigowda38ee3052017-03-10 16:00:40 -0800553 AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("+HWT\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800554
555 do {
556
557 status = hif_start(target->hif_dev);
Rakesh Pillai13146452017-06-22 12:52:31 +0530558 if (QDF_IS_STATUS_ERROR(status)) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700559 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
560 ("hif_start failed\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800561 break;
562 }
563
564 status = htc_wait_recv_ctrl_message(target);
565
Rakesh Pillai13146452017-06-22 12:52:31 +0530566 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800567 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800568
569 if (target->CtrlResponseLength < (sizeof(HTC_READY_EX_MSG))) {
570 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700571 ("Invalid HTC Ready Msg Len:%d!\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800572 target->CtrlResponseLength));
Rakesh Pillai13146452017-06-22 12:52:31 +0530573 status = QDF_STATUS_E_BADMSG;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800574 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,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700584 ("Invalid HTC Ready Msg : 0x%X!\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800585 htc_rdy_msg_id));
Rakesh Pillai13146452017-06-22 12:52:31 +0530586 status = QDF_STATUS_E_BADMSG;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800587 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 =
Yue Mab16cf302016-03-08 18:30:25 -0800595 (uint8_t) pReadyMsg->MaxMsgsPerHTCBundle;
Chris Guo37cf36d2017-07-06 18:56:32 +0800596 UPDATE_ALT_CREDIT(target, pReadyMsg->AltDataCreditSize);
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700597 /* for old fw this value is set to 0. But the minimum value
598 * should be 1, i.e., no bundling
599 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800600 if (target->MaxMsgsPerHTCBundle < 1)
601 target->MaxMsgsPerHTCBundle = 1;
602
603 AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
Rajeev Kumar885f2752018-01-18 14:55:17 -0800604 ("Target Ready! TX resource : %d size:%d, MaxMsgsPerHTCBundle = %d",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800605 target->TotalTransmitCredits,
606 target->TargetCreditSize,
607 target->MaxMsgsPerHTCBundle));
608
609 if ((0 == target->TotalTransmitCredits)
610 || (0 == target->TargetCreditSize)) {
Rakesh Pillai13146452017-06-22 12:52:31 +0530611 status = QDF_STATUS_E_ABORTED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800612 break;
613 }
Poddar, Siddarthf1763402016-11-21 15:55:27 +0530614
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 }
wadesongfbf643a2017-10-14 09:11:34 +0800629 LOCK_HTC_TX(target);
Poddar, Siddarthf1763402016-11-21 15:55:27 +0530630 target->pBundleFreeList = temp_bundle_packet;
wadesongfbf643a2017-10-14 09:11:34 +0800631 UNLOCK_HTC_TX(target);
Poddar, Siddarthf1763402016-11-21 15:55:27 +0530632 }
633
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800634 /* done processing */
635 target->CtrlResponseProcessing = false;
636
637 htc_setup_target_buffer_assignments(target);
638
639 /* setup our pseudo HTC control endpoint connection */
Yue Mab16cf302016-03-08 18:30:25 -0800640 qdf_mem_zero(&connect, sizeof(connect));
641 qdf_mem_zero(&resp, sizeof(resp));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800642 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;
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700646 connect.service_id = HTC_CTRL_RSVD_SVC;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800647
648 /* connect fake service */
649 status = htc_connect_service((HTC_HANDLE) target,
650 &connect, &resp);
651
652 } while (false);
653
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700654 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_wait_target - Exit (%d)\n",
655 status));
Srinivas Girigowda38ee3052017-03-10 16:00:40 -0800656 AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("-HWT\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800657 return status;
658}
659
660/* start HTC, this is called after all services are connected */
661static A_STATUS htc_config_target_hif_pipe(HTC_TARGET *target)
662{
663
664 return A_OK;
665}
666
667static 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++) {
Houston Hoffman29573d92015-10-20 17:49:44 -0700673 pEndpoint = &target->endpoint[i];
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700674 pEndpoint->service_id = 0;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800675 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;
Yue Mab16cf302016-03-08 18:30:25 -0800682 pEndpoint->TxCreditFlowEnabled = (bool)htc_credit_flow;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530683 qdf_atomic_init(&pEndpoint->TxProcessCount);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800684 }
685}
686
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700687/**
688 * htc_start() - Main HTC function to trigger HTC start
689 * @HTCHandle: pointer to HTC handle
690 *
Rakesh Pillai13146452017-06-22 12:52:31 +0530691 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700692 */
Rakesh Pillai13146452017-06-22 12:52:31 +0530693QDF_STATUS htc_start(HTC_HANDLE HTCHandle)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800694{
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530695 qdf_nbuf_t netbuf;
Rakesh Pillai13146452017-06-22 12:52:31 +0530696 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800697 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);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530711 qdf_print("%s: allocControlTxPacket failed\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800712 __func__);
Rakesh Pillai13146452017-06-22 12:52:31 +0530713 status = QDF_STATUS_E_NOMEM;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800714 break;
715 }
716
717 netbuf =
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530718 (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800719 /* assemble setup complete message */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530720 qdf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800721 pSetupComp =
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530722 (HTC_SETUP_COMPLETE_EX_MSG *) qdf_nbuf_data(netbuf);
Yue Mab16cf302016-03-08 18:30:25 -0800723 qdf_mem_zero(pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800724
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,
Rajeev Kumar885f2752018-01-18 14:55:17 -0800730 ("HTC will not use TX credit flow control"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800731 pSetupComp->SetupFlags |=
732 HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW;
733 } else {
734 AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
Rajeev Kumar885f2752018-01-18 14:55:17 -0800735 ("HTC using TX credit flow control"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800736 }
737
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700738 if ((hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO) ||
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700739 (hif_get_bus_type(target->hif_dev) ==
740 QDF_BUS_TYPE_USB)) {
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700741 if (HTC_RX_BUNDLE_ENABLED(target))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800742 pSetupComp->SetupFlags |=
743 HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV;
Mohit Khanna0f6194e2016-05-17 15:30:44 -0700744 hif_set_bundle_mode(target->hif_dev, true,
745 HTC_MAX_MSG_PER_BUNDLE_RX);
746 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800747
748 SET_HTC_PACKET_INFO_TX(pSendPacket,
749 NULL,
Yue Mab16cf302016-03-08 18:30:25 -0800750 (uint8_t *) pSetupComp,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800751 sizeof(HTC_SETUP_COMPLETE_EX_MSG),
752 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
753
754 status = htc_send_pkt((HTC_HANDLE) target, pSendPacket);
Rakesh Pillai13146452017-06-22 12:52:31 +0530755 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800756 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800757 } 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*/
764void 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
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530770 qdf_nbuf_t netbuf;
771 qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800772#endif
773
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530774 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800775
776 /* cleanup endpoints */
777 for (i = 0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -0700778 pEndpoint = &target->endpoint[i];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800779 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);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530787 while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
788 qdf_nbuf_free(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800789 RESET_RX_SG_CONFIG(target);
790 UNLOCK_HTC_RX(target);
791#endif
792
793 reset_endpoint_states(target);
794
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700795 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800796}
797
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700798/* stop HTC communications, i.e. stop interrupt reception, and flush all queued
799 * buffers
800 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800801void 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
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530807 qdf_nbuf_t netbuf;
808 qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800809#endif
810
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530811 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800812
813 /* cleanup endpoints */
814 for (i = 0; i < ENDPOINT_MAX; i++) {
Houston Hoffman29573d92015-10-20 17:49:44 -0700815 pEndpoint = &target->endpoint[i];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800816 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) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530819 qdf_timer_stop(&pEndpoint->ul_poll_timer);
820 qdf_timer_free(&pEndpoint->ul_poll_timer);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800821 }
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);
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530835 while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
836 qdf_nbuf_free(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800837 RESET_RX_SG_CONFIG(target);
838 UNLOCK_HTC_RX(target);
839#endif
840
841 reset_endpoint_states(target);
842
Houston Hoffman47e387b2015-10-20 17:04:42 -0700843 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop\n"));
844}
845
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800846void 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++) {
Houston Hoffman29573d92015-10-20 17:49:44 -0700853 pEndpoint = &target->endpoint[i];
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700854 if (0 == pEndpoint->service_id)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800855 continue;
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700856
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800857 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700858 ("--- EP : %d service_id: 0x%X --------------\n",
859 pEndpoint->Id, pEndpoint->service_id));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800860 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700861 (" TxCredits : %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800862 pEndpoint->TxCredits));
863 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700864 (" TxCreditSize : %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800865 pEndpoint->TxCreditSize));
866 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700867 (" TxCreditsPerMaxMsg : %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800868 pEndpoint->TxCreditsPerMaxMsg));
869 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700870 (" TxQueueDepth : %d\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800871 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
872 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700873 ("----------------------------------------\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800874 }
875}
876
Yue Mab16cf302016-03-08 18:30:25 -0800877bool htc_get_endpoint_statistics(HTC_HANDLE HTCHandle,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800878 HTC_ENDPOINT_ID Endpoint,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700879 enum htc_endpoint_stat_action Action,
880 struct htc_endpoint_stats *pStats)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800881{
882#ifdef HTC_EP_STAT_PROFILING
883 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
Yue Mab16cf302016-03-08 18:30:25 -0800884 bool clearStats = false;
885 bool sample = false;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800886
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 */
Yue Mab16cf302016-03-08 18:30:25 -0800911 qdf_mem_copy(pStats, &target->endpoint[Endpoint].endpoint_stats,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700912 sizeof(struct htc_endpoint_stats));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800913 }
914
915 if (clearStats) {
916 /* reset stats */
Yue Mab16cf302016-03-08 18:30:25 -0800917 qdf_mem_zero(&target->endpoint[Endpoint].endpoint_stats,
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700918 sizeof(struct htc_endpoint_stats));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800919 }
920
921 UNLOCK_HTC_RX(target);
922 UNLOCK_HTC_TX(target);
923
924 return true;
925#else
926 return false;
927#endif
928}
929
930void *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
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800937#ifdef IPA_OFFLOAD
Leo Changd85f78d2015-11-13 10:55:34 -0800938/**
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 */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800947void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle,
Sravan Kumar Kairam58e0adf2018-02-27 18:37:40 +0530948 qdf_shared_mem_t **ce_sr,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800949 uint32_t *ce_sr_ring_size,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530950 qdf_dma_addr_t *ce_reg_paddr)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800951{
952 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
953
Sravan Kumar Kairam58e0adf2018-02-27 18:37:40 +0530954 if (target->hif_dev)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800955 hif_ipa_get_ce_resource(target->hif_dev,
Sravan Kumar Kairam58e0adf2018-02-27 18:37:40 +0530956 ce_sr, ce_sr_ring_size, ce_reg_paddr);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800957}
958#endif /* IPA_OFFLOAD */
Komal Seelamf8600682016-02-02 18:17:13 +0530959
Poddar, Siddarthdf030092016-04-28 11:41:57 +0530960#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
961
962void htc_dump_bundle_stats(HTC_HANDLE HTCHandle)
963{
964 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
965 int total, i;
966
967 total = 0;
968 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++)
969 total += target->rx_bundle_stats[i];
970
971 if (total) {
972 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("RX Bundle stats:\n"));
973 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total RX packets: %d\n",
974 total));
975 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (
976 "Number of bundle: Number of packets\n"));
977 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++)
978 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
979 ("%10d:%10d(%2d%s)\n", (i+1),
980 target->rx_bundle_stats[i],
981 ((target->rx_bundle_stats[i]*100)/
982 total), "%"));
983 }
984
985
986 total = 0;
987 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++)
988 total += target->tx_bundle_stats[i];
989
990 if (total) {
991 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("TX Bundle stats:\n"));
992 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total TX packets: %d\n",
993 total));
994 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
995 ("Number of bundle: Number of packets\n"));
996 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++)
997 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
998 ("%10d:%10d(%2d%s)\n", (i+1),
999 target->tx_bundle_stats[i],
1000 ((target->tx_bundle_stats[i]*100)/
1001 total), "%"));
1002 }
1003}
1004
1005void htc_clear_bundle_stats(HTC_HANDLE HTCHandle)
1006{
1007 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
1008
1009 qdf_mem_zero(&target->rx_bundle_stats, sizeof(target->rx_bundle_stats));
1010 qdf_mem_zero(&target->tx_bundle_stats, sizeof(target->tx_bundle_stats));
1011}
1012#endif
1013
Komal Seelamf8600682016-02-02 18:17:13 +05301014/**
1015 * htc_vote_link_down - API to vote for link down
1016 * @htc_handle: HTC handle
1017 *
1018 * API for upper layers to call HIF to vote for link down
1019 *
1020 * Return: void
1021 */
1022void htc_vote_link_down(HTC_HANDLE htc_handle)
1023{
1024 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1025
1026 if (!target->hif_dev)
1027 return;
1028
1029 hif_vote_link_down(target->hif_dev);
1030}
1031
1032/**
1033 * htc_vote_link_up - API to vote for link up
1034 * @htc_handle: HTC Handle
1035 *
1036 * API for upper layers to call HIF to vote for link up
1037 *
1038 * Return: void
1039 */
1040void htc_vote_link_up(HTC_HANDLE htc_handle)
1041{
1042 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1043
1044 if (!target->hif_dev)
1045 return;
1046
1047 hif_vote_link_up(target->hif_dev);
1048}
1049
1050/**
1051 * htc_can_suspend_link - API to query HIF for link status
1052 * @htc_handle: HTC Handle
1053 *
1054 * API for upper layers to call HIF to query if the link can suspend
1055 *
1056 * Return: void
1057 */
1058bool htc_can_suspend_link(HTC_HANDLE htc_handle)
1059{
1060 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1061
1062 if (!target->hif_dev)
1063 return false;
1064
1065 return hif_can_suspend_link(target->hif_dev);
1066}
Houston Hoffman4d9b0802016-07-20 10:10:35 -07001067
1068#ifdef FEATURE_RUNTIME_PM
1069int htc_pm_runtime_get(HTC_HANDLE htc_handle)
1070{
1071 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1072
Houston Hoffman4d9b0802016-07-20 10:10:35 -07001073 return hif_pm_runtime_get(target->hif_dev);
1074}
1075
1076int htc_pm_runtime_put(HTC_HANDLE htc_handle)
1077{
1078 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1079
Houston Hoffman4d9b0802016-07-20 10:10:35 -07001080 return hif_pm_runtime_put(target->hif_dev);
1081}
1082#endif
Kiran Venkatappae17e3b62017-02-10 16:31:49 +05301083
1084/**
1085 * htc_set_wmi_endpoint_count: Set number of WMI endpoint
1086 * @htc_handle: HTC handle
1087 * @wmi_ep_count: WMI enpoint count
1088 *
1089 * return: None
1090 */
1091void htc_set_wmi_endpoint_count(HTC_HANDLE htc_handle, uint8_t wmi_ep_count)
1092{
1093 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1094
1095 target->wmi_ep_count = wmi_ep_count;
1096}
1097
1098/**
1099 * htc_get_wmi_endpoint_count: Get number of WMI endpoint
1100 * @htc_handle: HTC handle
1101 *
1102 * return: WMI enpoint count
1103 */
1104uint8_t htc_get_wmi_endpoint_count(HTC_HANDLE htc_handle)
1105{
1106 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
1107
1108 return target->wmi_ep_count;
1109}