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
This commit is contained in:
Agrawal Ashish 2016-08-18 13:24:32 +05:30 • committed by Gerrit - the friendly Code Review server
commit 6563461fa7
9 changed files with 234 additions and 3 deletions

View file

@ -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) */

View file

@ -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,

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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,

View file

@ -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;
/*----------------------------------------------------------------------------

View file

@ -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;