diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index b06bf29a9fc0..7c1d9c6df5af 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -4502,6 +4502,7 @@ struct adaptive_dwelltime_params { */ struct csa_offload_params { uint8_t channel; + uint32_t csa_chan_freq; uint8_t switch_mode; uint8_t sec_chan_offset; uint8_t new_ch_width; diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h index fba994fc3856..11a971eb7fe2 100644 --- a/core/mac/src/pe/include/lim_global.h +++ b/core/mac/src/pe/include/lim_global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -415,6 +415,7 @@ typedef enum eLimChannelSwitchState { /* Channel Switch Info */ typedef struct sLimChannelSwitchInfo { tLimChannelSwitchState state; + uint32_t sw_target_freq; uint8_t primaryChannel; uint8_t ch_center_freq_seg0; uint8_t ch_center_freq_seg1; diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index 929473e1ee2a..2e77cc08d07a 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -85,8 +85,7 @@ void lim_stop_tx_and_switch_channel(struct mac_context *mac, uint8_t sessionId) mac->lim.lim_timers.gLimChannelSwitchTimer.sessionId = sessionId; status = policy_mgr_check_and_set_hw_mode_for_channel_switch(mac->psoc, pe_session->smeSessionId, - wlan_chan_to_freq( - pe_session->gLimChannelSwitch.primaryChannel), + pe_session->gLimChannelSwitch.sw_target_freq, POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH_STA); /* @@ -100,8 +99,9 @@ void lim_stop_tx_and_switch_channel(struct mac_context *mac, uint8_t sessionId) * So contunue with CSA from here. */ if (status == QDF_STATUS_E_FAILURE) { - pe_err("Failed to set required HW mode for channel %d, ignore CSA", - pe_session->gLimChannelSwitch.primaryChannel); + pe_err("Failed to set required HW mode for channel %d freq %d, ignore CSA", + pe_session->gLimChannelSwitch.primaryChannel, + pe_session->gLimChannelSwitch.sw_target_freq); return; } @@ -240,6 +240,9 @@ static void __lim_process_channel_switch_action_frame(struct mac_context *mac_ct bcn_period = (uint16_t)val; ch_switch_params->primaryChannel = chnl_switch_frame->ChanSwitchAnn.newChannel; + ch_switch_params->sw_target_freq = wlan_reg_legacy_chan_to_freq + (mac_ctx->pdev, + chnl_switch_frame->ChanSwitchAnn.newChannel); ch_switch_params->switchCount = chnl_switch_frame->ChanSwitchAnn.switchCount; ch_switch_params->switchTimeoutValue = diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 8c3fdf78ba42..f26f64f73552 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -56,6 +56,7 @@ #include "wlan_utility.h" #include #include "../../core/src/vdev_mgr_ops.h" +#include "wma.h" /* SME REQ processing function templates */ static bool __lim_process_sme_sys_ready_ind(struct mac_context *, uint32_t *); @@ -5398,33 +5399,28 @@ end: update_ie->pAdditionIEBuffer = NULL; } -/** - * send_extended_chan_switch_action_frame()- function to send ECSA - * action frame for each sta connected to SAP/GO and AP in case of - * STA . - * @mac_ctx: pointer to global mac structure - * @new_channel: new channel to switch to. - * @ch_bandwidth: BW of channel to calculate op_class - * @session_entry: pe session - * - * This function is called to send ECSA frame for STA/CLI and SAP/GO. - * - * Return: void - */ - -static void send_extended_chan_switch_action_frame(struct mac_context *mac_ctx, - uint16_t new_channel, uint8_t ch_bandwidth, - struct pe_session *session_entry) +void send_extended_chan_switch_action_frame(struct mac_context *mac_ctx, + uint16_t new_channel_freq, + enum phy_ch_width ch_bandwidth, + enum offset_t offset, + struct pe_session *session_entry) { - uint16_t op_class; + uint8_t op_class = 0; uint8_t switch_mode = 0, i; tpDphHashNode psta; uint8_t switch_count; + uint8_t new_channel = 0; - op_class = wlan_reg_dmn_get_opclass_from_channel( - mac_ctx->scan.countryCodeCurrent, - new_channel, - ch_bandwidth); + new_channel = wlan_reg_freq_to_chan(mac_ctx->pdev, new_channel_freq); + if (WLAN_REG_IS_6GHZ_CHAN_FREQ(new_channel_freq)) + wlan_reg_freq_width_to_chan_op_class + (mac_ctx->pdev, new_channel_freq, + ch_width_in_mhz(ch_bandwidth), + true, BIT(BEHAV_NONE), &op_class, + &new_channel); + else + op_class = wlan_reg_dmn_get_opclass_from_channel + (mac_ctx->scan.countryCodeCurrent, new_channel, offset); if (LIM_IS_AP_ROLE(session_entry) && (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false)) @@ -5453,11 +5449,12 @@ static void send_extended_chan_switch_action_frame(struct mac_context *mac_ctx, } void lim_send_chan_switch_action_frame(struct mac_context *mac_ctx, - uint16_t new_channel, - uint8_t ch_bandwidth, + uint16_t new_channel_freq, + enum phy_ch_width ch_bandwidth, + enum offset_t offset, struct pe_session *session_entry) { - uint16_t op_class; + uint8_t op_class = 0, new_channel; uint8_t switch_mode = 0, i; uint8_t switch_count; tpDphHashNode psta; @@ -5465,10 +5462,17 @@ void lim_send_chan_switch_action_frame(struct mac_context *mac_ctx, dph_node_array_ptr = session_entry->dph.dphHashTable.pDphNodeArray; - op_class = wlan_reg_dmn_get_opclass_from_channel( - mac_ctx->scan.countryCodeCurrent, - new_channel, ch_bandwidth); - + new_channel = wlan_reg_freq_to_chan(mac_ctx->pdev, new_channel_freq); + if (WLAN_REG_IS_6GHZ_CHAN_FREQ(new_channel_freq)) + wlan_reg_freq_width_to_chan_op_class + (mac_ctx->pdev, new_channel_freq, + ch_width_in_mhz(ch_bandwidth), + true, BIT(BEHAV_NONE), &op_class, + &new_channel); + else + op_class = wlan_reg_dmn_get_opclass_from_channel + (mac_ctx->scan.countryCodeCurrent, + new_channel, offset); if (LIM_IS_AP_ROLE(session_entry) && (false == mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch)) switch_mode = session_entry->gLimChannelSwitch.switchMode; @@ -5518,6 +5522,8 @@ static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac_ctx, tLimWiderBWChannelSwitchInfo *wider_bw_ch_switch; enum offset_t ch_offset; QDF_STATUS status; + enum phy_ch_width ch_width; + uint32_t target_ch_freq; if (!msg_buf) { pe_err("Buffer is Pointing to NULL"); @@ -5541,14 +5547,21 @@ static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac_ctx, /* target channel */ session_entry->gLimChannelSwitch.primaryChannel = - wlan_reg_freq_to_chan(mac_ctx->pdev, dfs_csa_ie_req->target_chan_freq); - + wlan_reg_freq_to_chan(mac_ctx->pdev, + dfs_csa_ie_req->target_chan_freq); + session_entry->gLimChannelSwitch.sw_target_freq = + dfs_csa_ie_req->target_chan_freq; + target_ch_freq = dfs_csa_ie_req->target_chan_freq; /* Channel switch announcement needs to be included in beacon */ session_entry->dfsIncludeChanSwIe = true; session_entry->gLimChannelSwitch.switchCount = dfs_csa_ie_req->ch_switch_beacon_cnt; - session_entry->gLimChannelSwitch.ch_width = - dfs_csa_ie_req->ch_params.ch_width; + ch_width = dfs_csa_ie_req->ch_params.ch_width; + if (ch_width >= CH_WIDTH_160MHZ && + wma_get_vht_ch_width() < WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) { + ch_width = CH_WIDTH_80MHZ; + } + session_entry->gLimChannelSwitch.ch_width = ch_width; session_entry->gLimChannelSwitch.sec_ch_offset = dfs_csa_ie_req->ch_params.sec_ch_offset; if (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false) @@ -5564,7 +5577,7 @@ static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac_ctx, /* Now encode the Wider Ch BW element depending on the ch width */ wider_bw_ch_switch = &session_entry->gLimWiderBWChannelSwitch; - switch (dfs_csa_ie_req->ch_params.ch_width) { + switch (ch_width) { case CH_WIDTH_20MHZ: /* * Wide channel BW sublement in channel wrapper element is not @@ -5645,27 +5658,31 @@ skip_vht: if (QDF_IS_STATUS_ERROR(status)) pe_err("cannot start ap_ecsa_timer"); - if (dfs_csa_ie_req->ch_params.ch_width == CH_WIDTH_80MHZ) + if (ch_width == CH_WIDTH_80MHZ || ch_width == CH_WIDTH_160MHZ || + ch_width == CH_WIDTH_80P80MHZ) ch_offset = BW80; else ch_offset = dfs_csa_ie_req->ch_params.sec_ch_offset; - pe_debug("IE count:%d chan:%d width:%d wrapper:%d ch_offset:%d", - session_entry->gLimChannelSwitch.switchCount, - session_entry->gLimChannelSwitch.primaryChannel, - session_entry->gLimChannelSwitch.ch_width, - session_entry->dfsIncludeChanWrapperIe, - ch_offset); + pe_debug("IE count:%d chan:%d freq %d width:%d wrapper:%d ch_offset:%d", + session_entry->gLimChannelSwitch.switchCount, + session_entry->gLimChannelSwitch.primaryChannel, + session_entry->gLimChannelSwitch.sw_target_freq, + session_entry->gLimChannelSwitch.ch_width, + session_entry->dfsIncludeChanWrapperIe, + ch_offset); /* Send ECSA/CSA Action frame after updating the beacon */ - if (CHAN_HOP_ALL_BANDS_ENABLE) - lim_send_chan_switch_action_frame(mac_ctx, - session_entry->gLimChannelSwitch.primaryChannel, - ch_offset, session_entry); + if (CHAN_HOP_ALL_BANDS_ENABLE && + !WLAN_REG_IS_6GHZ_CHAN_FREQ(target_ch_freq)) + lim_send_chan_switch_action_frame + (mac_ctx, + session_entry->gLimChannelSwitch.primaryChannel, + ch_width, ch_offset, session_entry); else - send_extended_chan_switch_action_frame(mac_ctx, - session_entry->gLimChannelSwitch.primaryChannel, - ch_offset, session_entry); + send_extended_chan_switch_action_frame + (mac_ctx, target_ch_freq, ch_width, ch_offset, + session_entry); } /** @@ -5685,6 +5702,7 @@ static void lim_process_ext_change_channel(struct mac_context *mac_ctx, struct sir_sme_ext_cng_chan_req *ext_chng_channel = (struct sir_sme_ext_cng_chan_req *) msg; struct pe_session *session_entry = NULL; + uint32_t new_ext_chan_freq; if (!msg) { pe_err("Buffer is Pointing to NULL"); @@ -5701,9 +5719,11 @@ static void lim_process_ext_change_channel(struct mac_context *mac_ctx, pe_err("not an STA/CLI session"); return; } - send_extended_chan_switch_action_frame(mac_ctx, - ext_chng_channel->new_channel, - 0, session_entry); + new_ext_chan_freq = + wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, + ext_chng_channel->new_channel); + send_extended_chan_switch_action_frame(mac_ctx, new_ext_chan_freq, 0, + 0, session_entry); } /** diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index a33e448b9b44..3829b5309f3c 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1623,6 +1623,8 @@ void lim_handle_csa_offload_msg(struct mac_context *mac_ctx, session_entry->gLimChannelSwitch.switchCount = 0; session_entry->gLimChannelSwitch.primaryChannel = csa_params->channel; + session_entry->gLimChannelSwitch.sw_target_freq = + csa_params->csa_chan_freq; session_entry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; session_entry->gLimChannelSwitch.ch_width = CH_WIDTH_20MHZ; @@ -1633,7 +1635,7 @@ void lim_handle_csa_offload_msg(struct mac_context *mac_ctx, chnl_switch_info = &session_entry->gLimWiderBWChannelSwitch; - if (WLAN_REG_IS_24GHZ_CH(csa_params->channel)) { + if (WLAN_REG_IS_24GHZ_CH_FREQ(csa_params->csa_chan_freq)) { channel_bonding_mode = mac_ctx->roam.configParam.channelBondingMode24GHz; } else { @@ -1641,14 +1643,16 @@ void lim_handle_csa_offload_msg(struct mac_context *mac_ctx, mac_ctx->roam.configParam.channelBondingMode5GHz; } - pe_debug("vht: %d ht: %d flag: %x chan: %d, sec_ch_offset %d cbmode %d", + pe_debug("vht: %d ht: %d he %d flag: %x chan: %d, sec_ch_offset %d cbmode %d", session_entry->vhtCapability, session_entry->htSupportedChannelWidthSet, + lim_is_session_he_capable(session_entry), csa_params->ies_present_flag, csa_params->channel, csa_params->sec_chan_offset, channel_bonding_mode); - pe_debug("seg1: %d seg2: %d width: %d country: %s class: %d", + pe_debug("freq %d seg1: %d seg2: %d width: %d country: %s class: %d", + csa_params->csa_chan_freq, csa_params->new_ch_freq_seg1, csa_params->new_ch_freq_seg2, csa_params->new_ch_width, @@ -1657,8 +1661,9 @@ void lim_handle_csa_offload_msg(struct mac_context *mac_ctx, session_entry->htSupportedChannelWidthSet = false; - if (session_entry->vhtCapability && channel_bonding_mode && - session_entry->htCapability) { + if (channel_bonding_mode && + ((session_entry->vhtCapability && session_entry->htCapability) || + lim_is_session_he_capable(session_entry))) { if ((csa_params->ies_present_flag & lim_wbw_ie_present) && (QDF_STATUS_SUCCESS == lim_process_csa_wbw_ie(mac_ctx, csa_params, chnl_switch_info, @@ -1679,15 +1684,29 @@ void lim_handle_csa_offload_msg(struct mac_context *mac_ctx, } } else if (csa_params->ies_present_flag & lim_xcsa_ie_present) { - chan_space = + uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); + + if (wlan_reg_is_6ghz_op_class + (mac_ctx->pdev, csa_params->new_op_class)) { + chan_space = wlan_reg_get_op_class_width + (mac_ctx->pdev, + csa_params->new_op_class, true); + } else { + chan_space = wlan_reg_dmn_get_chanwidth_from_opclass( mac_ctx->scan.countryCodeCurrent, csa_params->channel, csa_params->new_op_class); + } + if (chan_space >= 160 && fw_vht_ch_wd < + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) + chan_space = 80; session_entry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; - - if (chan_space == 80) { + if (chan_space == 160) { + chnl_switch_info->newChanWidth = + CH_WIDTH_160MHZ; + } else if (chan_space == 80) { chnl_switch_info->newChanWidth = CH_WIDTH_80MHZ; session_entry->htSupportedChannelWidthSet = @@ -1797,19 +1816,17 @@ void lim_handle_csa_offload_msg(struct mac_context *mac_ctx, pe_debug("new ch width: %d space: %d new ht width %d", session_entry->gLimChannelSwitch.ch_width, chan_space, session_entry->htSupportedChannelWidthSet); - if ((wlan_reg_freq_to_chan(mac_ctx->pdev, - session_entry->curr_op_freq) == - csa_params->channel) && - session_entry->ch_width == - session_entry->gLimChannelSwitch.ch_width) { + if (session_entry->curr_op_freq == csa_params->csa_chan_freq && + session_entry->ch_width == + session_entry->gLimChannelSwitch.ch_width) { pe_debug("Ignore CSA, no change in ch and bw"); goto err; } - if (WLAN_REG_IS_24GHZ_CH(csa_params->channel) && - (session_entry->dot11mode == MLME_DOT11_MODE_11A)) + if (WLAN_REG_IS_24GHZ_CH_FREQ(csa_params->csa_chan_freq) && + session_entry->dot11mode == MLME_DOT11_MODE_11A) session_entry->dot11mode = MLME_DOT11_MODE_11G; - else if (WLAN_REG_IS_5GHZ_CH(csa_params->channel) && + else if (WLAN_REG_IS_5GHZ_CH_FREQ(csa_params->csa_chan_freq) && ((session_entry->dot11mode == MLME_DOT11_MODE_11G) || (session_entry->dot11mode == MLME_DOT11_MODE_11G_ONLY))) session_entry->dot11mode = MLME_DOT11_MODE_11A; diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 0db549c59537..a03c8df59c18 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -1817,7 +1817,7 @@ lim_decide_sta_protection(struct mac_context *mac_ctx, static void __lim_process_channel_switch_timeout(struct pe_session *pe_session) { struct mac_context *mac; - uint8_t channel; /* This is received and stored from channelSwitch Action frame */ + uint32_t channel_freq; if (!pe_session) { pe_err("Invalid pe session"); @@ -1842,7 +1842,7 @@ static void __lim_process_channel_switch_timeout(struct pe_session *pe_session) return; } - channel = pe_session->gLimChannelSwitch.primaryChannel; + channel_freq = pe_session->gLimChannelSwitch.sw_target_freq; /* Restore Channel Switch parameters to default */ pe_session->gLimChannelSwitch.switchTimeoutValue = 0; @@ -1853,7 +1853,7 @@ static void __lim_process_channel_switch_timeout(struct pe_session *pe_session) * Else, just don't bother to switch. Indicate HDD to look for a * better AP to associate */ - if (!lim_is_channel_valid_for_channel_switch(mac, channel)) { + if (!lim_is_channel_valid_for_channel_switch(mac, channel_freq)) { /* We need to restore pre-channelSwitch state on the STA */ if (lim_restore_pre_channel_switch_state(mac, pe_session) != QDF_STATUS_SUCCESS) { @@ -1883,14 +1883,14 @@ static void __lim_process_channel_switch_timeout(struct pe_session *pe_session) pe_warn("CHANNEL_SWITCH_PRIMARY_ONLY"); lim_switch_primary_channel(mac, pe_session->gLimChannelSwitch. - primaryChannel, pe_session); + sw_target_freq, pe_session); pe_session->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE; break; case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY: pe_warn("CHANNEL_SWITCH_PRIMARY_AND_SECONDARY"); lim_switch_primary_secondary_channel(mac, pe_session, - pe_session->gLimChannelSwitch.primaryChannel, + pe_session->gLimChannelSwitch.sw_target_freq, pe_session->gLimChannelSwitch.ch_center_freq_seg0, pe_session->gLimChannelSwitch.ch_center_freq_seg1, pe_session->gLimChannelSwitch.ch_width); @@ -1985,6 +1985,9 @@ lim_update_channel_switch(struct mac_context *mac_ctx, ch_switch_params = &psession_entry->gLimChannelSwitch; ch_switch_params->primaryChannel = chnl_switch->newChannel; + ch_switch_params->sw_target_freq = + wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, + chnl_switch->newChannel); ch_switch_params->switchCount = chnl_switch->switchCount; ch_switch_params->switchTimeoutValue = SYS_MS_TO_TICKS(beacon_period) * (chnl_switch->switchCount); @@ -2039,12 +2042,13 @@ lim_update_channel_switch(struct mac_context *mac_ctx, if (QDF_STATUS_SUCCESS != lim_start_channel_switch(mac_ctx, psession_entry)) pe_warn("Could not start Channel Switch"); - pe_debug("session: %d primary chl: %d ch_width: %d count: %d (%d ticks)", - psession_entry->peSessionId, - psession_entry->gLimChannelSwitch.primaryChannel, - psession_entry->gLimChannelSwitch.ch_width, - psession_entry->gLimChannelSwitch.switchCount, - psession_entry->gLimChannelSwitch.switchTimeoutValue); + pe_debug("session: %d primary chl: %d freq %d ch_width: %d count: %d (%d ticks)", + psession_entry->peSessionId, + psession_entry->gLimChannelSwitch.primaryChannel, + psession_entry->gLimChannelSwitch.sw_target_freq, + psession_entry->gLimChannelSwitch.ch_width, + psession_entry->gLimChannelSwitch.switchCount, + psession_entry->gLimChannelSwitch.switchTimeoutValue); return; } @@ -2201,10 +2205,7 @@ void lim_switch_channel_cback(struct mac_context *mac, QDF_STATUS status, pSirSmeSwitchChInd->messageType = eWNI_SME_SWITCH_CHL_IND; pSirSmeSwitchChInd->length = sizeof(*pSirSmeSwitchChInd); - pSirSmeSwitchChInd->freq = - wlan_reg_chan_to_freq(mac->pdev, - pe_session-> - gLimChannelSwitch.primaryChannel); + pSirSmeSwitchChInd->freq = pe_session->gLimChannelSwitch.sw_target_freq; pSirSmeSwitchChInd->sessionId = pe_session->smeSessionId; pSirSmeSwitchChInd->chan_params.ch_width = pe_session->gLimChannelSwitch.ch_width; @@ -2240,27 +2241,15 @@ void lim_switch_channel_cback(struct mac_context *mac, QDF_STATUS status, lim_switch_channel_vdev_started(pe_session); } -/** - * lim_switch_primary_channel() - * - ***FUNCTION: - * This function changes the current operating channel - * and sets the new new channel ID in WNI_CFG_CURRENT_CHANNEL. - * - ***NOTE: - * @param mac Pointer to Global MAC structure - * @param new_channel new chnannel ID - * @return NONE - */ -void lim_switch_primary_channel(struct mac_context *mac, uint8_t new_channel, +void lim_switch_primary_channel(struct mac_context *mac, + uint32_t new_channel_freq, struct pe_session *pe_session) { pe_debug("old chnl freq: %d --> new chnl freq: %d", pe_session->curr_op_freq, - wlan_reg_chan_to_freq(mac->pdev, new_channel)); + new_channel_freq); - pe_session->curr_req_chan_freq = wlan_reg_chan_to_freq(mac->pdev, - new_channel); + pe_session->curr_req_chan_freq = new_channel_freq; pe_session->curr_op_freq = pe_session->curr_req_chan_freq; pe_session->ch_center_freq_seg0 = 0; pe_session->ch_center_freq_seg1 = 0; @@ -2276,49 +2265,27 @@ void lim_switch_primary_channel(struct mac_context *mac, uint8_t new_channel, return; } -/** - * lim_switch_primary_secondary_channel() - * - ***FUNCTION: - * This function changes the primary and secondary channel. - * If 11h is enabled and user provides a "new channel ID" - * that is different from the current operating channel, - * then we must set this new channel in WNI_CFG_CURRENT_CHANNEL, - * assign notify LIM of such change. - * - ***NOTE: - * @param mac Pointer to Global MAC structure - * @param new_channel New chnannel ID (or current channel ID) - * @param subband CB secondary info: - * - eANI_CB_SECONDARY_NONE - * - eANI_CB_SECONDARY_UP - * - eANI_CB_SECONDARY_DOWN - * @return NONE - */ void lim_switch_primary_secondary_channel(struct mac_context *mac, - struct pe_session *pe_session, - uint8_t new_channel, - uint8_t ch_center_freq_seg0, - uint8_t ch_center_freq_seg1, - enum phy_ch_width ch_width) + struct pe_session *pe_session, + uint32_t new_channel_freq, + uint8_t ch_center_freq_seg0, + uint8_t ch_center_freq_seg1, + enum phy_ch_width ch_width) { /* Assign the callback to resume TX once channel is changed. */ - pe_session->curr_req_chan_freq = wlan_reg_chan_to_freq(mac->pdev, - new_channel); + pe_session->curr_req_chan_freq = new_channel_freq; pe_session->limRFBand = lim_get_rf_band(pe_session->curr_req_chan_freq); pe_session->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; mac->lim.gpchangeChannelCallback = lim_switch_channel_cback; mac->lim.gpchangeChannelData = NULL; /* Store the new primary and secondary channel in session entries if different */ - if (wlan_reg_freq_to_chan(mac->pdev, pe_session->curr_op_freq) != - new_channel) { + if (pe_session->curr_op_freq != new_channel_freq) { pe_warn("switch old chnl freq: %d --> new chnl freq: %d", - pe_session->curr_op_freq, wlan_reg_chan_to_freq( - mac->pdev, new_channel)); - pe_session->curr_op_freq = wlan_reg_chan_to_freq( - mac->pdev, new_channel); + pe_session->curr_op_freq, + new_channel_freq); + pe_session->curr_op_freq = new_channel_freq; } if (pe_session->htSecondaryChannelOffset != pe_session->gLimChannelSwitch.sec_ch_offset) { @@ -3960,7 +3927,10 @@ void lim_update_sta_run_time_ht_switch_chnl_params(struct mac_context *mac, || pe_session->htRecommendedTxWidthSet != (uint8_t) pHTInfo->recommendedTxWidthSet) { pe_session->gLimChannelSwitch.primaryChannel = - pHTInfo->primaryChannel; + pHTInfo->primaryChannel; + pe_session->gLimChannelSwitch.sw_target_freq = + wlan_reg_legacy_chan_to_freq(mac->pdev, + pHTInfo->primaryChannel); pe_session->htSecondaryChannelOffset = (ePhyChanBondState) pHTInfo->secondaryChannelOffset; pe_session->htRecommendedTxWidthSet = @@ -4383,30 +4353,14 @@ void lim_add_channel_status_info(struct mac_context *p_mac, return; } -/** - * @function : lim_is_channel_valid_for_channel_switch() - * - * @brief : This function checks if the channel to which AP - * is expecting us to switch, is a valid channel for us. - * LOGIC: - * - * ASSUMPTIONS: - * NA - * - * NOTE: - * NA - * - * @param mac - Pointer to Global MAC structure - * @param channel - New channel to which we are expected to move - * @return None - */ -bool lim_is_channel_valid_for_channel_switch(struct mac_context *mac, uint8_t channel) +bool lim_is_channel_valid_for_channel_switch(struct mac_context *mac, + uint32_t channel_freq) { uint8_t index; bool ok = false; - if (policy_mgr_is_chan_ok_for_dnbs(mac->psoc, - wlan_chan_to_freq(channel), &ok)) { + if (policy_mgr_is_chan_ok_for_dnbs(mac->psoc, channel_freq, + &ok)) { pe_err("policy_mgr_is_chan_ok_for_dnbs() returned error"); return false; } @@ -4418,11 +4372,11 @@ bool lim_is_channel_valid_for_channel_switch(struct mac_context *mac, uint8_t ch for (index = 0; index < mac->mlme_cfg->reg.valid_channel_list_num; index++) { if (mac->mlme_cfg->reg.valid_channel_freq_list[index] != - wlan_reg_chan_to_freq(mac->pdev, channel)) + channel_freq) continue; ok = policy_mgr_is_valid_for_channel_switch( - mac->psoc, wlan_chan_to_freq(channel)); + mac->psoc, channel_freq); return ok; } @@ -7819,7 +7773,8 @@ void lim_process_ap_ecsa_timeout(void *data) { struct pe_session *session = (struct pe_session *)data; struct mac_context *mac_ctx; - uint8_t bcn_int, ch, ch_width; + uint8_t bcn_int, ch_width, offset; + uint32_t ch_freq; QDF_STATUS status; if (!session || !session->valid) { @@ -7852,12 +7807,21 @@ void lim_process_ap_ecsa_timeout(void *data) /* Send the next beacon with updated CSA IE count */ lim_send_dfs_chan_sw_ie_update(mac_ctx, session); - ch = session->gLimChannelSwitch.primaryChannel; + ch_freq = session->gLimChannelSwitch.sw_target_freq; ch_width = session->gLimChannelSwitch.ch_width; - if (mac_ctx->mlme_cfg->dfs_cfg.dfs_beacon_tx_enhanced) - /* Send Action frame after updating beacon */ - lim_send_chan_switch_action_frame(mac_ctx, ch, ch_width, - session); + offset = session->gLimChannelSwitch.sec_ch_offset; + if (mac_ctx->mlme_cfg->dfs_cfg.dfs_beacon_tx_enhanced) { + if (WLAN_REG_IS_6GHZ_CHAN_FREQ(ch_freq)) { + send_extended_chan_switch_action_frame + (mac_ctx, ch_freq, ch_width, + offset, session); + } else { + /* Send Action frame after updating beacon */ + lim_send_chan_switch_action_frame + (mac_ctx, ch_freq, ch_width, + offset, session); + } + } /* Restart the timer */ if (session->beaconParams.beaconInterval) diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index d1953a9adb77..46e6f685da76 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -331,13 +331,45 @@ QDF_STATUS lim_start_channel_switch(struct mac_context *mac, void lim_update_channel_switch(struct mac_context *, tpSirProbeRespBeacon, struct pe_session *pe_session); -void lim_switch_primary_channel(struct mac_context *, uint8_t, struct pe_session *); +/** + * lim_switch_primary_channel() - switch primary channel of session + * @mac: Global MAC structure + * @new_channel_freq: new chnannel freq in Mhz + * @pe_session: pe session context + * + * This function changes the current operating channel frequency. + * + * return NONE + */ +void lim_switch_primary_channel(struct mac_context *mac, + uint32_t new_channel_freq, + struct pe_session *pe_session); + +/** + * lim_switch_primary_secondary_channel() - switch primary and secondary + * channel of session + * @mac: Global MAC structure + * @pe_session: session context + * @new_channel_freq: new channel frequency (MHz) + * @ch_center_freq_seg0: channel center freq seg0 + * @ch_center_freq_seg1: channel center freq seg1 + * @ch_width: ch width of enum phy_ch_width + * + * This function changes the primary and secondary channel. + * If 11h is enabled and user provides a "new channel freq" + * that is different from the current operating channel, + * then we must set this new channel in session context and + * assign notify LIM of such change. + * + * @return NONE + */ void lim_switch_primary_secondary_channel(struct mac_context *mac, - struct pe_session *pe_session, - uint8_t newChannel, - uint8_t ch_center_freq_seg0, - uint8_t ch_center_freq_seg1, - enum phy_ch_width ch_width); + struct pe_session *pe_session, + uint32_t new_channel_freq, + uint8_t ch_center_freq_seg0, + uint8_t ch_center_freq_seg1, + enum phy_ch_width ch_width); + void lim_update_sta_run_time_ht_capability(struct mac_context *mac, tDot11fIEHTCaps *pHTCaps); void lim_update_sta_run_time_ht_info(struct mac_context *mac, @@ -345,8 +377,20 @@ void lim_update_sta_run_time_ht_info(struct mac_context *mac, struct pe_session *pe_session); void lim_cancel_dot11h_channel_switch(struct mac_context *mac, struct pe_session *pe_session); + +/** + * lim_is_channel_valid_for_channel_switch - check channel valid for switching + * @mac: Global mac context + * @channel_freq: channel freq (MHz) + * + * This function checks if the channel to which AP is expecting us to switch, + * is a valid channel for us. + * + * Return bool, true if channel is valid + */ bool lim_is_channel_valid_for_channel_switch(struct mac_context *mac, - uint8_t channel); + uint32_t channel_freq); + QDF_STATUS lim_restore_pre_channel_switch_state(struct mac_context *mac, struct pe_session *pe_session); @@ -590,6 +634,26 @@ struct pe_session *lim_is_ibss_session_active(struct mac_context *mac) } #endif +static inline uint8_t ch_width_in_mhz(enum phy_ch_width ch_width) +{ + switch (ch_width) { + case CH_WIDTH_40MHZ: + return 40; + case CH_WIDTH_80MHZ: + return 80; + case CH_WIDTH_160MHZ: + return 160; + case CH_WIDTH_80P80MHZ: + return 160; + case CH_WIDTH_5MHZ: + return 5; + case CH_WIDTH_10MHZ: + return 10; + default: + return 20; + } +} + struct pe_session *lim_is_ap_session_active(struct mac_context *mac); void lim_handle_heart_beat_failure_timeout(struct mac_context *mac); @@ -1556,17 +1620,39 @@ void lim_send_start_bss_confirm(struct mac_context *mac_ctx, * sta capability. * * @mac_ctx: pointer to global mac structure - * @new_channel: new channel to switch to. - * @ch_bandwidth: BW of channel to calculate op_class + * @new_channel_freq: new channel freq(Mhz) to switch to. + * @ch_bandwidth: ch bw of enum phy_ch_width + * @offset: BW of type enum offset_t * @session_entry: pe session * * Return: void */ void lim_send_chan_switch_action_frame(struct mac_context *mac_ctx, - uint16_t new_channel, - uint8_t ch_bandwidth, + uint16_t new_channel_freq, + enum phy_ch_width ch_bandwidth, + enum offset_t offset, struct pe_session *session_entry); +/** + * send_extended_chan_switch_action_frame()- function to send ECSA + * action frame for each sta connected to SAP/GO and AP in case of + * STA . + * @mac_ctx: pointer to global mac structure + * @new_channel_freq: new channel to switch to. + * @ch_bandwidth: channel bw of type enum phy_ch_width + * @offset: BW of enum offset_t + * @session_entry: pe session + * + * This function is called to send ECSA frame for STA/CLI and SAP/GO. + * + * Return: void + */ +void send_extended_chan_switch_action_frame(struct mac_context *mac_ctx, + uint16_t new_channel_freq, + enum phy_ch_width ch_bandwidth, + enum offset_t offset, + struct pe_session *session_entry); + /** * lim_process_obss_detection_ind() - Process obss detection indication * @mac_ctx: Pointer to Global MAC structure. diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c index 87a1c304d0c7..26973321596d 100644 --- a/core/mac/src/pe/sch/sch_beacon_gen.c +++ b/core/mac/src/pe/sch/sch_beacon_gen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -245,6 +245,7 @@ sch_set_fixed_beacon_fields(struct mac_context *mac_ctx, struct pe_session *sess uint8_t *addn_ie = NULL; tDot11fIEExtCap extracted_extcap; bool extcap_present = true, addnie_present = false; + bool is_6ghz_chsw; bcn_1 = qdf_mem_malloc(sizeof(tDot11fBeacon1)); if (!bcn_1) @@ -344,11 +345,14 @@ sch_set_fixed_beacon_fields(struct mac_context *mac_ctx, struct pe_session *sess session->schBeaconOffsetBegin); /* Initialize the 'new' fields at the end of the beacon */ - - if ((session->limSystemRole == eLIM_AP_ROLE) && + is_6ghz_chsw = + WLAN_REG_IS_6GHZ_CHAN_FREQ(session->curr_op_freq) || + WLAN_REG_IS_6GHZ_CHAN_FREQ + (session->gLimChannelSwitch.sw_target_freq); + if (session->limSystemRole == eLIM_AP_ROLE && session->dfsIncludeChanSwIe == true) { if (!CHAN_HOP_ALL_BANDS_ENABLE || - session->lim_non_ecsa_cap_num == 0) { + session->lim_non_ecsa_cap_num == 0 || is_6ghz_chsw) { tDot11fIEext_chan_switch_ann *ext_csa = &bcn_2->ext_chan_switch_ann; populate_dot_11_f_ext_chann_switch_ann(mac_ctx, @@ -390,12 +394,15 @@ sch_set_fixed_beacon_fields(struct mac_context *mac_ctx, struct pe_session *sess * and SAP has instructed to announce channel switch IEs * in beacon and probe responses */ - populate_dot11f_chan_switch_ann(mac_ctx, - &bcn_2->ChanSwitchAnn, session); - pe_debug("csa: mode:%d chan:%d count:%d", - bcn_2->ChanSwitchAnn.switchMode, - bcn_2->ChanSwitchAnn.newChannel, - bcn_2->ChanSwitchAnn.switchCount); + if (!is_6ghz_chsw) { + populate_dot11f_chan_switch_ann + (mac_ctx, &bcn_2->ChanSwitchAnn, + session); + pe_debug("csa: mode:%d chan:%d count:%d", + bcn_2->ChanSwitchAnn.switchMode, + bcn_2->ChanSwitchAnn.newChannel, + bcn_2->ChanSwitchAnn.switchCount); + } /* * TODO: depending the CB mode, extended channel switch * announcement need to be called diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index 00cb4820c321..21d75089ded7 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -180,29 +180,47 @@ void populate_dot_11_f_ext_chann_switch_ann(struct mac_context *mac_ptr, struct pe_session *session_entry) { uint8_t ch_offset; + uint8_t op_class = 0; + uint8_t chan_num = 0; + uint32_t sw_target_freq; + uint8_t primary_channel; + enum phy_ch_width ch_width; - if (session_entry->gLimChannelSwitch.ch_width == CH_WIDTH_80MHZ) + ch_width = session_entry->gLimChannelSwitch.ch_width; + if (ch_width == CH_WIDTH_80MHZ) ch_offset = BW80; else ch_offset = session_entry->gLimChannelSwitch.sec_ch_offset; dot_11_ptr->switch_mode = session_entry->gLimChannelSwitch.switchMode; - dot_11_ptr->new_reg_class = wlan_reg_dmn_get_opclass_from_channel( - mac_ptr->scan.countryCodeCurrent, - session_entry->gLimChannelSwitch.primaryChannel, - ch_offset); + sw_target_freq = session_entry->gLimChannelSwitch.sw_target_freq; + primary_channel = session_entry->gLimChannelSwitch.primaryChannel; + if (WLAN_REG_IS_6GHZ_CHAN_FREQ(sw_target_freq)) { + wlan_reg_freq_width_to_chan_op_class + (mac_ptr->pdev, sw_target_freq, + ch_width_in_mhz(ch_width), + true, BIT(BEHAV_NONE), &op_class, &chan_num); + dot_11_ptr->new_reg_class = op_class; + } else { + dot_11_ptr->new_reg_class = + wlan_reg_dmn_get_opclass_from_channel + (mac_ptr->scan.countryCodeCurrent, + primary_channel, ch_offset); + } + dot_11_ptr->new_channel = session_entry->gLimChannelSwitch.primaryChannel; dot_11_ptr->switch_count = session_entry->gLimChannelSwitch.switchCount; dot_11_ptr->present = 1; - pe_debug("country:%s chan:%d width:%d reg:%d off:%d", - mac_ptr->scan.countryCodeCurrent, - session_entry->gLimChannelSwitch.primaryChannel, - session_entry->gLimChannelSwitch.ch_width, - dot_11_ptr->new_reg_class, - session_entry->gLimChannelSwitch.sec_ch_offset); + pe_debug("country:%s chan:%d freq %d width:%d reg:%d off:%d", + mac_ptr->scan.countryCodeCurrent, + session_entry->gLimChannelSwitch.primaryChannel, + sw_target_freq, + session_entry->gLimChannelSwitch.ch_width, + dot_11_ptr->new_reg_class, + session_entry->gLimChannelSwitch.sec_ch_offset); } void diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 6e266e9bb245..9a8d3d2cdae4 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -5730,7 +5730,7 @@ sme_update_roam_scan_home_away_time(mac_handle_t mac_handle, uint8_t vdev_id, * sme_ext_change_channel()- function to post send ECSA * action frame to csr. * @mac_handle: Opaque handle to the global MAC context - * @channel: new channel to switch + * @channel freq: new channel freq to switch * @session_id: senssion it should be sent on. * * This function is called to post ECSA frame to csr. diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 305c61aff5d8..24e9730cdec5 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1156,6 +1156,9 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len) csa_ie = (struct ieee80211_channelswitch_ie *) (&csa_event->csa_ie[0]); csa_offload_event->channel = csa_ie->newchannel; + csa_offload_event->csa_chan_freq = + wlan_reg_legacy_chan_to_freq(wma->pdev, + csa_ie->newchannel); csa_offload_event->switch_mode = csa_ie->switchmode; } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) { xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *) @@ -1163,6 +1166,16 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len) csa_offload_event->channel = xcsa_ie->newchannel; csa_offload_event->switch_mode = xcsa_ie->switchmode; csa_offload_event->new_op_class = xcsa_ie->newClass; + if (wlan_reg_is_6ghz_op_class(wma->pdev, xcsa_ie->newClass)) { + csa_offload_event->csa_chan_freq = + wlan_reg_chan_band_to_freq + (wma->pdev, xcsa_ie->newchannel, + BIT(REG_BAND_6G)); + } else { + csa_offload_event->csa_chan_freq = + wlan_reg_legacy_chan_to_freq + (wma->pdev, xcsa_ie->newchannel); + } } else { WMA_LOGE("CSA Event error: No CSA IE present"); qdf_mem_free(csa_offload_event); @@ -1193,8 +1206,9 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len) csa_offload_event->ies_present_flag = csa_event->ies_present_flag; - WMA_LOGD("CSA: New Channel = %d BSSID:%pM", - csa_offload_event->channel, csa_offload_event->bssId); + WMA_LOGD("CSA: New Channel = %d freq %d BSSID:%pM", + csa_offload_event->channel, csa_offload_event->csa_chan_freq, + csa_offload_event->bssId); WMA_LOGD("CSA: IEs Present Flag = 0x%x new ch width = %d ch center freq1 = %d ch center freq2 = %d new op class = %d", csa_event->ies_present_flag, csa_offload_event->new_ch_width,