qcacld-3.0: Add MAC counter WMI interface

qcacld-2.0 to qcacld-3.0 propagation

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
This commit is contained in:
Zhang Qian
2017-03-13 16:15:55 +08:00
committed by snandini
부모 1e3de00bfc
커밋 73c348a749
8개의 변경된 파일1230개의 추가작업 그리고 2개의 파일을 삭제

파일 보기

@@ -5082,6 +5082,450 @@ struct sir_wifi_iface_tx_fail {
enum htt_tx_status 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
* @msdus: number of totoal MSDUs on MAC layer in the period
* @mpdus: number of totoal MPDUs on MAC layer in the period
* @ppdus: number of totoal PPDUs on PHY 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 msdus;
uint32_t mpdus;
uint32_t ppdus;
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
* @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 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
* mac_address: MAC address
* @sta_ps_inds: how many times STAs go to sleep
* @sta_ps_durs: total sleep time of STAs (units in ms)
* @rx_probe_reqs: number of probe requests received
* @rx_oth_mgmts: number of other management frames received,
* not including probe requests
* @peer_signal_stat: signal stats
* @ac_stats: WMM BE/BK/VI/VO stats
*/
struct sir_wifi_ll_ext_peer_stats {
uint32_t peer_id;
uint32_t vdev_id;
tSirMacAddr mac_address;
uint32_t sta_ps_inds;
uint32_t sta_ps_durs;
uint32_t rx_probe_reqs;
uint32_t rx_oth_mgmts;
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
* @period: MAC counter indication period (unit in ms)
* @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 period;
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;
};
#define LL_STATS_MIN_PERIOD 10
#define LL_STATS_INVALID_PERIOD 0xFFFFFFFF
typedef struct {
uint32_t paramId;
uint8_t ifaceId;

파일 보기

@@ -639,7 +639,11 @@ typedef struct sSirMbMsgP2p {
#define SIR_HAL_SET_PER_ROAM_CONFIG_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 371)
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
#define SIR_HAL_LL_STATS_EXT_SET_THRESHOLD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 378)
#endif
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
/* CFG message types */
#define SIR_CFG_MSG_TYPES_BEGIN (SIR_CFG_MODULE_ID << 8)

파일 보기

@@ -889,6 +889,8 @@ QDF_STATUS sme_set_link_layer_ext_cb(tHalHandle hal,
void (*ll_stats_ext_cb)(tHddHandle callback_ctx,
tSirLLStatsResults * rsp));
QDF_STATUS sme_reset_link_layer_stats_ind_cb(tHalHandle hhal);
QDF_STATUS sme_ll_stats_set_thresh(tHalHandle hal,
struct sir_ll_ext_stats_threshold *threshold);
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
QDF_STATUS sme_fw_mem_dump(tHalHandle hHal, void *recvd_req);

파일 보기

@@ -13266,6 +13266,64 @@ QDF_STATUS sme_reset_link_layer_stats_ind_cb(tHalHandle h_hal)
return status;
}
/**
* sme_ll_stats_set_thresh - set threshold for mac counters
* @hal, hal layer handle
* @threshold, threshold for mac counters
*
* Return: QDF_STATUS Enumeration
*/
QDF_STATUS sme_ll_stats_set_thresh(tHalHandle hal,
struct sir_ll_ext_stats_threshold *threshold)
{
QDF_STATUS status;
tpAniSirGlobal mac;
struct scheduler_msg message;
struct sir_ll_ext_stats_threshold *thresh;
if (!threshold) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("threshold is not valid"));
return QDF_STATUS_E_INVAL;
}
if (!hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("hal is not valid"));
return QDF_STATUS_E_INVAL;
}
mac = PMAC_STRUCT(hal);
thresh = qdf_mem_malloc(sizeof(*thresh));
if (!thresh) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Fail to alloc mem", __func__);
return QDF_STATUS_E_NOMEM;
}
*thresh = *threshold;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = thresh;
message.type = WDA_LINK_LAYER_STATS_SET_THRESHOLD;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: not able to post WDA_LL_STATS_GET_REQ",
__func__);
qdf_mem_free(thresh);
}
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock error"));
qdf_mem_free(thresh);
}
return status;
}
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */

파일 보기

@@ -822,6 +822,8 @@ QDF_STATUS wma_process_ll_stats_get_req
int wma_unified_link_iface_stats_event_handler(void *handle,
uint8_t *cmd_param_info,
uint32_t len);
void wma_config_stats_ext_threshold(tp_wma_handle wma,
struct sir_ll_ext_stats_threshold *thresh);
#endif
void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,

파일 보기

@@ -413,6 +413,7 @@
#define WMA_LINK_LAYER_STATS_SET_REQ SIR_HAL_LL_STATS_SET_REQ
#define WMA_LINK_LAYER_STATS_GET_REQ SIR_HAL_LL_STATS_GET_REQ
#define WMA_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 WMA_LINK_STATUS_GET_REQ SIR_HAL_LINK_STATUS_GET_REQ

파일 보기

@@ -6794,6 +6794,11 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, struct scheduler_msg *msg)
(tpSirLLStatsGetReq) msg->bodyptr);
qdf_mem_free(msg->bodyptr);
break;
case WDA_LINK_LAYER_STATS_SET_THRESHOLD:
wma_config_stats_ext_threshold(wma_handle,
(struct sir_ll_ext_stats_threshold *)msg->bodyptr);
qdf_mem_free(msg->bodyptr);
break;
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
case SIR_HAL_UNIT_TEST_CMD:
wma_process_unit_test_cmd(wma_handle,

파일 보기

@@ -556,6 +556,556 @@ int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
#define WMA_FILL_TX_STATS(eve, msg) do {\
(msg)->msdus = (eve)->tx_msdu_cnt;\
(msg)->mpdus = (eve)->tx_mpdu_cnt;\
(msg)->ppdus = (eve)->tx_ppdu_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 *)qdf_mem_malloc(buf_len);
if (buf == NULL) {
WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
buf_len = 0;
return NULL;
}
*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
*
* Return: None
*/
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;
qdf_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;
qdf_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;
qdf_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;
qdf_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 *
sizeof(uint32_t);
ac->success_mcs_len = tx_succ_mcs_array_len *
sizeof(uint32_t);
ac->success_mcs = tx_succ_mcs;
ac->fail_mcs = tx_fail_mcs;
ac->fail_mcs_len = tx_fail_mcs_array_len *
sizeof(uint32_t);
ac->delay = tx_delay;
ac->delay_len = tx_delay_array_len *
sizeof(uint32_t);
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
*
* Return: None
*/
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_t *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;
qdf_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;
qdf_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;
peer_stats->sta_ps_inds = wmi_peer_rx[i].sta_ps_inds;
peer_stats->sta_ps_durs = wmi_peer_rx[i].sta_ps_durs;
peer_stats->rx_probe_reqs =
wmi_peer_rx[i].rx_probe_reqs;
peer_stats->rx_oth_mgmts = wmi_peer_rx[i].rx_oth_mgmts;
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 *
sizeof(uint32_t);
ac->mcs = rx_mcs;
ac->mcs_len = rx_mcs_array_len *
sizeof(uint32_t);
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)
{
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;
struct scheduler_msg sme_msg = { 0 };
QDF_STATUS qdf_status;
mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
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) {
qdf_mem_copy(peer_signal,
&wmi_peer_signal->vdev_id, dst_len);
result_size -= dst_len;
} else {
WMA_LOGE(FL("Invalid length of PEER signal."));
}
wmi_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) {
qdf_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);
sme_msg.type = eWMI_SME_LL_STATS_IND;
sme_msg.bodyptr = (void *)link_stats_results;
sme_msg.bodyval = 0;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
WMA_LOGP(FL("Failed to post peer stat change msg!"));
qdf_mem_free(link_stats_results);
return -EINVAL;
}
return 0;
}
/**
* wma_unified_link_peer_stats_event_handler() - peer stats event handler
* @handle: wma handle
@@ -1093,7 +1643,7 @@ static int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
sme_msg.bodyptr = link_stats_results;
sme_msg.bodyval = 0;
qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
WMA_LOGE("%s: Fail to post ps change ind msg", __func__);
qdf_mem_free(link_stats_results);
@@ -1209,6 +1759,10 @@ void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
WMI_PEER_STA_PS_STATECHG_EVENTID,
wma_peer_ps_evt_handler,
WMA_RX_SERIALIZER_CTX);
wmi_unified_register_event_handler(wma_handle->wmi_handle,
WMI_REPORT_STATS_EVENTID,
wma_ll_stats_evt_handler,
WMA_RX_SERIALIZER_CTX);
return;
}
@@ -1432,6 +1986,164 @@ int wma_unified_link_iface_stats_event_handler(void *handle,
return 0;
}
/**
* 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.
*
* Return: None
*/
void wma_config_stats_ext_threshold(tp_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;
if (!thresh) {
WMA_LOGE(FL("Invalid threshold input."));
return;
}
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;
WMA_LOGD(FL("idle time=%d, tx_time=%d, in_bss=%d, out_bss=%d"),
cca->idle_time, cca->tx_time,
cca->rx_in_bss_time, cca->rx_out_bss_time);
WMA_LOGD(FL("rx_busy=%d, rx_bad=%d, tx_bad=%d, not_avail=%d"),
cca->rx_busy_time, cca->rx_in_bad_cond_time,
cca->tx_in_bad_cond_time, 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;
WMA_LOGD(FL("snr=%d, nf=%d"), signal->per_chain_snr,
signal->per_chain_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;
WMA_LOGD(FL("msdu=%d, mpdu=%d, ppdu=%d, bytes=%d, msdu_drop=%d"),
tx->tx_msdu_cnt, tx->tx_mpdu_cnt, tx->tx_ppdu_cnt,
tx->tx_bytes, tx->tx_msdu_drop_cnt);
WMA_LOGD(FL("byte_drop=%d, mpdu_retry=%d, mpdu_fail=%d, ppdu_fail=%d"),
tx->tx_drop_bytes, tx->tx_mpdu_retry_cnt,
tx->tx_mpdu_fail_cnt, tx->tx_ppdu_fail_cnt);
WMA_LOGD(FL("aggr=%d, succ_mcs=%d, fail_mcs=%d, delay=%d"),
tx->tx_mpdu_aggr, tx->tx_succ_mcs, tx->tx_fail_mcs,
tx->tx_ppdu_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_dup_cnt = thresh->rx.mpdu_dup;
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;
WMA_LOGD(FL("rx_mpdu=%d, rx_bytes=%d, rx_ppdu=%d, rx_pbytes=%d"),
rx->mac_rx_mpdu_cnt, rx->mac_rx_bytes,
rx->phy_rx_ppdu_cnt, rx->phy_rx_bytes);
WMA_LOGD(FL("disorder=%d, rx_dup=%d, rx_aggr=%d, rx_mcs=%d"),
rx->rx_disorder_cnt, rx->rx_mpdu_dup_cnt,
rx->rx_mpdu_aggr, rx->rx_mcs);
WMA_LOGD(FL("rx_ind=%d, rx_dur=%d, rx_probe=%d, rx_mgmt=%d"),
rx->sta_ps_inds, rx->sta_ps_durs,
rx->rx_probe_reqs, rx->rx_oth_mgmts);
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);
}
}
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
/**