1 /*
2 * Copyright (c) 2014-2019,2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*========================================================================
21
22 \file epping_main.c
23
24 \brief WLAN End Point Ping test tool implementation
25
26 ========================================================================*/
27
28 /*--------------------------------------------------------------------------
29 Include Files
30 ------------------------------------------------------------------------*/
31 #include <cds_api.h>
32 #include <cds_sched.h>
33 #include <linux/etherdevice.h>
34 #include <linux/firmware.h>
35 #include <wni_api.h>
36 #include <wlan_ptt_sock_svc.h>
37 #include <linux/wireless.h>
38 #include <net/cfg80211.h>
39 #include <linux/rtnetlink.h>
40 #include <linux/semaphore.h>
41 #include <linux/ctype.h>
42 #include "bmi.h"
43 #include "ol_fw.h"
44 #include "ol_if_athvar.h"
45 #include "hif.h"
46 #include "epping_main.h"
47 #include "epping_internal.h"
48 #include "wlan_policy_mgr_api.h"
49
50 #ifdef TIMER_MANAGER
51 #define TIMER_MANAGER_STR " +TIMER_MANAGER"
52 #else
53 #define TIMER_MANAGER_STR ""
54 #endif
55
56 #ifdef MEMORY_DEBUG
57 #define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
58 #else
59 #define MEMORY_DEBUG_STR ""
60 #endif
61
62 #ifdef HIF_SDIO
63 #define WLAN_WAIT_TIME_WLANSTART 10000
64 #else
65 #define WLAN_WAIT_TIME_WLANSTART 2000
66 #endif
67
68 #ifdef WLAN_FEATURE_EPPING
69 static struct epping_context *g_epping_ctx;
70
71 /**
72 * epping_open(): End point ping driver open Function
73 *
74 * This function is called by HDD to open epping module
75 *
76 *
77 * return - 0 for success, negative for failure
78 */
epping_open(void)79 int epping_open(void)
80 {
81 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__);
82
83 g_epping_ctx = qdf_mem_malloc(sizeof(*g_epping_ctx));
84
85 if (!g_epping_ctx)
86 return -ENOMEM;
87
88 g_epping_ctx->con_mode = cds_get_conparam();
89 return 0;
90 }
91
92 /**
93 * epping_disable(): End point ping driver disable Function
94 *
95 * This is the driver disable function - called by HDD to
96 * disable epping module
97 *
98 * return: none
99 */
epping_disable(void)100 void epping_disable(void)
101 {
102 epping_context_t *epping_ctx;
103 struct hif_opaque_softc *hif_ctx;
104 HTC_HANDLE htc_handle;
105
106 epping_ctx = g_epping_ctx;
107 if (!epping_ctx) {
108 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
109 "%s: error: epping_ctx = NULL", __func__);
110 return;
111 }
112
113 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
114 if (!hif_ctx) {
115 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
116 "%s: error: hif_ctx = NULL", __func__);
117 return;
118 }
119 hif_disable_isr(hif_ctx);
120 hif_reset_soc(hif_ctx);
121
122 htc_handle = cds_get_context(QDF_MODULE_ID_HTC);
123 if (!htc_handle) {
124 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
125 "%s: error: htc_handle = NULL", __func__);
126 return;
127 }
128 htc_stop(htc_handle);
129 epping_cookie_cleanup(epping_ctx);
130 htc_destroy(htc_handle);
131
132 if (epping_ctx->epping_adapter) {
133 epping_destroy_adapter(epping_ctx->epping_adapter);
134 epping_ctx->epping_adapter = NULL;
135 }
136 }
137
138 /**
139 * epping_close(): End point ping driver close Function
140 *
141 * This is the driver close function - called by HDD to close epping module
142 *
143 * return: none
144 */
epping_close(void)145 void epping_close(void)
146 {
147 epping_context_t *to_free;
148
149 if (!g_epping_ctx) {
150 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
151 "%s: error: g_epping_ctx = NULL", __func__);
152 return;
153 }
154
155 to_free = g_epping_ctx;
156 g_epping_ctx = NULL;
157 qdf_mem_free(to_free);
158 }
159
160 /**
161 * epping_target_suspend_acknowledge() - process wow ack/nack from fw
162 * @context: htc_init_info->context
163 * @wow_nack: true when wow is rejected
164 * @reason_code : WoW status reason code
165 */
epping_target_suspend_acknowledge(void * context,bool wow_nack,uint16_t reson_code)166 static void epping_target_suspend_acknowledge(void *context, bool wow_nack,
167 uint16_t reson_code)
168 {
169 if (!g_epping_ctx) {
170 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
171 "%s: epping_ctx is NULL", __func__);
172 return;
173 }
174 /* EPPING_TODO: do we need wow_nack? */
175 g_epping_ctx->wow_nack = wow_nack;
176 }
177
178 #ifdef WLAN_FEATURE_BMI
179 /**
180 * epping_update_ol_config - API to update ol configuration parameters
181 *
182 * Return: void
183 */
epping_update_ol_config(void)184 static void epping_update_ol_config(void)
185 {
186 struct ol_config_info cfg;
187 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
188
189 if (!ol_ctx)
190 return;
191
192 cfg.enable_self_recovery = 0;
193 cfg.enable_uart_print = 0;
194 cfg.enable_fw_log = 0;
195 cfg.enable_ramdump_collection = 0;
196 cfg.enable_lpass_support = 0;
197
198 ol_init_ini_config(ol_ctx, &cfg);
199 }
200
201 static
epping_bmi_download_fw(struct ol_context * ol_ctx)202 QDF_STATUS epping_bmi_download_fw(struct ol_context *ol_ctx)
203 {
204 epping_update_ol_config();
205
206 /* Initialize BMI and Download firmware */
207 if (bmi_download_firmware(ol_ctx)) {
208 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
209 "%s: BMI failed to download target", __func__);
210 bmi_cleanup(ol_ctx);
211 return QDF_STATUS_E_INVAL;
212 }
213
214 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH,
215 "%s: bmi_download_firmware done", __func__);
216 return QDF_STATUS_SUCCESS;
217 }
218 #else
219 static
epping_bmi_download_fw(struct ol_context * ol_ctx)220 QDF_STATUS epping_bmi_download_fw(struct ol_context *ol_ctx)
221 {
222 return QDF_STATUS_SUCCESS;
223 }
224 #endif
225
226 /**
227 * epping_enable(): End point ping driver enable Function
228 *
229 * This is the driver enable function - called by HDD to enable
230 * epping module
231 *
232 * return - 0 : success, negative: error
233 */
epping_enable(struct device * parent_dev,bool rtnl_held)234 int epping_enable(struct device *parent_dev, bool rtnl_held)
235 {
236 int ret = 0;
237 epping_context_t *epping_ctx = NULL;
238 struct cds_context *p_cds_context = NULL;
239 qdf_device_t qdf_ctx;
240 struct htc_init_info htc_info;
241 struct hif_opaque_softc *scn;
242 tSirMacAddr adapter_macAddr;
243 struct ol_context *ol_ctx = NULL;
244 struct hif_target_info *tgt_info;
245
246 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__);
247
248 p_cds_context = cds_get_global_context();
249
250 if (!p_cds_context) {
251 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
252 "%s: Failed cds_get_global_context", __func__);
253 ret = -1;
254 return ret;
255 }
256
257 epping_ctx = g_epping_ctx;
258 if (!epping_ctx) {
259 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
260 "%s: Failed to get epping_ctx", __func__);
261 ret = -1;
262 return ret;
263 }
264 epping_ctx->parent_dev = (void *)parent_dev;
265 epping_get_dummy_mac_addr(adapter_macAddr);
266
267 /* Initialize the timer module */
268 qdf_timer_module_init();
269
270 scn = cds_get_context(QDF_MODULE_ID_HIF);
271 if (!scn) {
272 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
273 "%s: scn is null!", __func__);
274 return A_ERROR;
275 }
276
277 tgt_info = hif_get_target_info_handle(scn);
278
279 ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
280
281 if (epping_bmi_download_fw(ol_ctx) != QDF_STATUS_SUCCESS)
282 return A_ERROR;
283
284 /* store target type and target version info in hdd ctx */
285 epping_ctx->target_type = tgt_info->target_type;
286
287 htc_info.pContext = NULL;
288 htc_info.TargetFailure = ol_target_failure;
289 htc_info.TargetSendSuspendComplete = epping_target_suspend_acknowledge;
290 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
291
292 /* Create HTC */
293 p_cds_context->htc_ctx = htc_create(scn, &htc_info, qdf_ctx,
294 cds_get_conparam());
295 if (!p_cds_context->htc_ctx) {
296 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
297 "%s: Failed to Create HTC", __func__);
298 bmi_cleanup(ol_ctx);
299 return A_ERROR;
300 }
301 epping_ctx->HTCHandle =
302 cds_get_context(QDF_MODULE_ID_HTC);
303 if (!epping_ctx->HTCHandle) {
304 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
305 "%s: HTCHandle is NULL", __func__);
306 return A_ERROR;
307 }
308
309 if (bmi_done(ol_ctx)) {
310 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
311 "%s: Failed to complete BMI phase", __func__);
312 goto error_end;
313 }
314
315 /* start HIF */
316 if (htc_wait_target(epping_ctx->HTCHandle) != QDF_STATUS_SUCCESS) {
317 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
318 "%s: htc_wait_target error", __func__);
319 goto error_end;
320 }
321 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: HTC ready", __func__);
322
323 ret = epping_connect_service(epping_ctx);
324 if (ret != 0) {
325 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
326 "%s: htc_wait_targetdone", __func__);
327 goto error_end;
328 }
329 if (htc_start(epping_ctx->HTCHandle) != QDF_STATUS_SUCCESS)
330 goto error_end;
331
332 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: HTC started", __func__);
333
334 /* init the tx cookie resource */
335 ret = epping_cookie_init(epping_ctx);
336 if (ret < 0) {
337 EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
338 "%s: cookie init failed", __func__);
339 htc_stop(epping_ctx->HTCHandle);
340 epping_cookie_cleanup(epping_ctx);
341 goto error_end;
342 }
343
344 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Exit", __func__);
345 return ret;
346
347 error_end:
348 htc_destroy(p_cds_context->htc_ctx);
349 p_cds_context->htc_ctx = NULL;
350 bmi_cleanup(ol_ctx);
351 return A_ERROR;
352 }
353
epping_enable_adapter(void)354 void epping_enable_adapter(void)
355 {
356 epping_context_t *epping_ctx = g_epping_ctx;
357 tSirMacAddr adapter_macaddr;
358
359 if (!epping_ctx) {
360 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "epping context is NULL");
361 return;
362 }
363
364 epping_get_dummy_mac_addr(adapter_macaddr);
365 epping_ctx->epping_adapter = epping_add_adapter(epping_ctx,
366 adapter_macaddr,
367 QDF_STA_MODE, true);
368 if (!epping_ctx->epping_adapter)
369 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "epping add adapter failed");
370 }
371 #endif
372