diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 08e4d8fe4bbf..ae2fb200467f 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -39,7 +39,6 @@ #include "wlan_hdd_main.h" #define MAX_NUMBER_OF_CONC_CONNECTIONS 3 -#define MAX_NUM_CHAN 128 #define DBS_OPPORTUNISTIC_TIME 10 #ifdef QCA_WIFI_3_0_EMU #define CONNECTION_UPDATE_TIMEOUT 3000 @@ -643,7 +642,8 @@ void cds_decr_active_session(enum tQDF_ADAPTER_MODE mode, uint8_t sessionId); void cds_decr_session_set_pcl(enum tQDF_ADAPTER_MODE mode, uint8_t session_id); -QDF_STATUS cds_init_policy_mgr(void); +QDF_STATUS cds_init_policy_mgr( + QDF_STATUS (*sme_get_valid_chans)(void*, uint8_t *, uint32_t *)); QDF_STATUS cds_deinit_policy_mgr(void); QDF_STATUS cds_get_pcl(enum cds_con_mode mode, uint8_t *pcl_channels, uint32_t *len, @@ -751,6 +751,17 @@ QDF_STATUS cds_stop_start_opportunistic_timer(void); QDF_STATUS cds_handle_hw_mode_change_on_csa(uint16_t session_id, uint8_t channel, uint8_t *bssid, void *dst, void *src, uint32_t numbytes); +QDF_STATUS cds_modify_sap_pcl_based_on_mandatory_channel(uint8_t *pcl_list_org, + uint8_t *weight_list_org, + uint32_t *pcl_len_org); +QDF_STATUS cds_update_and_wait_for_connection_update(uint8_t session_id, + uint8_t channel, enum sir_conn_update_reason reason); +bool cds_is_sap_mandatory_channel_set(void); +bool cds_list_has_24GHz_channel(uint8_t *channel_list, uint32_t list_len); +QDF_STATUS cds_get_valid_chans(uint8_t *chan_list, uint32_t *list_len); +QDF_STATUS cds_get_sap_mandatory_channel(uint32_t *chan); +QDF_STATUS cds_set_sap_mandatory_channels(uint8_t *channels, uint32_t len); +QDF_STATUS cds_reset_sap_mandatory_channels(void); #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH QDF_STATUS cds_register_sap_restart_channel_switch_cb( void (*sap_restart_chan_switch_cb)(void *, uint32_t, uint32_t)); diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index b5ab151a5e1e..bd45ab153914 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -296,6 +296,13 @@ typedef struct _cds_context_type { #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH void (*sap_restart_chan_switch_cb)(void *, uint32_t, uint32_t); #endif + QDF_STATUS (*sme_get_valid_chans)(void*, uint8_t *, uint32_t *); + /* This list is not sessionized. This mandatory channel list would be + * as per OEMs preference as per the regulatory/other considerations. + * So, this would remain same for all the interfaces. + */ + uint8_t sap_mandatory_channels[QDF_MAX_NUM_CHAN]; + uint32_t sap_mandatory_channels_len; bool do_hw_mode_change; bool enable_fatal_event; } cds_context_type, *p_cds_contextType; diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 7fb5455f0b8b..72604bb412cd 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3758,11 +3758,14 @@ QDF_STATUS cds_get_pcl_for_existing_conn(enum cds_con_mode mode, cds_err("Invalid CDS Context"); return QDF_STATUS_E_INVAL; } + + cds_info("get pcl for existing conn:%d", mode); + qdf_mutex_acquire(&cds_ctx->qdf_conc_list_lock); if (cds_mode_specific_connection_count(mode, NULL) > 0) { /* Check, store and temp delete the mode's parameter */ cds_store_and_del_conn_info(mode, &info); - /* Set the PCL to the FW since connection got updated */ + /* Get the PCL */ status = cds_get_pcl(mode, pcl_ch, len, pcl_weight, weight_len); cds_info("Get PCL to FW for mode:%d", mode); /* Restore the connection info */ @@ -3956,6 +3959,13 @@ QDF_STATUS cds_deinit_policy_mgr(void) return QDF_STATUS_E_FAILURE; } + cds_ctx->sme_get_valid_chans = NULL; + + if (QDF_IS_STATUS_ERROR(cds_reset_sap_mandatory_channels())) { + cds_err("failed to reset sap mandatory channels"); + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; } @@ -3967,7 +3977,8 @@ QDF_STATUS cds_deinit_policy_mgr(void) * * Return: Success if the policy manager is initialized completely */ -QDF_STATUS cds_init_policy_mgr(void) +QDF_STATUS cds_init_policy_mgr( + QDF_STATUS (*sme_get_valid_chans)(void*, uint8_t *, uint32_t *)) { QDF_STATUS status; hdd_context_t *hdd_ctx; @@ -4015,6 +4026,13 @@ QDF_STATUS cds_init_policy_mgr(void) } cds_ctx->do_hw_mode_change = false; + cds_ctx->sme_get_valid_chans = sme_get_valid_chans; + + status = cds_reset_sap_mandatory_channels(); + if (QDF_IS_STATUS_ERROR(status)) { + cds_err("failed to reset mandatory channels"); + return status; + } return QDF_STATUS_SUCCESS; } @@ -4502,9 +4520,9 @@ QDF_STATUS cds_get_connection_channels(uint8_t *channels, void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len, uint8_t *weight_list, uint32_t weight_len) { - uint16_t unsafe_channel_list[MAX_NUM_CHAN]; - uint8_t current_channel_list[MAX_NUM_CHAN]; - uint8_t org_weight_list[MAX_NUM_CHAN]; + uint16_t unsafe_channel_list[QDF_MAX_NUM_CHAN]; + uint8_t current_channel_list[QDF_MAX_NUM_CHAN]; + uint8_t org_weight_list[QDF_MAX_NUM_CHAN]; uint16_t unsafe_channel_count = 0; uint8_t is_unsafe = 1; uint8_t i, j; @@ -4517,7 +4535,7 @@ void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len, } if (len) { - current_channel_count = QDF_MIN(*len, MAX_NUM_CHAN); + current_channel_count = QDF_MIN(*len, QDF_MAX_NUM_CHAN); } else { cds_err("invalid number of channel length"); return; @@ -4534,7 +4552,7 @@ void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len, qdf_mem_zero(pcl_channels, sizeof(*pcl_channels)*current_channel_count); - qdf_mem_copy(org_weight_list, weight_list, MAX_NUM_CHAN); + qdf_mem_copy(org_weight_list, weight_list, QDF_MAX_NUM_CHAN); qdf_mem_zero(weight_list, weight_len); for (i = 0; i < current_channel_count; i++) { @@ -4586,9 +4604,9 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, QDF_STATUS status = QDF_STATUS_E_FAILURE; uint32_t num_channels = WNI_CFG_VALID_CHANNEL_LIST_LEN; uint32_t chan_index = 0, chan_index_24 = 0, chan_index_5 = 0; - uint8_t channel_list[MAX_NUM_CHAN] = {0}; - uint8_t channel_list_24[MAX_NUM_CHAN] = {0}; - uint8_t channel_list_5[MAX_NUM_CHAN] = {0}; + uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0}; + uint8_t channel_list_24[QDF_MAX_NUM_CHAN] = {0}; + uint8_t channel_list_5[QDF_MAX_NUM_CHAN] = {0}; bool skip_dfs_channel = false; hdd_context_t *hdd_ctx; uint32_t i = 0, j = 0; @@ -4616,11 +4634,9 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, return QDF_STATUS_SUCCESS; } /* get the channel list for current domain */ - status = sme_get_cfg_valid_channels(hdd_ctx->hHal, channel_list, - &num_channels); - if (QDF_STATUS_SUCCESS != status) { - /* err msg*/ - cds_err("No valid channel"); + status = cds_get_valid_chans(channel_list, &num_channels); + if (QDF_IS_STATUS_ERROR(status)) { + cds_err("Error in getting valid channels"); return status; } @@ -4636,7 +4652,7 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, /* Let's divide the list in 2.4 & 5 Ghz lists */ while ((channel_list[chan_index] <= 11) && - (chan_index_24 < MAX_NUM_CHAN)) + (chan_index_24 < QDF_MAX_NUM_CHAN)) channel_list_24[chan_index_24++] = channel_list[chan_index++]; if (channel_list[chan_index] == 12) { channel_list_24[chan_index_24++] = channel_list[chan_index++]; @@ -4649,7 +4665,8 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, } } - while ((chan_index < num_channels) && (chan_index_5 < MAX_NUM_CHAN)) { + while ((chan_index < num_channels) && + (chan_index_5 < QDF_MAX_NUM_CHAN)) { if ((true == skip_dfs_channel) && CDS_IS_DFS_CH(channel_list[chan_index])) { chan_index++; @@ -4933,7 +4950,7 @@ QDF_STATUS cds_get_pcl(enum cds_con_mode mode, uint8_t *pcl_weight, uint32_t weight_len) { QDF_STATUS status = QDF_STATUS_E_FAILURE; - uint32_t num_connections = 0; + uint32_t num_connections = 0, i; enum cds_conc_priority_mode first_index = 0; enum cds_one_connection_mode second_index = 0; enum cds_two_connection_mode third_index = 0; @@ -5020,15 +5037,32 @@ QDF_STATUS cds_get_pcl(enum cds_con_mode mode, */ status = cds_get_channel_list(pcl, pcl_channels, len, mode, pcl_weight, weight_len); - if (status == QDF_STATUS_SUCCESS) { - uint32_t i; - cds_debug("pcl len:%d", *len); - for (i = 0; i < *len; i++) - cds_debug("chan:%d weight:%d", + if (QDF_IS_STATUS_ERROR(status)) { + cds_err("failed to get channel list:%d", status); + return status; + } + + cds_debug("pcl len:%d", *len); + for (i = 0; i < *len; i++) { + cds_debug("chan:%d weight:%d", pcl_channels[i], pcl_weight[i]); } - return status; + if ((mode == CDS_SAP_MODE) && cds_is_sap_mandatory_channel_set()) { + status = cds_modify_sap_pcl_based_on_mandatory_channel( + pcl_channels, pcl_weight, len); + if (QDF_IS_STATUS_ERROR(status)) { + cds_err("failed to get modified pcl for SAP"); + return status; + } + cds_debug("modified pcl len:%d", *len); + for (i = 0; i < *len; i++) + cds_debug("chan:%d weight:%d", + pcl_channels[i], pcl_weight[i]); + + } + + return QDF_STATUS_SUCCESS; } /** @@ -5898,6 +5932,49 @@ enum cds_two_connection_mode cds_get_third_connection_pcl_table_index(void) return index; } +/** + * cds_update_and_wait_for_connection_update() - Update and wait for + * connection update + * @session_id: Session id + * @channel: Channel number + * @reason: Reason for connection update + * + * Update the connection to either single MAC or dual MAC and wait for the + * update to complete + * + * Return: QDF_STATUS + */ +QDF_STATUS cds_update_and_wait_for_connection_update(uint8_t session_id, + uint8_t channel, + enum sir_conn_update_reason reason) +{ + QDF_STATUS status; + + cds_debug("session:%d channel:%d reason:%d", + session_id, channel, reason); + + status = qdf_reset_connection_update(); + if (QDF_IS_STATUS_ERROR(status)) + cds_err("clearing event failed"); + + status = cds_current_connections_update(session_id, channel, reason); + if (QDF_STATUS_E_FAILURE == status) { + cds_err("connections update failed"); + return QDF_STATUS_E_FAILURE; + } + + /* Wait only when status is success */ + if (QDF_IS_STATUS_SUCCESS(status)) { + status = qdf_wait_for_connection_update(); + if (QDF_IS_STATUS_ERROR(status)) { + cds_err("qdf wait for event failed"); + return QDF_STATUS_E_FAILURE; + } + } + + return QDF_STATUS_SUCCESS; +} + /** * cds_current_connections_update() - initiates actions * needed on current connections once channel has been decided @@ -7003,8 +7080,10 @@ static void cds_check_sta_ap_concurrent_ch_intf(void *data) hdd_ap_ctx->sapConfig.sec_ch, &hdd_ap_ctx->sapConfig.ch_params); - if ((hdd_ctx->config->WlanMccToSccSwitchMode == - QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION) && + if (((hdd_ctx->config->WlanMccToSccSwitchMode == + QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION) || + (hdd_ctx->config->WlanMccToSccSwitchMode == + QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL)) && (cds_ctx->sap_restart_chan_switch_cb)) { cds_info("SAP chan change without restart"); cds_ctx->sap_restart_chan_switch_cb(ap_adapter, @@ -7797,7 +7876,7 @@ QDF_STATUS cds_decr_connection_count_utfw(uint32_t del_all, } if (del_all) { - status = cds_init_policy_mgr(); + status = cds_init_policy_mgr(sme_get_cfg_valid_channels); if (!QDF_IS_STATUS_SUCCESS(status)) { cds_err("Policy manager initialization failed"); return QDF_STATUS_E_FAILURE; @@ -8406,6 +8485,279 @@ bool cds_is_any_nondfs_chnl_present(uint8_t *channel) return status; } +/** + * cds_get_valid_chans() - Get the valid channel list + * @chan_list: Pointer to the valid channel list + * @list_len: Pointer to the length of the valid channel list + * + * Gets the valid channel list filtered by band + * + * Return: QDF_STATUS + */ +QDF_STATUS cds_get_valid_chans(uint8_t *chan_list, uint32_t *list_len) +{ + QDF_STATUS status; + hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; + + *list_len = 0; + + hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return QDF_STATUS_E_FAILURE; + } + + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return QDF_STATUS_E_FAILURE; + } + + if (!cds_ctx->sme_get_valid_chans) { + cds_err("sme_get_valid_chans callback is NULL"); + return QDF_STATUS_E_FAILURE; + } + + *list_len = QDF_MAX_NUM_CHAN; + status = cds_ctx->sme_get_valid_chans(hdd_ctx->hHal, + chan_list, list_len); + if (QDF_IS_STATUS_ERROR(status)) { + cds_err("Error in getting valid channels"); + *list_len = 0; + return status; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * cds_list_has_24GHz_channel() - Check if list contains 2.4GHz channels + * @channel_list: Channel list + * @list_len: Length of the channel list + * + * Checks if the channel list contains atleast one 2.4GHz channel + * + * Return: True if 2.4GHz channel is present, false otherwise + */ +bool cds_list_has_24GHz_channel(uint8_t *channel_list, + uint32_t list_len) +{ + uint32_t i; + + for (i = 0; i < list_len; i++) { + if (CDS_IS_CHANNEL_24GHZ(channel_list[i])) + return true; + } + + return false; +} + +/** + * cds_set_sap_mandatory_channels() - Set the mandatory channel for SAP + * @channels: Channel list to be set + * @len: Length of the channel list + * + * Sets the channels for the mandatory channel list along with the length of + * of the channel list. + * + * Return: QDF_STATUS + */ +QDF_STATUS cds_set_sap_mandatory_channels(uint8_t *channels, uint32_t len) +{ + cds_context_type *cds_ctx; + uint32_t i; + + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return QDF_STATUS_E_FAILURE; + } + + if (!len) { + cds_err("No mandatory freq/chan configured"); + return QDF_STATUS_E_FAILURE; + } + + if (!cds_list_has_24GHz_channel(channels, len)) { + cds_err("2.4GHz channels missing, this is not expected"); + return QDF_STATUS_E_FAILURE; + } + + cds_debug("mandatory chan length:%d", + cds_ctx->sap_mandatory_channels_len); + + for (i = 0; i < len; i++) { + cds_ctx->sap_mandatory_channels[i] = channels[i]; + cds_debug("chan:%d", cds_ctx->sap_mandatory_channels[i]); + } + + cds_ctx->sap_mandatory_channels_len = len; + + return QDF_STATUS_SUCCESS; +} + +/** + * cds_reset_sap_mandatory_channels() - Reset the SAP mandatory channels + * + * Resets the SAP mandatory channel list and the length of the list + * + * Return: QDF_STATUS + */ +QDF_STATUS cds_reset_sap_mandatory_channels(void) +{ + cds_context_type *cds_ctx; + + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return QDF_STATUS_E_FAILURE; + } + + cds_ctx->sap_mandatory_channels_len = 0; + qdf_mem_zero(cds_ctx->sap_mandatory_channels, + QDF_ARRAY_SIZE(cds_ctx->sap_mandatory_channels)); + + return QDF_STATUS_SUCCESS; +} + +/** + * cds_is_sap_mandatory_channel_set() - Checks if SAP mandatory channel is set + * + * Checks if any mandatory channel is set for SAP operation + * + * Return: True if mandatory channel is set, false otherwise + */ +bool cds_is_sap_mandatory_channel_set(void) +{ + cds_context_type *cds_ctx; + + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return false; + } + + if (cds_ctx->sap_mandatory_channels_len) + return true; + else + return false; +} + +/** + * cds_modify_sap_pcl_based_on_mandatory_channel() - Modify SAPs PCL based on + * mandatory channel list + * @pcl_list_org: Pointer to the preferred channel list to be trimmed + * @weight_list_org: Pointer to the weights of the preferred channel list + * @pcl_len_org: Pointer to the length of the preferred chanel list + * + * Modifies the preferred channel list of SAP based on the mandatory channel + * + * Return: QDF_STATUS + */ +QDF_STATUS cds_modify_sap_pcl_based_on_mandatory_channel(uint8_t *pcl_list_org, + uint8_t *weight_list_org, + uint32_t *pcl_len_org) +{ + cds_context_type *cds_ctx; + uint32_t i, j, pcl_len = 0; + uint8_t pcl_list[QDF_MAX_NUM_CHAN]; + uint8_t weight_list[QDF_MAX_NUM_CHAN]; + bool found; + + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return QDF_STATUS_E_FAILURE; + } + + if (!cds_ctx->sap_mandatory_channels_len) + return QDF_STATUS_SUCCESS; + + if (!cds_list_has_24GHz_channel(cds_ctx->sap_mandatory_channels, + cds_ctx->sap_mandatory_channels_len)) { + cds_err("fav channel list is missing 2.4GHz channels"); + return QDF_STATUS_E_FAILURE; + } + + for (i = 0; i < cds_ctx->sap_mandatory_channels_len; i++) + cds_debug("fav chan:%d", cds_ctx->sap_mandatory_channels[i]); + + for (i = 0; i < *pcl_len_org; i++) { + found = false; + for (j = 0; j < cds_ctx->sap_mandatory_channels_len; j++) { + if (pcl_list_org[i] == + cds_ctx->sap_mandatory_channels[j]) { + found = true; + break; + } + } + if (found) { + pcl_list[pcl_len] = pcl_list_org[i]; + weight_list[pcl_len++] = weight_list_org[i]; + } + } + + qdf_mem_zero(pcl_list_org, QDF_ARRAY_SIZE(pcl_list_org)); + qdf_mem_zero(weight_list_org, QDF_ARRAY_SIZE(weight_list_org)); + qdf_mem_copy(pcl_list_org, pcl_list, pcl_len); + qdf_mem_copy(weight_list_org, weight_list, pcl_len); + *pcl_len_org = pcl_len; + + return QDF_STATUS_SUCCESS; +} + +/** + * cds_get_sap_mandatory_channel() - Get the mandatory channel for SAP + * @chan: Pointer to the SAP mandatory channel + * + * Gets the mandatory channel for SAP operation + * + * Return: QDF_STATUS + */ +QDF_STATUS cds_get_sap_mandatory_channel(uint32_t *chan) +{ + QDF_STATUS status; + struct sir_pcl_list pcl; + + qdf_mem_zero(&pcl, sizeof(pcl)); + + status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE, + pcl.pcl_list, &pcl.pcl_len, + pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list)); + if (QDF_IS_STATUS_ERROR(status)) { + cds_err("Unable to get PCL for SAP"); + return status; + } + + /* No existing SAP connection and hence a new SAP connection might be + * coming up. + */ + if (!pcl.pcl_len) { + cds_info("cds_get_pcl_for_existing_conn returned no pcl"); + status = cds_get_pcl(CDS_SAP_MODE, + pcl.pcl_list, &pcl.pcl_len, + pcl.weight_list, + QDF_ARRAY_SIZE(pcl.weight_list)); + if (QDF_IS_STATUS_ERROR(status)) { + cds_err("Unable to get PCL for SAP: cds_get_pcl"); + return status; + } + } + + status = cds_modify_sap_pcl_based_on_mandatory_channel(pcl.pcl_list, + pcl.weight_list, + &pcl.pcl_len); + if (QDF_IS_STATUS_ERROR(status)) { + cds_err("Unable to modify SAP PCL"); + return status; + } + + *chan = pcl.pcl_list[0]; + cds_info("mandatory channel:%d", *chan); + return QDF_STATUS_SUCCESS; +} + /** * cds_get_valid_chan_weights() - Get the weightage for all valid channels * @weight: Pointer to the structure containing pcl, saved channel list and diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 367d702cd845..d9924984d4cf 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -343,7 +343,8 @@ typedef enum { #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH #define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE "gWlanMccToSccSwitchMode" #define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MIN (QDF_MCC_TO_SCC_SWITCH_DISABLE) -#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MAX (QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION) +#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MAX \ + (QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL) #define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_DEFAULT (QDF_MCC_TO_SCC_SWITCH_DISABLE) #endif diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 5f695e28a98a..00a35209161f 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1398,7 +1398,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1]; bool ht_enabled, ht40_enabled, vht_enabled; uint8_t ch_width; - uint8_t weight_list[MAX_NUM_CHAN]; + uint8_t weight_list[QDF_MAX_NUM_CHAN]; /* ***Note*** Donot set SME config related to ACS operation here because * ACS operation is not synchronouse and ACS for Second AP may come when @@ -4317,9 +4317,9 @@ static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy, hdd_context_t *hdd_ctx = wiphy_priv(wiphy); int i, ret = 0; QDF_STATUS status; - uint8_t pcl[MAX_NUM_CHAN], weight_list[MAX_NUM_CHAN]; + uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN]; uint32_t pcl_len = 0; - uint32_t freq_list[MAX_NUM_CHAN]; + uint32_t freq_list[QDF_MAX_NUM_CHAN]; enum cds_con_mode intf_mode; struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1]; struct sk_buff *reply_skb; @@ -5400,6 +5400,7 @@ __wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy, uint8_t config_channel = 0; hdd_ap_ctx_t *ap_ctx; int ret; + QDF_STATUS status; ENTER(); @@ -5448,6 +5449,37 @@ __wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy, cds_restart_sap(hostapd_adapter); } + if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) { + uint32_t freq_len, i; + uint32_t *freq; + uint8_t chans[QDF_MAX_NUM_CHAN]; + + hdd_debug("setting mandatory freq/chan list"); + + freq_len = nla_len( + tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/ + sizeof(uint32_t); + + if (freq_len > QDF_MAX_NUM_CHAN) { + hdd_err("insufficient space to hold channels"); + return -ENOMEM; + } + + freq = nla_data( + tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]); + + hdd_debug("freq_len=%d", freq_len); + + for (i = 0; i < freq_len; i++) { + chans[i] = ieee80211_frequency_to_channel(freq[i]); + hdd_debug("freq[%d]=%d", i, freq[i]); + } + + status = cds_set_sap_mandatory_channels(chans, freq_len); + if (QDF_IS_STATUS_ERROR(status)) + return -EINVAL; + } + return 0; } diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index a3ab7485feb7..57b25e495416 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -2363,12 +2363,18 @@ enum qca_vendor_attr_txpower_scale_decr_db { * enum qca_wlan_vendor_attr_sap_config - config params for sap configuration * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_INVALID: invalid * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL: Channel on which SAP should start + * @QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST: List of frequencies on + * which AP is expected to operate. This is irrespective of ACS configuration. + * This list is a priority based one and is looked for before the AP is created + * to ensure the best concurrency sessions (avoid MCC and use DBS/SCC) co-exist + * in the system. * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST: after last * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX: max attribute */ enum qca_wlan_vendor_attr_sap_config { QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_INVALID = 0, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL, + QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX = diff --git a/core/hdd/src/wlan_hdd_conc_ut.c b/core/hdd/src/wlan_hdd_conc_ut.c index d42391602485..bd1c7e4726e5 100644 --- a/core/hdd/src/wlan_hdd_conc_ut.c +++ b/core/hdd/src/wlan_hdd_conc_ut.c @@ -73,7 +73,7 @@ struct report_t { bool status; char result_code[MAX_ALLOWED_CHAR_IN_REPORT]; char reason[MAX_ALLOWED_CHAR_IN_REPORT]; - char pcl[2 * MAX_NUM_CHAN]; + char pcl[2 * QDF_MAX_NUM_CHAN]; }; static struct report_t report[NUMBER_OF_SCENARIO]; @@ -231,7 +231,7 @@ void fill_report(hdd_context_t *hdd_ctx, char *title, if (pcl) { qdf_mem_zero(report[report_idx].pcl, sizeof(report[report_idx].pcl)); - for (i = 0; i < MAX_NUM_CHAN; i++) { + for (i = 0; i < QDF_MAX_NUM_CHAN; i++) { if (pcl[i] == 0) break; qdf_mem_zero(buf, sizeof(buf)); @@ -625,7 +625,8 @@ void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx) enum cds_con_mode sub_type; enum cds_conc_priority_mode system_pref = hdd_ctx->config->conc_system_pref; - uint8_t pcl[MAX_NUM_CHAN] = {0}, weight_list[MAX_NUM_CHAN] = {0}; + uint8_t pcl[QDF_MAX_NUM_CHAN] = {0}, + weight_list[QDF_MAX_NUM_CHAN] = {0}; uint32_t pcl_len = 0; bool status = false; enum cds_pcl_type pcl_type; @@ -633,7 +634,7 @@ void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx) QDF_STATUS ret; /* flush the entire table first */ - ret = cds_init_policy_mgr(); + ret = cds_init_policy_mgr(sme_get_cfg_valid_channels); if (!QDF_IS_STATUS_SUCCESS(ret)) { hdd_err("Policy manager initialization failed"); return; @@ -672,7 +673,8 @@ void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, { uint8_t vdevid = 0, tx_stream = 2, rx_stream = 2; uint8_t type = WMI_VDEV_TYPE_STA, channel_id = first_chnl, mac_id = 1; - uint8_t pcl[MAX_NUM_CHAN] = {0}, weight_list[MAX_NUM_CHAN] = {0}; + uint8_t pcl[QDF_MAX_NUM_CHAN] = {0}, + weight_list[QDF_MAX_NUM_CHAN] = {0}; uint32_t pcl_len = 0; enum cds_chain_mode chain_mask = first_chain_mask; enum cds_con_mode sub_type, next_sub_type, dummy_type; @@ -689,7 +691,7 @@ void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, type = wlan_hdd_valid_type_of_persona(sub_type); /* flush the entire table first */ - ret = cds_init_policy_mgr(); + ret = cds_init_policy_mgr(sme_get_cfg_valid_channels); if (!QDF_IS_STATUS_SUCCESS(ret)) { hdd_err("Policy manager initialization failed"); return; @@ -788,7 +790,7 @@ void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, type_1 = wlan_hdd_valid_type_of_persona(sub_type_1); /* flush the entire table first */ - ret = cds_init_policy_mgr(); + ret = cds_init_policy_mgr(sme_get_cfg_valid_channels); if (!QDF_IS_STATUS_SUCCESS(ret)) { hdd_err("Policy manager initialization failed"); return; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index aa243cf59d18..59031a396309 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -6619,7 +6619,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) #endif wlan_hdd_nan_init(hdd_ctx); - status = cds_init_policy_mgr(); + status = cds_init_policy_mgr(sme_get_cfg_valid_channels); if (!QDF_IS_STATUS_SUCCESS(status)) { hdd_err("Policy manager initialization failed"); goto err_debugfs_exit; diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 04c90f0bdf7a..e6d9ae421e1c 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -7997,8 +7997,8 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, case WE_POLICY_MANAGER_PCL_CMD: { - uint8_t pcl[MAX_NUM_CHAN] = {0}; - uint8_t weight_list[MAX_NUM_CHAN] = {0}; + uint8_t pcl[QDF_MAX_NUM_CHAN] = {0}; + uint8_t weight_list[QDF_MAX_NUM_CHAN] = {0}; uint32_t pcl_len = 0, i = 0; hddLog(LOGE, diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 0297953b7144..dd439e790da3 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -2091,6 +2091,8 @@ sap_dfs_is_channel_in_nol_list(ptSapContext sap_context, * @sap_event: State machine event * @sap_do_acs_pre_start_bss: true, if ACS scan is issued pre start BSS * false, if ACS scan is issued post start BSS. + * @check_for_connection_update: true, check and wait for connection update + * false, do not perform connection update * * Initiates sme scan for ACS to pick a channel. * @@ -2098,7 +2100,8 @@ sap_dfs_is_channel_in_nol_list(ptSapContext sap_context, */ QDF_STATUS sap_goto_channel_sel(ptSapContext sap_context, ptWLAN_SAPEvent sap_event, - bool sap_do_acs_pre_start_bss) + bool sap_do_acs_pre_start_bss, + bool check_for_connection_update) { /* Initiate a SCAN request */ @@ -2106,6 +2109,7 @@ QDF_STATUS sap_goto_channel_sel(ptSapContext sap_context, /* To be initialised if scan is required */ tCsrScanRequest scan_request; QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; + tpAniSirGlobal mac_ctx; #ifdef SOFTAP_CHANNEL_RANGE uint8_t *channel_list = NULL; @@ -2122,6 +2126,13 @@ QDF_STATUS sap_goto_channel_sel(ptSapContext sap_context, return QDF_STATUS_E_FAULT; } + mac_ctx = PMAC_STRUCT(h_hal); + if (NULL == mac_ctx) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, + FL("Invalid MAC context")); + return QDF_STATUS_E_FAILURE; + } + if (cds_concurrent_beaconing_sessions_running()) { con_ch = sme_get_concurrent_operation_channel(h_hal); @@ -2329,6 +2340,20 @@ QDF_STATUS sap_goto_channel_sel(ptSapContext sap_context, QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH, FL("for configured channel, Ch= %d"), sap_context->channel); + + if (mac_ctx->policy_manager_enabled && + check_for_connection_update) { + /* This wait happens in the hostapd context. The event + * is set in the MC thread context. + */ + qdf_status = cds_update_and_wait_for_connection_update( + sap_context->sessionId, + sap_context->channel, + SIR_UPDATE_REASON_START_AP); + if (QDF_IS_STATUS_ERROR(qdf_status)) + return qdf_status; + } + if (sap_do_acs_pre_start_bss == true) { QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, FL("ACS end due to Ch override. Sel Ch = %d"), @@ -3276,7 +3301,8 @@ static QDF_STATUS sap_fsm_state_disconnected(ptSapContext sap_ctx, * Perform sme_ScanRequest. This scan request is post start bss * request so, set the third to false. */ - qdf_status = sap_goto_channel_sel(sap_ctx, sap_event, false); + qdf_status = sap_goto_channel_sel(sap_ctx, sap_event, false, + true); /* * Transition from eSAP_DISCONNECTED to eSAP_CH_SELECT @@ -3310,7 +3336,8 @@ static QDF_STATUS sap_fsm_state_disconnected(ptSapContext sap_ctx, * Perform sme_ScanRequest. This scan request is post start bss * request so, set the third to false. */ - qdf_status = sap_goto_channel_sel(sap_ctx, sap_event, false); + qdf_status = sap_goto_channel_sel(sap_ctx, sap_event, false, + false); } else { QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, FL("in state %s, event msg %d"), diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h index 29ae041764a8..cec952dc9bdc 100644 --- a/core/sap/src/sap_internal.h +++ b/core/sap/src/sap_internal.h @@ -400,7 +400,8 @@ bool sap_dfs_is_channel_in_preferred_location(tHalHandle hHal, QDF_STATUS sap_goto_channel_sel( ptSapContext sapContext, ptWLAN_SAPEvent sapEvent, - bool sap_do_acs_pre_start_bss); + bool sap_do_acs_pre_start_bss, + bool check_for_connection_update); void sap_config_acs_result(tHalHandle hal, ptSapContext sap_ctx, uint32_t sec_ch); diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 9965c2b8ff7c..53d195c10ef5 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -3418,7 +3418,7 @@ wlansap_acs_chselect(void *pvos_gctx, * different scan callback fucntion to process * the results pre start BSS. */ - qdf_status = sap_goto_channel_sel(sap_context, NULL, true); + qdf_status = sap_goto_channel_sel(sap_context, NULL, true, false); if (QDF_STATUS_E_ABORTED == qdf_status) { QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 498910c2a875..a4cd74f89e7d 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2006,7 +2006,7 @@ csr_parse_scan_results(tpAniSirGlobal pMac, eCsrAuthType auth = eCSR_AUTH_TYPE_OPEN_SYSTEM; uint32_t len = 0; enum cds_con_mode new_mode; - uint8_t weight_list[MAX_NUM_CHAN]; + uint8_t weight_list[QDF_MAX_NUM_CHAN]; csr_ll_lock(&pMac->scan.scanResultList); diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 7e44a7c12371..a3aad92af9d7 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -694,6 +694,7 @@ uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal mac_ctx, uint16_t intf_ch = 0, sap_hbw = 0, intf_hbw = 0, intf_cfreq = 0; uint16_t sap_cfreq = 0; uint16_t sap_lfreq, sap_hfreq, intf_lfreq, intf_hfreq, sap_cch = 0; + QDF_STATUS status; sms_log(mac_ctx, LOG1, FL("sap_ch:%d sap_phymode:%d"), sap_ch, sap_phymode); @@ -761,13 +762,15 @@ uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal mac_ctx, } sms_log(mac_ctx, LOG1, - FL("intf_ch:%d sap_ch:%d intf_ch:%d"), - intf_ch, sap_ch, intf_ch); + FL("intf_ch:%d sap_ch:%d cc_switch_mode:%d"), + intf_ch, sap_ch, cc_switch_mode); if (intf_ch && sap_ch != intf_ch && cc_switch_mode != QDF_MCC_TO_SCC_SWITCH_FORCE && cc_switch_mode != - QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION) { + QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION && + cc_switch_mode != + QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL) { sap_lfreq = sap_cfreq - sap_hbw; sap_hfreq = sap_cfreq + sap_hbw; intf_lfreq = intf_cfreq - intf_hbw; @@ -790,14 +793,39 @@ uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal mac_ctx, } else if (intf_ch && sap_ch != intf_ch && ((cc_switch_mode == QDF_MCC_TO_SCC_SWITCH_FORCE) || (cc_switch_mode == - QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION))) { + QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION) || + (cc_switch_mode == + QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL))) { if (!((intf_ch < 14 && sap_ch < 14) || (intf_ch > 14 && sap_ch > 14))) intf_ch = 0; - } else if (intf_ch == sap_ch) { - intf_ch = 0; + else if (cc_switch_mode == + QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL) { + status = + cds_get_sap_mandatory_channel((uint32_t *)&intf_ch); + if (QDF_IS_STATUS_ERROR(status)) { + sms_log(mac_ctx, LOGE, + FL("no mandatory channel")); + intf_ch = sap_ch; + } + } + } else if ((intf_ch == sap_ch) && (cc_switch_mode == + QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL)) { + if (cds_chan_to_band(intf_ch) == CDS_BAND_2GHZ) { + status = + cds_get_sap_mandatory_channel( + (uint32_t *)&intf_ch); + if (QDF_IS_STATUS_ERROR(status)) { + sms_log(mac_ctx, LOGE, + FL("no mandatory channel")); + intf_ch = sap_ch; + } + } } + if (intf_ch == sap_ch) + intf_ch = 0; + sms_log(mac_ctx, LOGE, FL("##Concurrent Channels %s Interfering"), intf_ch == 0 ? "Not" : "Are"); return intf_ch;