diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c index 44ab1140e1..7505e73efa 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c @@ -1136,7 +1136,7 @@ dp_mon_register_feature_ops_2_0(struct dp_soc *soc) mon_ops->mon_tx_capture_debugfs_init = NULL; mon_ops->mon_tx_add_to_comp_queue = NULL; mon_ops->mon_print_pdev_tx_capture_stats = NULL; - mon_ops->mon_config_enh_tx_capture = NULL; + mon_ops->mon_config_enh_tx_capture = dp_config_enh_tx_core_capture_2_0; mon_ops->mon_tx_peer_filter = NULL; #endif #if defined(WDI_EVENT_ENABLE) &&\ diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h index 175abfb5d2..61fe633667 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h +++ b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h @@ -103,6 +103,8 @@ struct dp_mon_desc_pool { * struct dp_mon_pdev_be - BE specific monitor pdev object * @mon_pdev: monitor pdev structure * @filter_be: filters sent to fw + * @tx_mon_mode: tx monitor mode + * @tx_mon_filter_length: tx monitor filter length * @tx_capture: pointer to tx capture function * @tx_stats: tx monitor drop stats * @rx_mon_wq_lock: Rx mon workqueue lock @@ -116,9 +118,9 @@ struct dp_mon_desc_pool { struct dp_mon_pdev_be { struct dp_mon_pdev mon_pdev; struct dp_mon_filter_be **filter_be; -#ifdef WLAN_TX_PKT_CAPTURE_ENH_BE + uint8_t tx_mon_mode; + uint8_t tx_mon_filter_length; struct dp_pdev_tx_capture_be tx_capture_be; -#endif struct dp_tx_monitor_drop_stats tx_stats; qdf_spinlock_t rx_mon_wq_lock; qdf_workqueue_t *rx_mon_workqueue; @@ -243,6 +245,14 @@ QDF_STATUS dp_mon_buffers_replenish(struct dp_soc *dp_soc, void dp_mon_filter_show_filter_be(enum dp_mon_filter_mode mode, struct dp_mon_filter_be *filter); +/** + * dp_mon_filter_show_tx_filter_be() - Show the set filters + * @mode: The filter modes + * @tlv_filter: tlv filter + */ +void dp_mon_filter_show_tx_filter_be(enum dp_mon_filter_mode mode, + struct dp_mon_filter_be *filter); + /* * dp_mon_desc_get() - get monitor sw descriptor * diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_filter_2.0.c b/dp/wifi3.0/monitor/2.0/dp_mon_filter_2.0.c index 228e3fbec6..062c427206 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_filter_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_mon_filter_2.0.c @@ -856,11 +856,11 @@ int htt_h2t_tx_ring_cfg(struct htt_soc *htt_soc, int pdev_id, if (htt_tlv_filter->ctrl_filter) htt_tx_ring_pkt_type_set(*msg_word, ENABLE_FLAGS, - CTRL, 1); + CTRL, 2); if (htt_tlv_filter->data_filter) htt_tx_ring_pkt_type_set(*msg_word, ENABLE_FLAGS, - DATA, 1); + DATA, 4); if (htt_tlv_filter->mgmt_dma_length) HTT_TX_MONITOR_CFG_CONFIG_LENGTH_MGMT_SET(*msg_word, @@ -946,7 +946,7 @@ int htt_h2t_tx_ring_cfg(struct htt_soc *htt_soc, int pdev_id, htt_tx_tlv_filter_mask_set_in3(msg_word, htt_tlv_filter); - /* word 6 */ + /* word 7 */ msg_word++; *msg_word = 0; if (htt_tlv_filter->wmask.tx_fes_setup) @@ -957,9 +957,6 @@ int htt_h2t_tx_ring_cfg(struct htt_soc *htt_soc, int pdev_id, HTT_TX_MONITOR_CFG_TX_PEER_ENTRY_WORD_MASK_SET(*msg_word, htt_tlv_filter->wmask.tx_peer_entry); - /* word 7 */ - msg_word++; - *msg_word = 0; if (htt_tlv_filter->wmask.tx_queue_ext) HTT_TX_MONITOR_CFG_TX_QUEUE_EXT_WORD_MASK_SET(*msg_word, htt_tlv_filter->wmask.tx_queue_ext); @@ -971,10 +968,6 @@ int htt_h2t_tx_ring_cfg(struct htt_soc *htt_soc, int pdev_id, /* word 8 */ msg_word++; *msg_word = 0; - if (htt_tlv_filter->wmask.tx_mpdu_start) - HTT_TX_MONITOR_CFG_TX_MPDU_START_WORD_MASK_SET(*msg_word, - htt_tlv_filter->wmask.tx_mpdu_start); - if (htt_tlv_filter->wmask.pcu_ppdu_setup_init) HTT_TX_MONITOR_CFG_PCU_PPDU_SETUP_WORD_MASK_SET(*msg_word, htt_tlv_filter->wmask.pcu_ppdu_setup_init); @@ -982,6 +975,11 @@ int htt_h2t_tx_ring_cfg(struct htt_soc *htt_soc, int pdev_id, /* word 9 */ msg_word++; *msg_word = 0; + + if (htt_tlv_filter->wmask.tx_mpdu_start) + HTT_TX_MONITOR_CFG_TX_MPDU_START_WORD_MASK_SET(*msg_word, + htt_tlv_filter->wmask.tx_mpdu_start); + if (htt_tlv_filter->wmask.rxpcu_user_setup) HTT_TX_MONITOR_CFG_RXPCU_USER_SETUP_WORD_MASK_SET(*msg_word, htt_tlv_filter->wmask.rxpcu_user_setup); @@ -998,6 +996,10 @@ int htt_h2t_tx_ring_cfg(struct htt_soc *htt_soc, int pdev_id, DATA, htt_tlv_filter->data_mpdu_log); + HTT_TX_MONITOR_CFG_DMA_MPDU_MGMT_SET(*msg_word, 1); + HTT_TX_MONITOR_CFG_DMA_MPDU_CTRL_SET(*msg_word, 1); + HTT_TX_MONITOR_CFG_DMA_MPDU_DATA_SET(*msg_word, 1); + pkt = htt_htc_pkt_alloc(soc); if (!pkt) goto fail1; @@ -1153,7 +1155,8 @@ void dp_mon_filter_setup_tx_mon_mode_2_0(struct dp_pdev *pdev) } mon_pdev->current_filter_mode = mode; - filter.tx_valid = true; + filter.tx_valid = !!mon_pdev_be->tx_mon_mode; + mon_pdev_be->filter_be[mode][srng_type] = filter; } @@ -1221,7 +1224,7 @@ void dp_mon_filter_setup_rx_mon_mode_2_0(struct dp_pdev *pdev) mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); rx_tlv_filter = &filter.rx_tlv_filter; - rx_tlv_filter->valid = true; + rx_tlv_filter->valid = false; dp_mon_filter_set_status_cmn(mon_pdev, rx_tlv_filter); dp_mon_filter_show_filter(mon_pdev, mode, rx_tlv_filter); @@ -1531,6 +1534,16 @@ void dp_mon_filter_show_filter_be(enum dp_mon_filter_mode mode, dp_tx_mon_filter_show_filter(filter); } +void dp_mon_filter_show_tx_filter_be(enum dp_mon_filter_mode mode, + struct dp_mon_filter_be *filter) +{ + dp_mon_filter_err("TX MON RING TLV FILTER CONFIG:"); + dp_mon_filter_err("[Mode %d]: Valid: %d", mode, filter->tx_valid); + + if (filter->tx_valid) + dp_tx_mon_filter_show_filter(filter); +} + #ifdef WDI_EVENT_ENABLE void dp_mon_filter_setup_rx_pkt_log_full_2_0(struct dp_pdev *pdev) { @@ -2030,7 +2043,7 @@ dp_tx_mon_ht2_ring_cfg(struct dp_soc *soc, hal_ring_hdl = mon_soc_be->tx_mon_dst_ring[lmac_id].hal_srng; hal_ring_type = TX_MONITOR_DST; - ring_buf_size = RX_DATA_BUFFER_SIZE; + ring_buf_size = 2048; status = htt_h2t_tx_ring_cfg(soc->htt_handle, mac_for_pdev, hal_ring_hdl, hal_ring_type, @@ -2085,6 +2098,7 @@ QDF_STATUS dp_tx_mon_filter_update_2_0(struct dp_pdev *pdev) struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; struct dp_mon_pdev_be *mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); + uint8_t config_dma_length = DMA_LENGTH_64B; if (!pdev) { dp_mon_filter_err("pdev Context is null"); @@ -2103,19 +2117,21 @@ QDF_STATUS dp_tx_mon_filter_update_2_0(struct dp_pdev *pdev) return QDF_STATUS_E_FAILURE; } + if (mon_pdev_be->tx_mon_filter_length > config_dma_length) + config_dma_length = mon_pdev_be->tx_mon_filter_length; + if (filter_ptr->tx_valid) { tx_tlv_filter = &filter_ptr->tx_tlv_filter; dp_tx_mon_filter_set_all(tx_tlv_filter); - tx_tlv_filter->mgmt_dma_length = DEFAULT_DMA_LENGTH; - tx_tlv_filter->ctrl_dma_length = DEFAULT_DMA_LENGTH; - tx_tlv_filter->data_dma_length = DEFAULT_DMA_LENGTH; + + tx_tlv_filter->mgmt_dma_length = config_dma_length; + tx_tlv_filter->ctrl_dma_length = config_dma_length; + tx_tlv_filter->data_dma_length = config_dma_length; tx_tlv_filter->enable = 1; } else { qdf_mem_zero(filter_ptr, sizeof(struct dp_mon_filter_be)); } - - dp_mon_filter_show_filter_be(mode, - filter_ptr); + dp_mon_filter_show_tx_filter_be(mode, filter_ptr); dp_tx_mon_ht2_ring_cfg(soc, pdev, srng_type, &filter_ptr->tx_tlv_filter); diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_filter_2.0.h b/dp/wifi3.0/monitor/2.0/dp_mon_filter_2.0.h index 34534e8881..1afd7f5932 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_filter_2.0.h +++ b/dp/wifi3.0/monitor/2.0/dp_mon_filter_2.0.h @@ -21,6 +21,9 @@ #include #define DEFAULT_DMA_LENGTH 7 +#define DMA_LENGTH_64B 1 +#define DMA_LENGTH_128B 2 +#define DMA_LENGTH_256B 4 /** * dp_rx_mon_enable_set() - Setup rx monitor feature diff --git a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c index 7701a9fd85..657cfbbd02 100644 --- a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c @@ -28,6 +28,7 @@ #include #include #include +#include static inline uint32_t dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, @@ -38,6 +39,7 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, hal_soc_handle_t hal_soc; void *mon_dst_srng; struct dp_mon_pdev *mon_pdev; + struct dp_mon_pdev_be *mon_pdev_be; uint32_t work_done = 0; struct dp_mon_soc *mon_soc = soc->monitor_soc; struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc); @@ -45,6 +47,7 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, union dp_mon_desc_list_elem_t *tail = NULL; struct dp_mon_desc_pool *tx_mon_desc_pool = &mon_soc_be->tx_desc_mon; QDF_STATUS status; + uint32_t tx_monitor_reap_cnt = 0; if (!pdev) { dp_mon_err("%pK: pdev is null for mac_id = %d", soc, mac_id); @@ -60,6 +63,10 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, return work_done; } + mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); + if (qdf_unlikely(!mon_pdev_be)) + return work_done; + hal_soc = soc->hal_soc; qdf_assert((hal_soc && pdev)); @@ -76,13 +83,42 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, while (qdf_likely((tx_mon_dst_ring_desc = (void *)hal_srng_dst_peek(hal_soc, mon_dst_srng)) && quota--)) { - struct hal_mon_desc hal_mon_tx_desc; - struct dp_mon_desc *mon_desc; + struct hal_mon_desc hal_mon_tx_desc = {0}; + struct dp_mon_desc *mon_desc = NULL; + uint32_t end_offset = DP_MON_DATA_BUFFER_SIZE; hal_be_get_mon_dest_status(soc->hal_soc, tx_mon_dst_ring_desc, &hal_mon_tx_desc); + if (hal_mon_tx_desc.empty_descriptor) { + /* update stats counter */ + dp_mon_debug("P_ID:%d INIT:%d E_DESC:%d R_ID:%d L_CNT:%d DROP[PPDU:%d MPDU:%d TLV:%d] E_O_PPDU:%d", + hal_mon_tx_desc.ppdu_id, + hal_mon_tx_desc.initiator, + hal_mon_tx_desc.empty_descriptor, + hal_mon_tx_desc.ring_id, + hal_mon_tx_desc.looping_count, + hal_mon_tx_desc.ppdu_drop_count, + hal_mon_tx_desc.mpdu_drop_count, + hal_mon_tx_desc.tlv_drop_count, + hal_mon_tx_desc.end_of_ppdu_dropped); + + work_done++; + hal_srng_dst_get_next(hal_soc, mon_dst_srng); + continue; + } + + dp_mon_debug("P_ID:%d INIT:%d E_DESC:%d R_ID:%d L_CNT:%d BUF_ADDR: 0x%llx E_OFF: %d E_REA: %d", + hal_mon_tx_desc.ppdu_id, + hal_mon_tx_desc.initiator, + hal_mon_tx_desc.empty_descriptor, + hal_mon_tx_desc.ring_id, + hal_mon_tx_desc.looping_count, + hal_mon_tx_desc.buf_addr, + hal_mon_tx_desc.end_offset, + hal_mon_tx_desc.end_reason); + mon_desc = (struct dp_mon_desc *)(uintptr_t)(hal_mon_tx_desc.buf_addr); qdf_assert_always(mon_desc); @@ -94,19 +130,64 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, } if (mon_desc->magic != DP_MON_DESC_MAGIC) { - dp_mon_err("Invalid monitor descriptor"); - qdf_assert_always(mon_desc); + dp_mon_debug("Invalid monitor descriptor"); + qdf_assert_always(0); + } + + if (qdf_likely(hal_mon_tx_desc.end_offset)) + end_offset = hal_mon_tx_desc.end_offset; + + if ((hal_mon_tx_desc.end_reason == HAL_MON_FLUSH_DETECTED) || + (hal_mon_tx_desc.end_reason == HAL_MON_PPDU_TRUNCATED)) { + dp_tx_mon_update_end_reason(mon_pdev, + hal_mon_tx_desc.ppdu_id, + hal_mon_tx_desc.end_reason); + + qdf_frag_free(mon_desc->buf_addr); + ++tx_monitor_reap_cnt; + dp_mon_add_to_free_desc_list(&desc_list, + &tail, mon_desc); + + work_done++; + hal_srng_dst_get_next(hal_soc, mon_dst_srng); + continue; + } + + if (qdf_unlikely(!mon_desc->buf_addr)) { + dp_mon_debug("P_ID:%d INIT:%d E_DESC:%d R_ID:%d L_CNT:%d BUF_ADDR: 0x%llx E_OFF: %d E_REA: %d", + hal_mon_tx_desc.ppdu_id, + hal_mon_tx_desc.initiator, + hal_mon_tx_desc.empty_descriptor, + hal_mon_tx_desc.ring_id, + hal_mon_tx_desc.looping_count, + hal_mon_tx_desc.buf_addr, + hal_mon_tx_desc.end_offset, + hal_mon_tx_desc.end_reason); + + ++tx_monitor_reap_cnt; + dp_mon_add_to_free_desc_list(&desc_list, + &tail, mon_desc); + + work_done++; + hal_srng_dst_get_next(hal_soc, mon_dst_srng); + continue; } status = dp_tx_mon_process_status_tlv(soc, pdev, &hal_mon_tx_desc, - mon_desc->paddr); + mon_desc->buf_addr, + end_offset); + if (status != QDF_STATUS_SUCCESS) { hal_txmon_status_free_buffer(pdev->soc->hal_soc, - mon_desc->buf_addr); + mon_desc->buf_addr, + end_offset); } qdf_frag_free(mon_desc->buf_addr); + + mon_desc->buf_addr = NULL; + ++tx_monitor_reap_cnt; dp_mon_add_to_free_desc_list(&desc_list, &tail, mon_desc); work_done++; @@ -114,14 +195,15 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx, } dp_srng_access_end(int_ctx, soc, mon_dst_srng); - if (desc_list) + if (tx_monitor_reap_cnt) { dp_mon_buffers_replenish(soc, &mon_soc_be->tx_mon_buf_ring, tx_mon_desc_pool, - work_done, + tx_monitor_reap_cnt, &desc_list, &tail); - + } qdf_spin_unlock_bh(&mon_pdev->mon_lock); - dp_mon_info("mac_id: %d, work_done:%d", mac_id, work_done); + dp_mon_debug("mac_id: %d, work_done:%d tx_monitor_reap_cnt:%d", + mac_id, work_done, tx_monitor_reap_cnt); return work_done; } @@ -384,18 +466,24 @@ dp_config_enh_tx_capture_2_0(struct dp_pdev *pdev, uint8_t val) { /* TODO: send HTT msg to configure TLV based on mode */ tx_cap_be->mode = TX_MON_BE_DISABLE; + mon_pdev_be->tx_mon_mode = 0; + mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_64B; break; } case TX_MON_BE_FULL_CAPTURE: { /* TODO: send HTT msg to configure TLV based on mode */ tx_cap_be->mode = TX_MON_BE_FULL_CAPTURE; + mon_pdev_be->tx_mon_mode = 1; + mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH; break; } case TX_MON_BE_PEER_FILTER: { /* TODO: send HTT msg to configure TLV based on mode */ tx_cap_be->mode = TX_MON_BE_PEER_FILTER; + mon_pdev_be->tx_mon_mode = 1; + mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH; break; } default: @@ -405,6 +493,13 @@ dp_config_enh_tx_capture_2_0(struct dp_pdev *pdev, uint8_t val) } } + dp_mon_info("Tx monitor mode:%d mon_mode_flag:%d config_length:%d", + tx_cap_be->mode, mon_pdev_be->tx_mon_mode, + mon_pdev_be->tx_mon_filter_length); + + dp_mon_filter_setup_tx_mon_mode(pdev); + dp_tx_mon_filter_update(pdev); + return QDF_STATUS_SUCCESS; } @@ -733,4 +828,61 @@ void dp_tx_ppdu_stats_detach_2_0(struct dp_pdev *pdev) qdf_spinlock_destroy(&tx_cap_be->tx_mon_list_lock); } +#endif /* WLAN_TX_PKT_CAPTURE_ENH_BE */ + +#if (defined(WIFI_MONITOR_SUPPORT) && !defined(WLAN_TX_PKT_CAPTURE_ENH_BE)) +/* + * dp_config_enh_tx_core_capture_2_0()- API to validate core framework + * @pdev_handle: DP_PDEV handle + * @val: user provided value + * + * Return: QDF_STATUS + */ +QDF_STATUS +dp_config_enh_tx_core_capture_2_0(struct dp_pdev *pdev, uint8_t val) +{ + struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; + struct dp_mon_pdev_be *mon_pdev_be = + dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); + struct dp_pdev_tx_capture_be *tx_cap_be = + &mon_pdev_be->tx_capture_be; + + switch (val) { + case TX_MON_BE_FRM_WRK_DISABLE: + { + tx_cap_be->mode = val; + mon_pdev_be->tx_mon_mode = 0; + mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_64B; + break; + } + case TX_MON_BE_FRM_WRK_FULL_CAPTURE: + { + tx_cap_be->mode = val; + mon_pdev_be->tx_mon_mode = 1; + mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH; + break; + } + case TX_MON_BE_FRM_WRK_128B_CAPTURE: + { + tx_cap_be->mode = val; + mon_pdev_be->tx_mon_mode = 1; + mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_128B; + break; + } + default: + { + return QDF_STATUS_E_INVAL; + } + } + + dp_mon_debug("Tx monitor mode:%d mon_mode_flag:%d config_length:%d", + tx_cap_be->mode, mon_pdev_be->tx_mon_mode, + mon_pdev_be->tx_mon_filter_length); + + /* send HTT msg to configure TLV based on mode */ + dp_mon_filter_setup_tx_mon_mode(pdev); + dp_tx_mon_filter_update(pdev); + + return QDF_STATUS_SUCCESS; +} #endif diff --git a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h index eee646d47a..8ba21ddf1f 100644 --- a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h +++ b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h @@ -21,6 +21,7 @@ #include #include +struct dp_mon_desc; /* * dp_tx_mon_buffers_alloc() - allocate tx monitor buffers * @soc: DP soc handle @@ -74,18 +75,35 @@ void dp_tx_mon_buf_desc_pool_free(struct dp_soc *soc); QDF_STATUS dp_tx_mon_buf_desc_pool_alloc(struct dp_soc *soc); -/* - * dp_tx_mon_process_status_tlv() - process status tlv - * @soc: dp soc handle - * @pdev: dp pdev handle - * @mon_ring_desc: monitor ring descriptor - * @frag_addr: frag address +/** + * dp_tx_mon_update_end_reason() - API to update end reason * + * @mon_pdev - DP_MON_PDEV handle + * @ppdu_id - ppdu_id + * @end_reason - monitor destiantion descriptor end reason + * + * Return: void + */ +void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev, + int ppdu_id, int end_reason); + +/* + * dp_tx_mon_process_status_tlv() - API to processed TLV + * invoked from interrupt handler + * + * @soc - DP_SOC handle + * @pdev - DP_PDEV handle + * @mon_ring_desc - descriptor status info + * @addr - status buffer frag address + * @end_offset - end offset of buffer that has valid buffer + * + * Return: QDF_STATUS */ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, struct dp_pdev *pdev, struct hal_mon_desc *mon_ring_desc, - qdf_dma_addr_t addr); + qdf_frag_t status_frag, + uint32_t end_offset); /* * dp_tx_mon_process_2_0() - tx monitor interrupt process @@ -318,6 +336,18 @@ enum dp_tx_monitor_mode { TX_MON_BE_PEER_FILTER, }; +/** + * dp_tx_monitor_framework_mode - tx monitor framework mode + * @TX_MON_BE_FRM_WRK_DISABLE: tx monitor frame work disable + * @TX_MON_BE_FRM_WRK_FULL_CAPTURE: tx monitor frame work full capture + * @TX_MON_BE_FRM_WRK_128B_CAPTURE: tx monitor frame work 128B capture + */ +enum dp_tx_monitor_framework_mode { + TX_MON_BE_FRM_WRK_DISABLE, + TX_MON_BE_FRM_WRK_FULL_CAPTURE, + TX_MON_BE_FRM_WRK_128B_CAPTURE, +}; + #define TX_TAILQ_INSERT_TAIL(pdev, tx_ppdu_info) \ do { \ STAILQ_INSERT_TAIL(&pdev->tx_ppdu_info_list, \ @@ -346,10 +376,12 @@ enum dp_tx_monitor_mode { #ifndef WLAN_TX_PKT_CAPTURE_ENH_BE /** * dp_pdev_tx_capture_be - info to store tx capture information in pdev + * @mode: tx monitor core framework current mode * * This is a dummy structure */ struct dp_pdev_tx_capture_be { + uint32_t mode; }; /** @@ -515,4 +547,16 @@ QDF_STATUS dp_peer_set_tx_capture_enabled_2_0(struct dp_pdev *pdev_handle, uint8_t is_tx_pkt_cap_enable, uint8_t *peer_mac); #endif /* WLAN_TX_PKT_CAPTURE_ENH_BE */ + +#if (defined(WIFI_MONITOR_SUPPORT) && !defined(WLAN_TX_PKT_CAPTURE_ENH_BE)) +/* + * dp_config_enh_tx_core_capture_2_0()- API to validate core framework + * @pdev_handle: DP_PDEV handle + * @val: user provided value + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_config_enh_tx_core_capture_2_0(struct dp_pdev *pdev, uint8_t val); +#endif + #endif /* _DP_TX_MON_2_0_H_ */ diff --git a/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c b/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c index 7318c315de..0a955a03fe 100644 --- a/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c @@ -22,8 +22,8 @@ #include #include #include -#include #include +#include #if defined(WLAN_TX_PKT_CAPTURE_ENH_BE) && defined(QCA_MONITOR_2_0_SUPPORT) /** @@ -40,10 +40,12 @@ dp_tx_mon_status_queue_free(struct dp_pdev *pdev, uint8_t last_frag_q_idx = tx_cap_be->last_frag_q_idx; qdf_frag_t status_frag = NULL; uint8_t i = 0; + uint32_t end_offset = 0; for (; i < last_frag_q_idx; i++) { status_frag = tx_cap_be->status_frag_queue[last_frag_q_idx]; - hal_txmon_status_free_buffer(pdev->soc->hal_soc, status_frag); + hal_txmon_status_free_buffer(pdev->soc->hal_soc, status_frag, + end_offset); qdf_frag_free(status_frag); tx_cap_be->status_frag_queue[last_frag_q_idx] = NULL; } @@ -1104,11 +1106,15 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev) tx_prot_ppdu_info = dp_tx_mon_get_ppdu_info(pdev, TX_PROT_PPDU_INFO, 1, tx_cap_be->be_ppdu_id); - if (!tx_prot_ppdu_info) + if (!tx_prot_ppdu_info) { + dp_mon_info("tx prot ppdu info alloc got failed!!"); return QDF_STATUS_E_NOMEM; + } status_frag = tx_cap_be->status_frag_queue[cur_frag_q_idx]; tx_tlv = status_frag; + dp_mon_debug("last_frag_q_idx: %d status_frag:%pK", + tx_cap_be->last_frag_q_idx, status_frag); /* get number of user from tlv window */ tlv_status = hal_txmon_status_get_num_users(pdev->soc->hal_soc, @@ -1123,8 +1129,10 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev) tx_data_ppdu_info = dp_tx_mon_get_ppdu_info(pdev, TX_DATA_PPDU_INFO, num_users, tx_cap_be->be_ppdu_id); - if (!tx_data_ppdu_info) + if (!tx_data_ppdu_info) { + dp_mon_info("tx prot ppdu info alloc got failed!!"); return QDF_STATUS_E_NOMEM; + } /* iterate status buffer queue */ while (tx_cap_be->cur_frag_q_idx < tx_cap_be->last_frag_q_idx) { @@ -1237,6 +1245,33 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev) return QDF_STATUS_SUCCESS; } +/** + * dp_tx_mon_update_end_reason() - API to update end reason + * + * @mon_pdev - DP_MON_PDEV handle + * @ppdu_id - ppdu_id + * @end_reason - monitor destiantion descriptor end reason + * + * Return: void + */ +void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev, + int ppdu_id, int end_reason) +{ + struct dp_mon_pdev_be *mon_pdev_be; + struct dp_pdev_tx_capture_be *tx_cap_be; + + mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); + if (qdf_unlikely(!mon_pdev_be)) + return; + + tx_cap_be = &mon_pdev_be->tx_capture_be; + + if (tx_cap_be->be_ppdu_id != ppdu_id) + return; + + tx_cap_be->be_end_reason_bitmap |= (1 << end_reason); +} + /* * dp_tx_mon_process_status_tlv() - API to processed TLV * invoked from interrupt handler @@ -1244,14 +1279,16 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev) * @soc - DP_SOC handle * @pdev - DP_PDEV handle * @mon_ring_desc - descriptor status info - * @addr - status buffer frag address + * @status_frag - status buffer frag address + * @end_offset - end offset of buffer that has valid buffer * * Return: QDF_STATUS */ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, struct dp_pdev *pdev, struct hal_mon_desc *mon_ring_desc, - qdf_dma_addr_t addr) + qdf_frag_t status_frag, + uint32_t end_offset) { struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev_be *mon_pdev_be; @@ -1285,16 +1322,18 @@ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, if (tx_cap_be->mode == TX_MON_BE_DISABLE) return QDF_STATUS_E_INVAL; - if (tx_cap_be->be_ppdu_id != mon_ring_desc->ppdu_id) { + if (tx_cap_be->be_ppdu_id != mon_ring_desc->ppdu_id && + tx_cap_be->last_frag_q_idx) { if (tx_cap_be->be_end_reason_bitmap & - (1 << HAL_TX_MON_FLUSH_DETECTED)) { + (1 << HAL_MON_FLUSH_DETECTED)) { dp_tx_mon_status_queue_free(pdev, tx_cap_be); } else if (tx_cap_be->be_end_reason_bitmap & - (1 << HAL_TX_MON_PPDU_TRUNCATED)) { + (1 << HAL_MON_PPDU_TRUNCATED)) { dp_tx_mon_status_queue_free(pdev, tx_cap_be); - } else { + } else if (dp_tx_mon_process_tlv_2_0(pdev) != + QDF_STATUS_SUCCESS) { /* schedule ppdu worth information */ - dp_tx_mon_process_tlv_2_0(pdev); + dp_tx_mon_status_queue_free(pdev, tx_cap_be); } /* reset end reason bitmap */ @@ -1306,20 +1345,20 @@ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, /* get ppdu id from destination descriptor and store it in mon pdev */ if (mon_ring_desc->empty_descriptor == 1 || - mon_ring_desc->end_reason == HAL_TX_MON_FLUSH_DETECTED || - mon_ring_desc->end_reason == HAL_TX_MON_PPDU_TRUNCATED) { + mon_ring_desc->end_reason == HAL_MON_FLUSH_DETECTED || + mon_ring_desc->end_reason == HAL_MON_PPDU_TRUNCATED) { /* * free all page frags maintained at pdev level queue * update stats counter */ - tx_cap_be->status_frag_queue[last_frag_q_idx] = (void *)addr; + tx_cap_be->status_frag_queue[last_frag_q_idx] = status_frag; last_frag_q_idx = ++tx_cap_be->last_frag_q_idx; /* TODO: stats counter need to be updated */ return QDF_STATUS_SUCCESS; } - if (mon_ring_desc->end_reason == HAL_TX_MON_STATUS_BUFFER_FULL || - mon_ring_desc->end_reason == HAL_TX_MON_END_OF_PPDU) { + if (mon_ring_desc->end_reason == HAL_MON_STATUS_BUFFER_FULL || + mon_ring_desc->end_reason == HAL_MON_END_OF_PPDU) { /* * Get 64 bits sw desc virtual address from * stats_buf_virtual_address, @@ -1327,7 +1366,7 @@ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, * add status page frag to pdev level queue * add sw descriptor to local free list */ - tx_cap_be->status_frag_queue[last_frag_q_idx] = (void *)addr; + tx_cap_be->status_frag_queue[last_frag_q_idx] = status_frag; last_frag_q_idx = ++tx_cap_be->last_frag_q_idx; return QDF_STATUS_SUCCESS; } @@ -1345,14 +1384,30 @@ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, * @pdev - DP_PDEV handle * @mon_ring_desc - descriptor status info * @addr - status buffer frag address + * @end_offset - end offset of buffer that has valid buffer * * Return: QDF_STATUS */ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, struct dp_pdev *pdev, struct hal_mon_desc *mon_ring_desc, - qdf_dma_addr_t addr) + qdf_frag_t status_frag, + uint32_t end_offset) { return QDF_STATUS_E_INVAL; } + +/** + * dp_tx_mon_update_end_reason() - API to update end reason + * + * @mon_pdev - DP_MON_PDEV handle + * @ppdu_id - ppdu_id + * @end_reason - monitor destiantion descriptor end reason + * + * Return: void + */ +void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev, + int ppdu_id, int end_reason) +{ +} #endif diff --git a/dp/wifi3.0/monitor/dp_mon_filter.c b/dp/wifi3.0/monitor/dp_mon_filter.c index 809d014e33..017ce5fcf2 100644 --- a/dp/wifi3.0/monitor/dp_mon_filter.c +++ b/dp/wifi3.0/monitor/dp_mon_filter.c @@ -459,6 +459,13 @@ void dp_mon_filter_setup_mon_mode(struct dp_pdev *pdev) mon_ops = dp_mon_ops_get(pdev->soc); if (mon_ops && mon_ops->mon_filter_setup_rx_mon_mode) mon_ops->mon_filter_setup_rx_mon_mode(pdev); +} + +void dp_mon_filter_setup_tx_mon_mode(struct dp_pdev *pdev) +{ + struct dp_mon_ops *mon_ops = NULL; + + mon_ops = dp_mon_ops_get(pdev->soc); if (mon_ops && mon_ops->mon_filter_setup_tx_mon_mode) mon_ops->mon_filter_setup_tx_mon_mode(pdev); } @@ -470,8 +477,6 @@ void dp_mon_filter_reset_mon_mode(struct dp_pdev *pdev) mon_ops = dp_mon_ops_get(pdev->soc); if (mon_ops && mon_ops->mon_filter_reset_rx_mon_mode) mon_ops->mon_filter_reset_rx_mon_mode(pdev); - if (mon_ops && mon_ops->mon_filter_reset_tx_mon_mode) - mon_ops->mon_filter_reset_tx_mon_mode(pdev); } #ifdef WDI_EVENT_ENABLE @@ -560,15 +565,28 @@ QDF_STATUS dp_mon_filter_update(struct dp_pdev *pdev) return QDF_STATUS_E_FAILURE; } - if (mon_ops && mon_ops->tx_mon_filter_update) - mon_ops->tx_mon_filter_update(pdev); - if (mon_ops && mon_ops->rx_mon_filter_update) mon_ops->rx_mon_filter_update(pdev); return QDF_STATUS_SUCCESS; } +QDF_STATUS dp_tx_mon_filter_update(struct dp_pdev *pdev) +{ + struct dp_mon_ops *mon_ops = NULL; + + mon_ops = dp_mon_ops_get(pdev->soc); + if (!mon_ops) { + dp_mon_filter_err("Mon ops uninitialized"); + return QDF_STATUS_E_FAILURE; + } + + if (mon_ops && mon_ops->tx_mon_filter_update) + mon_ops->tx_mon_filter_update(pdev); + + return QDF_STATUS_SUCCESS; +} + #ifdef QCA_ENHANCED_STATS_SUPPORT void dp_mon_filters_reset(struct dp_pdev *pdev) { diff --git a/dp/wifi3.0/monitor/dp_mon_filter.h b/dp/wifi3.0/monitor/dp_mon_filter.h index c7d5e04f9a..9830a8eb1a 100644 --- a/dp/wifi3.0/monitor/dp_mon_filter.h +++ b/dp/wifi3.0/monitor/dp_mon_filter.h @@ -279,11 +279,17 @@ void dp_mon_filter_reset_rx_enh_capture(struct dp_pdev *pdev); #endif /* WLAN_RX_PKT_CAPTURE_ENH */ /** - * dp_mon_filter_setup_mon_mode() - Setup the Rx monitor mode filter + * dp_mon_filter_setup_mon_mode() - Setup the Rx and Tx monitor mode filter * @pdev: DP pdev handle */ void dp_mon_filter_setup_mon_mode(struct dp_pdev *pdev); +/** + * dp_mon_filter_setup_tx_mon_mode() - Setup the Tx monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_tx_mon_mode(struct dp_pdev *pdev); + /** * dp_mon_filter_reset_mon_mode() - Reset the Rx monitor mode filter * @pdev: DP pdev handle @@ -356,7 +362,7 @@ void dp_mon_filter_set_status_cbf(struct dp_pdev *pdev, struct dp_mon_filter *filter); /** - * dp_mon_filter_update() - Setup the monitor filter setting for a srng + * dp_mon_filter_update() - Setup the RX & Tx monitor filter setting for a srng * type * @pdev: DP pdev handle * @@ -438,6 +444,12 @@ void dp_mon_filter_set_status_cmn(struct dp_mon_pdev *mon_pdev, */ void dp_mon_filter_setup_mon_mode(struct dp_pdev *pdev); +/** + * dp_mon_filter_setup_tx_mon_mode() - Setup the Tx monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_tx_mon_mode(struct dp_pdev *pdev); + /** * dp_mon_filter_reset_mon_mode() - Reset the Rx monitor mode filter * @pdev: DP pdev handle @@ -455,13 +467,13 @@ void dp_mon_filter_set_cbf_cmn(struct dp_pdev *pdev, struct dp_mon_filter *filter); /** - * dp_mon_filter_update() - Setup the monitor filter setting for a srng + * dp_tx_mon_filter_update() - Setup the tx monitor filter setting for a srng * type * @pdev: DP pdev handle * * Return: QDF_STATUS */ -QDF_STATUS dp_mon_filter_update(struct dp_pdev *pdev); +QDF_STATUS dp_tx_mon_filter_update(struct dp_pdev *pdev); /** * dp_mon_filter_dealloc() - Deallocate the filter objects to be stored in diff --git a/hal/wifi3.0/be/hal_be_api_mon.h b/hal/wifi3.0/be/hal_be_api_mon.h index 4d97a50602..5c70c4fa07 100644 --- a/hal/wifi3.0/be/hal_be_api_mon.h +++ b/hal/wifi3.0/be/hal_be_api_mon.h @@ -850,7 +850,7 @@ hal_tx_status_get_next_tlv(uint8_t *tx_tlv) { tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(tx_tlv); return (uint8_t *)(((unsigned long)(tx_tlv + tlv_len + - HAL_RX_TLV32_HDR_SIZE + 3)) & (~3)); + HAL_RX_TLV32_HDR_SIZE + 7)) & (~7)); } /** @@ -907,17 +907,19 @@ hal_txmon_status_get_num_users(hal_soc_handle_t hal_soc_hdl, * hal_txmon_status_free_buffer() - api to free status buffer * @hal_soc: HAL soc handle * @status_frag: qdf_frag_t buffer + * @end_offset: end offset within buffer that has valid data * - * Return void + * Return status */ -static inline void +static inline QDF_STATUS hal_txmon_status_free_buffer(hal_soc_handle_t hal_soc_hdl, - qdf_frag_t status_frag) + qdf_frag_t status_frag, + uint32_t end_offset) { struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - if (hal_soc->ops->hal_txmon_status_free_buffer) - hal_soc->ops->hal_txmon_status_free_buffer(status_frag); + return hal_soc->ops->hal_txmon_status_free_buffer(status_frag, + end_offset); } /** diff --git a/hal/wifi3.0/be/hal_be_generic_api.h b/hal/wifi3.0/be/hal_be_generic_api.h index fc4f9842a1..5dbab8f017 100644 --- a/hal/wifi3.0/be/hal_be_generic_api.h +++ b/hal/wifi3.0/be/hal_be_generic_api.h @@ -377,8 +377,8 @@ hal_txmon_parse_tx_fes_setup(void *tx_tlv, static inline uint8_t hal_txmon_get_num_users(void *tx_tlv) { - uint8_t num_users = HAL_TX_DESC_GET(tx_tlv, - TX_FES_SETUP, NUMBER_OF_USERS); + uint8_t num_users = HAL_TX_DESC_GET_64(tx_tlv, + TX_FES_SETUP, NUMBER_OF_USERS); return num_users; } @@ -395,9 +395,9 @@ static inline void hal_txmon_parse_tx_fes_setup(void *tx_tlv, struct hal_tx_ppdu_info *tx_ppdu_info) { - tx_ppdu_info->num_users = HAL_TX_DESC_GET(tx_tlv, - TX_FES_SETUP, - NUMBER_OF_USERS); + tx_ppdu_info->num_users = HAL_TX_DESC_GET_64(tx_tlv, + TX_FES_SETUP, + NUMBER_OF_USERS); } #endif @@ -433,9 +433,9 @@ hal_txmon_status_get_num_users_generic_be(void *tx_tlv_hdr, uint8_t *num_users) } case WIFIRX_RESPONSE_REQUIRED_INFO_E: { - *num_users = HAL_TX_DESC_GET(tx_tlv, - RX_RESPONSE_REQUIRED_INFO, - RESPONSE_STA_COUNT); + *num_users = HAL_TX_DESC_GET_64(tx_tlv, + RX_RESPONSE_REQUIRED_INFO, + RESPONSE_STA_COUNT); tlv_status = HAL_MON_RX_RESPONSE_REQUIRED_INFO; break; } @@ -448,25 +448,30 @@ hal_txmon_status_get_num_users_generic_be(void *tx_tlv_hdr, uint8_t *num_users) * hal_txmon_free_status_buffer() - api to free status buffer * @pdev_handle: DP_PDEV handle * @status_frag: qdf_frag_t buffer + * @end_offset: end offset within buffer that has valid data * - * Return void + * Return status */ -static inline void -hal_txmon_status_free_buffer_generic_be(qdf_frag_t status_frag) +static inline QDF_STATUS +hal_txmon_status_free_buffer_generic_be(qdf_frag_t status_frag, + uint32_t end_offset) { uint32_t tlv_tag, tlv_len; uint32_t tlv_status = HAL_MON_TX_STATUS_PPDU_NOT_DONE; uint8_t *tx_tlv; uint8_t *tx_tlv_start; qdf_frag_t frag_buf = NULL; + QDF_STATUS status = QDF_STATUS_E_ABORTED; tx_tlv = (uint8_t *)status_frag; tx_tlv_start = tx_tlv; /* parse tlv and populate tx_ppdu_info */ do { - /* TODO: check config_length is full monitor mode */ - tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(tx_tlv); - tlv_len = HAL_RX_GET_USER_TLV32_LEN(tx_tlv); + tlv_tag = HAL_RX_GET_USER_TLV64_TYPE(tx_tlv); + tlv_len = HAL_RX_GET_USER_TLV64_LEN(tx_tlv); + + if (((tx_tlv - tx_tlv_start) + tlv_len) > end_offset) + return QDF_STATUS_E_ABORTED; if (tlv_tag == WIFIMON_BUFFER_ADDR_E) { frag_buf = hal_txmon_get_buffer_addr_generic_be(tx_tlv, @@ -476,11 +481,21 @@ hal_txmon_status_free_buffer_generic_be(qdf_frag_t status_frag) frag_buf = NULL; } + + if (WIFITX_FES_STATUS_END_E == tlv_tag || + WIFIRESPONSE_END_STATUS_E == tlv_tag || + WIFIDUMMY_E == tlv_tag) { + status = QDF_STATUS_SUCCESS; + break; + } + /* need api definition for hal_tx_status_get_next_tlv */ tx_tlv = hal_tx_status_get_next_tlv(tx_tlv); - if ((tx_tlv - tx_tlv_start) >= TX_MON_STATUS_BUF_SIZE) + if ((tx_tlv - tx_tlv_start) >= end_offset) break; } while (tlv_status == HAL_MON_TX_STATUS_PPDU_NOT_DONE); + + return status; } /** diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 8a5d6cfb79..4a7fe5420a 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -1061,7 +1061,8 @@ struct hal_hw_txrx_ops { qdf_frag_t status_frag); uint32_t (*hal_txmon_status_get_num_users)(void *tx_tlv_hdr, uint8_t *num_users); - void (*hal_txmon_status_free_buffer)(qdf_frag_t status_frag); + QDF_STATUS (*hal_txmon_status_free_buffer)(qdf_frag_t status_frag, + uint32_t end_offset); #endif /* QCA_MONITOR_2_0_SUPPORT */ void (*hal_reo_shared_qaddr_setup)(hal_soc_handle_t hal_soc_hdl); void (*hal_reo_shared_qaddr_init)(hal_soc_handle_t hal_soc_hdl);