diff --git a/os_if/linux/cp_stats/inc/wlan_cfg80211_mc_cp_stats.h b/os_if/linux/cp_stats/inc/wlan_cfg80211_mc_cp_stats.h index 40fcd481ee..bcc1b5f211 100644 --- a/os_if/linux/cp_stats/inc/wlan_cfg80211_mc_cp_stats.h +++ b/os_if/linux/cp_stats/inc/wlan_cfg80211_mc_cp_stats.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2019 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 @@ -52,6 +52,21 @@ int wlan_cfg80211_mc_cp_stats_get_wakelock_stats(struct wlan_objmgr_psoc *psoc, */ int wlan_cfg80211_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, int *dbm); +#ifdef WLAN_FEATURE_MIB_STATS +/** + * wlan_cfg80211_mc_cp_stats_get_mib_stats() - API to get mib stats + * statistics from firmware + * @vdev: Pointer to vdev + * @errno: error type in case of failure + * + * Callers of this API must call wlan_cfg80211_mc_cp_stats_free_stats_event + * API. + * Return: stats buffer on success, Null on failure + */ +struct stats_event * +wlan_cfg80211_mc_cp_stats_get_mib_stats(struct wlan_objmgr_vdev *vdev, + int *errno); +#endif /** * wlan_cfg80211_mc_cp_stats_get_station_stats() - API to get station diff --git a/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c index 32a10b54d5..818689fc3b 100644 --- a/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c +++ b/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c @@ -32,6 +32,24 @@ /* max time in ms, caller may wait for stats request get serviced */ #define CP_STATS_WAIT_TIME_STAT 800 +#ifdef WLAN_FEATURE_MIB_STATS +/** + * wlan_free_mib_stats() - free allocations for mib stats + * @stats: Pointer to stats event statucture + * + * Return: None + */ +static void wlan_free_mib_stats(struct stats_event *stats) +{ + qdf_mem_free(stats->mib_stats); + stats->mib_stats = NULL; +} +#else +static void wlan_free_mib_stats(struct stats_event *stats) +{ +} +#endif + /** * wlan_cfg80211_mc_cp_stats_dealloc() - callback to free priv * allocations for stats @@ -56,6 +74,7 @@ static void wlan_cfg80211_mc_cp_stats_dealloc(void *priv) qdf_mem_free(stats->vdev_summary_stats); qdf_mem_free(stats->vdev_chain_rssi); qdf_mem_free(stats->peer_adv_stats); + wlan_free_mib_stats(stats); osif_debug("Exit"); } @@ -581,6 +600,125 @@ get_station_stats_fail: return NULL; } +#ifdef WLAN_FEATURE_MIB_STATS +/** + * get_mib_stats_cb() - get mib stats from fw callback function + * @ev: mib stats buffer + * @cookie: a cookie for the request context + * + * Return: None + */ +static void get_mib_stats_cb(struct stats_event *ev, void *cookie) +{ + struct stats_event *priv; + struct osif_request *request; + + request = osif_request_get(cookie); + if (!request) { + osif_err("Obsolete request"); + return; + } + + priv = osif_request_priv(request); + + priv->mib_stats = qdf_mem_malloc(sizeof(*ev->mib_stats)); + if (!priv->mib_stats) + goto get_mib_stats_cb_fail; + + priv->num_mib_stats = ev->num_mib_stats; + qdf_mem_copy(priv->mib_stats, ev->mib_stats, sizeof(*ev->mib_stats)); + +get_mib_stats_cb_fail: + osif_request_complete(request); + osif_request_put(request); +} + +struct stats_event * +wlan_cfg80211_mc_cp_stats_get_mib_stats(struct wlan_objmgr_vdev *vdev, + int *errno) +{ + void *cookie; + QDF_STATUS status; + struct stats_event *priv, *out; + struct wlan_objmgr_peer *peer; + struct osif_request *request; + struct request_info info = {0}; + static const struct osif_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT, + .dealloc = wlan_cfg80211_mc_cp_stats_dealloc, + }; + + out = qdf_mem_malloc(sizeof(*out)); + if (!out) { + *errno = -ENOMEM; + return NULL; + } + + request = osif_request_alloc(¶ms); + if (!request) { + qdf_mem_free(out); + *errno = -ENOMEM; + return NULL; + } + + cookie = osif_request_cookie(request); + priv = osif_request_priv(request); + info.cookie = cookie; + info.u.get_mib_stats_cb = get_mib_stats_cb; + info.vdev_id = wlan_vdev_get_id(vdev); + info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)); + peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID); + if (!peer) { + osif_err("peer is null"); + *errno = -EINVAL; + goto get_mib_stats_fail; + } + qdf_mem_copy(info.peer_mac_addr, peer->macaddr, QDF_MAC_ADDR_SIZE); + + osif_debug("vdev id %d, pdev id %d, peer " QDF_MAC_ADDR_STR, + info.vdev_id, info.pdev_id, + QDF_MAC_ADDR_ARRAY(info.peer_mac_addr)); + + wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); + + status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_MIB_STATS, + &info); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("Failed to send stats request status: %d", status); + *errno = qdf_status_to_os_return(status); + goto get_mib_stats_fail; + } + + *errno = osif_request_wait_for_response(request); + if (*errno) { + osif_err("wait failed or timed out ret: %d", *errno); + goto get_mib_stats_fail; + } + + if (!priv->mib_stats || priv->num_mib_stats == 0 ) { + osif_err("Invalid mib stats %d:%pK", + priv->num_mib_stats, priv->mib_stats); + *errno = -EINVAL; + goto get_mib_stats_fail; + } + + out->num_mib_stats = priv->num_mib_stats; + out->mib_stats = priv->mib_stats; + priv->mib_stats = NULL; + + osif_request_put(request); + + return out; + +get_mib_stats_fail: + osif_request_put(request); + wlan_cfg80211_mc_cp_stats_free_stats_event(out); + + return NULL; +} +#endif + void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats) { if (!stats) @@ -592,5 +730,6 @@ void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats) qdf_mem_free(stats->vdev_summary_stats); qdf_mem_free(stats->vdev_chain_rssi); qdf_mem_free(stats->peer_adv_stats); + wlan_free_mib_stats(stats); qdf_mem_free(stats); } 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 794ddc5746..b22b89f384 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 @@ -35,6 +35,17 @@ #include #include "../../../umac/cmn_services/utils/inc/wlan_utility.h" +#ifdef WLAN_FEATURE_MIB_STATS +static void target_if_cp_stats_free_mib_stats(struct stats_event *ev) +{ + qdf_mem_free(ev->mib_stats); + ev->mib_stats = NULL; +} +#else +static void target_if_cp_stats_free_mib_stats(struct stats_event *ev) +{ +} +#endif static void target_if_cp_stats_free_stats_event(struct stats_event *ev) { qdf_mem_free(ev->pdev_stats); @@ -51,6 +62,7 @@ static void target_if_cp_stats_free_stats_event(struct stats_event *ev) ev->vdev_summary_stats = NULL; qdf_mem_free(ev->vdev_chain_rssi); ev->vdev_chain_rssi = NULL; + target_if_cp_stats_free_mib_stats(ev); } static QDF_STATUS target_if_cp_stats_extract_pdev_stats( @@ -232,6 +244,51 @@ static QDF_STATUS target_if_cp_stats_extract_cca_stats( return QDF_STATUS_SUCCESS; } +#ifdef WLAN_FEATURE_MIB_STATS +static QDF_STATUS target_if_cp_stats_extract_mib_stats( + struct wmi_unified *wmi_hdl, + wmi_host_stats_event *stats_param, + struct stats_event *ev, uint8_t *data) +{ + QDF_STATUS status; + + if (!stats_param->num_mib_stats) { + cp_stats_debug("no mib stats"); + return QDF_STATUS_SUCCESS; + } + if (stats_param->num_mib_stats != MAX_MIB_STATS || + (stats_param->num_mib_extd_stats && + stats_param->num_mib_extd_stats != MAX_MIB_STATS)) { + cp_stats_err("number of mib stats wrong, num_mib_stats %d, num_mib_extd_stats %d", + stats_param->num_mib_stats, + stats_param->num_mib_extd_stats); + return QDF_STATUS_E_INVAL; + } + + ev->num_mib_stats = stats_param->num_mib_stats; + + ev->mib_stats = qdf_mem_malloc(sizeof(*ev->mib_stats)); + if (!ev->mib_stats) + return QDF_STATUS_E_NOMEM; + + status = wmi_extract_mib_stats(wmi_hdl, data, ev->mib_stats); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("wmi_extract_mib_stats failed"); + return status; + } + + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS target_if_cp_stats_extract_mib_stats( + struct wmi_unified *wmi_hdl, + wmi_host_stats_event *stats_param, + struct stats_event *ev, uint8_t *data) +{ + return QDF_STATUS_SUCCESS; +} +#endif + static QDF_STATUS target_if_cp_stats_extract_vdev_summary_stats( struct wmi_unified *wmi_hdl, wmi_host_stats_event *stats_param, @@ -358,9 +415,11 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl, cp_stats_err("stats param extract failed: %d", status); return status; } - cp_stats_debug("num: pdev: %d, vdev: %d, peer: %d, rssi: %d", + cp_stats_debug("num: pdev: %d, vdev: %d, peer: %d, rssi: %d, mib %d, mib_extd %d", stats_param.num_pdev_stats, stats_param.num_vdev_stats, - stats_param.num_peer_stats, stats_param.num_rssi_stats); + stats_param.num_peer_stats, stats_param.num_rssi_stats, + stats_param.num_mib_stats, + stats_param.num_mib_extd_stats); ev->last_event = stats_param.last_event; status = target_if_cp_stats_extract_pdev_stats(wmi_hdl, &stats_param, @@ -390,6 +449,12 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl, if (QDF_IS_STATUS_ERROR(status)) return status; + status = target_if_cp_stats_extract_mib_stats(wmi_hdl, + &stats_param, + ev, data); + if (QDF_IS_STATUS_ERROR(status)) + return status; + return QDF_STATUS_SUCCESS; } @@ -591,6 +656,8 @@ static uint32_t get_stats_id(enum stats_req_type type) WMI_REQUEST_PDEV_STAT | WMI_REQUEST_PEER_EXTD2_STAT | WMI_REQUEST_RSSI_PER_CHAIN_STAT); + case TYPE_MIB_STATS: + return (WMI_REQUEST_MIB_STAT | WMI_REQUEST_MIB_EXTD_STAT); } return 0; 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 602054f581..8a53bf3e62 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 @@ -33,6 +33,8 @@ #define MAX_NUM_CHAINS 2 +#define MAX_MIB_STATS 1 + #define IS_MSB_SET(__num) ((__num) & BIT(31)) #define IS_LSB_SET(__num) ((__num) & BIT(0)) @@ -42,11 +44,13 @@ * @TYPE_CONNECTION_TX_POWER: tx power was requested * @TYPE_STATION_STATS: station stats was requested * @TYPE_PEER_STATS: peer stats was requested + * @TYPE_MIB_STATS: MIB stats was requested */ enum stats_req_type { TYPE_CONNECTION_TX_POWER = 0, TYPE_STATION_STATS, TYPE_PEER_STATS, + TYPE_MIB_STATS, TYPE_MAX, }; @@ -153,7 +157,8 @@ struct stats_event; /** * struct request_info: details of each request * @cookie: identifier for os_if request - * @callback: callback to process os_if request when response comes. + * @u: unified data type for callback to process tx power/peer rssi/ + * station stats/mib stats request when response comes. * @vdev_id: vdev_id of request * @pdev_id: pdev_id of request * @peer_mac_addr: peer mac address @@ -165,6 +170,8 @@ struct request_info { void (*get_peer_rssi_cb)(struct stats_event *ev, void *cookie); void (*get_station_stats_cb)(struct stats_event *ev, void *cookie); + void (*get_mib_stats_cb)(struct stats_event *ev, + void *cookie); } u; uint32_t vdev_id; uint32_t pdev_id; @@ -313,6 +320,137 @@ struct peer_adv_mc_cp_stats { uint64_t rx_bytes; }; +#ifdef WLAN_FEATURE_MIB_STATS +/** + * struct dot11_counters - mib group containing attributes that are MAC counters + * @tx_frags: successfully transmitted fragments + * @group_tx_frames: transmitted group addressed frames + * @failed_cnt: MSDUs not transmitted successfully + * @rx_frags: fragments successfully received + * @group_rx_frames: group addressed frames received + * @fcs_error_cnt: FCS errors detected + * @tx_frames: frames successfully transmitted + */ +struct dot11_counters { + uint32_t tx_frags; + uint32_t group_tx_frames; + uint32_t failed_cnt; + uint32_t rx_frags; + uint32_t group_rx_frames; + uint32_t fcs_error_cnt; + uint32_t tx_frames; +}; + +/** + * struct dot11_mac_statistics - mib stats information on the operation of MAC + * @retry_cnt: retries done by mac for successful transmition + * @multi_retry_cnt: multiple retries done before successful transmition + * @frame_dup_cnt: duplicate no of frames + * @rts_success_cnt: number of CTS received (in response to RTS) + * @rts_fail_cnt: number of CTS not received (in response to RTS) + * @tx_ack_fail_cnt: number of ACK not received + */ +struct dot11_mac_statistics { + uint32_t retry_cnt; + uint32_t multi_retry_cnt; + uint32_t frame_dup_cnt; + uint32_t rts_success_cnt; + uint32_t rts_fail_cnt; + uint32_t tx_ack_fail_cnt; +}; + +/** + * dot11_qos_counters - qos mac counters + * @qos_tx_frag_cnt: transmitted QoS fragments + * @qos_failed_cnt: failed Qos fragments + * @qos_retry_cnt: Qos frames transmitted after retransmissions + * @qos_multi_retry_cnt: Qos frames transmitted after more than + * one retransmissions + * @qos_frame_dup_cnt: duplicate frames + * @qos_rts_success_cnt: number of CTS received (in response to RTS) + * @qos_rts_fail_cnt: number of CTS not received (in response to RTS) + * @tx_qos_ack_fail_cnt_up: number of ACK not received + * (in response to Qos frame) + * @qos_rx_frag_cnt: number of received MPDU of type Data + * @qos_tx_frame_cnt: number of transmitted MPDU of type Data + * @qos_discarded_frame_cnt: total Discarded MSDUs + * @qos_mpdu_rx_cnt: total received MPDU + * @qos_retries_rx_cnt: received MPDU with retry bit equal to 1 + */ +struct dot11_qos_counters { + uint32_t qos_tx_frag_cnt; + uint32_t qos_failed_cnt; + uint32_t qos_retry_cnt; + uint32_t qos_multi_retry_cnt; + uint32_t qos_frame_dup_cnt; + uint32_t qos_rts_success_cnt; + uint32_t qos_rts_fail_cnt; + uint32_t tx_qos_ack_fail_cnt_up; + uint32_t qos_rx_frag_cnt; + uint32_t qos_tx_frame_cnt; + uint32_t qos_discarded_frame_cnt; + uint32_t qos_mpdu_rx_cnt; + uint32_t qos_retries_rx_cnt; +}; + +/** + * dot11_rsna_stats - mib rsn stats + * @rm_ccmp_replays: received robust management CCMP MPDUs discarded + * by the replay mechanism + * @tkip_icv_err: TKIP ICV errors encountered + * @tkip_replays: TKIP replay errors detected + * @ccmp_decrypt_err: MPDUs discarded by the CCMP decryption algorithm + * @ccmp_replays: received CCMP MPDUs discarded by the replay mechanism + * @cmac_icv_err: MPDUs discarded by the CMAC integrity check algorithm + * @cmac_replays: MPDUs discarded by the CMAC replay errors + */ +struct dot11_rsna_stats { + uint32_t rm_ccmp_replays; + uint32_t tkip_icv_err; + uint32_t tkip_replays; + uint32_t ccmp_decrypt_err; + uint32_t ccmp_replays; + uint32_t cmac_icv_err; + uint32_t cmac_replays; +}; + +/** + * dot11_counters_group3 - dot11 group3 stats + * @tx_ampdu_cnt: transmitted AMPDUs + * @tx_mpdus_in_ampdu_cnt: number of MPDUs in the A-MPDU in transmitted AMPDUs + * @tx_octets_in_ampdu_cnt: octets in the transmitted A-MPDUs + * @ampdu_rx_cnt: received A-MPDU + * @mpdu_in_rx_ampdu_cnt: MPDUs received in the A-MPDU + * @rx_octets_in_ampdu_cnt: octets in the received A-MPDU + * @rx_ampdu_deli_crc_err_cnt: number of MPDUs delimiter with CRC error + */ +struct dot11_counters_group3 { + uint32_t tx_ampdu_cnt; + uint32_t tx_mpdus_in_ampdu_cnt; + uint64_t tx_octets_in_ampdu_cnt; + uint32_t ampdu_rx_cnt; + uint32_t mpdu_in_rx_ampdu_cnt; + uint64_t rx_octets_in_ampdu_cnt; + uint32_t rx_ampdu_deli_crc_err_cnt; +}; + +/** + * mib_stats_metrics - mib stats counters + * @mib_counters: dot11Counters group + * @mib_mac_statistics: dot11MACStatistics group + * @mib_qos_counters: dot11QoSCounters group + * @mib_rsna_stats: dot11RSNAStats group + * @mib_counters_group3: dot11CountersGroup3 group + */ +struct mib_stats_metrics { + struct dot11_counters mib_counters; + struct dot11_mac_statistics mib_mac_statistics; + struct dot11_qos_counters mib_qos_counters; + struct dot11_rsna_stats mib_rsna_stats; + struct dot11_counters_group3 mib_counters_group3; +}; +#endif + /** * struct congestion_stats_event: congestion stats event param * @vdev_id: vdev_id of the event @@ -356,6 +494,8 @@ struct chain_rssi_event { * @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 + * @num_mib_stats: number of mib stats + * @mib_stats: if populated indicates array of mib stats per vdev * @num_chain_rssi_stats: number of chain rssi stats * @vdev_chain_rssi: if populated indicates array of chain rssi per vdev * @tx_rate: tx rate (kbps) @@ -375,6 +515,10 @@ struct stats_event { struct congestion_stats_event *cca_stats; uint32_t num_summary_stats; struct summary_stats_event *vdev_summary_stats; +#ifdef WLAN_FEATURE_MIB_STATS + uint32_t num_mib_stats; + struct mib_stats_metrics *mib_stats; +#endif uint32_t num_chain_rssi_stats; struct chain_rssi_event *vdev_chain_rssi; uint32_t tx_rate; 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 f121991577..e1fb014a4c 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 @@ -549,6 +549,39 @@ complete: } } +#ifdef WLAN_FEATURE_MIB_STATS +static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc, + struct stats_event *ev) +{ + QDF_STATUS status; + struct request_info last_req = {0}; + + if (!ev->mib_stats) { + cp_stats_debug("no mib stats"); + return; + } + + status = ucfg_mc_cp_stats_get_pending_req(psoc, + TYPE_MIB_STATS, &last_req); + + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed"); + return; + } + + if (tgt_mc_cp_stats_is_last_event(ev, TYPE_MIB_STATS)) { + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_MIB_STATS); + if (last_req.u.get_mib_stats_cb) + last_req.u.get_mib_stats_cb(ev, last_req.cookie); + } +} +#else +static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc, + struct stats_event *ev) +{ +} +#endif + static void tgt_mc_cp_stats_extract_cca_stats(struct wlan_objmgr_psoc *psoc, struct stats_event *ev) { @@ -877,6 +910,9 @@ QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc, if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_STATION_STATS)) tgt_mc_cp_stats_extract_station_stats(psoc, ev); + if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_MIB_STATS)) + tgt_mc_cp_stats_extract_mib_stats(psoc, ev); + tgt_mc_cp_stats_extract_cca_stats(psoc, ev); tgt_mc_cp_send_lost_link_stats(psoc, ev); diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index ec34cabf29..98f77f2e08 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -2828,6 +2828,19 @@ QDF_STATUS wmi_extract_per_chain_rssi_stats( uint32_t index, struct wmi_host_per_chain_rssi_stats *rssi_stats); +#ifdef WLAN_FEATURE_MIB_STATS +/** + * wmi_extract_mib_stats() - extract mib stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @mib_stats: pointer to hold mib stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_mib_stats(wmi_unified_t wmi_handle, void *evt_buf, + struct mib_stats_metrics *mib_stats); +#endif + /** * wmi_extract_vdev_extd_stats() - extract extended vdev stats from event * @wmi_handle: wmi handle diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 649f5800b0..254e0029f2 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -3801,6 +3801,8 @@ struct rx_reorder_queue_remove_params { * @num_bcn_stats: number of beacon stats * @num_rssi_stats: number of rssi stats * @num_peer_adv_stats: number of peer adv stats + * @num_mib_stats: number of mib stats + * @num_mib_extd_stats: number of extended mib stats * @last_event: specify if the current event is the last event */ typedef struct { @@ -3816,6 +3818,8 @@ typedef struct { uint32_t num_bcn_stats; uint32_t num_rssi_stats; uint32_t num_peer_adv_stats; + uint32_t num_mib_stats; + uint32_t num_mib_extd_stats; uint32_t last_event; } wmi_host_stats_event; diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 2ed0dcc777..a487cd2b9e 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -1592,6 +1592,11 @@ QDF_STATUS (*extract_peer_adv_stats)(wmi_unified_t wmi_handle, void *evt_buf, QDF_STATUS (*extract_chan_stats)(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index, wmi_host_chan_stats *chan_stats); +#ifdef WLAN_FEATURE_MIB_STATS +QDF_STATUS (*extract_mib_stats)(wmi_unified_t wmi_handle, void *evt_buf, + struct mib_stats_metrics *mib_stats); +#endif + QDF_STATUS (*extract_thermal_stats)(wmi_unified_t wmi_handle, void *evt_buf, uint32_t *temp, uint32_t *level, uint32_t *pdev_id); diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index cc0e3488a6..160fcf18b3 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -2178,6 +2178,19 @@ wmi_extract_chan_stats(wmi_unified_t wmi_handle, void *evt_buf, return QDF_STATUS_E_FAILURE; } +#ifdef WLAN_FEATURE_MIB_STATS +QDF_STATUS wmi_extract_mib_stats(wmi_unified_t wmi_handle, void *evt_buf, + struct mib_stats_metrics *mib_stats) +{ + if (wmi_handle->ops->extract_mib_stats) + return wmi_handle->ops->extract_mib_stats(wmi_handle, + evt_buf, + mib_stats); + + return QDF_STATUS_E_FAILURE; +} +#endif + QDF_STATUS wmi_extract_thermal_stats(wmi_unified_t wmi_handle, void *evt_buf, uint32_t *temp, uint32_t *level, uint32_t *pdev_id) diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 59677f39f9..f0f4f32c3c 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -9019,7 +9019,9 @@ static QDF_STATUS extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, (((uint64_t)ev->num_mib_stats) * sizeof(wmi_mib_stats)) + (((uint64_t)ev->num_bcn_stats) * sizeof(wmi_bcn_stats)) + (((uint64_t)ev->num_peer_extd_stats) * - sizeof(wmi_peer_extd_stats)); + sizeof(wmi_peer_extd_stats)) + + (((uint64_t)ev->num_mib_extd_stats) * + sizeof(wmi_mib_extd_stats)); if (param_buf->num_data != min_data_len) { WMI_LOGE("data len: %u isn't same as calculated: %llu", param_buf->num_data, min_data_len); @@ -9034,6 +9036,8 @@ static QDF_STATUS extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, 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_mib_stats = ev->num_mib_stats; + stats_param->num_mib_extd_stats = ev->num_mib_extd_stats; stats_param->num_bcn_stats = ev->num_bcn_stats; stats_param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host( wmi_handle, @@ -9549,6 +9553,144 @@ static QDF_STATUS extract_chan_stats_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_SUCCESS; } +#ifdef WLAN_FEATURE_MIB_STATS +/** + * extract_mib_stats_tlv() - extract mib stats from event + * @wmi_handle: wmi handle + * @param evt_buf: pointer to event buffer + * @param mib_stats: pointer to hold mib stats + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +static QDF_STATUS extract_mib_stats_tlv(wmi_unified_t wmi_handle, + void *evt_buf, + struct mib_stats_metrics + *mib_stats) +{ + WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; + wmi_stats_event_fixed_param *ev_param; + uint8_t *data; + wmi_mib_stats *ev; + wmi_mib_extd_stats *ev_extd; + + 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; + + ev = (wmi_mib_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)); + + qdf_mem_zero(mib_stats, sizeof(*mib_stats)); + + mib_stats->mib_counters.tx_frags = + ev->tx_mpdu_grp_frag_cnt; + mib_stats->mib_counters.group_tx_frames = + ev->tx_msdu_grp_frm_cnt; + mib_stats->mib_counters.failed_cnt = ev->tx_msdu_fail_cnt; + mib_stats->mib_counters.rx_frags = ev->rx_mpdu_frag_cnt; + mib_stats->mib_counters.group_rx_frames = + ev->rx_msdu_grp_frm_cnt; + mib_stats->mib_counters.fcs_error_cnt = + ev->rx_mpdu_fcs_err; + mib_stats->mib_counters.tx_frames = + ev->tx_msdu_frm_cnt; + mib_stats->mib_mac_statistics.retry_cnt = + ev->tx_msdu_retry_cnt; + mib_stats->mib_mac_statistics.frame_dup_cnt = + ev->rx_frm_dup_cnt; + mib_stats->mib_mac_statistics.rts_success_cnt = + ev->tx_rts_success_cnt; + mib_stats->mib_mac_statistics.rts_fail_cnt = + ev->tx_rts_fail_cnt; + + mib_stats->mib_qos_counters.qos_tx_frag_cnt = + ev->tx_Qos_mpdu_grp_frag_cnt; + mib_stats->mib_qos_counters.qos_retry_cnt = + ev->tx_Qos_msdu_retry_UP; + mib_stats->mib_qos_counters.qos_failed_cnt = + ev->tx_Qos_msdu_fail_UP; + mib_stats->mib_qos_counters.qos_frame_dup_cnt = + ev->rx_Qos_frm_dup_cnt_UP; + mib_stats->mib_qos_counters.qos_rts_success_cnt = + ev->tx_Qos_rts_success_cnt_UP; + mib_stats->mib_qos_counters.qos_rts_fail_cnt = + ev->tx_Qos_rts_fail_cnt_UP; + mib_stats->mib_qos_counters.qos_rx_frag_cnt = + ev->rx_Qos_mpdu_frag_cnt_UP; + mib_stats->mib_qos_counters.qos_tx_frame_cnt = + ev->tx_Qos_msdu_frm_cnt_UP; + mib_stats->mib_qos_counters.qos_discarded_frame_cnt = + ev->rx_Qos_msdu_discard_cnt_UP; + mib_stats->mib_qos_counters.qos_mpdu_rx_cnt = + ev->rx_Qos_mpdu_cnt; + mib_stats->mib_qos_counters.qos_retries_rx_cnt = + ev->rx_Qos_mpdu_retryBit_cnt; + + mib_stats->mib_rsna_stats.tkip_icv_err = + ev->rsna_TKIP_icv_err_cnt; + mib_stats->mib_rsna_stats.tkip_replays = + ev->rsna_TKIP_replay_err_cnt; + mib_stats->mib_rsna_stats.ccmp_decrypt_err = + ev->rsna_CCMP_decrypt_err_cnt; + mib_stats->mib_rsna_stats.ccmp_replays = + ev->rsna_CCMP_replay_err_cnt; + + mib_stats->mib_counters_group3.tx_ampdu_cnt = + ev->tx_ampdu_cnt; + mib_stats->mib_counters_group3.tx_mpdus_in_ampdu_cnt = + ev->tx_mpdu_cnt_in_ampdu; + mib_stats->mib_counters_group3.tx_octets_in_ampdu_cnt = + ev->tx_octets_in_ampdu.upload.high; + mib_stats->mib_counters_group3.tx_octets_in_ampdu_cnt = + mib_stats->mib_counters_group3.tx_octets_in_ampdu_cnt << 32; + mib_stats->mib_counters_group3.tx_octets_in_ampdu_cnt += + ev->tx_octets_in_ampdu.upload.low; + + mib_stats->mib_counters_group3.ampdu_rx_cnt = + ev->rx_ampdu_cnt; + mib_stats->mib_counters_group3.mpdu_in_rx_ampdu_cnt = + ev->rx_mpdu_cnt_in_ampdu; + mib_stats->mib_counters_group3.rx_octets_in_ampdu_cnt = + ev->rx_octets_in_ampdu.upload.rx_octets_in_ampdu_high; + mib_stats->mib_counters_group3.rx_octets_in_ampdu_cnt = + mib_stats->mib_counters_group3.rx_octets_in_ampdu_cnt << 32; + mib_stats->mib_counters_group3.rx_octets_in_ampdu_cnt += + ev->rx_octets_in_ampdu.upload.rx_octets_in_ampdu_low; + + if (ev_param->num_mib_extd_stats) { + ev_extd = (wmi_mib_extd_stats *)((uint8_t *)ev + + ev_param->num_mib_stats * sizeof(wmi_mib_stats) + + ev_param->num_bcn_stats * sizeof(wmi_bcn_stats) + + ev_param->num_peer_extd_stats * + sizeof(wmi_peer_extd_stats)); + mib_stats->mib_mac_statistics.multi_retry_cnt = + ev_extd->tx_msdu_multi_retry_cnt; + mib_stats->mib_mac_statistics.tx_ack_fail_cnt = + ev_extd->tx_ack_fail_cnt; + + mib_stats->mib_qos_counters.qos_multi_retry_cnt = + ev_extd->tx_qos_msdu_multi_retry_up; + mib_stats->mib_qos_counters.tx_qos_ack_fail_cnt_up = + ev_extd->tx_qos_ack_fail_cnt_up; + + mib_stats->mib_rsna_stats.cmac_icv_err = + ev_extd->rsna_cmac_icv_err_cnt; + mib_stats->mib_rsna_stats.cmac_replays = + ev_extd->rsna_cmac_replay_err_cnt; + + mib_stats->mib_counters_group3.rx_ampdu_deli_crc_err_cnt = + ev_extd->rx_ampdu_deli_crc_err_cnt; + } + + return QDF_STATUS_SUCCESS; +} +#endif + /** * extract_profile_ctx_tlv() - extract profile context from event * @wmi_handle: wmi handle @@ -12453,6 +12595,9 @@ struct wmi_ops tlv_ops = { .extract_peer_extd_stats = extract_peer_extd_stats_tlv, .extract_peer_adv_stats = extract_peer_adv_stats_tlv, .extract_chan_stats = extract_chan_stats_tlv, +#ifdef WLAN_FEATURE_MIB_STATS + .extract_mib_stats = extract_mib_stats_tlv, +#endif .extract_profile_ctx = extract_profile_ctx_tlv, .extract_profile_data = extract_profile_data_tlv, .send_fw_test_cmd = send_fw_test_cmd_tlv,