Browse Source

qcacld-3.0: Implement vendor command for ACS policy

qcacld-2.0 to qcacld-3.0 propagation

Add support for vendor command which informs the driver about the
ACS policy.
QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY is used to inform driver about
ACS policies.
QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE attribute tells if DFS channel
should be enabled or disabled in ACS.
QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL attribute provides channel number to SAP
module to skip ACS and use this channel as operating channel.

Change-Id: I1ba69ed8fdf1c56a90e857054c725b830293d6bf
CRs-Fixed: 997433
Agrawal Ashish 8 years ago
parent
commit
6563461fa7

+ 12 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -1224,6 +1224,16 @@ enum driver_modules_status {
 	DRIVER_MODULES_CLOSED
 };
 
+/**
+ * struct acs_dfs_policy - Define ACS policies
+ * @acs_dfs_mode: Dfs mode enabled/disabled.
+ * @acs_channel: pre defined channel to avoid ACS.
+ */
+struct acs_dfs_policy {
+	enum dfs_mode acs_dfs_mode;
+	uint8_t acs_channel;
+};
+
 /** Adapter structure definition */
 
 struct hdd_context_s {
@@ -1495,6 +1505,7 @@ struct hdd_context_s {
 	bool stop_modules_in_progress;
 	bool start_modules_in_progress;
 	bool update_mac_addr_to_fw;
+	struct acs_dfs_policy acs_policy;
 };
 
 /*---------------------------------------------------------------------------
@@ -1848,4 +1859,5 @@ static inline void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
 #endif
 void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context);
 
+enum  sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode);
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 128 - 1
core/hdd/src/wlan_hdd_cfg80211.c

@@ -74,6 +74,8 @@
 #include "wlan_hdd_nan.h"
 #include <wlan_hdd_ipa.h>
 #include "wlan_logging_sock_svc.h"
+#include "sap_api.h"
+
 
 #ifdef FEATURE_WLAN_EXTSCAN
 #include "wlan_hdd_ext_scan.h"
@@ -142,6 +144,11 @@
 
 #define HDD_CHANNEL_14 14
 
+#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
+			mode <= DFS_MODE_DEPRIORITIZE))
+#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
+		|| (channel >= 36 && channel <= 184))
+
 #define MAX_TXPOWER_SCALE 4
 #define CDS_MAX_FEATURE_SET   8
 
@@ -1330,7 +1337,10 @@ static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
 	int status;
 
 	sap_config = &adapter->sessionCtx.ap.sapConfig;
-	sap_config->channel = AUTO_CHANNEL_SELECT;
+	if (hdd_ctx->acs_policy.acs_channel)
+		sap_config->channel = hdd_ctx->acs_policy.acs_channel;
+	else
+		sap_config->channel = AUTO_CHANNEL_SELECT;
 
 	status = wlan_hdd_sap_cfg_dfs_override(adapter);
 	if (status < 0) {
@@ -6790,6 +6800,115 @@ wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
 	[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
 };
 
+static const struct nla_policy
+wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
+	[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
+};
+
+/**
+ * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Length of @data
+ *
+ * This function parses the incoming NL vendor command data attributes and
+ * updates the SAP context about channel_hint and DFS mode.
+ * If channel_hint is set, SAP will choose that channel
+ * as operating channel.
+ *
+ * If DFS mode is enabled, driver will include DFS channels
+ * in ACS else driver will skip DFS channels.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int
+__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
+		struct wireless_dev *wdev,
+		const void *data, int data_len)
+{
+	hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
+	int ret;
+	struct acs_dfs_policy *acs_policy;
+	int mode = DFS_MODE_NONE;
+	int channel_hint = 0;
+
+	ENTER_DEV(wdev->netdev);
+
+	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EINVAL;
+	}
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (0 != ret)
+		return ret;
+
+	if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
+				data, data_len,
+				wlan_hdd_set_acs_dfs_config_policy)) {
+		hdd_err("invalid attr");
+		return -EINVAL;
+	}
+
+	acs_policy = &hdd_ctx->acs_policy;
+	/*
+	 * SCM sends this attribute to restrict SAP from choosing
+	 * DFS channels from ACS.
+	 */
+	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
+		mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
+
+	if (!IS_DFS_MODE_VALID(mode)) {
+		hdd_err("attr acs dfs mode is not valid");
+		return -EINVAL;
+	}
+	acs_policy->acs_dfs_mode = mode;
+
+	/*
+	 * SCM sends this attribute to provide an active channel,
+	 * to skip redundant ACS between drivers, and save driver start up time
+	 */
+	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
+		channel_hint = nla_get_u8(
+				tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
+
+	if (!IS_CHANNEL_VALID(channel_hint)) {
+		hdd_err("acs channel is not valid");
+		return -EINVAL;
+	}
+	acs_policy->acs_channel = channel_hint;
+
+	return 0;
+}
+
+/**
+ * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
+ * @wiphy:    wiphy structure pointer
+ * @wdev:     Wireless device structure pointer
+ * @data:     Pointer to the data received
+ * @data_len: Length of @data
+ *
+ * This function parses the incoming NL vendor command data attributes and
+ * updates the SAP context about channel_hint and DFS mode.
+ *
+ * Return: 0 on success; errno on failure
+ */
+static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
+		struct wireless_dev *wdev,
+		const void *data, int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
 /**
  * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
  * SAP is on unsafe channel.
@@ -7816,6 +7935,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
 			WIPHY_VENDOR_CMD_NEED_RUNNING,
 		.doit = wlan_hdd_cfg80211_bpf_offload
 	},
+	{
+		.info.vendor_id = QCA_NL80211_VENDOR_ID,
+		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			WIPHY_VENDOR_CMD_NEED_NETDEV |
+			WIPHY_VENDOR_CMD_NEED_RUNNING,
+		.doit = wlan_hdd_cfg80211_acs_dfs_mode
+	},
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,

+ 34 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -419,6 +419,7 @@ enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE = 109,
 	/* Tx power scaling in db subcommands */
 	QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB = 115,
+	QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY = 116,
 	QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG  = 118,
 	QCA_NL80211_VENDOR_SUBCMD_TSF = 119,
 	QCA_NL80211_VENDOR_SUBCMD_WISA = 120,
@@ -2754,6 +2755,39 @@ enum qca_vendor_attr_txpower_scale_decr_db {
 		QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_AFTER_LAST - 1
 };
 
+/**
+ * enum dfs_mode - state of DFS mode
+ * @DFS_MODE_NONE: DFS mode attribute is none
+ * @DFS_MODE_ENABLE:  DFS mode is enabled
+ * @DFS_MODE_DISABLE: DFS mode is disabled
+ * @DFS_MODE_DEPRIORITIZE: Deprioritize DFS channels in scanning
+ */
+enum dfs_mode {
+	DFS_MODE_NONE,
+	DFS_MODE_ENABLE,
+	DFS_MODE_DISABLE,
+	DFS_MODE_DEPRIORITIZE
+};
+
+/**
+ * enum qca_wlan_vendor_attr_acs_config - Config params for ACS
+ * @QCA_WLAN_VENDOR_ATTR_ACS_MODE_INVALID: Invalid
+ * @QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE: Dfs mode for ACS
+ * QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT: channel_hint for ACS
+ * QCA_WLAN_VENDOR_ATTR_ACS_DFS_AFTER_LAST: after_last
+ * QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX: max attribute
+ */
+enum qca_wlan_vendor_attr_acs_config {
+	QCA_WLAN_VENDOR_ATTR_ACS_MODE_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE,
+	QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT,
+
+	QCA_WLAN_VENDOR_ATTR_ACS_DFS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX =
+		QCA_WLAN_VENDOR_ATTR_ACS_DFS_AFTER_LAST - 1,
+
+};
+
 /**
  * enum qca_wlan_vendor_attr_sap_config - config params for sap configuration
  * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_INVALID: invalid

+ 12 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -5595,6 +5595,7 @@ QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter)
 	int ret;
 	enum tQDF_ADAPTER_MODE mode;
 	uint32_t session_id = CSR_SESSION_ID_INVALID;
+	enum dfs_mode acs_dfs_mode;
 
 	ENTER();
 
@@ -5605,6 +5606,11 @@ QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter)
 	}
 
 	pAdapter->sessionCtx.ap.sapContext = sapContext;
+	pAdapter->sessionCtx.ap.sapConfig.channel =
+		pHddCtx->acs_policy.acs_channel;
+	acs_dfs_mode = pHddCtx->acs_policy.acs_dfs_mode;
+	pAdapter->sessionCtx.ap.sapConfig.acs_dfs_mode =
+		wlan_hdd_get_dfs_mode(acs_dfs_mode);
 
 	if (pAdapter->device_mode == QDF_P2P_GO_MODE) {
 		mode = QDF_P2P_GO_MODE;
@@ -6921,6 +6927,8 @@ int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
 	bool MFPCapable = false;
 	bool MFPRequired = false;
 	uint16_t prev_rsn_length = 0;
+	enum dfs_mode mode;
+
 	ENTER();
 
 	if (cds_is_connection_in_progress()) {
@@ -6952,6 +6960,10 @@ int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
 
 	pConfig->enOverLapCh = iniConfig->gEnableOverLapCh;
 	pConfig->dtim_period = pBeacon->dtim_period;
+	if (pHddCtx->acs_policy.acs_channel)
+		pConfig->channel = pHddCtx->acs_policy.acs_channel;
+	mode = pHddCtx->acs_policy.acs_dfs_mode;
+	pConfig->acs_dfs_mode = wlan_hdd_get_dfs_mode(mode);
 
 	hdd_info("****pConfig->dtim_period=%d***",
 		pConfig->dtim_period);

+ 25 - 0
core/hdd/src/wlan_hdd_main.c

@@ -9194,6 +9194,31 @@ int hdd_update_config(hdd_context_t *hdd_ctx)
 	return ret;
 }
 
+/**
+ * wlan_hdd_get_dfs_mode() - get ACS DFS mode
+ * @mode : cfg80211 DFS mode
+ *
+ * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
+ */
+enum  sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
+{
+	switch (mode) {
+	case DFS_MODE_ENABLE:
+		return ACS_DFS_MODE_ENABLE;
+		break;
+	case DFS_MODE_DISABLE:
+		return ACS_DFS_MODE_DISABLE;
+		break;
+	case DFS_MODE_DEPRIORITIZE:
+		return ACS_DFS_MODE_DEPRIORITIZE;
+		break;
+	default:
+		hdd_err("ACS dfs mode is NONE");
+		return  ACS_DFS_MODE_NONE;
+	}
+}
+
+
 /* Register the module init/exit functions */
 module_init(hdd_module_init);
 module_exit(hdd_module_exit);

+ 15 - 0
core/sap/inc/sap_api.h

@@ -508,6 +508,20 @@ enum vendor_ie_access_policy {
 	ACCESS_POLICY_DONOT_RESPOND_IF_IE_IS_PRESENT,
 };
 
+/*
+ * enum sap_acs_dfs_mode- state of DFS mode
+ * @ACS_DFS_MODE_NONE: DFS mode attribute is not valid
+ * @ACS_DFS_MODE_ENABLE:  DFS mode is enabled
+ * @ACS_DFS_MODE_DISABLE: DFS mode is disabled
+ * @ACS_DFS_MODE_DEPRIORITIZE: Deprioritize DFS channels in scanning
+ */
+enum  sap_acs_dfs_mode {
+	ACS_DFS_MODE_NONE,
+	ACS_DFS_MODE_ENABLE,
+	ACS_DFS_MODE_DISABLE,
+	ACS_DFS_MODE_DEPRIORITIZE
+};
+
 typedef struct sap_Config {
 	tSap_SSIDInfo_t SSIDinfo;
 	eCsrPhyMode SapHw_mode;         /* Wireless Mode */
@@ -577,6 +591,7 @@ typedef struct sap_Config {
 	uint8_t ampdu_size;
 	tSirMacRateSet supp_rate_set;
 	tSirMacRateSet extended_rate_set;
+	enum sap_acs_dfs_mode acs_dfs_mode;
 } tsap_Config_t;
 
 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE

+ 5 - 2
core/sap/src/sap_ch_select.c

@@ -586,7 +586,8 @@ bool sap_chan_sel_init(tHalHandle halHandle,
 #endif
 	sme_cfg_get_int(halHandle, WNI_CFG_DFS_MASTER_ENABLED,
 			&dfs_master_cap_enabled);
-	if (dfs_master_cap_enabled == 0)
+	if (dfs_master_cap_enabled == 0 ||
+	    ACS_DFS_MODE_DISABLE == pSapCtx->dfs_mode)
 		include_dfs_ch = false;
 
 	/* Fill the channel number in the spectrum in the operating freq band */
@@ -1949,7 +1950,6 @@ static uint8_t sap_select_channel_no_scan_result(tHalHandle hal,
 		if ((ch_type == CHANNEL_STATE_DISABLE) ||
 			(ch_type == CHANNEL_STATE_INVALID))
 			continue;
-
 		if ((!dfs_master_cap_enabled) &&
 			(CHANNEL_STATE_DFS == ch_type)) {
 			QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
@@ -1957,6 +1957,9 @@ static uint8_t sap_select_channel_no_scan_result(tHalHandle hal,
 				__func__, safe_channels[i].channelNumber);
 			continue;
 		}
+		if ((sap_ctx->dfs_mode == ACS_DFS_MODE_DISABLE) &&
+		    (CHANNEL_STATE_DFS == ch_type))
+			continue;
 
 		if (safe_channels[i].isSafe == true) {
 			QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,

+ 1 - 0
core/sap/src/sap_internal.h

@@ -270,6 +270,7 @@ typedef struct sSapContext {
 	uint8_t beacon_tx_rate;
 	tSirMacRateSet supp_rate_set;
 	tSirMacRateSet extended_rate_set;
+	enum sap_acs_dfs_mode dfs_mode;
 } *ptSapContext;
 
 /*----------------------------------------------------------------------------

+ 2 - 0
core/sap/src/sap_module.c

@@ -647,6 +647,7 @@ wlansap_set_scan_acs_channel_params(tsap_Config_t *pconfig,
 
 	/* Channel selection is auto or configured */
 	psap_ctx->channel = pconfig->channel;
+	psap_ctx->dfs_mode = pconfig->acs_dfs_mode;
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 	psap_ctx->cc_switch_mode = pconfig->cc_switch_mode;
 #endif
@@ -810,6 +811,7 @@ QDF_STATUS wlansap_start_bss(void *pCtx,     /* pwextCtx */
 
 	/* Channel selection is auto or configured */
 	pSapCtx->channel = pConfig->channel;
+	pSapCtx->dfs_mode = pConfig->acs_dfs_mode;
 	pSapCtx->ch_params.ch_width = pConfig->ch_params.ch_width;
 	pSapCtx->ch_params.center_freq_seg0 =
 		pConfig->ch_params.center_freq_seg0;