qcacld-3.0: Fix CSA process wide BW IE bandwidth issue
During channel switch for station mode, firmware reports CSA offload event to host driver, if the beacon IE includes wide band width IE, driver will process it and then set phy mode into firmware. Because function lim_process_csa_wbw_ie try to verify the segments and channel bandwidth in wrong way, it will lead to device use bandwidth which is mismatched with AP after channel switch. So data transaction gets failure. Fix this issue to verify channel bandwidth by correct algorithm. Change-Id: Ie26c3a887418dc61c0e8de041a9094aa82215098 CRs-Fixed: 2782049
This commit is contained in:
@@ -1425,94 +1425,132 @@ static QDF_STATUS lim_process_csa_wbw_ie(struct mac_context *mac_ctx,
|
||||
{
|
||||
struct ch_params ch_params = {0};
|
||||
uint8_t ap_new_ch_width;
|
||||
bool new_ch_width_dfn = false;
|
||||
uint8_t center_freq_diff;
|
||||
uint32_t fw_vht_ch_wd = wma_get_vht_ch_width() + 1;
|
||||
uint32_t cent_freq1, cent_freq2;
|
||||
uint32_t csa_cent_freq, csa_cent_freq1 = 0, csa_cent_freq2 = 0;
|
||||
|
||||
ap_new_ch_width = csa_params->new_ch_width + 1;
|
||||
|
||||
if ((ap_new_ch_width != CH_WIDTH_80MHZ) &&
|
||||
(ap_new_ch_width != CH_WIDTH_160MHZ) &&
|
||||
(ap_new_ch_width != CH_WIDTH_80P80MHZ)) {
|
||||
pe_err("CSA wide BW IE has wrong ch_width %d",
|
||||
csa_params->new_ch_width);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (!csa_params->new_ch_freq_seg1 && !csa_params->new_ch_freq_seg2) {
|
||||
pe_err("CSA wide BW IE has invalid center freq");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
if ((ap_new_ch_width == CH_WIDTH_80MHZ) &&
|
||||
csa_params->new_ch_freq_seg2) {
|
||||
new_ch_width_dfn = true;
|
||||
if (csa_params->new_ch_freq_seg2 >
|
||||
csa_params->new_ch_freq_seg1)
|
||||
center_freq_diff = csa_params->new_ch_freq_seg2 -
|
||||
csa_params->new_ch_freq_seg1;
|
||||
else
|
||||
center_freq_diff = csa_params->new_ch_freq_seg1 -
|
||||
csa_params->new_ch_freq_seg2;
|
||||
if (center_freq_diff == CENTER_FREQ_DIFF_160MHz)
|
||||
ap_new_ch_width = CH_WIDTH_160MHZ;
|
||||
else if (center_freq_diff > CENTER_FREQ_DIFF_80P80MHz)
|
||||
ap_new_ch_width = CH_WIDTH_80P80MHZ;
|
||||
else
|
||||
ap_new_ch_width = CH_WIDTH_80MHZ;
|
||||
|
||||
csa_cent_freq = csa_params->csa_chan_freq;
|
||||
if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev,
|
||||
csa_params->new_op_class)) {
|
||||
cent_freq1 = wlan_reg_chan_opclass_to_freq(
|
||||
csa_params->new_ch_freq_seg1,
|
||||
csa_params->new_op_class, false);
|
||||
cent_freq2 = wlan_reg_chan_opclass_to_freq(
|
||||
csa_params->new_ch_freq_seg2,
|
||||
csa_params->new_op_class, false);
|
||||
} else {
|
||||
cent_freq1 = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev,
|
||||
csa_params->new_ch_freq_seg1);
|
||||
cent_freq2 = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev,
|
||||
csa_params->new_ch_freq_seg2);
|
||||
}
|
||||
session_entry->gLimChannelSwitch.state =
|
||||
eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
|
||||
if ((ap_new_ch_width == CH_WIDTH_160MHZ) &&
|
||||
!new_ch_width_dfn) {
|
||||
if (abs(csa_params->new_ch_freq_seg1 - csa_params->channel) !=
|
||||
CH_TO_CNTR_FREQ_DIFF_160MHz) {
|
||||
pe_err("CSA wide BW IE has invalid center freq");
|
||||
|
||||
switch (ap_new_ch_width) {
|
||||
case CH_WIDTH_80MHZ:
|
||||
csa_cent_freq1 = cent_freq1;
|
||||
if (csa_params->new_ch_freq_seg2) {
|
||||
center_freq_diff = abs(csa_params->new_ch_freq_seg2 -
|
||||
csa_params->new_ch_freq_seg1);
|
||||
if (center_freq_diff == CENTER_FREQ_DIFF_160MHz) {
|
||||
ap_new_ch_width = CH_WIDTH_160MHZ;
|
||||
csa_cent_freq1 = cent_freq2;
|
||||
csa_params->new_ch_freq_seg1 =
|
||||
csa_params->new_ch_freq_seg2;
|
||||
csa_params->new_ch_freq_seg2 = 0;
|
||||
} else if (center_freq_diff > CENTER_FREQ_DIFF_160MHz) {
|
||||
ap_new_ch_width = CH_WIDTH_80P80MHZ;
|
||||
csa_cent_freq2 = cent_freq2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CH_WIDTH_80P80MHZ:
|
||||
csa_cent_freq1 = cent_freq1;
|
||||
csa_cent_freq2 = cent_freq2;
|
||||
break;
|
||||
case CH_WIDTH_160MHZ:
|
||||
csa_cent_freq1 = cent_freq1;
|
||||
break;
|
||||
default:
|
||||
pe_err("CSA wide BW IE has wrong ch_width %d", ap_new_ch_width);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
/* Verify whether the bandwidth and channel segments are valid. */
|
||||
switch (ap_new_ch_width) {
|
||||
case CH_WIDTH_80MHZ:
|
||||
if (abs(csa_cent_freq1 - csa_cent_freq) != 10 &&
|
||||
abs(csa_cent_freq1 - csa_cent_freq) != 30) {
|
||||
pe_err("CSA WBW 80MHz has invalid seg0 freq %d",
|
||||
csa_cent_freq1);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (ap_new_ch_width > fw_vht_ch_wd) {
|
||||
pe_debug("New BW is not supported, setting BW to %d",
|
||||
fw_vht_ch_wd);
|
||||
ap_new_ch_width = fw_vht_ch_wd;
|
||||
if (csa_cent_freq2) {
|
||||
pe_err("CSA WBW 80MHz has invalid seg1 freq %d",
|
||||
csa_cent_freq2);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
ch_params.ch_width = ap_new_ch_width ;
|
||||
break;
|
||||
case CH_WIDTH_80P80MHZ:
|
||||
if (abs(csa_cent_freq1 - csa_cent_freq) != 10 &&
|
||||
abs(csa_cent_freq1 - csa_cent_freq) != 30) {
|
||||
pe_err("CSA WBW 80MHz has invalid seg0 freq %d",
|
||||
csa_cent_freq1);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
if (!csa_cent_freq2) {
|
||||
pe_err("CSA WBW 80MHz has invalid seg1 freq %d",
|
||||
csa_cent_freq2);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
/* adjacent is not allowed -- that's a 160 MHz channel */
|
||||
if (abs(csa_cent_freq1 - csa_cent_freq2) == 80) {
|
||||
pe_err("CSA WBW wrong bandwidth");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
break;
|
||||
case CH_WIDTH_160MHZ:
|
||||
if (abs(csa_cent_freq1 - csa_cent_freq) != 70 &&
|
||||
abs(csa_cent_freq1 - csa_cent_freq) != 50 &&
|
||||
abs(csa_cent_freq1 - csa_cent_freq) != 30 &&
|
||||
abs(csa_cent_freq1 - csa_cent_freq) != 10) {
|
||||
pr_err("CSA WBW 160MHz has invalid seg0 freq %d",
|
||||
csa_cent_freq1);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
if (csa_cent_freq2) {
|
||||
pe_err("CSA WBW 80MHz has invalid seg1 freq %d",
|
||||
csa_cent_freq2);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pe_err("CSA wide BW IE has wrong ch_width %d", ap_new_ch_width);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (ap_new_ch_width > fw_vht_ch_wd) {
|
||||
pe_debug("New BW is not supported, setting BW to %d",
|
||||
fw_vht_ch_wd);
|
||||
ap_new_ch_width = fw_vht_ch_wd;
|
||||
ch_params.ch_width = ap_new_ch_width;
|
||||
wlan_reg_set_channel_params(mac_ctx->pdev,
|
||||
csa_params->channel, 0, &ch_params);
|
||||
ap_new_ch_width = ch_params.ch_width;
|
||||
csa_params->new_ch_freq_seg1 = ch_params.center_freq_seg0;
|
||||
csa_params->new_ch_freq_seg2 = ch_params.center_freq_seg1;
|
||||
} else if (!new_ch_width_dfn) {
|
||||
if (ap_new_ch_width > fw_vht_ch_wd) {
|
||||
pe_debug("New BW is not supported, setting BW to %d",
|
||||
fw_vht_ch_wd);
|
||||
ap_new_ch_width = fw_vht_ch_wd;
|
||||
}
|
||||
if (abs(csa_params->new_ch_freq_seg1 - csa_params->channel) !=
|
||||
CH_TO_CNTR_FREQ_DIFF_80MHz) {
|
||||
pe_err("CSA wide BW IE has invalid center freq");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
csa_params->new_ch_freq_seg2 = 0;
|
||||
}
|
||||
if (new_ch_width_dfn) {
|
||||
if (abs(csa_params->new_ch_freq_seg1 - csa_params->channel) !=
|
||||
CH_TO_CNTR_FREQ_DIFF_80MHz) {
|
||||
pe_err("CSA wide BW IE has invalid center freq");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
if (ap_new_ch_width > fw_vht_ch_wd) {
|
||||
pe_debug("New width is not supported, setting BW to %d",
|
||||
fw_vht_ch_wd);
|
||||
ap_new_ch_width = fw_vht_ch_wd;
|
||||
}
|
||||
if ((ap_new_ch_width == CH_WIDTH_160MHZ) &&
|
||||
(abs(csa_params->new_ch_freq_seg1 - csa_params->channel) !=
|
||||
CH_TO_CNTR_FREQ_DIFF_160MHz)) {
|
||||
pe_err("wide BW IE has invalid 160M center freq");
|
||||
csa_params->new_ch_freq_seg2 = 0;
|
||||
ap_new_ch_width = CH_WIDTH_80MHZ;
|
||||
}
|
||||
}
|
||||
|
||||
session_entry->gLimChannelSwitch.state =
|
||||
eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
|
||||
|
||||
chnl_switch_info->newChanWidth = ap_new_ch_width;
|
||||
chnl_switch_info->newCenterChanFreq0 = csa_params->new_ch_freq_seg1;
|
||||
chnl_switch_info->newCenterChanFreq1 = csa_params->new_ch_freq_seg2;
|
||||
@@ -1658,13 +1696,12 @@ void lim_handle_csa_offload_msg(struct mac_context *mac_ctx,
|
||||
lim_ch_switch->sec_ch_offset =
|
||||
PHY_SINGLE_CHANNEL_CENTERED;
|
||||
if (chnl_switch_info->newChanWidth) {
|
||||
if (csa_params->channel <
|
||||
csa_params->new_ch_freq_seg1)
|
||||
lim_ch_switch->sec_ch_offset =
|
||||
PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
|
||||
else
|
||||
lim_ch_switch->sec_ch_offset =
|
||||
PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
|
||||
ch_params.ch_width =
|
||||
chnl_switch_info->newChanWidth;
|
||||
wlan_reg_set_channel_params(mac_ctx->pdev,
|
||||
csa_params->channel, 0, &ch_params);
|
||||
lim_ch_switch->sec_ch_offset =
|
||||
ch_params.sec_ch_offset;
|
||||
session_entry->htSupportedChannelWidthSet =
|
||||
true;
|
||||
}
|
||||
|
مرجع در شماره جدید
Block a user