1 /* 2 * Copyright (c) 2014-2019,2021 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 278 if (epping_bmi_download_fw(ol_ctx) != QDF_STATUS_SUCCESS) 279 return A_ERROR; 280 281 /* store target type and target version info in hdd ctx */ 282 epping_ctx->target_type = tgt_info->target_type; 283 284 htc_info.pContext = NULL; 285 htc_info.TargetFailure = ol_target_failure; 286 htc_info.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, &htc_info, 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 epping_ctx->HTCHandle = 299 cds_get_context(QDF_MODULE_ID_HTC); 300 if (!epping_ctx->HTCHandle) { 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(epping_ctx->HTCHandle) != QDF_STATUS_SUCCESS) { 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(epping_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(epping_ctx->HTCHandle) != QDF_STATUS_SUCCESS) 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(epping_ctx); 333 if (ret < 0) { 334 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 335 "%s: cookie init failed", __func__); 336 htc_stop(epping_ctx->HTCHandle); 337 epping_cookie_cleanup(epping_ctx); 338 goto error_end; 339 } 340 341 EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Exit", __func__); 342 return ret; 343 344 error_end: 345 htc_destroy(p_cds_context->htc_ctx); 346 p_cds_context->htc_ctx = NULL; 347 bmi_cleanup(ol_ctx); 348 return A_ERROR; 349 } 350 351 void epping_enable_adapter(void) 352 { 353 epping_context_t *epping_ctx = g_epping_ctx; 354 tSirMacAddr adapter_macaddr; 355 356 if (!epping_ctx) { 357 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "epping context is NULL"); 358 return; 359 } 360 361 epping_get_dummy_mac_addr(adapter_macaddr); 362 epping_ctx->epping_adapter = epping_add_adapter(epping_ctx, 363 adapter_macaddr, 364 QDF_STA_MODE, true); 365 if (!epping_ctx->epping_adapter) 366 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "epping add adapter failed"); 367 } 368 #endif 369