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