diff options
| author | Arun Khandavalli <akhandav@codeaurora.org> | 2016-08-01 13:31:08 +0530 |
|---|---|---|
| committer | Arun Khandavalli <akhandav@codeaurora.org> | 2016-08-05 11:24:29 +0530 |
| commit | fae92945647176fdece9f45559e512ccb4583991 (patch) | |
| tree | 8d85e2c0ef9742efc61f8d3788df6b2cb9655118 | |
| parent | 1496fcb9bec8b36f7914e3c8ffdeddcf0a845cab (diff) | |
qcacld-3.0: Dynamic Mode changes
Currently MCL driver loads/unloads when user tries to
Switch On/Off from GUI and load process is different
for the static and dynamic built driver.
With this feature, we shall have a uniform behavior for
static and dynamic driver, where the driver will be
loaded once and unload never.
Mode switch for different modes is supported via sysfs entries.
Change-Id: Ica49dd289d7f1f0ad0c56af76bd7bcfeca433a2e
CRs-Fixed: 1049218
| -rw-r--r-- | core/cds/inc/cds_sched.h | 1 | ||||
| -rw-r--r-- | core/cds/src/cds_api.c | 91 | ||||
| -rw-r--r-- | core/cds/src/cds_concurrency.c | 7 | ||||
| -rw-r--r-- | core/cds/src/cds_sched.c | 1 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_cfg.h | 11 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_driver_ops.h | 5 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_ftm.h | 6 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_main.h | 37 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_memdump.h | 5 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_power.h | 2 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg.c | 11 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.c | 100 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_driver_ops.c | 89 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_ftm.c | 667 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_main.c | 1324 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_memdump.c | 8 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_power.c | 243 |
17 files changed, 1112 insertions, 1496 deletions
diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index 83cf40316412..0a269007a4fc 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -539,6 +539,7 @@ void cds_sched_deinit_mqs(p_cds_sched_context pSchedContext); void cds_sched_flush_mc_mqs(p_cds_sched_context pSchedContext); void qdf_timer_module_init(void); +void qdf_timer_module_deinit(void); void cds_ssr_protect_init(void); void cds_ssr_protect(const char *caller_func); void cds_ssr_unprotect(const char *caller_func); diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 4fd6f9a07e20..82ef025f51c5 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -198,13 +198,6 @@ QDF_STATUS cds_open(void) return QDF_STATUS_E_FAILURE; } - cds_cfg = cds_get_ini_config(); - if (!cds_cfg) { - cds_err("Cds config is NULL"); - QDF_ASSERT(0); - return QDF_STATUS_E_FAILURE; - } - /* Initialize the timer module */ qdf_timer_module_init(); @@ -245,25 +238,27 @@ QDF_STATUS cds_open(void) &(gp_cds_context->aMsgWrappers[iter])); } - /* Now Open the CDS Scheduler */ - qdf_status = cds_sched_open(gp_cds_context, &gp_cds_context->qdf_sched, - sizeof(cds_sched_context)); - - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + pHddCtx = (hdd_context_t *) (gp_cds_context->pHDDContext); + if ((NULL == pHddCtx) || (NULL == pHddCtx->config)) { /* Critical Error ... Cannot proceed further */ - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, - "%s: Failed to open CDS Scheduler", __func__); + cds_err("Hdd Context is Null"); QDF_ASSERT(0); goto err_msg_queue; } + /* Now Open the CDS Scheduler */ - pHddCtx = (hdd_context_t *) (gp_cds_context->pHDDContext); - if ((NULL == pHddCtx) || (NULL == pHddCtx->config)) { - /* Critical Error ... Cannot proceed further */ - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, - "%s: Hdd Context is Null", __func__); - QDF_ASSERT(0); - goto err_sched_close; + if (pHddCtx->driver_status == DRIVER_MODULES_UNINITIALIZED) { + qdf_status = cds_sched_open(gp_cds_context, + &gp_cds_context->qdf_sched, + sizeof(cds_sched_context)); + + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + /* Critical Error ... Cannot proceed further */ + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, + "%s: Failed to open CDS Scheduler", __func__); + QDF_ASSERT(0); + goto err_msg_queue; + } } scn = cds_get_context(QDF_MODULE_ID_HIF); @@ -272,6 +267,17 @@ QDF_STATUS cds_open(void) "%s: scn is null!", __func__); goto err_sched_close; } + + hdd_update_config(pHddCtx); + cds_cfg = cds_get_ini_config(); + if (!cds_cfg) { + cds_err("Cds config is NULL"); + QDF_ASSERT(0); + goto err_sched_close; + } + hdd_enable_fastpath(pHddCtx->config, scn); + hdd_wlan_update_target_info(pHddCtx, scn); + ol_ctx = cds_get_context(QDF_MODULE_ID_BMI); /* Initialize BMI and Download firmware */ qdf_status = bmi_download_firmware(ol_ctx); @@ -280,7 +286,6 @@ QDF_STATUS cds_open(void) "BMI FIALED status:%d", qdf_status); goto err_bmi_close; } - htcInfo.pContext = ol_ctx; htcInfo.TargetFailure = ol_target_failure; htcInfo.TargetSendSuspendComplete = wma_target_suspend_acknowledge; @@ -338,6 +343,8 @@ QDF_STATUS cds_open(void) /* UMA is supported in hardware for performing the * frame translation 802.11 <-> 802.3 */ + cds_cfg->frame_xln_reqd = 1; + sirStatus = mac_open(&(gp_cds_context->pMACContext), gp_cds_context->pHDDContext, cds_cfg); @@ -454,8 +461,11 @@ QDF_STATUS cds_pre_enable(v_CONTEXT_t cds_context) } /* call Packetlog connect service */ - htt_pkt_log_init(gp_cds_context->pdev_txrx_ctx, scn); - pktlog_htc_attach(); + if (QDF_GLOBAL_FTM_MODE != cds_get_conparam() && + QDF_GLOBAL_EPPING_MODE != cds_get_conparam()) { + htt_pkt_log_init(gp_cds_context->pdev_txrx_ctx, scn); + pktlog_htc_attach(); + } /* Reset wma wait event */ qdf_event_reset(&gp_cds_context->wmaCompleteEvent); @@ -653,18 +663,12 @@ err_wma_stop: QDF_STATUS cds_disable(v_CONTEXT_t cds_context) { QDF_STATUS qdf_status; - - /* wma_stop is called before the SYS so that the processing of target - * pending responses will not be handled during uninitialization of - * WLAN driver - */ - qdf_event_reset(&(gp_cds_context->wmaCompleteEvent)); + void *handle; qdf_status = wma_stop(cds_context, HAL_STOP_TYPE_RF_KILL); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to stop wma", __func__); + cds_err("Failed to stop wma"); QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); wma_setneedshutdown(cds_context); } @@ -672,15 +676,23 @@ QDF_STATUS cds_disable(v_CONTEXT_t cds_context) hif_disable_isr(((cds_context_type *) cds_context)->pHIFContext); hif_reset_soc(((cds_context_type *) cds_context)->pHIFContext); - /* SYS STOP will stop SME and MAC */ - qdf_status = sys_stop(cds_context); + handle = cds_get_context(QDF_MODULE_ID_PE); + if (!handle) { + cds_err("Invalid PE context return!"); + return QDF_STATUS_E_INVAL; + } + qdf_status = sme_stop(handle, HAL_STOP_TYPE_SYS_DEEP_SLEEP); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to stop SYS", __func__); + cds_err("Failed to stop SME: %d", qdf_status); QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); } + qdf_status = mac_stop(handle, HAL_STOP_TYPE_SYS_DEEP_SLEEP); - return QDF_STATUS_SUCCESS; + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + cds_err("Failed to stop MAC"); + QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); + } + return qdf_status; } /** @@ -762,10 +774,9 @@ QDF_STATUS cds_close(v_CONTEXT_t cds_context) } cds_deinit_log_completion(); - - gp_cds_context->pHDDContext = NULL; - cds_deinit_ini_config(); + qdf_timer_module_deinit(); + return QDF_STATUS_SUCCESS; } diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index ad89f6df623f..de14e62b8e56 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3918,6 +3918,13 @@ QDF_STATUS cds_deinit_policy_mgr(void) cds_err("Invalid CDS Context"); return QDF_STATUS_E_FAILURE; } + + if (!QDF_IS_STATUS_SUCCESS(qdf_event_destroy + (&cds_ctx->connection_update_done_evt))) { + cds_err("Failed to destroy connection_update_done_evt"); + return QDF_STATUS_E_FAILURE; + } + if (!QDF_IS_STATUS_SUCCESS(qdf_mutex_destroy( &cds_ctx->qdf_conc_list_lock))) { cds_err("Failed to destroy qdf_conc_list_lock"); diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index d452b7ede1b2..08cebb9feb53 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -1176,6 +1176,7 @@ QDF_STATUS cds_sched_close(void *p_cds_context) cds_drop_rxpkt_by_staid(gp_cds_sched_context, WLAN_MAX_STA_COUNT); cds_free_ol_rx_pkt_freeq(gp_cds_sched_context); unregister_hotcpu_notifier(&cds_cpu_hotplug_notifier); + gp_cds_sched_context->cpu_hot_plug_notifier = NULL; #endif return QDF_STATUS_SUCCESS; } /* cds_sched_close() */ diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 788827a0a760..c8c4ccea759e 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -248,6 +248,16 @@ typedef enum { #define CFG_ROAM_PREFER_5GHZ_DEFAULT (1) /* + * Timer waiting for interface up from the upper layer. If + * this timer expires all the cds modules shall be closed. + * Time Units: ms + */ +#define CFG_INTERFACE_CHANGE_WAIT_NAME "gInterfaceChangeWait" +#define CFG_INTERFACE_CHANGE_WAIT_MIN (10) +#define CFG_INTERFACE_CHANGE_WAIT_MAX (10000) +#define CFG_INTERFACE_CHANGE_WAIT_DEFAULT (50) + +/* To enable, set gRoamIntraBand=1 (Roaming within band) To disable, set gRoamIntraBand=0 (Roaming across band) */ @@ -4047,6 +4057,7 @@ struct hdd_config { bool enable_nan_datapath; uint8_t nan_datapath_ndi_channel; #endif + uint32_t iface_change_wait_time; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/inc/wlan_hdd_driver_ops.h b/core/hdd/inc/wlan_hdd_driver_ops.h index 70e2b7d8f393..3ea44449b55c 100644 --- a/core/hdd/inc/wlan_hdd_driver_ops.h +++ b/core/hdd/inc/wlan_hdd_driver_ops.h @@ -28,6 +28,8 @@ #ifndef __WLAN_HDD_DRIVER_OPS_H__ #define __WLAN_HDD_DRIVER_OPS_H__ +#include "hif.h" + /** * DOC: wlan_hdd_driver_ops.h * @@ -37,4 +39,7 @@ int wlan_hdd_register_driver(void); void wlan_hdd_unregister_driver(void); int wlan_hdd_bus_suspend(pm_message_t state); int wlan_hdd_bus_resume(void); +void hdd_hif_close(void *hif_ctx); +int hdd_hif_open(struct device *dev, void *bdev, const hif_bus_id *bid, + enum qdf_bus_type bus_type, bool reinit); #endif /* __WLAN_HDD_DRIVER_OPS_H__ */ diff --git a/core/hdd/inc/wlan_hdd_ftm.h b/core/hdd/inc/wlan_hdd_ftm.h index eddce28f6131..878a22e08d53 100644 --- a/core/hdd/inc/wlan_hdd_ftm.h +++ b/core/hdd/inc/wlan_hdd_ftm.h @@ -55,15 +55,11 @@ struct wlan_hdd_ftm_status { enum wlan_hdd_ftm_state ftm_state; }; -int wlan_hdd_ftm_open(hdd_context_t *hdd_ctx); -int wlan_hdd_ftm_close(hdd_context_t *hdd_ctx); int hdd_update_cds_config_ftm(hdd_context_t *hdd_ctx); - +void hdd_ftm_mc_process_msg(void *message); #if defined(QCA_WIFI_FTM) QDF_STATUS wlan_hdd_ftm_testmode_cmd(void *data, int len); int wlan_hdd_qcmbr_unified_ioctl(hdd_adapter_t *adapter, struct ifreq *ifr); -int hdd_ftm_start(hdd_context_t *hdd_ctx); -int hdd_ftm_stop(hdd_context_t *hdd_ctx); #endif #endif diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index cffdf54cb6e4..4fbec9b7dfbc 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1184,6 +1184,20 @@ struct hdd_bpf_context { struct sir_bpf_get_offload capability_response; }; +/** + * enum driver_status: Driver Modules status + * @DRIVER_MODULES_UNINITIALIZED: Driver CDS modules uninitialized + * @DRIVER_MODULES_OPENED: Driver CDS modules opened + * @DRIVER_MODULES_ENABLED: Driver CDS modules opened + * @DRIVER_MODULES_CLOSED: Driver CDS modules closed + */ +enum driver_modules_status { + DRIVER_MODULES_UNINITIALIZED, + DRIVER_MODULES_OPENED, + DRIVER_MODULES_ENABLED, + DRIVER_MODULES_CLOSED +}; + /** Adapter structure definition */ struct hdd_context_s { @@ -1435,6 +1449,12 @@ struct hdd_context_s { #ifdef WLAN_FEATURE_NAN_DATAPATH bool nan_datapath_enabled; #endif + /* Present state of driver cds modules */ + enum driver_modules_status driver_status; + /* MC timer interface change */ + qdf_mc_timer_t iface_change_timer; + /* Interface change lock */ + struct mutex iface_change_lock; }; /*--------------------------------------------------------------------------- @@ -1539,7 +1559,7 @@ static inline void hdd_stop_bus_bw_computer_timer(hdd_adapter_t *pAdapter) int hdd_init(void); void hdd_deinit(void); -int hdd_wlan_startup(struct device *dev, void *hif_sc); +int hdd_wlan_startup(struct device *dev); void __hdd_wlan_exit(void); int hdd_wlan_notify_modem_power_state(int state); #ifdef QCA_HT_2040_COEX @@ -1746,6 +1766,21 @@ int hdd_register_cb(hdd_context_t *hdd_ctx); void hdd_deregister_cb(hdd_context_t *hdd_ctx); int hdd_start_station_adapter(hdd_adapter_t *adapter); int hdd_start_ap_adapter(hdd_adapter_t *adapter); +int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter); int hdd_start_ftm_adapter(hdd_adapter_t *adapter); int hdd_set_fw_params(hdd_adapter_t *adapter); +int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, + bool reinit); +int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown); +int hdd_start_adapter(hdd_adapter_t *adapter); +#ifdef WLAN_FEATURE_FASTPATH +void hdd_enable_fastpath(struct hdd_config *hdd_cfg, + void *context); +#else +static inline void hdd_enable_fastpath(struct hdd_config *hdd_cfg, + void *context) +{ +} +#endif +void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context); #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/inc/wlan_hdd_memdump.h b/core/hdd/inc/wlan_hdd_memdump.h index 2100768ef69b..48a609396bce 100644 --- a/core/hdd/inc/wlan_hdd_memdump.h +++ b/core/hdd/inc/wlan_hdd_memdump.h @@ -88,8 +88,11 @@ static inline int wlan_hdd_cfg80211_get_fw_mem_dump(struct wiphy *wiphy, { return -ENOTSUPP; } + + static inline void wlan_hdd_cfg80211_fw_mem_dump_cb(void *ctx, - struct fw_dump_rsp *dump_rsp) + struct fw_dump_rsp + *dump_rsp) { } #endif diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h index d872fae107ac..a57e9b6eec7f 100644 --- a/core/hdd/inc/wlan_hdd_power.h +++ b/core/hdd/inc/wlan_hdd_power.h @@ -145,7 +145,7 @@ enum suspend_resume_state { /* SSR shutdown & re-init functions */ QDF_STATUS hdd_wlan_shutdown(void); -QDF_STATUS hdd_wlan_re_init(void *hif_sc); +QDF_STATUS hdd_wlan_re_init(void); void hdd_conf_mcastbcast_filter(hdd_context_t *pHddCtx, bool setfilter); QDF_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, bool fenable); diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 4647ae303e3a..d214ef603e84 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3981,8 +3981,14 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_ADAPT_DWELL_WIFI_THRESH_DEFAULT, CFG_ADAPT_DWELL_WIFI_THRESH_MIN, CFG_ADAPT_DWELL_WIFI_THRESH_MAX), -}; + REG_VARIABLE(CFG_INTERFACE_CHANGE_WAIT_NAME, WLAN_PARAM_Integer, + struct hdd_config, iface_change_wait_time, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_INTERFACE_CHANGE_WAIT_DEFAULT, + CFG_INTERFACE_CHANGE_WAIT_MIN, + CFG_INTERFACE_CHANGE_WAIT_MAX), +}; /** * get_next_line() - find and locate the new line pointer @@ -5583,6 +5589,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) hdd_info("Name = [%s] Value = [%u]", CFG_IDLE_TIME_NAME, pHddCtx->config->idle_time_conc); + hdd_info("Name = [%s] Value = [%u]", + CFG_INTERFACE_CHANGE_WAIT_NAME, + pHddCtx->config->iface_change_wait_time); hdd_info("Name = [%s] Value = [%u]", CFG_ENABLE_EDCA_INI_NAME, diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 400fbe4320e4..0c6807b0ddee 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -481,16 +481,6 @@ static const struct ieee80211_iface_limit }; static struct ieee80211_iface_combination - wlan_hdd_mon_iface[] = { - { - .limits = wlan_hdd_mon_iface_limit, - .max_interfaces = 3, - .num_different_channels = 2, - .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit), - }, -}; - -static struct ieee80211_iface_combination wlan_hdd_iface_combination[] = { /* STA */ { @@ -567,6 +557,13 @@ static struct ieee80211_iface_combination .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit), .beacon_int_infra_match = true, }, + /* Monitor */ + { + .limits = wlan_hdd_mon_iface_limit, + .max_interfaces = 3, + .num_different_channels = 2, + .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit), + }, }; static struct cfg80211_ops wlan_hdd_cfg80211_ops; @@ -6965,35 +6962,28 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS; - if (cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE) { - /* Supports STATION & AD-HOC modes right now */ - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) - | BIT(NL80211_IFTYPE_ADHOC) - | BIT(NL80211_IFTYPE_P2P_CLIENT) - | BIT(NL80211_IFTYPE_P2P_GO) - | BIT(NL80211_IFTYPE_AP); - - if (pCfg->advertiseConcurrentOperation) { - if (pCfg->enableMCC) { - int i; - - for (i = 0; - i < ARRAY_SIZE(wlan_hdd_iface_combination); - i++) { - if (!pCfg->allowMCCGODiffBI) - wlan_hdd_iface_combination[i]. - beacon_int_infra_match = true; - } + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) + | BIT(NL80211_IFTYPE_ADHOC) + | BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_AP) + | BIT(NL80211_IFTYPE_MONITOR); + + if (pCfg->advertiseConcurrentOperation) { + if (pCfg->enableMCC) { + int i; + + for (i = 0; + i < ARRAY_SIZE(wlan_hdd_iface_combination); + i++) { + if (!pCfg->allowMCCGODiffBI) + wlan_hdd_iface_combination[i]. + beacon_int_infra_match = true; } - wiphy->n_iface_combinations = - ARRAY_SIZE(wlan_hdd_iface_combination); - wiphy->iface_combinations = wlan_hdd_iface_combination; } - } else { - wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR); wiphy->n_iface_combinations = - ARRAY_SIZE(wlan_hdd_mon_iface); - wiphy->iface_combinations = wlan_hdd_mon_iface; + ARRAY_SIZE(wlan_hdd_iface_combination); + wiphy->iface_combinations = wlan_hdd_iface_combination; } /* Before registering we need to update the ht capabilitied based @@ -7648,6 +7638,12 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, hdd_notice("Device_mode = %d, IFTYPE = 0x%x", pAdapter->device_mode, type); + status = hdd_wlan_start_modules(pHddCtx, pAdapter, false); + if (status) { + hdd_err("Failed to start modules"); + return -EINVAL; + } + if (!cds_allow_concurrency( wlan_hdd_convert_nl_iftype_to_hdd_type(type), 0, HW_MODE_20_MHZ)) { @@ -7687,15 +7683,6 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, if (vstatus != QDF_STATUS_SUCCESS) return -EINVAL; - /* - * for ibss interface type flow control is not required - * so don't register tx flow control - */ - if (type != NL80211_IFTYPE_ADHOC) - hdd_register_tx_flow_control(pAdapter, - hdd_tx_resume_timer_expired_handler, - hdd_tx_resume_cb); - goto done; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: @@ -7710,8 +7697,8 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, wlan_hdd_cancel_existing_remain_on_channel (pAdapter); } - hdd_stop_adapter(pHddCtx, pAdapter, true); + hdd_stop_adapter(pHddCtx, pAdapter, true); /* De-init the adapter */ hdd_deinit_adapter(pHddCtx, pAdapter, true); memset(&pAdapter->sessionCtx, 0, @@ -7744,16 +7731,10 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, hdd_set_ap_ops(pAdapter->dev); - vstatus = hdd_init_ap_mode(pAdapter); - if (vstatus != QDF_STATUS_SUCCESS) { - hdd_alert("Error initializing the ap mode"); + if (hdd_start_adapter(pAdapter)) { + hdd_err("Error initializing the ap mode"); return -EINVAL; } - - hdd_register_tx_flow_control(pAdapter, - hdd_softap_tx_resume_timer_expired_handler, - hdd_softap_tx_resume_cb); - /* Interface type changed update in wiphy structure */ if (wdev) { wdev->iftype = type; @@ -7780,13 +7761,6 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, if (status != QDF_STATUS_SUCCESS) return status; - if ((NL80211_IFTYPE_P2P_CLIENT == type) || - (NL80211_IFTYPE_STATION == type)) { - - hdd_register_tx_flow_control(pAdapter, - hdd_tx_resume_timer_expired_handler, - hdd_tx_resume_cb); - } goto done; case NL80211_IFTYPE_AP: @@ -7794,10 +7768,6 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, wdev->iftype = type; pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ? QDF_SAP_MODE : QDF_P2P_GO_MODE; - - hdd_register_tx_flow_control(pAdapter, - hdd_softap_tx_resume_timer_expired_handler, - hdd_softap_tx_resume_cb); goto done; default: diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index e1843e831519..2f9ef28f03fb 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -210,7 +210,7 @@ static enum qdf_bus_type to_bus_type(enum pld_bus_type bus_type) * * Return: 0 on success and errno on failure. */ -static int hdd_hif_open(struct device *dev, void *bdev, const hif_bus_id *bid, +int hdd_hif_open(struct device *dev, void *bdev, const hif_bus_id *bid, enum qdf_bus_type bus_type, bool reinit) { QDF_STATUS status; @@ -255,6 +255,8 @@ static int hdd_hif_open(struct device *dev, void *bdev, const hif_bus_id *bid, } } + hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled()); + return 0; err_hif_close: @@ -269,11 +271,13 @@ err_hif_close: * * Helper function to close HIF */ -static void hdd_hif_close(void *hif_ctx) +void hdd_hif_close(void *hif_ctx) { if (hif_ctx == NULL) return; + hif_disable_power_management(hif_ctx); + hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE); hdd_napi_destroy(true); @@ -286,11 +290,13 @@ static void hdd_hif_close(void *hif_ctx) * hdd_init_qdf_ctx() - API to initialize global QDF Device structure * @dev: Device Pointer * @bdev: Bus Device pointer + * @bus_type: Underlying bus type + * @bid: Bus id passed by platform driver * * Return: void */ void hdd_init_qdf_ctx(struct device *dev, void *bdev, - enum qdf_bus_type bus_type) + enum qdf_bus_type bus_type, const struct hif_bus_id *bid) { qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); @@ -302,6 +308,7 @@ void hdd_init_qdf_ctx(struct device *dev, void *bdev, qdf_dev->dev = dev; qdf_dev->drv_hdl = bdev; qdf_dev->bus_type = bus_type; + qdf_dev->bid = bid; } /** @@ -320,11 +327,7 @@ void hdd_init_qdf_ctx(struct device *dev, void *bdev, static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, enum qdf_bus_type bus_type, bool reinit) { - void *hif_ctx; - QDF_STATUS status; int ret = 0; - qdf_device_t qdf_dev; - uint32_t mode = cds_get_conparam(); pr_info("%s: %sprobing driver v%s\n", WLAN_MODULE_NAME, reinit ? "re-" : "", QWLAN_VERSIONSTR); @@ -349,42 +352,16 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, cds_set_load_in_progress(true); } - if (QDF_IS_EPPING_ENABLED(mode)) { - status = epping_open(); - if (status != QDF_STATUS_SUCCESS) - goto err_hdd_deinit; - } - - hdd_init_qdf_ctx(dev, bdev, bus_type); - - ret = hdd_hif_open(dev, bdev, bid, bus_type, reinit); - - if (ret) - goto err_epping_close; - - hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); - - if (NULL == hif_ctx) - goto err_epping_close; - - qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); - - status = ol_cds_init(qdf_dev, hif_ctx); - - if (status != QDF_STATUS_SUCCESS) { - pr_err("%s No Memory to Create BMI Context\n", __func__); - goto err_hif_close; - } + hdd_init_qdf_ctx(dev, bdev, bus_type, (const struct hif_bus_id *)bid); if (reinit) - ret = hdd_wlan_re_init(hif_ctx); + ret = hdd_wlan_re_init(); else - ret = hdd_wlan_startup(dev, hif_ctx); + ret = hdd_wlan_startup(dev); if (ret) - goto err_bmi_close; + goto err_hdd_deinit; - hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled()); if (reinit) { cds_set_recovery_in_progress(false); @@ -398,15 +375,12 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, return 0; -err_bmi_close: - ol_cds_free(); -err_hif_close: - hdd_hif_close(hif_ctx); -err_epping_close: - if (QDF_IS_EPPING_ENABLED(mode)) - epping_close(); + err_hdd_deinit: - cds_set_load_in_progress(false); + if (reinit) + cds_set_recovery_in_progress(false); + else + cds_set_load_in_progress(false); hdd_deinit(); out: hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); @@ -431,6 +405,7 @@ static void wlan_hdd_remove(struct device *dev) { void *hif_ctx; + pr_info("%s: Removing driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR); @@ -453,8 +428,6 @@ static void wlan_hdd_remove(struct device *dev) if (NULL == hif_ctx) return; - hif_disable_power_management(hif_ctx); - if (QDF_IS_EPPING_ENABLED(cds_get_conparam())) { epping_disable(); epping_close(); @@ -462,8 +435,6 @@ static void wlan_hdd_remove(struct device *dev) __hdd_wlan_exit(); } - ol_cds_free(); - hdd_hif_close(hif_ctx); hdd_deinit(); pr_info("%s: Driver Removed\n", WLAN_MODULE_NAME); @@ -495,9 +466,6 @@ static void wlan_hdd_shutdown(void) hif_disable_isr(hif_ctx); hdd_wlan_shutdown(); } - - ol_cds_free(); - hdd_hif_close(hif_ctx); } /** @@ -549,7 +517,7 @@ void wlan_hdd_notify_handler(int state) */ static int __wlan_hdd_bus_suspend(pm_message_t state) { - void *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); void *hif_ctx; int err = wlan_hdd_validate_context(hdd_ctx); int status; @@ -564,6 +532,12 @@ static int __wlan_hdd_bus_suspend(pm_message_t state) err = -EINVAL; goto done; } + + if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) { + hdd_info("Driver Module closed return success"); + return 0; + } + err = qdf_status_to_os_return( ol_txrx_bus_suspend()); if (err) @@ -627,13 +601,18 @@ int wlan_hdd_bus_suspend(pm_message_t state) */ static int __wlan_hdd_bus_resume(void) { - void *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); void *hif_ctx; int status = wlan_hdd_validate_context(hdd_ctx); if (status) return status; + if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) { + hdd_info("Driver Module closed return success"); + return 0; + } + hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); if (NULL == hif_ctx) return -EINVAL; @@ -682,7 +661,7 @@ int wlan_hdd_bus_resume(void) */ static int __wlan_hdd_runtime_suspend(struct device *dev) { - void *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); void *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX); void *htc_ctx = cds_get_context(QDF_MODULE_ID_HTC); diff --git a/core/hdd/src/wlan_hdd_ftm.c b/core/hdd/src/wlan_hdd_ftm.c index 97a0cd2754d6..a96090e35033 100644 --- a/core/hdd/src/wlan_hdd_ftm.c +++ b/core/hdd/src/wlan_hdd_ftm.c @@ -111,32 +111,6 @@ static uint32_t wlan_ftm_postmsg(uint8_t *cmd_ptr, uint16_t cmd_len) return QDF_STATUS_SUCCESS; } -/** - * wlan_hdd_ftm_update_tgt_cfg() - Update target configuration - * @context: context registered with WMA - * @param: target configuration - * - * This function is registered with WMA via wma_open(), and is - * invoked via callback when target parameters are received - * from firmware. - * - * Return: None - */ -static void wlan_hdd_ftm_update_tgt_cfg(void *context, void *param) -{ - hdd_context_t *hdd_ctx = (hdd_context_t *) context; - struct wma_tgt_cfg *cfg = (struct wma_tgt_cfg *)param; - - if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) { - hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr); - } else { - hddLog(QDF_TRACE_LEVEL_ERROR, - "%s: Invalid MAC passed from target, using MAC from ini file" - MAC_ADDRESS_STR, __func__, - MAC_ADDR_ARRAY(hdd_ctx->config->intfMacAddr[0].bytes)); - } -} - #ifdef WLAN_FEATURE_LPSS static inline void hdd_is_lpass_supported(struct cds_config_info *cds_cfg, hdd_context_t *hdd_ctx) @@ -180,544 +154,6 @@ int hdd_update_cds_config_ftm(hdd_context_t *hdd_ctx) return 0; } -/** - * wlan_ftm_cds_open() - Open the CDS Module in FTM mode - * @p_cds_context: pointer to the global CDS context - * @hddContextSize: Size of the HDD context to allocate. - * - * The wlan_ftm_cds_open() function opens the QDF Scheduler - * Upon successful initialization: - * - All CDS submodules should have been initialized - * - The CDS scheduler should have opened - * - All the WLAN SW components should have been opened. This includes MAC. - * - * Returns: - * QDF_STATUS_SUCCESS - Scheduler was successfully initialized and - * is ready to be used. - * QDF_STATUS_E_RESOURCES - System resources (other than memory) - * are unavailable to initialize the scheduler - * QDF_STATUS_E_FAILURE - Failure to initialize the scheduler - */ -static QDF_STATUS wlan_ftm_cds_open(v_CONTEXT_t p_cds_context, - uint32_t hddContextSize) -{ - QDF_STATUS vStatus = QDF_STATUS_SUCCESS; - int iter = 0; - tSirRetStatus sirStatus = eSIR_SUCCESS; - p_cds_contextType gp_cds_context = (p_cds_contextType) p_cds_context; - struct cds_config_info *cds_cfg; -#if defined(QCA_WIFI_FTM) - qdf_device_t qdf_ctx; - HTC_INIT_INFO htcInfo; - void *pHifContext = NULL; - void *pHtcContext = NULL; - struct ol_context *ol_ctx; -#endif - cds_context_type *cds_ctx; - hdd_context_t *hdd_ctx; - - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, - "%s: Opening CDS", __func__); - - cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); - if (!cds_ctx) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Trying to open CDS without a PreOpen", __func__); - QDF_ASSERT(0); - return QDF_STATUS_E_FAILURE; - } - - cds_cfg = cds_ctx->cds_cfg; - - /* Initialize the probe event */ - if (qdf_event_create(&gp_cds_context->ProbeEvent) != QDF_STATUS_SUCCESS) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Unable to init probeEvent", __func__); - QDF_ASSERT(0); - return QDF_STATUS_E_FAILURE; - } - - if (qdf_event_create(&(gp_cds_context->wmaCompleteEvent)) != - QDF_STATUS_SUCCESS) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Unable to init wmaCompleteEvent", __func__); - QDF_ASSERT(0); - - goto err_probe_event; - } - - /* Initialize the free message queue */ - vStatus = cds_mq_init(&gp_cds_context->freeVosMq); - if (!QDF_IS_STATUS_SUCCESS(vStatus)) { - - /* Critical Error ... Cannot proceed further */ - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to initialize CDS free message queue %d", - __func__, vStatus); - QDF_ASSERT(0); - goto err_wma_complete_event; - } - - for (iter = 0; iter < CDS_CORE_MAX_MESSAGES; iter++) { - (gp_cds_context->aMsgWrappers[iter]).pVosMsg = - &(gp_cds_context->aMsgBuffers[iter]); - INIT_LIST_HEAD(&gp_cds_context->aMsgWrappers[iter].msgNode); - cds_mq_put(&gp_cds_context->freeVosMq, - &(gp_cds_context->aMsgWrappers[iter])); - } - - /* Now Open the CDS Scheduler */ - vStatus = cds_sched_open(gp_cds_context, &gp_cds_context->qdf_sched, - sizeof(cds_sched_context)); - - if (!QDF_IS_STATUS_SUCCESS(vStatus)) { - /* Critical Error ... Cannot proceed further */ - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to open CDS Scheduler %d", __func__, - vStatus); - QDF_ASSERT(0); - goto err_msg_queue; - } -#if defined(QCA_WIFI_FTM) - /* Initialize BMI and Download firmware */ - pHifContext = cds_get_context(QDF_MODULE_ID_HIF); - if (!pHifContext) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, - "%s: failed to get HIF context", __func__); - goto err_sched_close; - } - - ol_ctx = cds_get_context(QDF_MODULE_ID_BMI); - if (bmi_download_firmware(ol_ctx)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, - "%s: BMI failed to download target", __func__); - goto err_bmi_close; - } - - htcInfo.pContext = ol_ctx; - htcInfo.TargetFailure = ol_target_failure; - htcInfo.TargetSendSuspendComplete = wma_target_suspend_acknowledge; - qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); - - /* Create HTC */ - gp_cds_context->htc_ctx = - htc_create(pHifContext, &htcInfo, qdf_ctx, hdd_get_conparam()); - if (!gp_cds_context->htc_ctx) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, - "%s: Failed to Create HTC", __func__); - goto err_bmi_close; - } - - if (bmi_done(ol_ctx)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, - "%s: Failed to complete BMI phase", __func__); - goto err_htc_close; - } -#endif /* QCA_WIFI_FTM */ - - hdd_ctx = (hdd_context_t *) (gp_cds_context->pHDDContext); - if ((NULL == hdd_ctx) || (NULL == hdd_ctx->config)) { - /* Critical Error ... Cannot proceed further */ - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Hdd Context is Null", __func__); - QDF_ASSERT(0); - goto err_htc_close; - } - vStatus = wma_open(gp_cds_context, - wlan_hdd_ftm_update_tgt_cfg, NULL, cds_cfg); - if (!QDF_IS_STATUS_SUCCESS(vStatus)) { - /* Critical Error ... Cannot proceed further */ - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to open WMA module %d", __func__, - vStatus); - QDF_ASSERT(0); - goto err_htc_close; - } -#if defined(QCA_WIFI_FTM) - hdd_update_config(hdd_ctx); - pHtcContext = cds_get_context(QDF_MODULE_ID_HTC); - if (!pHtcContext) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, - "%s: failed to get HTC context", __func__); - goto err_wma_close; - } - if (htc_wait_target(pHtcContext)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, - "%s: Failed to complete BMI phase", __func__); - goto err_wma_close; - } -#endif - - /* Now proceed to open the MAC */ - sirStatus = - mac_open(&(gp_cds_context->pMACContext), - gp_cds_context->pHDDContext, cds_cfg); - - if (eSIR_SUCCESS != sirStatus) { - /* Critical Error ... Cannot proceed further */ - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to open MAC %d", __func__, sirStatus); - QDF_ASSERT(0); - goto err_wma_close; - } -#ifndef QCA_WIFI_FTM - /* Now proceed to open the SME */ - vStatus = sme_open(gp_cds_context->pMACContext); - if (!QDF_IS_STATUS_SUCCESS(vStatus)) { - /* Critical Error ... Cannot proceed further */ - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to open SME %d", __func__, vStatus); - goto err_mac_close; - } - - vStatus = sme_init_chan_list(gp_cds_context->pMACContext, - hdd_ctx->reg.alpha2, hdd_ctx->reg.cc_src); - if (!QDF_IS_STATUS_SUCCESS(vStatus)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to init sme channel list", __func__); - } else { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, - "%s: CDS successfully Opened", __func__); - return QDF_STATUS_SUCCESS; - } -#else - return QDF_STATUS_SUCCESS; -#endif - -#ifndef QCA_WIFI_FTM -err_mac_close: -#endif - mac_close(gp_cds_context->pMACContext); - -err_wma_close: - wma_close(gp_cds_context); - -err_htc_close: -#if defined(QCA_WIFI_FTM) - if (gp_cds_context->htc_ctx) { - htc_destroy(gp_cds_context->htc_ctx); - gp_cds_context->htc_ctx = NULL; - } - -err_bmi_close: - bmi_cleanup(ol_ctx); -#endif /* QCA_WIFI_FTM */ - -err_sched_close: - cds_sched_close(gp_cds_context); -err_msg_queue: - cds_mq_deinit(&gp_cds_context->freeVosMq); - -err_wma_complete_event: - qdf_event_destroy(&gp_cds_context->wmaCompleteEvent); - -err_probe_event: - qdf_event_destroy(&gp_cds_context->ProbeEvent); - - return QDF_STATUS_E_FAILURE; - -} /* wlan_ftm_cds_open() */ - -/** - * wlan_ftm_cds_close() - Close the QDF Module in FTM mode - * @cds_context: context of cds - * - * The wlan_ftm_cds_close() function closes the QDF Module - * - * Return: QDF_STATUS_SUCCESS - successfully closed - */ -static QDF_STATUS wlan_ftm_cds_close(v_CONTEXT_t cds_context) -{ - QDF_STATUS qdf_status; - p_cds_contextType gp_cds_context = (p_cds_contextType) cds_context; - -#ifndef QCA_WIFI_FTM - qdf_status = sme_close(((p_cds_contextType) cds_context)->pMACContext); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to close SME %d", __func__, qdf_status); - QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); - } -#endif - - qdf_status = mac_close(((p_cds_contextType) cds_context)->pMACContext); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to close MAC %d", __func__, qdf_status); - QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); - } - - ((p_cds_contextType) cds_context)->pMACContext = NULL; - - - qdf_status = wma_close(cds_context); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to close WMA %d", __func__, qdf_status); - QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); - } -#if defined(QCA_WIFI_FTM) - if (gp_cds_context->htc_ctx) { - htc_stop(gp_cds_context->htc_ctx); - htc_destroy(gp_cds_context->htc_ctx); - gp_cds_context->htc_ctx = NULL; - } - qdf_status = wma_wmi_service_close(cds_context); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to close wma_wmi_service", __func__); - QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); - } - - hif_disable_isr(gp_cds_context->pHIFContext); -#endif - - cds_mq_deinit(&((p_cds_contextType) cds_context)->freeVosMq); - - qdf_status = qdf_event_destroy(&gp_cds_context->ProbeEvent); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to destroy ProbeEvent %d", __func__, - qdf_status); - QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); - } - - qdf_status = qdf_event_destroy(&gp_cds_context->wmaCompleteEvent); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to destroy wmaCompleteEvent %d", __func__, - qdf_status); - QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); - } - - return QDF_STATUS_SUCCESS; -} - -/** - * cds_ftm_pre_start() - Pre-start CDS Module in FTM Mode - * @cds_context: The CDS context - * - * The cds_ftm_pre_start() function performs all pre-start activities - * in FTM mode. - * - * Return: QDF_STATUS_SUCCESS if pre-start was successful, an - * appropriate QDF_STATUS_E_** error code otherwise - */ -static QDF_STATUS cds_ftm_pre_start(v_CONTEXT_t cds_context) -{ - QDF_STATUS vStatus = QDF_STATUS_SUCCESS; - QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; - p_cds_contextType p_cds_context = (p_cds_contextType) cds_context; -#if defined(QCA_WIFI_FTM) - p_cds_contextType gp_cds_context = - cds_get_global_context(); -#endif - - QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO, "cds prestart"); - if (NULL == p_cds_context->pWMAContext) { - QDF_ASSERT(0); - QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR, - "%s: WMA NULL context", __func__); - return QDF_STATUS_E_FAILURE; - } - - /* Reset WMA wait event */ - qdf_event_reset(&p_cds_context->wmaCompleteEvent); - - /*call WMA pre start */ - vStatus = wma_pre_start(p_cds_context); - if (!QDF_IS_STATUS_SUCCESS(vStatus)) { - QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR, - "Failed to WMA prestart "); - QDF_ASSERT(0); - return QDF_STATUS_E_FAILURE; - } - - /* Need to update time out of complete */ - qdf_status = qdf_wait_single_event(&p_cds_context->wmaCompleteEvent, - HDD_FTM_WMA_PRE_START_TIMEOUT); - if (qdf_status != QDF_STATUS_SUCCESS) { - if (qdf_status == QDF_STATUS_E_TIMEOUT) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Timeout occurred before WMA complete", - __func__); - } else { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: wma_pre_start reporting other error", - __func__); - } - QDF_ASSERT(0); - return QDF_STATUS_E_FAILURE; - } -#if defined(QCA_WIFI_FTM) - vStatus = htc_start(gp_cds_context->htc_ctx); - if (!QDF_IS_STATUS_SUCCESS(vStatus)) { - QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_FATAL, - "Failed to Start HTC"); - QDF_ASSERT(0); - return QDF_STATUS_E_FAILURE; - } - wma_wait_for_ready_event(gp_cds_context->pWMAContext); -#endif /* QCA_WIFI_FTM */ - - return QDF_STATUS_SUCCESS; -} - -/** - * wlan_hdd_ftm_open() - Open HDD in FTM Mode - * @hdd_ctx: global HDD context - * - * The function hdd_wlan_startup calls this function to initialize the - * FTM specific modules. - * - * Return: 0 on success, non-zero on error - */ -int wlan_hdd_ftm_open(hdd_context_t *hdd_ctx) -{ - QDF_STATUS vStatus = QDF_STATUS_SUCCESS; - p_cds_contextType p_cds_context = NULL; - - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO_HIGH, - "%s: Opening CDS", __func__); - - p_cds_context = cds_get_global_context(); - - if (NULL == p_cds_context) { - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, - "%s: Trying to open CDS without a PreOpen", __func__); - QDF_ASSERT(0); - goto err_qdf_status_failure; - } - - vStatus = wlan_ftm_cds_open(p_cds_context, 0); - - if (!QDF_IS_STATUS_SUCCESS(vStatus)) { - hddLog(QDF_TRACE_LEVEL_FATAL, "%s: cds_open failed", __func__); - goto err_qdf_status_failure; - } - - /* - * only needed to start WMA, which happens in wlan_hdd_ftm_start() - */ - - /* Save the hal context in Adapter */ - hdd_ctx->hHal = - (tHalHandle) cds_get_context(QDF_MODULE_ID_SME); - - if (NULL == hdd_ctx->hHal) { - hddLog(QDF_TRACE_LEVEL_ERROR, "%s: HAL context is null", - __func__); - goto err_ftm_close; - } - - return 0; - -err_ftm_close: - wlan_ftm_cds_close(p_cds_context); - -err_qdf_status_failure: - return -EPERM; -} - -/** - * hdd_ftm_service_registration() - Register FTM service - * @hdd_ctx: global HDD context - * - * Return: 0 on success, non-zero on failure - */ -static int hdd_ftm_service_registration(hdd_context_t *hdd_ctx) -{ - hdd_adapter_t *adapter; - adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d", - wlan_hdd_get_intf_addr(hdd_ctx), - NET_NAME_UNKNOWN, false); - if (NULL == adapter) { - hddLog(QDF_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", - __func__); - goto err_adapter_open_failure; - } - - hdd_ctx->ftm.ftm_state = WLAN_FTM_INITIALIZED; - - return 0; - -err_adapter_open_failure: - - return -EPERM; -} - -/** - * wlan_ftm_stop() - Stop HDD in FTM mode - * @hdd_ctx: pointer to HDD context - * - * This function stops the following modules - * WMA - * - * Return: 0 on success, non-zero on failure - */ -static int wlan_ftm_stop(hdd_context_t *hdd_ctx) -{ - if (hdd_ctx->ftm.ftm_state != WLAN_FTM_STARTED) { - hddLog(LOGP, FL("FTM has not started. No need to stop")); - return -EPERM; - } - wma_stop(hdd_ctx->pcds_context, HAL_STOP_TYPE_RF_KILL); - return 0; -} - -/** - * wlan_hdd_ftm_close() - Close HDD in FTM mode - * @hdd_ctx: pointer to HDD context - * - * Return: 0 on success, non-zero on failure - */ -int wlan_hdd_ftm_close(hdd_context_t *hdd_ctx) -{ - QDF_STATUS qdf_status; - v_CONTEXT_t cds_context = hdd_ctx->pcds_context; - - hdd_adapter_t *adapter = hdd_get_adapter(hdd_ctx, QDF_FTM_MODE); - ENTER(); - if (adapter == NULL) { - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_FATAL, - "%s:adapter is NULL", __func__); - return -ENXIO; - } - - if (WLAN_FTM_STARTED == hdd_ctx->ftm.ftm_state) { - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_FATAL, - "%s: Ftm has been started. stopping ftm", __func__); - wlan_ftm_stop(hdd_ctx); - } - - hdd_close_all_adapters(hdd_ctx, false); - - qdf_status = cds_sched_close(cds_context); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to close CDS Scheduler", __func__); - QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); - } - /* Close CDS */ - wlan_ftm_cds_close(cds_context); - -#if defined(QCA_WIFI_FTM) && defined(LINUX_QCMBR) - spin_lock_bh(&qcmbr_queue_lock); - if (!list_empty(&qcmbr_queue_head)) { - qcmbr_queue_t *msg_buf, *tmp_buf; - list_for_each_entry_safe(msg_buf, tmp_buf, &qcmbr_queue_head, - list) { - list_del(&msg_buf->list); - kfree(msg_buf); - } - } - spin_unlock_bh(&qcmbr_queue_lock); -#endif - - return 0; - -} - /** * hdd_ftm_mc_process_msg() - Process FTM mailbox message @@ -727,7 +163,7 @@ int wlan_hdd_ftm_close(hdd_context_t *hdd_ctx) * * Return: void */ -static void hdd_ftm_mc_process_msg(void *message) +void hdd_ftm_mc_process_msg(void *message) { void *data; uint32_t data_len; @@ -750,107 +186,6 @@ static void hdd_ftm_mc_process_msg(void *message) return; } -/** - * wlan_hdd_ftm_start() - Start HDD in FTM mode - * @hdd_ctx: Global HDD context - * - * This function starts the following modules. - * 1) WMA Start. - * 2) HTC Start. - * 3) MAC Start to download the firmware. - * - * Return: 0 for success, non zero for failure - */ -static int wlan_hdd_ftm_start(hdd_context_t *hdd_ctx) -{ - QDF_STATUS vStatus = QDF_STATUS_SUCCESS; - p_cds_contextType p_cds_context = - (p_cds_contextType) (hdd_ctx->pcds_context); - - if (WLAN_FTM_STARTED == hdd_ctx->ftm.ftm_state) { - return 0; - } - - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO, - "%s: Starting CLD SW", __func__); - - /* We support only one instance for now ... */ - if (p_cds_context == NULL) { - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, - "%s: mismatch in context", __func__); - goto err_status_failure; - } - - if (p_cds_context->pMACContext == NULL) { - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, - "%s: MAC NULL context", __func__); - goto err_status_failure; - } - - /* Vos preStart is calling */ - if (!QDF_IS_STATUS_SUCCESS(cds_ftm_pre_start(hdd_ctx->pcds_context))) { - hddLog(QDF_TRACE_LEVEL_FATAL, "%s: cds_pre_enable failed", - __func__); - goto err_status_failure; - } - - sme_register_ftm_msg_processor(hdd_ctx->hHal, hdd_ftm_mc_process_msg); - - vStatus = wma_start(p_cds_context); - if (vStatus != QDF_STATUS_SUCCESS) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, - "%s: Failed to start WMA", __func__); - goto err_status_failure; - } - - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO, - "%s: MAC correctly started", __func__); - - if (hdd_ftm_service_registration(hdd_ctx)) { - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, - "%s: failed", __func__); - goto err_ftm_service_reg; - } - - hdd_ctx->ftm.ftm_state = WLAN_FTM_STARTED; - - return 0; - -err_ftm_service_reg: - wlan_hdd_ftm_close(hdd_ctx); - -err_status_failure: - - return -EPERM; - -} - -#if defined(QCA_WIFI_FTM) -/** - * hdd_ftm_start() - Start HDD in FTM mode - * @hdd_ctx: Global HDD context - * - * Return: 0 for success, non zero for failure - */ -int hdd_ftm_start(hdd_context_t *hdd_ctx) -{ - return wlan_hdd_ftm_start(hdd_ctx); -} -#endif - -#if defined(QCA_WIFI_FTM) -/** - * hdd_ftm_stop() - Stop HDD in FTM mode - * @hdd_ctx: Global HDD context - * - * Return: 0 for success, non zero for failure - */ -int hdd_ftm_stop(hdd_context_t *hdd_ctx) -{ - return wlan_ftm_stop(hdd_ctx); -} -#endif - #if defined(QCA_WIFI_FTM) #if defined(LINUX_QCMBR) /** diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c2f2666f95d0..73fc47efc146 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -36,6 +36,7 @@ #include <wlan_hdd_includes.h> #include <cds_api.h> #include <cds_sched.h> +#include <linux/cpu.h> #ifdef WLAN_FEATURE_LPSS #include <cds_utils.h> #endif @@ -124,6 +125,28 @@ #define MEMORY_DEBUG_STR "" #endif +#ifndef MODULE +static struct gwlan_loader *wlan_loader; +static ssize_t wlan_boot_cb(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count); +struct gwlan_loader { + bool loaded_state; + struct kobject *boot_wlan_obj; + struct attribute_group *attr_group; +}; + +static struct kobj_attribute wlan_boot_attribute = + __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb); + +static struct attribute *attrs[] = { + &wlan_boot_attribute.attr, + NULL, +}; + +#define MODULE_INITIALIZED 1 +#endif + /* the Android framework expects this param even though we don't use it */ #define BUF_LEN 20 static char fwpath_buffer[BUF_LEN]; @@ -136,10 +159,6 @@ static char *country_code; static int enable_11d = -1; static int enable_dfs_chan_scan = -1; -#ifndef MODULE -static int wlan_hdd_inited; -#endif - /* * spinlock for synchronizing asynchronous request/response * (full description of use in wlan_hdd_main.h) @@ -1526,6 +1545,208 @@ int hdd_mon_open(struct net_device *dev) } /** + * hdd_start_adapter() - Wrapper function for device specific adapter + * @adapter: pointer to HDD adapter + * + * This function is called to start the device specific adapter for + * the mode passed in the adapter's device_mode. + * + * Return: 0 for success; non-zero for failure + */ +int hdd_start_adapter(hdd_adapter_t *adapter) +{ + + int ret; + enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode; + + ENTER_DEV(adapter->dev); + hdd_info("Start_adapter for mode : %d", adapter->device_mode); + + switch (device_mode) { + case QDF_P2P_CLIENT_MODE: + case QDF_P2P_DEVICE_MODE: + case QDF_OCB_MODE: + case QDF_STA_MODE: + case QDF_MONITOR_MODE: + ret = hdd_start_station_adapter(adapter); + if (ret) + goto err_start_adapter; + break; + case QDF_P2P_GO_MODE: + case QDF_SAP_MODE: + ret = hdd_start_ap_adapter(adapter); + if (ret) + goto err_start_adapter; + break; + case QDF_FTM_MODE: + ret = hdd_start_ftm_adapter(adapter); + if (ret) + goto err_start_adapter; + break; + default: + hdd_err("Invalid session type %d", device_mode); + QDF_ASSERT(0); + goto err_start_adapter; + } + if (hdd_set_fw_params(adapter)) + hdd_err("Failed to set the FW params for the adapter!"); + + /* + * Action frame registered in one adapter which will + * applicable to all interfaces + */ + wlan_hdd_cfg80211_register_frames(adapter); + EXIT(); + return 0; +err_start_adapter: + return -EINVAL; +} + +/** + * hdd_wlan_start_modules() - Single driver state machine for starting modules + * @hdd_ctx: HDD context + * @adapter: HDD adapter + * @reinit: flag to indicate from SSR or normal path + * + * This function maintains the driver state machine it will be invoked from + * startup, reinit and change interface. Depending on the driver state shall + * perform the opening of the modules. + * + * Return: 0 for success; non-zero for failure + */ +int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, + bool reinit) +{ + int ret; + qdf_device_t qdf_dev; + QDF_STATUS status; + p_cds_contextType p_cds_context; + bool unint = false; + void *hif_ctx; + + ENTER(); + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + hdd_err("Global Context is NULL"); + QDF_ASSERT(0); + return -EINVAL; + } + + hdd_info("start modules called in state! :%d reinit: %d", + hdd_ctx->driver_status, reinit); + + qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); + if (!qdf_dev) { + hdd_err("QDF Device Context is Invalid return"); + return -EINVAL; + } + + mutex_lock(&hdd_ctx->iface_change_lock); + + if (QDF_TIMER_STATE_RUNNING == + qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) { + + hdd_set_idle_ps_config(hdd_ctx, false); + hdd_info("Interface change Timer running Stop timer"); + qdf_mc_timer_stop(&hdd_ctx->iface_change_timer); + } + + switch (hdd_ctx->driver_status) { + case DRIVER_MODULES_UNINITIALIZED: + unint = true; + /* Fall through dont add break here */ + case DRIVER_MODULES_CLOSED: + if (!reinit && !unint) { + ret = pld_power_on(qdf_dev->dev); + if (ret) { + hdd_err("Failed to Powerup the device: %d", ret); + goto release_lock; + } + } + ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid, + qdf_dev->bus_type, + (reinit == true) ? HIF_ENABLE_TYPE_REINIT : + HIF_ENABLE_TYPE_PROBE); + if (ret) { + hdd_err("Failed to open hif: %d", ret); + goto power_down; + } + + hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); + status = ol_cds_init(qdf_dev, hif_ctx); + if (status != QDF_STATUS_SUCCESS) { + hdd_err("No Memory to Create BMI Context :%d", status); + goto hif_close; + } + + status = cds_open(); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("Failed to Open CDS: %d", status); + goto ol_cds_free; + } + + hdd_ctx->driver_status = DRIVER_MODULES_OPENED; + + hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME); + + status = cds_pre_enable(hdd_ctx->pcds_context); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("Failed to pre-enable CDS: %d", status); + goto close; + } + + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { + sme_register_ftm_msg_processor(hdd_ctx->hHal, + hdd_ftm_mc_process_msg); + break; + } + if (unint) { + hdd_info("In phase-1 initialization don't enable modules"); + break; + } + /* Fall through dont add break here */ + case DRIVER_MODULES_OPENED: + if (!adapter) { + hdd_alert("adapter is Null"); + goto close; + } + if (hdd_configure_cds(hdd_ctx, adapter)) { + hdd_err("Failed to Enable cds modules"); + goto close; + } + hdd_info("Driver Modules Successfully Enabled"); + hdd_ctx->driver_status = DRIVER_MODULES_ENABLED; + break; + case DRIVER_MODULES_ENABLED: + hdd_info("Driver modules already Enabled"); + break; + default: + hdd_err("WLAN start invoked in wrong state! :%d\n", + hdd_ctx->driver_status); + goto release_lock; + } + mutex_unlock(&hdd_ctx->iface_change_lock); + EXIT(); + return 0; + +close: + cds_close(p_cds_context); + +ol_cds_free: + ol_cds_free(); + +hif_close: + hdd_hif_close(p_cds_context->pHIFContext); +power_down: + if (!reinit && !unint) + pld_power_off(qdf_dev->dev); +release_lock: + mutex_unlock(&hdd_ctx->iface_change_lock); + return -EINVAL; +} + +/** * __hdd_open() - HDD Open function * @dev: Pointer to net_device structure * @@ -1542,25 +1763,42 @@ static int __hdd_open(struct net_device *dev) ENTER_DEV(dev); MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST, - adapter->sessionId, adapter->device_mode)); + adapter->sessionId, adapter->device_mode)); ret = wlan_hdd_validate_context(hdd_ctx); if (ret) return ret; + ret = hdd_wlan_start_modules(hdd_ctx, adapter, false); + if (ret) { + hdd_err("Failed to start WLAN modules return"); + return -ret; + } + + + if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) { + ret = hdd_start_adapter(adapter); + if (ret) { + hdd_err("Failed to start adapter :%d", + adapter->device_mode); + return ret; + } + } + set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags); if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { - hddLog(LOG1, FL("Enabling Tx Queues")); + hdd_info("Enabling Tx Queues"); /* Enable TX queues only when we are connected */ wlan_hdd_netif_queue_control(adapter, - WLAN_START_ALL_NETIF_QUEUE, - WLAN_CONTROL_PATH); + WLAN_START_ALL_NETIF_QUEUE, + WLAN_CONTROL_PATH); } return ret; } + /** * hdd_open() - Wrapper function for __hdd_open to protect it from SSR * @dev: Pointer to net_device structure @@ -1592,7 +1830,10 @@ static int __hdd_stop(struct net_device *dev) { hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_adapter_list_node_t *adapternode = NULL, *next = NULL; int ret; + bool close_modules = true; + QDF_STATUS status; ENTER_DEV(dev); @@ -1632,11 +1873,36 @@ static int __hdd_stop(struct net_device *dev) * Notice that the hdd_stop_adapter is requested not to close the session * That is intentional to be able to scan if it is a STA/P2P interface */ - hdd_stop_adapter(hdd_ctx, adapter, false); + hdd_stop_adapter(hdd_ctx, adapter, true); /* DeInit the adapter. This ensures datapath cleanup as well */ hdd_deinit_adapter(hdd_ctx, adapter, true); + + /* + * Find if any iface is up. If any iface is up then can't put device to + * sleep/power save mode + */ + status = hdd_get_front_adapter(hdd_ctx, &adapternode); + while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) { + if (test_bit(DEVICE_IFACE_OPENED, + &adapternode->pAdapter->event_flags)) { + hdd_info("Still other ifaces are up cannot close modules"); + close_modules = false; + break; + } + status = hdd_get_next_adapter(hdd_ctx, adapternode, &next); + adapternode = next; + + } + + if (close_modules) { + hdd_info("Closing all modules from the hdd_stop"); + qdf_mc_timer_start(&hdd_ctx->iface_change_timer, + hdd_ctx->config->iface_change_wait_time + * 50000); + } + EXIT(); return 0; } @@ -2537,30 +2803,32 @@ static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx, uint32_t value = 0; int ret; - /* Enable FW logs based on INI configuration */ - if ((QDF_GLOBAL_FTM_MODE == cds_get_conparam() || - (!hdd_ctx->config->enable_fw_log))) { + if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() || + (!hdd_ctx->config->enable_fw_log)) { hdd_info("enable_fw_log not enabled in INI or in FTM mode return"); return; } + /* Enable FW logs based on INI configuration */ hdd_ctx->fw_log_settings.dl_type = hdd_ctx->config->enableFwLogType; ret = wma_cli_set_command(adapter->sessionId, - WMI_DBGLOG_TYPE, - hdd_ctx->config->enableFwLogType, - DBG_CMD); - if (ret) - hdd_err("Failed to enable FW log type ret %d", ret); + WMI_DBGLOG_TYPE, + hdd_ctx->config->enableFwLogType, + DBG_CMD); + if (ret != 0) + hdd_err("Failed to enable FW log type ret %d", + ret); hdd_ctx->fw_log_settings.dl_loglevel = - hdd_ctx->config->enableFwLogLevel; + hdd_ctx->config->enableFwLogLevel; ret = wma_cli_set_command(adapter->sessionId, - WMI_DBGLOG_LOG_LEVEL, - hdd_ctx->config->enableFwLogLevel, - DBG_CMD); - if (ret) - hdd_err("Failed to enable FW log level ret %d", ret); + WMI_DBGLOG_LOG_LEVEL, + hdd_ctx->config->enableFwLogLevel, + DBG_CMD); + if (ret != 0) + hdd_err("Failed to enable FW log level ret %d", + ret); hdd_string_to_u8_array( hdd_ctx->config->enableFwModuleLogLevel, @@ -2587,21 +2855,21 @@ static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx, * For FW module ID 7 enable log level 6 */ - /* - * FW expects WMI command value = + /* FW expects WMI command value = * Module ID * 10 + Module Log level */ value = ((moduleloglevel[count] * 10) + moduleloglevel[count + 1]); ret = wma_cli_set_command(adapter->sessionId, - WMI_DBGLOG_MOD_LOG_LEVEL, - value, DBG_CMD); - if (ret) + WMI_DBGLOG_MOD_LOG_LEVEL, + value, DBG_CMD); + if (ret != 0) hdd_err("Failed to enable FW module log level %d ret %d", value, ret); count += 2; } + } #else static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx, @@ -2631,12 +2899,11 @@ int hdd_set_fw_params(hdd_adapter_t *adapter) if (!hdd_ctx) return -EINVAL; - if ((QDF_GLOBAL_FTM_MODE == cds_get_conparam() || - (!hdd_ctx->config->enable2x2))) { + if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) || + (!hdd_ctx->config->enable2x2)) { hdd_info("enable2x2 not enabled in INI or in FTM mode return"); return 0; } - #define HDD_DTIM_1CHAIN_RX_ID 0x5 #define HDD_SMPS_PARAM_VALUE_S 29 @@ -2677,22 +2944,24 @@ int hdd_set_fw_params(hdd_adapter_t *adapter) } #undef HDD_DTIM_1CHAIN_RX_ID #undef HDD_SMPS_PARAM_VALUE_S - - ret = wma_cli_set_command(adapter->sessionId, - WMI_PDEV_PARAM_HYST_EN, - hdd_ctx->config->enableMemDeepSleep, - PDEV_CMD); - - if (ret != 0) { - hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d", - ret); - goto error; + if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) { + ret = wma_cli_set_command(adapter->sessionId, + WMI_PDEV_PARAM_HYST_EN, + hdd_ctx->config->enableMemDeepSleep, + PDEV_CMD); + + if (ret) { + hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d", + ret); + goto error; + } } hdd_set_fw_log_params(hdd_ctx, adapter); EXIT(); return 0; + error: return -EINVAL; } @@ -2721,37 +2990,29 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, hdd_adapter_list_node_t *pHddAdapterNode = NULL; QDF_STATUS status = QDF_STATUS_E_FAILURE; hdd_cfg80211_state_t *cfgState; - int ret; - hddLog(LOG2, FL("iface(%s) type(%d)"), iface_name, session_type); + hdd_info("iface(%s) type(%d)", iface_name, session_type); if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) { /* * Max limit reached on the number of vdevs configured by the * host. Return error */ - hddLog(QDF_TRACE_LEVEL_ERROR, - FL( - "Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d" - ), - hdd_ctx->current_intf_count, hdd_ctx->max_intf_count); + hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d", + hdd_ctx->current_intf_count, hdd_ctx->max_intf_count); return NULL; } if (macAddr == NULL) { /* Not received valid macAddr */ - hddLog(QDF_TRACE_LEVEL_ERROR, - FL( - "Unable to add virtual intf: Not able to get valid mac address" - )); + hdd_err("Unable to add virtual intf: Not able to get valid mac address"); return NULL; } status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr); if (QDF_STATUS_E_FAILURE == status) { - hddLog(QDF_TRACE_LEVEL_ERROR, - "Duplicate MAC addr: " MAC_ADDRESS_STR - " already exists", - MAC_ADDR_ARRAY(macAddr)); + hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR + " already exists", + MAC_ADDR_ARRAY(macAddr)); return NULL; } @@ -2763,17 +3024,14 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, case QDF_P2P_CLIENT_MODE: case QDF_P2P_DEVICE_MODE: case QDF_OCB_MODE: - case QDF_MONITOR_MODE: case QDF_NDI_MODE: - { adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr, name_assign_type, iface_name); if (NULL == adapter) { - hddLog(QDF_TRACE_LEVEL_FATAL, - FL("failed to allocate adapter for session %d"), - session_type); + hdd_err("failed to allocate adapter for session %d", + session_type); return NULL; } @@ -2781,8 +3039,6 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; else if (QDF_P2P_DEVICE_MODE == session_type) adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE; - else if (QDF_MONITOR_MODE == session_type) - adapter->wdev.iftype = NL80211_IFTYPE_MONITOR; else adapter->wdev.iftype = NL80211_IFTYPE_STATION; @@ -2792,10 +3048,6 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, status = hdd_init_nan_data_mode(adapter); if (QDF_STATUS_SUCCESS != status) goto err_free_netdev; - } else { - ret = hdd_start_station_adapter(adapter); - if (ret) - goto err_free_netdev; } hdd_lro_enable(hdd_ctx, adapter); @@ -2822,28 +3074,21 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, } /* Stop the Interface TX queue. */ - hddLog(LOG1, FL("Disabling queues")); + hdd_info("Disabling queues"); wlan_hdd_netif_queue_control(adapter, - WLAN_NETIF_TX_DISABLE_N_CARRIER, - WLAN_CONTROL_PATH); - - hdd_register_tx_flow_control(adapter, - hdd_tx_resume_timer_expired_handler, - hdd_tx_resume_cb); - + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); break; - } + case QDF_P2P_GO_MODE: case QDF_SAP_MODE: - { adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr, name_assign_type, (uint8_t *) iface_name); if (NULL == adapter) { - hddLog(QDF_TRACE_LEVEL_FATAL, - FL("failed to allocate adapter for session %d"), - session_type); + hdd_alert("failed to allocate adapter for session %d", + session_type); return NULL; } @@ -2853,64 +3098,21 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, NL80211_IFTYPE_P2P_GO; adapter->device_mode = session_type; - ret = hdd_start_ap_adapter(adapter); - if (ret) - goto err_free_netdev; - status = hdd_register_hostapd(adapter, rtnl_held); if (QDF_STATUS_SUCCESS != status) { hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held); goto err_free_netdev; } - - hddLog(LOG1, FL("Disabling queues")); + hdd_info("Disabling queues"); wlan_hdd_netif_queue_control(adapter, - WLAN_NETIF_TX_DISABLE_N_CARRIER, - WLAN_CONTROL_PATH); - + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); break; - } - case QDF_FTM_MODE: - { - adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr, - name_assign_type, - iface_name); - - if (NULL == adapter) { - hddLog(QDF_TRACE_LEVEL_FATAL, - FL("failed to allocate adapter for session %d"), - session_type); - return NULL; - } - - /* - * Assign NL80211_IFTYPE_STATION as interface type to resolve - * Kernel Warning message while loading driver in FTM mode. - */ - adapter->wdev.iftype = NL80211_IFTYPE_STATION; - adapter->device_mode = session_type; - status = hdd_register_interface(adapter, rtnl_held); - - ret = hdd_start_ftm_adapter(adapter); - if (ret) - goto err_free_netdev; - - /* Stop the Interface TX queue. */ - hddLog(LOG1, FL("Disabling queues")); - wlan_hdd_netif_queue_control(adapter, - WLAN_NETIF_TX_DISABLE_N_CARRIER, - WLAN_CONTROL_PATH); - } - break; default: - { - hddLog(QDF_TRACE_LEVEL_FATAL, - FL("Invalid session type %d"), - session_type); + hdd_alert("Invalid session type %d", session_type); QDF_ASSERT(0); return NULL; } - } cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter); mutex_init(&cfgState->remain_on_chan_ctx_lock); @@ -2957,11 +3159,6 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, cds_check_and_restart_sap_with_non_dfs_acs(); } - if (hdd_set_fw_params(adapter)) { - hdd_err("Failed to set the fw parameters"); - goto err_lro_cleanup; - } - if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter)) hdd_err("Interface %s wow debug_fs init failed", iface_name); @@ -3386,6 +3583,23 @@ QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx) return QDF_STATUS_SUCCESS; } +/** + * hdd_is_interface_up()- Checkfor interface up before ssr + * @hdd_ctx: HDD context + * + * check if there are any wlan interfaces before SSR accordingly start + * the interface. + * + * Return: 0 if interface was opened else false + */ +static bool hdd_is_interface_up(hdd_adapter_t *adapter) +{ + if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) + return true; + else + return false; +} + QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx) { hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; @@ -3399,10 +3613,12 @@ QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx) ENTER(); status = hdd_get_front_adapter(hdd_ctx, &adapterNode); - while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { adapter = adapterNode->pAdapter; + if (!hdd_is_interface_up(adapter)) + continue; + hdd_wmm_init(adapter); switch (adapter->device_mode) { @@ -3867,85 +4083,6 @@ static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) } #endif -#ifdef QCA_WIFI_FTM -/** - * hdd_disable_ftm() - Disable FTM mode - * @hdd_ctx: HDD context - * - * Helper function to disable FTM mode. - * - * Return: None. - */ -static void hdd_disable_ftm(hdd_context_t *hdd_ctx) -{ - hdd_notice("Disabling FTM mode"); - - if (hdd_ftm_stop(hdd_ctx)) { - hdd_alert("hdd_ftm_stop Failed!"); - QDF_ASSERT(0); - } - - hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED; - - wlan_hdd_ftm_close(hdd_ctx); - - return; -} - -/** - * hdd_enable_ftm() - Enable FTM mode - * @hdd_ctx: HDD context - * - * Helper function to enable FTM mode. - * - * Return: 0 on success and errno on failure. - */ -int hdd_enable_ftm(hdd_context_t *hdd_ctx) -{ - int ret; - - ret = wlan_hdd_ftm_open(hdd_ctx); - if (ret) { - hdd_alert("wlan_hdd_ftm_open Failed: %d", ret); - goto err_out; - } - - ret = hdd_ftm_start(hdd_ctx); - - if (ret) { - hdd_alert("hdd_ftm_start Failed: %d", ret); - goto err_ftm_close; - } - - ret = wiphy_register(hdd_ctx->wiphy); - if (ret) { - hdd_alert("wiphy register failed: %d", ret); - goto err_ftm_stop; - } - - hdd_err("FTM driver loaded"); - - return 0; - -err_ftm_stop: - hdd_ftm_stop(hdd_ctx); -err_ftm_close: - wlan_hdd_ftm_close(hdd_ctx); -err_out: - return ret; - -} -#else -int hdd_enable_ftm(hdd_context_t *hdd_ctx) -{ - hdd_err("Driver built without FTM feature enabled!"); - - return -ENOTSUPP; -} - -static inline void hdd_disable_ftm(hdd_context_t *hdd_ctx) { } -#endif - #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE /** * hdd_logging_sock_activate_svc() - Activate logging @@ -4232,39 +4369,23 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context; QDF_STATUS qdf_status; struct wiphy *wiphy = hdd_ctx->wiphy; + int driver_status; ENTER(); - hdd_unregister_wext_all_adapters(hdd_ctx); - - hdd_exit_netlink_services(hdd_ctx); + if (QDF_TIMER_STATE_RUNNING == + qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) { + hdd_info("Stpp interface change timer"); + qdf_mc_timer_stop(&hdd_ctx->iface_change_timer); + } - if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { - hdd_disable_ftm(hdd_ctx); + if (!QDF_IS_STATUS_SUCCESS + (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer))) + hdd_err("Cannot delete interface change timer"); - hdd_alert("FTM driver unloaded"); - goto free_hdd_ctx; - } hdd_unregister_notifiers(hdd_ctx); - /* - * Cancel any outstanding scan requests. We are about to close all - * of our adapters, but an adapter structure is what SME passes back - * to our callback function. Hence if there are any outstanding scan - * requests then there is a race condition between when the adapter - * is closed and when the callback is invoked. We try to resolve that - * race condition here by canceling any outstanding scans before we - * close the adapters. - * Note that the scans may be cancelled in an asynchronous manner, so - * ideally there needs to be some kind of synchronization. Rather than - * introduce a new synchronization here, we will utilize the fact that - * we are about to Request Full Power, and since that is synchronized, - * the expectation is that by the time Request Full Power has completed, - * all scans will be cancelled - */ - hdd_abort_mac_scan_all_adapters(hdd_ctx); - #ifdef MSM_PLATFORM if (QDF_TIMER_STATE_RUNNING == qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) { @@ -4291,33 +4412,40 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) } #endif + mutex_lock(&hdd_ctx->iface_change_lock); + driver_status = hdd_ctx->driver_status; + mutex_unlock(&hdd_ctx->iface_change_lock); + /* * Powersave Offload Case * Disable Idle Power Save Mode */ hdd_set_idle_ps_config(hdd_ctx, false); - /* Unregister the Net Device Notifier */ - unregister_netdevice_notifier(&hdd_netdev_notifier); - - /* - * Stop all adapters, this will ensure the termination of active - * connections on the interface. Make sure the cds_scheduler is - * still available to handle those control messages - */ - hdd_stop_all_adapters(hdd_ctx); - - /* De-register the SME callbacks */ - hdd_deregister_cb(hdd_ctx); - - /* Stop all the modules */ - qdf_status = cds_disable(p_cds_context); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hddLog(QDF_TRACE_LEVEL_FATAL, - FL("Failed to stop CDS")); - QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); + if (driver_status != DRIVER_MODULES_CLOSED) { + hdd_unregister_wext_all_adapters(hdd_ctx); + /* + * Cancel any outstanding scan requests. We are about to close + * all of our adapters, but an adapter structure is what SME + * passes back to our callback function. Hence if there + * are any outstanding scan requests then there is a + * race condition between when the adapter is closed and + * when the callback is invoked. We try to resolve that + * race condition here by canceling any outstanding scans + * before we close the adapters. + * Note that the scans may be cancelled in an asynchronous + * manner, so ideally there needs to be some kind of + * synchronization. Rather than introduce a new + * synchronization here, we will utilize the fact that we are + * about to Request Full Power, and since that is synchronized, + * the expectation is that by the time Request Full Power has + * completed, all scans will be cancelled + */ + hdd_abort_mac_scan_all_adapters(hdd_ctx); + hdd_stop_all_adapters(hdd_ctx); } + hdd_wlan_stop_modules(hdd_ctx, false); /* * Close the scheduler before calling cds_close to make sure no thread * is scheduled after the each module close is called i.e after all the @@ -4339,7 +4467,6 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) * This frees pMac(HAL) context. There should not be any call * that requires pMac access after this. */ - cds_close(p_cds_context); hdd_wlan_green_ap_deinit(hdd_ctx); @@ -4350,19 +4477,15 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) /* Free up RoC request queue and flush workqueue */ cds_flush_work(&hdd_ctx->roc_req_work); - if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) { - hdd_err("Failed to deinit policy manager"); - /* Proceed and complete the clean up */ - } - wlansap_global_deinit(); - -free_hdd_ctx: + wlansap_global_deinit(); wlan_hdd_deinit_tx_rx_histogram(hdd_ctx); wiphy_unregister(wiphy); wlan_hdd_cfg80211_deinit(wiphy); + hdd_exit_netlink_services(hdd_ctx); + mutex_destroy(&hdd_ctx->iface_change_lock); hdd_context_destroy(hdd_ctx); } @@ -5236,17 +5359,12 @@ static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx) * * Return: none */ -static void hdd_enable_fastpath(struct hdd_config *hdd_cfg, +void hdd_enable_fastpath(struct hdd_config *hdd_cfg, void *context) { if (hdd_cfg->fastpath_enable) hif_enable_fastpath(context); } -#else -static void hdd_enable_fastpath(struct hdd_config *hdd_cfg, - void *context) -{ -} #endif #if defined(FEATURE_WLAN_CH_AVOID) @@ -5909,21 +6027,19 @@ list_destroy: /** * hdd_context_create() - Allocate and inialize HDD context. - * @dev: Pointer to the underlying device - * @hif_sc: HIF context + * @dev: Device Pointer to the underlying device * * Allocate and initialize HDD context. HDD context is allocated as part of * wiphy allocation and then context is initialized. * * Return: HDD context on success and ERR_PTR on failure */ -hdd_context_t *hdd_context_create(struct device *dev, void *hif_sc) +hdd_context_t *hdd_context_create(struct device *dev) { QDF_STATUS status; int ret = 0; hdd_context_t *hdd_ctx; v_CONTEXT_t p_cds_context; - struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_sc); ENTER(); @@ -5954,7 +6070,7 @@ hdd_context_t *hdd_context_create(struct device *dev, void *hif_sc) /* Read and parse the qcom_cfg.ini file */ status = hdd_parse_config_ini(hdd_ctx); if (QDF_STATUS_SUCCESS != status) { - hdd_alert("Error (status: %d) parsing INI file: %s", status, + hdd_err("Error (status: %d) parsing INI file: %s", status, WLAN_INI_FILE); ret = -EINVAL; goto err_free_config; @@ -5977,12 +6093,10 @@ hdd_context_t *hdd_context_create(struct device *dev, void *hif_sc) if (ret) goto err_free_config; - hdd_ctx->target_type = tgt_info->target_type; pld_set_fw_debug_mode(hdd_ctx->parent_dev, hdd_ctx->config->enable_fw_log); - hdd_enable_fastpath(hdd_ctx->config, hif_sc); /* Uses to enabled logging after SSR */ hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log; @@ -6086,27 +6200,6 @@ static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx, #endif /** - * hdd_open_monitor_interface() - Open monitor mode interface - * @hdd_ctx: HDD context - * @rtnl_held: True if RTNL lock is held - * - * Return: Primary adapter on success and PTR_ERR on failure - */ -static hdd_adapter_t *hdd_open_monitor_interface(hdd_context_t *hdd_ctx, - bool rtnl_held) -{ - hdd_adapter_t *adapter; - - adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d", - wlan_hdd_get_intf_addr(hdd_ctx), - NET_NAME_UNKNOWN, rtnl_held); - if (adapter == NULL) - return ERR_PTR(-ENOSPC); - - return adapter; -} - -/** * hdd_start_station_adapter()- Start the Station Adapter * @adapter: HDD adapter * @@ -6127,6 +6220,10 @@ int hdd_start_station_adapter(hdd_adapter_t *adapter) return qdf_status_to_os_return(status); } + hdd_register_tx_flow_control(adapter, + hdd_tx_resume_timer_expired_handler, + hdd_tx_resume_cb); + EXIT(); return 0; } @@ -6152,6 +6249,10 @@ int hdd_start_ap_adapter(hdd_adapter_t *adapter) return qdf_status_to_os_return(status); } + hdd_register_tx_flow_control(adapter, + hdd_softap_tx_resume_timer_expired_handler, + hdd_softap_tx_resume_cb); + EXIT(); return 0; } @@ -6197,8 +6298,8 @@ static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter_11p = NULL; int ret; - /* Create only 802.11p interface */ if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) { + /* Create only 802.11p interface */ adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d", wlan_hdd_get_intf_addr(hdd_ctx), NET_NAME_UNKNOWN, rtnl_held); @@ -6208,7 +6309,6 @@ static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx, return adapter; } - adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d", wlan_hdd_get_intf_addr(hdd_ctx), NET_NAME_UNKNOWN, rtnl_held); @@ -6912,11 +7012,6 @@ static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) /* FW capabilities received, Set the Dot11 mode */ sme_setdef_dot11mode(hdd_ctx->hHal); - /* - * Action frame registered in one adapter which will - * applicable to all interfaces - */ - wlan_hdd_cfg80211_register_frames(adapter); if (hdd_ctx->config->fIsImpsEnabled) hdd_set_idle_ps_config(hdd_ctx, true); @@ -6989,6 +7084,218 @@ out: /** + * hdd_configure_cds() - Configure cds modules + * @hdd_ctx: HDD context + * @adapter: Primary adapter context + * + * Enable Cds modules after WLAN firmware is up. + * + * Return: 0 on success and errno on failure. + */ +int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) +{ + int ret; + QDF_STATUS status; + /* structure of function pointers to be used by CDS */ + struct cds_sme_cbacks sme_cbacks; + + ret = hdd_pre_enable_configure(hdd_ctx); + if (ret) { + hdd_err("Failed to pre-configure cds"); + goto out; + } + + /* + * Start CDS which starts up the SME/MAC/HAL modules and everything + * else + */ + status = cds_enable(hdd_ctx->pcds_context); + + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_alert("cds_enable failed"); + goto out; + } + + status = hdd_post_cds_enable_config(hdd_ctx); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_alert("hdd_post_cds_enable_config failed"); + goto out; + } + + ret = hdd_features_init(hdd_ctx, adapter); + if (ret) + goto out; + + sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels; + sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss; + status = cds_init_policy_mgr(&sme_cbacks); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("Policy manager initialization failed"); + goto out; + } + + return 0; +out: + return -EINVAL; +} + +/** + * hdd_deconfigure_cds() -De-Configure cds + * @hdd_ctx: HDD context + * + * Deconfigure Cds modules before WLAN firmware is down. + * + * Return: 0 on success and errno on failure. + */ +int hdd_deconfigure_cds(hdd_context_t *hdd_ctx) +{ + QDF_STATUS qdf_status; + + ENTER(); + /* De-register the SME callbacks */ + hdd_deregister_cb(hdd_ctx); + + /* De-init Policy Manager */ + if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) { + hdd_err("Failed to deinit policy manager"); + /* Proceed and complete the clean up */ + return -EINVAL; + } + + qdf_status = cds_disable(hdd_ctx->pcds_context); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + hdd_err("Failed to Disable the CDS Modules! :%d", + qdf_status); + return -EINVAL; + } + + EXIT(); + return 0; +} + + +/** + * hdd_wlan_stop_modules - Single driver state machine for stoping modules + * @hdd_ctx: HDD context + * @shutdown: flag to indicate from SSR or normal path + * + * This function maintains the driver state machine it will be invoked from + * exit, shutdown and con_mode change handler. Depending on the driver state + * shall perform the stopping/closing of the modules. + * + * Return: 0 for success; non-zero for failure + */ +int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown) +{ + void *hif_ctx; + qdf_device_t qdf_ctx; + QDF_STATUS qdf_status; + int ret; + p_cds_sched_context cds_sched_context = NULL; + + ENTER(); + + qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); + if (!qdf_ctx) { + hdd_err("QDF device context NULL"); + return -EINVAL; + } + + cds_sched_context = get_cds_sched_ctxt(); + if (!cds_sched_context) { + hdd_err("cds scheduler context NULL"); + return -EINVAL; + } + + hdd_info("Present Driver Status: %d", hdd_ctx->driver_status); + + switch (hdd_ctx->driver_status) { + case DRIVER_MODULES_UNINITIALIZED: + hdd_info("Modules not initialized just return"); + return 0; + case DRIVER_MODULES_CLOSED: + hdd_info("Modules already closed"); + return 0; + case DRIVER_MODULES_ENABLED: + if (hdd_deconfigure_cds(hdd_ctx)) { + hdd_alert("Failed to de-configure CDS"); + QDF_ASSERT(0); + return -EINVAL; + } + hdd_info("successfully Disabled the CDS modules!"); + hdd_ctx->driver_status = DRIVER_MODULES_OPENED; + break; + case DRIVER_MODULES_OPENED: + hdd_info("Closing CDS modules!"); + break; + default: + hdd_err("Trying to stop wlan in a wrong state: %d", + hdd_ctx->driver_status); + QDF_ASSERT(0); + return -EINVAL; + } + + qdf_status = cds_close(hdd_ctx->pcds_context); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + hdd_warn("Failed to stop CDS:%d", qdf_status); + QDF_ASSERT(0); + } + /* Clean up message queues of TX, RX and MC thread */ + cds_sched_flush_mc_mqs(cds_sched_context); + + hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); + if (!hif_ctx) { + hdd_err("Hif context is Null"); + return -EINVAL; + } + + hdd_hif_close(hif_ctx); + + ol_cds_free(); + + if (!shutdown) { + ret = pld_power_off(qdf_ctx->dev); + if (ret) + hdd_err("CNSS power down failed put device into Low power mode:%d", + ret); + } + hdd_ctx->driver_status = DRIVER_MODULES_CLOSED; + + EXIT(); + + return 0; + +} + +/** + * hdd_iface_change_callback() - Function invoked when stop modules expires + * @priv: pointer to hdd context + * + * This function is invoked when the timer waiting for the interface change + * expires, it shall cut-down the power to wlan and stop all the modules. + * + * Return: void + */ +static void hdd_iface_change_callback(void *priv) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *) priv; + int ret; + int status = wlan_hdd_validate_context(hdd_ctx); + + if (status) + return; + + ENTER(); + hdd_info("Interface change timer expired close the modules!"); + mutex_lock(&hdd_ctx->iface_change_lock); + ret = hdd_wlan_stop_modules(hdd_ctx, false); + if (ret) + hdd_alert("Failed to stop modules"); + mutex_unlock(&hdd_ctx->iface_change_lock); + EXIT(); +} + +/** * hdd_wlan_startup() - HDD init function * @dev: Pointer to the underlying device * @@ -6996,49 +7303,40 @@ out: * * Return: 0 for success, < 0 for failure */ -int hdd_wlan_startup(struct device *dev, void *hif_sc) +int hdd_wlan_startup(struct device *dev) { QDF_STATUS status; hdd_adapter_t *adapter = NULL; hdd_context_t *hdd_ctx = NULL; int ret; + void *hif_sc; bool rtnl_held; - /* structure of function pointers to be used by CDS */ - struct cds_sme_cbacks sme_cbacks; ENTER(); - if (QDF_IS_EPPING_ENABLED(con_mode)) { - ret = epping_enable(dev); - EXIT(); - return ret; - } - - hdd_ctx = hdd_context_create(dev, hif_sc); + hdd_ctx = hdd_context_create(dev); if (IS_ERR(hdd_ctx)) return PTR_ERR(hdd_ctx); + qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW, + hdd_iface_change_callback, (void *)hdd_ctx); + + mutex_init(&hdd_ctx->iface_change_lock); + ret = hdd_init_netlink_services(hdd_ctx); if (ret) goto err_hdd_free_context; + hdd_wlan_green_ap_init(hdd_ctx); + ret = hdd_update_config(hdd_ctx); if (ret) - goto err_hdd_free_context; - - if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { - ret = hdd_enable_ftm(hdd_ctx); - if (ret) - goto err_exit_nl_srv; - - goto success; - } + goto err_exit_nl_srv; - hdd_wlan_green_ap_init(hdd_ctx); - status = cds_open(); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_open failed")); + ret = hdd_wlan_start_modules(hdd_ctx, adapter, false); + if (ret) { + hdd_alert("Failed to start modules: %d", ret); goto err_exit_nl_srv; } @@ -7048,62 +7346,35 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) if (NULL == hdd_ctx->hHal) { hddLog(QDF_TRACE_LEVEL_FATAL, FL("HAL context is null")); - goto err_cds_close; - } - - status = cds_pre_enable(hdd_ctx->pcds_context); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_pre_enable failed")); - goto err_cds_close; + goto err_stop_modules; } ret = hdd_wiphy_init(hdd_ctx); if (ret) { hdd_alert("Failed to initialize wiphy: %d", ret); - goto err_cds_close; + goto err_stop_modules; } - ret = hdd_pre_enable_configure(hdd_ctx); - if (ret) - goto err_wiphy_unregister; - if (hdd_ctx->config->enable_dp_trace) qdf_dp_trace_init(); if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE) goto err_wiphy_unregister; - /* - * Start CDS which starts up the SME/MAC/HAL modules and everything - * else - */ - status = cds_enable(hdd_ctx->pcds_context); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_enable failed")); - goto err_ipa_cleanup; - } - - status = hdd_post_cds_enable_config(hdd_ctx); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hddLog(QDF_TRACE_LEVEL_FATAL, - FL("hdd_post_cds_enable_config failed")); - goto err_cds_disable; - } rtnl_held = hdd_hold_rtnl_lock(); - if (QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) - adapter = hdd_open_monitor_interface(hdd_ctx, rtnl_held); - else - adapter = hdd_open_interfaces(hdd_ctx, rtnl_held); + + adapter = hdd_open_interfaces(hdd_ctx, rtnl_held); if (IS_ERR(adapter)) { hddLog(QDF_TRACE_LEVEL_FATAL, FL("Failed to open interface, adapter is NULL")); ret = PTR_ERR(adapter); - goto err_cds_disable; + goto err_ipa_cleanup; } + hif_sc = cds_get_context(QDF_MODULE_ID_HIF); /* * target hw version/revision would only be retrieved after firmware * donwload @@ -7127,15 +7398,6 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hddLog(LOGE, FL("Failed to init ACS Skip timer")); #endif - sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels; - sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss; - status = cds_init_policy_mgr(&sme_cbacks); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hdd_err("Policy manager initialization failed"); - goto err_debugfs_exit; - } - - #ifdef MSM_PLATFORM spin_lock_init(&hdd_ctx->bus_bw_lock); qdf_mc_timer_init(&hdd_ctx->bus_bw_timer, @@ -7159,37 +7421,38 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) memdump_init(); - if (hdd_features_init(hdd_ctx, adapter)) { - hdd_err("Error Configuring the CDS!"); - goto err_exit_nl_srv; - } + if (hdd_ctx->config->fIsImpsEnabled) + hdd_set_idle_ps_config(hdd_ctx, true); + qdf_mc_timer_start(&hdd_ctx->iface_change_timer, + hdd_ctx->config->iface_change_wait_time * 5000); goto success; err_debugfs_exit: hdd_debugfs_exit(adapter); hdd_close_all_adapters(hdd_ctx, false); -err_cds_disable: if (rtnl_held) hdd_release_rtnl_lock(); - cds_disable(hdd_ctx->pcds_context); -err_ipa_cleanup: - hdd_ipa_cleanup(hdd_ctx); err_wiphy_unregister: wiphy_unregister(hdd_ctx->wiphy); wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy); -err_cds_close: +err_ipa_cleanup: + hdd_ipa_cleanup(hdd_ctx); + +err_stop_modules: + hdd_wlan_stop_modules(hdd_ctx, false); + + status = cds_sched_close(hdd_ctx->pcds_context); if (!QDF_IS_STATUS_SUCCESS(status)) { hddLog(QDF_TRACE_LEVEL_FATAL, FL("Failed to close CDS Scheduler")); QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status)); } - cds_close(hdd_ctx->pcds_context); err_exit_nl_srv: hdd_exit_netlink_services(hdd_ctx); @@ -7200,6 +7463,8 @@ err_exit_nl_srv: } cds_deinit_ini_config(); err_hdd_free_context: + qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer); + mutex_destroy(&hdd_ctx->iface_change_lock); hdd_context_destroy(hdd_ctx); QDF_BUG(1); @@ -7211,7 +7476,28 @@ success: } /** - * hdd_register_cb() - Register HDD callbacks. + * hdd_wlan_update_target_info() - update target type info + * @hdd_ctx: HDD context + * @context: hif context + * + * Update target info received from firmware in hdd context + * Return:None + */ + +void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context) +{ + struct hif_target_info *tgt_info = hif_get_target_info_handle(context); + + if (!tgt_info) { + hdd_err("Target info is Null"); + return; + } + + hdd_ctx->target_type = tgt_info->target_type; +} + +/** + * hdd_register_cb - Register HDD callbacks. * @hdd_ctx: HDD context * * Register the HDD callbacks to CDS/SME. @@ -8112,7 +8398,7 @@ static int __hdd_module_init(void) { int ret = 0; - pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME, + pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); pld_init(); @@ -8155,96 +8441,192 @@ static void __hdd_module_exit(void) return; } +#ifndef MODULE /** - * hdd_module_init() - Init Function + * wlan_boot_cb() - Wlan boot callback + * @kobj: object whose directory we're creating the link in. + * @attr: attribute the user is interacting with + * @buff: the buffer containing the user data + * @count: number of bytes in the buffer * - * This is the driver entry point (invoked when module is loaded using insmod) + * This callback is invoked when the fs is ready to start the + * wlan driver initialization. * - * Return: 0 for success, non zero for failure + * Return: 'count' on success or a negative error code in case of failure */ -#ifdef MODULE -static int __init hdd_module_init(void) -{ - return __hdd_module_init(); -} -#else /* #ifdef MODULE */ -static int __init hdd_module_init(void) +static ssize_t wlan_boot_cb(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) { - /* Driver initialization is delayed to fwpath_changed_handler */ - return 0; + + int ret = 0; + + if (wlan_loader->loaded_state) { + pr_info("Wlan driver already initialized"); + return 0; + } + + + pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); + + if (__hdd_module_init()) { + pr_err("%s: Failed to register handler\n", __func__); + ret = -EINVAL; + } else + wlan_loader->loaded_state = MODULE_INITIALIZED; + + return count; + } -#endif /* #ifdef MODULE */ /** - * hdd_module_exit() - Exit function + * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is + * ready * - * This is the driver exit point (invoked when module is unloaded using rmmod) + * This is creates the syfs entry boot_wlan. Which shall be invoked + * when the filesystem is ready. * * Return: None */ -static void __exit hdd_module_exit(void) +static int wlan_init_sysfs(void) { - __hdd_module_exit(); + int ret = -EINVAL; + + wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL); + if (!wlan_loader) { + pr_err("%s: memory alloc failed\n", __func__); + ret = -ENOMEM; + return ret; + } + + wlan_loader->boot_wlan_obj = NULL; + wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)), + GFP_KERNEL); + if (!wlan_loader->attr_group) { + pr_err("%s: malloc attr_group failed\n", __func__); + ret = -ENOMEM; + goto error_return; + } + + wlan_loader->loaded_state = 0; + wlan_loader->attr_group->attrs = attrs; + + wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan", + kernel_kobj); + if (!wlan_loader->boot_wlan_obj) { + pr_err("%s: sysfs create and add failed\n", __func__); + ret = -ENOMEM; + goto error_return; + } + + ret = sysfs_create_group(wlan_loader->boot_wlan_obj, + wlan_loader->attr_group); + if (ret) { + pr_err("%s: sysfs create group failed %d\n", __func__, ret); + goto error_return; + } + + return 0; + +error_return: + + if (wlan_loader->boot_wlan_obj) { + kobject_del(wlan_loader->boot_wlan_obj); + wlan_loader->boot_wlan_obj = NULL; + } + + return ret; } -#ifdef MODULE -static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp) +/** + * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan + * + * Return: 0 on success or errno on failure + */ +static int wlan_deinit_sysfs(void) { - return param_set_copystring(kmessage, kp); + + if (!wlan_loader) { + hdd_alert("wlan loader context is Null!"); + return -EINVAL; + } + + if (wlan_loader->boot_wlan_obj) { + sysfs_remove_group(wlan_loader->boot_wlan_obj, + wlan_loader->attr_group); + kobject_del(wlan_loader->boot_wlan_obj); + wlan_loader->boot_wlan_obj = NULL; + } + + return 0; } -#else /* #ifdef MODULE */ +#endif + +#ifdef MODULE /** - * kickstart_driver() - driver entry point + * __hdd_module_init - Module init helper * - * This is the driver entry point - * - delayed driver initialization when driver is statically linked - * - invoked when module parameter fwpath is modified from userspace to signal - * initializing the WLAN driver or when con_mode is modified from userspace - * to signal a switch in operating mode + * Module init helper function used by both module and static driver. * - * Return: 0 for success, non zero for failure + * Return: 0 for success, errno on failure */ -static int kickstart_driver(void) +static int hdd_module_init(void) { int ret = 0; - if (!wlan_hdd_inited) { - ret = __hdd_module_init(); - wlan_hdd_inited = ret ? 0 : 1; + pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); - return ret; + if (__hdd_module_init()) { + pr_err("%s: Failed to register handler\n", __func__); + ret = -EINVAL; } - __hdd_module_exit(); - - msleep(200); - - ret = __hdd_module_init(); + return ret; +} +#else +static int __init hdd_module_init(void) +{ + int ret = -EINVAL; - wlan_hdd_inited = ret ? 0 : 1; + ret = wlan_init_sysfs(); + if (!ret) + pr_err("Failed to create sysfs entry for loading wlan"); return ret; } +#endif + +#ifdef MODULE /** - * fwpath_changed_handler() - Handler Function + * hdd_module_exit() - Exit function * - * Handle changes to the fwpath parameter + * This is the driver exit point (invoked when module is unloaded using rmmod) * - * Return: 0 for success, non zero for failure + * Return: None */ -static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp) +static void __exit hdd_module_exit(void) { - int ret; + __hdd_module_exit(); +} +#else +static void __exit hdd_module_exit(void) +{ + __hdd_module_exit(); + wlan_deinit_sysfs(); +} +#endif - ret = param_set_copystring(kmessage, kp); - if (0 == ret) - ret = kickstart_driver(); - return ret; +static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp) +{ + return param_set_copystring(kmessage, kp); } -#ifdef QCA_WIFI_FTM + /** * con_mode_handler() - Handles module param con_mode change * @@ -8257,14 +8639,82 @@ static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp) static int con_mode_handler(const char *kmessage, struct kernel_param *kp) { int ret; + hdd_context_t *hdd_ctx; + hdd_adapter_t *adapter; + qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); + QDF_STATUS status; + hdd_info("con_mode handler: %s", kmessage); ret = param_set_int(kmessage, kp); - if (0 == ret) - ret = kickstart_driver(); + + if (!qdf_dev) { + hdd_err("qdf device context is Null return!"); + return -EINVAL; + } + + hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hdd_err("Hdd context Null return!"); + return -EINVAL; + } + mutex_lock(&hdd_ctx->iface_change_lock); + ret = hdd_wlan_stop_modules(hdd_ctx, false); + mutex_unlock(&hdd_ctx->iface_change_lock); + if (ret) { + hdd_err("Stop wlan modules failed"); + return -EINVAL; + } + + adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE); + if (!adapter) { + hdd_err("Failed to get station adapter"); + return -EINVAL; + } + + if (con_mode == QDF_GLOBAL_FTM_MODE) { + adapter->device_mode = QDF_FTM_MODE; + hdd_set_conparam(QDF_GLOBAL_FTM_MODE); + } else if (con_mode == QDF_GLOBAL_MONITOR_MODE) { + adapter->wdev.iftype = NL80211_IFTYPE_MONITOR; + adapter->device_mode = QDF_MONITOR_MODE; + hdd_set_conparam(QDF_GLOBAL_MONITOR_MODE); + hdd_set_station_ops(adapter->dev); + } else if (con_mode == QDF_GLOBAL_EPPING_MODE) { + hdd_set_conparam(QDF_GLOBAL_EPPING_MODE); + status = epping_open(); + if (status != QDF_STATUS_SUCCESS) { + hdd_err("Failed to open in eeping mode: %d", status); + return -EINVAL; + } + ret = epping_enable(qdf_dev->dev); + if (ret) { + hdd_err("Failed to enable in epping mode : %d", ret); + epping_close(); + return -EINVAL; + } + hdd_info("epping mode successfully enabled"); + return 0; + } else { + hdd_info("Con mode not supported"); + return -EINVAL; + } + + ret = hdd_wlan_start_modules(hdd_ctx, adapter, false); + if (ret) { + hdd_err("Start wlan modules failed: %d", ret); + return -EINVAL; + } + + if (hdd_start_adapter(adapter)) { + hdd_err("Failed to start %s adapter", kmessage); + return -EINVAL; + } else { + hdd_info("Mode successfully changed to %s", kmessage); + ret = 0; + } + return ret; } -#endif /* QCA_WIFI_FTM */ -#endif /* #ifdef MODULE */ /** * hdd_get_conparam() - driver exit point @@ -8387,12 +8837,8 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Qualcomm Atheros, Inc."); MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER"); -#if !defined(MODULE) && defined(QCA_WIFI_FTM) module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -#else -module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -#endif module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); diff --git a/core/hdd/src/wlan_hdd_memdump.c b/core/hdd/src/wlan_hdd_memdump.c index 2e13649614fd..cf35c4857f0f 100644 --- a/core/hdd/src/wlan_hdd_memdump.c +++ b/core/hdd/src/wlan_hdd_memdump.c @@ -536,7 +536,6 @@ int memdump_init(void) { hdd_context_t *hdd_ctx; int status = 0; - QDF_STATUS cb_status; QDF_STATUS qdf_status; hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); @@ -550,13 +549,6 @@ int memdump_init(void) return -EINVAL; } - cb_status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal, - wlan_hdd_cfg80211_fw_mem_dump_cb); - if (QDF_STATUS_SUCCESS != cb_status) { - hddLog(LOGE , FL("Failed to register the callback")); - return -EINVAL; - } - status = memdump_procfs_init(); if (status) { hddLog(LOGE , FL("Failed to create proc file")); diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index b6cb8024f589..a1df43603409 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1299,7 +1299,6 @@ static void hdd_ssr_timer_start(int msec) */ QDF_STATUS hdd_wlan_shutdown(void) { - QDF_STATUS qdf_status; v_CONTEXT_t p_cds_context = NULL; hdd_context_t *pHddCtx; p_cds_sched_context cds_sched_context = NULL; @@ -1350,76 +1349,8 @@ QDF_STATUS hdd_wlan_shutdown(void) } #endif - /* Stop all the threads; we do not want any messages to be a processed, - * any more and the best way to ensure that is to terminate the threads - * gracefully. - */ - /* Wait for MC to exit */ - hdd_alert("Shutting down MC thread"); - set_bit(MC_SHUTDOWN_EVENT_MASK, &cds_sched_context->mcEventFlag); - set_bit(MC_POST_EVENT_MASK, &cds_sched_context->mcEventFlag); - wake_up_interruptible(&cds_sched_context->mcWaitQueue); - wait_for_completion(&cds_sched_context->McShutdown); - -#ifdef QCA_CONFIG_SMP - /* Wait for OL RX to exit */ - hdd_alert("Shutting down OL RX thread"); - unregister_hotcpu_notifier(cds_sched_context->cpu_hot_plug_notifier); - set_bit(RX_SHUTDOWN_EVENT_MASK, &cds_sched_context->ol_rx_event_flag); - set_bit(RX_POST_EVENT_MASK, &cds_sched_context->ol_rx_event_flag); - wake_up_interruptible(&cds_sched_context->ol_rx_wait_queue); - wait_for_completion(&cds_sched_context->ol_rx_shutdown); - cds_sched_context->ol_rx_thread = NULL; - cds_drop_rxpkt_by_staid(cds_sched_context, WLAN_MAX_STA_COUNT); - cds_free_ol_rx_pkt_freeq(cds_sched_context); -#endif - - hdd_alert("Doing WMA STOP"); - qdf_status = wma_stop(p_cds_context, HAL_STOP_TYPE_RF_KILL); - - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, LOGE, - "%s: Failed to stop WMA", __func__); - QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); - wma_setneedshutdown(p_cds_context); - } - - hdd_alert("Doing SME STOP"); - /* Stop SME - Cannot invoke cds_disable as cds_disable relies - * on threads being running to process the SYS Stop - */ - qdf_status = sme_stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, LOGE, - "%s: Failed to stop sme %d", __func__, qdf_status); - QDF_ASSERT(0); - } - - hdd_alert("Doing MAC STOP"); - /* Stop MAC (PE and HAL) */ - qdf_status = mac_stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_QDF, LOGE, - "%s: Failed to stop mac %d", __func__, qdf_status); - QDF_ASSERT(0); - } - - hdd_notice("Flush Queues"); - /* Clean up message queues of TX, RX and MC thread */ - cds_sched_flush_mc_mqs(cds_sched_context); - - /* Deinit all the TX, RX and MC queues */ - cds_sched_deinit_mqs(cds_sched_context); - - hdd_notice("Doing CDS Shutdown"); - /* shutdown CDS */ - cds_shutdown(p_cds_context); - - /*mac context has already been released in mac_close call - so setting it to NULL in hdd context */ - pHddCtx->hHal = (tHalHandle) NULL; - wlansap_global_deinit(); + hdd_wlan_stop_modules(pHddCtx, true); hdd_alert("WLAN driver shutdown complete"); return QDF_STATUS_SUCCESS; @@ -1433,14 +1364,14 @@ QDF_STATUS hdd_wlan_shutdown(void) * Return: QDF_STATUS_SUCCESS if the driver was re-initialized, * or an error status otherwise */ -QDF_STATUS hdd_wlan_re_init(void *hif_sc) +QDF_STATUS hdd_wlan_re_init(void) { - QDF_STATUS qdf_status; + v_CONTEXT_t p_cds_context = NULL; hdd_context_t *pHddCtx = NULL; - QDF_STATUS qdf_ret_status; hdd_adapter_t *pAdapter; - int i, ret; + QDF_STATUS qdf_status; + int ret; hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT); @@ -1458,93 +1389,8 @@ QDF_STATUS hdd_wlan_re_init(void *hif_sc) goto err_re_init; } - if (!hif_sc) { - hdd_alert("hif_sc is NULL"); - goto err_re_init; - } - - ((cds_context_type *) p_cds_context)->pHIFContext = hif_sc; - /* The driver should always be initialized in STA mode after SSR */ hdd_set_conparam(0); - - ret = hdd_update_config(pHddCtx); - if (ret) - goto err_re_init; - - /* Re-open CDS, it is a re-open b'se control transport was never closed. */ - qdf_status = cds_open(); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_alert("cds_open failed"); - goto err_re_init; - } - - /* Save the hal context in Adapter */ - pHddCtx->hHal = cds_get_context(QDF_MODULE_ID_SME); - if (NULL == pHddCtx->hHal) { - hdd_alert("HAL context is null"); - goto err_cds_close; - } - - qdf_status = cds_pre_enable(pHddCtx->pcds_context); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_alert("cds_pre_enable failed"); - goto err_cds_close; - } - - /* - * Note that the cds_pre_enable() sequence triggers the cfg download. - * The cfg download must occur before we update the SME config - * since the SME config operation must access the cfg database. - * Set the SME configuration parameters. - */ - qdf_status = hdd_set_sme_config(pHddCtx); - if (QDF_STATUS_SUCCESS != qdf_status) { - hdd_alert("Failed hdd_set_sme_config"); - goto err_cds_close; - } - - ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb); - - qdf_status = hdd_set_sme_chan_list(pHddCtx); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_alert("Failed to init channel list"); - goto err_cds_close; - } - - /* Apply the cfg.ini to cfg.dat */ - if (false == hdd_update_config_dat(pHddCtx)) { - hdd_alert("config update failed"); - goto err_cds_close; - } - - /* Set the MAC Address, currently this is used by HAL to add self sta. - * Remove this once self sta is added as part of session open. */ - qdf_ret_status = cfg_set_str(pHddCtx->hHal, WNI_CFG_STA_ID, - (uint8_t *) &pHddCtx->config-> - intfMacAddr[0], - sizeof(pHddCtx->config->intfMacAddr[0])); - if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) { - hdd_err("Failed to set MAC Address. " - "HALStatus is %08d [x%08x]", qdf_ret_status, - qdf_ret_status); - goto err_cds_close; - } - - /* Start CDS which starts up the SME/MAC/HAL modules and everything else - Note: Firmware image will be read and downloaded inside cds_enable API */ - qdf_status = cds_enable(p_cds_context); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_alert("cds_enable failed"); - goto err_cds_close; - } - - qdf_status = hdd_post_cds_enable_config(pHddCtx); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_alert("hdd_post_cds_enable_config failed"); - goto err_cds_disable; - } - /* Try to get an adapter from mode ID */ pAdapter = hdd_get_adapter(pHddCtx, QDF_STA_MODE); if (!pAdapter) { @@ -1560,6 +1406,12 @@ QDF_STATUS hdd_wlan_re_init(void *hif_sc) if (pHddCtx->config->enable_dp_trace) qdf_dp_trace_init(); + ret = hdd_wlan_start_modules(pHddCtx, pAdapter, true); + if (ret) { + hdd_err("Failed to start wlan after error"); + goto err_wiphy_unregister; + } + if (hdd_ipa_uc_ssr_reinit()) hdd_err("HDD IPA UC reinit failed"); @@ -1568,50 +1420,6 @@ QDF_STATUS hdd_wlan_re_init(void *hif_sc) /* Restart all adapters */ hdd_start_all_adapters(pHddCtx); - /* Reconfigure FW logs after SSR */ - if (pAdapter) { - if (pHddCtx->fw_log_settings.enable != 0) { - wma_cli_set_command(pAdapter->sessionId, - WMI_DBGLOG_MODULE_ENABLE, - pHddCtx->fw_log_settings.enable, - DBG_CMD); - } else { - wma_cli_set_command(pAdapter->sessionId, - WMI_DBGLOG_MODULE_DISABLE, - pHddCtx->fw_log_settings.enable, - DBG_CMD); - } - - if (pHddCtx->fw_log_settings.dl_report != 0) { - wma_cli_set_command(pAdapter->sessionId, - WMI_DBGLOG_REPORT_ENABLE, - pHddCtx->fw_log_settings. - dl_report, DBG_CMD); - - wma_cli_set_command(pAdapter->sessionId, - WMI_DBGLOG_TYPE, - pHddCtx->fw_log_settings. - dl_type, DBG_CMD); - - wma_cli_set_command(pAdapter->sessionId, - WMI_DBGLOG_LOG_LEVEL, - pHddCtx->fw_log_settings. - dl_loglevel, DBG_CMD); - - for (i = 0; i < MAX_MOD_LOGLEVEL; i++) { - if (pHddCtx->fw_log_settings. - dl_mod_loglevel[i] != 0) { - wma_cli_set_command( - pAdapter->sessionId, - WMI_DBGLOG_MOD_LOG_LEVEL, - pHddCtx->fw_log_settings. - dl_mod_loglevel[i], - DBG_CMD); - } - } - } - } - pHddCtx->hdd_mcastbcast_filter_set = false; pHddCtx->btCoexModeSet = false; hdd_ssr_timer_del(); @@ -1639,16 +1447,13 @@ QDF_STATUS hdd_wlan_re_init(void *hif_sc) goto success; err_cds_disable: - cds_disable(p_cds_context); + hdd_wlan_stop_modules(pHddCtx, true); -err_cds_close: - cds_close(p_cds_context); - cds_sched_close(p_cds_context); +err_wiphy_unregister: if (pHddCtx) { /* Unregister the Net Device Notifier */ unregister_netdevice_notifier(&hdd_netdev_notifier); ptt_sock_deactivate_svc(); - nl_srv_exit(); /* Free up dynamically allocated members inside HDD Adapter */ @@ -1656,13 +1461,7 @@ err_cds_close: pHddCtx->config = NULL; wlan_hdd_deinit_tx_rx_histogram(pHddCtx); wiphy_unregister(pHddCtx->wiphy); - wlan_hdd_cfg80211_deinit(pHddCtx->wiphy); wiphy_free(pHddCtx->wiphy); - - if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) { - hdd_err("Failed to deinit policy manager"); - /* Proceed and complete the clean up */ - } } err_re_init: @@ -1763,6 +1562,14 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) result = wlan_hdd_validate_context(pHddCtx); if (0 != result) return result; + + mutex_lock(&pHddCtx->iface_change_lock); + if (pHddCtx->driver_status != DRIVER_MODULES_ENABLED) { + mutex_unlock(&pHddCtx->iface_change_lock); + hdd_info("Driver Module not enabled return success"); + return 0; + } + mutex_unlock(&pHddCtx->iface_change_lock); pld_request_bus_bandwidth(pHddCtx->parent_dev, PLD_BUS_WIDTH_MEDIUM); /* Resume MC thread */ @@ -1897,6 +1704,14 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, if (0 != rc) return rc; + mutex_lock(&pHddCtx->iface_change_lock); + if (pHddCtx->driver_status != DRIVER_MODULES_ENABLED) { + mutex_unlock(&pHddCtx->iface_change_lock); + hdd_info("Driver Modules not Enabled "); + return 0; + } + mutex_unlock(&pHddCtx->iface_change_lock); + /* If RADAR detection is in progress (HDD), prevent suspend. The flag * "dfs_cac_block_tx" is set to true when RADAR is found and stay true * until CAC is done for a SoftAP which is in started state. |
