diff --git a/core/hdd/inc/hdd_config.h b/core/hdd/inc/hdd_config.h index 3fa83a69d0c1..d809711df6b7 100644 --- a/core/hdd/inc/hdd_config.h +++ b/core/hdd/inc/hdd_config.h @@ -1195,6 +1195,26 @@ struct dhcp_server { 0, \ "Enable/Disable unit test framework") +/* + * + * gDisableChannel - Used to disable channels specified + * + * @Min: 0 + * @Max: 1 + * Default: 0 + * + * This ini is used to disable the channels given in the command + * SET_DISABLE_CHANNEL_LIST and to restore the channels when the + * command is given with channel list as 0 + * Usage: External + * + * + */ +#define CFG_ENABLE_DISABLE_CHANNEL CFG_INI_BOOL( \ + "gDisableChannel", \ + 0, \ + "Enable/Disable to disable channels specified") + #define CFG_HDD_ALL \ CFG_ENABLE_PACKET_LOG_ALL \ CFG_ENABLE_RUNTIME_PM_ALL \ @@ -1229,5 +1249,6 @@ struct dhcp_server { CFG(CFG_PRIVATE_WEXT_CONTROL) \ CFG(CFG_PROVISION_INTERFACE_POOL) \ CFG(CFG_TIMER_MULTIPLIER) \ - CFG(CFG_HDD_DOT11_MODE) + CFG(CFG_HDD_DOT11_MODE) \ + CFG(CFG_ENABLE_DISABLE_CHANNEL) #endif diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 4a25554fe07d..1339afaf5d1e 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -129,6 +129,7 @@ struct hdd_config { bool action_oui_enable; uint8_t action_oui_str[ACTION_OUI_MAXIMUM_ID][ACTION_OUI_MAX_STR_LEN]; bool is_unit_test_framework_enabled; + bool disable_channel; /* HDD converged ini items are listed below this*/ bool bug_on_reinit_failure; diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 5cd970f7ae95..a6a3b9cd8d7a 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -7029,6 +7029,67 @@ static int hdd_alloc_chan_cache(struct hdd_context *hdd_ctx, int num_chan) return 0; } +/** + * check_disable_channels() - Check for disable channel + * @hdd_ctx: Pointer to hdd context + * @operating_channel: Current operating channel of adapter + * + * This function checks original_channels array for a specific channel + * + * Return: 0 if channel not found, 1 if channel found + */ +static bool check_disable_channels(struct hdd_context *hdd_ctx, + uint8_t operating_channel) +{ + uint32_t num_channels; + uint8_t i; + + if (!hdd_ctx || !hdd_ctx->original_channels || + !hdd_ctx->original_channels->channel_info) + return false; + + num_channels = hdd_ctx->original_channels->num_channels; + for (i = 0; i < num_channels; i++) + if (hdd_ctx->original_channels->channel_info[i].channel_num == + operating_channel) + return true; + return false; +} + +/** + * disconnect_sta_and_stop_sap() - Disconnect STA and stop SAP + * + * @hdd_ctx: Pointer to hdd context + * + * Disable channels provided by user and disconnect STA if it is + * connected to any AP, stop SAP and send deauthentication request + * to STAs connected to SAP. + * + * Return: None + */ +static void disconnect_sta_and_stop_sap(struct hdd_context *hdd_ctx) +{ + struct hdd_adapter *adapter, *next = NULL; + QDF_STATUS status; + + if (!hdd_ctx) + return; + + hdd_check_and_disconnect_sta_on_invalid_channel(hdd_ctx); + + status = hdd_get_front_adapter(hdd_ctx, &adapter); + while (adapter && (status == QDF_STATUS_SUCCESS)) { + if (!hdd_validate_adapter(adapter) && + (adapter->device_mode == QDF_SAP_MODE) && + (check_disable_channels(hdd_ctx, + adapter->session.ap.operating_channel))) + wlan_hdd_stop_sap(adapter); + + status = hdd_get_next_adapter(hdd_ctx, adapter, &next); + adapter = next; + } +} + /** * hdd_parse_disable_chan_cmd() - Parse the channel list received * in command. @@ -7207,8 +7268,10 @@ mem_alloc_failed: qdf_mutex_release(&hdd_ctx->cache_channel_lock); /* Disable the channels received in command SET_DISABLE_CHANNEL_LIST */ if (!is_command_repeated && hdd_ctx->original_channels) { - wlan_hdd_disable_channels(hdd_ctx); - hdd_check_and_disconnect_sta_on_invalid_channel(hdd_ctx); + ret = wlan_hdd_disable_channels(hdd_ctx); + if (ret) + return ret; + disconnect_sta_and_stop_sap(hdd_ctx); } hdd_exit(); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 1a4f83307fa3..291b5fc2c47a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -9528,6 +9528,7 @@ static void hdd_cfg_params_init(struct hdd_context *hdd_ctx) config->enable_rtt_support = cfg_get(psoc, CFG_ENABLE_RTT_SUPPORT); config->is_unit_test_framework_enabled = cfg_get(psoc, CFG_ENABLE_UNIT_TEST_FRAMEWORK); + config->disable_channel = cfg_get(psoc, CFG_ENABLE_DISABLE_CHANNEL); hdd_init_vc_mode_cfg_bitmap(config, psoc); hdd_init_runtime_pm(config, psoc); diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index ba0178e4f2d2..4526e221c4f1 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -1183,7 +1183,8 @@ QDF_STATUS hdd_softap_stop_bss(struct hdd_adapter *adapter) } } } - if (adapter->device_mode == QDF_SAP_MODE) + if (adapter->device_mode == QDF_SAP_MODE && + !hdd_ctx->config->disable_channel) wlan_hdd_restore_channels(hdd_ctx, true); /* Mark the indoor channel (passive) to enable */