diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 498b74712a..fb5613a734 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -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); } /* diff --git a/dp/wifi3.0/dp_rx_mon_status.c b/dp/wifi3.0/dp_rx_mon_status.c index 05bb18eefb..b053058470 100644 --- a/dp/wifi3.0/dp_rx_mon_status.c +++ b/dp/wifi3.0/dp_rx_mon_status.c @@ -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; diff --git a/hal/wifi3.0/hal_api_mon.h b/hal/wifi3.0/hal_api_mon.h index 50ec3dcf67..ba0586e3a9 100644 --- a/hal/wifi3.0/hal_api_mon.h +++ b/hal/wifi3.0/hal_api_mon.h @@ -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, diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index e3e81d8d16..c4abe7e131 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -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 */ diff --git a/qdf/inc/qdf_util.h b/qdf/inc/qdf_util.h index c2c4823d1e..7c6ba1a7d5 100644 --- a/qdf/inc/qdf_util.h +++ b/qdf/inc/qdf_util.h @@ -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) diff --git a/qdf/linux/src/i_qdf_util.h b/qdf/linux/src/i_qdf_util.h index 6068291823..584312d778 100644 --- a/qdf/linux/src/i_qdf_util.h +++ b/qdf/linux/src/i_qdf_util.h @@ -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