qcacmn: Add PPDU Statistics Support for Rx datapath

Add support for processing rssi, mcs etc fields from
PPDU status ring and delivering to CDP interface

Change-Id: I312bef20605594645bae6ec748f0b59e4d427075
CRs-Fixed: 2098696
This commit is contained in:
Anish Nataraj
2017-08-18 19:41:17 +05:30
committed by snandini
parent 038d090817
commit 38a2956c7a
6 changed files with 200 additions and 0 deletions

View File

@@ -4461,6 +4461,38 @@ dp_get_host_peer_stats(struct cdp_pdev *pdev_handle, char *mac_addr)
return;
}
/*
* dp_ppdu_ring_cfg()- Configure PPDU Stats ring
* @pdev: DP_PDEV handle
*
* Return: void
*/
static void
dp_ppdu_ring_cfg(struct dp_pdev *pdev)
{
struct htt_rx_ring_tlv_filter htt_tlv_filter = {0};
htt_tlv_filter.mpdu_start = 0;
htt_tlv_filter.msdu_start = 0;
htt_tlv_filter.packet = 0;
htt_tlv_filter.msdu_end = 0;
htt_tlv_filter.mpdu_end = 0;
htt_tlv_filter.packet_header = 1;
htt_tlv_filter.attention = 1;
htt_tlv_filter.ppdu_start = 1;
htt_tlv_filter.ppdu_end = 1;
htt_tlv_filter.ppdu_end_user_stats = 1;
htt_tlv_filter.ppdu_end_user_stats_ext = 1;
htt_tlv_filter.ppdu_end_status_done = 1;
htt_tlv_filter.enable_fp = 1;
htt_tlv_filter.enable_md = 0;
htt_tlv_filter.enable_mo = 0;
htt_h2t_rx_ring_cfg(pdev->soc->htt_handle, pdev->pdev_id,
pdev->rxdma_mon_status_ring.hal_srng, RXDMA_MONITOR_STATUS,
RX_BUFFER_SIZE, &htt_tlv_filter);
}
/*
* dp_enable_enhanced_stats()- API to enable enhanced statistcs
* @pdev_handle: DP_PDEV handle
@@ -4472,6 +4504,8 @@ dp_enable_enhanced_stats(struct cdp_pdev *pdev_handle)
{
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
pdev->enhanced_stats_en = 1;
dp_ppdu_ring_cfg(pdev);
}
/*

View File

@@ -28,6 +28,107 @@
#include "dp_internal.h"
#include "qdf_mem.h" /* qdf_mem_malloc,free */
/**
* dp_rx_populate_cdp_indication_ppdu() - Populate cdp rx indication structure
* @soc: core txrx main context
* @ppdu_info: ppdu info structure from ppdu ring
* @ppdu_nbuf: qdf nbuf abstraction for linux skb
*
* Return: none
*/
#ifdef FEATURE_PERPKT_INFO
static inline void
dp_rx_populate_cdp_indication_ppdu(struct dp_soc *soc,
struct hal_rx_ppdu_info *ppdu_info,
qdf_nbuf_t ppdu_nbuf)
{
struct dp_peer *peer;
struct dp_ast_entry *ast_entry;
struct cdp_rx_indication_ppdu *cdp_rx_ppdu;
uint32_t ast_index;
cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)ppdu_nbuf->data;
ast_index = ppdu_info->rx_status.ast_index;
if (ast_index > (WLAN_UMAC_PSOC_MAX_PEERS * 2)) {
cdp_rx_ppdu->peer_id = HTT_INVALID_PEER;
return;
}
ast_entry = soc->ast_table[ast_index];
if (!ast_entry) {
cdp_rx_ppdu->peer_id = HTT_INVALID_PEER;
return;
}
peer = ast_entry->peer;
if (!peer || peer->peer_ids[0] == HTT_INVALID_PEER) {
cdp_rx_ppdu->peer_id = HTT_INVALID_PEER;
return;
}
cdp_rx_ppdu->peer_id = peer->peer_ids[0];
cdp_rx_ppdu->ppdu_id = ppdu_info->com_info.ppdu_id;
cdp_rx_ppdu->duration = ppdu_info->rx_status.duration;
cdp_rx_ppdu->u.bw = ppdu_info->rx_status.bw;
cdp_rx_ppdu->u.nss = ppdu_info->rx_status.nss;
cdp_rx_ppdu->u.mcs = ppdu_info->rx_status.mcs;
cdp_rx_ppdu->u.preamble = ppdu_info->rx_status.preamble_type;
cdp_rx_ppdu->rssi = ppdu_info->rx_status.rssi_comb;
cdp_rx_ppdu->timestamp = ppdu_info->com_info.ppdu_timestamp;
cdp_rx_ppdu->channel = ppdu_info->rx_status.chan_freq;
}
#else
static inline void
dp_rx_populate_cdp_indication_ppdu(struct dp_soc *soc,
struct hal_rx_ppdu_info *ppdu_info,
qdf_nbuf_t ppdu_nbuf)
{
}
#endif
/**
* dp_rx_handle_ppdu_stats() - Allocate and deliver ppdu stats to cdp layer
* @soc: core txrx main context
* @pdev: pdev strcuture
* @ppdu_info: structure for rx ppdu ring
*
* Return: none
*/
#ifdef FEATURE_PERPKT_INFO
static inline void
dp_rx_handle_ppdu_stats(struct dp_soc *soc, struct dp_pdev *pdev,
struct hal_rx_ppdu_info *ppdu_info)
{
qdf_nbuf_t ppdu_nbuf;
struct dp_peer *peer;
struct cdp_rx_indication_ppdu *cdp_rx_ppdu;
ppdu_nbuf = qdf_nbuf_alloc(pdev->osif_pdev,
sizeof(struct hal_rx_ppdu_info), 0, 0, FALSE);
if (ppdu_nbuf) {
dp_rx_populate_cdp_indication_ppdu(soc, ppdu_info, ppdu_nbuf);
qdf_nbuf_put_tail(ppdu_nbuf,
sizeof(struct cdp_rx_indication_ppdu));
cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)ppdu_nbuf->data;
peer = dp_peer_find_by_id(soc, cdp_rx_ppdu->peer_id);
if (peer && cdp_rx_ppdu->peer_id != HTT_INVALID_PEER) {
dp_wdi_event_handler(WDI_EVENT_RX_PPDU_DESC, soc,
ppdu_nbuf, cdp_rx_ppdu->peer_id,
WDI_NO_VAL, pdev->pdev_id);
} else
qdf_nbuf_free(ppdu_nbuf);
}
}
#else
static inline void
dp_rx_handle_ppdu_stats(struct dp_soc *soc, struct dp_pdev *pdev,
struct hal_rx_ppdu_info *ppdu_info)
{
}
#endif
/**
* dp_rx_mon_status_process_tlv() - Process status TLV in status
* buffer on Rx status Queue posted by status SRNG processing.
@@ -79,6 +180,8 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id,
qdf_nbuf_free(status_nbuf);
if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) {
if (pdev->enhanced_stats_en)
dp_rx_handle_ppdu_stats(soc, pdev, ppdu_info);
pdev->mon_ppdu_status = DP_PPDU_STATUS_DONE;
dp_rx_mon_dest_process(soc, mac_id, quota);
pdev->mon_ppdu_status = DP_PPDU_STATUS_START;

View File

@@ -469,6 +469,10 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
"[%s][%d] ppdu_end_e len=%d\n",
__func__, __LINE__, tlv_len);
/* This is followed by sub-TLVs of PPDU_END */
ppdu_info->rx_status.duration =
HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_8,
RX_PPDU_DURATION);
break;
case WIFIRXPCU_PPDU_END_INFO_E:
@@ -481,7 +485,26 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
break;
case WIFIRX_PPDU_END_USER_STATS_E:
{
unsigned long tid = 0;
ppdu_info->rx_status.ast_index =
HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_4,
AST_INDEX);
tid = HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_12,
RECEIVED_QOS_DATA_TID_BITMAP);
ppdu_info->rx_status.tid = qdf_find_first_bit(&tid, sizeof(tid)*8);
ppdu_info->rx_status.mcs =
HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_1,
MCS);
ppdu_info->rx_status.nss =
HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_1,
NSS);
ppdu_info->rx_status.first_data_seq_ctrl =
HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_3,
DATA_SEQUENCE_CONTROL_INFO_VALID);
break;
}
case WIFIRX_PPDU_END_USER_STATS_EXT_E:
break;
@@ -590,6 +613,14 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
HAL_RX_OFFSET(PHYRX_RSSI_LEGACY_3,
RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS);
ppdu_info->rx_status.rssi_comb = HAL_RX_GET(rssi_info_tlv,
PHYRX_RSSI_LEGACY_35, RSSI_COMB);
ppdu_info->rx_status.bw = HAL_RX_GET(rssi_info_tlv,
PHYRX_RSSI_LEGACY_35, RECEIVE_BANDWIDTH);
ppdu_info->rx_status.preamble_type = HAL_RX_GET(rssi_info_tlv,
PHYRX_RSSI_LEGACY_0, RECEPTION_TYPE);
ppdu_info->rx_status.he_re = 0;
value = HAL_RX_GET(rssi_info_tlv,
RECEIVE_RSSI_INFO_0, RSSI_PRI20_CHAIN0);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,

View File

@@ -121,6 +121,7 @@
* @he_sig_A2: HE (11ax) sig A1 field
* @he_sig_b_user: HE (11ax) sig B user field
* @he_sig_b_user_known: HE (11ax) sig B user known field
* @preamble_type: Preamble type in radio header
* @chan_freq: Capture channel frequency
* @chan_num: Capture channel number
* @chan_flags: Bitmap of Channel flags, IEEE80211_CHAN_TURBO,
@@ -138,12 +139,20 @@
* @ant_signal_db: Rx packet RSSI
* @nr_ant: Number of Antennas used for streaming
* @mcs: MCS index of Rx frame
* @nss: Number of spatial streams
* @bw: bandwidth of rx frame
* @is_stbc: Is STBC enabled
* @sgi: Rx frame short guard interval
* @he_re: HE range extension
* @ldpc: ldpc enabled
* @beamformed: Is frame beamformed.
* @he_sig_b_common_RU[4]: HE (11ax) common RU assignment index
* @rssi_comb: Combined RSSI
* @duration: 802.11 Duration
* @first_data_seq_ctrl: Sequence ctrl field of first data frame
* @ast_index: AST table hash index
* @tid: QoS traffic tid number
*
*/
struct mon_rx_status {
uint64_t tsft;
@@ -151,6 +160,7 @@ struct mon_rx_status {
uint32_t he_sig_A2;
uint32_t he_sig_b_user;
uint32_t he_sig_b_user_known;
uint32_t preamble_type;
uint16_t chan_freq;
uint16_t chan_num;
uint16_t chan_flags;
@@ -167,6 +177,7 @@ struct mon_rx_status {
uint8_t ant_signal_db;
uint8_t nr_ant;
uint8_t mcs;
uint8_t nss;
uint8_t bw;
uint8_t vht_flag_values1;
uint8_t vht_flag_values2;
@@ -175,9 +186,15 @@ struct mon_rx_status {
uint8_t vht_flag_values5;
uint8_t is_stbc;
uint8_t sgi;
uint8_t he_re;
uint8_t ldpc;
uint8_t beamformed;
uint8_t he_sig_b_common_RU[4];
int8_t rssi_comb;
uint16_t duration;
int16_t first_data_seq_ctrl;
uint32_t ast_index;
uint32_t tid;
};
/* Masks for HE SIG known fields in mon_rx_status structure */

View File

@@ -153,6 +153,15 @@ static inline int qdf_status_to_os_return(QDF_STATUS status)
*/
#define qdf_test_and_clear_bit(nr, addr) __qdf_test_and_clear_bit(nr, addr)
/**
* qdf_find_first_bit() - find first bit position in address
* @addr: address buffer pointer
* @nbits: number of bits
*
* Return: position first set bit in addr
*/
#define qdf_find_first_bit(addr, nbits) __qdf_find_first_bit(addr, nbits)
#define qdf_wait_queue_interruptible(wait_queue, condition) \
__qdf_wait_queue_interruptible(wait_queue, condition)

View File

@@ -168,6 +168,12 @@ static inline bool __qdf_test_and_clear_bit(unsigned int nr,
return __test_and_clear_bit(nr, addr);
}
static inline unsigned long __qdf_find_first_bit(unsigned long *addr,
unsigned long nbits)
{
return find_first_bit(addr, nbits);
}
/**
* __qdf_set_macaddr_broadcast() - set a QDF MacAddress to the 'broadcast'
* @mac_addr: pointer to the qdf MacAddress to set to broadcast