diff --git a/Kbuild b/Kbuild index 653352dac7..ec548089a2 100644 --- a/Kbuild +++ b/Kbuild @@ -2081,6 +2081,9 @@ cppflags-$(CONFIG_ENABLE_SMMU_S1_TRANSLATION) += -DENABLE_SMMU_S1_TRANSLATION #Flag to enable NUD tracking cppflags-$(CONFIG_WLAN_NUD_TRACKING) += -DWLAN_NUD_TRACKING +#Flag to enable set and get disable channel list feature +cppflags-$(CONFIG_DISABLE_CHANNEL_LIST) += -DDISABLE_CHANNEL_LIST + # configure log buffer size ifdef CONFIG_CFG_NUM_DP_TRACE_RECORD ccflags-y += -DMAX_QDF_DP_TRACE_RECORDS=$(CONFIG_CFG_NUM_DP_TRACE_RECORD) diff --git a/configs/default_defconfig b/configs/default_defconfig index fc7119cf37..c20d8e8fdd 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -514,6 +514,9 @@ CONFIG_WLAN_WEXT_SUPPORT_ENABLE := y #Flag to enable nud tracking feature CONFIG_WLAN_NUD_TRACKING := y +#Flag to enable set and get disable channel list feature +CONFIG_DISABLE_CHANNEL_LIST :=y + CONFIG_WIFI_POS_CONVERGED := y ifneq ($(CONFIG_WIFI_POS_CONVERGED), y) CONFIG_WIFI_POS_LEGACY := y diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index f89c041bc0..a9a6290de4 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1664,6 +1664,36 @@ enum RX_OFFLOAD { */ #define HDD_MAX_ADAPTERS (WLAN_MAX_STA_COUNT + QDF_MAX_NO_OF_SAP_MODE + 2) +#ifdef DISABLE_CHANNEL_LIST + +/** + * struct hdd_cache_channel_info - Structure of the channel info + * which needs to be cached + * @channel_num: channel number + * @reg_status: Current regulatory status of the channel + * Enable + * Disable + * DFS + * Invalid + * @wiphy_status: Current wiphy status + */ +struct hdd_cache_channel_info { + uint32_t channel_num; + enum channel_state reg_status; + uint32_t wiphy_status; +}; + +/** + * struct hdd_cache_channels - Structure of the channels to be cached + * @num_channels: Number of channels to be cached + * @channel_info: Structure of the channel info + */ +struct hdd_cache_channels { + uint32_t num_channels; + struct hdd_cache_channel_info *channel_info; +}; +#endif + /** Adapter structure definition */ struct hdd_context { struct wlan_objmgr_psoc *hdd_psoc; @@ -1934,6 +1964,11 @@ struct hdd_context { bool apf_supported; uint32_t apf_version; #endif + +#ifdef DISABLE_CHANNEL_LIST + struct hdd_cache_channels *original_channels; + qdf_mutex_t cache_channel_lock; +#endif }; /** @@ -3396,4 +3431,13 @@ struct hdd_context *hdd_handle_to_context(hdd_handle_t hdd_handle) { return (struct hdd_context *)hdd_handle; } + +/** + * wlan_hdd_free_cache_channels() - Free the cache channels list + * @hdd_ctx: Pointer to HDD context + * + * Return: None + */ +void wlan_hdd_free_cache_channels(struct hdd_context *hdd_ctx); + #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 4d744a5132..bca41579c9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -600,4 +600,16 @@ void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter, * Return : 0 on success and errno on failure */ int wlan_hdd_send_mode_change_event(void); + +/** + * wlan_hdd_restore_channels() - Restore the channels which were cached + * and disabled in wlan_hdd_disable_channels api. + * @hdd_ctx: Pointer to the HDD context + * @notify_sap_event: Indicates if SAP event needs to be notified + * + * Return: 0 on success, Error code on failure + */ +int wlan_hdd_restore_channels(struct hdd_context *hdd_ctx, + bool notify_sap_event); + #endif diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 192dbd5e70..0cfd992f94 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -4238,6 +4238,217 @@ static int wlan_hdd_setup_driver_overrides(struct hdd_adapter *ap_adapter) return 0; } +static void hdd_check_and_disconnect_sta_on_invalid_channel( + struct hdd_context *hdd_ctx) +{ + struct hdd_adapter *sta_adapter; + uint8_t sta_chan; + + sta_chan = hdd_get_operating_channel(hdd_ctx, QDF_STA_MODE); + + if (!sta_chan) { + hdd_err("STA not connected"); + return; + } + + hdd_err("STA connected on chan %d", sta_chan); + + if (sme_is_channel_valid(hdd_ctx->mac_handle, sta_chan)) { + hdd_err("STA connected on chan %d and it is valid", sta_chan); + return; + } + + sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE); + + if (!sta_adapter) { + hdd_err("STA adapter does not exist"); + return; + } + + hdd_err("chan %d not valid, issue disconnect", sta_chan); + /* Issue Disconnect request */ + wlan_hdd_disconnect(sta_adapter, eCSR_DISCONNECT_REASON_DEAUTH); +} + +#ifdef DISABLE_CHANNEL_LIST +/** + * wlan_hdd_get_wiphy_channel() - Get wiphy channel + * @wiphy: Pointer to wiphy structure + * @freq: Frequency of the channel for which the wiphy hw value is required + * + * Return: wiphy channel for valid frequency else return NULL + */ +static struct ieee80211_channel *wlan_hdd_get_wiphy_channel( + struct wiphy *wiphy, + uint32_t freq) +{ + uint32_t band_num, channel_num; + struct ieee80211_channel *wiphy_channel = NULL; + + for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; band_num++) { + for (channel_num = 0; channel_num < + wiphy->bands[band_num]->n_channels; + channel_num++) { + wiphy_channel = &(wiphy->bands[band_num]-> + channels[channel_num]); + if (wiphy_channel->center_freq == freq) + return wiphy_channel; + } + } + return wiphy_channel; +} + +int wlan_hdd_restore_channels(struct hdd_context *hdd_ctx, + bool notify_sap_event) +{ + struct hdd_cache_channels *cache_chann; + struct wiphy *wiphy; + int freq, status, rf_channel; + int i; + struct ieee80211_channel *wiphy_channel = NULL; + + hdd_enter(); + + if (!hdd_ctx) { + hdd_err("HDD Context is NULL"); + return -EINVAL; + } + + wiphy = hdd_ctx->wiphy; + if (!wiphy) { + hdd_err("Wiphy is NULL"); + return -EINVAL; + } + + qdf_mutex_acquire(&hdd_ctx->cache_channel_lock); + + cache_chann = hdd_ctx->original_channels; + + if (!cache_chann || !cache_chann->num_channels) { + qdf_mutex_release(&hdd_ctx->cache_channel_lock); + hdd_err("channel list is NULL or num channels are zero"); + return -EINVAL; + } + + for (i = 0; i < cache_chann->num_channels; i++) { + freq = reg_chan_to_freq( + hdd_ctx->hdd_pdev, + cache_chann->channel_info[i].channel_num); + if (!freq) + continue; + + wiphy_channel = wlan_hdd_get_wiphy_channel(wiphy, freq); + if (!wiphy_channel) + continue; + rf_channel = wiphy_channel->hw_value; + /* + * Restore the orginal states of the channels + * only if we have cached non zero values + */ + if (cache_chann->channel_info[i].wiphy_status && wiphy_channel) + wiphy_channel->flags = + cache_chann->channel_info[i].wiphy_status; + } + + qdf_mutex_release(&hdd_ctx->cache_channel_lock); + if (notify_sap_event) + ucfg_reg_notify_sap_event(hdd_ctx->hdd_pdev, false); + else + ucfg_reg_restore_cached_channels(hdd_ctx->hdd_pdev); + status = sme_update_channel_list(hdd_ctx->mac_handle); + if (status) + hdd_err("Can't Restore channel list"); + hdd_exit(); + + return 0; +} + +/** + * wlan_hdd_disable_channels() - Cache the channels + * and current state of the channels from the channel list + * received in the command and disable the channels on the + * wiphy and reg table. + * @hdd_ctx: Pointer to hdd context + * + * Return: 0 on success, Error code on failure + */ +static int wlan_hdd_disable_channels(struct hdd_context *hdd_ctx) +{ + struct hdd_cache_channels *cache_chann; + struct wiphy *wiphy; + int freq, status, rf_channel; + int i; + struct ieee80211_channel *wiphy_channel = NULL; + + hdd_enter(); + + if (!hdd_ctx) { + hdd_err("HDD Context is NULL"); + return -EINVAL; + } + + wiphy = hdd_ctx->wiphy; + if (!wiphy) { + hdd_err("Wiphy is NULL"); + return -EINVAL; + } + + qdf_mutex_acquire(&hdd_ctx->cache_channel_lock); + cache_chann = hdd_ctx->original_channels; + + if (!cache_chann || !cache_chann->num_channels) { + qdf_mutex_release(&hdd_ctx->cache_channel_lock); + hdd_err("channel list is NULL or num channels are zero"); + return -EINVAL; + } + + for (i = 0; i < cache_chann->num_channels; i++) { + freq = reg_chan_to_freq(hdd_ctx->hdd_pdev, + cache_chann-> + channel_info[i].channel_num); + if (!freq) + continue; + wiphy_channel = wlan_hdd_get_wiphy_channel(wiphy, freq); + if (!wiphy_channel) + continue; + rf_channel = wiphy_channel->hw_value; + /* + * Cache the current states of + * the channels + */ + cache_chann->channel_info[i].reg_status = + reg_get_channel_state( + hdd_ctx->hdd_pdev, + rf_channel); + cache_chann->channel_info[i].wiphy_status = + wiphy_channel->flags; + hdd_debug("Disable channel %d reg_stat %d wiphy_stat 0x%x", + cache_chann->channel_info[i].channel_num, + cache_chann->channel_info[i].reg_status, + wiphy_channel->flags); + + wiphy_channel->flags |= IEEE80211_CHAN_DISABLED; + } + + qdf_mutex_release(&hdd_ctx->cache_channel_lock); + status = ucfg_reg_notify_sap_event(hdd_ctx->hdd_pdev, true); + status = sme_update_channel_list(hdd_ctx->mac_handle); + + hdd_exit(); + return status; +} +#else +static int wlan_hdd_disable_channels(struct hdd_context *hdd_ctx) +{ + return 0; +} + +int wlan_hdd_restore_channels(struct hdd_context *hdd_ctx, + bool notify_sap_event) +{ + return 0; +} +#endif /** * wlan_hdd_cfg80211_start_bss() - start bss * @adapter: Pointer to hostapd adapter @@ -4355,7 +4566,18 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter, goto free; } } - + if (adapter->device_mode == QDF_SAP_MODE) { + /* + * Disable the channels received in command + * SET_DISABLE_CHANNEL_LIST + */ + status = wlan_hdd_disable_channels(hdd_ctx); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("Disable channel list fail"); + else + hdd_check_and_disconnect_sta_on_invalid_channel( + hdd_ctx); + } pConfig = &adapter->session.ap.sap_config; pBeacon = adapter->session.ap.beacon; @@ -4926,6 +5148,9 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter, goto free; error: + if (adapter->device_mode == QDF_SAP_MODE) + wlan_hdd_restore_channels(hdd_ctx, true); + /* Revert the indoor to passive marking if START BSS fails */ if (iniConfig->force_ssc_disable_indoor_channel) { hdd_update_indoor_channel(hdd_ctx, false); diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 2d086ba848..386f530c1d 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -6919,6 +6919,272 @@ static int drv_cmd_set_channel_switch(struct hdd_adapter *adapter, return 0; } +#ifdef DISABLE_CHANNEL_LIST +void wlan_hdd_free_cache_channels(struct hdd_context *hdd_ctx) +{ + hdd_enter(); + + if (!hdd_ctx->original_channels) + return; + + qdf_mutex_acquire(&hdd_ctx->cache_channel_lock); + hdd_ctx->original_channels->num_channels = 0; + if (hdd_ctx->original_channels->channel_info) { + qdf_mem_free(hdd_ctx->original_channels->channel_info); + hdd_ctx->original_channels->channel_info = NULL; + } + qdf_mem_free(hdd_ctx->original_channels); + hdd_ctx->original_channels = NULL; + qdf_mutex_release(&hdd_ctx->cache_channel_lock); + + hdd_exit(); +} + +/** + * hdd_alloc_chan_cache() - Allocate the memory to cache the channel + * info for the channels received in command SET_DISABLE_CHANNEL_LIST + * @hdd_ctx: Pointer to HDD context + * @num_chan: Number of channels for which memory needs to + * be allocated + * + * Return: 0 on success and error code on failure + */ +static int hdd_alloc_chan_cache(struct hdd_context *hdd_ctx, int num_chan) +{ + hdd_ctx->original_channels = + qdf_mem_malloc(sizeof(struct hdd_cache_channels)); + if (!hdd_ctx->original_channels) { + hdd_err("QDF_MALLOC_ERR"); + return -ENOMEM; + } + hdd_ctx->original_channels->num_channels = num_chan; + hdd_ctx->original_channels->channel_info = + qdf_mem_malloc(num_chan * + sizeof(struct hdd_cache_channel_info)); + if (!hdd_ctx->original_channels->channel_info) { + hdd_err("QDF_MALLOC_ERR"); + hdd_ctx->original_channels->num_channels = 0; + qdf_mem_free(hdd_ctx->original_channels); + hdd_ctx->original_channels = NULL; + return -ENOMEM; + } + return 0; +} + +/** + * hdd_parse_disable_chan_cmd() - Parse the channel list received + * in command. + * @adapter: pointer to hdd adapter + * @ptr: Pointer to the command string + * + * This function parses the channel list received in the command. + * command should be a string having format + * SET_DISABLE_CHANNEL_LIST + * . + * If the command comes multiple times than this function will compare + * the channels received in the command with the channles cached in the + * first command, if the channel list matches with the cached channles, + * it returns success otherwise returns failure. + * + * Return: 0 on success, Error code on failure + */ + +static int hdd_parse_disable_chan_cmd(struct hdd_adapter *adapter, uint8_t *ptr) +{ + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + uint8_t *param; + int j, i, temp_int, ret = 0, num_channels; + uint32_t parsed_channels[MAX_CHANNEL]; + bool is_command_repeated = false; + + if (NULL == hdd_ctx) { + hdd_err("HDD Context is NULL"); + return -EINVAL; + } + + param = strnchr(ptr, strlen(ptr), ' '); + /*no argument after the command*/ + if (NULL == param) + return -EINVAL; + + /*no space after the command*/ + else if (SPACE_ASCII_VALUE != *param) + return -EINVAL; + + param++; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param)) + param++; + + /*no argument followed by spaces*/ + if ('\0' == *param) + return -EINVAL; + + /*getting the first argument ie the number of channels*/ + if (sscanf(param, "%d ", &temp_int) != 1) { + hdd_err("Cannot get number of channels from input"); + return -EINVAL; + } + + if (temp_int < 0 || temp_int > MAX_CHANNEL) { + hdd_err("Invalid Number of channel received"); + return -EINVAL; + } + + hdd_debug("Number of channel to disable are: %d", temp_int); + + if (!temp_int) { + if (!wlan_hdd_restore_channels(hdd_ctx, false)) { + /* + * Free the cache channels only when the command is + * received with num channels as 0 + */ + wlan_hdd_free_cache_channels(hdd_ctx); + } + return 0; + } + + qdf_mutex_acquire(&hdd_ctx->cache_channel_lock); + + if (!hdd_ctx->original_channels) { + if (hdd_alloc_chan_cache(hdd_ctx, temp_int)) { + ret = -ENOMEM; + goto mem_alloc_failed; + } + } else if (hdd_ctx->original_channels->num_channels != temp_int) { + hdd_err("Invalid Number of channels"); + ret = -EINVAL; + is_command_repeated = true; + goto parse_failed; + } else { + is_command_repeated = true; + } + num_channels = temp_int; + for (j = 0; j < num_channels; j++) { + /* + * param pointing to the beginning of first space + * after number of channels + */ + param = strpbrk(param, " "); + /*no channel list after the number of channels argument*/ + if (NULL == param) { + hdd_err("Invalid No of channel provided in the list"); + ret = -EINVAL; + goto parse_failed; + } + + param++; + + /*removing empty space*/ + while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param)) + param++; + + if ('\0' == *param) { + hdd_err("No channel is provided in the list"); + ret = -EINVAL; + goto parse_failed; + } + + if (sscanf(param, "%d ", &temp_int) != 1) { + hdd_err("Cannot read channel number"); + ret = -EINVAL; + goto parse_failed; + } + + if (!IS_CHANNEL_VALID(temp_int)) { + hdd_err("Invalid channel number received"); + ret = -EINVAL; + goto parse_failed; + } + + hdd_debug("channel[%d] = %d", j, temp_int); + parsed_channels[j] = temp_int; + } + + /*extra arguments check*/ + param = strpbrk(param, " "); + if (NULL != param) { + while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param)) + param++; + + if ('\0' != *param) { + hdd_err("Invalid argument received"); + ret = -EINVAL; + goto parse_failed; + } + } + + /* + * If command is received first time, cache the channels to + * be disabled else compare the channels received in the + * command with the cached channels, if channel list matches + * return success otherewise return failure. + */ + if (!is_command_repeated) { + for (j = 0; j < num_channels; j++) + hdd_ctx->original_channels-> + channel_info[j].channel_num = + parsed_channels[j]; + /* + * Cache the channel list in regulatory also + */ + ucfg_reg_cache_channel_state(hdd_ctx->hdd_pdev, + parsed_channels, + num_channels); + } else { + for (i = 0; i < num_channels; i++) { + for (j = 0; j < num_channels; j++) + if (hdd_ctx->original_channels-> + channel_info[i].channel_num == + parsed_channels[j]) + break; + if (j == num_channels) { + ret = -EINVAL; + goto parse_failed; + } + } + ret = 0; + } +mem_alloc_failed: + + qdf_mutex_release(&hdd_ctx->cache_channel_lock); + hdd_exit(); + + return ret; + +parse_failed: + if (!is_command_repeated) + wlan_hdd_free_cache_channels(hdd_ctx); + qdf_mutex_release(&hdd_ctx->cache_channel_lock); + hdd_exit(); + + return ret; +} + +static int drv_cmd_set_disable_chan_list(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + return hdd_parse_disable_chan_cmd(adapter, command); +} +#else + +static int drv_cmd_set_disable_chan_list(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + return 0; +} + +void wlan_hdd_free_cache_channels(struct hdd_context *hdd_ctx) +{ +} +#endif /* * The following table contains all supported WLAN HDD * IOCTL driver commands and the handler for each of them. @@ -7032,6 +7298,7 @@ static const struct hdd_drv_cmd hdd_drv_cmds[] = { {"CHANNEL_SWITCH", drv_cmd_set_channel_switch, true}, {"SETANTENNAMODE", drv_cmd_set_antenna_mode, true}, {"GETANTENNAMODE", drv_cmd_get_antenna_mode, false}, + {"SET_DISABLE_CHANNEL_LIST", drv_cmd_set_disable_chan_list, true}, {"STOP", drv_cmd_dummy, false}, /* Deprecated commands */ {"RXFILTER-START", drv_cmd_dummy, false}, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 49bfe65c29..992690933e 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -6909,6 +6909,17 @@ static void wlan_destroy_bug_report_lock(void) qdf_spinlock_destroy(&p_cds_context->bug_report_lock); } +#ifdef DISABLE_CHANNEL_LIST +static void wlan_hdd_cache_chann_mutex_destroy(struct hdd_context *hdd_ctx) +{ + qdf_mutex_destroy(&hdd_ctx->cache_channel_lock); +} +#else +static void wlan_hdd_cache_chann_mutex_destroy(struct hdd_context *hdd_ctx) +{ +} +#endif + /** * hdd_wlan_exit() - HDD WLAN exit function * @hdd_ctx: Pointer to the HDD Context @@ -7002,6 +7013,7 @@ static void hdd_wlan_exit(struct hdd_context *hdd_ctx) qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock); qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock); qdf_spinlock_destroy(&hdd_ctx->connection_status_lock); + wlan_hdd_cache_chann_mutex_destroy(hdd_ctx); osif_request_manager_deinit(); @@ -10928,6 +10940,8 @@ int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode) hdd_err("CNSS power down failed put device into Low power mode:%d", ret); } + /* Free the cache channels of the command SET_DISABLE_CHANNEL_LIST */ + wlan_hdd_free_cache_channels(hdd_ctx); hdd_check_for_leaks(hdd_ctx, is_recovery_stop); hdd_debug_domain_set(QDF_DEBUG_DOMAIN_INIT); @@ -11097,6 +11111,18 @@ void hdd_dp_trace_init(struct hdd_config *config) } #endif +#ifdef DISABLE_CHANNEL_LIST +static int wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx) +{ + return qdf_mutex_create(&hdd_ctx->cache_channel_lock); +} +#else +static int wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx) +{ + return 0; +} +#endif + /** * hdd_wlan_startup() - HDD init function * @dev: Pointer to the underlying device @@ -11131,6 +11157,11 @@ int hdd_wlan_startup(struct device *dev) hdd_action_oui_config(hdd_ctx); qdf_nbuf_init_replenish_timer(); + + ret = wlan_hdd_cache_chann_mutex_create(hdd_ctx); + if (QDF_IS_STATUS_ERROR(ret)) + goto err_hdd_free_context; + #ifdef FEATURE_WLAN_CH_AVOID mutex_init(&hdd_ctx->avoid_freq_lock); #endif diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index b242b37bda..c36b8aaca4 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -1168,6 +1168,8 @@ QDF_STATUS hdd_softap_stop_bss(struct hdd_adapter *adapter) } } } + if (adapter->device_mode == QDF_SAP_MODE) + wlan_hdd_restore_channels(hdd_ctx, true); /* Mark the indoor channel (passive) to enable */ if (hdd_ctx->config->force_ssc_disable_indoor_channel) {