summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/cds/inc/cds_concurrency.h20
-rw-r--r--core/cds/inc/cds_sched.h3
-rw-r--r--core/cds/src/cds_concurrency.c58
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c64
-rw-r--r--core/hdd/src/wlan_hdd_hostapd.c16
-rw-r--r--core/sme/src/csr/csr_api_roam.c18
-rw-r--r--core/wma/inc/wma_api.h3
-rw-r--r--core/wma/src/wma_utils.c45
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
*