diff options
-rw-r--r-- | dp/inc/cdp_txrx_ops.h | 4 | ||||
-rw-r--r-- | dp/inc/cdp_txrx_peer_ops.h | 25 | ||||
-rw-r--r-- | os_if/linux/qca_vendor.h | 9 | ||||
-rw-r--r-- | os_if/linux/scan/src/wlan_cfg80211_scan.c | 90 | ||||
-rw-r--r-- | umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h | 16 | ||||
-rw-r--r-- | umac/regulatory/core/src/reg_services_common.c | 2 | ||||
-rw-r--r-- | umac/regulatory/core/src/reg_utils.c | 2 | ||||
-rw-r--r-- | umac/scan/core/src/wlan_scan_filter.c | 14 | ||||
-rw-r--r-- | umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h | 8 | ||||
-rw-r--r-- | umac/scan/dispatcher/src/wlan_scan_ucfg_api.c | 6 | ||||
-rw-r--r-- | umac/scan/dispatcher/src/wlan_scan_utils_api.c | 70 | ||||
-rw-r--r-- | wmi/inc/wmi_unified_param.h | 1 | ||||
-rw-r--r-- | wmi/inc/wmi_unified_priv.h | 1 | ||||
-rw-r--r-- | wmi/inc/wmi_unified_roam_param.h | 5 | ||||
-rw-r--r-- | wmi/src/wmi_unified.c | 5 | ||||
-rw-r--r-- | wmi/src/wmi_unified_nan_tlv.c | 11 | ||||
-rw-r--r-- | wmi/src/wmi_unified_roam_tlv.c | 16 | ||||
-rw-r--r-- | wmi/src/wmi_unified_tlv.c | 46 |
18 files changed, 262 insertions, 69 deletions
diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 7ed927cec..1b0802004 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -1355,6 +1355,8 @@ struct cdp_peer_ops { void (*update_last_real_peer)(struct cdp_pdev *pdev, void *vdev, uint8_t *peer_id, bool restore_last_peer); void (*peer_detach_force_delete)(void *peer); + void (*peer_flush_frags)(struct cdp_pdev *pdev, + uint8_t vdev_id, uint8_t *peer_mac); }; /** diff --git a/dp/inc/cdp_txrx_peer_ops.h b/dp/inc/cdp_txrx_peer_ops.h index 85fd1b6f4..19604ab93 100644 --- a/dp/inc/cdp_txrx_peer_ops.h +++ b/dp/inc/cdp_txrx_peer_ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, 2021 The Linux Foundation. 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 @@ -673,4 +673,27 @@ is_cdp_peer_detach_force_delete_supported(ol_txrx_soc_handle soc) return false; } + +/** + * cdp_peer_flush_frags() - Flush frags on peer + * @soc - data path soc handle + * @pdev - data path device instance + * @vdev_id - virtual interface id + * @peer_mac - peer mac addr + * + * Return: None + */ +static inline void +cdp_peer_flush_frags(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, + uint8_t vdev_id, uint8_t *peer_mac) +{ + if (!soc || !soc->ops || !soc->ops->peer_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return; + } + + if (soc->ops->peer_ops->peer_flush_frags) + soc->ops->peer_ops->peer_flush_frags(pdev, vdev_id, peer_mac); +} #endif /* _CDP_TXRX_PEER_H_ */ diff --git a/os_if/linux/qca_vendor.h b/os_if/linux/qca_vendor.h index 8a81c4b73..874390358 100644 --- a/os_if/linux/qca_vendor.h +++ b/os_if/linux/qca_vendor.h @@ -2207,6 +2207,12 @@ enum qca_wlan_vendor_attr_ll_stats_results_type { * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RTS_FAIL_CNT: RTS fail count * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_SUCC_CNT: PPDU successful count * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_FAIL_CNT: PPDU fail count + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_TX_TIME: Unsigned int 32bit + * value representing total number of msecs the radio is transmitting on + * this channel. + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME: Unsigned int 32bit + * value representing total number of msecs the radio is receiving all + * 802.11 frames intended for this device on this channel. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST: After last * @QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX: Max value */ @@ -2312,6 +2318,9 @@ enum qca_wlan_vendor_attr_ll_stats_results { QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_SUCC_CNT = 81, QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_FAIL_CNT = 82, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_TX_TIME = 84, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85, + /* keep last */ QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX = diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index e418e8fd8..ecc743a9c 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -645,20 +645,22 @@ wlan_copy_bssid_scan_request(struct scan_start_request *scan_req, #endif /** - * wlan_scan_request_enqueue() - enqueue Scan Request + * wlan_schedule_scan_start_request() - Schedule scan start request * @pdev: pointer to pdev object * @req: Pointer to the scan request * @source: source of the scan request - * @scan_id: scan identifier + * @scan_start_req: pointer to scan start request * - * Enqueue scan request in the global scan list.This list - * stores the active scan request information. + * Schedule scan start request and enqueue scan request in the global scan + * list. This list stores the active scan request information. * - * Return: 0 on success, error number otherwise + * Return: QDF_STATUS */ -static int wlan_scan_request_enqueue(struct wlan_objmgr_pdev *pdev, - struct cfg80211_scan_request *req, - uint8_t source, uint32_t scan_id) +static QDF_STATUS +wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev, + struct cfg80211_scan_request *req, + uint8_t source, + struct scan_start_request *scan_start_req) { struct scan_req *scan_req; QDF_STATUS status; @@ -666,32 +668,44 @@ static int wlan_scan_request_enqueue(struct wlan_objmgr_pdev *pdev, struct osif_scan_pdev *osif_scan; scan_req = qdf_mem_malloc(sizeof(*scan_req)); - if (!scan_req) - return -ENOMEM; + if (!scan_req) { + ucfg_scm_scan_free_scan_request_mem(scan_start_req); + return QDF_STATUS_E_NOMEM; + } /* Get NL global context from objmgr*/ osif_ctx = wlan_pdev_get_ospriv(pdev); osif_scan = osif_ctx->osif_scan; scan_req->scan_request = req; scan_req->source = source; - scan_req->scan_id = scan_id; + scan_req->scan_id = scan_start_req->scan_req.scan_id; scan_req->dev = req->wdev->netdev; qdf_mutex_acquire(&osif_scan->scan_req_q_lock); - if (qdf_list_size(&osif_scan->scan_req_q) < WLAN_MAX_SCAN_COUNT) - status = qdf_list_insert_back(&osif_scan->scan_req_q, - &scan_req->node); - else + if (qdf_list_size(&osif_scan->scan_req_q) < WLAN_MAX_SCAN_COUNT) { + status = ucfg_scan_start(scan_start_req); + if (QDF_IS_STATUS_SUCCESS(status)) { + qdf_list_insert_back(&osif_scan->scan_req_q, + &scan_req->node); + } else { + cfg80211_debug_rl("scan req failed with error %d", + status); + if (status == QDF_STATUS_E_RESOURCES) + cfg80211_debug_rl("HO is in progress.So defer the scan by informing busy"); + } + } else { + ucfg_scm_scan_free_scan_request_mem(scan_start_req); status = QDF_STATUS_E_RESOURCES; + } + qdf_mutex_release(&osif_scan->scan_req_q_lock); if (QDF_IS_STATUS_ERROR(status)) { cfg80211_debug_rl("Failed to enqueue Scan Req as max scan %d already queued", qdf_list_size(&osif_scan->scan_req_q)); qdf_mem_free(scan_req); - return -EINVAL; } - return 0; + return status; } /** @@ -728,12 +742,13 @@ static QDF_STATUS wlan_scan_request_dequeue( } scan_priv = osif_ctx->osif_scan; + qdf_mutex_acquire(&scan_priv->scan_req_q_lock); if (qdf_list_empty(&scan_priv->scan_req_q)) { + qdf_mutex_release(&scan_priv->scan_req_q_lock); cfg80211_info("Scan List is empty"); return QDF_STATUS_E_FAILURE; } - qdf_mutex_acquire(&scan_priv->scan_req_q_lock); if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&scan_priv->scan_req_q, &next_node)) { qdf_mutex_release(&scan_priv->scan_req_q_lock); @@ -1020,9 +1035,11 @@ static void wlan_cfg80211_scan_done_callback( wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); allow_suspend: osif_priv = wlan_pdev_get_ospriv(pdev); + qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock); if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) { struct wlan_objmgr_psoc *psoc; + qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock); qdf_runtime_pm_allow_suspend( &osif_priv->osif_scan->runtime_pm_lock); @@ -1039,6 +1056,8 @@ allow_suspend: wlan_scan_acquire_wake_lock_timeout(psoc, &osif_priv->osif_scan->scan_wake_lock, SCAN_WAKE_LOCK_CONNECT_DURATION); + } else { + qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock); } } @@ -1289,7 +1308,6 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, wlan_scan_id scan_id; bool is_p2p_scan = false; enum wlan_band band; - struct net_device *netdev = NULL; QDF_STATUS qdf_status; enum QDF_OPMODE opmode; uint32_t extra_ie_len = 0; @@ -1316,12 +1334,15 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, * is not empty, and the simultaneous scan is disabled, dont allow 2nd * scan. */ + qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock); if (!wlan_cfg80211_allow_simultaneous_scan(psoc) && !qdf_list_empty(&osif_priv->osif_scan->scan_req_q) && opmode != QDF_SAP_MODE) { + qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock); cfg80211_err("Simultaneous scan disabled, reject scan"); return -EBUSY; } + qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock); req = qdf_mem_malloc(sizeof(*req)); if (!req) @@ -1344,14 +1365,6 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, req->scan_req.scan_id = scan_id; req->scan_req.scan_req_id = req_id; - /* Enqueue the scan request */ - ret = wlan_scan_request_enqueue(pdev, request, params->source, - req->scan_req.scan_id); - if (ret) { - qdf_mem_free(req); - return ret; - } - /* Update scan policy type flags according to cfg scan request */ wlan_cfg80211_update_scan_policy_type_flags(request, &req->scan_req); @@ -1544,18 +1557,21 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, qdf_runtime_pm_prevent_suspend( &osif_priv->osif_scan->runtime_pm_lock); - qdf_status = ucfg_scan_start(req); + qdf_status = wlan_schedule_scan_start_request(pdev, request, + params->source, req); if (QDF_IS_STATUS_ERROR(qdf_status)) { - cfg80211_err("scan req failed with error %d", qdf_status); - if (qdf_status == QDF_STATUS_E_RESOURCES) - cfg80211_err("HO is in progress.So defer the scan by informing busy"); - wlan_scan_request_dequeue(pdev, scan_id, &request, - ¶ms->source, &netdev); + qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock); if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) { + qdf_mutex_release( + &osif_priv->osif_scan->scan_req_q_lock); qdf_runtime_pm_allow_suspend( - &osif_priv->osif_scan->runtime_pm_lock); - wlan_scan_release_wake_lock(psoc, - &osif_priv->osif_scan->scan_wake_lock); + &osif_priv->osif_scan->runtime_pm_lock); + wlan_scan_release_wake_lock( + psoc, + &osif_priv->osif_scan->scan_wake_lock); + } else { + qdf_mutex_release( + &osif_priv->osif_scan->scan_req_q_lock); } } @@ -1563,8 +1579,6 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, err: qdf_mem_free(req); - wlan_scan_request_dequeue(pdev, scan_id, &request, - ¶ms->source, &netdev); return ret; } diff --git a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h index 6a1470b6e..d8d688e58 100644 --- a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h +++ b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h @@ -135,6 +135,17 @@ #define WLAN_REQUEST_IE_MAX_LEN 255 #define WLAN_RM_CAPABILITY_IE_MAX_LEN 5 +/* Wide band channel switch IE length */ +#define WLAN_WIDE_BW_CHAN_SWITCH_IE_LEN 3 + +/* Number of max TX power elements supported plus size of Transmit Power + * Information element. + */ +#define WLAN_TPE_IE_MAX_LEN 9 + +/* Max channel switch time IE length */ +#define WLAN_MAX_CHAN_SWITCH_TIME_IE_LEN 4 + /* HT capability flags */ #define WLAN_HTCAP_C_ADVCODING 0x0001 #define WLAN_HTCAP_C_CHWIDTH40 0x0002 @@ -1410,6 +1421,8 @@ is_bwnss_oui(uint8_t *frm) ((ATH_OUI_BW_NSS_MAP_TYPE << 24) | ATH_OUI)); } +#define WLAN_BWNSS_MAP_OFFSET 6 + /** * is_he_cap_oui() - If vendor IE is HE CAP OUI * @frm: vendor IE pointer @@ -1786,9 +1799,12 @@ static inline void wlan_parse_wapi_ie(uint8_t *wapi_ie, len -= WLAN_OUI_SIZE; } + if (len < 2) + return; wapi->uc_cipher_count = LE_READ_2(ie); ie += 2; len -= 2; + if ((wapi->uc_cipher_count > WLAN_MAX_CIPHER) || len < (wapi->uc_cipher_count * WLAN_OUI_SIZE + 2)) return; diff --git a/umac/regulatory/core/src/reg_services_common.c b/umac/regulatory/core/src/reg_services_common.c index 8f717cddb..9e18112e4 100644 --- a/umac/regulatory/core/src/reg_services_common.c +++ b/umac/regulatory/core/src/reg_services_common.c @@ -1739,7 +1739,7 @@ QDF_STATUS reg_get_curr_regdomain(struct wlan_objmgr_pdev *pdev, } if (index == num_reg_dmn) { - reg_err("invalid regdomain"); + reg_debug_rl("invalid regdomain"); return QDF_STATUS_E_FAILURE; } diff --git a/umac/regulatory/core/src/reg_utils.c b/umac/regulatory/core/src/reg_utils.c index ef956a5a6..5c9293f7c 100644 --- a/umac/regulatory/core/src/reg_utils.c +++ b/umac/regulatory/core/src/reg_utils.c @@ -320,7 +320,7 @@ bool reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev) status = reg_get_curr_regdomain(pdev, &cur_reg_dmn); if (status != QDF_STATUS_SUCCESS) { - reg_err("Failed to get reg domain"); + reg_debug_rl("Failed to get reg domain"); return false; } diff --git a/umac/scan/core/src/wlan_scan_filter.c b/umac/scan/core/src/wlan_scan_filter.c index 4581289d7..6f7a2565e 100644 --- a/umac/scan/core/src/wlan_scan_filter.c +++ b/umac/scan/core/src/wlan_scan_filter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. 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 @@ -1034,6 +1034,7 @@ static bool scm_is_fils_config_match(struct scan_filter *filter, int i; struct fils_indication_ie *indication_ie; uint8_t *data; + uint8_t *end_ptr; if (!filter->fils_scan_filter.realm_check) return true; @@ -1045,14 +1046,19 @@ static bool scm_is_fils_config_match(struct scan_filter *filter, indication_ie = (struct fils_indication_ie *) db_entry->ie_list.fils_indication; + end_ptr = (uint8_t *)indication_ie + indication_ie->len + 2; + data = indication_ie->variable_data; - if (indication_ie->is_cache_id_present) + if (indication_ie->is_cache_id_present && + (data + CACHE_IDENTIFIER_LEN) <= end_ptr) data += CACHE_IDENTIFIER_LEN; - if (indication_ie->is_hessid_present) + if (indication_ie->is_hessid_present && + (data + HESSID_LEN) <= end_ptr) data += HESSID_LEN; - for (i = 1; i <= indication_ie->realm_identifiers_cnt; i++) { + for (i = 1; i <= indication_ie->realm_identifiers_cnt && + (data + REAM_HASH_LEN) <= end_ptr; i++) { if (!qdf_mem_cmp(filter->fils_scan_filter.fils_realm, data, REAM_HASH_LEN)) return true; diff --git a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h index b5eee5ce9..dbc4f90ee 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h @@ -163,6 +163,14 @@ ucfg_scan_get_pno_match(struct wlan_objmgr_vdev *vdev) } #endif /* FEATURE_WLAN_SCAN_PNO */ /** + * ucfg_scm_scan_free_scan_request_mem() - Free scan request memory + * @req: scan_start_request object + * + * Return: QDF_STATUS + */ +QDF_STATUS ucfg_scm_scan_free_scan_request_mem(struct scan_start_request *req); + +/** * ucfg_scan_start() - Public API to start a scan * @req: start scan req params * diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index 3c31fc17d..298b3bb2e 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -430,6 +430,12 @@ ucfg_scan_set_custom_scan_chan_list(struct wlan_objmgr_pdev *pdev, } QDF_STATUS +ucfg_scm_scan_free_scan_request_mem(struct scan_start_request *req) +{ + return scm_scan_free_scan_request_mem(req); +} + +QDF_STATUS ucfg_scan_start(struct scan_start_request *req) { struct scheduler_msg msg = {0}; diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 97ef1a8cd..b1c9ea5ac 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. 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 @@ -371,12 +371,18 @@ util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry *scan_params, } switch (sub_ie->ie_id) { case WLAN_ELEMID_COUNTRY: + if (sub_ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN) + return QDF_STATUS_E_INVAL; scan_params->ie_list.country = (uint8_t *)sub_ie; break; case WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH: + if (sub_ie->ie_len < WLAN_WIDE_BW_CHAN_SWITCH_IE_LEN) + return QDF_STATUS_E_INVAL; scan_params->ie_list.widebw = (uint8_t *)sub_ie; break; case WLAN_ELEMID_VHT_TX_PWR_ENVLP: + if (sub_ie->ie_len > WLAN_TPE_IE_MAX_LEN) + return QDF_STATUS_E_INVAL; scan_params->ie_list.txpwrenvlp = (uint8_t *)sub_ie; break; } @@ -419,6 +425,8 @@ util_scan_parse_extn_ie(struct scan_cache_entry *scan_params, switch (extn_ie->ie_extn_id) { case WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME: + if (extn_ie->ie_len != WLAN_MAX_CHAN_SWITCH_TIME_IE_LEN) + return QDF_STATUS_E_INVAL; scan_params->ie_list.mcst = (uint8_t *)ie; break; case WLAN_EXTN_ELEMID_SRP: @@ -525,7 +533,8 @@ util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params, * Bandwidth-NSS map has sub-type & version. * hence copy data just after version byte */ - scan_params->ie_list.bwnss_map = (((uint8_t *)ie) + 8); + if (ie->ie_len > WLAN_BWNSS_MAP_OFFSET) + scan_params->ie_list.bwnss_map = (((uint8_t *)ie) + 8); } else if (is_mbo_oce_oui((uint8_t *)ie)) { scan_params->ie_list.mbo_oce = (uint8_t *)ie; } else if (is_extender_oui((uint8_t *)ie)) { @@ -795,7 +804,8 @@ static void util_scan_update_esp_data(struct wlan_esp_ie *esp_information, return; } - for (i = 0; i < total_elements; i++) { + for (i = 0; i < total_elements && + data < ((uint8_t *)esp_ie + esp_ie->esp_len + 3); i++) { esp_info = (struct wlan_esp_info *)data; if (esp_info->access_category == ESP_AC_BK) { qdf_mem_copy(&esp_information->esp_info_AC_BK, @@ -1308,6 +1318,7 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, uint8_t *pos, *tmp; const uint8_t *tmp_old, *tmp_new; uint8_t *sub_copy; + size_t tmp_rem_len; /* copy subelement as we need to change its content to * mark an ie after it is processed. @@ -1322,8 +1333,10 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, /* new ssid */ tmp_new = util_scan_find_ie(WLAN_ELEMID_SSID, sub_copy, subie_len); if (tmp_new) { - qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); - pos += (tmp_new[1] + 2); + if ((pos + tmp_new[1] + 2) <= (new_ie + ielen)) { + qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); + pos += (tmp_new[1] + 2); + } } /* go through IEs in ie (skip SSID) and subelement, @@ -1343,8 +1356,12 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, if (!tmp) { /* ie in old ie but not in subelement */ if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) { - qdf_mem_copy(pos, tmp_old, tmp_old[1] + 2); - pos += tmp_old[1] + 2; + if ((pos + tmp_old[1] + 2) <= + (new_ie + ielen)) { + qdf_mem_copy(pos, tmp_old, + tmp_old[1] + 2); + pos += tmp_old[1] + 2; + } } } else { /* ie in transmitting ie also in subelement, @@ -1353,24 +1370,35 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, * vendor ie, compare OUI + type + subType to * determine if they are the same ie. */ - if (tmp_old[0] == WLAN_ELEMID_VENDOR) { + tmp_rem_len = subie_len - (tmp - sub_copy); + if (tmp_old[0] == WLAN_ELEMID_VENDOR && + tmp_rem_len >= 7) { if (!qdf_mem_cmp(tmp_old + 2, tmp + 2, 5)) { /* same vendor ie, copy from * subelement */ - qdf_mem_copy(pos, tmp, tmp[1] + 2); - pos += tmp[1] + 2; - tmp[0] = 0xff; + if ((pos + tmp[1] + 2) <= + (new_ie + ielen)) { + qdf_mem_copy(pos, tmp, + tmp[1] + 2); + pos += tmp[1] + 2; + tmp[0] = 0xff; + } } else { - qdf_mem_copy(pos, tmp_old, - tmp_old[1] + 2); - pos += tmp_old[1] + 2; + if ((pos + tmp_old[1] + 2) <= + (new_ie + ielen)) { + qdf_mem_copy(pos, tmp_old, + tmp_old[1] + 2); + pos += tmp_old[1] + 2; + } } } else { /* copy ie from subelement into new ie */ - qdf_mem_copy(pos, tmp, tmp[1] + 2); - pos += tmp[1] + 2; - tmp[0] = 0xff; + if ((pos + tmp[1] + 2) <= (new_ie + ielen)) { + qdf_mem_copy(pos, tmp, tmp[1] + 2); + pos += tmp[1] + 2; + tmp[0] = 0xff; + } } } @@ -1389,8 +1417,10 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, tmp_new[0] == WLAN_ELEMID_SSID || tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX || tmp_new[0] == 0xff)) { - qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); - pos += tmp_new[1] + 2; + if ((pos + tmp_new[1] + 2) <= (new_ie + ielen)) { + qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); + pos += tmp_new[1] + 2; + } } if (tmp_new + tmp_new[1] + 2 - sub_copy == subie_len) break; @@ -1432,7 +1462,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, pos = ie; - new_ie = qdf_mem_malloc(MAX_IE_LEN); + new_ie = qdf_mem_malloc(ielen); if (!new_ie) return QDF_STATUS_E_NOMEM; diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index a9473e512..3ea5c231f 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -5367,6 +5367,7 @@ typedef enum { wmi_service_packet_capture_support, wmi_service_peer_delete_no_peer_flush_tids_cmd, wmi_service_suiteb_roam_support, + wmi_service_ll_stats_per_chan_rx_tx_time, wmi_services_max, } wmi_conv_service_ids; #define WMI_SERVICE_UNAVAILABLE 0xFFFF diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 0319360e1..65bcdd08e 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -2156,6 +2156,7 @@ struct wmi_soc { /* WMI service bitmap received from target */ uint32_t *wmi_service_bitmap; uint32_t *wmi_ext_service_bitmap; + uint32_t *wmi_ext2_service_bitmap; uint32_t services[wmi_services_max]; uint16_t wmi_max_cmds; uint32_t soc_idx; diff --git a/wmi/inc/wmi_unified_roam_param.h b/wmi/inc/wmi_unified_roam_param.h index c2bed0b0a..e5c43057d 100644 --- a/wmi/inc/wmi_unified_roam_param.h +++ b/wmi/inc/wmi_unified_roam_param.h @@ -436,8 +436,11 @@ struct scoring_param { #define IDLE_ROAM_TRIGGER 0 #define BTM_ROAM_TRIGGER 1 +#define NUM_OF_ROAM_MIN_RSSI 3 + #define DEAUTH_MIN_RSSI 0 #define BMISS_MIN_RSSI 1 +#define MIN_RSSI_2G_TO_5G_ROAM 2 /** * enum roam_trigger_reason - Reason for triggering roam @@ -524,7 +527,7 @@ struct ap_profile_params { uint8_t vdev_id; struct ap_profile profile; struct scoring_param param; - struct roam_trigger_min_rssi min_rssi_params[NUM_OF_ROAM_TRIGGERS]; + struct roam_trigger_min_rssi min_rssi_params[NUM_OF_ROAM_MIN_RSSI]; struct roam_trigger_score_delta score_delta_param[NUM_OF_ROAM_TRIGGERS]; }; diff --git a/wmi/src/wmi_unified.c b/wmi/src/wmi_unified.c index 27bb33d99..4d094b349 100644 --- a/wmi/src/wmi_unified.c +++ b/wmi/src/wmi_unified.c @@ -2720,6 +2720,11 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle) soc->wmi_ext_service_bitmap = NULL; } + if (soc->wmi_ext2_service_bitmap) { + qdf_mem_free(soc->wmi_ext2_service_bitmap); + soc->wmi_ext2_service_bitmap = NULL; + } + /* Decrease the ref count once refcount infra is present */ soc->wmi_psoc = NULL; qdf_mem_free(soc); diff --git a/wmi/src/wmi_unified_nan_tlv.c b/wmi/src/wmi_unified_nan_tlv.c index 5f43bc10e..f9b6d76b2 100644 --- a/wmi/src/wmi_unified_nan_tlv.c +++ b/wmi/src/wmi_unified_nan_tlv.c @@ -744,6 +744,13 @@ static QDF_STATUS extract_ndp_ind_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_E_INVAL; } + if (fixed_params->nan_scid_len > event->num_ndp_scid) { + WMI_LOGE("FW msg ndp scid info len %d more than TLV hdr %d", + fixed_params->nan_scid_len, + event->num_ndp_scid); + return QDF_STATUS_E_INVAL; + } + if (fixed_params->ndp_cfg_len > (WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_params))) { WMI_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", @@ -922,6 +929,10 @@ static QDF_STATUS extract_ndp_confirm_tlv(wmi_unified_t wmi_handle, WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr, rsp->peer_ndi_mac_addr.bytes); rsp->ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len; + + if (rsp->ndp_info.ndp_app_info_len > NDP_APP_INFO_LEN) + rsp->ndp_info.ndp_app_info_len = NDP_APP_INFO_LEN; + qdf_mem_copy(rsp->ndp_info.ndp_app_info, event->ndp_app_info, rsp->ndp_info.ndp_app_info_len); diff --git a/wmi/src/wmi_unified_roam_tlv.c b/wmi/src/wmi_unified_roam_tlv.c index 851d61875..eba204845 100644 --- a/wmi/src/wmi_unified_roam_tlv.c +++ b/wmi/src/wmi_unified_roam_tlv.c @@ -1550,7 +1550,7 @@ send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, len += WMI_TLV_HDR_SIZE; len += NUM_OF_ROAM_TRIGGERS * sizeof(*score_delta_param); len += WMI_TLV_HDR_SIZE; - len += NUM_OF_ROAM_TRIGGERS * sizeof(*min_rssi_param); + len += NUM_OF_ROAM_MIN_RSSI * sizeof(*min_rssi_param); buf = wmi_buf_alloc(wmi_handle, len); if (!buf) { return QDF_STATUS_E_NOMEM; @@ -1743,7 +1743,7 @@ send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, buf_ptr += sizeof(*score_delta_param); WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, - (NUM_OF_ROAM_TRIGGERS * sizeof(*min_rssi_param))); + (NUM_OF_ROAM_MIN_RSSI * sizeof(*min_rssi_param))); buf_ptr += WMI_TLV_HDR_SIZE; min_rssi_param = (wmi_roam_cnd_min_rssi_param *)buf_ptr; @@ -1769,6 +1769,18 @@ send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, min_rssi_param->candidate_min_rssi = ap_profile->min_rssi_params[BMISS_MIN_RSSI].min_rssi; + buf_ptr += sizeof(*min_rssi_param); + min_rssi_param = (wmi_roam_cnd_min_rssi_param *)buf_ptr; + WMITLV_SET_HDR(&min_rssi_param->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_cnd_min_rssi_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_roam_cnd_min_rssi_param)); + trig_reason = + ap_profile->min_rssi_params[MIN_RSSI_2G_TO_5G_ROAM].trigger_reason; + min_rssi_param->roam_trigger_reason = + convert_roam_trigger_reason(trig_reason); + min_rssi_param->candidate_min_rssi = + ap_profile->min_rssi_params[MIN_RSSI_2G_TO_5G_ROAM].min_rssi; + wmi_mtrace(WMI_ROAM_AP_PROFILE, NO_SESSION, 0); status = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_ROAM_AP_PROFILE); diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index a8515e587..bc8bab86e 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -8177,6 +8177,7 @@ QDF_STATUS save_ext_service_bitmap_tlv(wmi_unified_t wmi_handle, void *evt_buf, WMI_SERVICE_AVAILABLE_EVENTID_param_tlvs *param_buf; wmi_service_available_event_fixed_param *ev; struct wmi_soc *soc = wmi_handle->soc; + uint32_t i = 0; param_buf = (WMI_SERVICE_AVAILABLE_EVENTID_param_tlvs *) evt_buf; @@ -8205,6 +8206,29 @@ QDF_STATUS save_ext_service_bitmap_tlv(wmi_unified_t wmi_handle, void *evt_buf, soc->wmi_ext_service_bitmap, (WMI_SERVICE_SEGMENT_BM_SIZE32 * sizeof(uint32_t))); + if (!param_buf->wmi_service_ext_bitmap) { + WMI_LOGD("wmi_service_ext_bitmap not available"); + return QDF_STATUS_SUCCESS; + } + + if (!soc->wmi_ext2_service_bitmap) { + soc->wmi_ext2_service_bitmap = + qdf_mem_malloc(param_buf->num_wmi_service_ext_bitmap * + sizeof(uint32_t)); + if (!soc->wmi_ext2_service_bitmap) + return QDF_STATUS_E_NOMEM; + } + + qdf_mem_copy(soc->wmi_ext2_service_bitmap, + param_buf->wmi_service_ext_bitmap, + (param_buf->num_wmi_service_ext_bitmap * + sizeof(uint32_t))); + + for (i = 0; i < param_buf->num_wmi_service_ext_bitmap; i++) { + WMI_LOGD("wmi_ext2_service_bitmap %u:0x%x", + i, soc->wmi_ext2_service_bitmap[i]); + } + return QDF_STATUS_SUCCESS; } /** @@ -8224,6 +8248,26 @@ static bool is_service_enabled_tlv(wmi_unified_t wmi_handle, return false; } + if (!soc->wmi_ext_service_bitmap) { + WMI_LOGE("WMI service ext bit map is not saved yet"); + return false; + } + + /* if wmi_service_enabled was received with extended2 bitmap, + * use WMI_SERVICE_EXT2_IS_ENABLED to check the services. + */ + if (soc->wmi_ext2_service_bitmap) + return WMI_SERVICE_EXT2_IS_ENABLED(soc->wmi_service_bitmap, + soc->wmi_ext_service_bitmap, + soc->wmi_ext2_service_bitmap, + service_id); + + if (service_id >= WMI_MAX_EXT_SERVICE) { + WMI_LOGE("Service id %d but WMI ext2 service bitmap is NULL", + service_id); + return false; + } + /* if wmi_service_enabled was received with extended bitmap, * use WMI_SERVICE_EXT_IS_ENABLED to check the services. */ @@ -13090,6 +13134,8 @@ static void populate_tlv_service(uint32_t *wmi_service) WMI_SERVICE_PEER_DELETE_NO_PEER_FLUSH_TIDS_CMD; wmi_service[wmi_service_suiteb_roam_support] = WMI_SERVICE_WPA3_SUITEB_ROAM_SUPPORT; + wmi_service[wmi_service_ll_stats_per_chan_rx_tx_time] = + WMI_SERVICE_LL_STATS_PER_CHAN_RX_TX_TIME_SUPPORT; } /** |