qcacmn: Add APIs to enable HTT FW Stats

Adding support to parse stream of HTT TLV's recieved as response
to the HTT EXT stats request message

Change-Id: I44c990a1ed91c2381b89811de33c0717bd24be7d
CRs-Fixed: 1114641
This commit is contained in:
Ishank Jain
2017-03-21 10:49:39 +05:30
committed by snandini
parent 8dac1dba72
commit 6290a3c543
10 changed files with 737 additions and 70 deletions

View File

@@ -494,17 +494,16 @@ static inline void cdp_flush_cache_rx_queue(ol_txrx_soc_handle soc)
* cdp_txrx_stats(): function to map to host and firmware statistics
* @soc: soc handle
* @vdev: virtual device
* @req: statistics request handle
* @stats: statistics option
*
* return: status
*/
static inline
int cdp_txrx_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev,
struct ol_txrx_stats_req *req, enum cdp_stats stats)
enum cdp_stats stats)
{
if (soc->ops->cmn_drv_ops->txrx_stats)
return soc->ops->cmn_drv_ops->txrx_stats(vdev, req, stats);
return soc->ops->cmn_drv_ops->txrx_stats(vdev, stats);
return 0;
}

View File

@@ -130,11 +130,11 @@ enum htt_cmn_dbg_stats_type {
*/
enum cdp_host_txrx_stats {
TXRX_HOST_STATS_INVALID = -1,
TXRX_RX_RATE_STATS = 0,
TXRX_TX_RATE_STATS = 1,
TXRX_TX_HOST_STATS = 2,
TXRX_RX_HOST_STATS = 3,
TXRX_CLEAR_STATS = 4,
TXRX_CLEAR_STATS = 0,
TXRX_RX_RATE_STATS = 1,
TXRX_TX_RATE_STATS = 2,
TXRX_TX_HOST_STATS = 3,
TXRX_RX_HOST_STATS = 4,
TXRX_HOST_STATS_MAX,
};
@@ -517,7 +517,8 @@ enum cdp_stats {
CDP_TXRX_STATS_25,
CDP_TXRX_STATS_26,
CDP_TXRX_STATS_27,
CDP_TXRX_MAX_STATS,
CDP_TXRX_STATS_HTT_MAX = 256,
CDP_TXRX_MAX_STATS = 512,
};
/* Different Packet Types */

View File

@@ -32,29 +32,36 @@
#ifndef _CDP_TXRX_HOST_STATS_H_
#define _CDP_TXRX_HOST_STATS_H_
#include "cdp_txrx_handle.h"
/* WIN */
/* Need to remove the "req" parameter */
/* Need to rename the function to reflect the functionality "show" / "display"
* WIN -- to figure out whether to change OSIF to converge (not an immediate AI)
* */
/**
* cdp_host_stats_get: cdp call to get host stats
* @soc: SOC handle
* @req: Requirement type
* @type: Host stat type
*
* return: 0 for Success, Failure returns error message
*/
static inline int cdp_host_stats_get(ol_txrx_soc_handle soc,
struct cdp_vdev *vdev,
struct ol_txrx_stats_req *req, enum cdp_host_txrx_stats type)
struct ol_txrx_stats_req *req)
{
if (soc->ops->host_stats_ops->txrx_host_stats_get)
return soc->ops->host_stats_ops->txrx_host_stats_get(vdev, req,
type);
return soc->ops->host_stats_ops->txrx_host_stats_get(vdev, req);
return 0;
}
/**
* cdp_host_stats_clr: cdp call to clear host stats
* @vdev: vdev handle
*
* return: void
*/
static inline void
cdp_host_stats_clr(ol_txrx_soc_handle soc, struct cdp_vdev *vdev)
{
if (soc->ops->host_stats_ops->txrx_host_stats_clr)
return soc->ops->host_stats_ops->txrx_host_stats_clr(vdev);
return;
}
static inline void
cdp_host_ce_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev)
{
@@ -213,6 +220,15 @@ cdp_reset_lro_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev)
return;
}
static inline void cdp_get_dp_fw_peer_stats(ol_txrx_soc_handle soc,
struct cdp_pdev *pdev, uint8_t *mac, uint32_t caps)
{
if (soc->ops->host_stats_ops->get_fw_peer_stats)
return soc->ops->host_stats_ops->get_fw_peer_stats
(pdev, mac, caps);
return;
}
/**
* @brief Parse the stats header and get the payload from the message.
*

View File

@@ -199,8 +199,7 @@ struct cdp_cmn_ops {
void (*set_pdev_dscp_tid_map)(struct cdp_pdev *pdev, uint8_t map_id,
uint8_t tos, uint8_t tid);
A_STATUS(*txrx_stats)(struct cdp_vdev *vdev,
struct ol_txrx_stats_req *req, enum cdp_stats stats);
int (*txrx_stats)(struct cdp_vdev *vdev, enum cdp_stats stats);
QDF_STATUS (*display_stats)(void *psoc, uint16_t value);
@@ -466,8 +465,9 @@ struct cdp_mon_ops {
struct cdp_host_stats_ops {
int (*txrx_host_stats_get)(struct cdp_vdev *vdev,
struct ol_txrx_stats_req *req,
enum cdp_host_txrx_stats type);
struct ol_txrx_stats_req *req);
void (*txrx_host_stats_clr)(struct cdp_vdev *vdev);
void (*txrx_host_ce_stats)(struct cdp_vdev *vdev);
@@ -530,6 +530,10 @@ struct cdp_host_stats_ops {
void
(*reset_lro_stats)(struct cdp_vdev *vdev);
void
(*get_fw_peer_stats)(struct cdp_pdev *pdev, uint8_t *addr,
uint32_t cap);
};
struct cdp_wds_ops {

View File

@@ -23,12 +23,16 @@
#include "dp_types.h"
#include "dp_internal.h"
#include "dp_rx_mon.h"
#include "htt_stats.h"
#define HTT_TLV_HDR_LEN HTT_T2H_EXT_STATS_CONF_TLV_HDR_SIZE
#define HTT_HTC_PKT_POOL_INIT_SIZE 64
#define HTT_MSG_BUF_SIZE(msg_bytes) \
((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
#define DP_EXT_MSG_LENGTH 2048
/*
* htt_htc_pkt_alloc() - Allocate HTC packet buffer
* @htt_soc: HTT SOC handle
@@ -853,6 +857,210 @@ fail0:
return QDF_STATUS_E_FAILURE;
}
/**
* dp_process_htt_stat_msg(): Process the list of buffers of HTT EXT stats
* @soc: DP SOC handle
*
* The FW sends the HTT EXT STATS as a stream of T2H messages. Each T2H message
* contains sub messages which are identified by a TLV header.
* In this function we will process the stream of T2H messages and read all the
* TLV contained in the message.
*
* THe following cases have been taken care of
* Case 1: When the tlv_remain_length <= msg_remain_length of HTT MSG buffer
* In this case the buffer will contain multiple tlvs.
* Case 2: When the tlv_remain_length > msg_remain_length of HTT MSG buffer.
* Only one tlv will be contained in the HTT message and this tag
* will extend onto the next buffer.
* Case 3: When the buffer is the continuation of the previous message
* Case 4: tlv length is 0. which will indicate the end of message
*
* return: void
*/
static inline void dp_process_htt_stat_msg(struct dp_soc *soc)
{
htt_tlv_tag_t tlv_type = 0xff;
qdf_nbuf_t htt_msg = NULL;
uint32_t *msg_word;
uint8_t *tlv_buf_head = NULL;
uint8_t *tlv_buf_tail = NULL;
uint32_t msg_remain_len = 0;
uint32_t tlv_remain_len = 0;
uint32_t *tlv_start;
/* Process node in the HTT message queue */
while ((htt_msg = qdf_nbuf_queue_remove(&soc->htt_stats_msg)) != NULL) {
msg_word = (uint32_t *) qdf_nbuf_data(htt_msg);
/* read 5th word */
msg_word = msg_word + 4;
msg_remain_len = qdf_min(soc->htt_msg_len,
(uint32_t)DP_EXT_MSG_LENGTH);
/* Keep processing the node till node length is 0 */
while (msg_remain_len) {
/*
* if message is not a continuation of previous message
* read the tlv type and tlv length
*/
if (!tlv_buf_head) {
tlv_type = HTT_STATS_TLV_TAG_GET(
*msg_word);
tlv_remain_len = HTT_STATS_TLV_LENGTH_GET(
*msg_word);
}
if (tlv_remain_len == 0) {
msg_remain_len = 0;
if (tlv_buf_head) {
qdf_mem_free(tlv_buf_head);
tlv_buf_head = NULL;
tlv_buf_tail = NULL;
}
goto error;
}
tlv_remain_len += HTT_TLV_HDR_LEN;
if ((tlv_remain_len <= msg_remain_len)) {
/* Case 3 */
if (tlv_buf_head) {
qdf_mem_copy(tlv_buf_tail,
(uint8_t *)msg_word,
tlv_remain_len);
tlv_start = (uint32_t *)tlv_buf_head;
} else {
/* Case 1 */
tlv_start = msg_word;
}
dp_htt_stats_print_tag(tlv_type, tlv_start);
msg_remain_len -= tlv_remain_len;
msg_word = (uint32_t *)
(((uint8_t *)msg_word) +
tlv_remain_len);
tlv_remain_len = 0;
if (tlv_buf_head) {
qdf_mem_free(tlv_buf_head);
tlv_buf_head = NULL;
tlv_buf_tail = NULL;
}
} else { /* tlv_remain_len > msg_remain_len */
/* Case 2 & 3 */
if (!tlv_buf_head) {
tlv_buf_head = qdf_mem_malloc(
tlv_remain_len);
if (!tlv_buf_head) {
QDF_TRACE(QDF_MODULE_ID_TXRX,
QDF_TRACE_LEVEL_ERROR,
"Alloc failed");
goto error;
}
tlv_buf_tail = tlv_buf_head;
}
qdf_mem_copy(tlv_buf_tail, (uint8_t *)msg_word,
msg_remain_len);
tlv_remain_len -= msg_remain_len;
tlv_buf_tail += msg_remain_len;
msg_remain_len = 0;
}
}
if (soc->htt_msg_len >= DP_EXT_MSG_LENGTH) {
soc->htt_msg_len -= DP_EXT_MSG_LENGTH;
}
qdf_nbuf_free(htt_msg);
}
soc->htt_msg_len = 0;
return;
error:
qdf_nbuf_free(htt_msg);
soc->htt_msg_len = 0;
while ((htt_msg = qdf_nbuf_queue_remove(&soc->htt_stats_msg))
!= NULL)
qdf_nbuf_free(htt_msg);
}
/**
* dp_txrx_fw_stats_handler():Function to process HTT EXT stats
* @soc: DP SOC handle
* @htt_t2h_msg: HTT message nbuf
*
* return:void
*/
static inline void dp_txrx_fw_stats_handler(struct dp_soc *soc,
qdf_nbuf_t htt_t2h_msg)
{
uint32_t length;
uint8_t done;
qdf_nbuf_t msg_copy;
uint32_t *msg_word;
msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg);
msg_word = msg_word + 3;
done = 0;
length = HTT_T2H_EXT_STATS_CONF_TLV_LENGTH_GET(*msg_word);
done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*msg_word);
/*
* HTT EXT stats response comes as stream of TLVs which span over
* multiple T2H messages.
* The first message will carry length of the response.
* For rest of the messages length will be zero.
*/
if (soc->htt_msg_len && length)
goto error;
if (length)
soc->htt_msg_len = length;
/*
* Clone the T2H message buffer and store it in a list to process
* it later.
*
* The original T2H message buffers gets freed in the T2H HTT event
* handler
*/
msg_copy = qdf_nbuf_clone(htt_t2h_msg);
if (!msg_copy) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
"T2H messge clone failed for HTT EXT STATS");
soc->htt_msg_len = 0;
goto error;
}
qdf_nbuf_queue_add(&soc->htt_stats_msg, msg_copy);
/*
* Done bit signifies that this is the last T2H buffer in the stream of
* HTT EXT STATS message
*/
if (done)
dp_process_htt_stat_msg(soc);
return;
error:
while ((msg_copy = qdf_nbuf_queue_remove(&soc->htt_stats_msg))
!= NULL) {
qdf_nbuf_free(msg_copy);
}
return;
}
/*
* htt_soc_attach_target() - SOC level HTT setup
* @htt_soc: HTT SOC handle
@@ -1015,8 +1223,11 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
}
break;
}
case HTT_T2H_MSG_TYPE_EXT_STATS_CONF:
{
dp_txrx_fw_stats_handler(soc->dp_soc, htt_t2h_msg);
break;
}
default:
break;
};
@@ -1166,3 +1377,100 @@ htt_soc_detach(void *htt_soc)
qdf_mem_free(soc);
}
/**
* dp_h2t_ext_stats_msg_send(): function to contruct HTT message to pass to FW
* @pdev: DP PDEV handle
* @stats_type_upload_mask: stats type requested by user
* @config_param_0: extra configuration parameters
* @config_param_1: extra configuration parameters
* @config_param_2: extra configuration parameters
* @config_param_3: extra configuration parameters
*
* return: QDF STATUS
*/
QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev,
uint32_t stats_type_upload_mask, uint32_t config_param_0,
uint32_t config_param_1, uint32_t config_param_2,
uint32_t config_param_3)
{
struct htt_soc *soc = pdev->soc->htt_handle;
struct dp_htt_htc_pkt *pkt;
qdf_nbuf_t msg;
uint32_t *msg_word;
uint8_t pdev_mask;
msg = qdf_nbuf_alloc(
soc->osdev,
HTT_MSG_BUF_SIZE(HTT_H2T_EXT_STATS_REQ_MSG_SZ),
HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
if (!msg)
return QDF_STATUS_E_NOMEM;
/*TODO:Add support for SOC stats
* Bit 0: SOC Stats
* Bit 1: Pdev stats for pdev id 0
* Bit 2: Pdev stats for pdev id 1
* Bit 3: Pdev stats for pdev id 2
*/
pdev_mask = 1 << (pdev->pdev_id + 1);
/*
* Set the length of the message.
* The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
* separately during the below call to qdf_nbuf_push_head.
* The contribution from the HTC header is added separately inside HTC.
*/
if (qdf_nbuf_put_tail(msg, HTT_H2T_EXT_STATS_REQ_MSG_SZ) == NULL) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Failed to expand head for HTT_EXT_STATS");
qdf_nbuf_free(msg);
return QDF_STATUS_E_FAILURE;
}
msg_word = (uint32_t *) qdf_nbuf_data(msg);
qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
*msg_word = 0;
HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_EXT_STATS_REQ);
HTT_H2T_EXT_STATS_REQ_PDEV_MASK_SET(*msg_word, pdev_mask);
HTT_H2T_EXT_STATS_REQ_STATS_TYPE_SET(*msg_word, stats_type_upload_mask);
/* word 1 */
msg_word++;
*msg_word = 0;
HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_0);
/* word 2 */
msg_word++;
*msg_word = 0;
HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_1);
/* word 3 */
msg_word++;
*msg_word = 0;
HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_2);
/* word 4 */
msg_word++;
*msg_word = 0;
HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_3);
HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, 0);
pkt = htt_htc_pkt_alloc(soc);
if (!pkt) {
qdf_nbuf_free(msg);
return QDF_STATUS_E_NOMEM;
}
pkt->soc_ctxt = NULL; /* not used during send-done callback */
SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
dp_htt_h2t_send_complete_free_netbuf,
qdf_nbuf_data(msg), qdf_nbuf_len(msg),
soc->htc_endpoint,
1); /* tag - not relevant here */
SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
return htc_send_pkt(soc->htc_soc, &pkt->htc_pkt);
}

View File

@@ -279,4 +279,9 @@ uint16_t dp_tx_me_send_convert_ucast(struct cdp_vdev *vdev_handle,
void dp_tx_me_alloc_descriptor(struct cdp_pdev *pdev);
void dp_tx_me_free_descriptor(struct cdp_pdev *pdev);
QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev,
uint32_t stats_type_upload_mask, uint32_t config_param_0,
uint32_t config_param_1, uint32_t config_param_2,
uint32_t config_param_3);
void dp_htt_stats_print_tag(uint8_t tag_type, uint32_t *tag_buf);
#endif /* #ifndef _DP_INTERNAL_H_ */

View File

@@ -36,12 +36,15 @@
#include <qdf_util.h>
#include "dp_peer.h"
#include "dp_rx_mon.h"
#include "htt_stats.h"
#define DP_INTR_POLL_TIMER_MS 10
#define DP_MCS_LENGTH (6*MAX_MCS)
#define DP_NSS_LENGTH (6*SS_COUNT)
#define DP_RXDMA_ERR_LENGTH (6*MAX_RXDMA_ERRORS)
#define DP_REO_ERR_LENGTH (6*REO_ERROR_TYPE_MAX)
#define DP_CURR_FW_STATS_AVAIL 19
#define DP_HTT_DBG_EXT_STATS_MAX 256
/**
* default_dscp_tid_map - Default DSCP-TID mapping
@@ -89,33 +92,31 @@ enum dp_fw_stats {
* currently supported
*/
const int dp_stats_mapping_table[][STATS_TYPE_MAX] = {
{HTT_DBG_EXT_STATS_RESET, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_PDEV_TX, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_PDEV_RX, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_PDEV_TX_HWQ, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_PDEV_TX_SCHED, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_PDEV_ERROR, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_PDEV_TQM, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_TQM_CMDQ, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_TX_DE_INFO, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_PDEV_TX_RATE, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_PDEV_RX_RATE, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_RX_RATE_STATS},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_TX_RATE_STATS},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_TX_HOST_STATS},
{HTT_DBG_EXT_STATS_TX_SELFGEN_INFO, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_TX_MU_HWQ, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_RING_IF_INFO, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_SRNG_INFO, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_SFM_INFO, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_PDEV_TX_MU, TXRX_HOST_STATS_INVALID},
{HTT_DBG_EXT_STATS_ACTIVE_PEERS_LIST, TXRX_HOST_STATS_INVALID},
/* Last ENUM for HTT FW STATS */
{DP_HTT_DBG_EXT_STATS_MAX, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_CLEAR_STATS},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_HOST_STATS_INVALID},
{TXRX_FW_STATS_INVALID, TXRX_RX_RATE_STATS},
{TXRX_FW_STATS_INVALID, TXRX_TX_RATE_STATS},
{TXRX_FW_STATS_INVALID, TXRX_TX_HOST_STATS},
{TXRX_FW_STATS_INVALID, TXRX_RX_HOST_STATS},
};
@@ -975,6 +976,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
hal_reo_setup(soc->hal_soc, &reo_params);
qdf_atomic_set(&soc->cmn_init_done, 1);
qdf_nbuf_queue_init(&soc->htt_stats_msg);
return 0;
fail1:
/*
@@ -3289,27 +3291,28 @@ static inline void dp_print_peer_stats(struct dp_peer *peer)
/**
* dp_print_host_stats()- Function to print the stats aggregated at host
* @vdev_handle: DP_VDEV handle
* @req: ol_txrx_stats_req
* @type: host stats type
*
* Available Stat types
* TXRX_CLEAR_STATS : Clear the stats
* TXRX_RX_RATE_STATS: Print Rx Rate Info
* TXRX_TX_RATE_STATS: Print Tx Rate Info
* TXRX_TX_HOST_STATS: Print Tx Stats
* TXRX_RX_HOST_STATS: Print Rx Stats
* TXRX_CLEAR_STATS : Clear the stats
*
* Return: 0 on success, print error message in case of failure
*/
static int
dp_print_host_stats(struct cdp_vdev *vdev_handle, struct ol_txrx_stats_req *req,
enum cdp_host_txrx_stats type)
dp_print_host_stats(struct cdp_vdev *vdev_handle, enum cdp_host_txrx_stats type)
{
struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle;
struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev;
dp_aggregate_pdev_stats(pdev);
switch (type) {
case TXRX_CLEAR_STATS:
dp_txrx_host_stats_clr(vdev);
break;
case TXRX_RX_RATE_STATS:
dp_print_rx_rates(vdev);
break;
@@ -3324,9 +3327,6 @@ dp_print_host_stats(struct cdp_vdev *vdev_handle, struct ol_txrx_stats_req *req,
dp_print_pdev_rx_stats(pdev);
dp_print_soc_rx_stats(pdev->soc);
break;
case TXRX_CLEAR_STATS:
dp_txrx_host_stats_clr(vdev);
break;
default:
DP_TRACE(FATAL, "Wrong Input For TxRx Host Stats");
break;
@@ -3335,14 +3335,14 @@ dp_print_host_stats(struct cdp_vdev *vdev_handle, struct ol_txrx_stats_req *req,
}
/*
* dp_get_peer_stats()- function to print peer stats
* dp_get_host_peer_stats()- function to print peer stats
* @pdev_handle: DP_PDEV handle
* @mac_addr: mac address of the peer
*
* Return: void
*/
static void
dp_get_peer_stats(struct cdp_pdev *pdev_handle, char *mac_addr)
dp_get_host_peer_stats(struct cdp_pdev *pdev_handle, char *mac_addr)
{
struct dp_peer *peer;
uint8_t local_id;
@@ -3352,6 +3352,48 @@ dp_get_peer_stats(struct cdp_pdev *pdev_handle, char *mac_addr)
dp_print_peer_stats(peer);
return;
}
/*
* dp_get_fw_peer_stats()- function to print peer stats
* @pdev_handle: DP_PDEV handle
* @mac_addr: mac address of the peer
* @cap: Type of htt stats requested
*
* Currently Supporting only MAC ID based requests Only
* 1: HTT_PEER_STATS_REQ_MODE_NO_QUERY
* 2: HTT_PEER_STATS_REQ_MODE_QUERY_TQM
* 3: HTT_PEER_STATS_REQ_MODE_FLUSH_TQM
*
* Return: void
*/
static void
dp_get_fw_peer_stats(struct cdp_pdev *pdev_handle, uint8_t *mac_addr,
uint32_t cap)
{
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
uint32_t config_param0 = 0;
uint32_t config_param1 = 0;
uint32_t config_param2 = 0;
uint32_t config_param3 = 0;
HTT_DBG_EXT_STATS_PEER_INFO_IS_MAC_ADDR_SET(config_param0, 1);
config_param0 |= (1 << (cap + 1));
config_param1 = 0x8f;
config_param2 |= (mac_addr[0] & 0x000000ff);
config_param2 |= ((mac_addr[1] << 8) & 0x0000ff00);
config_param2 |= ((mac_addr[2] << 16) & 0x00ff0000);
config_param2 |= ((mac_addr[3] << 24) & 0xff000000);
config_param3 |= (mac_addr[4] & 0x000000ff);
config_param3 |= ((mac_addr[5] << 8) & 0x0000ff00);
dp_h2t_ext_stats_msg_send(pdev, HTT_DBG_EXT_STATS_PEER_INFO,
config_param0, config_param1, config_param2,
config_param3);
}
/*
* dp_set_vdev_param: function to set parameters in vdev
* @param: parameter type to be set
@@ -3436,16 +3478,35 @@ static void dp_set_pdev_dscp_tid_map_wifi3(struct cdp_pdev *pdev_handle,
return;
}
/**
* dp_fw_stats_process(): Process TxRX FW stats request
* @vdev_handle: DP VDEV handle
* @val: value passed by user
*
* return: int
*/
static int dp_fw_stats_process(struct cdp_vdev *vdev_handle, uint32_t val)
{
struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle;
struct dp_pdev *pdev = NULL;
if (!vdev) {
DP_TRACE(NONE, "VDEV not found");
return 1;
}
pdev = vdev->pdev;
return dp_h2t_ext_stats_msg_send(pdev, val, 0, 0, 0, 0);
}
/*
* dp_txrx_stats() - function to map to firmware and host stats
* @vdev: virtual handle
* @req: statistics request handle
* @stats: type of statistics requested
*
* Return: integer
*/
static int dp_txrx_stats(struct cdp_vdev *vdev,
struct ol_txrx_stats_req *req, enum cdp_stats stats)
static int dp_txrx_stats(struct cdp_vdev *vdev, enum cdp_stats stats)
{
int host_stats;
int fw_stats;
@@ -3453,6 +3514,12 @@ static int dp_txrx_stats(struct cdp_vdev *vdev,
if (stats >= CDP_TXRX_MAX_STATS)
return 0;
/*
* DP_CURR_FW_STATS_AVAIL: no of FW stats currently available
* has to be updated if new FW HTT stats added
*/
if (stats > CDP_TXRX_STATS_HTT_MAX)
stats = stats + DP_CURR_FW_STATS_AVAIL - DP_HTT_DBG_EXT_STATS_MAX;
fw_stats = dp_stats_mapping_table[stats][STATS_FW];
host_stats = dp_stats_mapping_table[stats][STATS_HOST];
@@ -3460,11 +3527,12 @@ static int dp_txrx_stats(struct cdp_vdev *vdev,
"stats: %u fw_stats_type: %d host_stats_type: %d",
stats, fw_stats, host_stats);
/* TODO: Firmware Mapping not implemented */
if (fw_stats != TXRX_FW_STATS_INVALID)
return dp_fw_stats_process(vdev, fw_stats);
if ((host_stats != TXRX_HOST_STATS_INVALID) &&
(host_stats <= TXRX_HOST_STATS_MAX))
return dp_print_host_stats(vdev, req, host_stats);
return dp_print_host_stats(vdev, host_stats);
else
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
"Wrong Input for TxRx Stats");
@@ -3751,8 +3819,8 @@ static struct cdp_mon_ops dp_ops_mon = {
};
static struct cdp_host_stats_ops dp_ops_host_stats = {
.txrx_host_stats_get = dp_print_host_stats,
.txrx_per_peer_stats = dp_get_peer_stats,
.txrx_per_peer_stats = dp_get_host_peer_stats,
.get_fw_peer_stats = dp_get_fw_peer_stats,
/* TODO */
};

262
dp/wifi3.0/dp_stats.c Normal file
View File

@@ -0,0 +1,262 @@
/*
* Copyright (c) 2017 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "qdf_types.h"
#include "htt_stats.h"
#include "dp_types.h"
#include "dp_internal.h"
#define DP_MAX_STRING_LEN 500
/* these values are fixed in the next gerrit */
#define DP_HTT_DATA_LEN 1
#define DP_HTT_URRN_STATS_LEN 1
#define DP_HTT_FLUSH_ERRS_LEN 1
#define DP_HTT_SIFS_STATUS_LEN 1
#define DP_HTT_PHY_ERRS_LEN 1
#define DP_HTT_HW_INTR_NAME_LEN HTT_STATS_MAX_HW_INTR_NAME_LEN
#define DP_HTT_HW_MODULE_NAME_LEN HTT_STATS_MAX_HW_MODULE_NAME_LEN
#define DP_HTT_COUNTER_NAME_LEN HTT_MAX_COUNTER_NAME
#define DP_HTT_PEER_DETAILS_LEN 1
#define DP_HTT_MU_MIMO_SCH_STATS_TLV_LEN 1
#define DP_HTT_MU_MIMO_MPDU_STATS_TLV_LEN 1
#define DP_HTT_DIFS_LATENCY_HIST_LEN 1
#define DP_HTT_CMD_RESULT_LEN 1
#define DP_HTT_CMD_STALL_STATUS_LEN 1
#define DP_HTT_FES_RESULT_LEN 1
#define DP_HTT_SCHED_CMD_POSTED_LEN 1
#define DP_HTT_SCHED_CMD_REAPED_LEN 1
#define DP_HTT_GEN_MPDU_END_REASON_LEN 1
#define DP_HTT_LIST_MPDU_END_REASON_LEN 1
#define DP_HTT_LIST_MPDU_CNT_HIST_LEN 1
#define DP_HTT_LOW_WM_HIT_COUNT_LEN HTT_STATS_LOW_WM_BINS
#define DP_HTT_HIGH_WM_HIT_COUNT_LEN HTT_STATS_HIGH_WM_BINS
#define DP_HTT_DWORDS_USED_BY_USER_N_LEN 1
#define DP_HTT_TX_MCS_LEN HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS
#define DP_HTT_TX_SU_MCS_LEN HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS
#define DP_HTT_TX_MU_MCS_LEN HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS
#define DP_HTT_TX_NSS_LEN HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS
#define DP_HTT_TX_BW_LEN HTT_TX_PDEV_STATS_NUM_BW_COUNTERS
#define DP_HTT_TX_STBC_LEN HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS
#define DP_HTT_TX_PREAM_LEN HTT_TX_PDEV_STATS_NUM_PREAMBLE_TYPES
#define DP_HTT_TX_GI_LEN HTT_TX_PDEV_STATS_NUM_GI_COUNTERS
#define DP_HTT_TX_DCM_LEN HTT_TX_PDEV_STATS_NUM_DCM_COUNTERS
#define DP_HTT_RX_MCS_LEN HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS
#define DP_HTT_RX_NSS_LEN HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS
#define DP_HTT_RX_DCM_LEN HTT_RX_PDEV_STATS_NUM_DCM_COUNTERS
#define DP_HTT_RX_STBC_LEN HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS
#define DP_HTT_RX_BW_LEN HTT_RX_PDEV_STATS_NUM_BW_COUNTERS
#define DP_HTT_RX_PREAM_LEN HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES
#define DP_HTT_RSSI_CHAIN_LEN HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS
#define DP_HTT_RX_GI_LEN HTT_RX_PDEV_STATS_NUM_GI_COUNTERS
#define DP_HTT_REFILL_RING_EMPTY_CNT_LEN 1
#define DP_HTT_REFILL_RING_NUM_REFILL_LEN 1
#define DP_HTT_FW_RING_MGMT_SUBTYPE_LEN HTT_STATS_SUBTYPE_MAX
#define DP_HTT_FW_RING_CTRL_SUBTYPE_LEN HTT_STATS_SUBTYPE_MAX
#define DP_HTT_FW_RING_MPDU_ERR_LEN HTT_RX_STATS_RXDMA_MAX_ERR
#define DP_HTT_FW_MPDU_DROP_LEN 1
#define DP_HTT_TID_NAME_LEN MAX_HTT_TID_NAME
/* TODO:Below stat function is for initial testing
* Further functions will be added after reviews on the FW side are complete
*/
/**
* dp_print_tx_pdev_stats_cmn_tlv: display htt_tx_pdev_stats_cmn_tlv
* @dp_htt_tag:pointer to structure htt_tx_pdev_stats_cmn_tlv
*
* return:void
*/
static inline void dp_print_tx_pdev_stats_cmn_tlv(uint32_t *tag_buf)
{
htt_tx_pdev_stats_cmn_tlv *dp_htt_tag =
(htt_tx_pdev_stats_cmn_tlv *)tag_buf;
DP_TRACE_STATS(NONE, "Pdev Stats:\n");
DP_TRACE_STATS(NONE, "mac_id__word = %d",
dp_htt_tag->mac_id__word);
DP_TRACE_STATS(NONE, "hw_queued = %d",
dp_htt_tag->hw_queued);
DP_TRACE_STATS(NONE, "hw_reaped = %d",
dp_htt_tag->hw_reaped);
DP_TRACE_STATS(NONE, "underrun = %d",
dp_htt_tag->underrun);
DP_TRACE_STATS(NONE, "hw_paused = %d",
dp_htt_tag->hw_paused);
DP_TRACE_STATS(NONE, "hw_flush = %d",
dp_htt_tag->hw_flush);
DP_TRACE_STATS(NONE, "hw_filt = %d",
dp_htt_tag->hw_filt);
DP_TRACE_STATS(NONE, "tx_abort = %d",
dp_htt_tag->tx_abort);
DP_TRACE_STATS(NONE, "mpdu_requeued = %d",
dp_htt_tag->mpdu_requed);
DP_TRACE_STATS(NONE, "tx_xretry = %d",
dp_htt_tag->tx_xretry);
DP_TRACE_STATS(NONE, "data_rc = %d",
dp_htt_tag->data_rc);
DP_TRACE_STATS(NONE, "mpdu_dropped_xretry = %d",
dp_htt_tag->mpdu_dropped_xretry);
DP_TRACE_STATS(NONE, "illegal_rate_phy_err = %d",
dp_htt_tag->illgl_rate_phy_err);
DP_TRACE_STATS(NONE, "cont_xretry = %d",
dp_htt_tag->cont_xretry);
DP_TRACE_STATS(NONE, "tx_timeout = %d",
dp_htt_tag->tx_timeout);
DP_TRACE_STATS(NONE, "pdev_resets = %d",
dp_htt_tag->pdev_resets);
DP_TRACE_STATS(NONE, "phy_underrun = %d",
dp_htt_tag->phy_underrun);
DP_TRACE_STATS(NONE, "txop_ovf = %d",
dp_htt_tag->txop_ovf);
DP_TRACE_STATS(NONE, "seq_posted = %d",
dp_htt_tag->seq_posted);
DP_TRACE_STATS(NONE, "seq_failed_queueing = %d",
dp_htt_tag->seq_failed_queueing);
DP_TRACE_STATS(NONE, "seq_completed = %d",
dp_htt_tag->seq_completed);
DP_TRACE_STATS(NONE, "seq_restarted = %d",
dp_htt_tag->seq_restarted);
DP_TRACE_STATS(NONE, "mu_seq_posted = %d",
dp_htt_tag->mu_seq_posted);
DP_TRACE_STATS(NONE, "mpdu_count_tqm = %d",
dp_htt_tag->mpdu_count_tqm);
DP_TRACE_STATS(NONE, "msdu_count_tqm = %d",
dp_htt_tag->msdu_count_tqm);
DP_TRACE_STATS(NONE, "mpdu_removed_tqm = %d",
dp_htt_tag->mpdu_removed_tqm);
DP_TRACE_STATS(NONE, "msdu_removed_tqm = %d",
dp_htt_tag->msdu_removed_tqm);
DP_TRACE_STATS(NONE, "mpdus_sw_flush = %d",
dp_htt_tag->mpdus_sw_flush);
DP_TRACE_STATS(NONE, "mpdus_hw_filter = %d",
dp_htt_tag->mpdus_hw_filter);
DP_TRACE_STATS(NONE, "mpdus_truncated = %d",
dp_htt_tag->mpdus_truncated);
DP_TRACE_STATS(NONE, "mpdus_ack_failed = %d",
dp_htt_tag->mpdus_ack_failed);
DP_TRACE_STATS(NONE, "mpdus_expired = %d",
dp_htt_tag->mpdus_expired);
DP_TRACE_STATS(NONE, "mpdus_seq_hw_retry = %d",
dp_htt_tag->mpdus_seq_hw_retry);
DP_TRACE_STATS(NONE, "ack_tlv_proc = %d",
dp_htt_tag->ack_tlv_proc);
DP_TRACE_STATS(NONE, "coex_abort_mpdu_cnt_valid = %d",
dp_htt_tag->
coex_abort_mpdu_cnt_valid);
DP_TRACE_STATS(NONE, "coex_abort_mpdu_cnt = %d",
dp_htt_tag->coex_abort_mpdu_cnt);
}
/**
* dp_print_tx_pdev_stats_urrn_tlv_v: display htt_tx_pdev_stats_urrn_tlv_v
* @tag_buf: buffer containing the tlv
*
* return:void
*/
static inline void dp_print_tx_pdev_stats_urrn_tlv_v(uint32_t *tag_buf)
{
htt_tx_pdev_stats_urrn_tlv_v *dp_htt_tag =
(htt_tx_pdev_stats_urrn_tlv_v *)tag_buf;
uint8_t i;
uint16_t index = 0;
char urrn_stats[DP_MAX_STRING_LEN];
uint32_t tag_len = (HTT_STATS_TLV_LENGTH_GET(*tag_buf) >> 2);
tag_len = qdf_min(tag_len, (uint32_t)HTT_TX_PDEV_MAX_URRN_STATS);
DP_TRACE_STATS(NONE, "Pdev Underun Stats:\n");
for (i = 0; i < tag_len; i++) {
index += qdf_snprint(&urrn_stats[index],
DP_MAX_STRING_LEN - index, " %d,",
dp_htt_tag->urrn_stats[i]);
}
DP_TRACE_STATS(NONE, "urrn_stats = %s", urrn_stats);
}
/*
* dp_print_tx_pdev_stats_flush_tlv_v: display htt_tx_pdev_stats_flush_tlv_v
* @tag_buf: buffer containing the tlv *
* return:void
*/
static inline void dp_print_tx_pdev_stats_flush_tlv_v(uint32_t *tag_buf)
{
htt_tx_pdev_stats_flush_tlv_v *dp_htt_tag =
(htt_tx_pdev_stats_flush_tlv_v *)tag_buf;
uint8_t i;
uint8_t index = 0;
char flush_errs[DP_MAX_STRING_LEN];
uint32_t tag_len = (HTT_STATS_TLV_LENGTH_GET(*tag_buf) >> 2);
tag_len = qdf_min(tag_len,
(uint32_t)HTT_TX_PDEV_MAX_FLUSH_REASON_STATS);
DP_TRACE_STATS(NONE, "Pdev Flush Stats:\n");
for (i = 0; i < tag_len; i++) {
index += qdf_snprint(&flush_errs[index],
DP_MAX_STRING_LEN - index, " %d,",
dp_htt_tag->flush_errs[i]);
}
DP_TRACE_STATS(NONE, "flush_errs = %s ", flush_errs);
}
/*
* dp_print_tx_pdev_stats_sifs_tlv_v: display htt_tx_pdev_stats_sifs_tlv_v
* @tag_buf: buffer containing the tlv *
* return:void
*/
static inline void dp_print_tx_pdev_stats_sifs_tlv_v(uint32_t *tag_buf)
{
htt_tx_pdev_stats_sifs_tlv_v *dp_htt_tag =
(htt_tx_pdev_stats_sifs_tlv_v *)tag_buf;
uint8_t i;
uint8_t index = 0;
char sifs_status[DP_MAX_STRING_LEN];
uint32_t tag_len = (HTT_STATS_TLV_LENGTH_GET(*tag_buf) >> 2);
tag_len = qdf_min(tag_len, (uint32_t)HTT_TX_PDEV_MAX_SIFS_BURST_STATS);
DP_TRACE_STATS(NONE, "Pdev SIFS Stats:\n");
for (i = 0; i < tag_len; i++) {
index += qdf_snprint(&sifs_status[index],
DP_MAX_STRING_LEN - index, " %d,",
dp_htt_tag->sifs_status[i]);
}
DP_TRACE_STATS(NONE, "sifs_status = %s ", sifs_status);
}
/**
* dp_htt_stats_print_tag: function to select the tag type and
* print the corresponding tag structure
* @tag_type: tag type that is to be printed
* @tag_buf: pointer to the tag structure
*
* return: void
*/
void dp_htt_stats_print_tag(uint8_t tag_type, uint32_t *tag_buf)
{
switch (tag_type) {
case HTT_STATS_TX_PDEV_CMN_TAG:
dp_print_tx_pdev_stats_cmn_tlv(tag_buf);
break;
case HTT_STATS_TX_PDEV_UNDERRUN_TAG:
dp_print_tx_pdev_stats_urrn_tlv_v(tag_buf);
break;
case HTT_STATS_TX_PDEV_SIFS_TAG:
dp_print_tx_pdev_stats_sifs_tlv_v(tag_buf);
break;
default:
break;
}
}

View File

@@ -633,6 +633,10 @@ struct dp_soc {
u_int16_t pdev_bs_inact_interval;
/* Inactivity timer */
#endif /* QCA_SUPPORT_SON */
/* T2H Ext stats message queue */
qdf_nbuf_queue_t htt_stats_msg;
/* T2H Ext stats message length */
uint32_t htt_msg_len;
};
#define MAX_RX_MAC_RINGS 2
/* Same as NAC_MAX_CLENT */

View File

@@ -220,8 +220,8 @@ static inline bool __qdf_is_macaddr_equal(struct qdf_mac_addr *mac_addr1,
/**
* @brief memory barriers.
*/
#define __qdf_min(_a, _b) min(a, b)
#define __qdf_max(_a, _b) max(a, b)
#define __qdf_min(_a, _b) min(_a, _b)
#define __qdf_max(_a, _b) max(_a, _b)
#define MEMINFO_KB(x) ((x) << (PAGE_SHIFT - 10)) /* In kilobytes */