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 == NULL) { 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 == NULL) { 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 == NULL) { 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 (NULL == 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 ol_ctx = cds_get_context(QDF_MODULE_ID_BMI); 202 if (!ol_ctx) { 203 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 204 "%s: ol_ctx is NULL", __func__); 205 return QDF_STATUS_E_INVAL; 206 } 207 208 epping_update_ol_config(); 209 210 /* Initialize BMI and Download firmware */ 211 if (bmi_download_firmware(ol_ctx)) { 212 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 213 "%s: BMI failed to download target", __func__); 214 bmi_cleanup(ol_ctx); 215 return QDF_STATUS_E_INVAL; 216 } 217 218 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, 219 "%s: bmi_download_firmware done", __func__); 220 return QDF_STATUS_SUCCESS; 221 } 222 #else 223 static 224 QDF_STATUS epping_bmi_download_fw(struct ol_context *ol_ctx) 225 { 226 return QDF_STATUS_SUCCESS; 227 } 228 #endif 229 230 /** 231 * epping_enable(): End point ping driver enable Function 232 * 233 * This is the driver enable function - called by HDD to enable 234 * epping module 235 * 236 * return - 0 : success, negative: error 237 */ 238 int epping_enable(struct device *parent_dev, bool rtnl_held) 239 { 240 int ret = 0; 241 epping_context_t *epping_ctx = NULL; 242 struct cds_context *p_cds_context = NULL; 243 qdf_device_t qdf_ctx; 244 struct htc_init_info htc_info; 245 struct hif_opaque_softc *scn; 246 tSirMacAddr adapter_macAddr; 247 struct ol_context *ol_ctx = NULL; 248 struct hif_target_info *tgt_info; 249 250 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__); 251 252 p_cds_context = cds_get_global_context(); 253 254 if (p_cds_context == NULL) { 255 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 256 "%s: Failed cds_get_global_context", __func__); 257 ret = -1; 258 return ret; 259 } 260 261 epping_ctx = g_epping_ctx; 262 if (!epping_ctx) { 263 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 264 "%s: Failed to get epping_ctx", __func__); 265 ret = -1; 266 return ret; 267 } 268 epping_ctx->parent_dev = (void *)parent_dev; 269 epping_get_dummy_mac_addr(adapter_macAddr); 270 271 /* Initialize the timer module */ 272 qdf_timer_module_init(); 273 274 scn = cds_get_context(QDF_MODULE_ID_HIF); 275 if (!scn) { 276 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 277 "%s: scn is null!", __func__); 278 return A_ERROR; 279 } 280 281 tgt_info = hif_get_target_info_handle(scn); 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