diff options
| author | Manishekar Chandrasekaran <cmshekar@codeaurora.org> | 2016-05-25 18:44:01 +0530 |
|---|---|---|
| committer | Akash Patel <akashp@codeaurora.org> | 2016-06-10 11:30:54 -0700 |
| commit | c67b2bb16c5d52fca54c413037fb433a1ee2ef79 (patch) | |
| tree | 71cbe94940da0ca040752400b037d1e6f171125e | |
| parent | 9736118d7e9c840fbac7d312bb21c514423274cf (diff) | |
qcacld-3.0: Restart SAP through (E)CSA on channel avoidance event
Restart SAP through (E)CSA on receiving channel avoidance event
from FW instead of doing a hard restart. This provides the
advantage of not disconnecting the connected clients.
Change-Id: Ibaa74dc8d7c75ed793faa418ee8c179b4210b35e
CRs-Fixed: 1020771
| -rw-r--r-- | core/cds/inc/cds_concurrency.h | 2 | ||||
| -rw-r--r-- | core/cds/src/cds_concurrency.c | 28 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_main.c | 284 |
3 files changed, 214 insertions, 100 deletions
diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index fd44258ef48f..e7132c8700da 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -614,6 +614,8 @@ QDF_STATUS cds_change_mcc_go_beacon_interval(hdd_adapter_t *pHostapdAdapter); int cds_go_set_mcc_p2p_quota(hdd_adapter_t *hostapd_adapter, uint32_t set_value); void cds_set_mcc_latency(hdd_adapter_t *adapter, int set_value); +void cds_change_sap_channel_with_csa(hdd_adapter_t *adapter, + hdd_ap_ctx_t *hdd_ap_ctx); #if defined(FEATURE_WLAN_MCC_TO_SCC_SWITCH) || \ defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) void cds_restart_sap(hdd_adapter_t *ap_adapter); diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 2aed923d4491..e22010f273f5 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -7494,6 +7494,34 @@ void cds_set_mcc_latency(hdd_adapter_t *adapter, int set_value) } } +/** + * cds_change_sap_channel_with_csa() - Move SAP channel using (E)CSA + * @adapter: AP adapter + * @hdd_ap_ctx: AP context + * + * Invoke the callback function to change SAP channel using (E)CSA + * + * Return: None + */ +void cds_change_sap_channel_with_csa(hdd_adapter_t *adapter, + hdd_ap_ctx_t *hdd_ap_ctx) +{ + p_cds_contextType cds_ctx; + + cds_ctx = cds_get_global_context(); + if (!cds_ctx) { + cds_err("Invalid CDS context"); + return; + } + + if (cds_ctx->sap_restart_chan_switch_cb) { + cds_info("SAP change change without restart"); + cds_ctx->sap_restart_chan_switch_cb(adapter, + hdd_ap_ctx->sapConfig.channel, + hdd_ap_ctx->sapConfig.ch_params.ch_width); + } +} + #if defined(FEATURE_WLAN_MCC_TO_SCC_SWITCH) || \ defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) /** diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 566227f71ff0..77b75b816f1d 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5046,72 +5046,148 @@ static void hdd_set_thermal_level_cb(void *context, u_int8_t level) } /** - * hdd_find_prefd_safe_chnl() - find safe channel within preferred channel - * @hdd_ctxt: hdd context pointer - * @ap_adapter: hdd hostapd adapter pointer + * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP + * restart + * @adapter: AP adapter * - * Try to find safe channel within preferred channel - * In case auto channel selection enabled - * - Preferred and safe channel should be used - * - If no overlapping, preferred channel should be used + * Get a safe channel to restart SAP. PCL already takes into account the + * unsafe channels. So, the PCL is validated with the ACS range to provide + * a safe channel for the SAP to restart. * - * Return: 1: found preferred safe channel - * 0: could not found preferred safe channel + * Return: Channel number to restart SAP in case of success. In case of any + * failure, the channel number returned is zero. */ -static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt, - hdd_adapter_t *ap_adapter) +static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range( + hdd_adapter_t *adapter) { - uint16_t safe_channels[NUM_CHANNELS]; - uint16_t safe_channel_count; - uint16_t unsafe_channel_count; - uint8_t is_unsafe = 1; - uint16_t i; - uint16_t channel_loop; + struct sir_pcl_list pcl; + QDF_STATUS status; + uint32_t i, j; + tHalHandle *hal_handle; + hdd_context_t *hdd_ctx; + bool found = false; - if (!hdd_ctxt || !ap_adapter) { - hdd_err("invalid context/adapter"); - return 0; + hal_handle = WLAN_HDD_GET_HAL_CTX(adapter); + if (!hal_handle) { + hdd_err("invalid HAL handle"); + return INVALID_CHANNEL_ID; } - safe_channel_count = 0; - unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctxt->unsafe_channel_count, - (uint16_t)NUM_CHANNELS); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (!hdd_ctx) { + hdd_err("invalid HDD context"); + return INVALID_CHANNEL_ID; + } + + 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)) { + hdd_err("Get PCL failed"); + return INVALID_CHANNEL_ID; + } + + if (!pcl.pcl_len) { + hdd_alert("pcl length is zero. this is not expected"); + return INVALID_CHANNEL_ID; + } + + hdd_info("start:%d end:%d", + adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch, + adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch); + + /* PCL already takes unsafe channel into account */ + for (i = 0; i < pcl.pcl_len; i++) { + hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]); + if ((pcl.pcl_list[i] >= + adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) && + (pcl.pcl_list[i] <= + adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) { + hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]); + return pcl.pcl_list[i]; + } + } + + hdd_info("no safe channel from PCL found in ACS range"); - for (i = 0; i < NUM_CHANNELS; i++) { - is_unsafe = 0; - for (channel_loop = 0; - channel_loop < unsafe_channel_count; channel_loop++) { - if (CDS_CHANNEL_NUM(i) == - hdd_ctxt->unsafe_channel_list[channel_loop]) { - is_unsafe = 1; + /* Try for safe channel from all valid channel */ + pcl.pcl_len = MAX_NUM_CHAN; + status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list, + &pcl.pcl_len); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("error in getting valid channel list"); + return INVALID_CHANNEL_ID; + } + + for (i = 0; i < pcl.pcl_len; i++) { + hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]); + found = false; + for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) { + if (cds_chan_to_freq(pcl.pcl_list[i]) == + hdd_ctx->unsafe_channel_list[j]) { + hdd_info("unsafe chan:%d", pcl.pcl_list[i]); + found = true; break; } } - if (!is_unsafe) { - safe_channels[safe_channel_count] = - CDS_CHANNEL_NUM(i); - hddLog(QDF_TRACE_LEVEL_INFO_HIGH, - FL("safe channel %d"), - safe_channels[safe_channel_count]); - safe_channel_count++; + + if (found) + continue; + + if ((pcl.pcl_list[i] >= + adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) && + (pcl.pcl_list[i] <= + adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) { + hdd_info("found safe chan:%d", pcl.pcl_list[i]); + return pcl.pcl_list[i]; } } - hddLog(QDF_TRACE_LEVEL_INFO_HIGH, - FL("perferred range %d - %d"), - ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch, - ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch); - for (i = 0; i < safe_channel_count; i++) { - if (safe_channels[i] >= - ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch - && safe_channels[i] <= - ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch) { - hddLog(QDF_TRACE_LEVEL_INFO_HIGH, - FL("safe channel %d is in perferred range"), - safe_channels[i]); - return 1; - } + + return INVALID_CHANNEL_ID; +} + +/** + * hdd_restart_sap() - Restarts SAP on the given channel + * @adapter: AP adapter + * @channel: Channel + * + * Restarts the SAP interface by invoking the function which executes the + * callback to perform channel switch using (E)CSA. + * + * Return: None + */ +void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel) +{ + hdd_ap_ctx_t *hdd_ap_ctx; + tHalHandle *hal_handle; + + if (!adapter) { + hdd_err("invalid adapter"); + return; } - return 0; + + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); + + hal_handle = WLAN_HDD_GET_HAL_CTX(adapter); + if (!hal_handle) { + hdd_err("invalid HAL handle"); + return; + } + + hdd_ap_ctx->sapConfig.channel = channel; + hdd_ap_ctx->sapConfig.ch_params.ch_width = + hdd_ap_ctx->sapConfig.ch_width_orig; + + hdd_info("chan:%d width:%d", + channel, hdd_ap_ctx->sapConfig.ch_width_orig); + + sme_set_ch_params(hal_handle, + hdd_ap_ctx->sapConfig.SapHw_mode, + hdd_ap_ctx->sapConfig.channel, + hdd_ap_ctx->sapConfig.sec_ch, + &hdd_ap_ctx->sapConfig.ch_params); + + cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx); } /** @@ -5127,7 +5203,6 @@ static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt, */ static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param) { - hdd_adapter_t *hostapd_adapter = NULL; hdd_context_t *hdd_ctxt; tSirChAvoidIndType *ch_avoid_indi; uint8_t range_loop; @@ -5136,9 +5211,13 @@ static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param) uint16_t start_channel; uint16_t end_channel; v_CONTEXT_t cds_context; - static int restart_sap_in_progress; tHddAvoidFreqList hdd_avoid_freq_list; uint32_t i; + QDF_STATUS status; + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + hdd_adapter_t *adapter_temp; + uint8_t restart_chan; + bool found = false; /* Basic sanity */ if (!hdd_context || !indi_param) { @@ -5260,56 +5339,61 @@ static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param) hdd_ctxt->unsafe_channel_list[channel_loop]); } - /* - * If auto channel select is enabled - * preferred channel is in safe channel, - * re-start softap interface with safe channel. - * no overlap with preferred channel and safe channel - * do not re-start softap interface - * stay current operating channel. + if (!hdd_ctxt->unsafe_channel_count) { + hdd_info("no unsafe channels - not restarting SAP"); + return; + } + + /* No channel change is done for fixed channel SAP. + * Loop through all ACS SAP interfaces and change the channels for + * the ones operating on unsafe channels. */ - if (hdd_ctxt->unsafe_channel_count) { - hostapd_adapter = hdd_get_adapter(hdd_ctxt, QDF_SAP_MODE); - if (hostapd_adapter) { - if ((hostapd_adapter->sessionCtx.ap.sapConfig. - acs_cfg.acs_mode) && - (!hdd_find_prefd_safe_chnl(hdd_ctxt, - hostapd_adapter))) - return; + status = hdd_get_front_adapter(hdd_ctxt, &adapter_node); + while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) { + adapter_temp = adapter_node->pAdapter; + + if (!((adapter_temp->device_mode == QDF_SAP_MODE) && + (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) { + hdd_info("skip device mode:%d acs:%d", + adapter_temp->device_mode, + adapter_temp->sessionCtx.ap.sapConfig. + acs_cfg.acs_mode); + goto next_adapater; + } - hddLog(QDF_TRACE_LEVEL_INFO, - FL( - "Current operation channel %d, sessionCtx.ap.sapConfig.channel %d" - ), - hostapd_adapter->sessionCtx.ap. - operatingChannel, - hostapd_adapter->sessionCtx.ap.sapConfig. - channel); - for (channel_loop = 0; - channel_loop < hdd_ctxt->unsafe_channel_count; - channel_loop++) { - if (((hdd_ctxt-> - unsafe_channel_list[channel_loop] == - hostapd_adapter->sessionCtx.ap. - operatingChannel)) && - (hostapd_adapter->sessionCtx.ap. - sapConfig.acs_cfg.acs_mode - == true) && - !restart_sap_in_progress) { - hddLog(QDF_TRACE_LEVEL_INFO, - FL("Restarting SAP")); - wlan_hdd_send_svc_nlink_msg - (WLAN_SVC_LTE_COEX_IND, NULL, 0); - restart_sap_in_progress = 1; - /* - * current operating channel is un-safe - * channel, restart driver - */ - hdd_hostapd_stop(hostapd_adapter->dev); - break; - } + found = false; + for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) { + if (cds_chan_to_freq( + adapter_temp->sessionCtx.ap.operatingChannel) == + hdd_ctxt->unsafe_channel_list[i]) { + found = true; + hdd_info("operating ch:%d is unsafe", + adapter_temp->sessionCtx.ap.operatingChannel); + break; } } + + if (!found) { + hdd_info("ch:%d is safe. no need to change channel", + adapter_temp->sessionCtx.ap.operatingChannel); + goto next_adapater; + } + + restart_chan = + hdd_get_safe_channel_from_pcl_and_acs_range( + adapter_temp); + if (!restart_chan) { + hdd_alert("fail to restart SAP"); + } else { + hdd_info("sending coex indication"); + wlan_hdd_send_svc_nlink_msg + (WLAN_SVC_LTE_COEX_IND, NULL, 0); + hdd_restart_sap(adapter_temp, restart_chan); + } + +next_adapater: + status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next); + adapter_node = next; } return; } |
