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