1 /* 2 * Copyright (c) 2014-2018 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 == NULL) { 85 EPPING_LOG(QDF_TRACE_LEVEL_ERROR, 86 "%s: cannot alloc epping context", __func__); 87 return -ENOMEM; 88 } 89 90 g_epping_ctx->con_mode = cds_get_conparam(); 91 return 0; 92 } 93 94 /** 95 * epping_disable(): End point ping driver disable Function 96 * 97 * This is the driver disable function - called by HDD to 98 * disable epping module 99 * 100 * return: none 101 */ 102 void epping_disable(void) 103 { 104 epping_context_t *pEpping_ctx; 105 struct hif_opaque_softc *hif_ctx; 106 HTC_HANDLE htc_handle; 107 108 pEpping_ctx = g_epping_ctx; 109 if (pEpping_ctx == NULL) { 110 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 111 "%s: error: pEpping_ctx = NULL", __func__); 112 return; 113 } 114 115 if (pEpping_ctx->epping_adapter) { 116 epping_destroy_adapter(pEpping_ctx->epping_adapter); 117 pEpping_ctx->epping_adapter = NULL; 118 } 119 120 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 121 if (hif_ctx == NULL) { 122 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 123 "%s: error: hif_ctx = NULL", __func__); 124 return; 125 } 126 hif_disable_isr(hif_ctx); 127 hif_reset_soc(hif_ctx); 128 129 htc_handle = cds_get_context(QDF_MODULE_ID_HTC); 130 if (htc_handle == NULL) { 131 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 132 "%s: error: htc_handle = NULL", __func__); 133 return; 134 } 135 htc_stop(htc_handle); 136 epping_cookie_cleanup(pEpping_ctx); 137 htc_destroy(htc_handle); 138 } 139 140 /** 141 * epping_close(): End point ping driver close Function 142 * 143 * This is the driver close function - called by HDD to close epping module 144 * 145 * return: none 146 */ 147 void epping_close(void) 148 { 149 epping_context_t *to_free; 150 151 152 if (g_epping_ctx == NULL) { 153 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 154 "%s: error: g_epping_ctx = NULL", __func__); 155 return; 156 } 157 158 to_free = g_epping_ctx; 159 g_epping_ctx = NULL; 160 qdf_mem_free(to_free); 161 } 162 163 /** 164 * epping_target_suspend_acknowledge() - process wow ack/nack from fw 165 * @context: htc_init_info->context 166 * @wow_nack: true when wow is rejected 167 */ 168 static void epping_target_suspend_acknowledge(void *context, bool wow_nack) 169 { 170 if (NULL == g_epping_ctx) { 171 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 172 "%s: epping_ctx is NULL", __func__); 173 return; 174 } 175 /* EPPING_TODO: do we need wow_nack? */ 176 g_epping_ctx->wow_nack = wow_nack; 177 } 178 179 /** 180 * epping_update_ol_config - API to update ol configuration parameters 181 * 182 * Return: void 183 */ 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 * epping_enable(): End point ping driver enable Function 202 * 203 * This is the driver enable function - called by HDD to enable 204 * epping module 205 * 206 * return - 0 : success, negative: error 207 */ 208 int epping_enable(struct device *parent_dev) 209 { 210 int ret = 0; 211 epping_context_t *pEpping_ctx = NULL; 212 cds_context_type *p_cds_context = NULL; 213 qdf_device_t qdf_ctx; 214 struct htc_init_info htcInfo; 215 struct hif_opaque_softc *scn; 216 tSirMacAddr adapter_macAddr; 217 struct hif_target_info *tgt_info; 218 struct ol_context *ol_ctx; 219 220 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__); 221 222 p_cds_context = cds_get_global_context(); 223 224 if (p_cds_context == NULL) { 225 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 226 "%s: Failed cds_get_global_context", __func__); 227 ret = -1; 228 return ret; 229 } 230 231 pEpping_ctx = g_epping_ctx; 232 if (pEpping_ctx == NULL) { 233 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 234 "%s: Failed to get pEpping_ctx", __func__); 235 ret = -1; 236 return ret; 237 } 238 pEpping_ctx->parent_dev = (void *)parent_dev; 239 epping_get_dummy_mac_addr(adapter_macAddr); 240 241 /* Initialize the timer module */ 242 qdf_timer_module_init(); 243 244 scn = cds_get_context(QDF_MODULE_ID_HIF); 245 if (!scn) { 246 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 247 "%s: scn is null!", __func__); 248 return A_ERROR; 249 } 250 251 tgt_info = hif_get_target_info_handle(scn); 252 253 /* store target type and target version info in hdd ctx */ 254 pEpping_ctx->target_type = tgt_info->target_type; 255 256 ol_ctx = cds_get_context(QDF_MODULE_ID_BMI); 257 if (!ol_ctx) { 258 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 259 "%s: ol_ctx is NULL", __func__); 260 return A_ERROR; 261 } 262 263 epping_update_ol_config(); 264 #ifndef FEATURE_BMI_2 265 /* Initialize BMI and Download firmware */ 266 if (bmi_download_firmware(ol_ctx)) { 267 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 268 "%s: BMI failed to download target", __func__); 269 bmi_cleanup(ol_ctx); 270 return A_ERROR; 271 } 272 #endif 273 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, 274 "%s: bmi_download_firmware done", __func__); 275 276 htcInfo.pContext = ol_ctx; 277 htcInfo.TargetFailure = ol_target_failure; 278 htcInfo.TargetSendSuspendComplete = epping_target_suspend_acknowledge; 279 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 280 281 /* Create HTC */ 282 p_cds_context->htc_ctx = htc_create(scn, &htcInfo, qdf_ctx, 283 cds_get_conparam()); 284 if (!p_cds_context->htc_ctx) { 285 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 286 "%s: Failed to Create HTC", __func__); 287 bmi_cleanup(ol_ctx); 288 return A_ERROR; 289 } 290 pEpping_ctx->HTCHandle = 291 cds_get_context(QDF_MODULE_ID_HTC); 292 if (pEpping_ctx->HTCHandle == NULL) { 293 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 294 "%s: HTCHandle is NULL", __func__); 295 return A_ERROR; 296 } 297 298 if (bmi_done(ol_ctx)) { 299 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 300 "%s: Failed to complete BMI phase", __func__); 301 goto error_end; 302 } 303 304 /* start HIF */ 305 if (htc_wait_target(pEpping_ctx->HTCHandle) != QDF_STATUS_SUCCESS) { 306 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 307 "%s: htc_wait_target error", __func__); 308 goto error_end; 309 } 310 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: HTC ready", __func__); 311 312 ret = epping_connect_service(pEpping_ctx); 313 if (ret != 0) { 314 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 315 "%s: htc_wait_targetdone", __func__); 316 goto error_end; 317 } 318 if (htc_start(pEpping_ctx->HTCHandle) != QDF_STATUS_SUCCESS) { 319 goto error_end; 320 } 321 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: HTC started", __func__); 322 323 /* init the tx cookie resource */ 324 ret = epping_cookie_init(pEpping_ctx); 325 if (ret == 0) { 326 pEpping_ctx->epping_adapter = epping_add_adapter(pEpping_ctx, 327 adapter_macAddr, 328 QDF_STA_MODE); 329 } 330 if (ret < 0 || pEpping_ctx->epping_adapter == NULL) { 331 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 332 "%s: epping_add_adaptererror error", __func__); 333 htc_stop(pEpping_ctx->HTCHandle); 334 epping_cookie_cleanup(pEpping_ctx); 335 goto error_end; 336 } 337 338 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Exit", __func__); 339 return ret; 340 341 error_end: 342 htc_destroy(p_cds_context->htc_ctx); 343 p_cds_context->htc_ctx = NULL; 344 bmi_cleanup(ol_ctx); 345 return A_ERROR; 346 } 347 #endif 348