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:
@@ -4461,6 +4461,38 @@ dp_get_host_peer_stats(struct cdp_pdev *pdev_handle, char *mac_addr)
|
|||||||
return;
|
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
|
* dp_enable_enhanced_stats()- API to enable enhanced statistcs
|
||||||
* @pdev_handle: DP_PDEV handle
|
* @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;
|
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
|
||||||
pdev->enhanced_stats_en = 1;
|
pdev->enhanced_stats_en = 1;
|
||||||
|
|
||||||
|
dp_ppdu_ring_cfg(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -28,6 +28,107 @@
|
|||||||
#include "dp_internal.h"
|
#include "dp_internal.h"
|
||||||
#include "qdf_mem.h" /* qdf_mem_malloc,free */
|
#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
|
* dp_rx_mon_status_process_tlv() - Process status TLV in status
|
||||||
* buffer on Rx status Queue posted by status SRNG processing.
|
* 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);
|
qdf_nbuf_free(status_nbuf);
|
||||||
|
|
||||||
if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) {
|
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;
|
pdev->mon_ppdu_status = DP_PPDU_STATUS_DONE;
|
||||||
dp_rx_mon_dest_process(soc, mac_id, quota);
|
dp_rx_mon_dest_process(soc, mac_id, quota);
|
||||||
pdev->mon_ppdu_status = DP_PPDU_STATUS_START;
|
pdev->mon_ppdu_status = DP_PPDU_STATUS_START;
|
||||||
|
@@ -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",
|
"[%s][%d] ppdu_end_e len=%d\n",
|
||||||
__func__, __LINE__, tlv_len);
|
__func__, __LINE__, tlv_len);
|
||||||
/* This is followed by sub-TLVs of PPDU_END */
|
/* 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;
|
break;
|
||||||
|
|
||||||
case WIFIRXPCU_PPDU_END_INFO_E:
|
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;
|
break;
|
||||||
|
|
||||||
case WIFIRX_PPDU_END_USER_STATS_E:
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case WIFIRX_PPDU_END_USER_STATS_EXT_E:
|
case WIFIRX_PPDU_END_USER_STATS_EXT_E:
|
||||||
break;
|
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,
|
HAL_RX_OFFSET(PHYRX_RSSI_LEGACY_3,
|
||||||
RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS);
|
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,
|
value = HAL_RX_GET(rssi_info_tlv,
|
||||||
RECEIVE_RSSI_INFO_0, RSSI_PRI20_CHAIN0);
|
RECEIVE_RSSI_INFO_0, RSSI_PRI20_CHAIN0);
|
||||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
|
||||||
|
@@ -121,6 +121,7 @@
|
|||||||
* @he_sig_A2: HE (11ax) sig A1 field
|
* @he_sig_A2: HE (11ax) sig A1 field
|
||||||
* @he_sig_b_user: HE (11ax) sig B user field
|
* @he_sig_b_user: HE (11ax) sig B user field
|
||||||
* @he_sig_b_user_known: HE (11ax) sig B user known 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_freq: Capture channel frequency
|
||||||
* @chan_num: Capture channel number
|
* @chan_num: Capture channel number
|
||||||
* @chan_flags: Bitmap of Channel flags, IEEE80211_CHAN_TURBO,
|
* @chan_flags: Bitmap of Channel flags, IEEE80211_CHAN_TURBO,
|
||||||
@@ -138,12 +139,20 @@
|
|||||||
* @ant_signal_db: Rx packet RSSI
|
* @ant_signal_db: Rx packet RSSI
|
||||||
* @nr_ant: Number of Antennas used for streaming
|
* @nr_ant: Number of Antennas used for streaming
|
||||||
* @mcs: MCS index of Rx frame
|
* @mcs: MCS index of Rx frame
|
||||||
|
* @nss: Number of spatial streams
|
||||||
* @bw: bandwidth of rx frame
|
* @bw: bandwidth of rx frame
|
||||||
* @is_stbc: Is STBC enabled
|
* @is_stbc: Is STBC enabled
|
||||||
* @sgi: Rx frame short guard interval
|
* @sgi: Rx frame short guard interval
|
||||||
|
* @he_re: HE range extension
|
||||||
* @ldpc: ldpc enabled
|
* @ldpc: ldpc enabled
|
||||||
* @beamformed: Is frame beamformed.
|
* @beamformed: Is frame beamformed.
|
||||||
* @he_sig_b_common_RU[4]: HE (11ax) common RU assignment index
|
* @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 {
|
struct mon_rx_status {
|
||||||
uint64_t tsft;
|
uint64_t tsft;
|
||||||
@@ -151,6 +160,7 @@ struct mon_rx_status {
|
|||||||
uint32_t he_sig_A2;
|
uint32_t he_sig_A2;
|
||||||
uint32_t he_sig_b_user;
|
uint32_t he_sig_b_user;
|
||||||
uint32_t he_sig_b_user_known;
|
uint32_t he_sig_b_user_known;
|
||||||
|
uint32_t preamble_type;
|
||||||
uint16_t chan_freq;
|
uint16_t chan_freq;
|
||||||
uint16_t chan_num;
|
uint16_t chan_num;
|
||||||
uint16_t chan_flags;
|
uint16_t chan_flags;
|
||||||
@@ -167,6 +177,7 @@ struct mon_rx_status {
|
|||||||
uint8_t ant_signal_db;
|
uint8_t ant_signal_db;
|
||||||
uint8_t nr_ant;
|
uint8_t nr_ant;
|
||||||
uint8_t mcs;
|
uint8_t mcs;
|
||||||
|
uint8_t nss;
|
||||||
uint8_t bw;
|
uint8_t bw;
|
||||||
uint8_t vht_flag_values1;
|
uint8_t vht_flag_values1;
|
||||||
uint8_t vht_flag_values2;
|
uint8_t vht_flag_values2;
|
||||||
@@ -175,9 +186,15 @@ struct mon_rx_status {
|
|||||||
uint8_t vht_flag_values5;
|
uint8_t vht_flag_values5;
|
||||||
uint8_t is_stbc;
|
uint8_t is_stbc;
|
||||||
uint8_t sgi;
|
uint8_t sgi;
|
||||||
|
uint8_t he_re;
|
||||||
uint8_t ldpc;
|
uint8_t ldpc;
|
||||||
uint8_t beamformed;
|
uint8_t beamformed;
|
||||||
uint8_t he_sig_b_common_RU[4];
|
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 */
|
/* Masks for HE SIG known fields in mon_rx_status structure */
|
||||||
|
@@ -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)
|
#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) \
|
#define qdf_wait_queue_interruptible(wait_queue, condition) \
|
||||||
__qdf_wait_queue_interruptible(wait_queue, condition)
|
__qdf_wait_queue_interruptible(wait_queue, condition)
|
||||||
|
|
||||||
|
@@ -168,6 +168,12 @@ static inline bool __qdf_test_and_clear_bit(unsigned int nr,
|
|||||||
return __test_and_clear_bit(nr, addr);
|
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'
|
* __qdf_set_macaddr_broadcast() - set a QDF MacAddress to the 'broadcast'
|
||||||
* @mac_addr: pointer to the qdf MacAddress to set to broadcast
|
* @mac_addr: pointer to the qdf MacAddress to set to broadcast
|
||||||
|
Reference in New Issue
Block a user