From bbe23a736cf9f795958884240fdb4bdaf6dcc9c3 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Wed, 12 Dec 2018 10:52:32 +0530 Subject: [PATCH] qcacld-3.0: Fix channel width update sent during channel switch During channel switch if the new channel's phymode is different than the old channel the host will update its phymode and send vdev restart to firmware. Once vdev restart resp is received, host sends new phymode and channel width to the firmware. If host process beacon with opmode IE while waiting for vdev restart response, it check if new channel width in bcn is valid for new phymode and send channel width to firmware. If channel width changed is greater than allowed value for older phymode, firmware is not able to handle it. Fix is to ignore any opmode IE during channel switch. Also ignore the beacons with CSA/ECSA IE if channel switch detection is offloaded. The opmode or any other change in beacon will be detected with the beacons on new channel once AP moves to new channel. Change-Id: If3bfb555dfa7b63dc997bbdf2fe6a0836bcf17fd CRs-Fixed: 2361553 --- .../mac/src/pe/lim/lim_process_action_frame.c | 9 +++++++++ core/mac/src/pe/sch/sch_beacon_process.c | 19 +++++++++++++++++++ core/wma/src/wma_mgmt.c | 5 +++++ 3 files changed, 33 insertions(+) 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 772c25b74bc9..9764e814be66 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -418,6 +418,15 @@ static void __lim_process_operating_mode_action_frame(struct mac_context *mac_ct frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); pe_debug("Received Operating Mode action frame"); + + /* + * Ignore opmode change during channel change The opmode will be updated + * with the beacons on new channel once the AP move to new channel. + */ + if (session->ch_switch_in_progress) { + pe_debug("Ignore opmode change as channel switch is in progress"); + return; + } operating_mode_frm = qdf_mem_malloc(sizeof(*operating_mode_frm)); if (!operating_mode_frm) return; diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c index a22ccba34d77..a0710d8e296d 100644 --- a/core/mac/src/pe/sch/sch_beacon_process.c +++ b/core/mac/src/pe/sch/sch_beacon_process.c @@ -368,6 +368,16 @@ sch_bcn_process_sta(struct mac_context *mac_ctx, bcn->channelNumber); return false; } + + /* + * Ignore bcn as channel switch IE present and csa offload is enabled, + * as in CSA offload enabled case FW will send Event to switch channel + */ + if (bcn->channelSwitchPresent && wma_is_csa_offload_enabled()) { + pe_err_rl("Ignore bcn as channel switch IE present and csa offload is enabled"); + return false; + } + lim_detect_change_in_ap_capabilities(mac_ctx, bcn, session); if (lim_get_sta_hash_bssidx(mac_ctx, DPH_STA_HASH_INDEX_PEER, bssIdx, session) != QDF_STATUS_SUCCESS) @@ -552,6 +562,15 @@ sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds, uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); uint8_t ch_width = 0; + /* + * Ignore opmode change during channel change The opmode will be updated + * with the beacons on new channel once the AP move to new channel. + */ + if (session->ch_switch_in_progress) { + pe_debug("Ignore opmode change as channel switch is in progress"); + return; + } + if (session->vhtCapability && bcn->OperatingMode.present) { update_nss(mac_ctx, sta_ds, bcn, session, mac_hdr); oper_mode = get_operating_channel_width(sta_ds); diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 995ec2c3c98b..d488a0a1f2c9 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -3307,6 +3307,11 @@ void wma_process_update_opmode(tp_wma_handle wma_handle, ch_width); return; } + WMA_LOGD("%s: phymode = %d", __func__, iface->chanmode); + /* Always send phymode before BW to avoid any mismatch in FW */ + wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac, + WMI_PEER_PHYMODE, iface->chanmode, + update_vht_opmode->smesessionId); WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode); wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac, WMI_PEER_CHWIDTH, update_vht_opmode->opMode,