summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhang Qian <zhangq@codeaurora.org>2016-10-21 11:40:45 +0800
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-11-11 19:44:23 +0530
commitcab730d29ded331721d23229f02506ab3cef2d8e (patch)
tree4a278bdfb43faab22d5d515ec1980d7e5850c344
parentdea8b6c6f53e5e262a0d2c127021c5dd44b4fc1b (diff)
qcacld-2.0: Add MAC counter WMI interface
When MAC counter offload is enabled, FW will indicate following statistics periodically or as host's settings. - RSSI and SNR per antenna/RF chain - RSSI, SNR and MCS code (Tx and Rx) per peer - 11h, 11k radio measurements on current channel, CSMA/CA parameters, channel interference estimations - Tx/Rx statistics(data rate, aggregation size, etc) New WMI interface is introduced by this change: - set threshold using WMI_PDEV_SET_STATS_THRESHOLD_CMDID - process WMI_REPORT_STATS_EVENTID and send all mac counters to HDD_CFG80211 Change-Id: I6d679bbf331baf187cccc882216eecc239bf298c CRs-Fixed: 1080673
-rw-r--r--CORE/MAC/inc/sirApi.h435
-rw-r--r--CORE/MAC/src/include/sirParams.h3
-rw-r--r--CORE/SERVICES/WMA/wma.c668
-rw-r--r--CORE/SME/inc/sme_Api.h3
-rw-r--r--CORE/SME/src/sme_common/sme_Api.c46
-rw-r--r--CORE/WDA/inc/wlan_qct_wda.h1
6 files changed, 1155 insertions, 1 deletions
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 6c4d8c1eab0f..fcc86e61115e 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -6215,6 +6215,441 @@ struct sir_wifi_iface_tx_fail {
uint32_t status;
};
+/**
+ * struct sir_wifi_chan_cca_stats - channal CCA stats
+ * @vdev_id: vdev ID
+ * @idle_time: percentage of idle time, no TX, no RX, no interference
+ * @tx_time: percentage of time transmitting packets
+ * @rx_in_bss_time: percentage of time receiving packets in current BSS
+ * @rx_out_bss_time: percentage of time receiving packets not in current BSS
+ * @rx_busy_time: percentage of time interference detected
+ * @rx_in_bad_cond_time: percentage of time receiving packets with errors
+ * or packets flagged as retransmission or seqnum discontinued.
+ * @tx_in_bad_cond_time: percentage of time the device transmitted packets
+ * that haven't been ACKed.
+ * @wlan_not_avail_time: percentage of time the chip is unable to
+ * work in normal conditions.
+ */
+struct sir_wifi_chan_cca_stats {
+ uint32_t vdev_id;
+ uint32_t idle_time;
+ uint32_t tx_time;
+ uint32_t rx_in_bss_time;
+ uint32_t rx_out_bss_time;
+ uint32_t rx_busy_time;
+ uint32_t rx_in_bad_cond_time;
+ uint32_t tx_in_bad_cond_time;
+ uint32_t wlan_not_avail_time;
+};
+
+#define WIFI_MAX_CHAINS 8
+
+/**
+ * struct sir_wifi_peer_signal_stats - peer signal stats
+ * @vdev_id: vdev ID
+ * @peer_id: peer ID
+ * @per_ant_snr: per antenna SNR
+ * @nf: peer background noise
+ */
+struct sir_wifi_peer_signal_stats {
+ uint32_t vdev_id;
+ uint32_t peer_id;
+
+ /* per antenna SNR in current bss */
+ int32_t per_ant_snr[WIFI_MAX_CHAINS];
+
+ /* Background noise */
+ int32_t nf[WIFI_MAX_CHAINS];
+};
+
+#define WIFI_VDEV_NUM 4
+#define WFIF_MCS_NUM 10
+#define WIFI_AGGR_NUM 8
+#define WIFI_DELAY_SIZE 11
+
+/**
+ * struct sir_wifi_tx - per AC tx stats
+ * @mpdus: number of totoal TX packets on MAC layer in the period
+ * @bytes: bytes of tx data on MAC layer in the period
+ * @drops: number of TX packets cancelled due to any reason in the period,
+ * such as WMM limitation/bandwidth limitation/radio congestion
+ * @drop_bytes: bytes of dropped TX packets in the period
+ * @retries: number of unacked transmissions of MPDUs
+ * @failed: number of packets have not been ACKed despite retried
+ * @aggr_len: length of the MPDU aggregation size buffer
+ * @mpdu_aggr_size: histogram of MPDU aggregation size
+ * @success_mcs_len: length of success mcs buffer
+ * @success_mcs: histogram of successed received MPDUs encoding rate
+ * @fail_mcs_len: length of failed mcs buffer
+ * @fail_mcs: histogram of failed received MPDUs encoding rate
+ * @delay_len: length of the delay histofram buffer
+ * @delay: histogram of delays on MAC layer
+ */
+struct sir_wifi_tx {
+ uint32_t mpdus;
+ uint32_t bytes;
+ uint32_t drops;
+ uint32_t drop_bytes;
+ uint32_t retries;
+ uint32_t failed;
+ uint32_t aggr_len;
+ uint32_t *mpdu_aggr_size;
+ uint32_t success_mcs_len;
+ uint32_t *success_mcs;
+ uint32_t fail_mcs_len;
+ uint32_t *fail_mcs;
+ uint32_t delay_len;
+ uint32_t *delay;
+};
+
+/**
+ * struct sir_wifi_rx - per AC rx stats
+ * @mpdus: number of RX packets on MAC layer
+ * @bytes: bytes of RX packets on MAC layer
+ * @ppdus: number of RX packets on PHY layer
+ * @ppdu_bytes: bytes of RX packets on PHY layer
+ * @mpdu_lost: number of discontinuity in seqnum
+ * @mpdu_retry: number of RX packets flagged as retransmissions
+ * @mpdu_dup: number of RX packets identified as duplicates
+ * @mpdu_discard: number of RX packets discarded
+ * @sta_ps_inds: how many times STAs go to sleep
+ * @sta_ps_durs: total sleep time of STAs
+ * @probe_reqs: number of probe requests received
+ * @mgmts: number of management frames received, no probe requests
+ * @aggr_len: length of MPDU aggregation histogram buffer
+ * @mpdu_aggr: histogram of MPDU aggregation size
+ * @mcs_len: length of mcs histogram buffer
+ * @mcs: histogram of encoding rate.
+ */
+struct sir_wifi_rx {
+ uint32_t mpdus;
+ uint32_t bytes;
+ uint32_t ppdus;
+ uint32_t ppdu_bytes;
+ uint32_t mpdu_lost;
+ uint32_t mpdu_retry;
+ uint32_t mpdu_dup;
+ uint32_t mpdu_discard;
+ uint32_t sta_ps_inds;
+ uint32_t sta_ps_durs;
+ uint32_t probe_reqs;
+ uint32_t mgmts;
+ uint32_t aggr_len;
+ uint32_t *mpdu_aggr;
+ uint32_t mcs_len;
+ uint32_t *mcs;
+};
+
+/**
+ * struct sir_wifi_ll_ext_wmm_ac_stats - stats for WMM AC
+ * @type: WMM AC type
+ * @tx_stats: pointer to TX stats
+ * @rx_stats: pointer to RX stats
+ */
+struct sir_wifi_ll_ext_wmm_ac_stats {
+ uint32_t type;
+ struct sir_wifi_tx *tx_stats;
+ struct sir_wifi_rx *rx_stats;
+};
+
+#define WIFI_INVALID_PEER_ID (-1)
+#define WIFI_INVALID_VDEV_ID (-1)
+#define WIFI_MAX_AC (4)
+
+/**
+ * struct sir_wifi_ll_ext_peer_stats - per peer stats
+ * @peer_id: peer ID
+ * @vdev_id: VDEV ID
+ * @peer_signal_stat: signal stats
+ * @be_stats: WMM BE stats
+ * @bk_stats: WMM BK stats
+ * @vi_stats: WMM VI stats
+ * @vo_stats: WMM VO stats
+ */
+struct sir_wifi_ll_ext_peer_stats {
+ uint32_t peer_id;
+ uint32_t vdev_id;
+ struct sir_wifi_peer_signal_stats peer_signal_stats;
+ struct sir_wifi_ll_ext_wmm_ac_stats ac_stats[WIFI_MAX_AC];
+};
+
+/**
+ * struct sir_wifi_ll_ext_stats - link layer stats report
+ * @trigger_cond_id: Indicate what triggered this event.
+ * 1: timeout. 2: threshold
+ * @cca_chgd_bitmap: Bitmap to indicate changed channel CCA stats
+ * which exceeded the thresholds
+ * @sig_chgd_bitmap: Bitmap to indicate changed peer signal stats
+ * which exceeded the thresholds
+ * @tx_chgd_bitmap: Bitmap to indicate changed TX counters
+ * which exceeded the thresholds
+ * @rx_chgd_bitmap: Bitmap to indicate changed RX counters
+ * which exceeded the thresholds
+ * @chan_cca_stats: channel CCA stats
+ * @peer_signal_stats: peer signal stats
+ * @tx_mpdu_aggr_array_len: length of TX MPDU aggregation buffer
+ * @tx_succ_mcs_array_len: length of mcs buffer for ACKed MPDUs
+ * @tx_fail_mcs_array_len: length of mcs buffer for no-ACKed MPDUs
+ * @tx_delay_array_len: length of delay stats buffer
+ * @rx_mpdu_aggr_array_len: length of RX MPDU aggregation buffer
+ * @rx_mcs_array_len: length of RX mcs stats buffer
+ * @peer_stats: peer stats
+ * @cca: physical channel CCA stats
+ * @stats: pointer to stats data buffer.
+ *
+ * Structure of the whole statictics is like this:
+ * ---------------------------------
+ * | trigger_cond_i |
+ * +-------------------------------+
+ * | cca_chgd_bitmap |
+ * +-------------------------------+
+ * | sig_chgd_bitmap |
+ * +-------------------------------+
+ * | tx_chgd_bitmap |
+ * +-------------------------------+
+ * | rx_chgd_bitmap |
+ * +-------------------------------+
+ * | peer_num |
+ * +-------------------------------+
+ * | channel_num |
+ * +-------------------------------+
+ * | tx_mpdu_aggr_array_len |
+ * +-------------------------------+
+ * | tx_succ_mcs_array_len |
+ * +-------------------------------+
+ * | tx_fail_mcs_array_len |
+ * +-------------------------------+
+ * | tx_delay_array_len |
+ * +-------------------------------+
+ * | rx_mpdu_aggr_array_len |
+ * +-------------------------------+
+ * | rx_mcs_array_len |
+ * +-------------------------------+
+ * | pointer to CCA stats |
+ * +-------------------------------+
+ * | pointer to peer stats |
+ * +-------------------------------+
+ * | CCA stats |
+ * +-------------------------------+
+ * | peer_stats |----+
+ * +-------------------------------+ |
+ * | per peer signals stats |<---+
+ * | peer0 ~ peern | |
+ * +-------------------------------+ |
+ * | TX aggr/mcs parameters array | |
+ * | Length of this buffer is | |
+ * | configurable for user layer. |<-+ |
+ * +-------------------------------+ | |
+ * | per peer tx stats |--+ |
+ * | BE | <--+
+ * | BK | |
+ * | VI | |
+ * | VO | |
+ * +-------------------------------+ |
+ * | TX aggr/mcs parameters array | |
+ * | Length of this buffer is | |
+ * | configurable for user layer. |<-+ |
+ * +-------------------------------+ | |
+ * | peer peer rx stats |--+ |
+ * | BE | <--+
+ * | BE |
+ * | BK |
+ * | VI |
+ * | VO |
+ * ---------------------------------
+ */
+struct sir_wifi_ll_ext_stats {
+ uint32_t trigger_cond_id;
+ uint32_t cca_chgd_bitmap;
+ uint32_t sig_chgd_bitmap;
+ uint32_t tx_chgd_bitmap;
+ uint32_t rx_chgd_bitmap;
+ uint8_t peer_num;
+ uint8_t channel_num;
+ uint32_t tx_mpdu_aggr_array_len;
+ uint32_t tx_succ_mcs_array_len;
+ uint32_t tx_fail_mcs_array_len;
+ uint32_t tx_delay_array_len;
+ uint32_t rx_mpdu_aggr_array_len;
+ uint32_t rx_mcs_array_len;
+ struct sir_wifi_ll_ext_peer_stats *peer_stats;
+ struct sir_wifi_chan_cca_stats *cca;
+ uint8_t stats[];
+};
+
+/**
+ * struct sir_channel_cca_threshold - threshold for channel CCA
+ * @idle_time: idle time, no TX, no RX, no interference
+ * @tx_time: time transmitting packets
+ * @rx_in_bss_time: time receiving packets in current BSSs
+ * @rx_out_bss_time: time receiving packets not in current BSSs
+ * @rx_busy_time: time interference detected
+ * @rx_in_bad_cond_time: receiving packets with errors
+ * @tx_in_bad_cond_time: time transmitted packets not been ACKed
+ * @wlan_not_avail_time: wlan card cannot work
+ */
+struct sir_channel_cca_threshold {
+ uint32_t idle_time;
+ uint32_t tx_time;
+ uint32_t rx_in_bss_time;
+ uint32_t rx_out_bss_time;
+ uint32_t rx_busy_time;
+ uint32_t rx_in_bad_cond_time;
+ uint32_t tx_in_bad_cond_time;
+ uint32_t wlan_not_avail_time;
+};
+
+/**
+ * struct sir_signal_threshold - threshold for per peer sigbal
+ * @snr: signal to noise rate
+ * @nf: noise floor
+ */
+struct sir_signal_threshold {
+ uint32_t snr;
+ uint32_t nf;
+};
+
+/**
+ * struct sir_tx_threshold - threshold for TX
+ * @msdu: TX MSDUs on MAC layer
+ * @mpdu: TX MPDUs on MAC layer
+ * @ppdu: TX PPDUs on MAC layer
+ * @bytes: TX bytes on MAC layer
+ * @msdu_drop: drooped MSDUs
+ * @byte_drop: dropped Bytes
+ * @mpdu_retry: MPDU not acked
+ * @ppdu_fail: PPDUs which received no block ack
+ * @aggregation: aggregation size
+ * @succ_mcs: histogram of encoding rate for acked PPDUs
+ * @fail_mcs: histogram of encoding rate for no-acked PPDUs
+ */
+struct sir_tx_threshold {
+ uint32_t msdu;
+ uint32_t mpdu;
+ uint32_t ppdu;
+ uint32_t bytes;
+ uint32_t msdu_drop;
+ uint32_t byte_drop;
+ uint32_t mpdu_retry;
+ uint32_t mpdu_fail;
+ uint32_t ppdu_fail;
+ uint32_t aggregation;
+ uint32_t succ_mcs;
+ uint32_t fail_mcs;
+ uint32_t delay;
+};
+
+/**
+ * struct sir_rx_threshold - threshold for RX
+ * @mpdu: RX MPDUs on MAC layer
+ * @bytes: RX bytes on MAC layer
+ * @ppdu: RX PPDU on PHY layer
+ * @ppdu_bytes: RX bytes on PHY layer
+ * @disorder: discontinuity in seqnum
+ * @mpdu_retry: MPDUs flagged as retry
+ * @mpdu_dup: MPDUs identified as duplicated
+ * @aggregation: aggregation size
+ * @mcs: histogram of encoding rate for PPDUs
+ * @ps_inds: power save indication
+ * @ps_durs: total time in power save
+ * @probe_reqs: probe request received
+ * @other_mgmt: other MGMT frames received
+ */
+struct sir_rx_threshold {
+ uint32_t mpdu;
+ uint32_t bytes;
+ uint32_t ppdu;
+ uint32_t ppdu_bytes;
+ uint32_t disorder;
+ uint32_t mpdu_lost;
+ uint32_t mpdu_retry;
+ uint32_t mpdu_dup;
+ uint32_t mpdu_discard;
+ uint32_t aggregation;
+ uint32_t mcs;
+ uint32_t ps_inds;
+ uint32_t ps_durs;
+ uint32_t probe_reqs;
+ uint32_t other_mgmt;
+};
+
+/**
+ * struct sir_wifi_ll_ext_stats_threshold - Threshold for stats update
+ * @enable: if threshold mechnism is enabled or disabled
+ * @enable_bitmap: whether dedicated threshold is enabed.
+ * Every MAC counter has a dedicated threshold. If the dedicated
+ * threshold is not set in the bitmap, global threshold will take
+ * effect.
+ * @global: whether clobal threshold is enabled.
+ * When both global and dedicated threshold are diabled, MAC counter
+ * will indicate stats periodically.
+ * @global_threshold: global threshold value
+ * @cca_bitmap: bitmap for CCA.
+ * Bit0: idle time
+ * Bit1: tx time
+ * Bit2: RX in BSS
+ * Bit3: RX out of BSS
+ * Bit4: medium busy
+ * Bit5: RX bad
+ * Bit6: TX bad
+ * Bit7: WLAN card not available
+ * @signal_bitmap:
+ * Bit0: Per channel SNR counter
+ * Bit1: Per channel noise floor counter
+ * @tx_bitmap: bitmap for TX counters
+ * Bit0: TX counter unit in MSDU
+ * Bit1: TX counter unit in MPDU
+ * Bit2: TX counter unit in PPDU
+ * Bit3: TX counter unit in byte
+ * Bit4: Dropped MSDUs
+ * Bit5: Dropped Bytes
+ * Bit6: MPDU retry counter
+ * Bit7: MPDU failure counter
+ * Bit8: PPDU failure counter
+ * Bit9: MPDU aggregation counter
+ * Bit10: MCS counter for ACKed MPDUs
+ * Bit11: MCS counter for Failed MPDUs
+ * Bit12: TX Delay counter
+ * @rx_bitmap:bitmap for RX counters
+ * Bit0: MAC RX counter unit in MPDU
+ * Bit1: MAC RX counter unit in byte
+ * Bit2: PHY RX counter unit in PPDU
+ * Bit3: PHY RX counter unit in byte
+ * Bit4: Disorder counter
+ * Bit5: Retry counter
+ * Bit6: Duplication counter
+ * Bit7: Discard counter
+ * Bit8: MPDU aggregation size counter
+ * Bit9: MCS counter
+ * Bit10: Peer STA power state change (wake to sleep) counter
+ * Bit11: Peer STA power save counter, total time in PS mode
+ * Bit12: Probe request counter
+ * Bit13: Other management frames counter
+ * @cca_thresh: CCA threshold
+ * @signal_thresh: signal threshold
+ * @tx_thresh: TX threshold
+ * @rx_thresh: RX threshold
+ *
+ * Generally, Link layer statistics is reported periodically. But if the
+ * variation of one stats of compared to the pervious notification exceeds
+ * a threshold, FW will report the new stats immediately.
+ * This structure contains threshold for different counters.
+ */
+struct sir_ll_ext_stats_threshold {
+ uint32_t enable;
+ uint32_t enable_bitmap;
+ uint32_t global;
+ uint32_t global_threshold;
+ uint32_t cca_bitmap;
+ uint32_t signal_bitmap;
+ uint32_t tx_bitmap;
+ uint32_t rx_bitmap;
+ struct sir_channel_cca_threshold cca;
+ struct sir_signal_threshold signal;
+ struct sir_tx_threshold tx;
+ struct sir_rx_threshold rx;
+};
+
typedef struct
{
tANI_U32 paramId;
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 571375da133b..620a55c380ac 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -784,6 +784,9 @@ typedef struct sSirMbMsgP2p
#define SIR_HAL_STA_INACTIVITY_TIMEOUT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 365)
#define SIR_HAL_RX_CHN_STATUS_EVENT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 366)
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+#define SIR_HAL_LL_STATS_EXT_SET_THRESHOLD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 367)
+#endif
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
// CFG message types
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index effb4af7b92f..8c4621df724b 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -5033,6 +5033,542 @@ static int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
return 0;
}
+#define WMA_FILL_TX_STATS(eve, msg) do {\
+ (msg)->mpdus = (eve)->tx_mpdu_cnt;\
+ (msg)->bytes = (eve)->tx_bytes;\
+ (msg)->drops = (eve)->tx_msdu_drop_cnt;\
+ (msg)->drop_bytes = (eve)->tx_drop_bytes;\
+ (msg)->retries = (eve)->tx_mpdu_retry_cnt;\
+ (msg)->failed = (eve)->tx_mpdu_fail_cnt;\
+} while (0)
+
+#define WMA_FILL_RX_STATS(eve, msg) do {\
+ (msg)->mpdus = (eve)->mac_rx_mpdu_cnt;\
+ (msg)->bytes = (eve)->mac_rx_bytes;\
+ (msg)->ppdus = (eve)->phy_rx_ppdu_cnt;\
+ (msg)->ppdu_bytes = (eve)->phy_rx_bytes;\
+ (msg)->mpdu_retry = (eve)->rx_mpdu_retry_cnt;\
+ (msg)->mpdu_dup = (eve)->rx_mpdu_dup_cnt;\
+ (msg)->mpdu_discard = (eve)->rx_mpdu_discard_cnt;\
+} while (0)
+
+/**
+ * __wma_get_ll_stats_ext_buf() - alloc result buffer for MAC counters
+ * @len: buffer length output
+ * @peer_num: peer number
+ * @fixed_param: fixed parameters in WMI event
+ *
+ * Structure of the stats message
+ * LL_EXT_STATS
+ * |
+ * |--Channel stats[1~n]
+ * |--Peer[1~n]
+ * |
+ * +---Signal
+ * +---TX
+ * | +---BE
+ * | +---BK
+ * | +---VI
+ * | +---VO
+ * |
+ * +---RX
+ * +---BE
+ * +---BK
+ * +---VI
+ * +---VO
+ * For each Access Category, the arregation and mcs
+ * stats are as this:
+ * TX
+ * +-BE/BK/VI/VO
+ * +----tx_mpdu_aggr_array
+ * +----tx_succ_mcs_array
+ * +----tx_fail_mcs_array
+ * +----tx_delay_array
+ * RX
+ * +-BE/BK/VI/VO
+ * +----rx_mpdu_aggr_array
+ * +----rx_mcs_array
+ *
+ * return: Address for result buffer.
+ */
+static tSirLLStatsResults *__wma_get_ll_stats_ext_buf(uint32_t *len,
+ uint32_t peer_num,
+ wmi_report_stats_event_fixed_param *fixed_param)
+{
+ tSirLLStatsResults *buf;
+ uint32_t buf_len;
+
+ if (!len || !fixed_param) {
+ WMA_LOGE(FL("Invalid input parameters."));
+ return NULL;
+ }
+
+ /*
+ * Result buffer has a structure like this:
+ * ---------------------------------
+ * | trigger_cond_i |
+ * +-------------------------------+
+ * | cca_chgd_bitmap |
+ * +-------------------------------+
+ * | sig_chgd_bitmap |
+ * +-------------------------------+
+ * | tx_chgd_bitmap |
+ * +-------------------------------+
+ * | rx_chgd_bitmap |
+ * +-------------------------------+
+ * | peer_num |
+ * +-------------------------------+
+ * | channel_num |
+ * +-------------------------------+
+ * | tx_mpdu_aggr_array_len |
+ * +-------------------------------+
+ * | tx_succ_mcs_array_len |
+ * +-------------------------------+
+ * | tx_fail_mcs_array_len |
+ * +-------------------------------+
+ * | tx_delay_array_len |
+ * +-------------------------------+
+ * | rx_mpdu_aggr_array_len |
+ * +-------------------------------+
+ * | rx_mcs_array_len |
+ * +-------------------------------+
+ * | pointer to CCA stats |
+ * +-------------------------------+
+ * | CCA stats |
+ * +-------------------------------+
+ * | peer_stats |----+
+ * +-------------------------------+ |
+ * | TX aggr/mcs parameters array | |
+ * | Length of this buffer is | |
+ * | not fixed. |<-+ |
+ * +-------------------------------+ | |
+ * | per peer tx stats |--+ |
+ * | BE | <--+
+ * | BK | |
+ * | VI | |
+ * | VO | |
+ * +-------------------------------+ |
+ * | TX aggr/mcs parameters array | |
+ * | Length of this buffer is | |
+ * | not fixed. |<-+ |
+ * +-------------------------------+ | |
+ * | peer peer rx stats |--+ |
+ * | BE | <--+
+ * | BK |
+ * | VI |
+ * | VO |
+ * ---------------------------------
+ */
+ buf_len = sizeof(tSirLLStatsResults) +
+ sizeof(struct sir_wifi_ll_ext_stats) +
+ fixed_param->num_chan_cca_stats *
+ sizeof(struct sir_wifi_chan_cca_stats) +
+ peer_num *
+ (sizeof(struct sir_wifi_ll_ext_peer_stats) +
+ WLAN_MAX_AC *
+ (sizeof(struct sir_wifi_tx) +
+ sizeof(struct sir_wifi_rx)) +
+ sizeof(uint32_t) * WLAN_MAX_AC *
+ (fixed_param->tx_mpdu_aggr_array_len +
+ fixed_param->tx_succ_mcs_array_len +
+ fixed_param->tx_fail_mcs_array_len +
+ fixed_param->tx_ppdu_delay_array_len +
+ fixed_param->rx_mpdu_aggr_array_len +
+ fixed_param->rx_mcs_array_len));
+
+ buf = (tSirLLStatsResults *)vos_mem_malloc(buf_len);
+ if (buf == NULL) {
+ WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
+ buf_len = 0;
+ return NULL;
+ }
+
+ vos_mem_zero(buf, buf_len);
+ *len = buf_len;
+ return buf;
+}
+
+/**
+ * __wma_fill_tx_stats() - Fix TX stats into result buffer
+ * @ll_stats: LL stats buffer
+ * @fix_param: parameters with fixed length in WMI event
+ * @param_buf: parameters without fixed length in WMI event
+ * @buf: buffer for TLV parameters
+ */
+static void __wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
+ wmi_report_stats_event_fixed_param *fix_param,
+ WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
+ uint8_t **buf,
+ uint32_t *buf_length)
+{
+ uint8_t *result;
+ uint32_t i, j, k;
+ wmi_peer_ac_tx_stats *wmi_peer_tx;
+ wmi_tx_stats *wmi_tx;
+ struct sir_wifi_tx *tx_stats;
+ struct sir_wifi_ll_ext_peer_stats *peer_stats;
+ uint32_t *tx_mpdu_aggr, *tx_succ_mcs, *tx_fail_mcs, *tx_delay;
+ uint32_t len, dst_len, tx_mpdu_aggr_array_len, tx_succ_mcs_array_len,
+ tx_fail_mcs_array_len, tx_delay_array_len;
+
+ result = *buf;
+ dst_len = *buf_length;
+ tx_mpdu_aggr_array_len = fix_param->tx_mpdu_aggr_array_len;
+ ll_stats->tx_mpdu_aggr_array_len = tx_mpdu_aggr_array_len;
+ tx_succ_mcs_array_len = fix_param->tx_succ_mcs_array_len;
+ ll_stats->tx_succ_mcs_array_len = tx_succ_mcs_array_len;
+ tx_fail_mcs_array_len = fix_param->tx_fail_mcs_array_len;
+ ll_stats->tx_fail_mcs_array_len = tx_fail_mcs_array_len;
+ tx_delay_array_len = fix_param->tx_ppdu_delay_array_len;
+ ll_stats->tx_delay_array_len = tx_delay_array_len;
+ wmi_peer_tx = param_buf->peer_ac_tx_stats;
+ wmi_tx = param_buf->tx_stats;
+
+ len = fix_param->num_peer_ac_tx_stats *
+ WLAN_MAX_AC * tx_mpdu_aggr_array_len * sizeof(uint32_t);
+ if (len <= dst_len) {
+ tx_mpdu_aggr = (uint32_t *)result;
+ vos_mem_copy(tx_mpdu_aggr, param_buf->tx_mpdu_aggr, len);
+ result += len;
+ dst_len -= len;
+ } else {
+ WMA_LOGE(FL("TX_MPDU_AGGR buffer length is wrong."));
+ tx_mpdu_aggr = NULL;
+ }
+
+ len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
+ tx_succ_mcs_array_len * sizeof(uint32_t);
+ if (len <= dst_len) {
+ tx_succ_mcs = (uint32_t *)result;
+ vos_mem_copy(tx_succ_mcs, param_buf->tx_succ_mcs, len);
+ result += len;
+ dst_len -= len;
+ } else {
+ WMA_LOGE(FL("TX_SUCC_MCS buffer length is wrong."));
+ tx_succ_mcs = NULL;
+ }
+
+ len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
+ tx_fail_mcs_array_len * sizeof(uint32_t);
+ if (len <= dst_len) {
+ tx_fail_mcs = (uint32_t *)result;
+ vos_mem_copy(tx_fail_mcs, param_buf->tx_fail_mcs, len);
+ result += len;
+ dst_len -= len;
+ } else {
+ WMA_LOGE(FL("TX_FAIL_MCS buffer length is wrong."));
+ tx_fail_mcs = NULL;
+ }
+
+ len = fix_param->num_peer_ac_tx_stats *
+ WLAN_MAX_AC * tx_delay_array_len * sizeof(uint32_t);
+ if (len <= dst_len) {
+ tx_delay = (uint32_t *)result;
+ vos_mem_copy(tx_delay, param_buf->tx_ppdu_delay, len);
+ result += len;
+ dst_len -= len;
+ } else {
+ WMA_LOGE(FL("TX_DELAY buffer length is wrong."));
+ tx_delay = NULL;
+ }
+
+ /* per peer tx stats */
+ peer_stats = ll_stats->peer_stats;
+
+ for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) {
+ uint32_t peer_id = wmi_peer_tx[i].peer_id;
+ struct sir_wifi_tx *ac;
+ wmi_tx_stats *wmi_tx_stats;
+
+ for (j = 0; j < ll_stats->peer_num; j++) {
+ peer_stats += j;
+ if (peer_stats->peer_id == WIFI_INVALID_PEER_ID ||
+ peer_stats->peer_id == peer_id)
+ break;
+ }
+
+ if (j < ll_stats->peer_num) {
+ peer_stats->peer_id = wmi_peer_tx[i].peer_id;
+ peer_stats->vdev_id = wmi_peer_tx[i].vdev_id;
+ tx_stats = (struct sir_wifi_tx *)result;
+ for (k = 0; k < WLAN_MAX_AC; k++) {
+ wmi_tx_stats = &wmi_tx[i * WLAN_MAX_AC + k];
+ ac = &tx_stats[k];
+ WMA_FILL_TX_STATS(wmi_tx_stats, ac);
+ ac->mpdu_aggr_size = tx_mpdu_aggr;
+ ac->aggr_len = tx_mpdu_aggr_array_len;
+ ac->success_mcs_len = tx_succ_mcs_array_len;
+ ac->success_mcs = tx_succ_mcs;
+ ac->fail_mcs = tx_fail_mcs;
+ ac->fail_mcs_len = tx_fail_mcs_array_len;
+ ac->delay = tx_delay;
+ ac->delay_len = tx_delay_array_len;
+ peer_stats->ac_stats[k].tx_stats = ac;
+ peer_stats->ac_stats[k].type = k;
+ tx_mpdu_aggr += tx_mpdu_aggr_array_len;
+ tx_succ_mcs += tx_succ_mcs_array_len;
+ tx_fail_mcs += tx_fail_mcs_array_len;
+ tx_delay += tx_delay_array_len;
+ }
+ result += WLAN_MAX_AC * sizeof(struct sir_wifi_tx);
+ } else {
+ /*
+ * Buffer for Peer TX counter overflow.
+ * There is peer ID mismatch between TX, RX,
+ * signal counters.
+ */
+ WMA_LOGE(FL("One peer TX info is dropped."));
+
+ tx_mpdu_aggr += tx_mpdu_aggr_array_len * WLAN_MAX_AC;
+ tx_succ_mcs += tx_succ_mcs_array_len * WLAN_MAX_AC;
+ tx_fail_mcs += tx_fail_mcs_array_len * WLAN_MAX_AC;
+ tx_delay += tx_delay_array_len * WLAN_MAX_AC;
+ }
+ }
+ *buf = result;
+ *buf_length = dst_len;
+}
+
+/**
+ * __wma_fill_rx_stats() - Fix RX stats into result buffer
+ * @ll_stats: LL stats buffer
+ * @fix_param: parameters with fixed length in WMI event
+ * @param_buf: parameters without fixed length in WMI event
+ * @buf: buffer for TLV parameters
+ */
+static void __wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
+ wmi_report_stats_event_fixed_param *fix_param,
+ WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
+ uint8_t **buf,
+ uint32_t *buf_length)
+{
+ uint8 *result;
+ uint32_t i, j, k;
+ uint32_t *rx_mpdu_aggr, *rx_mcs;
+ wmi_rx_stats *wmi_rx;
+ wmi_peer_ac_rx_stats *wmi_peer_rx;
+ struct sir_wifi_rx *rx_stats;
+ struct sir_wifi_ll_ext_peer_stats *peer_stats;
+ uint32_t len, dst_len, rx_mpdu_aggr_array_len, rx_mcs_array_len;
+
+ rx_mpdu_aggr_array_len = fix_param->rx_mpdu_aggr_array_len;
+ ll_stats->rx_mpdu_aggr_array_len = rx_mpdu_aggr_array_len;
+ rx_mcs_array_len = fix_param->rx_mcs_array_len;
+ ll_stats->rx_mcs_array_len = rx_mcs_array_len;
+ wmi_peer_rx = param_buf->peer_ac_rx_stats;
+ wmi_rx = param_buf->rx_stats;
+
+ result = *buf;
+ dst_len = *buf_length;
+ len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
+ WLAN_MAX_AC * rx_mpdu_aggr_array_len);
+ if (len <= dst_len) {
+ rx_mpdu_aggr = (uint32_t *)result;
+ vos_mem_copy(rx_mpdu_aggr, param_buf->rx_mpdu_aggr, len);
+ result += len;
+ dst_len -= len;
+ } else {
+ WMA_LOGE(FL("RX_MPDU_AGGR array length is wrong."));
+ rx_mpdu_aggr = NULL;
+ }
+
+ len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
+ WLAN_MAX_AC * rx_mcs_array_len);
+ if (len <= dst_len) {
+ rx_mcs = (uint32_t *)result;
+ vos_mem_copy(rx_mcs, param_buf->rx_mcs, len);
+ result += len;
+ dst_len -= len;
+ } else {
+ WMA_LOGE(FL("RX_MCS array length is wrong."));
+ rx_mcs = NULL;
+ }
+
+ /* per peer rx stats */
+ peer_stats = ll_stats->peer_stats;
+ 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;
+ wmi_rx_stats *wmi_rx_stats;
+
+ for (j = 0; j < ll_stats->peer_num; j++) {
+ peer_stats += j;
+ if ((peer_stats->peer_id == WIFI_INVALID_PEER_ID) ||
+ (peer_stats->peer_id == peer_id))
+ break;
+ }
+
+ if (j < ll_stats->peer_num) {
+ peer_stats->peer_id = wmi_peer_rx[i].peer_id;
+ peer_stats->vdev_id = wmi_peer_rx[i].vdev_id;
+ rx_stats = (struct sir_wifi_rx *)result;
+
+ for (k = 0; k < WLAN_MAX_AC; k++) {
+ wmi_rx_stats = &wmi_rx[i * WLAN_MAX_AC + k];
+ ac = &rx_stats[k];
+ WMA_FILL_RX_STATS(wmi_rx_stats, ac);
+ ac->mpdu_aggr = rx_mpdu_aggr;
+ ac->aggr_len = rx_mpdu_aggr_array_len;
+ ac->mcs = rx_mcs;
+ ac->mcs_len = rx_mcs_array_len;
+ peer_stats->ac_stats[k].rx_stats = ac;
+ peer_stats->ac_stats[k].type = k;
+ rx_mpdu_aggr += rx_mpdu_aggr_array_len;
+ rx_mcs += rx_mcs_array_len;
+ }
+ result += WLAN_MAX_AC * sizeof(struct sir_wifi_rx);
+ } else {
+ /*
+ * Buffer for Peer RX counter overflow.
+ * There is peer ID mismatch between TX, RX,
+ * signal counters.
+ */
+ WMA_LOGE(FL("One peer RX info is dropped."));
+ rx_mpdu_aggr += rx_mpdu_aggr_array_len * WLAN_MAX_AC;
+ rx_mcs += rx_mcs_array_len * WLAN_MAX_AC;
+ }
+ }
+ *buf = result;
+ *buf_length = dst_len;
+}
+
+/**
+ * wma_ll_stats_evt_handler() - handler for MAC layer counters.
+ * @handle - wma handle
+ * @event - FW event
+ * @len - length of FW event
+ *
+ * return: 0 success.
+ */
+static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event,
+ u_int32_t len)
+{
+ tp_wma_handle wma_handle = (tp_wma_handle) handle;
+ WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf;
+ wmi_report_stats_event_fixed_param *fixed_param;
+ tSirLLStatsResults *link_stats_results;
+ wmi_chan_cca_stats *wmi_cca_stats;
+ wmi_peer_signal_stats *wmi_peer_signal;
+ wmi_peer_ac_rx_stats *wmi_peer_rx;
+ struct sir_wifi_ll_ext_stats *ll_stats;
+ struct sir_wifi_ll_ext_peer_stats *peer_stats;
+ struct sir_wifi_chan_cca_stats *cca_stats;
+ struct sir_wifi_peer_signal_stats *peer_signal;
+ uint8_t *result;
+ uint32_t i, peer_num, result_size, dst_len;
+ tpAniSirGlobal mac;
+ vos_msg_t vos_msg;
+
+ mac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE,
+ wma_handle->vos_context);
+ if (!mac) {
+ WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
+ return -EINVAL;
+ }
+
+ if (!mac->sme.link_layer_stats_ext_cb) {
+ WMA_LOGD("%s: HDD callback is null", __func__);
+ return -EINVAL;
+ }
+
+ WMA_LOGD("%s: Posting MAC counters event to HDD", __func__);
+
+ param_buf = (WMI_REPORT_STATS_EVENTID_param_tlvs *)event;
+ fixed_param = param_buf->fixed_param;
+ wmi_cca_stats = param_buf->chan_cca_stats;
+ wmi_peer_signal = param_buf->peer_signal_stats;
+ wmi_peer_rx = param_buf->peer_ac_rx_stats;
+
+ /* Get the MAX of three peer numbers */
+ peer_num = fixed_param->num_peer_signal_stats >
+ fixed_param->num_peer_ac_tx_stats ?
+ fixed_param->num_peer_signal_stats :
+ fixed_param->num_peer_ac_tx_stats;
+ peer_num = peer_num > fixed_param->num_peer_ac_rx_stats ?
+ peer_num : fixed_param->num_peer_ac_rx_stats;
+
+ if (peer_num == 0)
+ return -EINVAL;
+
+ link_stats_results = __wma_get_ll_stats_ext_buf(&result_size,
+ peer_num,
+ fixed_param);
+ if (!link_stats_results) {
+ WMA_LOGE("%s: Fail to allocate stats buffer", __func__);
+ return -EINVAL;
+ }
+ link_stats_results->paramId = WMI_LL_STATS_EXT_MAC_COUNTER;
+ link_stats_results->num_peers = peer_num;
+ link_stats_results->peer_event_number = 1;
+ link_stats_results->moreResultToFollow = 0;
+
+ ll_stats = (struct sir_wifi_ll_ext_stats *)link_stats_results->results;
+ ll_stats->trigger_cond_id = fixed_param->trigger_cond_id;
+ ll_stats->cca_chgd_bitmap = fixed_param->cca_chgd_bitmap;
+ ll_stats->sig_chgd_bitmap = fixed_param->sig_chgd_bitmap;
+ ll_stats->tx_chgd_bitmap = fixed_param->tx_chgd_bitmap;
+ ll_stats->rx_chgd_bitmap = fixed_param->rx_chgd_bitmap;
+ ll_stats->channel_num = fixed_param->num_chan_cca_stats;
+ ll_stats->peer_num = peer_num;
+
+ result = (uint8_t *)ll_stats->stats;
+ peer_stats = (struct sir_wifi_ll_ext_peer_stats *)result;
+ ll_stats->peer_stats = peer_stats;
+
+ for (i = 0; i < peer_num; i++) {
+ peer_stats[i].peer_id = WIFI_INVALID_PEER_ID;
+ peer_stats[i].vdev_id = WIFI_INVALID_VDEV_ID;
+ }
+
+ /* Per peer signal */
+ result_size -= sizeof(struct sir_wifi_ll_ext_stats);
+ dst_len = sizeof(struct sir_wifi_peer_signal_stats);
+ for (i = 0; i < fixed_param->num_peer_signal_stats; i++) {
+ peer_stats[i].peer_id = wmi_peer_signal->peer_id;
+ peer_stats[i].vdev_id = wmi_peer_signal->vdev_id;
+ peer_signal = &peer_stats[i].peer_signal_stats;
+
+ if (dst_len <= result_size) {
+ vos_mem_copy(peer_signal,
+ &wmi_peer_signal->vdev_id, dst_len);
+ result_size -= dst_len;
+ } else {
+ WMA_LOGE(FL("Invalid length of PEER signal."));
+ }
+ }
+
+ result += peer_num * sizeof(struct sir_wifi_ll_ext_peer_stats);
+ cca_stats = (struct sir_wifi_chan_cca_stats *)result;
+ ll_stats->cca = cca_stats;
+ dst_len = sizeof(struct sir_wifi_chan_cca_stats);
+ for (i = 0; i < ll_stats->channel_num; i++) {
+ if (dst_len <= result_size) {
+ vos_mem_copy(&cca_stats[i], &wmi_cca_stats->vdev_id,
+ dst_len);
+ result_size -= dst_len;
+ } else {
+ WMA_LOGE(FL("Invalid length of CCA."));
+ }
+ }
+
+ result += i * sizeof(struct sir_wifi_chan_cca_stats);
+ __wma_fill_tx_stats(ll_stats, fixed_param, param_buf,
+ &result, &result_size);
+ __wma_fill_rx_stats(ll_stats, fixed_param, param_buf,
+ &result, &result_size);
+ vos_msg.type = eWMI_SME_LL_STATS_IND;
+ vos_msg.bodyptr = (void *)link_stats_results;
+ vos_msg.bodyval = 0;
+ if (VOS_STATUS_SUCCESS !=
+ vos_mq_post_message(VOS_MQ_ID_SME, &vos_msg)) {
+ WMA_LOGP(FL("Failed to post peer stat change msg!"));
+ vos_mem_free(link_stats_results);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* wma_tx_failure_cb() - TX failure callback
* @ctx: txrx context
@@ -5086,6 +5622,129 @@ void wma_tx_failure_cb(void *ctx, uint32_t num_msdu, uint8_t tid, uint32 status)
}
}
+/**
+ * void wma_config_stats_ext_threshold - set threthold for MAC counters
+ * @wma: wma handler
+ * @threshold: threhold for MAC counters
+ *
+ * For each MAC layer counter, FW holds two copies. One is the current value.
+ * The other is the last report. Once a current counter's increment is larger
+ * than the threshold, FW will indicate that counter to host even if the
+ * monitoring timer does not expire.
+ */
+void wma_config_stats_ext_threshold(struct wma_handle *wma,
+ struct sir_ll_ext_stats_threshold *thresh)
+{
+ uint32_t len, tag, hdr_len;
+ uint8_t *buf_ptr;
+ wmi_buf_t buf;
+ wmi_pdev_set_stats_threshold_cmd_fixed_param *cmd;
+ wmi_chan_cca_stats_thresh *cca;
+ wmi_peer_signal_stats_thresh *signal;
+ wmi_tx_stats_thresh *tx;
+ wmi_rx_stats_thresh *rx;
+
+ len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param) +
+ sizeof(wmi_chan_cca_stats_thresh) +
+ sizeof(wmi_peer_signal_stats_thresh) +
+ sizeof(wmi_tx_stats_thresh) +
+ sizeof(wmi_rx_stats_thresh) +
+ 5 * WMI_TLV_HDR_SIZE;
+ buf = wmi_buf_alloc(wma->wmi_handle, len);
+ if (!buf) {
+ WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
+ return;
+ }
+
+ buf_ptr = (u_int8_t *)wmi_buf_data(buf);
+ tag = WMITLV_TAG_STRUC_wmi_pdev_set_stats_threshold_cmd_fixed_param;
+ hdr_len = WMITLV_GET_STRUCT_TLVLEN(
+ wmi_pdev_set_stats_threshold_cmd_fixed_param);
+ WMA_LOGD(FL("Setting fixed parameters. tag=%d, len=%d"), tag, hdr_len);
+ cmd = (wmi_pdev_set_stats_threshold_cmd_fixed_param *)buf_ptr;
+ WMITLV_SET_HDR(&cmd->tlv_header, tag, hdr_len);
+ cmd->enable_thresh = thresh->enable;
+ cmd->use_thresh_bitmap = thresh->enable_bitmap;
+ cmd->gbl_thresh = thresh->global_threshold;
+ cmd->cca_thresh_enable_bitmap = thresh->cca_bitmap;
+ cmd->signal_thresh_enable_bitmap = thresh->signal_bitmap;
+ cmd->tx_thresh_enable_bitmap = thresh->tx_bitmap;
+ cmd->rx_thresh_enable_bitmap = thresh->rx_bitmap;
+ len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param);
+
+ tag = WMITLV_TAG_STRUC_wmi_chan_cca_stats_thresh,
+ hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_chan_cca_stats_thresh);
+ cca = (wmi_chan_cca_stats_thresh *)(buf_ptr + len);
+ WMITLV_SET_HDR(&cca->tlv_header, tag, hdr_len);
+ WMA_LOGD(FL("Setting cca parameters. tag=%d, len=%d"), tag, hdr_len);
+ cca->idle_time = thresh->cca.idle_time;
+ cca->tx_time = thresh->cca.tx_time;
+ cca->rx_in_bss_time = thresh->cca.rx_in_bss_time;
+ cca->rx_out_bss_time = thresh->cca.rx_out_bss_time;
+ cca->rx_busy_time = thresh->cca.rx_busy_time;
+ cca->rx_in_bad_cond_time = thresh->cca.rx_in_bad_cond_time;
+ cca->tx_in_bad_cond_time = thresh->cca.tx_in_bad_cond_time;
+ cca->wlan_not_avail_time = thresh->cca.wlan_not_avail_time;
+ len += sizeof(wmi_chan_cca_stats_thresh);
+
+ signal = (wmi_peer_signal_stats_thresh *)(buf_ptr + len);
+ tag = WMITLV_TAG_STRUC_wmi_peer_signal_stats_thresh;
+ hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_peer_signal_stats_thresh);
+ WMA_LOGD(FL("Setting signal parameters. tag=%d, len=%d"), tag, hdr_len);
+ WMITLV_SET_HDR(&signal->tlv_header, tag, hdr_len);
+ signal->per_chain_snr = thresh->signal.snr;
+ signal->per_chain_nf = thresh->signal.nf;
+ len += sizeof(wmi_peer_signal_stats_thresh);
+
+ tx = (wmi_tx_stats_thresh *)(buf_ptr + len);
+ tag = WMITLV_TAG_STRUC_wmi_tx_stats_thresh;
+ hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_tx_stats_thresh);
+ WMA_LOGD(FL("Setting TX parameters. tag=%d, len=%d"), tag, len);
+ WMITLV_SET_HDR(&tx->tlv_header, tag, hdr_len);
+ tx->tx_msdu_cnt = thresh->tx.msdu;
+ tx->tx_mpdu_cnt = thresh->tx.mpdu;
+ tx->tx_ppdu_cnt = thresh->tx.ppdu;
+ tx->tx_bytes = thresh->tx.bytes;
+ tx->tx_msdu_drop_cnt = thresh->tx.msdu_drop;
+ tx->tx_drop_bytes = thresh->tx.byte_drop;
+ tx->tx_mpdu_retry_cnt = thresh->tx.mpdu_retry;
+ tx->tx_mpdu_fail_cnt = thresh->tx.mpdu_fail;
+ tx->tx_ppdu_fail_cnt = thresh->tx.ppdu_fail;
+ tx->tx_mpdu_aggr = thresh->tx.aggregation;
+ tx->tx_succ_mcs = thresh->tx.succ_mcs;
+ tx->tx_fail_mcs = thresh->tx.fail_mcs;
+ tx->tx_ppdu_delay = thresh->tx.delay;
+ len += sizeof(wmi_tx_stats_thresh);
+
+ rx = (wmi_rx_stats_thresh *)(buf_ptr + len);
+ tag = WMITLV_TAG_STRUC_wmi_rx_stats_thresh,
+ hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_rx_stats_thresh);
+ WMITLV_SET_HDR(&rx->tlv_header, tag, hdr_len);
+ WMA_LOGD(FL("Setting RX parameters. tag=%d, len=%d"), tag, hdr_len);
+ rx->mac_rx_mpdu_cnt = thresh->rx.mpdu;
+ rx->mac_rx_bytes = thresh->rx.bytes;
+ rx->phy_rx_ppdu_cnt = thresh->rx.ppdu;
+ rx->phy_rx_bytes = thresh->rx.ppdu_bytes;
+ rx->rx_disorder_cnt = thresh->rx.disorder;
+ rx->rx_mpdu_retry_cnt = thresh->rx.mpdu_retry;
+ rx->rx_mpdu_discard_cnt = thresh->rx.mpdu_discard;
+ rx->rx_mpdu_aggr = thresh->rx.aggregation;
+ rx->rx_mcs = thresh->rx.mcs;
+ rx->sta_ps_inds = thresh->rx.ps_inds;
+ rx->sta_ps_durs = thresh->rx.ps_durs;
+ rx->rx_probe_reqs = thresh->rx.probe_reqs;
+ rx->rx_oth_mgmts = thresh->rx.other_mgmt;
+ len += sizeof(wmi_rx_stats_thresh);
+
+ WMA_LOGA("WMA --> WMI_PDEV_SET_STATS_THRESHOLD_CMDID(0x%x), length=%d",
+ WMI_PDEV_SET_STATS_THRESHOLD_CMDID, len);
+ if (EOK != wmi_unified_cmd_send(wma->wmi_handle,
+ buf, len,
+ WMI_PDEV_SET_STATS_THRESHOLD_CMDID)) {
+ WMA_LOGE("Failed to send WMI_PDEV_SET_STATS_THRESHOLD_CMDID");
+ wmi_buf_free(buf);
+ }
+}
#else
/**
* wma_tx_failure_cb() - TX failure callback
@@ -6598,7 +7257,9 @@ wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
wmi_unified_register_event_handler(wma_handle->wmi_handle,
WMI_PEER_STA_PS_STATECHG_EVENTID,
wma_peer_ps_evt_handler);
-
+ wmi_unified_register_event_handler(wma_handle->wmi_handle,
+ WMI_REPORT_STATS_EVENTID,
+ wma_ll_stats_evt_handler);
return;
}
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
@@ -31241,6 +31902,11 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg)
(tpSirLLStatsGetReq)msg->bodyptr);
vos_mem_free(msg->bodyptr);
break;
+ case WDA_LINK_LAYER_STATS_SET_THRESHOLD:
+ wma_config_stats_ext_threshold(wma_handle,
+ msg->bodyptr);
+ vos_mem_free(msg->bodyptr);
+ break;
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
case SIR_HAL_UNIT_TEST_CMD:
wma_process_unit_test_cmd(wma_handle,
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 38bb94e4b17e..c3e0b8eebeab 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4213,6 +4213,9 @@ eHalStatus sme_LLStatsSetReq (tHalHandle hHal,
eHalStatus sme_LLStatsGetReq (tHalHandle hHal,
tSirLLStatsGetReq *pgetStatsReq);
+eHalStatus sme_ll_stats_set_thresh(tHalHandle hal,
+ struct sir_ll_ext_stats_threshold *thresh);
+
/* ---------------------------------------------------------------------------
\fn sme_SetLinkLayerStatsIndCB
\brief SME API to trigger the stats are available after get request
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index a5d08da5796c..1b3a7e931341 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -16506,6 +16506,52 @@ eHalStatus sme_LLStatsGetReq (tHalHandle hHal,
return status;
}
+/**
+ * eHalStatus sme_ll_stats_set_thresh - set threshold for mac counters
+ * @hal, hal layer handle
+ * @threshold, threshold for mac counters
+ */
+eHalStatus sme_ll_stats_set_thresh(tHalHandle hal,
+ struct sir_ll_ext_stats_threshold *threshold)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal mac = PMAC_STRUCT(hal);
+ vos_msg_t message;
+ struct sir_ll_ext_stats_threshold *thresh;
+
+ thresh = vos_mem_malloc(sizeof(*thresh));
+ if (!thresh) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: Fail to alloc mem", __func__);
+ return eHAL_STATUS_FAILURE;
+ }
+ *thresh = *threshold;
+
+ if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&mac->sme)) {
+ /* Serialize the req through MC thread */
+ message.bodyptr = thresh;
+ message.type = WDA_LINK_LAYER_STATS_SET_THRESHOLD;
+ MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_TX_WDA_MSG,
+ NO_SESSION, message.type));
+ vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &message);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ "%s: not able to post WDA_LL_STATS_GET_REQ",
+ __func__);
+ vos_mem_free(thresh);
+ status = eHAL_STATUS_FAILURE;
+ }
+ sme_ReleaseGlobalLock(&mac->sme);
+ } else {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("sme_AcquireGlobalLock error"));
+ vos_mem_free(thresh);
+ status = eHAL_STATUS_FAILURE;
+ }
+ return status;
+}
+
/* ---------------------------------------------------------------------------
\fn sme_SetLinkLayerStatsIndCB
\brief SME API to trigger the stats are available after get request
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 9e05a8caf9d0..3d788c4c8580 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -1010,6 +1010,7 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb);
#define WDA_LINK_LAYER_STATS_SET_REQ SIR_HAL_LL_STATS_SET_REQ
#define WDA_LINK_LAYER_STATS_GET_REQ SIR_HAL_LL_STATS_GET_REQ
#define WDA_LINK_LAYER_STATS_RESULTS_RSP SIR_HAL_LL_STATS_RESULTS_RSP
+#define WDA_LINK_LAYER_STATS_SET_THRESHOLD SIR_HAL_LL_STATS_EXT_SET_THRESHOLD
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
#define WDA_LINK_STATUS_GET_REQ SIR_HAL_LINK_STATUS_GET_REQ