diff options
| author | Agrawal Ashish <ashishka@qti.qualcomm.com> | 2016-03-21 17:20:02 +0530 |
|---|---|---|
| committer | Anjaneedevi Kapparapu <akappa@codeaurora.org> | 2016-04-22 17:13:36 +0530 |
| commit | e7dbbfc383b71439edce631a8dc4a4968d09fbf3 (patch) | |
| tree | ab27250ed06842d34d735f0c218efbea2266df2d | |
| parent | b1a3c24ed7e2af1ad86934a2acf9b0237ec9a04b (diff) | |
qcacld-2.0: Implement vendor command for ACS policy
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
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_cfg80211.h | 35 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_main.h | 12 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg80211.c | 131 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_hostapd.c | 6 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_main.c | 25 | ||||
| -rw-r--r-- | CORE/SAP/inc/sapApi.h | 16 | ||||
| -rw-r--r-- | CORE/SAP/src/sapChSelect.c | 6 | ||||
| -rw-r--r-- | CORE/SAP/src/sapInternal.h | 3 | ||||
| -rw-r--r-- | CORE/SAP/src/sapModule.c | 2 |
9 files changed, 231 insertions, 5 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 17a965b84c4b..5fedfe86845d 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -263,6 +263,7 @@ enum qca_nl80211_vendor_subcmds { /* subcommand to get link properties */ QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES = 101, QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105, + QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY = 116, }; enum qca_nl80211_vendor_subcmds_index { @@ -1810,6 +1811,40 @@ enum qca_wlan_vendor_attr_wake_stats { QCA_WLAN_VENDOR_GET_WAKE_STATS_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 +}; + +/** + * 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, + +}; + + struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo ); diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index a973aa28548c..174873dab76b 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1451,6 +1451,16 @@ struct hdd_bpf_context { struct sir_bpf_get_offload capability_response; }; +/** + * 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 stucture definition */ struct hdd_context_s @@ -1812,6 +1822,7 @@ struct hdd_context_s unsigned int last_scan_bug_report_timestamp; bool driver_being_stopped; /* Track if DRIVER STOP cmd is sent */ uint8_t max_mc_addr_list; + struct acs_dfs_policy acs_policy; }; /*--------------------------------------------------------------------------- @@ -2190,5 +2201,6 @@ static inline void hdd_deinit_packet_filtering(hdd_adapter_t *adapter) { } #endif +enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode); #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 76bf3bb6efad..03d87b4541bc 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -109,6 +109,7 @@ #include "wlan_hdd_memdump.h" #include "wlan_logging_sock_svc.h" +#include "sapApi.h" #define g_mode_rates_size (12) #define a_mode_rates_size (8) @@ -186,6 +187,10 @@ #define HDD_CHANNEL_14 14 #define WLAN_HDD_MAX_FEATURE_SET 8 +#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)) + #ifdef FEATURE_WLAN_EXTSCAN /* * Used to allocate the size of 4096 for the EXTScan NL data. @@ -7898,7 +7903,6 @@ 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; status = wlan_hdd_sap_cfg_dfs_override(adapter); if (status < 0) { return status; @@ -10529,6 +10533,115 @@ static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy, return ret; } +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(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX, + data, data_len, + wlan_hdd_set_acs_dfs_config_policy)) { + hddLog(LOGE, FL("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)) { + hddLog(LOGE, FL("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)) { + hddLog(LOGE, FL("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; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { @@ -11001,6 +11114,15 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = .doit = wlan_hdd_cfg80211_process_ndp_cmd }, #endif + { + .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 + }, + }; @@ -12657,7 +12779,6 @@ static inline int wlan_hdd_set_udp_resp_offload(hdd_adapter_t *padapter, } #endif - #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) && !defined(WITH_BACKPORTS) static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, struct beacon_parameters *params) @@ -12689,6 +12810,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, v_BOOL_t MFPCapable = VOS_FALSE; v_BOOL_t MFPRequired = VOS_FALSE; u_int16_t prev_rsn_length = 0; + enum dfs_mode mode; int ret; ENTER(); @@ -12716,6 +12838,11 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, 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); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***", pConfig->dtim_period); diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index aa40347f359a..f56a73301fac 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -6952,6 +6952,7 @@ VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter ) #ifdef WLAN_FEATURE_MBSSID v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; v_CONTEXT_t sapContext=NULL; + enum dfs_mode mode; #endif int ret; @@ -6975,6 +6976,11 @@ VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter ) } pAdapter->sessionCtx.ap.sapContext = sapContext; + pAdapter->sessionCtx.ap.sapConfig.channel = pHddCtx->acs_policy.acs_channel; + mode = pHddCtx->acs_policy.acs_dfs_mode; + pAdapter->sessionCtx.ap.sapConfig.acs_dfs_mode = + wlan_hdd_get_dfs_mode(mode); + status = WLANSAP_Start(sapContext); if ( ! VOS_IS_STATUS_SUCCESS( status ) ) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 4be7de1f1e0d..442bf47e13d6 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -17763,6 +17763,31 @@ void hdd_deinit_packet_filtering(hdd_adapter_t *adapter) } #endif +/** + * 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: + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("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); diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h index be366cbf475e..52452d09ea4d 100644 --- a/CORE/SAP/inc/sapApi.h +++ b/CORE/SAP/inc/sapApi.h @@ -458,6 +458,20 @@ struct sap_acs_cfg { }; +/* + * 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 */ @@ -519,7 +533,7 @@ typedef struct sap_Config { v_U16_t probeRespBcnIEsLen; v_PVOID_t pProbeRespBcnIEsBuffer; /* buffer for addn ies comes from hostapd*/ uint8_t sap_dot11mc; /* Specify if 11MC is enabled or disabled*/ - + enum sap_acs_dfs_mode acs_dfs_mode; } tsap_Config_t; #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE diff --git a/CORE/SAP/src/sapChSelect.c b/CORE/SAP/src/sapChSelect.c index ac74e57c6100..46cea6ce8d0d 100644 --- a/CORE/SAP/src/sapChSelect.c +++ b/CORE/SAP/src/sapChSelect.c @@ -635,7 +635,8 @@ v_BOOL_t sapChanSelInit(tHalHandle halHandle, #endif ccmCfgGetInt(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 = VOS_FALSE; // Fill the channel number in the spectrum in the operating freq band @@ -2473,6 +2474,9 @@ v_U8_t sapSelectChannel(tHalHandle halHandle, ptSapContext pSapCtx, tScanResult if ((NV_CHANNEL_DISABLE == enable_type) || (NV_CHANNEL_INVALID == enable_type)) continue; + if ((pSapCtx->dfs_mode == ACS_DFS_MODE_DISABLE) && + (NV_CHANNEL_DFS == enable_type)) + continue; if ((!dfs_master_cap_enabled) && (NV_CHANNEL_DFS == enable_type)) diff --git a/CORE/SAP/src/sapInternal.h b/CORE/SAP/src/sapInternal.h index 892307856592..ce77ba6dc07e 100644 --- a/CORE/SAP/src/sapInternal.h +++ b/CORE/SAP/src/sapInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -301,6 +301,7 @@ typedef struct sSapContext { */ struct sap_avoid_channels_info sap_detected_avoid_ch_ie; #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + enum sap_acs_dfs_mode dfs_mode; } *ptSapContext; diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c index 882f3047ee8b..fe619deb637a 100644 --- a/CORE/SAP/src/sapModule.c +++ b/CORE/SAP/src/sapModule.c @@ -713,6 +713,7 @@ WLANSAP_SetScanAcsChannelParams(tsap_Config_t *pConfig, /* Channel selection is auto or configured */ pSapCtx->channel = pConfig->channel; + pSapCtx->dfs_mode = pConfig->acs_dfs_mode; #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH pSapCtx->cc_switch_mode = pConfig->cc_switch_mode; #endif @@ -830,6 +831,7 @@ WLANSAP_StartBss /* Channel selection is auto or configured */ pSapCtx->channel = pConfig->channel; + pSapCtx->dfs_mode = pConfig->acs_dfs_mode; pSapCtx->vht_channel_width = pConfig->vht_channel_width; pSapCtx->ch_width_orig = pConfig->ch_width_orig; #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH |
