diff options
| author | Zhang Qian <zhangq@codeaurora.org> | 2016-10-21 11:40:45 +0800 |
|---|---|---|
| committer | Anjaneedevi Kapparapu <akappa@codeaurora.org> | 2016-11-11 19:44:23 +0530 |
| commit | cab730d29ded331721d23229f02506ab3cef2d8e (patch) | |
| tree | 4a278bdfb43faab22d5d515ec1980d7e5850c344 | |
| parent | dea8b6c6f53e5e262a0d2c127021c5dd44b4fc1b (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.h | 435 | ||||
| -rw-r--r-- | CORE/MAC/src/include/sirParams.h | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 668 | ||||
| -rw-r--r-- | CORE/SME/inc/sme_Api.h | 3 | ||||
| -rw-r--r-- | CORE/SME/src/sme_common/sme_Api.c | 46 | ||||
| -rw-r--r-- | CORE/WDA/inc/wlan_qct_wda.h | 1 |
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 |
