From ef70c0dd64e886d3bf1efd1be762b40adafa3ea6 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Tue, 20 Oct 2015 19:54:55 +0530 Subject: [PATCH] qcacld-3.0: Set HW mode before issuing connect for Hidden SSID Set the HW mode if needed before connecting to an SSID that is hidden. CRs-Fixed: 928208 Change-Id: Ibefd207327da1b85ae26a91afd27fc6baf98cf14 --- core/cds/inc/cds_concurrency.h | 16 +- core/cds/src/cds_concurrency.c | 184 ++++++++++++--- core/hdd/src/wlan_hdd_cfg80211.c | 13 +- core/hdd/src/wlan_hdd_hostapd.c | 4 +- core/hdd/src/wlan_hdd_wext.c | 19 +- core/mac/inc/sir_api.h | 26 +++ .../src/pe/lim/lim_process_sme_req_messages.c | 1 + core/sme/inc/sme_internal.h | 1 + core/sme/src/common/sme_api.c | 44 ++++ core/sme/src/csr/csr_api_roam.c | 18 ++ core/sme/src/csr/csr_api_scan.c | 221 +++++++++++++++++- core/sme/src/csr/csr_inside_api.h | 5 + 12 files changed, 489 insertions(+), 63 deletions(-) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 9cf3ec0226a0..ff9f30b0940e 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -600,6 +600,9 @@ static inline bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, return true; } #endif /* FEATURE_WLAN_CH_AVOID */ +uint8_t cds_search_and_check_for_session_conc(uint8_t session_id, + tCsrRoamProfile * roam_profile); +bool cds_check_for_session_conc(uint8_t session_id, uint8_t channel); bool cds_handle_conc_multiport(uint8_t session_id, uint8_t channel); #ifdef FEATURE_WLAN_FORCE_SAP_SCC @@ -681,8 +684,9 @@ CDF_STATUS cds_update_connection_info(hdd_context_t *hdd_ctx, uint32_t vdev_id); CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, uint32_t vdev_id); -CDF_STATUS cds_current_connections_update( - hdd_context_t *hdd_ctx, uint8_t channel); +CDF_STATUS cds_current_connections_update(uint32_t session_id, + uint8_t channel, + enum cds_conn_update_reason); #ifdef MPC_UT_FRAMEWORK CDF_STATUS cds_incr_connection_count_utfw(hdd_context_t *hdd_ctx, uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, @@ -738,16 +742,20 @@ enum cds_con_mode cds_convert_device_mode_to_hdd_type( device_mode_t device_mode); uint32_t cds_get_connection_count(hdd_context_t *hdd_ctx); CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, + uint32_t session_id, enum hw_mode_ss_config mac0_ss, enum hw_mode_bandwidth mac0_bw, enum hw_mode_ss_config mac1_ss, enum hw_mode_bandwidth mac1_bw, enum hw_mode_dbs_capab dbs, - enum hw_mode_agile_dfs_capab dfs); + enum hw_mode_agile_dfs_capab dfs, + enum cds_conn_update_reason reason); enum cds_conc_next_action cds_need_opportunistic_upgrade( hdd_context_t *hdd_ctx); CDF_STATUS cds_next_actions( - hdd_context_t *hdd_ctx, enum cds_conc_next_action action); + hdd_context_t *hdd_ctx, uint32_t session_id, + enum cds_conc_next_action action, + enum cds_conn_update_reason reason); void cds_set_dual_mac_scan_config(hdd_context_t *hdd_ctx, uint8_t dbs_val, uint8_t dbs_plus_agile_scan_val, diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 28c0d3b442b3..6792d1122265 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -2377,12 +2377,14 @@ static void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, /** * cds_soc_set_hw_mode() - Set HW mode command to SME * @hdd_ctx: HDD context + * @session_id: Session ID * @mac0_ss: MAC0 spatial stream configuration * @mac0_bw: MAC0 bandwidth configuration * @mac1_ss: MAC1 spatial stream configuration * @mac1_bw: MAC1 bandwidth configuration * @dbs: HW DBS capability * @dfs: HW Agile DFS capability + * @reason: Reason for connection update * * Sends the set hw mode to the SME module which will pass on * this message to WMA layer @@ -2403,12 +2405,14 @@ static void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, * Return: Success if the message made it down to the next layer */ CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, + uint32_t session_id, enum hw_mode_ss_config mac0_ss, enum hw_mode_bandwidth mac0_bw, enum hw_mode_ss_config mac1_ss, enum hw_mode_bandwidth mac1_bw, enum hw_mode_dbs_capab dbs, - enum hw_mode_agile_dfs_capab dfs) + enum hw_mode_agile_dfs_capab dfs, + enum cds_conn_update_reason reason) { int8_t hw_mode_index; struct sir_hw_mode msg; @@ -2428,6 +2432,8 @@ CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, msg.hw_mode_index = hw_mode_index; msg.set_hw_mode_cb = (void *)cds_soc_set_hw_mode_cb; + msg.reason = reason; + msg.session_id = session_id; cds_info("set hw mode to sme: hw_mode_index: %d", msg.hw_mode_index); @@ -3625,7 +3631,12 @@ void cds_dbs_opportunistic_timer_handler(void *data) action = cds_need_opportunistic_upgrade(hdd_ctx); if (action) { /* lets call for action */ - cds_next_actions(hdd_ctx, action); + /* session id is being used only + * in hidden ssid case for now. + * So, session id 0 is ok here. + */ + cds_next_actions(hdd_ctx, 0, action, + CDS_UPDATE_REASON_OPPORTUNISTIC); } cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); @@ -5240,8 +5251,9 @@ CDF_STATUS cds_mode_switch_mcc_to_dbs(hdd_context_t *hdd_ctx) * cds_current_connections_update() - initiates actions * needed on current connections once channel has been decided * for the new connection - * @hdd_ctx: HDD Context + * @session_id: Session id * @channel: Channel on which new connection will be + * @reason: Reason for which connection update is required * * This function initiates initiates actions * needed on current connections once channel has been decided @@ -5249,17 +5261,24 @@ CDF_STATUS cds_mode_switch_mcc_to_dbs(hdd_context_t *hdd_ctx) * * Return: CDF_STATUS enum */ -CDF_STATUS cds_current_connections_update( - hdd_context_t *hdd_ctx, - uint8_t channel) +CDF_STATUS cds_current_connections_update(uint32_t session_id, + uint8_t channel, + enum cds_conn_update_reason reason) { enum cds_conc_next_action next_action = CDS_NOP; uint32_t num_connections = 0; enum cds_one_connection_mode second_index = 0; enum cds_two_connection_mode third_index = 0; enum cds_band band; + hdd_context_t *hdd_ctx; CDF_STATUS status = CDF_STATUS_E_FAILURE; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("Invalid HDD context"); + return CDF_STATUS_E_FAILURE; + } + if (wma_is_hw_dbs_capable() == false) { cds_err("driver isn't dbs capable, no further action needed"); return CDF_STATUS_E_NOSUPPORT; @@ -5315,12 +5334,14 @@ CDF_STATUS cds_current_connections_update( } if (CDS_NOP != next_action) - status = cds_next_actions(hdd_ctx, next_action); + status = cds_next_actions(hdd_ctx, session_id, + next_action, reason); else status = CDF_STATUS_E_NOSUPPORT; - cds_debug("index2=%d index3=%d next_action=%d, band=%d status=%d", - second_index, third_index, next_action, band, status); + cds_debug("index2=%d index3=%d next_action=%d, band=%d status=%d reason=%d session_id=%d", + second_index, third_index, next_action, band, status, + reason, session_id); done: cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); @@ -5437,7 +5458,9 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, break; } if (!wait) - cds_next_actions(hdd_ctx, next_action); + cds_next_actions(hdd_ctx, vdev_id, + next_action, + CDS_UPDATE_REASON_NSS_UPDATE); cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); return; } @@ -5450,6 +5473,8 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, * @new_nss: the new nss value * @next_action: next action to happen at policy mgr after * beacon update + * @reason: Reason for connection update + * @session_id: Session id * * This function initiates initiates actions * needed on current connections once channel has been decided @@ -5458,7 +5483,9 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, * Return: CDF_STATUS enum */ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, - uint8_t new_nss, uint8_t next_action) + uint8_t new_nss, uint8_t next_action, + enum cds_conn_update_reason reason, + uint32_t session_id) { CDF_STATUS status = CDF_STATUS_E_FAILURE; uint32_t index = 0, count = 0; @@ -5518,7 +5545,8 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, index++; } if (!CDF_IS_STATUS_SUCCESS(status)) - status = cds_next_actions(hdd_ctx, next_action); + status = cds_next_actions(hdd_ctx, session_id, + next_action, reason); return status; } @@ -5528,7 +5556,9 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, * connections once channel has been decided for the new * connection * @hdd_ctx: HDD Context + * @session_id: Session id * @action: action to be executed + * @reason: Reason for connection update * * This function initiates initiates actions * needed on current connections once channel has been decided @@ -5537,7 +5567,9 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, * Return: CDF_STATUS enum */ CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, - enum cds_conc_next_action action) + uint32_t session_id, + enum cds_conc_next_action action, + enum cds_conn_update_reason reason) { CDF_STATUS status = CDF_STATUS_E_FAILURE; struct sir_hw_mode_params hw_mode; @@ -5574,14 +5606,17 @@ CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, * update the beacon template & notify FW. Once FW confirms * beacon updated, send down the HW mode change req */ - status = cds_complete_action(hdd_ctx, 1, CDS_DBS); + status = cds_complete_action(hdd_ctx, 1, CDS_DBS, reason, + session_id); break; case CDS_DBS: - status = cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_1x1, + status = cds_soc_set_hw_mode(hdd_ctx, session_id, + HW_MODE_SS_1x1, HW_MODE_80_MHZ, HW_MODE_SS_1x1, HW_MODE_40_MHZ, HW_MODE_DBS, - HW_MODE_AGILE_DFS_NONE); + HW_MODE_AGILE_DFS_NONE, + reason); break; case CDS_MCC_UPGRADE: /* @@ -5589,14 +5624,17 @@ CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, * intially. If yes, update the beacon template & notify FW. * Once FW confirms beacon updated, send the HW mode change req */ - status = cds_complete_action(hdd_ctx, 0, CDS_MCC); + status = cds_complete_action(hdd_ctx, 0, CDS_MCC, reason, + session_id); break; case CDS_MCC: - status = cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_2x2, + status = cds_soc_set_hw_mode(hdd_ctx, session_id, + HW_MODE_SS_2x2, HW_MODE_80_MHZ, HW_MODE_SS_0x0, HW_MODE_BW_NONE, HW_MODE_DBS_NONE, - HW_MODE_AGILE_DFS_NONE); + HW_MODE_AGILE_DFS_NONE, + reason); break; default: /* err msg */ @@ -6118,29 +6156,72 @@ CDF_STATUS cds_get_channel_from_scan_result(hdd_adapter_t *adapter, } /** - * cds_handle_conc_multiport() - to handle multiport concurrency + * cds_search_and_check_for_session_conc() - Checks if concurrecy is allowed + * @session_id: Session id + * @roam_profile: Pointer to the roam profile + * + * Searches and gets the channel number from the scan results and checks if + * concurrency is allowed for the given session ID + * + * Non zero channel number if concurrency is allowed, zero otherwise + */ +uint8_t cds_search_and_check_for_session_conc(uint8_t session_id, + tCsrRoamProfile *roam_profile) +{ + uint8_t channel = 0; + CDF_STATUS status; + hdd_context_t *hdd_ctx; + hdd_adapter_t *adapter; + bool ret; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("Invalid HDD context"); + return channel; + } + + adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id); + if (!adapter) { + cds_err("Invalid HDD adapter"); + return channel; + } + + status = cds_get_channel_from_scan_result(adapter, + roam_profile, &channel); + if ((CDF_STATUS_SUCCESS != status) || (channel == 0)) { + cds_err("%s error %d %d", + __func__, status, channel); + return 0; + } + + /* Take care of 160MHz and 80+80Mhz later */ + ret = cds_allow_concurrency(hdd_ctx, + cds_convert_device_mode_to_hdd_type( + adapter->device_mode), + channel, HW_MODE_20_MHZ); + if (false == ret) { + cds_err("Connection failed due to conc check fail"); + return 0; + } + + return channel; +} + +/** + * cds_check_for_session_conc() - Check if concurrency is allowed for a session * @session_id: Session ID * @channel: Channel number * - * This routine will handle STA side concurrency when policy manager - * is enabled. + * Checks if connection is allowed for a given session_id * - * Return: true or false + * True if the concurrency is allowed, false otherwise */ -bool cds_handle_conc_multiport(uint8_t session_id, +bool cds_check_for_session_conc(uint8_t session_id, uint8_t channel) { - bool ret = true; - CDF_STATUS status; - p_cds_contextType cds_context; - hdd_adapter_t *adapter; hdd_context_t *hdd_ctx; - - cds_context = cds_get_global_context(); - if (!cds_context) { - cds_err("Invalid CDS context"); - return false; - } + hdd_adapter_t *adapter; + bool ret; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -6158,6 +6239,7 @@ bool cds_handle_conc_multiport(uint8_t session_id, cds_err("Invalid channel number 0"); return false; } + /* Take care of 160MHz and 80+80Mhz later */ ret = cds_allow_concurrency(hdd_ctx, cds_convert_device_mode_to_hdd_type( @@ -6165,6 +6247,36 @@ bool cds_handle_conc_multiport(uint8_t session_id, channel, HW_MODE_20_MHZ); if (false == ret) { cds_err("Connection failed due to conc check fail"); + return 0; + } + + return true; +} + +/** + * cds_handle_conc_multiport() - to handle multiport concurrency + * @session_id: Session ID + * @channel: Channel number + * + * This routine will handle STA side concurrency when policy manager + * is enabled. + * + * Return: true or false + */ +bool cds_handle_conc_multiport(uint8_t session_id, + uint8_t channel) +{ + CDF_STATUS status; + p_cds_contextType cds_context; + + cds_context = cds_get_global_context(); + if (!cds_context) { + cds_err("Invalid CDS context"); + return false; + } + + if (!cds_check_for_session_conc(session_id, channel)) { + cds_err("Conc not allowed for the session %d", session_id); return false; } @@ -6172,7 +6284,9 @@ bool cds_handle_conc_multiport(uint8_t session_id, if (!CDF_IS_STATUS_SUCCESS(status)) cds_err("clearing event failed"); - status = cds_current_connections_update(hdd_ctx, channel); + status = cds_current_connections_update(session_id, + channel, + CDS_UPDATE_REASON_NORMAL_STA); if (CDF_STATUS_E_FAILURE == status) { cds_err("connections update failed"); return false; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 9012628af8b6..c78b8bf80282 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4107,7 +4107,8 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy, const void *data, int data_len) { - + struct net_device *ndev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev); hdd_context_t *hdd_ctx = wiphy_priv(wiphy); int ret = 0; enum cds_con_mode intf_mode; @@ -4165,8 +4166,9 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy, if (!CDF_IS_STATUS_SUCCESS(ret)) hdd_err("clearing event failed"); - ret = cds_current_connections_update(hdd_ctx, - channel_hint); + ret = cds_current_connections_update(adapter->sessionId, + channel_hint, + CDS_UPDATE_REASON_SET_OPER_CHAN); if (CDF_STATUS_E_FAILURE == ret) { /* return in the failure case */ hdd_err("ERROR: connections update failed!!"); @@ -8807,8 +8809,9 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, if (!CDF_IS_STATUS_SUCCESS(status)) hdd_err("ERR: clear event failed"); - status = cds_current_connections_update(pHddCtx, - channelNum); + status = cds_current_connections_update(pAdapter->sessionId, + channelNum, + CDS_UPDATE_REASON_JOIN_IBSS); if (CDF_STATUS_E_FAILURE == status) { hdd_err("ERROR: connections update failed!!"); return -EINVAL; diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 2727e1286c44..437a5416430f 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -8241,7 +8241,9 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, if (!CDF_IS_STATUS_SUCCESS(status)) hdd_err("ERR: clear event failed"); - status = cds_current_connections_update(pHddCtx, channel); + status = cds_current_connections_update(pAdapter->sessionId, + channel, + CDS_UPDATE_REASON_START_AP); if (CDF_STATUS_E_FAILURE == status) { hdd_err("ERROR: connections update failed!!"); return -EINVAL; diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 9110a2b72093..1f7cc4985028 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -7692,19 +7692,25 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, if (apps_args[0] == 0) { hddLog(LOGE, FL("set hw mode for single mac\n")); - cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_2x2, + cds_soc_set_hw_mode(hdd_ctx, + pAdapter->sessionId, + HW_MODE_SS_2x2, HW_MODE_80_MHZ, HW_MODE_SS_0x0, HW_MODE_BW_NONE, HW_MODE_DBS_NONE, - HW_MODE_AGILE_DFS_NONE); + HW_MODE_AGILE_DFS_NONE, + CDS_UPDATE_REASON_UT); } else if (apps_args[0] == 1) { hddLog(LOGE, FL("set hw mode for dual mac\n")); - cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_1x1, + cds_soc_set_hw_mode(hdd_ctx, + pAdapter->sessionId, + HW_MODE_SS_1x1, HW_MODE_80_MHZ, HW_MODE_SS_1x1, HW_MODE_40_MHZ, HW_MODE_DBS, - HW_MODE_AGILE_DFS_NONE); + HW_MODE_AGILE_DFS_NONE, + CDS_UPDATE_REASON_UT); } } break; @@ -7714,8 +7720,9 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, enum cds_conc_next_action action; hddLog(LOGE, FL(" is called\n")); - action = cds_current_connections_update(hdd_ctx, - apps_args[0]); + action = cds_current_connections_update(pAdapter->sessionId, + apps_args[0], + CDS_UPDATE_REASON_UT); pr_info("next action is %d {HDD_NOP = 0, HDD_DBS, HDD_DBS_DOWNGRADE, HDD_MCC, HDD_MCC_UPGRADE}", action); } break; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 887901bc8bb0..ba16dd997141 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -95,6 +95,28 @@ typedef uint8_t tSirVersionString[SIR_VERSION_STRING_LEN]; /* This should not be greater than MAX_NUMBER_OF_CONC_CONNECTIONS */ #define MAX_VDEV_SUPPORTED 4 +/** + * enum cds_conn_update_reason: Reason for conc connection update + * @CDS_UPDATE_REASON_SET_OPER_CHAN: Set probable operating channel + * @CDS_UPDATE_REASON_JOIN_IBSS: Join IBSS + * @CDS_UPDATE_REASON_UT: Unit test related + * @CDS_UPDATE_REASON_START_AP: Start AP + * @CDS_UPDATE_REASON_NORMAL_STA: Connection to Normal STA + * @CDS_UPDATE_REASON_HIDDEN_STA: Connection to Hidden STA + * @CDS_UPDATE_REASON_OPPORTUNISTIC: Opportunistic HW mode update + * @CDS_UPDATE_REASON_NSS_UPDATE: NSS update + */ +enum cds_conn_update_reason { + CDS_UPDATE_REASON_SET_OPER_CHAN, + CDS_UPDATE_REASON_JOIN_IBSS, + CDS_UPDATE_REASON_UT, + CDS_UPDATE_REASON_START_AP, + CDS_UPDATE_REASON_NORMAL_STA, + CDS_UPDATE_REASON_HIDDEN_STA, + CDS_UPDATE_REASON_OPPORTUNISTIC, + CDS_UPDATE_REASON_NSS_UPDATE, +}; + typedef enum { eSIR_EXTSCAN_INVALID, eSIR_EXTSCAN_START_RSP, @@ -397,10 +419,14 @@ typedef struct sSirSmeReadyReq { * struct sir_hw_mode - Format of set HW mode * @hw_mode_index: Index of HW mode to be set * @set_hw_mode_cb: HDD set HW mode callback + * @reason: Reason for HW mode change + * @session_id: Session id */ struct sir_hw_mode { uint32_t hw_mode_index; void *set_hw_mode_cb; + enum cds_conn_update_reason reason; + uint32_t session_id; }; /** diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 0db6d07bfc33..b06e32d060fa 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -156,6 +156,7 @@ static CDF_STATUS lim_process_set_hw_mode(tpAniSirGlobal mac, uint32_t *msg) cdf_mem_zero(req_msg, len); req_msg->hw_mode_index = buf->set_hw.hw_mode_index; + req_msg->reason = buf->set_hw.reason; /* Other parameters are not needed for WMA */ cds_message.bodyptr = req_msg; diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index 4ff54c72872b..adc01cbd96a9 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -218,6 +218,7 @@ typedef struct tagSmeStruct { void *dcc_stats_event_context; ocb_callback dcc_stats_event_callback; sme_set_thermal_level_callback set_thermal_level_cb; + void *saved_scan_cmd; } tSmeStruct, *tpSmeStruct; #endif /* #if !defined( __SMEINTERNAL_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index c436ce546bab..60c8729660a0 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -156,7 +156,10 @@ static CDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) bool found; hw_mode_cb callback = NULL; struct sir_set_hw_mode_resp *param; + enum cds_conn_update_reason reason; + tSmeCmd *saved_cmd; + sms_log(mac, LOG1, FL("%s"), __func__); param = (struct sir_set_hw_mode_resp *)msg; if (!param) { sms_log(mac, LOGE, FL("HW mode resp param is NULL")); @@ -184,10 +187,48 @@ static CDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) } callback = command->u.set_hw_mode_cmd.set_hw_mode_cb; + reason = command->u.set_hw_mode_cmd.reason; if (callback) { if (!param) { sms_log(mac, LOGE, FL("Callback failed since HW mode params is NULL")); + } else if (reason == CDS_UPDATE_REASON_HIDDEN_STA) { + /* In the case of hidden SSID, connection update + * (set hw mode) is done after the scan with reason + * code eCsrScanForSsid completes. The connect/failure + * needs to be handled after the response of set hw + * mode + */ + saved_cmd = (tSmeCmd *)mac->sme.saved_scan_cmd; + if (!saved_cmd) { + sms_log(mac, LOGP, + FL("saved cmd is NULL, Check this")); + goto end; + } + if (param->status == SET_HW_MODE_STATUS_OK) { + sms_log(mac, LOG1, + FL("search for ssid success")); + csr_scan_handle_search_for_ssid(mac, + saved_cmd); + } else { + sms_log(mac, LOG1, + FL("search for ssid failure")); + csr_scan_handle_search_for_ssid_failure(mac, + saved_cmd); + } + if (saved_cmd->u.roamCmd.pRoamBssEntry) + cdf_mem_free( + saved_cmd->u.roamCmd.pRoamBssEntry); + if (saved_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList) + cdf_mem_free(saved_cmd->u.scanCmd.u. + scanRequest.SSIDs.SSIDList); + if (saved_cmd->u.scanCmd.pToRoamProfile) + cdf_mem_free(saved_cmd->u.scanCmd. + pToRoamProfile); + if (saved_cmd) { + cdf_mem_free(saved_cmd); + saved_cmd = NULL; + } } else { sms_log(mac, LOGE, FL("Calling HDD callback for HW mode response")); @@ -200,6 +241,7 @@ static CDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) sms_log(mac, LOGE, FL("Callback does not exist")); } +end: found = csr_ll_remove_entry(&mac->sme.smeCmdActiveList, entry, LL_ACCESS_LOCK); if (found) { @@ -14391,6 +14433,8 @@ CDF_STATUS sme_soc_set_hw_mode(tHalHandle hal, cmd->command = e_sme_command_set_hw_mode; cmd->u.set_hw_mode_cmd.hw_mode_index = msg.hw_mode_index; cmd->u.set_hw_mode_cmd.set_hw_mode_cb = msg.set_hw_mode_cb; + cmd->u.set_hw_mode_cmd.reason = msg.reason; + cmd->u.set_hw_mode_cmd.session_id = msg.session_id; sms_log(mac, LOG1, FL("Queuing e_sme_command_set_hw_mode to CSR")); csr_queue_sme_command(mac, cmd, false); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index f4dfbbe4a956..b6125f06dbcf 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -453,6 +453,10 @@ CDF_STATUS csr_close(tpAniSirGlobal pMac) csr_ll_close(&pMac->roam.statsClientReqList); csr_ll_close(&pMac->roam.peStatsReqList); csr_ll_close(&pMac->roam.roamCmdPendingList); + if (pMac->sme.saved_scan_cmd) { + cdf_mem_free(pMac->sme.saved_scan_cmd); + pMac->sme.saved_scan_cmd = NULL; + } /* DeInit Globals */ csr_roam_de_init_globals(pMac); return status; @@ -18818,11 +18822,25 @@ void csr_process_set_hw_mode(tpAniSirGlobal mac, tSmeCmd *command) goto fail; } + /* For hidden SSID case, if there is any scan command pending + * it needs to be cleared before issuing set HW mode + */ + if (command->u.set_hw_mode_cmd.reason == CDS_UPDATE_REASON_HIDDEN_STA) { + sms_log(mac, LOGE, FL("clear any pending scan command")); + status = csr_scan_abort_mac_scan_not_for_connect(mac, + command->u.set_hw_mode_cmd.session_id); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, FL("Failed to clear scan cmd")); + goto fail; + } + } + cdf_mem_set(cmd, len, 0); cmd->messageType = eWNI_SME_SET_HW_MODE_REQ; cmd->length = len; cmd->set_hw.hw_mode_index = command->u.set_hw_mode_cmd.hw_mode_index; + cmd->set_hw.reason = command->u.set_hw_mode_cmd.reason; /* * Below callback and context info are not needed for PE as of now. * Storing the passed value in the same s_sir_set_hw_mode format. diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 68f0aeeef874..e66a5417202e 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2022,8 +2022,11 @@ csr_parse_scan_results(tpAniSirGlobal pMac, pNewIes = NULL; status = csr_save_ies(pMac, pFilter, pBssDesc, &pNewIes, &fMatch, &uc, &mc, &auth); - if (!CDF_IS_STATUS_SUCCESS(status)) + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, FL("save ies fail %d"), + status); break; + } /* * Modify the prefer value to honor PCL list */ @@ -2032,8 +2035,11 @@ csr_parse_scan_results(tpAniSirGlobal pMac, status = csr_save_scan_entry(pMac, pFilter, fMatch, pBssDesc, pNewIes, pRetList, count, uc, mc, &auth); - if (!CDF_IS_STATUS_SUCCESS(status)) + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, FL("save entry fail %d"), + status); break; + } pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK); } /* while */ @@ -2055,14 +2061,17 @@ CDF_STATUS csr_scan_get_result(tpAniSirGlobal pMac, csr_prefer_5ghz(pMac, pFilter); pRetList = cdf_mem_malloc(sizeof(tScanResultList)); - if (NULL == pRetList) + if (NULL == pRetList) { + sms_log(pMac, LOGE, FL("pRetList is NULL")); return CDF_STATUS_E_NOMEM; + } cdf_mem_set(pRetList, sizeof(tScanResultList), 0); csr_ll_open(pMac->hHdd, &pRetList->List); pRetList->pCurEntry = NULL; status = csr_parse_scan_results(pMac, pFilter, pRetList, &count); - sms_log(pMac, LOG2, FL("return %d BSS"), csr_ll_count(&pRetList->List)); + sms_log(pMac, LOG1, FL("return %d BSS %d"), + csr_ll_count(&pRetList->List), status); if (!CDF_IS_STATUS_SUCCESS(status) || (phResult == NULL)) { /* Fail or No one wants the result. */ csr_scan_result_purge(pMac, (tScanResultHandle) pRetList); @@ -3654,9 +3663,11 @@ void csr_reinit_scan_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) eCsrScanCompleteNextCommand csr_scan_get_next_command_state(tpAniSirGlobal pMac, tSmeCmd *pCommand, - bool fSuccess) + bool fSuccess, + uint8_t *chan) { eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing; + int8_t channel; switch (pCommand->u.scanCmd.reason) { case eCsrScan11d1: @@ -3688,9 +3699,35 @@ eCsrScanCompleteNextCommand csr_scan_get_next_command_state(tpAniSirGlobal pMac, eCsrNextLostLinkScan3Failed; break; case eCsrScanForSsid: - NextCommand = - (fSuccess) ? eCsrNexteScanForSsidSuccess : - eCsrNexteScanForSsidFailure; + /* When policy manager is disabled: + * success: csr_scan_handle_search_for_ssid + * failure: csr_scan_handle_search_for_ssid_failure + * + * When policy manager is enabled: + * success: + * set hw_mode success -> csr_scan_handle_search_for_ssid + * set hw_mode fail -> csr_scan_handle_search_for_ssid_failure + * failure: csr_scan_handle_search_for_ssid_failure + */ + if (pMac->policy_manager_enabled) { + sms_log(pMac, LOG1, FL("Resp for eCsrScanForSsid")); + channel = cds_search_and_check_for_session_conc( + pCommand->sessionId, + pCommand->u.scanCmd.pToRoamProfile); + if ((!channel) || !fSuccess) { + NextCommand = eCsrNexteScanForSsidFailure; + sms_log(pMac, LOG1, + FL("next ScanForSsidFailure %d %d"), + channel, fSuccess); + } else { + NextCommand = eCsrNextCheckAllowConc; + *chan = channel; + sms_log(pMac, LOG1, FL("next CheckAllowConc")); + } + } else { + NextCommand = (fSuccess) ? eCsrNexteScanForSsidSuccess : + eCsrNexteScanForSsidFailure; + } break; default: NextCommand = eCsrNextScanNothing; @@ -3789,12 +3826,122 @@ csr_diag_scan_complete(tpAniSirGlobal pMac, } #endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ +/** + * csr_save_profile() - Save the profile info from sme command + * @mac_ctx: Global MAC context + * @save_cmd: Pointer where the command will be saved + * @command: Command from which the profile will be saved + * + * Saves the profile information from the SME's scan command + * + * Return: CDF_STATUS + */ +CDF_STATUS csr_save_profile(tpAniSirGlobal mac_ctx, + tSmeCmd *save_cmd, tSmeCmd *command) +{ + tCsrScanResult *scan_result; + tCsrScanResult *temp; + uint32_t bss_len; + CDF_STATUS status; + + save_cmd->u.scanCmd.pToRoamProfile = + cdf_mem_malloc(sizeof(tCsrRoamProfile)); + if (!save_cmd->u.scanCmd.pToRoamProfile) { + sms_log(mac_ctx, LOGE, FL("pToRoamProfile mem fail")); + goto error; + } + + status = csr_roam_copy_profile(mac_ctx, + save_cmd->u.scanCmd.pToRoamProfile, + command->u.scanCmd.pToRoamProfile); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("csr_roam_copy_profile fail")); + goto error; + } + + save_cmd->sessionId = command->sessionId; + save_cmd->u.scanCmd.roamId = command->u.scanCmd.roamId; + save_cmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = + command->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs; + save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList = + cdf_mem_malloc( + save_cmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs * + sizeof(tCsrSSIDInfo)); + if (!save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList) { + sms_log(mac_ctx, LOGE, FL("SSIDList mem fail")); + goto error; + } + + cdf_mem_copy(save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList, + command->u.scanCmd.u.scanRequest.SSIDs.SSIDList, + save_cmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs * + sizeof(tCsrSSIDInfo)); + + if (!command->u.roamCmd.pRoamBssEntry) + return CDF_STATUS_SUCCESS; + + scan_result = GET_BASE_ADDR(command->u.roamCmd.pRoamBssEntry, + tCsrScanResult, Link); + + bss_len = scan_result->Result.BssDescriptor.length + + sizeof(scan_result->Result.BssDescriptor.length); + + temp = cdf_mem_malloc(sizeof(tCsrScanResult) + bss_len); + if (!temp) { + sms_log(mac_ctx, LOGE, FL("bss mem fail")); + goto error; + } + + temp->AgingCount = scan_result->AgingCount; + temp->preferValue = scan_result->preferValue; + temp->capValue = scan_result->capValue; + temp->ucEncryptionType = scan_result->ucEncryptionType; + temp->mcEncryptionType = scan_result->mcEncryptionType; + temp->authType = scan_result->authType; + /* pvIes is unsued in success/failure */ + temp->Result.pvIes = NULL; + + cdf_mem_copy(temp->Result.pvIes, + scan_result->Result.pvIes, + sizeof(*scan_result->Result.pvIes)); + temp->Result.ssId.length = scan_result->Result.ssId.length; + cdf_mem_copy(temp->Result.ssId.ssId, + scan_result->Result.ssId.ssId, + sizeof(scan_result->Result.ssId.ssId)); + temp->Result.timer = scan_result->Result.timer; + cdf_mem_copy(&temp->Result.BssDescriptor, + &scan_result->Result.BssDescriptor, + sizeof(temp->Result.BssDescriptor)); + temp->Link.last = temp->Link.next = NULL; + save_cmd->u.roamCmd.pRoamBssEntry = (tListElem *)temp; + + return CDF_STATUS_SUCCESS; +error: + csr_scan_handle_search_for_ssid_failure(mac_ctx, + command); + if (save_cmd->u.roamCmd.pRoamBssEntry) + cdf_mem_free(save_cmd->u.roamCmd.pRoamBssEntry); + if (save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList) + cdf_mem_free(save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList); + if (save_cmd->u.scanCmd.pToRoamProfile) + cdf_mem_free(save_cmd->u.scanCmd.pToRoamProfile); + if (save_cmd) { + cdf_mem_free(save_cmd); + save_cmd = NULL; + } + + return CDF_STATUS_E_FAILURE; +} + static void csr_handle_nxt_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *pCommand, eCsrScanCompleteNextCommand *nxt_cmd, - bool *remove_cmd, uint32_t session_id) + bool *remove_cmd, uint32_t session_id, + uint8_t chan) { - CDF_STATUS status; + CDF_STATUS status, ret; + tSmeCmd *save_cmd = NULL; + switch (*nxt_cmd) { case eCsrNext11dScan1Success: case eCsrNext11dScan2Success: @@ -3852,6 +3999,54 @@ csr_handle_nxt_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *pCommand, case eCsrNexteScanForSsidFailure: csr_scan_handle_search_for_ssid_failure(mac_ctx, pCommand); break; + case eCsrNextCheckAllowConc: + ret = cds_current_connections_update(pCommand->sessionId, + chan, + CDS_UPDATE_REASON_HIDDEN_STA); + sms_log(mac_ctx, LOG1, FL("chan: %d session: %d status: %d"), + chan, pCommand->sessionId, ret); + if (mac_ctx->sme.saved_scan_cmd) { + cdf_mem_free(mac_ctx->sme.saved_scan_cmd); + mac_ctx->sme.saved_scan_cmd = NULL; + sms_log(mac_ctx, LOGE, + FL("memory should have been free. Check!")); + } + + save_cmd = (tSmeCmd *) cdf_mem_malloc(sizeof(*pCommand)); + if (!save_cmd) { + sms_log(mac_ctx, LOGE, FL("save_cmd mem fail")); + goto error; + } + + status = csr_save_profile(mac_ctx, save_cmd, pCommand); + if (!CDF_IS_STATUS_SUCCESS(status) || + !save_cmd) { + /* csr_save_profile should report error */ + sms_log(mac_ctx, LOGE, FL("profile save failed %d"), + status); + return; + } + + mac_ctx->sme.saved_scan_cmd = (void *)save_cmd; + + if (CDF_STATUS_E_FAILURE == ret) { +error: + sms_log(mac_ctx, LOGE, FL("conn update fail %d"), chan); + csr_scan_handle_search_for_ssid_failure(mac_ctx, + pCommand); + if (mac_ctx->sme.saved_scan_cmd) { + cdf_mem_free(mac_ctx->sme.saved_scan_cmd); + mac_ctx->sme.saved_scan_cmd = NULL; + } + } else if (CDF_STATUS_E_NOSUPPORT == ret) { + sms_log(mac_ctx, LOGE, FL("conn update not supported")); + csr_scan_handle_search_for_ssid(mac_ctx, pCommand); + if (mac_ctx->sme.saved_scan_cmd) { + cdf_mem_free(mac_ctx->sme.saved_scan_cmd); + mac_ctx->sme.saved_scan_cmd = NULL; + } + } + break; default: break; } @@ -3916,6 +4111,7 @@ bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp) bool fRemoveCommand = true; bool fSuccess; uint32_t sessionId = 0; + uint8_t chan; csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry); if (!pEntry) { @@ -3966,10 +4162,11 @@ bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp) #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR csr_diag_scan_complete(pMac, pCommand, pScanRsp); #endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ - NextCommand = csr_scan_get_next_command_state(pMac, pCommand, fSuccess); + NextCommand = csr_scan_get_next_command_state(pMac, pCommand, fSuccess, + &chan); /* We reuse the command here instead reissue a new command */ csr_handle_nxt_cmd(pMac, pCommand, &NextCommand, - &fRemoveCommand, sessionId); + &fRemoveCommand, sessionId, chan); return fRemoveCommand; } diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 16797840820a..0c7fef801057 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -123,6 +123,7 @@ typedef enum { eCsrNext11dScan2Success, eCsrNext11dScanComplete, eCsrNexteScanForSsidFailure, + eCsrNextCheckAllowConc, } eCsrScanCompleteNextCommand; @@ -1060,6 +1061,10 @@ void csr_clear_votes_for_country_info(tpAniSirGlobal pMac); CDF_STATUS csr_set_ht2040_mode(tpAniSirGlobal pMac, uint32_t sessionId, ePhyChanBondState cbMode, bool obssEnabled); #endif +CDF_STATUS csr_scan_handle_search_for_ssid(tpAniSirGlobal mac, + tSmeCmd *command); +CDF_STATUS csr_scan_handle_search_for_ssid_failure(tpAniSirGlobal mac, + tSmeCmd *command); tSirBssDescription* csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle, tSirBssDescription *bss_descr);