From f9d2c0f54eea2e99103d9c114940bfe1b1fad40d Mon Sep 17 00:00:00 2001 From: Aniruddha Paul Date: Tue, 22 Oct 2019 14:28:37 +0530 Subject: [PATCH] qcacmn: Add common framework for mon filters A framework is added where the filters for every mode are stored on a radio instance. Whenever a mode comes up, it stores the filters in the radio and calls a common API which iterates through all the enabled mode filters and loops through them to create a superset of filters which is sent to HTT. This framework can be extended for new feature addition which set filters for the monitor status and monitor destination rings. Change-Id: I9b739af2086bbe261b65c57af0a5bd867294f30f CRs-Fixed: 2585872 --- dp/inc/cdp_txrx_ctrl.h | 3 + dp/inc/cdp_txrx_mon.h | 6 +- dp/inc/cdp_txrx_ops.h | 4 +- dp/wifi3.0/dp_htt.h | 4 +- dp/wifi3.0/dp_internal.h | 10 + dp/wifi3.0/dp_main.c | 756 +++++++---------------- dp/wifi3.0/dp_mon_filter.c | 1182 ++++++++++++++++++++++++++++++++++++ dp/wifi3.0/dp_mon_filter.h | 262 ++++++++ dp/wifi3.0/dp_rx_mon.h | 12 +- dp/wifi3.0/dp_tx.c | 1 + dp/wifi3.0/dp_types.h | 3 + 11 files changed, 1677 insertions(+), 566 deletions(-) create mode 100644 dp/wifi3.0/dp_mon_filter.c create mode 100644 dp/wifi3.0/dp_mon_filter.h diff --git a/dp/inc/cdp_txrx_ctrl.h b/dp/inc/cdp_txrx_ctrl.h index 206436d42c..4ee13bf8a0 100644 --- a/dp/inc/cdp_txrx_ctrl.h +++ b/dp/inc/cdp_txrx_ctrl.h @@ -65,6 +65,8 @@ cdp_mempools_attach(ol_txrx_soc_handle soc) return soc->ops->ctrl_ops->txrx_mempools_attach(soc); } + +#if defined(ATH_SUPPORT_NAC) || defined(ATH_SUPPORT_NAC_RSSI) /** * @brief update the neighbour peer addresses * @details @@ -95,6 +97,7 @@ cdp_update_filter_neighbour_peers(ol_txrx_soc_handle soc, return soc->ops->ctrl_ops->txrx_update_filter_neighbour_peers (soc, vdev_id, cmd, macaddr); } +#endif /* ATH_SUPPORT_NAC || ATH_SUPPORT_NAC_RSSI*/ /** * @brief set the Reo Destination ring for the pdev diff --git a/dp/inc/cdp_txrx_mon.h b/dp/inc/cdp_txrx_mon.h index 11d327953e..a11bb95846 100644 --- a/dp/inc/cdp_txrx_mon.h +++ b/dp/inc/cdp_txrx_mon.h @@ -27,7 +27,8 @@ #include "cdp_txrx_handle.h" static inline QDF_STATUS cdp_reset_monitor_mode(ol_txrx_soc_handle soc, - uint8_t pdev_id) + uint8_t pdev_id, + u_int8_t smart_monitor) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -40,7 +41,8 @@ static inline QDF_STATUS cdp_reset_monitor_mode(ol_txrx_soc_handle soc, !soc->ops->mon_ops->txrx_reset_monitor_mode) return 0; - return soc->ops->mon_ops->txrx_reset_monitor_mode(soc, pdev_id); + return soc->ops->mon_ops->txrx_reset_monitor_mode(soc, pdev_id, + smart_monitor); } /** diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index f29de12d4a..2292f630d2 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -700,8 +700,8 @@ struct cdp_me_ops { struct cdp_mon_ops { - QDF_STATUS (*txrx_reset_monitor_mode)(ol_txrx_soc_handle soc, - uint8_t pdev_id); + QDF_STATUS (*txrx_reset_monitor_mode) + (ol_txrx_soc_handle soc, uint8_t pdev_id, u_int8_t smart_monitor); QDF_STATUS (*txrx_deliver_tx_mgmt) (struct cdp_soc_t *cdp_soc, uint8_t pdev_id, qdf_nbuf_t nbuf); diff --git a/dp/wifi3.0/dp_htt.h b/dp/wifi3.0/dp_htt.h index 5f7001f106..364506d66d 100644 --- a/dp/wifi3.0/dp_htt.h +++ b/dp/wifi3.0/dp_htt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -200,6 +200,8 @@ struct htt_soc { * @rx_msdu_end_offset: Offset of rx_msdu_end tlv * @rx_msdu_start_offset: Offset of rx_msdu_start tlv * @rx_attn_offset: Offset of rx_attention tlv + * + * NOTE: Do not change the layout of this structure */ struct htt_rx_ring_tlv_filter { u_int32_t mpdu_start:1, diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index b60bf02272..b508aa8fd6 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -1977,5 +1977,15 @@ QDF_STATUS dp_rx_tid_update_wifi3(struct dp_peer *peer, int tid, uint32_t uint16_t dp_get_peer_mac_list(ol_txrx_soc_handle soc, uint8_t vdev_id, u_int8_t newmac[][QDF_MAC_ADDR_SIZE], u_int16_t mac_cnt); +/* + * dp_is_hw_dbs_enable() - Procedure to check if DBS is supported + * @soc: DP SoC context + * @max_mac_rings: No of MAC rings + * + * Return: None + */ +void dp_is_hw_dbs_enable(struct dp_soc *soc, + int *max_mac_rings); + #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 442857f49f..07541b62cc 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -49,6 +49,7 @@ #include "htt_ppdu_stats.h" #include "qdf_mem.h" /* qdf_mem_malloc,free */ #include "cfg_ucfg_api.h" +#include "dp_mon_filter.h" #ifdef QCA_LL_TX_FLOW_CONTROL_V2 #include "cdp_txrx_flow_ctrl_v2.h" #else @@ -151,8 +152,6 @@ static inline QDF_STATUS dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac_addr); static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id, uint8_t *peer_mac, uint32_t bitmap); -static void dp_ppdu_ring_reset(struct dp_pdev *pdev); -static void dp_ppdu_ring_cfg(struct dp_pdev *pdev); static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle, bool unmap_only); #ifdef ENABLE_VERBOSE_DEBUG @@ -3551,6 +3550,15 @@ static inline QDF_STATUS dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, goto fail0; } + pdev->filter = dp_mon_filter_alloc(pdev); + if (!pdev->filter) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Memory allocation failed for monitor filters")); + qdf_mem_free(pdev); + ret = QDF_STATUS_E_NOMEM; + goto fail0; + } + /* * Variable to prevent double pdev deinitialization during * radio detach execution .i.e. in the absence of any vdev. @@ -3561,6 +3569,7 @@ static inline QDF_STATUS dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, if (!pdev->invalid_peer) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("Invalid peer memory allocation failed")); + dp_mon_filter_dealloc(pdev); qdf_mem_free(pdev); ret = QDF_STATUS_E_NOMEM; goto fail0; @@ -3574,6 +3583,7 @@ static inline QDF_STATUS dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, FL("pdev cfg_attach failed")); qdf_mem_free(pdev->invalid_peer); + dp_mon_filter_dealloc(pdev); qdf_mem_free(pdev); ret = QDF_STATUS_E_FAILURE; goto fail0; @@ -3805,8 +3815,11 @@ fail2: fail1: if (pdev->invalid_peer) qdf_mem_free(pdev->invalid_peer); - dp_pdev_detach((struct cdp_pdev *)pdev, 0); + if (pdev->filter) + dp_mon_filter_dealloc(pdev); + + dp_pdev_detach((struct cdp_pdev *)pdev, 0); fail0: return ret; } @@ -4107,6 +4120,13 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force) wlan_cfg_pdev_detach(pdev->wlan_cfg_ctx); if (pdev->invalid_peer) qdf_mem_free(pdev->invalid_peer); + + /* + * Fee the monitor filter allocated and stored + */ + if (pdev->filter) + dp_mon_filter_dealloc(pdev); + qdf_mem_free(pdev->dp_txrx_handle); dp_pdev_mem_reset(pdev); } @@ -5948,6 +5968,7 @@ dp_get_pdev_reo_dest(struct cdp_soc_t *txrx_soc, uint8_t pdev_id) return cdp_host_reo_dest_ring_unknown; } +#ifdef ATH_SUPPORT_NAC /* * dp_set_filter_neigh_peers() - set filter neighbour peers for smart mesh * @pdev_handle: device object @@ -5964,7 +5985,15 @@ static int dp_set_filter_neigh_peers(struct dp_pdev *pdev, pdev->filter_neighbour_peers = val; return 0; } +#else +static int dp_set_filter_neigh_peers(struct dp_pdev *pdev, + bool val) +{ + return 0; +} +#endif /* ATH_SUPPORT_NAC */ +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) /* * dp_update_filter_neighbour_peers() - set neighbour peers(nac clients) * address for smart mesh filtering @@ -6019,8 +6048,18 @@ static int dp_update_filter_neighbour_peers(struct cdp_soc_t *soc, /* first neighbour */ if (!pdev->neighbour_peers_added) { + QDF_STATUS status = QDF_STATUS_SUCCESS; + pdev->neighbour_peers_added = true; - dp_ppdu_ring_cfg(pdev); + dp_mon_filter_setup_smart_monitor(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("smart mon filter setup failed")); + dp_mon_filter_reset_smart_monitor(pdev); + pdev->neighbour_peers_added = false; + } } return 1; @@ -6039,15 +6078,20 @@ static int dp_update_filter_neighbour_peers(struct cdp_soc_t *soc, } /* last neighbour deleted */ if (TAILQ_EMPTY(&pdev->neighbour_peers_list)) { + QDF_STATUS status = QDF_STATUS_SUCCESS; + pdev->neighbour_peers_added = false; - dp_ppdu_ring_cfg(pdev); + dp_mon_filter_reset_smart_monitor(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("smart mon filter clear failed")); + } + } qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex); - - if (!pdev->mcopy_mode && !pdev->neighbour_peers_added && - !pdev->enhanced_stats_en) - dp_ppdu_ring_reset(pdev); return 1; } @@ -6055,6 +6099,7 @@ static int dp_update_filter_neighbour_peers(struct cdp_soc_t *soc, fail0: return 0; } +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ /* * dp_get_sec_type() - Get the security type @@ -6577,6 +6622,8 @@ static inline void dp_pdev_disable_mcopy_code(struct dp_pdev *pdev) { pdev->mcopy_mode = 0; + pdev->monitor_configured = false; + pdev->monitor_vdev = NULL; qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q); } @@ -6587,54 +6634,48 @@ dp_pdev_disable_mcopy_code(struct dp_pdev *pdev) * * Return: QDF_STATUS */ -QDF_STATUS dp_reset_monitor_mode(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) +QDF_STATUS dp_reset_monitor_mode(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + uint8_t special_monitor) { struct dp_soc *soc = (struct dp_soc *)soc_hdl; - struct htt_rx_ring_tlv_filter htt_tlv_filter; - int mac_id; - QDF_STATUS status = QDF_STATUS_SUCCESS; struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, pdev_id); + QDF_STATUS status = QDF_STATUS_SUCCESS; if (!pdev) return QDF_STATUS_E_FAILURE; qdf_spin_lock_bh(&pdev->mon_lock); - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - /* - * Obtain lmac id from pdev to access the ring in soc - * context - */ - int lmac_id = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev_id); - status = dp_monitor_mode_ring_config(soc, mac_for_pdev, - pdev, lmac_id, - htt_tlv_filter); - - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send tlv filter for monitor mode rings"); - qdf_spin_unlock_bh(&pdev->mon_lock); - return status; - } - - htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - soc->rxdma_mon_status_ring[lmac_id] - .hal_srng, - RXDMA_MONITOR_STATUS, RX_DATA_BUFFER_SIZE, - &htt_tlv_filter); - } - pdev->monitor_vdev = NULL; - if (pdev->mcopy_mode) - dp_pdev_disable_mcopy_code(pdev); pdev->monitor_configured = false; - qdf_spin_unlock_bh(&pdev->mon_lock); + /* + * Lite monitor mode, smart monitor mode and monitor + * mode uses this APIs to filter reset and mode disable + */ + if (pdev->mcopy_mode) { +#if defined(FEATURE_PERPKT_INFO) + dp_pdev_disable_mcopy_code(pdev); + dp_mon_filter_reset_mcopy_mode(pdev); +#endif /* FEATURE_PERPKT_INFO */ + } else if (special_monitor) { +#if defined(ATH_SUPPORT_NAC) + dp_mon_filter_reset_smart_monitor(pdev); +#endif /* ATH_SUPPORT_NAC */ + } else { + dp_mon_filter_reset_mon_mode(pdev); + } + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to reset monitor filters")); + } + + qdf_spin_unlock_bh(&pdev->mon_lock); return QDF_STATUS_SUCCESS; } @@ -6679,171 +6720,6 @@ static QDF_STATUS dp_get_peer_mac_from_peer_id(struct cdp_soc_t *soc, return QDF_STATUS_E_FAILURE; } -/** - * dp_pdev_configure_monitor_rings() - configure monitor rings - * @vdev_handle: Datapath VDEV handle - * - * Return: QDF_STATUS - */ -QDF_STATUS dp_pdev_configure_monitor_rings(struct dp_pdev *pdev) -{ - struct htt_rx_ring_tlv_filter htt_tlv_filter; - struct dp_soc *soc; - uint8_t pdev_id; - int mac_id; - QDF_STATUS status = QDF_STATUS_SUCCESS; - - pdev_id = pdev->pdev_id; - soc = pdev->soc; - - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "MODE[%x] FP[%02x|%02x|%02x] MO[%02x|%02x|%02x]", - pdev->mon_filter_mode, pdev->fp_mgmt_filter, - pdev->fp_ctrl_filter, pdev->fp_data_filter, - pdev->mo_mgmt_filter, pdev->mo_ctrl_filter, - pdev->mo_data_filter); - - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 1; - htt_tlv_filter.packet = 1; - htt_tlv_filter.msdu_end = 1; - htt_tlv_filter.mpdu_end = 1; - htt_tlv_filter.packet_header = 1; - htt_tlv_filter.attention = 1; - htt_tlv_filter.ppdu_start = 0; - htt_tlv_filter.ppdu_end = 0; - htt_tlv_filter.ppdu_end_user_stats = 0; - htt_tlv_filter.ppdu_end_user_stats_ext = 0; - htt_tlv_filter.ppdu_end_status_done = 0; - htt_tlv_filter.header_per_msdu = 1; - htt_tlv_filter.enable_fp = - (pdev->mon_filter_mode & MON_FILTER_PASS) ? 1 : 0; - htt_tlv_filter.enable_md = 0; - htt_tlv_filter.enable_mo = - (pdev->mon_filter_mode & MON_FILTER_OTHER) ? 1 : 0; - htt_tlv_filter.fp_mgmt_filter = pdev->fp_mgmt_filter; - htt_tlv_filter.fp_ctrl_filter = pdev->fp_ctrl_filter; - - if (pdev->mcopy_mode) { - htt_tlv_filter.fp_data_filter = 0; - htt_tlv_filter.mo_data_filter = 0; - } else { - htt_tlv_filter.fp_data_filter = pdev->fp_data_filter; - htt_tlv_filter.mo_data_filter = pdev->mo_data_filter; - } - htt_tlv_filter.mo_mgmt_filter = pdev->mo_mgmt_filter; - htt_tlv_filter.mo_ctrl_filter = pdev->mo_ctrl_filter; - htt_tlv_filter.offset_valid = false; - - if ((pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU) || - (pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU_MSDU)) { - htt_tlv_filter.fp_mgmt_filter = 0; - htt_tlv_filter.fp_ctrl_filter = 0; - htt_tlv_filter.fp_data_filter = 0; - htt_tlv_filter.mo_mgmt_filter = 0; - htt_tlv_filter.mo_ctrl_filter = 0; - htt_tlv_filter.mo_data_filter = 0; - } - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - /* - * Obtain lmac id from pdev to access the LMAC ring in soc - * context - */ - int lmac_id = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev_id); - - status = dp_monitor_mode_ring_config(soc, mac_for_pdev, - pdev, lmac_id, - htt_tlv_filter); - - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send tlv filter for monitor mode rings"); - return status; - } - } - - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 0; - htt_tlv_filter.packet = 0; - htt_tlv_filter.msdu_end = 0; - htt_tlv_filter.mpdu_end = 0; - if ((pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU) || - (pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU_MSDU)) { - htt_tlv_filter.mpdu_end = 1; - } - htt_tlv_filter.attention = 0; - 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 = 1; - if (pdev->mcopy_mode || - (pdev->rx_enh_capture_mode != CDP_RX_ENH_CAPTURE_DISABLED)) { - htt_tlv_filter.packet_header = 1; - if (pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU) { - htt_tlv_filter.header_per_msdu = 0; - htt_tlv_filter.enable_mo = 0; - } else if (pdev->rx_enh_capture_mode == - CDP_RX_ENH_CAPTURE_MPDU_MSDU) { - bool is_rx_mon_proto_flow_tag_enabled = - wlan_cfg_is_rx_mon_protocol_flow_tag_enabled( - soc->wlan_cfg_ctx); - htt_tlv_filter.header_per_msdu = 1; - htt_tlv_filter.enable_mo = 0; - if (pdev->is_rx_enh_capture_trailer_enabled || - is_rx_mon_proto_flow_tag_enabled) - htt_tlv_filter.msdu_end = 1; - } - } - - htt_tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - /* - * Obtain lmac id from pdev to access the LMAC ring in soc - * context - */ - int lmac_id = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev_id); - - /* - * If two back to back HTT msg sending happened in - * short time, the second HTT msg source SRNG HP - * writing has chance to fail, this has been confirmed - * by HST HW. - * for monitor mode, here is the last HTT msg for sending. - * if the 2nd HTT msg for monitor status ring sending failed, - * HW won't provide anything into 2nd monitor status ring. - * as a WAR, add some delay before 2nd HTT msg start sending, - * > 2us is required per HST HW, delay 100 us for safe. - */ - if (mac_id) - qdf_udelay(100); - - htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - soc->rxdma_mon_status_ring[lmac_id] - .hal_srng, - RXDMA_MONITOR_STATUS, - RX_DATA_BUFFER_SIZE, &htt_tlv_filter); - } - - return status; -} - /** * dp_vdev_set_monitor_mode() - Set DP VDEV to monitor mode * @vdev_handle: Datapath VDEV handle @@ -6859,6 +6735,7 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *soc, struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, vdev_id); + QDF_STATUS status = QDF_STATUS_SUCCESS; if (!vdev) return QDF_STATUS_E_FAILURE; @@ -6887,10 +6764,19 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *soc, } pdev->monitor_configured = true; - dp_mon_buf_delayed_replenish(pdev); - return dp_pdev_configure_monitor_rings(pdev); + dp_mon_filter_setup_mon_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to reset monitor filters")); + dp_mon_filter_reset_mon_mode(pdev); + pdev->monitor_configured = false; + pdev->monitor_vdev = NULL; + } + + return status; } /** @@ -6909,12 +6795,10 @@ dp_pdev_set_advance_monitor_filter(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, */ struct dp_soc *soc = (struct dp_soc *)soc_hdl; struct dp_vdev *vdev; - struct htt_rx_ring_tlv_filter htt_tlv_filter; - int mac_id; - QDF_STATUS status = QDF_STATUS_SUCCESS; struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, pdev_id); + QDF_STATUS status = QDF_STATUS_SUCCESS; if (!pdev) return QDF_STATUS_E_FAILURE; @@ -6944,131 +6828,15 @@ dp_pdev_set_advance_monitor_filter(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, pdev->mo_ctrl_filter = filter_val->mo_ctrl; pdev->mo_data_filter = filter_val->mo_data; - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "MODE[%x] FP[%02x|%02x|%02x] MO[%02x|%02x|%02x]", - pdev->mon_filter_mode, pdev->fp_mgmt_filter, - pdev->fp_ctrl_filter, pdev->fp_data_filter, - pdev->mo_mgmt_filter, pdev->mo_ctrl_filter, - pdev->mo_data_filter); - - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - /* - * Obtain lmac id from pdev to access the LMAC ring in soc - * context - */ - int lmac_id = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev_id); - - status = dp_monitor_mode_ring_config(soc, mac_for_pdev, - pdev, lmac_id, - htt_tlv_filter); - - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send tlv filter for monitor mode rings"); - return status; - } - - htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - soc->rxdma_mon_status_ring[lmac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_DATA_BUFFER_SIZE, - &htt_tlv_filter); + dp_mon_filter_setup_mon_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to set filter for advance mon mode")); + dp_mon_filter_reset_mon_mode(pdev); } - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 1; - htt_tlv_filter.packet = 1; - htt_tlv_filter.msdu_end = 1; - htt_tlv_filter.mpdu_end = 1; - htt_tlv_filter.packet_header = 1; - htt_tlv_filter.attention = 1; - htt_tlv_filter.ppdu_start = 0; - htt_tlv_filter.ppdu_end = 0; - htt_tlv_filter.ppdu_end_user_stats = 0; - htt_tlv_filter.ppdu_end_user_stats_ext = 0; - htt_tlv_filter.ppdu_end_status_done = 0; - htt_tlv_filter.header_per_msdu = 1; - htt_tlv_filter.enable_fp = - (pdev->mon_filter_mode & MON_FILTER_PASS) ? 1 : 0; - htt_tlv_filter.enable_md = 0; - htt_tlv_filter.enable_mo = - (pdev->mon_filter_mode & MON_FILTER_OTHER) ? 1 : 0; - htt_tlv_filter.fp_mgmt_filter = pdev->fp_mgmt_filter; - htt_tlv_filter.fp_ctrl_filter = pdev->fp_ctrl_filter; - if (pdev->mcopy_mode) - htt_tlv_filter.fp_data_filter = 0; - else - htt_tlv_filter.fp_data_filter = pdev->fp_data_filter; - htt_tlv_filter.mo_mgmt_filter = pdev->mo_mgmt_filter; - htt_tlv_filter.mo_ctrl_filter = pdev->mo_ctrl_filter; - htt_tlv_filter.mo_data_filter = pdev->mo_data_filter; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - /* - * Obtain lmac id from pdev to access the LMAC ring in soc - * context - */ - int lmac_id = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev_id); - - status = dp_monitor_mode_ring_config(soc, mac_for_pdev, - pdev, lmac_id, - htt_tlv_filter); - - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send tlv filter for monitor mode rings"); - return status; - } - } - - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - htt_tlv_filter.mpdu_start = 1; - 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.attention = 0; - 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 = 1; - if (pdev->mcopy_mode) { - htt_tlv_filter.packet_header = 1; - } - htt_tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = - dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - /* - * Obtain lmac id from pdev to access the LMAC ring in soc - * context - */ - int lmac_id = - dp_get_lmac_id_for_pdev_id(soc, - mac_id, pdev->pdev_id); - - htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - soc->rxdma_mon_status_ring[lmac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_DATA_BUFFER_SIZE, - &htt_tlv_filter); - } - - return QDF_STATUS_SUCCESS; + return status; } /** @@ -7664,102 +7432,6 @@ dp_print_host_stats(struct dp_vdev *vdev, return 0; } -/* - * dp_ppdu_ring_reset()- Reset PPDU Stats ring - * @pdev: DP_PDEV handle - * - * Return: void - */ -static void -dp_ppdu_ring_reset(struct dp_pdev *pdev) -{ - struct htt_rx_ring_tlv_filter htt_tlv_filter; - int mac_id; - - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = - dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id); - /* - * Obtain lmac id from pdev to access the LMAC ring in soc - * context - */ - int lmac_id = - dp_get_lmac_id_for_pdev_id(pdev->soc, - mac_id, pdev->pdev_id); - - htt_h2t_rx_ring_cfg(pdev->soc->htt_handle, mac_for_pdev, - pdev->soc->rxdma_mon_status_ring[lmac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_DATA_BUFFER_SIZE, - &htt_tlv_filter); - } -} - -/* - * 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}; - int mac_id; - - htt_tlv_filter.mpdu_start = 1; - 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.attention = 0; - 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; - if (pdev->neighbour_peers_added && - pdev->soc->hw_nac_monitor_support) { - htt_tlv_filter.enable_md = 1; - htt_tlv_filter.packet_header = 1; - } - if (pdev->mcopy_mode) { - htt_tlv_filter.packet_header = 1; - htt_tlv_filter.enable_mo = 1; - } - htt_tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - if (pdev->neighbour_peers_added && - pdev->soc->hw_nac_monitor_support) - htt_tlv_filter.md_data_filter = FILTER_DATA_ALL; - - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - /* - * Obtain lmac id from pdev to access the LMAC ring in soc - * context - */ - int lmac_id = - dp_get_lmac_id_for_pdev_id(pdev->soc, - mac_id, pdev->pdev_id); - - htt_h2t_rx_ring_cfg(pdev->soc->htt_handle, mac_for_pdev, - pdev->soc->rxdma_mon_status_ring[lmac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_DATA_BUFFER_SIZE, - &htt_tlv_filter); - } -} - /* * is_ppdu_txrx_capture_enabled() - API to check both pktlog and debug_sniffer * modes are enabled or not. @@ -7865,20 +7537,37 @@ dp_config_debug_sniffer(struct dp_pdev *pdev, int val) { QDF_STATUS status = QDF_STATUS_SUCCESS; - if (pdev->mcopy_mode) - dp_reset_monitor_mode((struct cdp_soc_t *)(pdev->soc), - pdev->pdev_id); + /* + * Note: The mirror copy mode cannot co-exist with any other + * monitor modes. Hence disabling the filter for this mode will + * reset the monitor destination ring filters. + */ + if (pdev->mcopy_mode) { +#ifdef FEATURE_PERPKT_INFO + dp_pdev_disable_mcopy_code(pdev); + dp_mon_filter_reset_mcopy_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to reset AM copy mode filters")); + } +#endif /* FEATURE_PERPKT_INFO */ + } switch (val) { case 0: pdev->tx_sniffer_enable = 0; - pdev->monitor_configured = false; + /* + * We don't need to reset the Rx monitor status ring or call + * the API dp_ppdu_ring_reset() if all debug sniffer mode is + * disabled. The Rx monitor status ring will be disabled when + * the last mode using the monitor status ring get disabled. + */ if (!pdev->pktlog_ppdu_stats && !pdev->enhanced_stats_en && !pdev->bpr_enable) { dp_h2t_cfg_stats_msg_send(pdev, 0, pdev->pdev_id); - dp_ppdu_ring_reset(pdev); } else if (pdev->enhanced_stats_en && !pdev->bpr_enable) { dp_h2t_cfg_stats_msg_send(pdev, DP_PPDU_STATS_CFG_ENH_STATS, pdev->pdev_id); @@ -7907,14 +7596,28 @@ dp_config_debug_sniffer(struct dp_pdev *pdev, int val) break; } +#ifdef FEATURE_PERPKT_INFO pdev->mcopy_mode = 1; - dp_pdev_configure_monitor_rings(pdev); - pdev->monitor_configured = true; pdev->tx_sniffer_enable = 0; + pdev->monitor_configured = true; + + /* + * Setup the M copy mode filter. + */ + dp_mon_filter_setup_mcopy_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to set M_copy mode filters")); + dp_mon_filter_reset_mcopy_mode(pdev); + dp_pdev_disable_mcopy_code(pdev); + return status; + } if (!pdev->pktlog_ppdu_stats) dp_h2t_cfg_stats_msg_send(pdev, DP_PPDU_STATS_CFG_SNIFFER, pdev->pdev_id); +#endif /* FEATURE_PERPKT_INFO */ break; default: @@ -7925,6 +7628,7 @@ dp_config_debug_sniffer(struct dp_pdev *pdev, int val) return status; } +#ifdef FEATURE_PERPKT_INFO /* * dp_enable_enhanced_stats()- API to enable enhanced statistcs * @soc_handle: DP_SOC handle @@ -7935,9 +7639,11 @@ dp_config_debug_sniffer(struct dp_pdev *pdev, int val) static QDF_STATUS dp_enable_enhanced_stats(struct cdp_soc_t *soc, uint8_t pdev_id) { - struct dp_pdev *pdev = - dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, - pdev_id); + struct dp_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); if (!pdev) return QDF_STATUS_E_FAILURE; @@ -7947,9 +7653,16 @@ dp_enable_enhanced_stats(struct cdp_soc_t *soc, uint8_t pdev_id) pdev->enhanced_stats_en = 1; - if (!pdev->mcopy_mode && !pdev->neighbour_peers_added && - !pdev->monitor_vdev) - dp_ppdu_ring_cfg(pdev); + dp_mon_filter_setup_enhanced_stats(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to set enhanced mode filters")); + dp_mon_filter_reset_enhanced_stats(pdev); + dp_cal_client_timer_stop(pdev->cal_client_ctx); + pdev->enhanced_stats_en = 0; + return QDF_STATUS_E_FAILURE; + } if (is_ppdu_txrx_capture_enabled(pdev) && !pdev->bpr_enable) { dp_h2t_cfg_stats_msg_send(pdev, DP_PPDU_STATS_CFG_ENH_STATS, pdev->pdev_id); @@ -7992,12 +7705,15 @@ dp_disable_enhanced_stats(struct cdp_soc_t *soc, uint8_t pdev_id) pdev->pdev_id); } - if (!pdev->mcopy_mode && !pdev->neighbour_peers_added && - !pdev->monitor_vdev) - dp_ppdu_ring_reset(pdev); + dp_mon_filter_reset_enhanced_stats(pdev); + if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to reset enhanced mode filters")); + } return QDF_STATUS_SUCCESS; } +#endif /* FEATURE_PERPKT_INFO */ /* * dp_get_fw_peer_stats()- function to print peer stats @@ -10175,8 +9891,10 @@ static struct cdp_ctrl_ops dp_ops_ctrl = { .txrx_get_psoc_param = dp_get_psoc_param, .txrx_set_pdev_reo_dest = dp_set_pdev_reo_dest, .txrx_get_pdev_reo_dest = dp_get_pdev_reo_dest, +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) .txrx_update_filter_neighbour_peers = dp_update_filter_neighbour_peers, +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ .txrx_get_sec_type = dp_get_sec_type, .txrx_wdi_event_sub = dp_wdi_event_sub, .txrx_wdi_event_unsub = dp_wdi_event_unsub, @@ -10234,8 +9952,10 @@ static struct cdp_host_stats_ops dp_ops_host_stats = { .txrx_per_peer_stats = dp_get_host_peer_stats, .get_fw_peer_stats = dp_get_fw_peer_stats, .get_htt_stats = dp_get_htt_stats, +#ifdef FEATURE_PERPKT_INFO .txrx_enable_enhanced_stats = dp_enable_enhanced_stats, .txrx_disable_enhanced_stats = dp_disable_enhanced_stats, +#endif /* FEATURE_PERPKT_INFO */ .txrx_stats_publish = dp_txrx_stats_publish, .txrx_get_vdev_stats = dp_txrx_get_vdev_stats, .txrx_get_peer_stats = dp_txrx_get_peer_stats, @@ -11110,7 +10830,6 @@ void *dp_get_pdev_for_mac_id(struct dp_soc *soc, uint32_t mac_id) * * Return: None */ -static void dp_is_hw_dbs_enable(struct dp_soc *soc, int *max_mac_rings) { @@ -11268,7 +10987,6 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, bool enable) { struct dp_soc *soc = NULL; - struct htt_rx_ring_tlv_filter htt_tlv_filter = {0}; int max_mac_rings = wlan_cfg_get_num_mac_rings (pdev->wlan_cfg_ctx); uint8_t mac_id = 0; @@ -11289,51 +11007,18 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, */ return 0; } + if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_FULL) { pdev->rx_pktlog_mode = DP_RX_PKTLOG_FULL; - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 1; - htt_tlv_filter.msdu_end = 1; - htt_tlv_filter.mpdu_end = 1; - 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.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < max_mac_rings; - mac_id++) { - int pdev_id = pdev->pdev_id; - int mac_for_pdev = - dp_get_mac_id_for_pdev(mac_id, - pdev_id); - /* - * Obtain LMAC id from pdev for - * accessing LMAC ring from SOC - */ - int lmac_id = - dp_get_lmac_id_for_pdev_id(soc, - mac_id, - pdev_id); - - htt_h2t_rx_ring_cfg(soc->htt_handle, - mac_for_pdev, - soc->rxdma_mon_status_ring[lmac_id] - .hal_srng, - RXDMA_MONITOR_STATUS, - RX_DATA_BUFFER_SIZE, - &htt_tlv_filter); - + dp_mon_filter_setup_rx_pkt_log_full(pdev); + if (dp_mon_filter_update(pdev) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Pktlog full filters set failed")); + dp_mon_filter_reset_rx_pkt_log_full(pdev); + pdev->rx_pktlog_mode = DP_RX_PKTLOG_DISABLED; + return 0; } if (soc->reap_timer_init) @@ -11349,47 +11034,21 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, */ return 0; } - if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_LITE) { pdev->rx_pktlog_mode = DP_RX_PKTLOG_LITE; - 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.mpdu_start = 1; - htt_tlv_filter.enable_fp = 1; - htt_tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < max_mac_rings; - mac_id++) { - int pdev_id = pdev->pdev_id; - int mac_for_pdev = - dp_get_mac_id_for_pdev(mac_id, - pdev_id); - /* - * Obtain lmac id from pdev to access - * the LMAC ring in soc context - */ - int lmac_id = - dp_get_lmac_id_for_pdev_id(soc, - mac_id, - pdev_id); - - htt_h2t_rx_ring_cfg(soc->htt_handle, - mac_for_pdev, - soc->rxdma_mon_status_ring[lmac_id] - .hal_srng, - RXDMA_MONITOR_STATUS, - RX_BUFFER_SIZE_PKTLOG_LITE, - &htt_tlv_filter); + /* + * Set the packet log lite mode filter. + */ + dp_mon_filter_setup_rx_pkt_log_lite(pdev); + if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Pktlog lite filters set failed")); + dp_mon_filter_reset_rx_pkt_log_lite(pdev); + pdev->rx_pktlog_mode = + DP_RX_PKTLOG_DISABLED; + return 0; } if (soc->reap_timer_init) @@ -11433,29 +11092,22 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, } if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) { pdev->rx_pktlog_mode = DP_RX_PKTLOG_DISABLED; + dp_mon_filter_reset_rx_pkt_log_full(pdev); + if (dp_mon_filter_update(pdev) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Pktlog filters reset failed")); + return 0; + } - for (mac_id = 0; mac_id < max_mac_rings; - mac_id++) { - int pdev_id = pdev->pdev_id; - int mac_for_pdev = - dp_get_mac_id_for_pdev(mac_id, - pdev_id); - /* - * Obtain lmac id from pdev to access - * the LMAC ring in soc context - */ - int lmac_id = - dp_get_lmac_id_for_pdev_id(soc, - mac_id, - pdev_id); - - htt_h2t_rx_ring_cfg(soc->htt_handle, - mac_for_pdev, - soc->rxdma_mon_status_ring[lmac_id] - .hal_srng, - RXDMA_MONITOR_STATUS, - RX_DATA_BUFFER_SIZE, - &htt_tlv_filter); + dp_mon_filter_reset_rx_pkt_log_lite(pdev); + if (dp_mon_filter_update(pdev) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Pktlog filters reset failed")); + return 0; } if (soc->reap_timer_init) diff --git a/dp/wifi3.0/dp_mon_filter.c b/dp/wifi3.0/dp_mon_filter.c new file mode 100644 index 0000000000..cfd9619be4 --- /dev/null +++ b/dp/wifi3.0/dp_mon_filter.c @@ -0,0 +1,1182 @@ +/* + * Copyright (c) 2020 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 +#include +#include "dp_types.h" +#include "dp_internal.h" +#include "dp_htt.h" +#include "dp_mon_filter.h" + +/** + * dp_mon_filter_mode_type_to_str + * Monitor Filter mode to string + */ +static int8_t *dp_mon_filter_mode_type_to_str[DP_MON_FILTER_MAX_MODE] = { +#ifdef FEATURE_PERPKT_INFO + "DP MON FILTER ENHACHED STATS MODE", + "DP MON FILTER MCOPY MODE", +#endif /* FEATURE_PERPKT_INFO */ +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) + "DP MON FILTER SMART MONITOR MODE", +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ + "DP_MON FILTER MONITOR MODE", +#ifdef WLAN_RX_PKT_CAPTURE_ENH + "DP MON FILTER RX CAPTURE MODE", +#endif /* WLAN_RX_PKT_CAPTURE_ENH */ +#ifdef WDI_EVENT_ENABLE + "DP MON FILTER PKT LOG FULL MODE", + "DP MON FILTER PKT LOG LITE_MODE", +#endif /* WDI_EVENT_ENABLE */ +}; + +/** + * dp_mon_filter_show_filter() - Show the set filters + * @pdev: DP pdev handle + * @mode: The filter modes + * @tlv_filter: tlv filter + */ +static void dp_mon_filter_show_filter(struct dp_pdev *pdev, + enum dp_mon_filter_mode mode, + struct dp_mon_filter *filter) +{ + struct htt_rx_ring_tlv_filter *tlv_filter = &filter->tlv_filter; + + DP_MON_FILTER_PRINT("[%s]: Valid: %d", + dp_mon_filter_mode_type_to_str[mode], + filter->valid); + DP_MON_FILTER_PRINT("mpdu_start: %d", tlv_filter->mpdu_start); + DP_MON_FILTER_PRINT("msdu_start: %d", tlv_filter->msdu_start); + DP_MON_FILTER_PRINT("packet: %d", tlv_filter->packet); + DP_MON_FILTER_PRINT("msdu_end: %d", tlv_filter->msdu_end); + DP_MON_FILTER_PRINT("mpdu_end: %d", tlv_filter->mpdu_end); + DP_MON_FILTER_PRINT("packet_header: %d", + tlv_filter->packet_header); + DP_MON_FILTER_PRINT("attention: %d", tlv_filter->attention); + DP_MON_FILTER_PRINT("ppdu_start: %d", tlv_filter->ppdu_start); + DP_MON_FILTER_PRINT("ppdu_end: %d", tlv_filter->ppdu_end); + DP_MON_FILTER_PRINT("ppdu_end_user_stats: %d", + tlv_filter->ppdu_end_user_stats); + DP_MON_FILTER_PRINT("ppdu_end_user_stats_ext: %d", + tlv_filter->ppdu_end_user_stats_ext); + DP_MON_FILTER_PRINT("ppdu_end_status_done: %d", + tlv_filter->ppdu_end_status_done); + DP_MON_FILTER_PRINT("header_per_msdu: %d", tlv_filter->header_per_msdu); + DP_MON_FILTER_PRINT("enable_fp: %d", tlv_filter->enable_fp); + DP_MON_FILTER_PRINT("enable_md: %d", tlv_filter->enable_md); + DP_MON_FILTER_PRINT("enable_mo: %d", tlv_filter->enable_mo); + DP_MON_FILTER_PRINT("fp_mgmt_filter: 0x%x", tlv_filter->fp_mgmt_filter); + DP_MON_FILTER_PRINT("mo_mgmt_filter: 0x%x", tlv_filter->mo_mgmt_filter); + DP_MON_FILTER_PRINT("fp_ctrl_filter: 0x%x", tlv_filter->fp_ctrl_filter); + DP_MON_FILTER_PRINT("mo_ctrl_filter: 0x%x", tlv_filter->mo_ctrl_filter); + DP_MON_FILTER_PRINT("fp_data_filter: 0x%x", tlv_filter->fp_data_filter); + DP_MON_FILTER_PRINT("mo_data_filter: 0x%x", tlv_filter->mo_data_filter); + DP_MON_FILTER_PRINT("md_data_filter: 0x%x", tlv_filter->md_data_filter); + DP_MON_FILTER_PRINT("md_mgmt_filter: 0x%x", tlv_filter->md_mgmt_filter); + DP_MON_FILTER_PRINT("md_ctrl_filter: 0x%x", tlv_filter->md_ctrl_filter); +} + +/** + * dp_mon_ht2_rx_ring_cfg() - Send the tlv config to fw for a srng_type + * based on target + * @soc: DP soc handle + * @pdev: DP pdev handle + * @srng_type: The srng type for which filter wll be set + * @tlv_filter: tlv filter + */ +static QDF_STATUS +dp_mon_ht2_rx_ring_cfg(struct dp_soc *soc, + struct dp_pdev *pdev, + enum dp_mon_filter_srng_type srng_type, + struct htt_rx_ring_tlv_filter *tlv_filter) +{ + int mac_id; + int max_mac_rings = wlan_cfg_get_num_mac_rings(pdev->wlan_cfg_ctx); + QDF_STATUS status = QDF_STATUS_SUCCESS; + + /* + * Overwrite the max_mac_rings for the status rings. + */ + if (srng_type == DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS) + dp_is_hw_dbs_enable(soc, &max_mac_rings); + + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_INFO, + FL("srng type %d Max_mac_rings %d "), + srng_type, + max_mac_rings); + + /* + * Loop through all MACs per radio and set the filter to the individual + * macs. For MCL + */ + for (mac_id = 0; mac_id < max_mac_rings; mac_id++) { + int mac_for_pdev = + dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id); + int lmac_id = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev->pdev_id); + int hal_ring_type, ring_buf_size; + hal_ring_handle_t hal_ring_hdl; + + switch (srng_type) { + case DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF: + hal_ring_hdl = pdev->rx_mac_buf_ring[lmac_id].hal_srng; + hal_ring_type = RXDMA_BUF; + ring_buf_size = RX_DATA_BUFFER_SIZE; + break; + + case DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS: + /* + * If two back to back HTT msg sending happened in + * short time, the second HTT msg source SRNG HP + * writing has chance to fail, this has been confirmed + * by HST HW. + * for monitor mode, here is the last HTT msg for sending. + * if the 2nd HTT msg for monitor status ring sending failed, + * HW won't provide anything into 2nd monitor status ring. + * as a WAR, add some delay before 2nd HTT msg start sending, + * > 2us is required per HST HW, delay 100 us for safe. + */ + if (mac_id) + qdf_udelay(100); + + hal_ring_hdl = + soc->rxdma_mon_status_ring[lmac_id].hal_srng; + hal_ring_type = RXDMA_MONITOR_STATUS; + ring_buf_size = RX_DATA_BUFFER_SIZE; + break; + + case DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF: + hal_ring_hdl = + soc->rxdma_mon_buf_ring[lmac_id].hal_srng; + hal_ring_type = RXDMA_MONITOR_BUF; + ring_buf_size = RX_DATA_BUFFER_SIZE; + break; + + default: + return QDF_STATUS_E_FAILURE; + } + + status = htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, + hal_ring_hdl, hal_ring_type, + ring_buf_size, + tlv_filter); + if (status != QDF_STATUS_SUCCESS) + return status; + } + + return status; +} + +/** + * dp_mon_filter_ht2_setup() - Setup the filter for the Target setup + * @soc: DP soc handle + * @pdev: DP pdev handle + * @srng_type: The srng type for which filter wll be set + * @tlv_filter: tlv filter + */ +static void dp_mon_filter_ht2_setup(struct dp_soc *soc, struct dp_pdev *pdev, + enum dp_mon_filter_srng_type srng_type, + struct dp_mon_filter *filter) +{ + int32_t current_mode = 0; + struct htt_rx_ring_tlv_filter *tlv_filter = &filter->tlv_filter; + + /* + * Loop through all the modes. + */ + for (current_mode = 0; current_mode < DP_MON_FILTER_MAX_MODE; + current_mode++) { + struct dp_mon_filter *mon_filter = + &pdev->filter[current_mode][srng_type]; + uint32_t src_filter = 0, dst_filter = 0; + + /* + * Check if the correct mode is enabled or not. + */ + if (!mon_filter->valid) + continue; + + filter->valid = true; + + /* + * Set the super bit fields + */ + src_filter = + DP_MON_FILTER_GET(&mon_filter->tlv_filter, FILTER_TLV); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_TLV); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_TLV, dst_filter); + + /* + * Set the filter management filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_FP_MGMT); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_FP_MGMT); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_FP_MGMT, dst_filter); + + /* + * Set the monitor other management filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MO_MGMT); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MO_MGMT); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MO_MGMT, dst_filter); + + /* + * Set the filter pass control filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_FP_CTRL); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_FP_CTRL); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_FP_CTRL, dst_filter); + + /* + * Set the monitor other control filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MO_CTRL); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MO_CTRL); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MO_CTRL, dst_filter); + + /* + * Set the filter pass data filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_FP_DATA); + dst_filter = DP_MON_FILTER_GET(tlv_filter, + FILTER_FP_DATA); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, + FILTER_FP_DATA, dst_filter); + + /* + * Set the monitor other data filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MO_DATA); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MO_DATA); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MO_DATA, dst_filter); + + /* + * Set the monitor direct data filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MD_DATA); + dst_filter = DP_MON_FILTER_GET(tlv_filter, + FILTER_MD_DATA); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, + FILTER_MD_DATA, dst_filter); + + /* + * Set the monitor direct management filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MD_MGMT); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MD_MGMT); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MD_MGMT, dst_filter); + + /* + * Set the monitor direct management filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MD_CTRL); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MD_CTRL); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MD_CTRL, dst_filter); + } + + dp_mon_filter_show_filter(pdev, 0, filter); +} + +/** + * dp_mon_filter_reset_mon_srng() + * @soc: DP SoC handle + * @pdev: DP pdev handle + * @mon_srng_type: Monitor srng type + */ +static void +dp_mon_filter_reset_mon_srng(struct dp_soc *soc, struct dp_pdev *pdev, + enum dp_mon_filter_srng_type mon_srng_type) +{ + struct htt_rx_ring_tlv_filter tlv_filter = {0}; + + if (dp_mon_ht2_rx_ring_cfg(soc, pdev, mon_srng_type, + &tlv_filter) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor destinatin ring filter setting failed")); + } +} + +#if defined(FEATURE_PERPKT_INFO) || defined(ATH_SUPPORT_NAC_RSSI) \ + || defined(ATH_SUPPORT_NAC) || defined(WLAN_RX_PKT_CAPTURE_ENH) +/** + * dp_mon_filter_check_co_exist() - Check the co-existing of the + * enabled modes. + * @pdev: DP pdev handle + * + * Return: QDF_STATUS + */ +static QDF_STATUS dp_mon_filter_check_co_exist(struct dp_pdev *pdev) +{ + /* + * Check if the Rx Enhanced capture mode, monitor mode, + * smart_monitor_mode and mcopy mode can co-exist together. + */ + if ((pdev->rx_enh_capture_mode != CDP_RX_ENH_CAPTURE_DISABLED) && + ((pdev->neighbour_peers_added && pdev->monitor_vdev) || + pdev->mcopy_mode)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Rx Capture mode can't exist with modes:\n" + "Smart Monitor Mode:%d\n" + "M_Copy Mode:%d"), + pdev->neighbour_peers_added, + pdev->mcopy_mode); + return QDF_STATUS_E_FAILURE; + } + + /* + * Check if the monitor mode cannot co-exist with any other mode. + */ + if ((pdev->monitor_vdev && pdev->monitor_configured) && + (pdev->mcopy_mode || pdev->neighbour_peers_added)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor mode can't exist with modes\n" + "M_Copy Mode:%d\n" + "Smart Monitor Mode:%d"), + pdev->mcopy_mode, + pdev->neighbour_peers_added); + return QDF_STATUS_E_FAILURE; + } + + /* + * Check if the smart monitor mode can co-exist with any other mode + */ + if (pdev->neighbour_peers_added && + ((pdev->mcopy_mode) || pdev->monitor_configured)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Smart Monitor mode can't exist with modes\n" + "M_Copy Mode:%d\n" + "Monitor Mode:%d"), + pdev->mcopy_mode, + pdev->monitor_configured); + return QDF_STATUS_E_FAILURE; + } + + /* + * Check if the m_copy, monitor mode and the smart_monitor_mode + * can co-exist togther. + */ + if (pdev->mcopy_mode && + (pdev->monitor_vdev || pdev->neighbour_peers_added)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("mcopy mode can't exist with modes\n" + "Monitor Mode:%d\n" + "Smart Monitor Mode:%d"), + pdev->monitor_vdev, + pdev->neighbour_peers_added); + return QDF_STATUS_E_FAILURE; + } + + /* + * Check if the Rx packet log lite or full can co-exist with + * the enable modes. + */ + if ((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) && + (pdev->monitor_vdev || pdev->monitor_configured)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Rx pktlog full/lite can't exist with modes\n" + "Monitor Mode:%d"), + pdev->monitor_configured); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS dp_mon_filter_check_co_exist(struct dp_pdev *pdev) +{ + /* + * Check if the Rx packet log lite or full can co-exist with + * the enable modes. + */ + if ((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) && + (pdev->monitor_vdev || pdev->monitor_configured)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Rx pktlog full/lite can't exist with modes\n" + "Monitor Mode:%d"), + pdev->monitor_configured); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} +#endif + +/** + * dp_mon_filter_set_mon_cmn() - Setp the common mon filters + * @pdev: DP pdev handle + * @filter: DP mon filter + * + * Return: QDF_STATUS + */ +static void dp_mon_filter_set_mon_cmn(struct dp_pdev *pdev, + struct dp_mon_filter *filter) +{ + filter->tlv_filter.mpdu_start = 1; + filter->tlv_filter.msdu_start = 1; + filter->tlv_filter.packet = 1; + filter->tlv_filter.msdu_end = 1; + filter->tlv_filter.mpdu_end = 1; + filter->tlv_filter.packet_header = 1; + filter->tlv_filter.attention = 1; + filter->tlv_filter.ppdu_start = 0; + filter->tlv_filter.ppdu_end = 0; + filter->tlv_filter.ppdu_end_user_stats = 0; + filter->tlv_filter.ppdu_end_user_stats_ext = 0; + filter->tlv_filter.ppdu_end_status_done = 0; + filter->tlv_filter.header_per_msdu = 1; + filter->tlv_filter.enable_fp = + (pdev->mon_filter_mode & MON_FILTER_PASS) ? 1 : 0; + filter->tlv_filter.enable_mo = + (pdev->mon_filter_mode & MON_FILTER_OTHER) ? 1 : 0; + + filter->tlv_filter.fp_mgmt_filter = pdev->fp_mgmt_filter; + filter->tlv_filter.fp_ctrl_filter = pdev->fp_ctrl_filter; + filter->tlv_filter.fp_data_filter = pdev->fp_data_filter; + filter->tlv_filter.mo_mgmt_filter = pdev->mo_mgmt_filter; + filter->tlv_filter.mo_ctrl_filter = pdev->mo_ctrl_filter; + filter->tlv_filter.mo_data_filter = pdev->mo_data_filter; + filter->tlv_filter.offset_valid = false; +} + +/** + * dp_mon_filter_set_status_cmn() - Setp the common status filters + * @pdev: DP pdev handle + * @filter: Dp mon filters + * + * Return: QDF_STATUS + */ +static void dp_mon_filter_set_status_cmn(struct dp_pdev *pdev, + struct dp_mon_filter *filter) +{ + filter->tlv_filter.mpdu_start = 1; + filter->tlv_filter.msdu_start = 0; + filter->tlv_filter.packet = 0; + filter->tlv_filter.msdu_end = 0; + filter->tlv_filter.mpdu_end = 0; + filter->tlv_filter.attention = 0; + filter->tlv_filter.ppdu_start = 1; + filter->tlv_filter.ppdu_end = 1; + filter->tlv_filter.ppdu_end_user_stats = 1; + filter->tlv_filter.ppdu_end_user_stats_ext = 1; + filter->tlv_filter.ppdu_end_status_done = 1; + filter->tlv_filter.enable_fp = 1; + filter->tlv_filter.enable_md = 0; + filter->tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; + filter->tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; + filter->tlv_filter.fp_data_filter = FILTER_DATA_ALL; + filter->tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; + filter->tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; + filter->tlv_filter.mo_data_filter = FILTER_DATA_ALL; + filter->tlv_filter.offset_valid = false; +} + +#ifdef FEATURE_PERPKT_INFO +/** + * dp_mon_filter_setup_enhanced_stats() - Setup the enhanced stats filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_enhanced_stats(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_ENHACHED_STATS_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + + dp_mon_filter_set_status_cmn(pdev, &filter); + dp_mon_filter_show_filter(pdev, mode, &filter); + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_enhanced_stats() - Reset the enhanced stats filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_enhanced_stats(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_ENHACHED_STATS_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_setup_mcopy_mode() - Setup the m_copy mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_mcopy_mode(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_MCOPY_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_mon_cmn(pdev, &filter); + + filter.tlv_filter.fp_data_filter = 0; + filter.tlv_filter.mo_data_filter = 0; + + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + /* Clear the filter as the same filter will be used to set the + * monitor status ring + */ + qdf_mem_zero(&(filter), sizeof(struct dp_mon_filter)); + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + /* Setup the filter */ + filter.tlv_filter.enable_mo = 1; + filter.tlv_filter.packet_header = 1; + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_mcopy_mode() - Reset the m_copy mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_mcopy_mode(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_MCOPY_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} +#endif /* FEATURE_PERPKT_INFO */ + +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) +/** + * dp_mon_filter_setup_smart_monitor() - Setup the smart monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_smart_monitor(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_SMART_MONITOR_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + if (soc->hw_nac_monitor_support) { + filter.tlv_filter.enable_md = 1; + filter.tlv_filter.packet_header = 1; + filter.tlv_filter.md_data_filter = FILTER_DATA_ALL; + } + + dp_mon_filter_show_filter(pdev, mode, &filter); + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_smart_monitor() - Reset the smart monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_smart_monitor(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_SMART_MONITOR_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + pdev->filter[mode][srng_type] = filter; +} +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ + +#ifdef WLAN_RX_PKT_CAPTURE_ENH +/** + * dp_mon_filter_setup_rx_enh_capture() - Setup the Rx capture mode filters + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_enh_capture(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_RX_CAPTURE_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_mon_cmn(pdev, &filter); + + filter.tlv_filter.fp_mgmt_filter = 0; + filter.tlv_filter.fp_ctrl_filter = 0; + filter.tlv_filter.fp_data_filter = 0; + filter.tlv_filter.mo_mgmt_filter = 0; + filter.tlv_filter.mo_ctrl_filter = 0; + filter.tlv_filter.mo_data_filter = 0; + + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + /* Clear the filter as the same filter will be used to set the + * monitor status ring + */ + qdf_mem_zero(&(filter), sizeof(struct dp_mon_filter)); + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + /* Setup the filter */ + filter.tlv_filter.mpdu_end = 1; + filter.tlv_filter.enable_mo = 1; + filter.tlv_filter.packet_header = 1; + + if (pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU) { + filter.tlv_filter.header_per_msdu = 0; + filter.tlv_filter.enable_mo = 0; + } else if (pdev->rx_enh_capture_mode == + CDP_RX_ENH_CAPTURE_MPDU_MSDU) { + bool is_rx_mon_proto_flow_tag_enabled = + wlan_cfg_is_rx_mon_protocol_flow_tag_enabled(soc->wlan_cfg_ctx); + filter.tlv_filter.header_per_msdu = 1; + filter.tlv_filter.enable_mo = 0; + if (pdev->is_rx_enh_capture_trailer_enabled || + is_rx_mon_proto_flow_tag_enabled) + filter.tlv_filter.msdu_end = 1; + } + + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_rx_enh_capture() - Reset the Rx capture mode filters + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_enh_capture(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_RX_CAPTURE_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} +#endif /* WLAN_RX_PKT_CAPTURE_ENH */ + +/** + * dp_mon_filter_setup_mon_mode() - Setup the Rx monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_mon_mode(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_MONITOR_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + filter.valid = true; + dp_mon_filter_set_mon_cmn(pdev, &filter); + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + /* Clear the filter as the same filter will be used to set the + * monitor status ring + */ + qdf_mem_zero(&(filter), sizeof(struct dp_mon_filter)); + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + filter.tlv_filter.enable_mo = 1; + + dp_mon_filter_show_filter(pdev, mode, &filter); + + /* Store the above filter */ + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_mon_mode() - Reset the Rx monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_mon_mode(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_MONITOR_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} + +#ifdef WDI_EVENT_ENABLE +/** + * dp_mon_filter_setup_rx_pkt_log_full() - Setup the Rx pktlog full mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_pkt_log_full(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_FULL_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + /* Setup the filter */ + filter.tlv_filter.packet_header = 1; + filter.tlv_filter.msdu_start = 1; + filter.tlv_filter.msdu_end = 1; + filter.tlv_filter.mpdu_end = 1; + filter.tlv_filter.attention = 1; + + dp_mon_filter_show_filter(pdev, mode, &filter); + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_rx_pkt_log_full() - Reset the Rx pktlog full mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_pkt_log_full(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_FULL_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_setup_rx_pkt_log_lite() - Setup the Rx pktlog lite mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_pkt_log_lite(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_LITE_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + dp_mon_filter_show_filter(pdev, mode, &filter); + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_rx_pkt_log_lite() - Reset the Rx pktlog lite mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_pkt_log_lite(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_LITE_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + pdev->filter[mode][srng_type] = filter; +} +#endif /* WDI_EVENT_ENABLE */ + +/** + * dp_mon_filter_update() - Setup the monitor filter setting for a srng + * type + * @pdev: DP pdev handle + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_mon_filter_update(struct dp_pdev *pdev) +{ + struct dp_soc *soc; + bool mon_mode_set = false; + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_srng_type mon_srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return QDF_STATUS_E_FAILURE; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return QDF_STATUS_E_FAILURE; + } + + status = dp_mon_filter_check_co_exist(pdev); + if (status != QDF_STATUS_SUCCESS) + return status; + + /* + * Setup the filters for the monitor destination ring. + */ + if (!soc->wlan_cfg_ctx->rxdma1_enable) + mon_srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF; + + /* + * Setup the filters for the monitor mode. + */ + qdf_mem_zero(&(filter), sizeof(filter)); + dp_mon_filter_ht2_setup(soc, pdev, mon_srng_type, &filter); + + mon_mode_set = filter.valid; + if (mon_mode_set) { + status = dp_mon_ht2_rx_ring_cfg(soc, pdev, + mon_srng_type, + &filter.tlv_filter); + } else { + /* + * For WIN case the monitor buffer ring is used and it does need + * reset when monitor mode gets disabled. + */ + if (soc->wlan_cfg_ctx->rxdma1_enable) { + status = dp_mon_ht2_rx_ring_cfg(soc, pdev, + mon_srng_type, + &filter.tlv_filter); + } + } + + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor destination ring filter setting failed")); + return QDF_STATUS_E_FAILURE; + } + + /* + * Setup the filters for the status ring. + */ + qdf_mem_zero(&(filter), sizeof(filter)); + dp_mon_filter_ht2_setup(soc, pdev, + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS, + &filter); + + /* + * Reset the monitor filters if the all the modes for the status rings + * are disabled. This is done to prevent the HW backpressure from the + * monitor destination ring in case the status ring filters + * are not enabled. + */ + if (!filter.valid && mon_mode_set) + dp_mon_filter_reset_mon_srng(soc, pdev, mon_srng_type); + + if (dp_mon_ht2_rx_ring_cfg(soc, pdev, + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS, + &filter.tlv_filter) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor status ring filter setting failed")); + dp_mon_filter_reset_mon_srng(soc, pdev, mon_srng_type); + return QDF_STATUS_E_FAILURE; + } + + return status; +} + +/** + * dp_mon_filter_dealloc() - Deallocate the filter objects to be stored in + * the radio object. + * @pdev: DP pdev handle + */ +void dp_mon_filter_dealloc(struct dp_pdev *pdev) +{ + enum dp_mon_filter_mode mode; + struct dp_mon_filter **mon_filter = NULL; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + mon_filter = pdev->filter; + + /* + * Check if the monitor filters are already allocated to the pdev. + */ + if (!mon_filter) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Found NULL memmory for the Monitor filter")); + return; + } + + /* + * Iterate through the every mode and free the filter object. + */ + for (mode = 0; mode < DP_MON_FILTER_MAX_MODE; mode++) { + if (!mon_filter[mode]) { + continue; + } + + qdf_mem_free(mon_filter[mode]); + mon_filter[mode] = NULL; + } + + qdf_mem_free(mon_filter); + pdev->filter = NULL; +} + +/** + * dp_mon_filter_alloc() - Allocate the filter objects to be stored in + * the radio object. + * @pdev: DP pdev handle + */ +struct dp_mon_filter **dp_mon_filter_alloc(struct dp_pdev *pdev) +{ + struct dp_mon_filter **mon_filter = NULL; + enum dp_mon_filter_mode mode; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return NULL; + } + + mon_filter = (struct dp_mon_filter **)qdf_mem_malloc( + (sizeof(struct dp_mon_filter *) * + DP_MON_FILTER_MAX_MODE)); + if (!mon_filter) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor filter mem allocation failed")); + return NULL; + } + + qdf_mem_zero(mon_filter, + sizeof(struct dp_mon_filter *) * DP_MON_FILTER_MAX_MODE); + + /* + * Allocate the memory for filters for different srngs for each modes. + */ + for (mode = 0; mode < DP_MON_FILTER_MAX_MODE; mode++) { + mon_filter[mode] = qdf_mem_malloc(sizeof(struct dp_mon_filter) * + DP_MON_FILTER_SRNG_TYPE_MAX); + /* Assign the mon_filter to the pdev->filter such + * that the dp_mon_filter_dealloc() can free up the filters. */ + if (!mon_filter[mode]) { + pdev->filter = mon_filter; + goto fail; + } + } + + return mon_filter; +fail: + dp_mon_filter_dealloc(pdev); + return NULL; +} diff --git a/dp/wifi3.0/dp_mon_filter.h b/dp/wifi3.0/dp_mon_filter.h new file mode 100644 index 0000000000..711185f28b --- /dev/null +++ b/dp/wifi3.0/dp_mon_filter.h @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef _DP_MON_FILTER_H_ +#define _DP_MON_FILTER_H_ + +/** + * Accessor Macros to access the software + * defined HTT filter htt_rx_ring_tlv_filter. + */ +#define DP_MON_FILTER_TLV_OFFSET 0x00000000 +#define DP_MON_FILTER_TLV_MASK 0xffffffff +#define DP_MON_FILTER_TLV_LSB 0 + +#define DP_MON_FILTER_FP_MGMT_OFFSET 0x00000004 +#define DP_MON_FILTER_FP_MGMT_MASK 0x0000ffff +#define DP_MON_FILTER_FP_MGMT_LSB 0 + +#define DP_MON_FILTER_MO_MGMT_OFFSET 0x00000004 +#define DP_MON_FILTER_MO_MGMT_MASK 0xffff0000 +#define DP_MON_FILTER_MO_MGMT_LSB 16 + +#define DP_MON_FILTER_FP_CTRL_OFFSET 0x00000008 +#define DP_MON_FILTER_FP_CTRL_MASK 0x0000ffff +#define DP_MON_FILTER_FP_CTRL_LSB 0 + +#define DP_MON_FILTER_MO_CTRL_OFFSET 0x00000008 +#define DP_MON_FILTER_MO_CTRL_MASK 0xffff0000 +#define DP_MON_FILTER_MO_CTRL_LSB 16 + +#define DP_MON_FILTER_FP_DATA_OFFSET 0x0000000c +#define DP_MON_FILTER_FP_DATA_MASK 0x0000ffff +#define DP_MON_FILTER_FP_DATA_LSB 0 + +#define DP_MON_FILTER_MO_DATA_OFFSET 0x0000000c +#define DP_MON_FILTER_MO_DATA_MASK 0xffff0000 +#define DP_MON_FILTER_MO_DATA_LSB 16 + +#define DP_MON_FILTER_MD_DATA_OFFSET 0x00000010 +#define DP_MON_FILTER_MD_DATA_MASK 0x0000ffff +#define DP_MON_FILTER_MD_DATA_LSB 0 + +#define DP_MON_FILTER_MD_MGMT_OFFSET 0x00000010 +#define DP_MON_FILTER_MD_MGMT_MASK 0xffff0000 +#define DP_MON_FILTER_MD_MGMT_LSB 16 + +#define DP_MON_FILTER_MD_CTRL_OFFSET 0x00000014 +#define DP_MON_FILTER_MD_CTRL_MASK 0x0000ffff +#define DP_MON_FILTER_MD_CTRL_LSB 0 + +#define DP_MON_FILTER_GET(src, field) \ + ((*((uint32_t *)((uint8_t *)(src) + DP_MON_ ## field ## _OFFSET)) & \ + (DP_MON_ ## field ## _MASK)) >> DP_MON_ ## field ## _LSB) \ + +#define DP_MON_FILTER_SET(dst, field, value) \ +do { \ + uint32_t *val = \ + ((uint32_t *)((uint8_t *)(dst) + DP_MON_ ## field ## _OFFSET)); \ + *val &= ~(DP_MON_ ## field ## _MASK); \ + *val |= ((value) << DP_MON_ ## field ## _LSB); \ +} while (0) + +#define DP_MON_FILTER_PRINT(fmt, args ...) \ + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_DEBUG, \ + fmt, ## args) +/** + * struct dp_mon_filter - Monitor TLV filter + * @valid: enable/disable TLV filter + * @tlv_filter: Rx ring TLV filter + */ +struct dp_mon_filter { + bool valid; + struct htt_rx_ring_tlv_filter tlv_filter; +}; + +/** + * enum dp_mon_filter_mode - Different modes for SRNG filters + * @DP_MON_FILTER_ENHACHED_STATS_MODE: PPDU enhanced stats mode + * @DP_MON_FILTER_SMART_MONITOR_MODE: Smart monitor mode + * @DP_MON_FILTER_MCOPY_MODE: AM copy mode + * @DP_MON_FILTER_MONITOR_MODE: Monitor mode + * @DP_MON_FILTER_RX_CAPTURE_MODE: Rx Capture mode + * @DP_MON_FILTER_PKT_LOG_FULL_MODE: Packet log full mode + * @DP_MON_FILTER_PKT_LOG_LITE_MODE: Packet log lite mode + */ +enum dp_mon_filter_mode { +#ifdef FEATURE_PERPKT_INFO + DP_MON_FILTER_ENHACHED_STATS_MODE, + DP_MON_FILTER_MCOPY_MODE, +#endif /* FEATURE_PERPKT_INFO */ +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) + DP_MON_FILTER_SMART_MONITOR_MODE, +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ + DP_MON_FILTER_MONITOR_MODE, +#ifdef WLAN_RX_PKT_CAPTURE_ENH + DP_MON_FILTER_RX_CAPTURE_MODE, +#endif /* WLAN_RX_PKT_CAPTURE_ENH */ + +#ifdef WDI_EVENT_ENABLE + DP_MON_FILTER_PKT_LOG_FULL_MODE, + DP_MON_FILTER_PKT_LOG_LITE_MODE, +#endif /* WDI_EVENT_ENABLE */ + DP_MON_FILTER_MAX_MODE +}; + +/** + * enum dp_mon_filter_srng_type - Srng types dynamic mode filter + * settings. + * @DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF: RXDMA srng type + * @DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS: RxDMA monitor status srng + * @DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF: RxDMA destination srng + * @DP_MON_FILTER_SRNG_TYPE_MAX: Srng max type + */ +enum dp_mon_filter_srng_type { + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF, + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS, + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF, + DP_MON_FILTER_SRNG_TYPE_MAX +}; + +/** + * enum dp_mon_filter_action - Action for storing the filters + * into the radio structure. + * @DP_MON_FILTER_CLEAR - Clears the filter for a mode + * @DP_MON_FILTER_SET - Set the filtes for a mode + */ +enum dp_mon_filter_action { + DP_MON_FILTER_CLEAR, + DP_MON_FILTER_SET, +}; + +#ifdef FEATURE_PERPKT_INFO +/** + * dp_mon_filter_setup_enhanced_stats() - Setup the enhanced stats filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_enhanced_stats(struct dp_pdev *pdev); + +/*** + * dp_mon_filter_reset_enhanced_stats() - Reset the enhanced stats filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_enhanced_stats(struct dp_pdev *pdev); + +/** + * dp_mon_filter_setup_mcopy_mode() - Setup the m_copy mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_mcopy_mode(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_mcopy_mode() - Reset the m_copy mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_mcopy_mode(struct dp_pdev *pdev); +#endif /* FEATURE_PERPKT_INFO */ + +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) +/** + * dp_mon_filter_setup_smart_monitor() - Setup the smart monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_smart_monitor(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_smart_monitor() - Reset the smart monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_smart_monitor(struct dp_pdev *pdev); +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ + +#ifdef WLAN_RX_PKT_CAPTURE_ENH +/** + * dp_mon_filter_setup_rx_enh_capture() - Setup the Rx capture mode filters + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_enh_capture(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_rx_enh_capture() - Reset the Rx capture mode filters + * @pdev: DP pdev handle + */ +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 + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_mon_mode(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_mon_mode() - Reset the Rx monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_mon_mode(struct dp_pdev *pdev); + +#ifdef WDI_EVENT_ENABLE +/** + * dp_mon_filter_setup_rx_pkt_log_full() - Setup the Rx pktlog full mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_pkt_log_full(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_rx_pkt_log_full() - Reset the Rx pktlog full mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_pkt_log_full(struct dp_pdev *pdev); + +/** + * dp_mon_filter_setup_rx_pkt_log_lite() - Setup the Rx pktlog lite mode filter + * in the radio object. + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_pkt_log_lite(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_rx_pkt_log_lite() - Reset the Rx pktlog lite mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_pkt_log_lite(struct dp_pdev *pdev); +#endif /* WDI_EVENT_ENABLE */ + +/** + * dp_mon_filter_update() - Setup the monitor filter setting for a srng + * type + * @pdev: DP pdev handle + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_mon_filter_update(struct dp_pdev *pdev); + +/** + * dp_mon_filter_dealloc() - Deallocate the filter objects to be stored in + * the radio object. + * @pdev: DP pdev handle + */ +void dp_mon_filter_dealloc(struct dp_pdev *pdev); + +/** + * dp_mon_filter_alloc() - Allocate the filter objects to be stored in + * the radio object. + * @pdev: DP pdev handle + */ +struct dp_mon_filter **dp_mon_filter_alloc(struct dp_pdev *pdev); +#endif /* #ifndef _DP_MON_FILTER_H_ */ diff --git a/dp/wifi3.0/dp_rx_mon.h b/dp/wifi3.0/dp_rx_mon.h index f6b6315618..80eda34f67 100644 --- a/dp/wifi3.0/dp_rx_mon.h +++ b/dp/wifi3.0/dp_rx_mon.h @@ -45,15 +45,9 @@ QDF_STATUS dp_rx_pdev_mon_status_detach(struct dp_pdev *pdev, int mac_id); * * Return: QDF_STATUS */ -QDF_STATUS dp_reset_monitor_mode(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); - -/** - * dp_pdev_configure_monitor_rings() - configure monitor rings - * @vdev_handle: Datapath VDEV handle - * - * Return: QDF_STATUS - */ -QDF_STATUS dp_pdev_configure_monitor_rings(struct dp_pdev *pdev); +QDF_STATUS dp_reset_monitor_mode(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + uint8_t smart_monitor); /** * dp_mon_link_free() - free monitor link desc pool diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 5fe16a0491..a185815510 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -3143,6 +3143,7 @@ static inline void dp_tx_sojourn_stats_process(struct dp_pdev *pdev, } #else static inline void dp_tx_sojourn_stats_process(struct dp_pdev *pdev, + struct dp_peer *peer, uint8_t tid, uint64_t txdesc_ts, uint32_t ppdu_id) diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 51ee721b8e..90f446e889 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -134,6 +134,7 @@ union dp_rx_desc_list_elem_t; struct cdp_peer_rate_stats_ctx; struct cdp_soc_rate_stats_ctx; struct dp_rx_fst; +struct dp_mon_filter; #define DP_PDEV_ITERATE_VDEV_LIST(_pdev, _vdev) \ TAILQ_FOREACH((_vdev), &(_pdev)->vdev_list, vdev_list_elem) @@ -1774,6 +1775,8 @@ struct dp_pdev { #ifdef WLAN_SUPPORT_DATA_STALL data_stall_detect_cb data_stall_detect_callback; #endif /* WLAN_SUPPORT_DATA_STALL */ + + struct dp_mon_filter **filter; /* Monitor Filter pointer */ }; struct dp_peer;