qcacld-3.0: Fix client disconnect from SAP in 2.4 GHz
After SAP moved to 2.4 GHz HT 40 because of Radar detected in 5 GHz, the REF STA send SA Query to SAP. But the REF STA disabled HT 40 in 2.4 GHz(channelBondingMode24GHz=0), the REF STA switched to HT 20. The SA query OCI included op class 81 (20 MHz) from REF STA, the SAP check OCI failure (SAP op class 84, 40 MHz) by lim_check_oci_match and send deauth to REF STA. lim_check_oci_match only check the op_class equal or not with received OCI. If not equal, it will return false. According OCI doc, local transmit BW is not allowed greater than BW in OCI received from peer. Fix it by checking BW of local and peer instead of op class only. Change-Id: I62a477f8edabae31d07d6ec8ebb78ca76ca78792 CRs-Fixed: 3268105
This commit is contained in:

committed by
Madan Koyyalamudi

parent
bd995b86b7
commit
dac2e7867e
@@ -1214,6 +1214,9 @@ lim_check_oci_match(struct mac_context *mac, struct pe_session *pe_session,
|
||||
{
|
||||
const uint8_t *oci_ie;
|
||||
tDot11fIEoci self_oci, *peer_oci;
|
||||
uint16_t peer_chan_width;
|
||||
uint16_t local_peer_chan_width = 0;
|
||||
uint8_t country_code[CDS_COUNTRY_CODE_LEN + 1];
|
||||
|
||||
if (!lim_is_self_and_peer_ocv_capable(mac, peer, pe_session))
|
||||
return true;
|
||||
@@ -1233,18 +1236,29 @@ lim_check_oci_match(struct mac_context *mac, struct pe_session *pe_session,
|
||||
* Freq_seg_1_ch_num : 1 byte
|
||||
*/
|
||||
peer_oci = (tDot11fIEoci *)&oci_ie[2];
|
||||
lim_fill_oci_params(mac, pe_session, &self_oci);
|
||||
|
||||
if ((self_oci.op_class != peer_oci->op_class) ||
|
||||
wlan_reg_read_current_country(mac->psoc, country_code);
|
||||
peer_chan_width =
|
||||
wlan_reg_dmn_get_chanwidth_from_opclass_auto(
|
||||
country_code,
|
||||
peer_oci->prim_ch_num,
|
||||
peer_oci->op_class);
|
||||
|
||||
lim_fill_oci_params(mac, pe_session, &self_oci, peer,
|
||||
&local_peer_chan_width);
|
||||
if (((self_oci.op_class != peer_oci->op_class) &&
|
||||
(local_peer_chan_width > peer_chan_width)) ||
|
||||
(self_oci.prim_ch_num != peer_oci->prim_ch_num) ||
|
||||
(self_oci.freq_seg_1_ch_num != peer_oci->freq_seg_1_ch_num)) {
|
||||
pe_err("OCI mismatch,self %d %d %d, peer %d %d %d",
|
||||
pe_err("OCI mismatch,self %d %d %d %d, peer %d %d %d %d",
|
||||
self_oci.op_class,
|
||||
self_oci.prim_ch_num,
|
||||
self_oci.freq_seg_1_ch_num,
|
||||
local_peer_chan_width,
|
||||
peer_oci->op_class,
|
||||
peer_oci->prim_ch_num,
|
||||
peer_oci->freq_seg_1_ch_num);
|
||||
peer_oci->freq_seg_1_ch_num,
|
||||
peer_chan_width);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -5621,8 +5621,10 @@ lim_is_self_and_peer_ocv_capable(struct mac_context *mac,
|
||||
|
||||
void
|
||||
lim_fill_oci_params(struct mac_context *mac, struct pe_session *session,
|
||||
tDot11fIEoci *oci)
|
||||
tDot11fIEoci *oci, uint8_t *peer, uint16_t *tx_chan_width)
|
||||
{
|
||||
tpDphHashNode sta_ds;
|
||||
uint16_t aid;
|
||||
uint8_t ch_offset;
|
||||
uint8_t prim_ch_num = wlan_reg_freq_to_chan(mac->pdev,
|
||||
session->curr_op_freq);
|
||||
@@ -5648,6 +5650,30 @@ lim_fill_oci_params(struct mac_context *mac, struct pe_session *session,
|
||||
oci->prim_ch_num = prim_ch_num;
|
||||
oci->freq_seg_1_ch_num = session->ch_center_freq_seg1;
|
||||
oci->present = 1;
|
||||
if (tx_chan_width)
|
||||
*tx_chan_width = ch_width_in_mhz(session->ch_width);
|
||||
if (LIM_IS_STA_ROLE(session))
|
||||
return;
|
||||
|
||||
if (!peer || !tx_chan_width)
|
||||
return;
|
||||
|
||||
sta_ds = dph_lookup_hash_entry(mac, peer, &aid,
|
||||
&session->dph.dphHashTable);
|
||||
if (!sta_ds) {
|
||||
pe_nofl_debug("no find sta ds "QDF_MAC_ADDR_FMT,
|
||||
QDF_MAC_ADDR_REF(peer));
|
||||
return;
|
||||
}
|
||||
if (WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq)) {
|
||||
if (*tx_chan_width > 20 &&
|
||||
!sta_ds->htSupportedChannelWidthSet) {
|
||||
*tx_chan_width = 20;
|
||||
pe_nofl_debug("peer no support ht40 in 2g, %d :"QDF_MAC_ADDR_FMT,
|
||||
sta_ds->ch_width,
|
||||
QDF_MAC_ADDR_REF(peer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5693,7 +5719,7 @@ QDF_STATUS lim_send_sa_query_request_frame(struct mac_context *mac, uint8_t *tra
|
||||
qdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2);
|
||||
|
||||
if (lim_is_self_and_peer_ocv_capable(mac, peer, pe_session))
|
||||
lim_fill_oci_params(mac, pe_session, &frm.oci);
|
||||
lim_fill_oci_params(mac, pe_session, &frm.oci, NULL, NULL);
|
||||
|
||||
nStatus = dot11f_get_packed_sa_query_req_size(mac, &frm, &nPayload);
|
||||
if (DOT11F_FAILED(nStatus)) {
|
||||
@@ -5825,7 +5851,7 @@ QDF_STATUS lim_send_sa_query_response_frame(struct mac_context *mac,
|
||||
SA query request transId */
|
||||
qdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2);
|
||||
if (lim_is_self_and_peer_ocv_capable(mac, peer, pe_session))
|
||||
lim_fill_oci_params(mac, pe_session, &frm.oci);
|
||||
lim_fill_oci_params(mac, pe_session, &frm.oci, NULL, NULL);
|
||||
|
||||
nStatus = dot11f_get_packed_sa_query_rsp_size(mac, &frm, &nPayload);
|
||||
if (DOT11F_FAILED(nStatus)) {
|
||||
|
@@ -2907,12 +2907,14 @@ lim_is_self_and_peer_ocv_capable(struct mac_context *mac,
|
||||
* @mac: pointer to mac data
|
||||
* @session: pointer to pe session
|
||||
.* @oci: pointer of tDot11fIEoci
|
||||
* @peer: peer mac address
|
||||
* @tx_chan_width: tx channel width in MHz
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void
|
||||
lim_fill_oci_params(struct mac_context *mac, struct pe_session *session,
|
||||
tDot11fIEoci *oci);
|
||||
tDot11fIEoci *oci, uint8_t *peer, uint16_t *tx_chan_width);
|
||||
|
||||
#ifdef WLAN_FEATURE_SAE
|
||||
/**
|
||||
|
Reference in New Issue
Block a user