diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 697d3cd8d3..d3606db24b 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -201,6 +201,17 @@ static inline QDF_STATUS monitor_pdev_deinit(struct dp_pdev *pdev) { return QDF_STATUS_SUCCESS; } + +static inline QDF_STATUS monitor_soc_cfg_init(struct dp_soc *soc) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS monitor_config_debug_sniffer(struct dp_pdev *pdev, + int val) +{ + return QDF_STATUS_E_FAILURE; +} #endif #ifdef WLAN_TX_PKT_CAPTURE_ENH diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 061554f4e0..4fea0e94f7 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -283,8 +283,8 @@ dp_is_enable_reap_timer_non_pkt(struct dp_pdev *pdev); static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc, enum hal_ring_type ring_type, int ring_num); -static QDF_STATUS dp_vdev_set_monitor_mode_rings(struct dp_pdev *pdev, - uint8_t delayed_replenish); +QDF_STATUS dp_vdev_set_monitor_mode_rings(struct dp_pdev *pdev, + uint8_t delayed_replenish); static void dp_vdev_set_monitor_mode_buf_rings(struct dp_pdev *pdev); #define DP_INTR_POLL_TIMER_MS 5 @@ -6057,32 +6057,6 @@ dp_soc_attach_target_wifi3(struct cdp_soc_t *cdp_soc) return QDF_STATUS_SUCCESS; } -#ifdef QCA_SUPPORT_FULL_MON -static inline QDF_STATUS -dp_soc_config_full_mon_mode(struct dp_pdev *pdev, enum dp_full_mon_config val) -{ - struct dp_soc *soc = pdev->soc; - QDF_STATUS status = QDF_STATUS_SUCCESS; - - if (!soc->full_mon_mode) - return QDF_STATUS_SUCCESS; - - if ((htt_h2t_full_mon_cfg(soc->htt_handle, - pdev->pdev_id, - val)) != QDF_STATUS_SUCCESS) { - status = QDF_STATUS_E_FAILURE; - } - - return status; -} -#else -static inline QDF_STATUS -dp_soc_config_full_mon_mode(struct dp_pdev *pdev, enum dp_full_mon_config val) -{ - return 0; -} -#endif - /* * dp_vdev_id_map_tbl_add() - Add vdev into vdev_id table * @soc: SoC handle @@ -8106,67 +8080,7 @@ QDF_STATUS dp_monitor_mode_ring_config(struct dp_soc *soc, uint8_t mac_for_pdev, return status; } -static inline void -dp_pdev_disable_mcopy_code(struct dp_pdev *pdev) -{ - pdev->mcopy_mode = M_COPY_DISABLED; - pdev->monitor_vdev = NULL; -} - -/** - * dp_reset_monitor_mode() - Disable monitor mode - * @soc_hdl: Datapath soc handle - * @pdev_id: id of datapath PDEV handle - * - * Return: QDF_STATUS - */ -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 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); - - dp_soc_config_full_mon_mode(pdev, DP_FULL_MON_DISABLE); - pdev->monitor_vdev = NULL; - - /* - * 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) { - dp_rx_mon_dest_err("%pK: Failed to reset monitor filters", - soc); - } - pdev->monitor_configured = false; - - qdf_spin_unlock_bh(&pdev->mon_lock); - return QDF_STATUS_SUCCESS; -} - -/** +/* * dp_get_tx_pending() - read pending tx * @pdev_handle: Datapath PDEV handle * @@ -8218,8 +8132,8 @@ static QDF_STATUS dp_get_peer_mac_from_peer_id(struct cdp_soc_t *soc, * * Return: QDF_STATUS */ -static QDF_STATUS dp_vdev_set_monitor_mode_rings(struct dp_pdev *pdev, - uint8_t delayed_replenish) +QDF_STATUS dp_vdev_set_monitor_mode_rings(struct dp_pdev *pdev, + uint8_t delayed_replenish) { struct wlan_cfg_dp_pdev_ctxt *pdev_cfg_ctx; uint32_t mac_id; @@ -8345,151 +8259,6 @@ static void dp_vdev_set_monitor_mode_buf_rings(struct dp_pdev *pdev) } } -/** - * dp_vdev_set_monitor_mode() - Set DP VDEV to monitor mode - * @vdev_handle: Datapath VDEV handle - * @smart_monitor: Flag to denote if its smart monitor mode - * - * Return: 0 on success, not 0 on failure - */ -static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *dp_soc, - uint8_t vdev_id, - uint8_t special_monitor) -{ - struct dp_soc *soc = (struct dp_soc *)dp_soc; - struct dp_pdev *pdev; - struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, - DP_MOD_ID_CDP); - QDF_STATUS status = QDF_STATUS_SUCCESS; - - if (!vdev) - return QDF_STATUS_E_FAILURE; - - pdev = vdev->pdev; - pdev->monitor_vdev = vdev; - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, - "pdev=%pK, pdev_id=%d, soc=%pK vdev=%pK\n", - pdev, pdev->pdev_id, pdev->soc, vdev); - - /* - * do not configure monitor buf ring and filter for smart and - * lite monitor - * for smart monitor filters are added along with first NAC - * for lite monitor required configuration done through - * dp_set_pdev_param - */ - - if (special_monitor) { - status = QDF_STATUS_SUCCESS; - goto fail; - } - - /*Check if current pdev's monitor_vdev exists */ - if (pdev->monitor_configured) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, - "monitor vap already created vdev=%pK\n", vdev); - status = QDF_STATUS_E_RESOURCES; - goto fail; - } - - pdev->monitor_configured = true; - - dp_soc_config_full_mon_mode(pdev, DP_FULL_MON_ENABLE); - dp_mon_filter_setup_mon_mode(pdev); - status = dp_mon_filter_update(pdev); - if (status != QDF_STATUS_SUCCESS) { - dp_cdp_err("%pK: Failed to reset monitor filters", soc); - dp_mon_filter_reset_mon_mode(pdev); - pdev->monitor_configured = false; - pdev->monitor_vdev = NULL; - } - -fail: - dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); - return status; -} - -/** - * dp_pdev_set_advance_monitor_filter() - Set DP PDEV monitor filter - * @soc: soc handle - * @pdev_id: id of Datapath PDEV handle - * @filter_val: Flag to select Filter for monitor mode - * Return: 0 on success, not 0 on failure - */ -static QDF_STATUS -dp_pdev_set_advance_monitor_filter(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, - struct cdp_monitor_filter *filter_val) -{ - /* Many monitor VAPs can exists in a system but only one can be up at - * anytime - */ - struct dp_soc *soc = (struct dp_soc *)soc_hdl; - struct dp_vdev *vdev; - 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; - - vdev = pdev->monitor_vdev; - - if (!vdev) - return QDF_STATUS_E_FAILURE; - - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, - "pdev=%pK, pdev_id=%d, soc=%pK vdev=%pK", - pdev, pdev_id, soc, vdev); - - /*Check if current pdev's monitor_vdev exists */ - if (!pdev->monitor_vdev) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "vdev=%pK", vdev); - qdf_assert(vdev); - } - - /* update filter mode, type in pdev structure */ - pdev->mon_filter_mode = filter_val->mode; - pdev->fp_mgmt_filter = filter_val->fp_mgmt; - pdev->fp_ctrl_filter = filter_val->fp_ctrl; - pdev->fp_data_filter = filter_val->fp_data; - pdev->mo_mgmt_filter = filter_val->mo_mgmt; - pdev->mo_ctrl_filter = filter_val->mo_ctrl; - pdev->mo_data_filter = filter_val->mo_data; - - dp_mon_filter_setup_mon_mode(pdev); - status = dp_mon_filter_update(pdev); - if (status != QDF_STATUS_SUCCESS) { - dp_rx_mon_dest_err("%pK: Failed to set filter for advance mon mode", - soc); - dp_mon_filter_reset_mon_mode(pdev); - } - - return status; -} - -/** - * dp_deliver_tx_mgmt() - Deliver mgmt frame for tx capture - * @cdp_soc : data path soc handle - * @pdev_id : pdev_id - * @nbuf: Management frame buffer - */ -static QDF_STATUS -dp_deliver_tx_mgmt(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, qdf_nbuf_t nbuf) -{ - struct dp_pdev *pdev = - dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)cdp_soc, - pdev_id); - - if (!pdev) - return QDF_STATUS_E_FAILURE; - - dp_deliver_mgmt_frm(pdev, nbuf); - - return QDF_STATUS_SUCCESS; -} - /** * dp_set_bsscolor() - sets bsscolor for tx capture * @pdev: Datapath PDEV handle @@ -9346,115 +9115,6 @@ dp_pdev_tid_stats_osif_drop(struct dp_pdev *pdev, uint32_t val) pdev->stats.tid_stats.osif_drop += val; } -/* - * dp_config_debug_sniffer()- API to enable/disable debug sniffer - * @pdev: DP_PDEV handle - * @val: user provided value - * - * Return: 0 for success. nonzero for failure. - */ -static QDF_STATUS -dp_config_debug_sniffer(struct dp_pdev *pdev, int val) -{ - QDF_STATUS status = QDF_STATUS_SUCCESS; - - /* - * 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_soc_config_full_mon_mode(pdev, DP_FULL_MON_DISABLE); - 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")); - } - pdev->monitor_configured = false; -#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); - } 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); - } else if (!pdev->enhanced_stats_en && pdev->bpr_enable) { - dp_h2t_cfg_stats_msg_send(pdev, - DP_PPDU_STATS_CFG_BPR_ENH, - pdev->pdev_id); - } else { - dp_h2t_cfg_stats_msg_send(pdev, - DP_PPDU_STATS_CFG_BPR, - pdev->pdev_id); - } - break; - - case 1: - pdev->tx_sniffer_enable = 1; - pdev->monitor_configured = false; - - if (!pdev->pktlog_ppdu_stats) - dp_h2t_cfg_stats_msg_send(pdev, - DP_PPDU_STATS_CFG_SNIFFER, pdev->pdev_id); - break; - case 2: - case 4: - if (pdev->monitor_vdev) { - status = QDF_STATUS_E_RESOURCES; - break; - } - -#ifdef FEATURE_PERPKT_INFO - pdev->mcopy_mode = val; - pdev->tx_sniffer_enable = 0; - pdev->monitor_configured = true; - - if (!wlan_cfg_is_delay_mon_replenish(pdev->soc->wlan_cfg_ctx)) - dp_vdev_set_monitor_mode_rings(pdev, true); - - /* - * Setup the M copy mode filter. - */ - dp_soc_config_full_mon_mode(pdev, DP_FULL_MON_ENABLE); - 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: - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Invalid value"); - break; - } - return status; -} - #ifdef FEATURE_PERPKT_INFO /* * dp_enable_enhanced_stats()- API to enable enhanced statistcs @@ -9827,10 +9487,10 @@ static QDF_STATUS dp_set_pdev_param(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, switch (param) { case CDP_CONFIG_TX_CAPTURE: - return dp_config_debug_sniffer(pdev, + return monitor_config_debug_sniffer(pdev, val.cdp_pdev_param_tx_capture); case CDP_CONFIG_DEBUG_SNIFFER: - return dp_config_debug_sniffer(pdev, + return monitor_config_debug_sniffer(pdev, val.cdp_pdev_param_dbg_snf); case CDP_CONFIG_BPR_ENABLE: return dp_set_bpr_enable(pdev, val.cdp_pdev_param_bpr_enable); @@ -12070,27 +11730,6 @@ static QDF_STATUS dp_set_vdev_pcp_tid_map_wifi3(struct cdp_soc_t *soc_hdl, return QDF_STATUS_SUCCESS; } -#ifdef QCA_SUPPORT_FULL_MON -static inline QDF_STATUS -dp_config_full_mon_mode(struct cdp_soc_t *soc_handle, - uint8_t val) -{ - struct dp_soc *soc = (struct dp_soc *)soc_handle; - - soc->full_mon_mode = val; - qdf_alert("Configure full monitor mode val: %d ", val); - - return QDF_STATUS_SUCCESS; -} -#else -static inline QDF_STATUS -dp_config_full_mon_mode(struct cdp_soc_t *soc_handle, - uint8_t val) -{ - return 0; -} -#endif - #if defined(FEATURE_RUNTIME_PM) || defined(DP_POWER_SAVE) static void dp_drain_txrx(struct cdp_soc_t *soc_handle) { @@ -12175,7 +11814,6 @@ static struct cdp_cmn_ops dp_ops_cmn = { .set_pdev_dscp_tid_map = dp_set_pdev_dscp_tid_map_wifi3, .txrx_get_total_per = dp_get_total_per, .txrx_stats_request = dp_txrx_stats_request, - .txrx_set_monitor_mode = dp_vdev_set_monitor_mode, .txrx_get_peer_mac_from_peer_id = dp_get_peer_mac_from_peer_id, .display_stats = dp_txrx_dump_stats, .txrx_intr_attach = dp_soc_interrupt_attach_wrapper, @@ -12312,14 +11950,6 @@ static struct cdp_me_ops dp_ops_me = { #endif }; -static struct cdp_mon_ops dp_ops_mon = { - .txrx_reset_monitor_mode = dp_reset_monitor_mode, - /* Added support for HK advance filter */ - .txrx_set_advance_monitor_filter = dp_pdev_set_advance_monitor_filter, - .txrx_deliver_tx_mgmt = dp_deliver_tx_mgmt, - .config_full_mon_mode = dp_config_full_mon_mode, -}; - 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, @@ -13050,7 +12680,6 @@ static struct cdp_ops dp_txrx_ops = { .cmn_drv_ops = &dp_ops_cmn, .ctrl_ops = &dp_ops_ctrl, .me_ops = &dp_ops_me, - .mon_ops = &dp_ops_mon, .host_stats_ops = &dp_ops_host_stats, .wds_ops = &dp_ops_wds, .raw_ops = &dp_ops_raw, @@ -13324,6 +12953,7 @@ void *dp_soc_init(struct dp_soc *soc, HTC_HANDLE htc_handle, dp_soc_cfg_init(soc); + monitor_soc_cfg_init(soc); /* Reset/Initialize wbm sg list and flags */ dp_rx_wbm_sg_list_reset(soc); @@ -14851,8 +14481,6 @@ static void dp_soc_cfg_init(struct dp_soc *soc) soc->wlan_cfg_ctx->rxdma1_enable = 0; break; case TARGET_TYPE_QCA8074: - wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, - MON_BUF_MIN_ENTRIES); wlan_cfg_set_reo_dst_ring_size(soc->wlan_cfg_ctx, REO_DST_RING_SIZE_QCA8074); wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, true); @@ -14862,12 +14490,9 @@ static void dp_soc_cfg_init(struct dp_soc *soc) case TARGET_TYPE_QCA8074V2: case TARGET_TYPE_QCA6018: case TARGET_TYPE_QCA9574: - wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, - MON_BUF_MIN_ENTRIES); wlan_cfg_set_reo_dst_ring_size(soc->wlan_cfg_ctx, REO_DST_RING_SIZE_QCA8074); wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, false); - soc->hw_nac_monitor_support = 1; soc->ast_override_support = 1; soc->per_tid_basize_max_tid = 8; soc->num_hw_dscp_tid_map = HAL_MAX_HW_DSCP_TID_V2_MAPS; @@ -14875,31 +14500,23 @@ static void dp_soc_cfg_init(struct dp_soc *soc) soc->is_rx_fse_full_cache_invalidate_war_enabled = true; break; case TARGET_TYPE_QCN9000: - wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, - MON_BUF_MIN_ENTRIES); wlan_cfg_set_reo_dst_ring_size(soc->wlan_cfg_ctx, REO_DST_RING_SIZE_QCN9000); soc->ast_override_support = 1; soc->da_war_enabled = false; wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, false); - soc->hw_nac_monitor_support = 1; soc->per_tid_basize_max_tid = 8; soc->num_hw_dscp_tid_map = HAL_MAX_HW_DSCP_TID_V2_MAPS; soc->lmac_polled_mode = 0; soc->wbm_release_desc_rx_sg_support = 1; - if (cfg_get(soc->ctrl_psoc, CFG_DP_FULL_MON_MODE)) - dp_config_full_mon_mode((struct cdp_soc_t *)soc, 1); break; case TARGET_TYPE_QCA5018: case TARGET_TYPE_QCN6122: - wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, - MON_BUF_MIN_ENTRIES); wlan_cfg_set_reo_dst_ring_size(soc->wlan_cfg_ctx, REO_DST_RING_SIZE_QCA8074); soc->ast_override_support = 1; soc->da_war_enabled = false; wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, false); - soc->hw_nac_monitor_support = 1; soc->per_tid_basize_max_tid = 8; soc->num_hw_dscp_tid_map = HAL_MAX_HW_DSCP_TID_MAPS_11AX; soc->disable_mac1_intr = 1; @@ -14907,14 +14524,11 @@ static void dp_soc_cfg_init(struct dp_soc *soc) soc->wbm_release_desc_rx_sg_support = 1; break; case TARGET_TYPE_QCN9224: - wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, - MON_BUF_MIN_ENTRIES); wlan_cfg_set_reo_dst_ring_size(soc->wlan_cfg_ctx, REO_DST_RING_SIZE_QCA8074); soc->ast_override_support = 1; soc->da_war_enabled = false; wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, false); - soc->hw_nac_monitor_support = 1; soc->per_tid_basize_max_tid = 8; soc->wbm_release_desc_rx_sg_support = 1; diff --git a/dp/wifi3.0/monitor/dp_mon.c b/dp/wifi3.0/monitor/dp_mon.c index eb2b20f983..830bbbe8d7 100644 --- a/dp/wifi3.0/monitor/dp_mon.c +++ b/dp/wifi3.0/monitor/dp_mon.c @@ -20,6 +20,7 @@ #include #include #include +#include "htt_ppdu_stats.h" #define RNG_ERR "SRNG setup failed for" #define mon_init_err(params...) QDF_TRACE_ERROR(QDF_MODULE_ID_DP_INIT, params) @@ -37,6 +38,8 @@ QDF_STATUS dp_htt_ppdu_stats_attach(struct dp_pdev *pdev); void dp_htt_ppdu_stats_detach(struct dp_pdev *pdev); void dp_neighbour_peers_detach(struct dp_pdev *pdev); void dp_pktlogmod_exit(struct dp_pdev *handle); +QDF_STATUS dp_vdev_set_monitor_mode_rings(struct dp_pdev *pdev, + uint8_t delayed_replenish); #if !defined(DISABLE_MON_CONFIG) /** @@ -240,17 +243,430 @@ QDF_STATUS dp_mon_rings_alloc(struct dp_soc *soc, struct dp_pdev *pdev) return QDF_STATUS_SUCCESS; } #endif +#ifdef QCA_SUPPORT_FULL_MON +static inline QDF_STATUS +dp_config_full_mon_mode(struct cdp_soc_t *soc_handle, + uint8_t val) +{ + struct dp_soc *soc = (struct dp_soc *)soc_handle; + + soc->full_mon_mode = val; + dp_cdp_err("Configure full monitor mode val: %d ", val); + + return QDF_STATUS_SUCCESS; +} +#else +static inline QDF_STATUS +dp_config_full_mon_mode(struct cdp_soc_t *soc_handle, + uint8_t val) +{ + return 0; +} +#endif + +static inline void +dp_pdev_disable_mcopy_code(struct dp_pdev *pdev) +{ + pdev->mcopy_mode = M_COPY_DISABLED; + pdev->monitor_configured = false; + pdev->monitor_vdev = NULL; +} + +#ifdef QCA_SUPPORT_FULL_MON +static inline QDF_STATUS +dp_soc_config_full_mon_mode(struct dp_pdev *pdev, enum dp_full_mon_config val) +{ + struct dp_soc *soc = pdev->soc; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!soc->full_mon_mode) + return QDF_STATUS_SUCCESS; + + if ((htt_h2t_full_mon_cfg(soc->htt_handle, + pdev->pdev_id, + val)) != QDF_STATUS_SUCCESS) { + status = QDF_STATUS_E_FAILURE; + } + + return status; +} +#else +static inline QDF_STATUS +dp_soc_config_full_mon_mode(struct dp_pdev *pdev, enum dp_full_mon_config val) +{ + return 0; +} +#endif + +/** + * dp_reset_monitor_mode() - Disable monitor mode + * @soc_hdl: Datapath soc handle + * @pdev_id: id of datapath PDEV handle + * + * Return: QDF_STATUS + */ +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 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); + + dp_soc_config_full_mon_mode(pdev, DP_FULL_MON_DISABLE); + pdev->monitor_vdev = NULL; + pdev->monitor_configured = false; + + /* + * 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) { + dp_rx_mon_dest_err("%pK: Failed to reset monitor filters", + soc); + } + + qdf_spin_unlock_bh(&pdev->mon_lock); + return QDF_STATUS_SUCCESS; +} + +/** + * dp_pdev_set_advance_monitor_filter() - Set DP PDEV monitor filter + * @soc: soc handle + * @pdev_id: id of Datapath PDEV handle + * @filter_val: Flag to select Filter for monitor mode + * Return: 0 on success, not 0 on failure + */ +static QDF_STATUS +dp_pdev_set_advance_monitor_filter(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct cdp_monitor_filter *filter_val) +{ + /* Many monitor VAPs can exists in a system but only one can be up at + * anytime + */ + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_vdev *vdev; + 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; + + vdev = pdev->monitor_vdev; + + if (!vdev) + return QDF_STATUS_E_FAILURE; + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, + "pdev=%pK, pdev_id=%d, soc=%pK vdev=%pK", + pdev, pdev_id, soc, vdev); + + /*Check if current pdev's monitor_vdev exists */ + if (!pdev->monitor_vdev) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "vdev=%pK", vdev); + qdf_assert(vdev); + } + + /* update filter mode, type in pdev structure */ + pdev->mon_filter_mode = filter_val->mode; + pdev->fp_mgmt_filter = filter_val->fp_mgmt; + pdev->fp_ctrl_filter = filter_val->fp_ctrl; + pdev->fp_data_filter = filter_val->fp_data; + pdev->mo_mgmt_filter = filter_val->mo_mgmt; + pdev->mo_ctrl_filter = filter_val->mo_ctrl; + pdev->mo_data_filter = filter_val->mo_data; + + dp_mon_filter_setup_mon_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + dp_rx_mon_dest_err("%pK: Failed to set filter for adv mon mode", + soc); + dp_mon_filter_reset_mon_mode(pdev); + } + + return status; +} + +/** + * dp_deliver_tx_mgmt() - Deliver mgmt frame for tx capture + * @cdp_soc : data path soc handle + * @pdev_id : pdev_id + * @nbuf: Management frame buffer + */ +static QDF_STATUS +dp_deliver_tx_mgmt(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, qdf_nbuf_t nbuf) +{ + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)cdp_soc, + pdev_id); + + if (!pdev) + return QDF_STATUS_E_FAILURE; + + dp_deliver_mgmt_frm(pdev, nbuf); + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_vdev_set_monitor_mode() - Set DP VDEV to monitor mode + * @vdev_handle: Datapath VDEV handle + * @smart_monitor: Flag to denote if its smart monitor mode + * + * Return: 0 on success, not 0 on failure + */ +static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *dp_soc, + uint8_t vdev_id, + uint8_t special_monitor) +{ + struct dp_soc *soc = (struct dp_soc *)dp_soc; + struct dp_pdev *pdev; + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, + DP_MOD_ID_CDP); + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!vdev) + return QDF_STATUS_E_FAILURE; + + pdev = vdev->pdev; + pdev->monitor_vdev = vdev; + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, + "pdev=%pK, pdev_id=%d, soc=%pK vdev=%pK\n", + pdev, pdev->pdev_id, pdev->soc, vdev); + + /* + * do not configure monitor buf ring and filter for smart and + * lite monitor + * for smart monitor filters are added along with first NAC + * for lite monitor required configuration done through + * dp_set_pdev_param + */ + + if (special_monitor) { + status = QDF_STATUS_SUCCESS; + goto fail; + } + + /*Check if current pdev's monitor_vdev exists */ + if (pdev->monitor_configured) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "monitor vap already created vdev=%pK\n", vdev); + status = QDF_STATUS_E_RESOURCES; + goto fail; + } + + pdev->monitor_configured = true; + + dp_soc_config_full_mon_mode(pdev, DP_FULL_MON_ENABLE); + dp_mon_filter_setup_mon_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + dp_cdp_err("%pK: Failed to reset monitor filters", soc); + dp_mon_filter_reset_mon_mode(pdev); + pdev->monitor_configured = false; + pdev->monitor_vdev = NULL; + } + +fail: + dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); + return status; +} + +/* + * dp_config_debug_sniffer()- API to enable/disable debug sniffer + * @pdev: DP_PDEV handle + * @val: user provided value + * + * Return: 0 for success. nonzero for failure. + */ +static QDF_STATUS +dp_config_debug_sniffer(struct dp_pdev *pdev, int val) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + /* + * 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_soc_config_full_mon_mode(pdev, DP_FULL_MON_DISABLE); + 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); + } 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); + } else if (!pdev->enhanced_stats_en && pdev->bpr_enable) { + dp_h2t_cfg_stats_msg_send(pdev, + DP_PPDU_STATS_CFG_BPR_ENH, + pdev->pdev_id); + } else { + dp_h2t_cfg_stats_msg_send(pdev, + DP_PPDU_STATS_CFG_BPR, + pdev->pdev_id); + } + break; + + case 1: + pdev->tx_sniffer_enable = 1; + pdev->monitor_configured = false; + + if (!pdev->pktlog_ppdu_stats) + dp_h2t_cfg_stats_msg_send(pdev, + DP_PPDU_STATS_CFG_SNIFFER, + pdev->pdev_id); + break; + case 2: + case 4: + if (pdev->monitor_vdev) { + status = QDF_STATUS_E_RESOURCES; + break; + } + +#ifdef FEATURE_PERPKT_INFO + pdev->mcopy_mode = val; + pdev->tx_sniffer_enable = 0; + pdev->monitor_configured = true; + + if (!wlan_cfg_is_delay_mon_replenish(pdev->soc->wlan_cfg_ctx)) + dp_vdev_set_monitor_mode_rings(pdev, true); + + /* + * Setup the M copy mode filter. + */ + dp_soc_config_full_mon_mode(pdev, DP_FULL_MON_ENABLE); + 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: + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Invalid value"); + break; + } + return status; +} QDF_STATUS dp_mon_soc_cfg_init(struct dp_soc *soc) { + int target_type; + + target_type = hal_get_target_type(soc->hal_soc); + switch (target_type) { + case TARGET_TYPE_QCA6290: + case TARGET_TYPE_QCA6390: + case TARGET_TYPE_QCA6490: + case TARGET_TYPE_QCA6750: + break; + case TARGET_TYPE_QCA8074: + wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, + MON_BUF_MIN_ENTRIES); + break; + case TARGET_TYPE_QCA8074V2: + case TARGET_TYPE_QCA6018: + case TARGET_TYPE_QCA9574: + wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, + MON_BUF_MIN_ENTRIES); + soc->hw_nac_monitor_support = 1; + break; + case TARGET_TYPE_QCN9000: + wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, + MON_BUF_MIN_ENTRIES); + soc->hw_nac_monitor_support = 1; + if (cfg_get(soc->ctrl_psoc, CFG_DP_FULL_MON_MODE)) + dp_config_full_mon_mode((struct cdp_soc_t *)soc, 1); + break; + case TARGET_TYPE_QCA5018: + case TARGET_TYPE_QCN6122: + wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, + MON_BUF_MIN_ENTRIES); + soc->hw_nac_monitor_support = 1; + break; + case TARGET_TYPE_QCN9224: + wlan_cfg_set_mon_delayed_replenish_entries(soc->wlan_cfg_ctx, + MON_BUF_MIN_ENTRIES); + soc->hw_nac_monitor_support = 1; + break; + default: + qdf_print("%s: Unknown tgt type %d\n", __func__, target_type); + qdf_assert_always(0); + break; + } return QDF_STATUS_SUCCESS; } QDF_STATUS dp_mon_pdev_attach(struct dp_pdev *pdev) { - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc; struct dp_mon_pdev *mon_pdev; + if (!pdev) { + mon_init_err("pdev is NULL"); + goto fail0; + } + + soc = pdev->soc; + mon_pdev = (struct dp_mon_pdev *)qdf_mem_malloc(sizeof(*mon_pdev)); if (!mon_pdev) { mon_init_err("%pK: MONITOR pdev allocation failed", pdev); @@ -258,13 +674,13 @@ QDF_STATUS dp_mon_pdev_attach(struct dp_pdev *pdev) } if (dp_mon_rings_alloc(soc, pdev)) { - mon_init_err("%pK: MONITOR rings setup failed", soc); + mon_init_err("%pK: MONITOR rings setup failed", pdev); goto fail1; } /* Rx monitor mode specific init */ if (dp_rx_pdev_mon_desc_pool_alloc(pdev)) { - mon_init_err("%pK: dp_rx_pdev_mon_attach failed", soc); + mon_init_err("%pK: dp_rx_pdev_mon_attach failed", pdev); goto fail2; } @@ -282,8 +698,14 @@ fail0: QDF_STATUS dp_mon_pdev_detach(struct dp_pdev *pdev) { - struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; + struct dp_mon_pdev *mon_pdev; + if (!pdev) { + mon_init_err("pdev is NULL"); + return QDF_STATUS_E_FAILURE; + } + + mon_pdev = pdev->monitor_pdev; dp_rx_pdev_mon_desc_pool_free(pdev); dp_mon_rings_free(pdev); pdev->monitor_pdev = NULL; @@ -293,12 +715,19 @@ QDF_STATUS dp_mon_pdev_detach(struct dp_pdev *pdev) QDF_STATUS dp_mon_pdev_init(struct dp_pdev *pdev) { - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc; + + if (!pdev) { + mon_init_err("pdev is NULL"); + return QDF_STATUS_E_FAILURE; + } + + soc = pdev->soc; pdev->filter = dp_mon_filter_alloc(pdev); if (!pdev->filter) { mon_init_err("%pK: Memory allocation failed for monitor filter", - soc); + pdev); return QDF_STATUS_E_NOMEM; } @@ -325,7 +754,7 @@ QDF_STATUS dp_mon_pdev_init(struct dp_pdev *pdev) goto fail0; if (dp_mon_rings_init(soc, pdev)) { - mon_init_err("%pK: MONITOR rings setup failed", soc); + mon_init_err("%pK: MONITOR rings setup failed", pdev); goto fail1; } /* initialize sw monitor rx descriptors */ @@ -367,6 +796,15 @@ static struct dp_mon_ops monitor_ops = { .mon_pdev_detach = dp_mon_pdev_detach, .mon_pdev_init = dp_mon_pdev_init, .mon_pdev_deinit = dp_mon_pdev_deinit, + .mon_config_debug_sniffer = dp_config_debug_sniffer, +}; + +static struct cdp_mon_ops dp_ops_mon = { + .txrx_reset_monitor_mode = dp_reset_monitor_mode, + /* Added support for HK advance filter */ + .txrx_set_advance_monitor_filter = dp_pdev_set_advance_monitor_filter, + .txrx_deliver_tx_mgmt = dp_deliver_tx_mgmt, + .config_full_mon_mode = dp_config_full_mon_mode, }; static inline void dp_mon_ops_register(struct dp_mon_soc *mon_soc) @@ -374,10 +812,28 @@ static inline void dp_mon_ops_register(struct dp_mon_soc *mon_soc) mon_soc->mon_ops = &monitor_ops; } +static inline void dp_mon_cdp_ops_register(struct dp_soc *soc) +{ + struct cdp_ops *ops = soc->cdp_soc.ops; + + if (!ops) { + mon_init_err("cdp_ops is NULL"); + return; + } + + ops->mon_ops = &dp_ops_mon; + ops->cmn_drv_ops->txrx_set_monitor_mode = dp_vdev_set_monitor_mode; +} + QDF_STATUS dp_mon_soc_attach(struct dp_soc *soc) { struct dp_mon_soc *mon_soc; + if (!soc) { + mon_init_err("dp_soc is NULL"); + return QDF_STATUS_E_FAILURE; + } + mon_soc = (struct dp_mon_soc *)qdf_mem_malloc(sizeof(*mon_soc)); if (!mon_soc) { mon_init_err("%pK: mem allocation failed", soc); @@ -387,13 +843,20 @@ QDF_STATUS dp_mon_soc_attach(struct dp_soc *soc) dp_mon_ops_register(mon_soc); soc->monitor_soc = mon_soc; + dp_mon_cdp_ops_register(soc); return QDF_STATUS_SUCCESS; } QDF_STATUS dp_mon_soc_detach(struct dp_soc *soc) { - struct dp_mon_soc *mon_soc = soc->monitor_soc; + struct dp_mon_soc *mon_soc; + if (!soc) { + mon_init_err("dp_soc is NULL"); + return QDF_STATUS_E_FAILURE; + } + + mon_soc = soc->monitor_soc; soc->monitor_soc = NULL; qdf_mem_free(mon_soc); return QDF_STATUS_SUCCESS; diff --git a/dp/wifi3.0/monitor/dp_mon.h b/dp/wifi3.0/monitor/dp_mon.h index 0b7124f958..9a08c6cd7a 100644 --- a/dp/wifi3.0/monitor/dp_mon.h +++ b/dp/wifi3.0/monitor/dp_mon.h @@ -19,6 +19,7 @@ struct dp_mon_ops { QDF_STATUS (*mon_pdev_detach)(struct dp_pdev *pdev); QDF_STATUS (*mon_pdev_init)(struct dp_pdev *pdev); QDF_STATUS (*mon_pdev_deinit)(struct dp_pdev *pdev); + QDF_STATUS (*mon_config_debug_sniffer)(struct dp_pdev *pdev, int val); }; struct dp_mon_soc { @@ -124,3 +125,44 @@ static inline QDF_STATUS monitor_pdev_deinit(struct dp_pdev *pdev) return monitor_ops->mon_pdev_deinit(pdev); } + +static inline QDF_STATUS monitor_soc_cfg_init(struct dp_soc *soc) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + /* + * this API is getting call from dp_soc_init, + * mon_soc will be uninitialized for WIN here + * So returning QDF_STATUS_SUCCESS. + * For WIN, soc cfg init is done while monitor insmod. + */ + if (!mon_soc) + return QDF_STATUS_SUCCESS; + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_soc_cfg_init) { + qdf_err("callback not registered"); + return QDF_STATUS_E_FAILURE; + } + + return monitor_ops->mon_soc_cfg_init(soc); +} + +static inline QDF_STATUS monitor_config_debug_sniffer(struct dp_pdev *pdev, + int val) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = pdev->soc->monitor_soc; + + if (!mon_soc) + return QDF_STATUS_E_FAILURE; + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_config_debug_sniffer) { + qdf_err("callback not registered"); + return QDF_STATUS_E_FAILURE; + } + + return monitor_ops->mon_config_debug_sniffer(pdev, val); +}