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