From bc3bde34bf2b7fcb71e3396b19f4405eef193d84 Mon Sep 17 00:00:00 2001 From: Min Liu Date: Mon, 25 Mar 2019 11:20:12 +0800 Subject: [PATCH 1/3] qcacmn: Add AP mode support for PMKSA Currently only STA mode is supported in wlan_crypto_set_del_pmksa. For SAE SAP, need to add AP mode support in this API. Change-Id: If45a516713e302b3516d163516263bbcbafeaed2 CRs-Fixed: 2424893 --- umac/cmn_services/crypto/src/wlan_crypto_global_api.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index cbdc095ef5db..39fdf9700e56 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -394,8 +394,11 @@ QDF_STATUS wlan_crypto_set_del_pmksa(struct wlan_objmgr_vdev *vdev, QDF_STATUS status = QDF_STATUS_E_INVAL; struct wlan_crypto_comp_priv *crypto_priv; struct wlan_crypto_params *crypto_params; + enum QDF_OPMODE op_mode; - if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) + op_mode = wlan_vdev_mlme_get_opmode(vdev); + + if (op_mode != QDF_STA_MODE && op_mode != QDF_SAP_MODE) return QDF_STATUS_E_NOSUPPORT; if (!pmksa && set) { From a3bad2b70e5b770edeb592050a0d985e758f2b3b Mon Sep 17 00:00:00 2001 From: Min Liu Date: Mon, 25 Mar 2019 11:48:49 +0800 Subject: [PATCH 2/3] qcacmn: Reject STA with PMF disabled only when PMF is required In wlan_crypto_rsn_info, only need to reject STA with PMF disabled when PMF is required. Change-Id: I7a7d4b2d1a2d44a95d08eb6bfac14540940f0be3 CRs-Fixed: 2424932 --- .../crypto/inc/wlan_crypto_global_api.h | 10 ++++++ .../crypto/src/wlan_crypto_global_api.c | 32 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h index 4010f4b29a5b..43efd71f18de 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h @@ -222,6 +222,16 @@ QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev, */ bool wlan_crypto_vdev_is_pmf_enabled(struct wlan_objmgr_vdev *vdev); +/** + * wlan_crypto_vdev_is_pmf_required - called to check is pmf required in vdev + * @vdev: vdev + * + * This function gets called to check is pmf required or not in vdev. + * + * Return: true or false + */ +bool wlan_crypto_vdev_is_pmf_required(struct wlan_objmgr_vdev *vdev); + /** * wlan_crypto_is_pmf_enabled - called by mgmt txrx to check is pmf enabled * @vdev: vdev diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index 39fdf9700e56..5bc4b007bf4a 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -1645,6 +1645,36 @@ bool wlan_crypto_vdev_is_pmf_enabled(struct wlan_objmgr_vdev *vdev) return false; } + +/** + * wlan_crypto_vdev_is_pmf_required - called to check is pmf required in vdev + * @vdev: vdev + * + * This function gets called to check is pmf required or not in vdev. + * + * Return: true or false + */ +bool wlan_crypto_vdev_is_pmf_required(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_crypto_comp_priv *crypto_priv; + struct wlan_crypto_params *vdev_crypto_params; + + if (!vdev) + return false; + + vdev_crypto_params = wlan_crypto_vdev_get_comp_params(vdev, + &crypto_priv); + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return QDF_STATUS_E_INVAL; + } + + if (vdev_crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED) + return true; + + return false; +} + /** * wlan_crypto_is_pmf_enabled - called by mgmt txrx to check is pmf enabled * @vdev: vdev @@ -2808,7 +2838,7 @@ bool wlan_crypto_rsn_info(struct wlan_objmgr_vdev *vdev, crypto_debug("Key mgmt match failed"); return false; } - if (wlan_crypto_vdev_is_pmf_enabled(vdev) && + if (wlan_crypto_vdev_is_pmf_required(vdev) && !(crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) { crypto_debug("Peer is not PMF capable"); return false; From 5e3af684b5c96854eb6244718ad3712285f7e98c Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Tue, 10 Jul 2018 18:54:41 +0530 Subject: [PATCH 3/3] qcacmn: Add support to cache peer capability info Currently capability information and RX multicast broadcast packet count of the connected peer is not getting cached. Add support to cache the capability info from assoc request and RX multicast broadcast packets from FW. Change-Id: I105e055b1e440852e8e6b508c25e45f79db2d062 CRs-Fixed: 2409521 --- os_if/linux/qca_vendor.h | 5 +- .../cp_stats/src/target_if_mc_cp_stats.c | 50 ++++++- umac/cp_stats/core/src/wlan_cp_stats_defs.h | 2 + .../dispatcher/inc/wlan_cp_stats_mc_defs.h | 26 ++++ .../dispatcher/src/wlan_cp_stats_mc_tgt_api.c | 124 +++++++++++++++++- .../src/wlan_cp_stats_mc_ucfg_api.c | 15 ++- wmi/inc/wmi_unified_param.h | 11 +- wmi/src/wmi_unified_tlv.c | 34 +++++ 8 files changed, 256 insertions(+), 11 deletions(-) diff --git a/os_if/linux/qca_vendor.h b/os_if/linux/qca_vendor.h index fe2e783a2a81..ef9db55aa4a1 100644 --- a/os_if/linux/qca_vendor.h +++ b/os_if/linux/qca_vendor.h @@ -770,9 +770,10 @@ enum qca_wlan_vendor_attr_get_station_info { QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_STBC, QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH, QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD, -#endif + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_RETRY_COUNT, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BC_MC_COUNT, + /* keep last */ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_MAX = diff --git a/target_if/cp_stats/src/target_if_mc_cp_stats.c b/target_if/cp_stats/src/target_if_mc_cp_stats.c index 6886b3051720..c91f50ae737c 100644 --- a/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/target_if/cp_stats/src/target_if_mc_cp_stats.c @@ -43,6 +43,8 @@ static void target_if_cp_stats_free_stats_event(struct stats_event *ev) ev->peer_stats = NULL; qdf_mem_free(ev->peer_adv_stats); ev->peer_adv_stats = NULL; + qdf_mem_free(ev->peer_extended_stats); + ev->peer_extended_stats = NULL; qdf_mem_free(ev->cca_stats); ev->cca_stats = NULL; qdf_mem_free(ev->vdev_summary_stats); @@ -86,6 +88,43 @@ static QDF_STATUS target_if_cp_stats_extract_pdev_stats( return QDF_STATUS_SUCCESS; } +static void target_if_cp_stats_extract_peer_extd_stats( + struct wmi_unified *wmi_hdl, + wmi_host_stats_event *stats_param, + struct stats_event *ev, + uint8_t *data) + +{ + QDF_STATUS status; + uint32_t i; + wmi_host_peer_extd_stats peer_extd_stats; + + if (!stats_param->num_peer_extd_stats) + return; + + ev->peer_extended_stats = + qdf_mem_malloc(sizeof(*ev->peer_extended_stats) * + stats_param->num_peer_extd_stats); + if (!ev->peer_extended_stats) + return; + + ev->num_peer_extd_stats = stats_param->num_peer_extd_stats; + + for (i = 0; i < ev->num_peer_extd_stats; i++) { + status = wmi_extract_peer_extd_stats(wmi_hdl, data, i, + &peer_extd_stats); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("wmi_extract_peer_extd_stats failed"); + continue; + } + WMI_MAC_ADDR_TO_CHAR_ARRAY( + &peer_extd_stats.peer_macaddr, + ev->peer_extended_stats[i].peer_macaddr); + ev->peer_extended_stats[i].rx_mc_bc_cnt = + peer_extd_stats.rx_mc_bc_cnt; + } +} + static QDF_STATUS target_if_cp_stats_extract_peer_stats( struct wmi_unified *wmi_hdl, wmi_host_stats_event *stats_param, @@ -99,14 +138,14 @@ static QDF_STATUS target_if_cp_stats_extract_peer_stats( struct wmi_host_peer_adv_stats *peer_adv_stats; /* Extract peer_stats */ - ev->num_peer_stats = stats_param->num_peer_stats; - if (!ev->num_peer_stats) + if (!stats_param->num_peer_stats) return QDF_STATUS_SUCCESS; ev->peer_stats = qdf_mem_malloc(sizeof(*ev->peer_stats) * - ev->num_peer_stats); + stats_param->num_peer_stats); if (!ev->peer_stats) return QDF_STATUS_E_NOMEM; + ev->num_peer_stats = stats_param->num_peer_stats; db2dbm_enabled = wmi_service_enabled(wmi_hdl, wmi_service_hw_db2dbm_support); @@ -127,6 +166,9 @@ static QDF_STATUS target_if_cp_stats_extract_peer_stats( TGT_NOISE_FLOOR_DBM; } + target_if_cp_stats_extract_peer_extd_stats(wmi_hdl, stats_param, ev, + data); + /* Extract peer_adv_stats */ ev->num_peer_adv_stats = stats_param->num_peer_adv_stats; if (!ev->num_peer_adv_stats) @@ -540,7 +582,7 @@ static uint32_t get_stats_id(enum stats_req_type type) case TYPE_CONNECTION_TX_POWER: return WMI_REQUEST_PDEV_STAT; case TYPE_PEER_STATS: - return WMI_REQUEST_PEER_STAT; + return WMI_REQUEST_PEER_STAT | WMI_REQUEST_PEER_EXTD_STAT; case TYPE_STATION_STATS: return (WMI_REQUEST_AP_STAT | WMI_REQUEST_PEER_STAT | diff --git a/umac/cp_stats/core/src/wlan_cp_stats_defs.h b/umac/cp_stats/core/src/wlan_cp_stats_defs.h index dcad1b24f1ad..4381cfa687f0 100644 --- a/umac/cp_stats/core/src/wlan_cp_stats_defs.h +++ b/umac/cp_stats/core/src/wlan_cp_stats_defs.h @@ -88,6 +88,7 @@ struct vdev_cp_stats { * @peer_obj: pointer to peer * @peer_stats: pointer to ic/mc specific stats * @peer_adv_stats: pointer to peer adv stats + * @peer_extd_stats: Pointer to peer extended stats * @peer_comp_priv_obj[]: component's private object pointers * @peer_cp_stats_lock: lock to protect object */ @@ -95,6 +96,7 @@ struct peer_cp_stats { struct wlan_objmgr_peer *peer_obj; void *peer_stats; void *peer_adv_stats; + void *peer_extd_stats; void *peer_comp_priv_obj[WLAN_CP_STATS_MAX_COMPONENTS]; qdf_spinlock_t peer_cp_stats_lock; }; diff --git a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h index b5138e808dea..357b86244ec5 100644 --- a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h +++ b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h @@ -237,6 +237,28 @@ struct vdev_mc_cp_stats { struct summary_stats vdev_summary_stats; }; +/** + * struct peer_extd_stats - Peer extension statistics + * @peer_macaddr: peer MAC address + * @rx_duration: lower 32 bits of rx duration in microseconds + * @peer_tx_bytes: Total TX bytes (including dot11 header) sent to peer + * @peer_rx_bytes: Total RX bytes (including dot11 header) received from peer + * @last_tx_rate_code: last TX ratecode + * @last_tx_power: TX power used by peer - units are 0.5 dBm + * @rx_mc_bc_cnt: Total number of received multicast & broadcast data frames + * corresponding to this peer, 1 in the MSB of rx_mc_bc_cnt represents a + * valid data + */ +struct peer_extd_stats { + uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE]; + uint32_t rx_duration; + uint32_t peer_tx_bytes; + uint32_t peer_rx_bytes; + uint32_t last_tx_rate_code; + int32_t last_tx_power; + uint32_t rx_mc_bc_cnt; +}; + /** * struct peer_mc_cp_stats - peer specific stats * @tx_rate: tx rate @@ -303,6 +325,8 @@ struct chain_rssi_event { * @peer_stats: if populated array indicating peer stats * @peer_adv_stats: if populated, indicates peer adv (extd2) stats * @num_peer_adv_stats: number of peer adv (extd2) stats + * @num_peer_extd_stats: Num peer extended stats + * @peer_extended_stats: Peer extended stats * @cca_stats: if populated indicates congestion stats * @num_summary_stats: number of summary stats * @vdev_summary_stats: if populated indicates array of summary stats per vdev @@ -320,6 +344,8 @@ struct stats_event { struct peer_mc_cp_stats *peer_stats; uint32_t num_peer_adv_stats; struct peer_adv_mc_cp_stats *peer_adv_stats; + uint32_t num_peer_extd_stats; + struct peer_extd_stats *peer_extended_stats; struct congestion_stats_event *cca_stats; uint32_t num_summary_stats; struct summary_stats_event *vdev_summary_stats; diff --git a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c index 03dcc7463401..edad12c386d0 100644 --- a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c +++ b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c @@ -115,6 +115,7 @@ static void peer_rssi_iterator(struct wlan_objmgr_pdev *pdev, struct stats_event *ev; struct peer_mc_cp_stats *peer_mc_stats; struct peer_cp_stats *peer_cp_stats_priv; + struct peer_extd_stats *peer_extd_mc_stats; if (WLAN_PEER_SELF == wlan_peer_get_peer_type(peer)) { cp_stats_err("ignore self peer: %pM", @@ -133,6 +134,10 @@ static void peer_rssi_iterator(struct wlan_objmgr_pdev *pdev, ev = arg; ev->peer_stats[ev->num_peer_stats] = *peer_mc_stats; ev->num_peer_stats++; + + peer_extd_mc_stats = peer_cp_stats_priv->peer_extd_stats; + ev->peer_extended_stats[ev->num_peer_extd_stats] = *peer_extd_mc_stats; + ev->num_peer_extd_stats++; wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); } @@ -147,6 +152,7 @@ tgt_mc_cp_stats_prepare_raw_peer_rssi(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_peer *peer = NULL; struct peer_mc_cp_stats *peer_mc_stats; + struct peer_extd_stats *peer_mc_extd_stats; struct peer_cp_stats *peer_cp_stats_priv; void (*get_peer_rssi_cb)(struct stats_event *ev, void *cookie); @@ -172,6 +178,12 @@ tgt_mc_cp_stats_prepare_raw_peer_rssi(struct wlan_objmgr_psoc *psoc, if (!ev.peer_stats) goto end; + ev.peer_extended_stats = + qdf_mem_malloc(sizeof(*ev.peer_extended_stats) * + peer_count); + if (!ev.peer_extended_stats) + goto end; + wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_PEER_OP, peer_rssi_iterator, &ev, true, WLAN_CP_STATS_ID); @@ -194,9 +206,20 @@ tgt_mc_cp_stats_prepare_raw_peer_rssi(struct wlan_objmgr_psoc *psoc, goto end; ev.num_peer_stats = 1; + + ev.peer_extended_stats = + qdf_mem_malloc(sizeof(*ev.peer_extended_stats)); + if (!ev.peer_extended_stats) + goto end; + + ev.num_peer_extd_stats = 1; + wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv); peer_mc_stats = peer_cp_stats_priv->peer_stats; *ev.peer_stats = *peer_mc_stats; + + peer_mc_extd_stats = peer_cp_stats_priv->peer_extd_stats; + *ev.peer_extended_stats = *peer_mc_extd_stats; wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); } @@ -299,8 +322,7 @@ tgt_mc_cp_stats_update_peer_stats(struct wlan_objmgr_psoc *psoc, peer_mc_stats->rx_rate = peer_stats->rx_rate; if (peer_stats->peer_rssi) peer_mc_stats->peer_rssi = peer_stats->peer_rssi; - - cp_stats_debug("peer_mac=%pM, tx_rate=%u, rx_rate=%u, peer_rssi=%u", + cp_stats_debug("peer_mac=%pM, tx_rate=%u, rx_rate=%u, peer_rssi=%d", peer_mc_stats->peer_macaddr, peer_mc_stats->tx_rate, peer_mc_stats->rx_rate, peer_mc_stats->peer_rssi); wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); @@ -312,6 +334,103 @@ end: return status; } +static QDF_STATUS +tgt_mc_cp_stats_update_peer_extd_stats( + struct wlan_objmgr_psoc *psoc, + struct peer_extd_stats *peer_extended_stats) +{ + uint8_t *peer_mac_addr; + struct wlan_objmgr_peer *peer; + struct peer_extd_stats *peer_extd_mc_stats; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct peer_cp_stats *peer_cp_stats_priv; + + if (!peer_extended_stats) + return QDF_STATUS_E_INVAL; + + peer_mac_addr = peer_extended_stats->peer_macaddr; + peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac_addr, + WLAN_CP_STATS_ID); + if (!peer) { + cp_stats_err("peer is null"); + return QDF_STATUS_E_EXISTS; + } + + peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer); + if (!peer_cp_stats_priv) { + cp_stats_err("peer_cp_stats_priv is null"); + status = QDF_STATUS_E_EXISTS; + goto end; + } + + wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv); + peer_extd_mc_stats = peer_cp_stats_priv->peer_extd_stats; + if (!peer_extd_mc_stats) { + wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); + cp_stats_err("No peer_extd_mc_stats"); + status = QDF_STATUS_E_INVAL; + goto end; + } + qdf_mem_copy(peer_extd_mc_stats->peer_macaddr, + peer_extended_stats->peer_macaddr, + QDF_MAC_ADDR_SIZE); + if (peer_extended_stats->rx_mc_bc_cnt) + peer_extd_mc_stats->rx_mc_bc_cnt = + peer_extended_stats->rx_mc_bc_cnt; + wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); + + cp_stats_debug("peer_mac=%pM, rx_mc_bc_cnt=%u", + peer_extended_stats->peer_macaddr, + peer_extended_stats->rx_mc_bc_cnt); + +end: + wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); + + return status; +} + +static void tgt_mc_cp_stats_extract_peer_extd_stats( + struct wlan_objmgr_psoc *psoc, + struct stats_event *ev) +{ + uint32_t i, selected; + QDF_STATUS status; + struct request_info last_req = {0}; + + status = ucfg_mc_cp_stats_get_pending_req(psoc, + TYPE_PEER_STATS, + &last_req); + + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed"); + return; + } + + selected = ev->num_peer_extd_stats; + for (i = 0; i < ev->num_peer_extd_stats; i++) { + status = tgt_mc_cp_stats_update_peer_extd_stats( + psoc, + &ev->peer_extended_stats[i]); + if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) && + !qdf_mem_cmp(ev->peer_stats[i].peer_macaddr, + last_req.peer_mac_addr, + QDF_MAC_ADDR_SIZE)) { + /* mac is specified, but failed to update the peer */ + if (QDF_IS_STATUS_ERROR(status)) + return; + + selected = i; + } + } + + /* no matched peer */ + if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) && + selected == ev->num_peer_extd_stats) { + cp_stats_err("peer not found stats"); + return; + } +} + static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc, struct stats_event *ev, bool is_station_stats) @@ -397,6 +516,7 @@ complete: if (is_station_stats) return; + tgt_mc_cp_stats_extract_peer_extd_stats(psoc, ev); tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req); ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS); } diff --git a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c index def4b8c95615..409c4d8d087c 100644 --- a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c +++ b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c @@ -88,10 +88,19 @@ QDF_STATUS wlan_cp_stats_peer_cs_init(struct peer_cp_stats *peer_cs) peer_cs->peer_adv_stats = qdf_mem_malloc(sizeof (struct peer_adv_mc_cp_stats)); if (!peer_cs->peer_adv_stats) { - cp_stats_err("malloc failed"); qdf_mem_free(peer_cs->peer_stats); return QDF_STATUS_E_NOMEM; } + + peer_cs->peer_extd_stats = + qdf_mem_malloc(sizeof(struct peer_extd_stats)); + if (!peer_cs->peer_extd_stats) { + qdf_mem_free(peer_cs->peer_stats); + peer_cs->peer_stats = NULL; + qdf_mem_free(peer_cs->peer_adv_stats); + peer_cs->peer_adv_stats = NULL; + return QDF_STATUS_E_NOMEM; + } return QDF_STATUS_SUCCESS; } @@ -99,8 +108,11 @@ QDF_STATUS wlan_cp_stats_peer_cs_deinit(struct peer_cp_stats *peer_cs) { qdf_mem_free(peer_cs->peer_adv_stats); peer_cs->peer_adv_stats = NULL; + qdf_mem_free(peer_cs->peer_extd_stats); + peer_cs->peer_extd_stats = NULL; qdf_mem_free(peer_cs->peer_stats); peer_cs->peer_stats = NULL; + return QDF_STATUS_SUCCESS; } @@ -568,6 +580,7 @@ void ucfg_mc_cp_stats_free_stats_resources(struct stats_event *ev) qdf_mem_free(ev->cca_stats); qdf_mem_free(ev->vdev_summary_stats); qdf_mem_free(ev->vdev_chain_rssi); + qdf_mem_free(ev->peer_extended_stats); qdf_mem_zero(ev, sizeof(*ev)); } diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index daf37a880ecf..69df9b04a118 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -4083,6 +4083,8 @@ struct rx_reorder_queue_remove_params { * @num_pdev_ext_stats: number of pdev ext stats event structures * @num_vdev_stats: number of vdev stats * @num_peer_stats: number of peer stats event structures 0 or max peers + * @num_peer_extd_stats: number of peer extended stats event structures 0 + * or max peers * @num_bcnflt_stats: number of beacon filter stats * @num_chan_stats: number of channel stats * @pdev_id: device id for the radio @@ -4097,6 +4099,7 @@ typedef struct { uint32_t num_pdev_ext_stats; uint32_t num_vdev_stats; uint32_t num_peer_stats; + uint32_t num_peer_extd_stats; uint32_t num_bcnflt_stats; uint32_t num_chan_stats; uint32_t pdev_id; @@ -4119,7 +4122,10 @@ typedef struct { * @atf_tokens_utilized: atf tokens utilized * @num_mu_tx_blacklisted: Blacklisted MU Tx count * @sgi_count: sgi count of the peer - * @reserved: for future use + * @rx_mc_bc_cnt: Total number of received multicast & broadcast data frames + * corresponding to this peer, 1 in the MSB of rx_mc_bc_cnt represents a + * valid data + * @rx_retry_cnt: Number of rx retries received from current station */ typedef struct { wmi_host_mac_addr peer_macaddr; @@ -4133,7 +4139,8 @@ typedef struct { uint32_t atf_tokens_utilized; uint32_t num_mu_tx_blacklisted; uint32_t sgi_count; - uint32_t reserved[2]; + uint32_t rx_mc_bc_cnt; + uint32_t rx_retry_cnt; } wmi_host_peer_extd_stats; /** diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 2ed7493a8b62..433238246d58 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -8341,6 +8341,9 @@ static QDF_STATUS extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, case WMI_REQUEST_BCN_STAT: stats_param->stats_id |= WMI_HOST_REQUEST_BCN_STAT; break; + case WMI_REQUEST_PEER_EXTD_STAT: + stats_param->stats_id |= WMI_REQUEST_PEER_EXTD_STAT; + break; case WMI_REQUEST_PEER_EXTD2_STAT: stats_param->stats_id |= WMI_HOST_REQUEST_PEER_ADV_STATS; @@ -8377,6 +8380,7 @@ static QDF_STATUS extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, stats_param->num_pdev_ext_stats = 0; stats_param->num_vdev_stats = ev->num_vdev_stats; stats_param->num_peer_stats = ev->num_peer_stats; + stats_param->num_peer_extd_stats = ev->num_peer_extd_stats; stats_param->num_bcnflt_stats = ev->num_bcnflt_stats; stats_param->num_chan_stats = ev->num_chan_stats; stats_param->num_bcn_stats = ev->num_bcn_stats; @@ -8821,7 +8825,37 @@ static QDF_STATUS extract_peer_extd_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index, wmi_host_peer_extd_stats *peer_extd_stats) { + WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; + wmi_stats_event_fixed_param *ev_param; + uint8_t *data; + + param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf; + ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param; + data = (uint8_t *)param_buf->data; + if (!data) + return QDF_STATUS_E_FAILURE; + + if (index < ev_param->num_peer_extd_stats) { + wmi_peer_extd_stats *ev = (wmi_peer_extd_stats *) (data + + (ev_param->num_pdev_stats * sizeof(wmi_pdev_stats)) + + (ev_param->num_vdev_stats * sizeof(wmi_vdev_stats)) + + (ev_param->num_peer_stats * sizeof(wmi_peer_stats)) + + (ev_param->num_bcnflt_stats * + sizeof(wmi_bcnfilter_stats_t)) + + (ev_param->num_chan_stats * sizeof(wmi_chan_stats)) + + (ev_param->num_mib_stats * sizeof(wmi_mib_stats)) + + (ev_param->num_bcn_stats * sizeof(wmi_bcn_stats)) + + (index * sizeof(wmi_peer_extd_stats))); + + qdf_mem_zero(peer_extd_stats, sizeof(wmi_host_peer_extd_stats)); + qdf_mem_copy(&peer_extd_stats->peer_macaddr, &ev->peer_macaddr, + sizeof(wmi_mac_addr)); + + peer_extd_stats->rx_mc_bc_cnt = ev->rx_mc_bc_cnt; + } + return QDF_STATUS_SUCCESS; + } /**