From 94ca6f67f6e181a995b9cf0be8c72899d99ee032 Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Sun, 11 Dec 2016 18:43:12 +0530 Subject: [PATCH] qcacld-3.0: Add APIs to validate vendor ACS channel If channel set is coming from external application, it could be possible that it doesn't fall into valid channel criteria. Add APIs to validate the channel. Change-Id: I1aa855b64c7702418471111d59c92ebaebe8be49 CRs-Fixed: 1110061 --- core/hdd/inc/wlan_hdd_main.h | 18 +++- core/hdd/src/wlan_hdd_cfg80211.c | 140 ++++++++++++++++++++++++++++--- core/sap/inc/sap_api.h | 23 +++++ core/sap/src/sap_fsm.c | 2 +- core/sap/src/sap_internal.h | 23 ++++- core/sap/src/sap_module.c | 67 +++++++++++++++ 6 files changed, 255 insertions(+), 18 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 77837e4e1b3b..0309e29fd090 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2059,9 +2059,6 @@ int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value); void wlan_hdd_undo_acs(hdd_adapter_t *adapter); -int hdd_update_reg_chan_info(hdd_adapter_t *adapter, - uint32_t channel_count, - uint8_t *channel_list); #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)) static inline int hdd_wlan_nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) @@ -2087,4 +2084,19 @@ static inline int wlan_hdd_validate_session_id(u8 session_id) bool hdd_is_roaming_in_progress(void); void hdd_set_roaming_in_progress(bool value); +/** + * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list + * @ap_adapter: adapter + * @channel_count: valid channel count + * @channel_list: valid channel list + * + * This API returns valid channel list for SAP after removing nol and + * channel which lies outside of configuration. + * + * Return: Zero on success, non-zero on failure + */ +int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter, + uint32_t *channel_count, + uint8_t *channel_list); + #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 633913b23846..0b91f98f7b7e 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1389,6 +1389,29 @@ static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter) return 0; } +/** + * wlan_hdd_sap_get_nol() - Get SAPs NOL + * @ap_adapter: AP adapter + * @nol: Non-occupancy list + * @nol_len: Length of NOL + * + * Get the NOL for SAP + * + * Return: Zero on success, non-zero on failure + */ +static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol, + uint32_t *nol_len) +{ + QDF_STATUS ret; + + ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), + nol, nol_len); + if (QDF_IS_STATUS_ERROR(ret)) + return -EINVAL; + + return 0; +} + /** * hdd_update_reg_chan_info : This API contructs channel info * for all the given channel @@ -6927,24 +6950,83 @@ static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter, } /** - * wlan_hdd_sap_get_nol() - Get SAPs NOL - * @ap_adapter: AP adapter - * @nol: Non-occupancy list - * @nol_len: Length of NOL + * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which + * are in nol list from provided channel list + * @adapter: AP adapter + * @channel_count: channel count + * @channel_list: channel list * - * Get the NOL for SAP - * - * Return: Zero on success, non-zero on failure + * Return: None */ -static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol, - uint32_t *nol_len) +static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter, + uint32_t *channel_count, + uint8_t *channel_list) { - QDF_STATUS ret; + uint8_t i, j; + uint32_t nol_len = 0; + uint8_t nol[QDF_MAX_NUM_CHAN] = {0}; + uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0}; + uint32_t chan_count; + bool found; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), - nol, nol_len); - if (QDF_IS_STATUS_ERROR(ret)) + if (!hdd_ctx) { + hdd_err("hdd ctx not found"); + *channel_count = 0; + return; + } + + if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) { + hdd_err("invalid channel count %d", *channel_count); + return; + } + + wlan_hdd_sap_get_nol(adapter, nol, &nol_len); + if (nol_len == 0) + return; + + qdf_mem_copy(tmp_chan_list, channel_list, *channel_count); + chan_count = *channel_count; + qdf_mem_zero(channel_list, chan_count); + *channel_count = 0; + + for (i = 0 ; i < chan_count; i++) { + if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) || + (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i])) + continue; + found = false; + for (j = 0; j < nol_len; j++) { + if (tmp_chan_list[i] == nol[j]) { + found = true; + hdd_notice("skipped channel %d due to nol", + nol[j]); + break; + } + } + if (!found) { + channel_list[*channel_count] = tmp_chan_list[i]; + *channel_count = *channel_count + 1; + } + } +} + +int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter, + uint32_t *channel_count, + uint8_t *channel_list) +{ + tsap_Config_t *sap_config; + + sap_config = &adapter->sessionCtx.ap.sapConfig; + + qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list, + sap_config->acs_cfg.ch_list_count); + *channel_count = sap_config->acs_cfg.ch_list_count; + wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list); + + if (*channel_count == 0) { + hdd_err("no valid channel found"); return -EINVAL; + } return 0; } @@ -8188,6 +8270,38 @@ static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy, return ret; } +/** + *wlan_hdd_validate_acs_channel() - validate channel provided by ACS + * @adapter: hdd adapter + * @channel: channel number + * + * return: QDF status based on success or failure + */ +static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter, + int channel, int chan_bw) +{ + if (QDF_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(adapter, channel)) + return QDF_STATUS_E_FAILURE; + if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + channel, + PHY_SINGLE_CHANNEL_CENTERED))) { + hdd_notice("channel %d is in nol", channel); + return -EINVAL; + } + + if ((wlansap_is_channel_leaking_in_nol( + WLAN_HDD_GET_SAP_CTX_PTR(adapter), + channel, chan_bw))) { + hdd_notice("channel %d is leaking in nol", channel); + return -EINVAL; + } + + return 0; + +} + + /** * wlan_hdd_cfg80211_setband() - Wrapper to setband * @wiphy: wiphy structure pointer diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index f74e4af0df2d..fac81ce9138d 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -878,6 +878,29 @@ typedef QDF_STATUS (*tpWLAN_SAPEventCB)(tpSap_Event pSapEvent, void *pUsrContext); uint8_t wlansap_get_state(void *p_cds_gctx); +/** + * wlansap_is_channel_in_nol_list() - This API checks if channel is + * in nol list + * @ctx: context pointer + * @channel: channel + * @chanBondState: channel bonding state + * + * Return: True/False + */ +bool wlansap_is_channel_in_nol_list(void *p_cds_gctx, uint8_t channel_no, + ePhyChanBondState chanBondState); +/** + * wlansap_is_channel_leaking_in_nol() - This API checks if channel is leaking + * in nol list + * @ctx: context pointer + * @channel: channel + * @chan_bw: channel bandwidth + * + * Return: True/False + */ +bool wlansap_is_channel_leaking_in_nol(void *ctx, uint8_t channel, + uint8_t chan_bw); + QDF_STATUS wlansap_start_bss(void *p_cds_gctx, tpWLAN_SAPEventCB pSapEventCallback, tsap_Config_t *pConfig, void *pUsrContext); diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 9fb24a6a7158..bba3bfeb3446 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -994,7 +994,7 @@ sap_find_target_channel_in_channel_matrix(ptSapContext sapContext, * Return: QDF_STATUS */ -static QDF_STATUS +QDF_STATUS sap_mark_leaking_ch(ptSapContext sap_ctx, enum phy_ch_width ch_width, tSapDfsNolInfo *nol, diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h index 1259ebbc7808..827ef56b9171 100644 --- a/core/sap/src/sap_internal.h +++ b/core/sap/src/sap_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -433,6 +433,27 @@ QDF_STATUS sap_open_session(tHalHandle hHal, ptSapContext sapContext, QDF_STATUS sap_close_session(tHalHandle hHal, ptSapContext sapContext, csr_roamSessionCloseCallback callback, bool valid); +/** + * sap_mark_leaking_ch() - to mark channel leaking in to nol + * @sap_ctx: pointer to SAP context + * @ch_width: channel width + * @nol: nol info + * @temp_ch_lst_sz: the target channel list + * @temp_ch_lst: the target channel list + * + * This function removes the channels from temp channel list that + * (if selected as target channel) will cause leakage in one of + * the NOL channels + * + * Return: QDF_STATUS + */ +QDF_STATUS +sap_mark_leaking_ch(ptSapContext sap_ctx, + enum phy_ch_width ch_width, + tSapDfsNolInfo *nol, + uint8_t temp_ch_lst_sz, + uint8_t *temp_ch_lst); + #ifdef __cplusplus } #endif diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index a32f623e066d..9ac035ee4648 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -581,6 +581,73 @@ uint8_t wlansap_get_state(void *pCtx) return pSapCtx->sapsMachine; } +bool wlansap_is_channel_in_nol_list(void *p_cds_gctx, + uint8_t channelNumber, + ePhyChanBondState chanBondState) +{ + ptSapContext pSapCtx = NULL; + + pSapCtx = CDS_GET_SAP_CB(p_cds_gctx); + + if (!pSapCtx) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pCtx", __func__); + return QDF_STATUS_E_FAULT; + } + + return sap_dfs_is_channel_in_nol_list(pSapCtx, channelNumber, + chanBondState); +} + +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION +static QDF_STATUS wlansap_mark_leaking_channel(ptSapContext sap_ctx, + tSapDfsNolInfo *nol, + uint8_t *leakage_adjusted_lst, + uint8_t chan_bw) +{ + + return sap_mark_leaking_ch(sap_ctx, chan_bw, nol, 1, + leakage_adjusted_lst); +} +#else +static QDF_STATUS wlansap_mark_leaking_channel(ptSapContext sap_ctx, + tSapDfsNolInfo *nol, + uint8_t *leakage_adjusted_lst, + uint8_t chan_bw) +{ + return QDF_STATUS_SUCCESS; +} +#endif + +bool wlansap_is_channel_leaking_in_nol(void *ctx, uint8_t channel, + uint8_t chan_bw) +{ + ptSapContext sap_ctx = CDS_GET_SAP_CB(ctx); + tpAniSirGlobal mac_ctx; + uint8_t leakage_adjusted_lst[1]; + void *handle = NULL; + tSapDfsNolInfo *nol; + + leakage_adjusted_lst[0] = channel; + handle = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + mac_ctx = PMAC_STRUCT(handle); + if (!mac_ctx) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, + "%s: Invalid mac pointer", __func__); + return QDF_STATUS_E_FAULT; + } + nol = mac_ctx->sap.SapDfsInfo.sapDfsChannelNolList; + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, + FL("sapdfs: Processing current chan against NOL.")); + if (wlansap_mark_leaking_channel(sap_ctx, nol, + leakage_adjusted_lst, chan_bw) != QDF_STATUS_SUCCESS) { + return true; + } + if (leakage_adjusted_lst[0] == 0) + return true; + return false; +} + #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH /*========================================================================== FUNCTION wlansap_check_cc_intf