diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index a13d92fe8c62..44e88e969116 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -2770,6 +2770,64 @@ static void wlan_hdd_trim_acs_channel_list(uint32_t *pcl, uint8_t pcl_count, *org_ch_list_count = ch_list_count; } +/** + * wlan_hdd_handle_zero_acs_list() - Handle worst case of acs channel + * trimmed to zero + * @hdd_ctx: struct hdd_context + * @org_ch_list: ACS channel list from user space + * @org_ch_list_count: ACS channel count from user space + * + * When all chan in ACS freq list is filtered out + * by wlan_hdd_trim_acs_channel_list, the hostapd start will fail. + * This happens when PCL is PM_24G_SCC_CH_SBS_CH, and SAP acs range includes + * 5G channel list. One example is STA active on 6Ghz chan. Hostapd + * start SAP on 5G ACS range. The intersection of PCL and ACS range is zero. + * Instead of ACS failure, this API selects one channel from ACS range + * and report to Hostapd. When hostapd do start_ap, the driver will + * force SCC to 6G or move SAP to 2G based on SAP's configuration. + * + * Return: None + */ +static void wlan_hdd_handle_zero_acs_list(struct hdd_context *hdd_ctx, + uint32_t *acs_freq_list, + uint8_t *acs_ch_list_count, + uint32_t *org_freq_list, + uint8_t org_ch_list_count) +{ + uint16_t i, sta_count; + uint32_t acs_chan_default = 0; + + if (!acs_ch_list_count || *acs_ch_list_count > 0 || + !acs_freq_list) { + return; + } + if (!org_ch_list_count || !org_freq_list) + return; + + if (!policy_mgr_is_force_scc(hdd_ctx->psoc)) + return; + sta_count = policy_mgr_mode_specific_connection_count + (hdd_ctx->psoc, PM_STA_MODE, NULL); + sta_count += policy_mgr_mode_specific_connection_count + (hdd_ctx->psoc, PM_P2P_CLIENT_MODE, NULL); + if (!sta_count) + return; + + for (i = 0; i < org_ch_list_count; i++) { + if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, + org_freq_list[i])) { + acs_chan_default = org_freq_list[i]; + break; + } + } + if (!acs_chan_default) + acs_chan_default = org_freq_list[0]; + + acs_freq_list[0] = acs_chan_default; + *acs_ch_list_count = 1; + hdd_debug("retore acs chan list to single freq %d", acs_chan_default); +} + /** * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD * @wiphy: Linux wiphy struct pointer @@ -2918,7 +2976,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg)); - hdd_debug("channel width =%d", ch_width); + hdd_debug("channel width =%d hw_mode %d", ch_width, hw_mode); if (ch_width == 160) sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ; else if (ch_width == 80) @@ -3036,7 +3094,14 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, sap_config->acs_cfg.pcl_ch_count, sap_config->acs_cfg.freq_list, &sap_config->acs_cfg.ch_list_count); - + if (!sap_config->acs_cfg.ch_list_count && + sap_config->acs_cfg.master_ch_list_count) + wlan_hdd_handle_zero_acs_list( + hdd_ctx, + sap_config->acs_cfg.freq_list, + &sap_config->acs_cfg.ch_list_count, + sap_config->acs_cfg.master_freq_list, + sap_config->acs_cfg.master_ch_list_count); /* if it is only one channel, send ACS event to upper layer */ if (sap_config->acs_cfg.ch_list_count == 1) { sap_config->acs_cfg.pri_ch_freq =