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