From c3f92f7f4475fe969a935469ee9dfe5ee07dcac8 Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Mon, 7 Aug 2017 17:04:50 +0530 Subject: [PATCH] qcacld-3.0: Set start and end channel configuration option Add changes to enforce start and end channel limit in do_acs if driver force acs and vendor based acs are enabled. Also add changes to fix memory leak in set vendor channel API Change-Id: Id45aaf3eb3c3dc1606a249136d3801a63ee854c4 CRs-Fixed: 2088567 --- core/hdd/src/wlan_hdd_cfg80211.c | 93 ++++++++++++++++++++++++++++---- core/hdd/src/wlan_hdd_hostapd.c | 3 +- 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index d6182596c020..c7ee32859d03 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1506,6 +1506,59 @@ int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter) return con_ch; } +/** + * wlan_hdd_reset_force_acs_chan_range: Set acs channel ranges as per force ACS + * configuration. + * @hdd_ctx: pointer to hdd context + * @sap_config: pointer to SAP config struct + * + * Return: 0 if success else error code + */ +static int wlan_hdd_reset_force_acs_chan_range(hdd_context_t *hdd_ctx, + tsap_Config_t *sap_config) +{ + bool is_dfs_mode_enabled = false; + uint32_t i, num_channels = 0; + uint8_t channels[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + + if (hdd_ctx->config->force_sap_acs_st_ch > + hdd_ctx->config->force_sap_acs_end_ch) { + hdd_err("invalid configuration for start and end channel"); + return -EINVAL; + } + if (hdd_ctx->config->enableDFSMasterCap) + is_dfs_mode_enabled = true; + + sap_config->acs_cfg.start_ch = + hdd_ctx->config->force_sap_acs_st_ch; + sap_config->acs_cfg.end_ch = + hdd_ctx->config->force_sap_acs_end_ch; + + for (i = sap_config->acs_cfg.start_ch; + i <= sap_config->acs_cfg.end_ch; i++) { + if ((CHANNEL_STATE_ENABLE == + wlan_reg_get_channel_state(hdd_ctx->hdd_pdev, i)) || + (is_dfs_mode_enabled && + CHANNEL_STATE_DFS == + wlan_reg_get_channel_state(hdd_ctx->hdd_pdev, i))) { + channels[num_channels] = i; + num_channels++; + } + } + if (sap_config->acs_cfg.ch_list) + qdf_mem_free(sap_config->acs_cfg.ch_list); + + sap_config->acs_cfg.ch_list = qdf_mem_malloc(num_channels); + if (!sap_config->acs_cfg.ch_list) { + hdd_err("ACS config alloc fail"); + return -ENOMEM; + } + qdf_mem_copy(sap_config->acs_cfg.ch_list, channels, num_channels); + sap_config->acs_cfg.ch_list_count = num_channels; + + return 0; +} + /** * wlan_hdd_set_acs_ch_range : Start ACS channel range values * @sap_cfg: pointer to SAP config struct @@ -1515,7 +1568,6 @@ int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter) * * Return: None */ - static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled, bool vht_enabled) { @@ -1545,7 +1597,6 @@ static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled, if (vht_enabled) sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac; - /* Parse ACS Chan list from hostapd */ if (!sap_cfg->acs_cfg.ch_list) return; @@ -2177,6 +2228,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, hw_mode; + QDF_STATUS qdf_status; /* ***Note*** Donot set SME config related to ACS operation here because * ACS operation is not synchronouse and ACS for Second AP may come when @@ -2325,12 +2377,12 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, hdd_debug("get pcl for DO_ACS vendor command"); /* consult policy manager to get PCL */ - status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE, + qdf_status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE, sap_config->acs_cfg.pcl_channels, &sap_config->acs_cfg.pcl_ch_count, sap_config->acs_cfg.pcl_channels_weight_list, QDF_MAX_NUM_CHAN); - if (QDF_STATUS_SUCCESS != status) + if (QDF_STATUS_SUCCESS != qdf_status) hdd_err("Get PCL failed"); if (sap_config->acs_cfg.pcl_ch_count) { @@ -2342,12 +2394,20 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, pcl_channels[i], sap_config->acs_cfg. pcl_channels_weight_list[i]); - } + } wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled); - /* ACS override for android */ + + if (hdd_ctx->config->force_sap_acs) { + hdd_debug("forcing SAP acs start and end channel"); + status = wlan_hdd_reset_force_acs_chan_range(hdd_ctx, + sap_config); + if (status != 0) + goto out; + } sap_config->acs_cfg.band = hw_mode; + /* ACS override for android */ if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled && !hdd_ctx->config->sap_force_11n_for_11ac) { hdd_debug("ACS Config override for 11AC vhtChannelWidth %d", @@ -2366,7 +2426,6 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, } } - hdd_debug("ACS Config for %s: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d band %d", adapter->dev->name, sap_config->acs_cfg.hw_mode, ch_width, ht_enabled, vht_enabled, @@ -9878,7 +9937,6 @@ static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason, default: hdd_info("invalid reason for timer invoke"); } - qdf_mem_free(channel_list); EXIT(); return status; } @@ -9939,6 +9997,10 @@ static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * (*channel_cnt)); + if (NULL == channel_list) { + hdd_err("Could not allocate for channel_list"); + return -ENOMEM; + } i = 0; nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) { @@ -10020,6 +10082,7 @@ static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy, struct hdd_vendor_chan_info *channel_list = NULL; hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev); hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct hdd_vendor_chan_info *channel_list_ptr; ENTER(); @@ -10041,6 +10104,7 @@ static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy, ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason, &channel_cnt, data, data_len); + channel_list_ptr = channel_list; if (ret_val) return ret_val; @@ -10051,16 +10115,27 @@ static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy, channel_list->chan_width); if (qdf_status == QDF_STATUS_SUCCESS) break; + else if (channel_cnt == 1) { + hdd_err("invalid channel %d received from app", + channel_list->pri_ch); + channel_list->pri_ch = 0; + break; + } + channel_cnt--; channel_list++; } + hdd_debug("received primary channel as %d", channel_list->pri_ch); if ((channel_cnt <= 0) || !channel_list) { - hdd_err("no available channel/chanlist %p", channel_list); + hdd_err("no available channel/chanlist %d/%p", channel_cnt, + channel_list); + qdf_mem_free(channel_list_ptr); return -EINVAL; } qdf_status = hdd_update_acs_channel(adapter, reason, channel_cnt, channel_list); + qdf_mem_free(channel_list_ptr); return qdf_status_to_os_return(qdf_status); } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 766157a4a92e..00a0fde944ea 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -7307,7 +7307,8 @@ static int wlan_hdd_setup_driver_overrides(hdd_adapter_t *ap_adapter) struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter); if (ap_adapter->device_mode == QDF_SAP_MODE && - hdd_ctx->config->force_sap_acs) + hdd_ctx->config->force_sap_acs && + !hdd_ctx->config->vendor_acs_support) goto setup_acs_overrides; /* Fixed channel 11AC override: