diff --git a/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h b/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h index d902f7ee4327..141ce08f47a2 100644 --- a/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h +++ b/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h @@ -210,6 +210,24 @@ QDF_STATUS policy_mgr_get_sta_sap_scc_on_dfs_chnl(struct wlan_objmgr_psoc *psoc, uint8_t *sta_sap_scc_on_dfs_chnl); +/** + * policy_mgr_is_bonded_chan_dfs() - check whether the given bonded + * channel configuration falls under DFS + * @psoc: pointer to psoc + * @ch_width: channel width of the operating channel + * @mhz_freq_seg1: center frequency of segment 1; used for 80+80 MHz + * @chan_freq: primary/operating channel frequency in MHz + * + * This API checks whether the given channel or bonded channel span + * includes DFS, based on the channel width and frequency segments. + * + * Return: true if the given bonded channel is DFS, else false. + */ +bool +policy_mgr_is_bonded_chan_dfs(struct wlan_objmgr_psoc *psoc, + enum phy_ch_width ch_width, + qdf_freq_t mhz_freq_seg1, + uint32_t chan_freq); /** * policy_mgr_get_dfs_master_dynamic_enabled() - support dfs master or not * on AP interafce when STA+SAP(GO) concurrency diff --git a/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c b/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c index 5661c5a03491..0bffbe5e612e 100644 --- a/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c +++ b/drivers/staging/qcacld-3.0/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c @@ -181,6 +181,45 @@ policy_mgr_get_sta_sap_scc_on_dfs_chnl(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +bool +policy_mgr_is_bonded_chan_dfs(struct wlan_objmgr_psoc *psoc, + enum phy_ch_width ch_width, + qdf_freq_t mhz_freq_seg1, + uint32_t chan_freq) +{ + bool is_ch_dfs = false; + struct policy_mgr_psoc_priv_obj *pm_ctx; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("pm_ctx is NULL"); + return false; + } + + if (ch_width == CH_WIDTH_160MHZ) { + if (wlan_reg_get_5g_bonded_channel_state_for_freq(pm_ctx->pdev, + chan_freq, + ch_width) + == CHANNEL_STATE_DFS) + is_ch_dfs = true; + } else if (ch_width == CH_WIDTH_80P80MHZ) { + if (wlan_reg_get_channel_state_for_freq( + pm_ctx->pdev, + chan_freq) == + CHANNEL_STATE_DFS || + wlan_reg_get_channel_state_for_freq( + pm_ctx->pdev, + mhz_freq_seg1) == + CHANNEL_STATE_DFS) + is_ch_dfs = true; + } else { + if (wlan_reg_is_dfs_for_freq(pm_ctx->pdev, chan_freq)) + is_ch_dfs = true; + } + + return is_ch_dfs; +} + static bool policy_mgr_update_dfs_master_dynamic_enabled( struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_api.h b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_api.h index 401bd9c549e5..3b757579f129 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -2444,11 +2444,30 @@ wlan_mlme_get_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc, char *mlme_get_roam_trigger_str(uint32_t roam_scan_trigger); /** - * mlme_get_roam_scan_type_str() - Get the string for roam sacn type + * enum roam_stats_scan_type - Roam scan type defines + * @ROAM_STATS_SCAN_TYPE_PARTIAL: Partial scan + * @ROAM_STATS_SCAN_TYPE_FULL: Full scan + * @ROAM_STATS_SCAN_TYPE_NO_SCAN: No roam scan was triggered. This is generally + * used in BTM events to indicate BTM frame exchange logs. + * @ROAM_STATS_SCAN_TYPE_HIGHER_BAND_5GHZ_6GHZ: Higher band roam scan from 2 GHz + * to 5 GHz or 6 GHz + * @ROAM_STATS_SCAN_TYPE_HIGHER_BAND_6GHZ: Higher band roam scan from 5 GHz to + * 6 GHz + */ +enum roam_stats_scan_type { + ROAM_STATS_SCAN_TYPE_PARTIAL = 0, + ROAM_STATS_SCAN_TYPE_FULL = 1, + ROAM_STATS_SCAN_TYPE_NO_SCAN = 2, + ROAM_STATS_SCAN_TYPE_HIGHER_BAND_5GHZ_6GHZ = 3, + ROAM_STATS_SCAN_TYPE_HIGHER_BAND_6GHZ = 4, +}; + +/** + * mlme_get_roam_scan_type_str() - Get the string for roam scan type * @roam_scan_type: roam scan type coming from fw via * wmi_roam_scan_info tlv * - * Return: Meaningful string for roam sacn type + * Return: Meaningful string for roam scan type */ char *mlme_get_roam_scan_type_str(uint32_t roam_scan_type); diff --git a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_api.c b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_api.c index dd930d969742..633b36067c91 100644 --- a/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/drivers/staging/qcacld-3.0/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -3793,14 +3793,16 @@ char *mlme_get_roam_status_str(uint32_t roam_status) char *mlme_get_roam_scan_type_str(uint32_t roam_scan_type) { switch (roam_scan_type) { - case 0: + case ROAM_STATS_SCAN_TYPE_PARTIAL: return "PARTIAL"; - case 1: + case ROAM_STATS_SCAN_TYPE_FULL: return "FULL"; - case 2: + case ROAM_STATS_SCAN_TYPE_NO_SCAN: return "NO SCAN"; - case 3: - return "Higher Band"; + case ROAM_STATS_SCAN_TYPE_HIGHER_BAND_5GHZ_6GHZ: + return "Higher Band: 5 GHz + 6 GHz"; + case ROAM_STATS_SCAN_TYPE_HIGHER_BAND_6GHZ: + return "Higher Band : 6 GHz"; default: return "UNKNOWN"; } diff --git a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c index d0d84e40a9ce..835f795e7736 100644 --- a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c +++ b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c @@ -1677,15 +1677,33 @@ static int dp_add_nbuf_to_fisa_flow(struct dp_rx_fst *fisa_hdl, fse_metadata = hal_rx_msdu_fse_metadata_get(hal_soc_hdl, rx_tlv_hdr); cce_match = hal_rx_msdu_cce_match_get(rx_tlv_hdr); - if (cce_match || (fisa_hdl->del_flow_count && - fse_metadata != fisa_flow->metadata)) { + /* + * For two cases the fse_metadata will not match the metadata + * from the fisa_flow_table entry + * 1) Flow has been evicted (lru deletion), and this packet is + * one of the few packets pending in the rx ring from the prev + * flow + * 2) HW flow table match fails for some packets in the + * currently active flow. + */ + if (cce_match) { dp_rx_fisa_release_ft_lock(fisa_hdl, napi_id); + DP_STATS_INC(fisa_hdl, reo_mismatch.allow_cce_match, + 1); + return FISA_AGGR_NOT_ELIGIBLE; + } + + if (fse_metadata != fisa_flow->metadata) { + dp_rx_fisa_release_ft_lock(fisa_hdl, napi_id); + DP_STATS_INC(fisa_hdl, + reo_mismatch.allow_fse_metdata_mismatch, + 1); return FISA_AGGR_NOT_ELIGIBLE; } dp_err("REO id mismatch flow: %pK napi_id: %u nbuf: %pK reo_id: %u", fisa_flow, fisa_flow->napi_id, nbuf, napi_id); - DP_STATS_INC(fisa_hdl, reo_mismatch, 1); + DP_STATS_INC(fisa_hdl, reo_mismatch.allow_non_aggr, 1); QDF_BUG(0); dp_rx_fisa_release_ft_lock(fisa_hdl, napi_id); return FISA_AGGR_NOT_ELIGIBLE; diff --git a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_rx_fst.c b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_rx_fst.c index 023729a53bf1..4d88045dedf1 100644 --- a/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_rx_fst.c +++ b/drivers/staging/qcacld-3.0/core/dp/txrx3.0/dp_rx_fst.c @@ -63,6 +63,24 @@ void dp_rx_dump_fisa_table(struct dp_soc *soc) } } +void dp_print_fisa_stats(struct dp_soc *soc) +{ + struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx; + struct dp_rx_fst *fst = soc->rx_fst; + + /* Check if it is enabled in the INI */ + if (!wlan_cfg_is_rx_fisa_enabled(cfg)) + return; + + dp_info("invalid flow index: %u", fst->stats.invalid_flow_index); + dp_info("reo_mismatch: cce_match: %u", + fst->stats.reo_mismatch.allow_cce_match); + dp_info("reo_mismatch: allow_fse_metdata_mismatch: %u", + fst->stats.reo_mismatch.allow_fse_metdata_mismatch); + dp_info("reo_mismatch: allow_non_aggr: %u", + fst->stats.reo_mismatch.allow_non_aggr); +} + /** * dp_rx_flow_send_htt_operation_cmd() - Invalidate FSE cache on FT change * @pdev: handle to DP pdev diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c index e34540cc9108..117189fcac04 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c @@ -1718,7 +1718,7 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = }; /** - * __is_driver_dfs_capable() - get driver DFS capability + * __is_driver_dfs_capable() - get driver DFS offload capability * @wiphy: pointer to wireless wiphy structure. * @wdev: pointer to wireless_dev structure. * @data: Pointer to the data to be passed via vendor interface @@ -17744,7 +17744,7 @@ void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx) { int value; bool fils_enabled, mac_spoofing_enabled; - bool dfs_master_capable = true, is_oce_sta_enabled = false; + bool is_oce_sta_enabled = false; QDF_STATUS status; struct wiphy *wiphy = hdd_ctx->wiphy; uint8_t allow_mcc_go_diff_bi = 0, enable_mcc = 0; @@ -17769,11 +17769,7 @@ void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx) if (fils_enabled) wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy); - status = ucfg_mlme_get_dfs_master_capability(hdd_ctx->psoc, - &dfs_master_capable); - if (QDF_IS_STATUS_SUCCESS(status) && dfs_master_capable) - wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy); - + wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy); status = ucfg_mlme_get_bigtk_support(hdd_ctx->psoc, &is_bigtk_supported); diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c index 80659541d94a..76a1a5228125 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c @@ -5244,6 +5244,7 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter, bool deliver_start_evt = true; struct s_ext_cap *p_ext_cap; enum reg_phymode reg_phy_mode, updated_phy_mode; + bool dfs_master_capable; hdd_enter(); @@ -5787,6 +5788,24 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter, config->ch_width_orig = CH_WIDTH_20MHZ; } + status = ucfg_mlme_get_dfs_master_capability(hdd_ctx->psoc, + &dfs_master_capable); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to get dfs master capable"); + ret = -EINVAL; + goto error; + } + + if (!dfs_master_capable && + policy_mgr_is_bonded_chan_dfs(hdd_ctx->psoc, + config->ch_width_orig, + config->ch_params.mhz_freq_seg1, + config->chan_freq)) { + hdd_err("Failed to bringup SAP; Atleast one bonded channel is DFS"); + ret = -EINVAL; + goto error; + } + if (wlan_hdd_setup_driver_overrides(adapter)) { ret = -EINVAL; goto error; diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c index 82e357d2e799..67f104883d23 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c @@ -3917,7 +3917,8 @@ hdd_get_roam_rt_stats_event_len(struct mlme_roam_debug_info *roam_stats) len += nla_total_size(sizeof(uint8_t)); if (roam_stats->scan.present) { - if (roam_stats->scan.num_chan && !roam_stats->scan.type) + if (roam_stats->scan.num_chan && + roam_stats->scan.type == ROAM_STATS_SCAN_TYPE_PARTIAL) for (i = 0; i < roam_stats->scan.num_chan;) i++; @@ -3990,7 +3991,8 @@ roam_rt_stats_fill_scan_freq(struct sk_buff *vendor_event, kfree_skb(vendor_event); return; } - if (roam_stats->scan.num_chan && !roam_stats->scan.type) { + if (roam_stats->scan.num_chan && + roam_stats->scan.type == ROAM_STATS_SCAN_TYPE_PARTIAL) { for (i = 0; i < roam_stats->scan.num_chan; i++) { if (nla_put_u32(vendor_event, i, roam_stats->scan.chan_freq[i])) { diff --git a/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h b/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h index 3bdcdf7f390a..d520ba3f3525 100644 --- a/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h +++ b/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h @@ -786,6 +786,7 @@ struct bss_description { #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) uint32_t is_single_pmk; #endif + uint16_t neg_rsn_caps; /* Please keep the structure 4 bytes aligned above the ieFields */ uint32_t ieFields[1]; }; diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c index 80ee8867c140..2e0f0511dc89 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_api.c @@ -2631,6 +2631,10 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, lim_fill_ft_session(mac_ctx, bss_desc, ft_session_ptr, session_ptr, roam_sync_ind_ptr->phy_mode); pe_update_crypto_params(mac_ctx, ft_session_ptr, roam_sync_ind_ptr); + + /* Reset the SPMK global cache */ + wlan_mlme_set_sae_single_pmk_bss_cap(mac_ctx->psoc, + ft_session_ptr->vdev_id, false); /* Next routine may update nss based on dot11Mode */ lim_ft_prepare_add_bss_req(mac_ctx, ft_session_ptr, bss_desc); if (session_ptr->is11Rconnection) diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 0f57abe3c224..f9eb195526dd 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1604,6 +1604,14 @@ __lim_process_sme_join_req(struct mac_context *mac_ctx, void *msg_buf) session->connected_akm = sme_join_req->akm; session->is_adaptive_11r_connection = sme_join_req->is_adaptive_11r_connection; + /* Reset the SPMK global cache for non-SAE connection */ + if (session->connected_akm != ANI_AKM_TYPE_SAE) { + wlan_mlme_set_sae_single_pmk_bss_cap(mac_ctx->psoc, + session->vdev_id, + false); + wlan_mlme_clear_sae_single_pmk_info(session->vdev, + NULL); + } #ifdef FEATURE_WLAN_ESE session->isESEconnection = sme_join_req->isESEconnection; #endif @@ -1832,7 +1840,7 @@ __lim_process_sme_join_req(struct mac_context *mac_ctx, void *msg_buf) session->spectrumMgtEnabled = true; session->isOSENConnection = sme_join_req->isOSENConnection; - pe_debug("Freq %d width %d freq0 %d freq1 %d, Smps %d: mode %d action %d, nss 1x1 %d vdev_nss %d nss %d cbMode %d dot11mode %d subfer %d subfee %d csn %d is_cisco %d", + pe_debug("Freq %d width %d freq0 %d freq1 %d, Smps %d: mode %d action %d, nss 1x1 %d vdev_nss %d nss %d cbMode %d dot11mode %d subfer %d subfee %d csn %d is_cisco %d akm %d", session->curr_op_freq, session->ch_width, session->ch_center_freq_seg0, session->ch_center_freq_seg1, @@ -1843,7 +1851,7 @@ __lim_process_sme_join_req(struct mac_context *mac_ctx, void *msg_buf) session->vht_config.su_beam_former, session->vht_config.su_beam_formee, session->vht_config.csnof_beamformer_antSup, - session->isCiscoVendorAP); + session->isCiscoVendorAP, session->connected_akm); /* Issue LIM_MLM_JOIN_REQ to MLM */ status = lim_send_join_req(session, mlm_join_req); diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c index 4484ed3c5ce8..cf719e8501a6 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c @@ -21461,12 +21461,15 @@ csr_process_roam_sync_callback(struct mac_context *mac_ctx, mac_ctx->psoc); mac_ctx->sme.set_connection_info_cb(false); - if (roam_synch_data->pmk_len) + if (roam_synch_data->pmk_len) { + mlme_debug("Received pmk in roam sync. Length: %d", + roam_synch_data->pmk_len); csr_check_and_set_sae_single_pmk_cap( mac_ctx, session, session_id, roam_synch_data->pmk, roam_synch_data->pmk_len); + } if (ucfg_pkt_capture_get_pktcap_mode(mac_ctx->psoc)) ucfg_pkt_capture_record_channel(vdev); diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_scan.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_scan.c index 8ba4ef61b6a1..5ce7d5345138 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_scan.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_scan.c @@ -2256,6 +2256,7 @@ static QDF_STATUS csr_fill_bss_from_scan_entry(struct mac_context *mac_ctx, bss_desc->beaconInterval = scan_entry->bcn_int; bss_desc->capabilityInfo = scan_entry->cap_info.value; + bss_desc->neg_rsn_caps = scan_entry->neg_sec_info.rsn_caps; if (WLAN_REG_IS_5GHZ_CH_FREQ(scan_entry->channel.chan_freq) || WLAN_REG_IS_6GHZ_CHAN_FREQ(scan_entry->channel.chan_freq)) diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c index f8c2f48b711c..c2e0f97e1e1f 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_util.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -2451,18 +2451,27 @@ static void csr_update_key_mgmt_crypto_param(struct wlan_objmgr_vdev *vdev, { int32_t key_mgmt = 0; int32_t neg_akm; + int32_t ap_akm = 0; uint8_t i; - neg_akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); + neg_akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_ORIG_KEY_MGMT); if (neg_akm < 0) { sme_err("Invalid AKM suite"); return; } for (i = 0; i < ap_rsn.akm_suite_cnt; i++) - SET_PARAM(neg_akm, + SET_PARAM(ap_akm, wlan_crypto_rsn_suite_to_keymgmt(ap_rsn.akm_suite[i])); + /* Intersect crypto AKM and candidate AP's AKM */ + neg_akm &= ap_akm; + if (neg_akm <= 0) { + sme_err("Invalid AKM suite"); + return; + } + sme_debug("Intersected AKM with AP's AKM 0x%x", neg_akm); + /* * As there can be multiple AKM present select the most secured AKM * present @@ -2531,6 +2540,7 @@ static void csr_update_ucast_cipher_crypto_param(struct wlan_objmgr_vdev *vdev, { int32_t ucastcipherset = 0; int32_t neg_ucastcipher; + int32_t ap_ucastcipher = 0; uint8_t i; neg_ucastcipher = wlan_crypto_get_param(vdev, @@ -2541,9 +2551,16 @@ static void csr_update_ucast_cipher_crypto_param(struct wlan_objmgr_vdev *vdev, } for (i = 0; i < ap_rsn.pwise_cipher_suite_count; i++) - SET_PARAM(neg_ucastcipher, + SET_PARAM(ap_ucastcipher, wlan_crypto_rsn_suite_to_cipher(ap_rsn.pwise_cipher_suites[i])); + /* Intersect crypto cipherset and candidate AP's cipherset */ + neg_ucastcipher &= ap_ucastcipher; + if (neg_ucastcipher <= 0) { + sme_err("Invalid unicast cipherset"); + return; + } + /* * As there can be multiple ucastcipher present select the most secured * ucastcipher present. @@ -2587,8 +2604,6 @@ uint8_t csr_construct_rsn_ie(struct mac_context *mac, uint32_t sessionId, (mac, pSirBssDesc, &local_ap_ie)))) return ie_len; - /* get AP RSN cap */ - qdf_mem_copy(&rsn_cap, local_ap_ie->RSN.RSN_Cap, sizeof(rsn_cap)); if (!ap_ie && local_ap_ie) /* locally allocated */ qdf_mem_free(local_ap_ie); @@ -2608,6 +2623,8 @@ uint8_t csr_construct_rsn_ie(struct mac_context *mac, uint32_t sessionId, } self_rsn_cap = (uint16_t)rsn_val; + /* get AP RSN cap */ + rsn_cap = pSirBssDesc->neg_rsn_caps; /* If AP is capable then use self capability else set PMF as 0 */ if (rsn_cap & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED && pProfile->MFPCapable) { diff --git a/drivers/staging/qcacld-3.0/core/wma/inc/wma.h b/drivers/staging/qcacld-3.0/core/wma/inc/wma.h index 5474fe767d0f..99b2164e618a 100644 --- a/drivers/staging/qcacld-3.0/core/wma/inc/wma.h +++ b/drivers/staging/qcacld-3.0/core/wma/inc/wma.h @@ -909,11 +909,12 @@ struct wma_wlm_stats_data { * @dynamic_nss_chains_update: per vdev nss, chains update * @ito_repeat_count: Indicates ito repeated count * @wma_fw_time_sync_timer: timer used for firmware time sync - * * @fw_therm_throt_support: FW Supports thermal throttling? + * @fw_therm_throt_support: FW Supports thermal throttling? + * @roam_sync_runtime_lock: roam sync runtime lock + * @is_roam_lock_acquired: Is roam_sync_runtime_lock acquired * * This structure is the global wma context. It contains global wma * module parameters and handles of other modules. - */ typedef struct { void *wmi_handle; @@ -1045,6 +1046,8 @@ typedef struct { qdf_mc_timer_t wma_fw_time_sync_timer; bool fw_therm_throt_support; bool enable_tx_compl_tsf64; + qdf_runtime_lock_t roam_sync_runtime_lock; + bool is_roam_lock_acquired; } t_wma_handle, *tp_wma_handle; /** diff --git a/drivers/staging/qcacld-3.0/core/wma/inc/wma_internal.h b/drivers/staging/qcacld-3.0/core/wma/inc/wma_internal.h index 1d7f88d5392c..45e2e678442b 100644 --- a/drivers/staging/qcacld-3.0/core/wma/inc/wma_internal.h +++ b/drivers/staging/qcacld-3.0/core/wma/inc/wma_internal.h @@ -1587,6 +1587,23 @@ void wma_acquire_wakelock(qdf_wake_lock_t *wl, uint32_t msec); */ void wma_release_wakelock(qdf_wake_lock_t *wl); +/** + * wma_prevent_pm_during_roam_sync() - prevent runtime PM during roam sync + * @wma: a reference to the global WMA handle + * + * Return: None + */ +void wma_prevent_pm_during_roam_sync(t_wma_handle *wma); + +/** + * wma_allow_pm_after_roam_sync() - allow runtime PM after roam + * sync complete + * @wma: a reference to the global WMA handle + * + * Return: None + */ +void wma_allow_pm_after_roam_sync(t_wma_handle *wma); + /** * wma_send_vdev_stop_to_fw() - send the vdev stop command to firmware * @wma: a reference to the global WMA handle diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c index 15f3c657a065..4d045b27df28 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c @@ -943,14 +943,14 @@ static void wma_peer_send_phymode(struct wlan_objmgr_vdev *vdev, fw_phymode = wma_host_to_fw_phymode(new_phymode); vdev_id = wlan_vdev_get_id(vdev); - wma_set_peer_param(wma, peer_mac_addr, WMI_PEER_PHYMODE, - fw_phymode, vdev_id); - max_ch_width_supported = wmi_get_ch_width_from_phy_mode(wma->wmi_handle, fw_phymode); wma_set_peer_param(wma, peer_mac_addr, WMI_PEER_CHWIDTH, max_ch_width_supported, vdev_id); + wma_set_peer_param(wma, peer_mac_addr, WMI_PEER_PHYMODE, + fw_phymode, vdev_id); + wma_debug("FW phymode %d old phymode %d new phymode %d bw %d macaddr "QDF_MAC_ADDR_FMT, fw_phymode, old_peer_phymode, new_phymode, max_ch_width_supported, QDF_MAC_ADDR_REF(peer_mac_addr)); diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c index b48b2729e9ae..7021b8720fc3 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c @@ -3428,6 +3428,8 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, "wlan_fw_rsp_wakelock"); qdf_runtime_lock_init(&wma_handle->wmi_cmd_rsp_runtime_lock); qdf_runtime_lock_init(&wma_handle->sap_prevent_runtime_pm_lock); + qdf_runtime_lock_init(&wma_handle->roam_sync_runtime_lock); + wma_handle->is_roam_lock_acquired = false; /* Register peer assoc conf event handler */ wmi_unified_register_event_handler(wma_handle->wmi_handle, @@ -3538,6 +3540,7 @@ err_dbglog_init: qdf_runtime_lock_deinit(&wma_handle->sap_prevent_runtime_pm_lock); qdf_runtime_lock_deinit(&wma_handle->wmi_cmd_rsp_runtime_lock); qdf_spinlock_destroy(&wma_handle->wma_hold_req_q_lock); + qdf_runtime_lock_deinit(&wma_handle->roam_sync_runtime_lock); err_event_init: wmi_unified_unregister_event_handler(wma_handle->wmi_handle, wmi_debug_print_event_id); @@ -4592,6 +4595,7 @@ QDF_STATUS wma_close(void) qdf_wake_lock_destroy(&wma_handle->wmi_cmd_rsp_wake_lock); qdf_runtime_lock_deinit(&wma_handle->sap_prevent_runtime_pm_lock); qdf_runtime_lock_deinit(&wma_handle->wmi_cmd_rsp_runtime_lock); + qdf_runtime_lock_deinit(&wma_handle->roam_sync_runtime_lock); qdf_spinlock_destroy(&wma_handle->wma_hold_req_q_lock); if (wma_handle->pGetRssiReq) { diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c index 3c7e6c9105e0..ec3e079e5096 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022, 2026 Qualcomm Innovation Center, Inc. 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 @@ -2732,6 +2732,10 @@ void wma_process_update_opmode(tp_wma_handle wma_handle, wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac, WMI_PEER_CHWIDTH, update_vht_opmode->opMode, update_vht_opmode->smesessionId); + + wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac, + WMI_PEER_PHYMODE, + fw_phymode, update_vht_opmode->smesessionId); } /** diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c index 702063ef6170..915e196f4d81 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c @@ -1617,21 +1617,23 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, return status; } + wma_prevent_pm_during_roam_sync(wma); + param_buf = (WMI_ROAM_SYNCH_EVENTID_param_tlvs *)event; if (!param_buf) { wma_err_rl("received null buf from target"); - return status; + goto fail; } synch_event = param_buf->fixed_param; if (!synch_event) { wma_err_rl("received null event data from target"); - return status; + goto fail; } if (synch_event->vdev_id >= wma->max_bssid) { wma_err_rl("received invalid vdev_id %d", synch_event->vdev_id); - return status; + goto fail; } iface = &wma->interfaces[synch_event->vdev_id]; @@ -1647,10 +1649,14 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, if (QDF_IS_STATUS_ERROR(qdf_status)) { wma_err("Failed to send the EV_ROAM"); wma_post_roam_sync_failure(wma, synch_event->vdev_id); - return status; + goto fail; } wma_debug("Posted EV_ROAM to VDEV SM"); return 0; + +fail: + wma_allow_pm_after_roam_sync(wma); + return status; } int wma_roam_auth_offload_event_handler(WMA_HANDLE handle, uint8_t *event, @@ -2064,7 +2070,7 @@ wma_rso_print_scan_info(struct wmi_roam_scan_data *scan, uint8_t vdev_id, tmp = buf; /* For partial scans, print the channel info */ - if (!scan->type) { + if (scan->type == ROAM_STATS_SCAN_TYPE_PARTIAL) { buf_cons = qdf_snprint(tmp, buf_left, "{"); buf_left -= buf_cons; tmp += buf_cons; @@ -2833,6 +2839,7 @@ void wma_process_roam_synch_complete(WMA_HANDLE handle, uint8_t vdev_id) wma_info("LFR3: vdev[%d] Sent ROAM_SYNCH_COMPLETE", vdev_id); wlan_roam_debug_log(vdev_id, DEBUG_ROAM_SYNCH_CNF, DEBUG_INVALID_PEER_ID, NULL, NULL, 0, 0); + wma_allow_pm_after_roam_sync(wma_handle); } #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ @@ -4551,10 +4558,12 @@ static void wma_invalid_roam_reason_handler(tp_wma_handle wma_handle, if (notif == WMI_ROAM_NOTIF_ROAM_START) { wma_handle->interfaces[vdev_id].roaming_in_progress = true; op_code = SIR_ROAMING_START; + wma_prevent_pm_during_roam_sync(wma_handle); } else if (notif == WMI_ROAM_NOTIF_ROAM_ABORT) { wma_handle->interfaces[vdev_id].roaming_in_progress = false; op_code = SIR_ROAMING_ABORT; lim_sae_auth_cleanup_retry(wma_handle->mac_context, vdev_id); + wma_allow_pm_after_roam_sync(wma_handle); } else { wma_debug("Invalid notif %d", notif); return; @@ -4730,6 +4739,7 @@ int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf, = false; lim_sae_auth_cleanup_retry(wma_handle->mac_context, wmi_event->vdev_id); + wma_allow_pm_after_roam_sync(wma_handle); break; #endif case WMI_ROAM_REASON_INVALID: diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c index 57d3d09ea1da..23d2e9a87be8 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c @@ -1361,6 +1361,15 @@ wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats, wmi_peer_rx, wmi_rx, peer_stats); return QDF_STATUS_E_FAILURE; } + + /* Check if num_rx_stats is sufficient to avoid buffer overflow */ + if (param_buf->num_rx_stats < + fix_param->num_peer_ac_rx_stats * WLAN_MAX_AC) { + wma_err("Insufficient rx_stats buffer: available %d, required %d", + param_buf->num_rx_stats, + fix_param->num_peer_ac_rx_stats * WLAN_MAX_AC); + return QDF_STATUS_E_FAILURE; + } for (i = 0; i < fix_param->num_peer_ac_rx_stats; i++) { uint32_t peer_id = wmi_peer_rx[i].peer_id; struct sir_wifi_rx *ac; @@ -3815,6 +3824,30 @@ void wma_release_wakelock(qdf_wake_lock_t *wl) qdf_runtime_pm_allow_suspend(&wma->wmi_cmd_rsp_runtime_lock); } +void wma_prevent_pm_during_roam_sync(t_wma_handle *wma) +{ + if (!wma) + return; + + if (wma->is_roam_lock_acquired) + return; + + qdf_runtime_pm_prevent_suspend(&wma->roam_sync_runtime_lock); + wma->is_roam_lock_acquired = true; +} + +void wma_allow_pm_after_roam_sync(t_wma_handle *wma) +{ + if (!wma) + return; + + if (!wma->is_roam_lock_acquired) + return; + + qdf_runtime_pm_allow_suspend(&wma->roam_sync_runtime_lock); + wma->is_roam_lock_acquired = false; +} + QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id) { QDF_STATUS status = QDF_STATUS_E_FAILURE; diff --git a/drivers/staging/qcacld-3.0/uapi/linux/a_types.h b/drivers/staging/qcacld-3.0/uapi/linux/a_types.h index 190d40df6afd..5537fae67697 100644 --- a/drivers/staging/qcacld-3.0/uapi/linux/a_types.h +++ b/drivers/staging/qcacld-3.0/uapi/linux/a_types.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -29,15 +30,21 @@ #define _A_TYPES_H_ #include -typedef unsigned int A_UINT32; typedef unsigned long long A_UINT64; +typedef long long A_INT64; + +typedef unsigned int A_UINT32; +typedef int A_INT32; + typedef unsigned short A_UINT16; +typedef short A_INT16; + typedef unsigned char A_UINT8; -typedef int A_INT32; -typedef short A_INT16; -typedef char A_INT8; +typedef char A_INT8; + typedef unsigned char A_UCHAR; -typedef char A_CHAR; +typedef char A_CHAR; + typedef _Bool A_BOOL; #endif /* _ATHTYPES_H_ */