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:
@@ -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 */
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user