diff options
| -rw-r--r-- | core/cds/inc/cds_concurrency.h | 20 | ||||
| -rw-r--r-- | core/cds/inc/cds_sched.h | 3 | ||||
| -rw-r--r-- | core/cds/src/cds_concurrency.c | 58 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.c | 64 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_hostapd.c | 16 | ||||
| -rw-r--r-- | core/sme/src/csr/csr_api_roam.c | 18 | ||||
| -rw-r--r-- | core/wma/inc/wma_api.h | 3 | ||||
| -rw-r--r-- | core/wma/src/wma_utils.c | 45 |
8 files changed, 213 insertions, 14 deletions
diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index e65545c95e71..d5ba8c555e51 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -577,6 +577,24 @@ enum cds_band { }; /** + * enum cds_hw_mode_change - identify the HW mode switching to. + * + * @CDS_HW_MODE_NOT_IN_PROGRESS: HW mode change not in progress + * @CDS_SMM_IN_PROGRESS: switching to SMM mode + * @CDS_DBS_IN_PROGRESS: switching to DBS mode + * @CDS_SBS_IN_PROGRESS: switching to SBS mode + * + * These are generic IDs that identify the various roles + * in the software system + */ +enum cds_hw_mode_change { + CDS_HW_MODE_NOT_IN_PROGRESS = 0, + CDS_SMM_IN_PROGRESS, + CDS_DBS_IN_PROGRESS, + CDS_SBS_IN_PROGRESS +}; + +/** * struct cds_conc_connection_info - information of all existing * connections in the wlan system * @@ -858,4 +876,6 @@ void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, uint32_t new_hw_mode_index, uint32_t num_vdev_mac_entries, struct sir_vdev_mac_map *vdev_mac_map); +void cds_set_hw_mode_change_in_progress(enum cds_hw_mode_change value); +enum cds_hw_mode_change cds_is_hw_mode_change_in_progress(void); #endif /* __CDS_CONCURRENCY_H */ diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index 7a52b40cccaa..3b34c426a4e4 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -327,6 +327,9 @@ typedef struct _cds_context_type { bool do_hw_mode_change; bool enable_fatal_event; struct cds_config_info *cds_cfg; + + /* This is to track if HW mode change is in progress */ + uint32_t hw_mode_change_in_progress; } cds_context_type, *p_cds_contextType; /*--------------------------------------------------------------------------- diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 6bb5ff76f10b..3424cba69de2 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -2500,6 +2500,8 @@ static void cds_pdev_set_hw_mode_cb(uint32_t status, struct sir_hw_mode_params hw_mode; uint32_t i; + cds_set_hw_mode_change_in_progress(CDS_HW_MODE_NOT_IN_PROGRESS); + if (status != SET_HW_MODE_STATUS_OK) { cds_err("Set HW mode failed with status %d", status); return; @@ -4239,6 +4241,7 @@ QDF_STATUS cds_init_policy_mgr(struct cds_sme_cbacks *sme_cbacks) } cds_ctx->do_hw_mode_change = false; + cds_ctx->hw_mode_change_in_progress = CDS_HW_MODE_NOT_IN_PROGRESS; cds_ctx->sme_get_valid_channels = sme_cbacks->sme_get_valid_channels; cds_ctx->sme_get_nss_for_vdev = sme_cbacks->sme_get_nss_for_vdev; @@ -9596,3 +9599,58 @@ bool cds_is_hw_mode_change_after_vdev_up(void) return flag; } + +/** + * cds_set_hw_mode_change_in_progress() - Set value corresponding to + * cds_hw_mode_change that indicate if HW mode change is in progress + * @value: Indicate if hw mode change is in progress + * + * Set the value corresponding to cds_hw_mode_change that + * indicated if hw mode change is in progress. + * + * Return: None + */ +void cds_set_hw_mode_change_in_progress(enum cds_hw_mode_change value) +{ + cds_context_type *cds_ctx; + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return; + } + + qdf_mutex_acquire(&cds_ctx->qdf_conc_list_lock); + cds_ctx->hw_mode_change_in_progress = value; + qdf_mutex_release(&cds_ctx->qdf_conc_list_lock); + + cds_debug("hw_mode_change_in_progress:%d", value); +} + +/** + * cds_is_hw_mode_change_in_progress() - Check if HW mode change is in + * progress. + * + * Returns the corresponding cds_hw_mode_change value. + * + * Return: cds_hw_mode_change value. + */ +enum cds_hw_mode_change cds_is_hw_mode_change_in_progress(void) +{ + cds_context_type *cds_ctx; + enum cds_hw_mode_change value; + value = CDS_HW_MODE_NOT_IN_PROGRESS; + + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return value; + } + + qdf_mutex_acquire(&cds_ctx->qdf_conc_list_lock); + value = cds_ctx->hw_mode_change_in_progress; + qdf_mutex_release(&cds_ctx->qdf_conc_list_lock); + + return value; +} diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index f104fdb63604..af52481706b9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -11912,11 +11912,18 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, status = wlan_hdd_validate_context(pHddCtx); if (status) - return status; + goto ret_status; if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) { hdd_err("wrong SSID len"); - return -EINVAL; + status = -EINVAL; + goto ret_status; + } + + if (true == cds_is_connection_in_progress(NULL, NULL)) { + hdd_err("Connection refused: conn in progress"); + status = -EINVAL; + goto ret_status; } pRoamProfile = &pWextState->roamProfile; @@ -11927,6 +11934,24 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, hdd_station_ctx_t *pHddStaCtx; pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + /* Restart the opportunistic timer + * + * If hw_mode_change_in_progress is true, then wait + * till firmware sends the callback for hw_mode change. + * + * Else set connect_in_progress as true and proceed. + */ + cds_restart_opportunistic_timer(false); + if (cds_is_hw_mode_change_in_progress()) { + status = qdf_wait_for_connection_update(); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("qdf wait for event failed!!"); + status = -EINVAL; + goto ret_status; + } + } + cds_set_connection_in_progress(true); + if (HDD_WMM_USER_MODE_NO_QOS == (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) { /*QoS not enabled in cfg file */ @@ -12058,7 +12083,8 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, if (QDF_STATUS_SUCCESS != status) { hdd_err("Set IBSS Power Save Params Failed"); - return -EINVAL; + status = -EINVAL; + goto conn_failure; } pRoamProfile->ch_params.ch_width = hdd_map_nl_chan_width(ch_width); @@ -12084,12 +12110,8 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, pWextState->roamProfile.MFPEnabled, pWextState->roamProfile.MFPRequired, pWextState->roamProfile.MFPCapable); - return -EINVAL; - } - - if (true == cds_is_connection_in_progress(NULL, NULL)) { - hdd_err("Connection refused: conn in progress"); - return -EINVAL; + status = -EINVAL; + goto conn_failure; } /* @@ -12116,8 +12138,10 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, if (wma_is_hw_dbs_capable() == false) { cds_handle_conc_rule1(pAdapter, pRoamProfile); if (true != cds_handle_conc_rule2( - pAdapter, pRoamProfile, &roamId)) - return 0; + pAdapter, pRoamProfile, &roamId)) { + status = 0; + goto conn_failure; + } } if ((wma_is_hw_dbs_capable() == true) && @@ -12126,7 +12150,8 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, hdd_err("sap-sta conc will fail, can't allow sta"); hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected); - return -ENOMEM; + status = -ENOMEM; + goto conn_failure; } sme_config = qdf_mem_malloc(sizeof(*sme_config)); @@ -12134,7 +12159,8 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, hdd_err("unable to allocate sme_config"); hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected); - return -ENOMEM; + status = -ENOMEM; + goto conn_failure; } sme_get_config_param(pHddCtx->hHal, sme_config); /* These values are not sessionized. So, any change in these SME @@ -12192,6 +12218,9 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, connect); } + /* Reset connect_in_progress */ + cds_set_connection_in_progress(false); + pRoamProfile->ChannelInfo.ChannelList = NULL; pRoamProfile->ChannelInfo.numOfChannels = 0; @@ -12206,8 +12235,15 @@ static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, } else { hdd_err("No valid Roam profile"); - return -EINVAL; + status = -EINVAL; } + goto ret_status; + +conn_failure: + /* Reset connect_in_progress */ + cds_set_connection_in_progress(false); + +ret_status: EXIT(); return status; } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 19c99cbd4fcd..33244a0bab62 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -7277,6 +7277,14 @@ int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, return -EINVAL; } + if (cds_is_hw_mode_change_in_progress()) { + status = qdf_wait_for_connection_update(); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("qdf wait for event failed!!"); + return -EINVAL; + } + } + iniConfig = pHddCtx->config; pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); @@ -8144,6 +8152,14 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, return -EBUSY; } + if (cds_is_hw_mode_change_in_progress()) { + status = qdf_wait_for_connection_update(); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("qdf wait for event failed!!"); + return -EINVAL; + } + } + channel_width = wlan_hdd_get_channel_bw(params->chandef.width); channel = ieee80211_frequency_to_channel( params->chandef.chan->center_freq); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index fffb6990a7d5..adf92d4dd481 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -19430,6 +19430,7 @@ void csr_process_set_hw_mode(tpAniSirGlobal mac, tSmeCmd *command) QDF_STATUS status; tSirMsgQ msg; struct sir_set_hw_mode_resp *param; + enum cds_hw_mode_change cds_hw_mode; /* Setting HW mode is for the entire system. * So, no need to check session @@ -19463,6 +19464,22 @@ void csr_process_set_hw_mode(tpAniSirGlobal mac, tSmeCmd *command) } } + if ((SIR_UPDATE_REASON_OPPORTUNISTIC == + command->u.set_hw_mode_cmd.reason) && + (true == cds_is_connection_in_progress(NULL, NULL))) { + sms_log(mac, LOGE, FL("Set HW mode refused: conn in progress")); + cds_restart_opportunistic_timer(false); + goto fail; + } + + cds_hw_mode = wma_get_cds_hw_mode_change_from_hw_mode_index( + command->u.set_hw_mode_cmd.hw_mode_index); + + if (CDS_HW_MODE_NOT_IN_PROGRESS == cds_hw_mode) + goto fail; + + cds_set_hw_mode_change_in_progress(cds_hw_mode); + 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; @@ -19480,6 +19497,7 @@ void csr_process_set_hw_mode(tpAniSirGlobal mac, tSmeCmd *command) status = cds_send_mb_message_to_mac(cmd); if (QDF_STATUS_SUCCESS != status) { + cds_set_hw_mode_change_in_progress(CDS_HW_MODE_NOT_IN_PROGRESS); sms_log(mac, LOGE, FL("Posting to PE failed")); return; } diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 52cb5b7d65ac..b4f28168f4da 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -236,6 +236,9 @@ void wma_set_dbs_capability_ut(uint32_t dbs); QDF_STATUS wma_get_dbs_hw_modes(bool *one_by_one_dbs, bool *two_by_two_dbs); QDF_STATUS wma_get_current_hw_mode(struct sir_hw_mode_params *hw_mode); bool wma_is_dbs_enable(void); +enum cds_hw_mode_change +wma_get_cds_hw_mode_change_from_hw_mode_index(uint32_t hw_mode_index); + QDF_STATUS wma_get_updated_scan_config(uint32_t *scan_config, bool dbs_scan, bool dbs_plus_agile_scan, diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index dc46ad2640a6..0a7dbd081921 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -3062,6 +3062,51 @@ bool wma_is_hw_dbs_capable(void) } /** + * wma_get_cds_hw_mode_change_from_hw_mode_index - Returns value in terms of + * cds_hw_mode_change enums derived from hw_mode_index. + * + * Returns cds_hw_mode_change value derived from hw_mode_index. + * + * Return: value in terms of cds_hw_mode_change enums. + */ +enum cds_hw_mode_change +wma_get_cds_hw_mode_change_from_hw_mode_index(uint32_t hw_mode_index) +{ + tp_wma_handle wma; + uint32_t param = 0; + enum cds_hw_mode_change value = CDS_HW_MODE_NOT_IN_PROGRESS; + + wma = cds_get_context(QDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + goto ret_value; + } + + WMA_LOGI("%s: HW param: %x", __func__, param); + + param = wma->hw_mode.hw_mode_list[hw_mode_index]; + if (WMA_HW_MODE_DBS_MODE_GET(param)) { + WMA_LOGI("%s: DBS is requested with HW (%d)", __func__, + hw_mode_index); + value = CDS_DBS_IN_PROGRESS; + goto ret_value; + } + + if (WMA_HW_MODE_SBS_MODE_GET(param)) { + WMA_LOGI("%s: SBS is requested with HW (%d)", __func__, + hw_mode_index); + value = CDS_SBS_IN_PROGRESS; + goto ret_value; + } + + value = CDS_SMM_IN_PROGRESS; + WMA_LOGI("%s: SMM is requested with HW (%d)", __func__, + hw_mode_index); +ret_value: + return value; +} + +/** * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev * @vdev_id: VDEV whose MAC ID is required * |
