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:
Liangwei Dong
2022-08-16 18:48:04 +08:00
committed by Madan Koyyalamudi
parent bd995b86b7
commit dac2e7867e
3 changed files with 50 additions and 8 deletions

View File

@@ -1214,6 +1214,9 @@ lim_check_oci_match(struct mac_context *mac, struct pe_session *pe_session,
{ {
const uint8_t *oci_ie; const uint8_t *oci_ie;
tDot11fIEoci self_oci, *peer_oci; 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)) if (!lim_is_self_and_peer_ocv_capable(mac, peer, pe_session))
return true; 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 * Freq_seg_1_ch_num : 1 byte
*/ */
peer_oci = (tDot11fIEoci *)&oci_ie[2]; 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.prim_ch_num != peer_oci->prim_ch_num) ||
(self_oci.freq_seg_1_ch_num != peer_oci->freq_seg_1_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.op_class,
self_oci.prim_ch_num, self_oci.prim_ch_num,
self_oci.freq_seg_1_ch_num, self_oci.freq_seg_1_ch_num,
local_peer_chan_width,
peer_oci->op_class, peer_oci->op_class,
peer_oci->prim_ch_num, peer_oci->prim_ch_num,
peer_oci->freq_seg_1_ch_num); peer_oci->freq_seg_1_ch_num,
peer_chan_width);
return false; return false;
} }

View File

@@ -5621,8 +5621,10 @@ lim_is_self_and_peer_ocv_capable(struct mac_context *mac,
void void
lim_fill_oci_params(struct mac_context *mac, struct pe_session *session, 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 ch_offset;
uint8_t prim_ch_num = wlan_reg_freq_to_chan(mac->pdev, uint8_t prim_ch_num = wlan_reg_freq_to_chan(mac->pdev,
session->curr_op_freq); 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->prim_ch_num = prim_ch_num;
oci->freq_seg_1_ch_num = session->ch_center_freq_seg1; oci->freq_seg_1_ch_num = session->ch_center_freq_seg1;
oci->present = 1; 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); qdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2);
if (lim_is_self_and_peer_ocv_capable(mac, peer, pe_session)) 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); nStatus = dot11f_get_packed_sa_query_req_size(mac, &frm, &nPayload);
if (DOT11F_FAILED(nStatus)) { if (DOT11F_FAILED(nStatus)) {
@@ -5825,7 +5851,7 @@ QDF_STATUS lim_send_sa_query_response_frame(struct mac_context *mac,
SA query request transId */ SA query request transId */
qdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2); qdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2);
if (lim_is_self_and_peer_ocv_capable(mac, peer, pe_session)) 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); nStatus = dot11f_get_packed_sa_query_rsp_size(mac, &frm, &nPayload);
if (DOT11F_FAILED(nStatus)) { if (DOT11F_FAILED(nStatus)) {

View File

@@ -2907,12 +2907,14 @@ lim_is_self_and_peer_ocv_capable(struct mac_context *mac,
* @mac: pointer to mac data * @mac: pointer to mac data
* @session: pointer to pe session * @session: pointer to pe session
.* @oci: pointer of tDot11fIEoci .* @oci: pointer of tDot11fIEoci
* @peer: peer mac address
* @tx_chan_width: tx channel width in MHz
* *
* Return: void * Return: void
*/ */
void void
lim_fill_oci_params(struct mac_context *mac, struct pe_session *session, 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 #ifdef WLAN_FEATURE_SAE
/** /**