From c4796962ca713477a145b019088d4d14ed0ce138 Mon Sep 17 00:00:00 2001 From: aloksing Date: Tue, 25 May 2021 22:49:19 +0530 Subject: [PATCH] qcacmn: Monitor vdev and peer attach/detach PATCH[5/7]: This patch consists following changes: -Monitor vdev context allocation while vdev attach and free while vdev delete -Monitor peer context allocation while peer create and free while peer delete -Move monitor vdev timer function to monitor file -Move monitor reap timer handler function to monitor file -Move monitor timer related variables to monitor file -Add timer init/deinit and start/stop in monitor file. Change-Id: I9c7910671d3678c53ca9ec44a57bc10e892008d9 CRs-Fixed: 2983994 --- dp/wifi3.0/dp_htt.h | 14 - dp/wifi3.0/dp_internal.h | 89 +++++- dp/wifi3.0/dp_main.c | 182 +++---------- dp/wifi3.0/dp_peer.c | 26 -- dp/wifi3.0/dp_types.h | 24 +- dp/wifi3.0/monitor/dp_mon.c | 378 +++++++++++++++++++++----- dp/wifi3.0/monitor/dp_mon.h | 348 ++++++++++++++++++++++++ dp/wifi3.0/monitor/dp_rx_mon_dest.c | 18 +- dp/wifi3.0/monitor/dp_rx_mon_status.c | 6 +- 9 files changed, 798 insertions(+), 287 deletions(-) diff --git a/dp/wifi3.0/dp_htt.h b/dp/wifi3.0/dp_htt.h index 22bb18d789..b466f4f21c 100644 --- a/dp/wifi3.0/dp_htt.h +++ b/dp/wifi3.0/dp_htt.h @@ -454,20 +454,6 @@ struct htt_stats_context { uint32_t msg_len; }; -int -dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap(uint32_t bitmap); - -/** - * dp_ppdu_desc_user_stats_update(): Function to update TX user stats - * @pdev: DP pdev handle - * @ppdu_info: per PPDU TLV descriptor - * - * return: void - */ -void -dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, - struct ppdu_info *ppdu_info); - /** * dp_htt_rx_flow_fst_setup(): Send HTT Rx FST setup message to FW * @pdev: DP pdev handle diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 7f1a9bd981..212ce1ce04 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -192,6 +192,28 @@ static inline QDF_STATUS monitor_pdev_detach(struct dp_pdev *pdev) return QDF_STATUS_SUCCESS; } +static inline QDF_STATUS monitor_vdev_attach(struct dp_vdev *vdev) +{ + return QDF_STATUS_E_FAILURE; +} + +static inline QDF_STATUS monitor_vdev_detach(struct dp_vdev *vdev) +{ + return QDF_STATUS_E_FAILURE; +} + +static inline QDF_STATUS monitor_peer_attach(struct dp_soc *soc, + struct dp_peer *peer) +{ + return QDF_STATUS_E_FAILURE; +} + +static inline QDF_STATUS monitor_peer_detach(struct dp_soc *soc, + struct dp_peer *peer) +{ + return QDF_STATUS_E_FAILURE; +} + static inline QDF_STATUS monitor_pdev_init(struct dp_pdev *pdev) { return QDF_STATUS_SUCCESS; @@ -387,6 +409,48 @@ static inline QDF_STATUS monitor_filter_neighbour_peer(struct dp_pdev *pdev, static inline void monitor_print_pdev_tx_capture_stats(struct dp_pdev *pdev) { } + +static inline +void monitor_reap_timer_init(struct dp_soc *soc) +{ +} + +static inline +void monitor_reap_timer_deinit(struct dp_soc *soc) +{ +} + +static inline +void monitor_reap_timer_start(struct dp_soc *soc) +{ +} + +static inline +bool monitor_reap_timer_stop(struct dp_soc *soc) +{ + return false; +} + +static inline +void monitor_vdev_timer_init(struct dp_soc *soc) +{ +} + +static inline +void monitor_vdev_timer_deinit(struct dp_soc *soc) +{ +} + +static inline +void monitor_vdev_timer_start(struct dp_soc *soc) +{ +} + +static inline +bool monitor_vdev_timer_stop(struct dp_soc *soc) +{ + return false; +} #endif #ifndef WIFI_MONITOR_SUPPORT @@ -400,6 +464,24 @@ static inline bool dp_is_enable_reap_timer_non_pkt(struct dp_pdev *pdev) { return false; } + +static inline void monitor_vdev_register_osif(struct dp_vdev *vdev, + struct ol_txrx_ops *txrx_ops) +{ +} + +static inline bool monitor_is_vdev_timer_running(struct dp_soc *soc) +{ + return false; +} + +static inline void monitor_vdev_delete(struct dp_soc *soc, struct dp_vdev *vdev) +{ +} + +static inline void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer) +{ +} #endif #define DP_MAX_TIMER_EXEC_TIME_TICKS \ @@ -1300,13 +1382,6 @@ void dp_peer_find_id_to_obj_remove(struct dp_soc *soc, uint16_t peer_id); void dp_vdev_unref_delete(struct dp_soc *soc, struct dp_vdev *vdev, enum dp_mod_id mod_id); -/* - * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer - * @peer: Datapath peer - * - * return: void - */ -void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer); /* * dp_peer_ppdu_delayed_ba_cleanup() free ppdu allocated in peer diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 39162b31bb..559517a83e 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -275,9 +275,6 @@ static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc, /* Threshold for peer's cached buf queue beyond which frames are dropped */ #define DP_RX_CACHED_BUFQ_THRESH 64 -/* Budget to reap monitor status ring */ -#define DP_MON_REAP_BUDGET 1024 - /** * default_dscp_tid_map - Default DSCP-TID mapping * @@ -418,23 +415,6 @@ uint32_t dp_soc_get_mon_mask_for_interrupt_mode(struct dp_soc *soc, int intr_ctx return 0; } -/* - * dp_mon_reap_timer_handler()- timer to reap monitor rings - * reqd as we are not getting ppdu end interrupts - * @arg: SoC Handle - * - * Return: - * - */ -static void dp_mon_reap_timer_handler(void *arg) -{ - struct dp_soc *soc = (struct dp_soc *)arg; - - monitor_service_mon_rings(soc, QCA_NAPI_BUDGET); - - qdf_timer_mod(&soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); -} - /** * dp_get_num_rx_contexts() - get number of RX contexts * @soc_hdl: cdp opaque soc handle @@ -2212,7 +2192,7 @@ static inline void dp_srng_record_timer_exit(struct dp_soc *dp_soc, * * Return: enum with yield code */ -static enum timer_yield_status +enum timer_yield_status dp_should_timer_irq_yield(struct dp_soc *soc, uint32_t work_done, uint64_t start_time) { @@ -2227,6 +2207,8 @@ dp_should_timer_irq_yield(struct dp_soc *soc, uint32_t work_done, return DP_TIMER_NO_YIELD; } +qdf_export_symbol(dp_should_timer_irq_yield); + /** * dp_process_lmac_rings() - Process LMAC rings * @int_ctx: interrupt context @@ -2447,7 +2429,7 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) int_ctx->intr_stats.num_reo_status_ring_masks++; } - if (qdf_unlikely(!(soc->mon_vdev_timer_state & MON_VDEV_TIMER_RUNNING))) { + if (qdf_unlikely(!monitor_is_vdev_timer_running(soc))) { work_done = dp_process_lmac_rings(int_ctx, remaining_quota); if (work_done) { budget -= work_done; @@ -2488,7 +2470,7 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) int_ctx->intr_stats.num_reo_status_ring_masks++; } - if (qdf_unlikely(!(soc->mon_vdev_timer_state & MON_VDEV_TIMER_RUNNING))) { + if (qdf_unlikely(!monitor_is_vdev_timer_running(soc))) { work_done = dp_process_lmac_rings(int_ctx, remaining_quota); if (work_done) { budget -= work_done; @@ -2507,70 +2489,6 @@ budget_done: #endif /* QCA_HOST_MODE_WIFI_DISABLED */ -/* dp_mon_vdev_timer()- timer poll for interrupts - * - * @arg: SoC Handle - * - * Return: - * - */ -static void dp_mon_vdev_timer(void *arg) -{ - struct dp_soc *soc = (struct dp_soc *)arg; - struct dp_pdev *pdev = soc->pdev_list[0]; - enum timer_yield_status yield = DP_TIMER_NO_YIELD; - uint32_t work_done = 0, total_work_done = 0; - int budget = 0xffff; - uint32_t remaining_quota = budget; - uint64_t start_time; - uint32_t lmac_id = DP_MON_INVALID_LMAC_ID; - uint32_t lmac_iter; - int max_mac_rings = wlan_cfg_get_num_mac_rings(pdev->wlan_cfg_ctx); - - if (!qdf_atomic_read(&soc->cmn_init_done)) - return; - - if (pdev->mon_chan_band != REG_BAND_UNKNOWN) - lmac_id = pdev->ch_band_lmac_id_mapping[pdev->mon_chan_band]; - - start_time = qdf_get_log_timestamp(); - dp_is_hw_dbs_enable(soc, &max_mac_rings); - - while (yield == DP_TIMER_NO_YIELD) { - for (lmac_iter = 0; lmac_iter < max_mac_rings; lmac_iter++) { - if (lmac_iter == lmac_id) - work_done = monitor_process( - soc, NULL, - lmac_iter, remaining_quota); - else - work_done = - monitor_drop_packets_for_mac(pdev, - lmac_iter, - remaining_quota); - if (work_done) { - budget -= work_done; - if (budget <= 0) { - yield = DP_TIMER_WORK_EXHAUST; - goto budget_done; - } - remaining_quota = budget; - total_work_done += work_done; - } - } - - yield = dp_should_timer_irq_yield(soc, total_work_done, - start_time); - total_work_done = 0; - } - -budget_done: - if (yield == DP_TIMER_WORK_EXHAUST || - yield == DP_TIMER_TIME_EXHAUST) - qdf_timer_mod(&soc->mon_vdev_timer, 1); - else - qdf_timer_mod(&soc->mon_vdev_timer, DP_INTR_POLL_TIMER_MS); -} - /* dp_interrupt_timer()- timer poll for interrupts * * @arg: SoC Handle @@ -4932,10 +4850,7 @@ static void dp_rxdma_ring_cleanup(struct dp_soc *soc, struct dp_pdev *pdev) dp_srng_free(soc, &pdev->rx_mac_buf_ring[i]); } - if (soc->reap_timer_init) { - qdf_timer_free(&soc->mon_reap_timer); - soc->reap_timer_init = 0; - } + monitor_reap_timer_deinit(soc); } #else static void dp_rxdma_ring_cleanup(struct dp_soc *soc, struct dp_pdev *pdev) @@ -5396,15 +5311,12 @@ static void dp_soc_detach(struct cdp_soc_t *txrx_soc) dp_soc_tx_history_detach(soc); dp_soc_rx_history_detach(soc); + monitor_vdev_timer_deinit(soc); + if (!dp_monitor_modularized_enable()) { dp_mon_soc_detach_wrapper(soc); } - if (soc->mon_vdev_timer_state & MON_VDEV_TIMER_INIT) { - qdf_timer_free(&soc->mon_vdev_timer); - soc->mon_vdev_timer_state = 0; - } - qdf_mem_free(soc); } @@ -5523,14 +5435,8 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc) * Timer to reap rxdma status rings. * Needed until we enable ppdu end interrupts */ - qdf_timer_init(soc->osdev, &soc->mon_reap_timer, - dp_mon_reap_timer_handler, (void *)soc, - QDF_TIMER_TYPE_WAKE_APPS); - soc->reap_timer_init = 1; - qdf_timer_init(soc->osdev, &soc->mon_vdev_timer, - dp_mon_vdev_timer, (void *)soc, - QDF_TIMER_TYPE_WAKE_APPS); - soc->mon_vdev_timer_state |= MON_VDEV_TIMER_INIT; + monitor_reap_timer_init(soc); + monitor_vdev_timer_init(soc); return status; } #else @@ -5554,24 +5460,13 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc) htt_srng_setup(soc->htt_handle, mac_for_pdev, soc->rx_refill_buf_ring[lmac_id]. hal_srng, RXDMA_BUF); -#ifndef DISABLE_MON_CONFIG - - if (soc->wlan_cfg_ctx->rxdma1_enable && - wlan_cfg_is_delay_mon_replenish(soc->wlan_cfg_ctx)) { - htt_srng_setup(soc->htt_handle, mac_for_pdev, - soc->rxdma_mon_buf_ring[lmac_id].hal_srng, - RXDMA_MONITOR_BUF); - htt_srng_setup(soc->htt_handle, mac_for_pdev, - soc->rxdma_mon_dst_ring[lmac_id].hal_srng, - RXDMA_MONITOR_DST); - htt_srng_setup(soc->htt_handle, mac_for_pdev, - soc->rxdma_mon_desc_ring[lmac_id].hal_srng, - RXDMA_MONITOR_DESC); + if (wlan_cfg_is_delay_mon_replenish(soc->wlan_cfg_ctx)) { + /* Configure monitor mode rings */ + monitor_htt_srng_setup(soc, pdev, + lmac_id, + mac_for_pdev); } - htt_srng_setup(soc->htt_handle, mac_for_pdev, - soc->rxdma_mon_status_ring[lmac_id].hal_srng, - RXDMA_MONITOR_STATUS); -#endif + htt_srng_setup(soc->htt_handle, mac_for_pdev, soc->rxdma_err_dst_ring[lmac_id].hal_srng, RXDMA_DST); @@ -5904,7 +5799,6 @@ static QDF_STATUS dp_vdev_attach_wifi3(struct cdp_soc_t *cdp_soc, vdev->osif_rx = NULL; vdev->osif_rsim_rx_decap = NULL; vdev->osif_get_key = NULL; - vdev->osif_rx_mon = NULL; vdev->osif_tx_free_ext = NULL; vdev->osif_vdev = NULL; @@ -5942,16 +5836,14 @@ static QDF_STATUS dp_vdev_attach_wifi3(struct cdp_soc_t *cdp_soc, (wlan_op_mode_monitor == vdev->opmode)) qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS); } else if (soc->intr_mode == DP_INTR_MSI && - wlan_op_mode_monitor == vdev->opmode && - soc->mon_vdev_timer_state & MON_VDEV_TIMER_INIT) { - qdf_timer_mod(&soc->mon_vdev_timer, DP_INTR_POLL_TIMER_MS); - soc->mon_vdev_timer_state |= MON_VDEV_TIMER_RUNNING; + wlan_op_mode_monitor == vdev->opmode) { + monitor_vdev_timer_start(soc); } dp_vdev_id_map_tbl_add(soc, vdev, vdev_id); if (wlan_op_mode_monitor == vdev->opmode) { - monitor_vdev_set_monitor_mode_buf_rings(pdev); + monitor_vdev_attach(vdev); pdev->monitor_vdev = vdev; return QDF_STATUS_SUCCESS; } @@ -6070,7 +5962,7 @@ static QDF_STATUS dp_vdev_register_wifi3(struct cdp_soc_t *soc_hdl, vdev->osif_fisa_rx = txrx_ops->rx.osif_fisa_rx; vdev->osif_fisa_flush = txrx_ops->rx.osif_fisa_flush; vdev->osif_get_key = txrx_ops->get_key; - vdev->osif_rx_mon = txrx_ops->rx.mon; + monitor_vdev_register_osif(vdev, txrx_ops); vdev->osif_tx_free_ext = txrx_ops->tx.tx_free_ext; vdev->tx_comp = txrx_ops->tx.tx_comp; vdev->stats_cb = txrx_ops->rx.stats_rx; @@ -6540,6 +6432,7 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, QDF_STATUS_SUCCESS) dp_warn("peer ext_stats ctx alloc failed"); + monitor_peer_attach(soc, peer); /* * In tx_monitor mode, filter may be set for unassociated peer * when unassociated peer get associated peer need to @@ -7189,18 +7082,11 @@ void dp_vdev_unref_delete(struct dp_soc *soc, struct dp_vdev *vdev, vdev, QDF_MAC_ADDR_REF(vdev->mac_addr.raw)); if (wlan_op_mode_monitor == vdev->opmode) { - if (soc->intr_mode == DP_INTR_POLL) { - qdf_timer_sync_cancel(&soc->int_timer); - monitor_flush_rings(soc); - } else if (soc->intr_mode == DP_INTR_MSI && - soc->mon_vdev_timer_state & MON_VDEV_TIMER_RUNNING) { - qdf_timer_sync_cancel(&soc->mon_vdev_timer); - monitor_flush_rings(soc); - soc->mon_vdev_timer_state &= ~MON_VDEV_TIMER_RUNNING; - } + monitor_vdev_delete(soc, vdev); pdev->monitor_vdev = NULL; goto free_vdev; } + /* all peers are gone, go ahead and delete it */ dp_tx_flow_pool_unmap_handler(pdev, vdev_id, FLOW_TYPE_VDEV, vdev_id); @@ -7299,6 +7185,8 @@ void dp_peer_unref_delete(struct dp_peer *peer, enum dp_mod_id mod_id) wlan_minidump_remove(peer, sizeof(*peer), soc->ctrl_psoc, WLAN_MD_DP_PEER, "dp_peer"); + monitor_peer_detach(soc, peer); + qdf_spin_lock_bh(&soc->inactive_peer_list_lock); TAILQ_FOREACH(tmp_peer, &soc->inactive_peer_list, inactive_list_elem) { @@ -11446,10 +11334,9 @@ static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) /* Stop monitor reap timer and reap any pending frames in ring */ if (((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) || - dp_is_enable_reap_timer_non_pkt(pdev)) && - soc->reap_timer_init) { - qdf_timer_sync_cancel(&soc->mon_reap_timer); - monitor_service_mon_rings(soc, DP_MON_REAP_BUDGET); + dp_is_enable_reap_timer_non_pkt(pdev))) { + if (monitor_reap_timer_stop(soc)) + monitor_service_mon_rings(soc, DP_MON_REAP_BUDGET); } dp_suspend_fse_cache_flush(soc); @@ -11472,10 +11359,8 @@ static QDF_STATUS dp_bus_resume(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) /* Start monitor reap timer */ if (((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) || - dp_is_enable_reap_timer_non_pkt(pdev)) && - soc->reap_timer_init) - qdf_timer_mod(&soc->mon_reap_timer, - DP_INTR_POLL_TIMER_MS); + dp_is_enable_reap_timer_non_pkt(pdev))) + monitor_reap_timer_start(soc); dp_resume_fse_cache_flush(soc); @@ -11531,10 +11416,9 @@ static void dp_process_target_suspend_req(struct cdp_soc_t *soc_hdl, /* Stop monitor reap timer and reap any pending frames in ring */ if (((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) || - dp_is_enable_reap_timer_non_pkt(pdev)) && - soc->reap_timer_init) { - qdf_timer_sync_cancel(&soc->mon_reap_timer); - monitor_service_mon_rings(soc, DP_MON_REAP_BUDGET); + dp_is_enable_reap_timer_non_pkt(pdev))) { + if (monitor_reap_timer_stop(soc)) + monitor_service_mon_rings(soc, DP_MON_REAP_BUDGET); } } diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 39d62a1a37..ccfc438667 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -3311,32 +3311,6 @@ void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer) #endif } -#ifdef FEATURE_PERPKT_INFO -/* - * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer - * @peer: Datapath peer - * - * return: void - */ -void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer) -{ - qdf_mem_zero(&peer->delayed_ba_ppdu_stats, - sizeof(struct cdp_delayed_tx_completion_ppdu_user)); - peer->last_delayed_ba = false; - peer->last_delayed_ba_ppduid = 0; -} -#else -/* - * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer - * @peer: Datapath peer - * - * return: void - */ -void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer) -{ -} -#endif - /* * dp_peer_cleanup() – Cleanup peer information * @vdev: Datapath vdev diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index a0bd80ac42..52bd85d782 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1917,16 +1917,11 @@ struct dp_soc { bool pending_ageout; uint32_t max_ast_ageout_count; - /*interrupt timer*/ - qdf_timer_t mon_reap_timer; - uint8_t reap_timer_init; qdf_timer_t lmac_reap_timer; uint8_t lmac_timer_init; qdf_timer_t int_timer; uint8_t intr_mode; uint8_t lmac_polled_mode; - qdf_timer_t mon_vdev_timer; - uint8_t mon_vdev_timer_state; qdf_list_t reo_desc_freelist; qdf_spinlock_t reo_desc_freelist_lock; @@ -2902,9 +2897,6 @@ struct dp_vdev { /* proxy arp function */ ol_txrx_proxy_arp_fp osif_proxy_arp; - /* callback to hand rx monitor 802.11 MPDU to the OS shim */ - ol_txrx_rx_mon_fp osif_rx_mon; - ol_txrx_mcast_me_fp me_convert; /* completion function used by this vdev*/ @@ -3040,6 +3032,9 @@ struct dp_vdev { uint8_t latency_tid; } mesh_tid_latency_config; #endif +#ifdef WIFI_MONITOR_SUPPORT + struct dp_mon_vdev *monitor_vdev; +#endif #ifdef WLAN_FEATURE_TSF_UPLINK_DELAY /* Indicate if uplink delay report is enabled or not */ @@ -3225,8 +3220,6 @@ struct dp_peer { /* TID structures */ struct dp_rx_tid rx_tid[DP_MAX_TIDS]; - struct dp_peer_tx_capture tx_capture; - /* TBD: No transmit TID state required? */ @@ -3303,14 +3296,6 @@ struct dp_peer { qdf_atomic_t flush_in_progress; struct dp_peer_cached_bufq bufq_info; #endif -#ifdef FEATURE_PERPKT_INFO - /* delayed ba ppdu stats handling */ - struct cdp_delayed_tx_completion_ppdu_user delayed_ba_ppdu_stats; - /* delayed ba flag */ - bool last_delayed_ba; - /* delayed ba ppdu id */ - uint32_t last_delayed_ba_ppduid; -#endif #ifdef QCA_PEER_MULTIQ_SUPPORT struct dp_peer_ast_params peer_ast_flowq_idx[DP_PEER_AST_FLOWQ_MAX]; #endif @@ -3337,6 +3322,9 @@ struct dp_peer { #ifdef WLAN_SUPPORT_MESH_LATENCY struct dp_peer_mesh_latency_parameter mesh_latency_params[DP_MAX_TIDS]; #endif +#ifdef WIFI_MONITOR_SUPPORT + struct dp_mon_peer *monitor_peer; +#endif }; /* diff --git a/dp/wifi3.0/monitor/dp_mon.c b/dp/wifi3.0/monitor/dp_mon.c index 49dd6a3023..bded198b9f 100644 --- a/dp/wifi3.0/monitor/dp_mon.c +++ b/dp/wifi3.0/monitor/dp_mon.c @@ -58,8 +58,12 @@ QDF_STATUS dp_srng_init(struct dp_soc *soc, struct dp_srng *srng, void dp_srng_deinit(struct dp_soc *soc, struct dp_srng *srng, int ring_type, int ring_num); -QDF_STATUS dp_vdev_set_monitor_mode_rings(struct dp_pdev *pdev, - uint8_t delayed_replenish); +enum timer_yield_status +dp_should_timer_irq_yield(struct dp_soc *soc, uint32_t work_done, + uint64_t start_time); + +static QDF_STATUS dp_vdev_set_monitor_mode_rings(struct dp_pdev *pdev, + uint8_t delayed_replenish); #ifndef WLAN_TX_PKT_CAPTURE_ENH static inline void @@ -1017,11 +1021,12 @@ dp_peer_copy_delay_stats(struct dp_peer *peer, { struct dp_pdev *pdev; struct dp_vdev *vdev; + struct dp_mon_peer *mon_peer = peer->monitor_peer; - if (peer->last_delayed_ba) { + if (mon_peer->last_delayed_ba) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "BA not yet recv for prev delayed ppdu[%d] - cur ppdu[%d]", - peer->last_delayed_ba_ppduid, cur_ppdu_id); + mon_peer->last_delayed_ba_ppduid, cur_ppdu_id); vdev = peer->vdev; if (vdev) { pdev = vdev->pdev; @@ -1029,30 +1034,32 @@ dp_peer_copy_delay_stats(struct dp_peer *peer, } } - peer->delayed_ba_ppdu_stats.ltf_size = ppdu->ltf_size; - peer->delayed_ba_ppdu_stats.stbc = ppdu->stbc; - peer->delayed_ba_ppdu_stats.he_re = ppdu->he_re; - peer->delayed_ba_ppdu_stats.txbf = ppdu->txbf; - peer->delayed_ba_ppdu_stats.bw = ppdu->bw; - peer->delayed_ba_ppdu_stats.nss = ppdu->nss; - peer->delayed_ba_ppdu_stats.gi = ppdu->gi; - peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; - peer->delayed_ba_ppdu_stats.ldpc = ppdu->ldpc; - peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; - peer->delayed_ba_ppdu_stats.mpdu_tried_ucast = ppdu->mpdu_tried_ucast; - peer->delayed_ba_ppdu_stats.mpdu_tried_mcast = ppdu->mpdu_tried_mcast; - peer->delayed_ba_ppdu_stats.frame_ctrl = ppdu->frame_ctrl; - peer->delayed_ba_ppdu_stats.qos_ctrl = ppdu->qos_ctrl; - peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; + mon_peer->delayed_ba_ppdu_stats.ltf_size = ppdu->ltf_size; + mon_peer->delayed_ba_ppdu_stats.stbc = ppdu->stbc; + mon_peer->delayed_ba_ppdu_stats.he_re = ppdu->he_re; + mon_peer->delayed_ba_ppdu_stats.txbf = ppdu->txbf; + mon_peer->delayed_ba_ppdu_stats.bw = ppdu->bw; + mon_peer->delayed_ba_ppdu_stats.nss = ppdu->nss; + mon_peer->delayed_ba_ppdu_stats.gi = ppdu->gi; + mon_peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; + mon_peer->delayed_ba_ppdu_stats.ldpc = ppdu->ldpc; + mon_peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; + mon_peer->delayed_ba_ppdu_stats.mpdu_tried_ucast = + ppdu->mpdu_tried_ucast; + mon_peer->delayed_ba_ppdu_stats.mpdu_tried_mcast = + ppdu->mpdu_tried_mcast; + mon_peer->delayed_ba_ppdu_stats.frame_ctrl = ppdu->frame_ctrl; + mon_peer->delayed_ba_ppdu_stats.qos_ctrl = ppdu->qos_ctrl; + mon_peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; - peer->delayed_ba_ppdu_stats.ru_start = ppdu->ru_start; - peer->delayed_ba_ppdu_stats.ru_tones = ppdu->ru_tones; - peer->delayed_ba_ppdu_stats.is_mcast = ppdu->is_mcast; + mon_peer->delayed_ba_ppdu_stats.ru_start = ppdu->ru_start; + mon_peer->delayed_ba_ppdu_stats.ru_tones = ppdu->ru_tones; + mon_peer->delayed_ba_ppdu_stats.is_mcast = ppdu->is_mcast; - peer->delayed_ba_ppdu_stats.user_pos = ppdu->user_pos; - peer->delayed_ba_ppdu_stats.mu_group_id = ppdu->mu_group_id; + mon_peer->delayed_ba_ppdu_stats.user_pos = ppdu->user_pos; + mon_peer->delayed_ba_ppdu_stats.mu_group_id = ppdu->mu_group_id; - peer->last_delayed_ba = true; + mon_peer->last_delayed_ba = true; ppdu->debug_copied = true; } @@ -1074,30 +1081,34 @@ static void dp_peer_copy_stats_to_bar(struct dp_peer *peer, struct cdp_tx_completion_ppdu_user *ppdu) { - ppdu->ltf_size = peer->delayed_ba_ppdu_stats.ltf_size; - ppdu->stbc = peer->delayed_ba_ppdu_stats.stbc; - ppdu->he_re = peer->delayed_ba_ppdu_stats.he_re; - ppdu->txbf = peer->delayed_ba_ppdu_stats.txbf; - ppdu->bw = peer->delayed_ba_ppdu_stats.bw; - ppdu->nss = peer->delayed_ba_ppdu_stats.nss; - ppdu->gi = peer->delayed_ba_ppdu_stats.gi; - ppdu->dcm = peer->delayed_ba_ppdu_stats.dcm; - ppdu->ldpc = peer->delayed_ba_ppdu_stats.ldpc; - ppdu->dcm = peer->delayed_ba_ppdu_stats.dcm; - ppdu->mpdu_tried_ucast = peer->delayed_ba_ppdu_stats.mpdu_tried_ucast; - ppdu->mpdu_tried_mcast = peer->delayed_ba_ppdu_stats.mpdu_tried_mcast; - ppdu->frame_ctrl = peer->delayed_ba_ppdu_stats.frame_ctrl; - ppdu->qos_ctrl = peer->delayed_ba_ppdu_stats.qos_ctrl; - ppdu->dcm = peer->delayed_ba_ppdu_stats.dcm; + struct dp_mon_peer *mon_peer = peer->monitor_peer; - ppdu->ru_start = peer->delayed_ba_ppdu_stats.ru_start; - ppdu->ru_tones = peer->delayed_ba_ppdu_stats.ru_tones; - ppdu->is_mcast = peer->delayed_ba_ppdu_stats.is_mcast; + ppdu->ltf_size = mon_peer->delayed_ba_ppdu_stats.ltf_size; + ppdu->stbc = mon_peer->delayed_ba_ppdu_stats.stbc; + ppdu->he_re = mon_peer->delayed_ba_ppdu_stats.he_re; + ppdu->txbf = mon_peer->delayed_ba_ppdu_stats.txbf; + ppdu->bw = mon_peer->delayed_ba_ppdu_stats.bw; + ppdu->nss = mon_peer->delayed_ba_ppdu_stats.nss; + ppdu->gi = mon_peer->delayed_ba_ppdu_stats.gi; + ppdu->dcm = mon_peer->delayed_ba_ppdu_stats.dcm; + ppdu->ldpc = mon_peer->delayed_ba_ppdu_stats.ldpc; + ppdu->dcm = mon_peer->delayed_ba_ppdu_stats.dcm; + ppdu->mpdu_tried_ucast = + mon_peer->delayed_ba_ppdu_stats.mpdu_tried_ucast; + ppdu->mpdu_tried_mcast = + mon_peer->delayed_ba_ppdu_stats.mpdu_tried_mcast; + ppdu->frame_ctrl = mon_peer->delayed_ba_ppdu_stats.frame_ctrl; + ppdu->qos_ctrl = mon_peer->delayed_ba_ppdu_stats.qos_ctrl; + ppdu->dcm = mon_peer->delayed_ba_ppdu_stats.dcm; - ppdu->user_pos = peer->delayed_ba_ppdu_stats.user_pos; - ppdu->mu_group_id = peer->delayed_ba_ppdu_stats.mu_group_id; + ppdu->ru_start = mon_peer->delayed_ba_ppdu_stats.ru_start; + ppdu->ru_tones = mon_peer->delayed_ba_ppdu_stats.ru_tones; + ppdu->is_mcast = mon_peer->delayed_ba_ppdu_stats.is_mcast; - peer->last_delayed_ba = false; + ppdu->user_pos = mon_peer->delayed_ba_ppdu_stats.user_pos; + ppdu->mu_group_id = mon_peer->delayed_ba_ppdu_stats.mu_group_id; + + mon_peer->last_delayed_ba = false; ppdu->debug_copied = true; } @@ -2272,7 +2283,7 @@ dp_process_ppdu_stats_sch_cmd_status_tlv(struct dp_pdev *pdev, if (!peer) continue; - delay_ppdu = &peer->delayed_ba_ppdu_stats; + delay_ppdu = &peer->monitor_peer->delayed_ba_ppdu_stats; start_tsf = ppdu_desc->ppdu_start_timestamp; end_tsf = ppdu_desc->ppdu_end_timestamp; /** @@ -2282,12 +2293,13 @@ dp_process_ppdu_stats_sch_cmd_status_tlv(struct dp_pdev *pdev, dp_peer_copy_delay_stats(peer, &ppdu_desc->user[i], ppdu_id); - peer->last_delayed_ba_ppduid = ppdu_id; + peer->monitor_peer->last_delayed_ba_ppduid = + ppdu_id; delay_ppdu->ppdu_start_timestamp = start_tsf; delay_ppdu->ppdu_end_timestamp = end_tsf; } ppdu_desc->user[i].peer_last_delayed_ba = - peer->last_delayed_ba; + peer->monitor_peer->last_delayed_ba; dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); @@ -2334,20 +2346,20 @@ dp_process_ppdu_stats_sch_cmd_status_tlv(struct dp_pdev *pdev, continue; } - delay_ppdu = &peer->delayed_ba_ppdu_stats; + delay_ppdu = &peer->monitor_peer->delayed_ba_ppdu_stats; start_tsf = delay_ppdu->ppdu_start_timestamp; end_tsf = delay_ppdu->ppdu_end_timestamp; - if (peer->last_delayed_ba) { + if (peer->monitor_peer->last_delayed_ba) { dp_peer_copy_stats_to_bar(peer, &ppdu_desc->user[i]); ppdu_desc->ppdu_id = - peer->last_delayed_ba_ppduid; + peer->monitor_peer->last_delayed_ba_ppduid; ppdu_desc->ppdu_start_timestamp = start_tsf; ppdu_desc->ppdu_end_timestamp = end_tsf; } ppdu_desc->user[i].peer_last_delayed_ba = - peer->last_delayed_ba; + peer->monitor_peer->last_delayed_ba; dp_peer_unref_delete(peer, DP_MOD_ID_TX_PPDU_STATS); } } @@ -3572,8 +3584,10 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, int max_mac_rings = wlan_cfg_get_num_mac_rings (pdev->wlan_cfg_ctx); uint8_t mac_id = 0; + struct dp_mon_soc *mon_soc; soc = pdev->soc; + mon_soc = soc->monitor_soc; dp_is_hw_dbs_enable(soc, &max_mac_rings); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, @@ -3603,9 +3617,9 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, return 0; } - if (soc->reap_timer_init && + if (mon_soc->reap_timer_init && (!dp_is_enable_reap_timer_non_pkt(pdev))) - qdf_timer_mod(&soc->mon_reap_timer, + qdf_timer_mod(&mon_soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); } break; @@ -3634,9 +3648,9 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, return 0; } - if (soc->reap_timer_init && + if (mon_soc->reap_timer_init && (!dp_is_enable_reap_timer_non_pkt(pdev))) - qdf_timer_mod(&soc->mon_reap_timer, + qdf_timer_mod(&mon_soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); } break; @@ -3682,9 +3696,9 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, return 0; } - if (soc->reap_timer_init && + if (mon_soc->reap_timer_init && !dp_is_enable_reap_timer_non_pkt(pdev)) - qdf_timer_mod(&soc->mon_reap_timer, + qdf_timer_mod(&mon_soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); } break; @@ -3720,9 +3734,9 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, return 0; } - if (soc->reap_timer_init && + if (mon_soc->reap_timer_init && (!dp_is_enable_reap_timer_non_pkt(pdev))) - qdf_timer_stop(&soc->mon_reap_timer); + qdf_timer_stop(&mon_soc->mon_reap_timer); } break; case WDI_EVENT_LITE_T2H: @@ -3781,6 +3795,7 @@ static void dp_pktlogmod_exit(struct dp_pdev *pdev) { struct dp_soc *soc = pdev->soc; struct hif_opaque_softc *scn = soc->hif_handle; + struct dp_mon_soc *mon_soc = soc->monitor_soc; if (!scn) { dp_err("Invalid hif(scn) handle"); @@ -3789,8 +3804,9 @@ static void dp_pktlogmod_exit(struct dp_pdev *pdev) /* stop mon_reap_timer if it has been started */ if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED && - soc->reap_timer_init && (!dp_is_enable_reap_timer_non_pkt(pdev))) - qdf_timer_sync_cancel(&soc->mon_reap_timer); + mon_soc->reap_timer_init && + (!dp_is_enable_reap_timer_non_pkt(pdev))) + qdf_timer_sync_cancel(&mon_soc->mon_reap_timer); pktlogmod_exit(scn); pdev->pkt_log_init = false; @@ -4183,6 +4199,7 @@ dp_enable_mon_reap_timer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_pdev *pdev = NULL; + struct dp_mon_soc *mon_soc = soc->monitor_soc; pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); if (!pdev) { @@ -4196,16 +4213,16 @@ dp_enable_mon_reap_timer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, return; } - if (!soc->reap_timer_init) { + if (!mon_soc->reap_timer_init) { dp_err("reap timer not init"); return; } if (enable) - qdf_timer_mod(&soc->mon_reap_timer, + qdf_timer_mod(&mon_soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); else - qdf_timer_sync_cancel(&soc->mon_reap_timer); + qdf_timer_sync_cancel(&mon_soc->mon_reap_timer); } #endif @@ -4488,8 +4505,8 @@ dp_peer_update_pkt_capture_params(ol_txrx_soc_handle soc, * * Return: QDF_STATUS */ -QDF_STATUS dp_vdev_set_monitor_mode_rings(struct dp_pdev *pdev, - uint8_t delayed_replenish) +static 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; @@ -4564,6 +4581,168 @@ fail0: return QDF_STATUS_E_FAILURE; } +/* dp_mon_vdev_timer()- timer poll for interrupts + * + * @arg: SoC Handle + * + * Return: + * + */ +static void dp_mon_vdev_timer(void *arg) +{ + struct dp_soc *soc = (struct dp_soc *)arg; + struct dp_pdev *pdev = soc->pdev_list[0]; + enum timer_yield_status yield = DP_TIMER_NO_YIELD; + uint32_t work_done = 0, total_work_done = 0; + int budget = 0xffff; + uint32_t remaining_quota = budget; + uint64_t start_time; + uint32_t lmac_id = DP_MON_INVALID_LMAC_ID; + uint32_t lmac_iter; + int max_mac_rings = wlan_cfg_get_num_mac_rings(pdev->wlan_cfg_ctx); + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!qdf_atomic_read(&soc->cmn_init_done)) + return; + + if (pdev->mon_chan_band != REG_BAND_UNKNOWN) + lmac_id = pdev->ch_band_lmac_id_mapping[pdev->mon_chan_band]; + + start_time = qdf_get_log_timestamp(); + dp_is_hw_dbs_enable(soc, &max_mac_rings); + + while (yield == DP_TIMER_NO_YIELD) { + for (lmac_iter = 0; lmac_iter < max_mac_rings; lmac_iter++) { + if (lmac_iter == lmac_id) + work_done = monitor_process(soc, NULL, + lmac_iter, + remaining_quota); + else + work_done = + monitor_drop_packets_for_mac(pdev, + lmac_iter, + remaining_quota); + if (work_done) { + budget -= work_done; + if (budget <= 0) { + yield = DP_TIMER_WORK_EXHAUST; + goto budget_done; + } + remaining_quota = budget; + total_work_done += work_done; + } + } + + yield = dp_should_timer_irq_yield(soc, total_work_done, + start_time); + total_work_done = 0; + } + +budget_done: + if (yield == DP_TIMER_WORK_EXHAUST || + yield == DP_TIMER_TIME_EXHAUST) + qdf_timer_mod(&mon_soc->mon_vdev_timer, 1); + else + qdf_timer_mod(&mon_soc->mon_vdev_timer, DP_INTR_POLL_TIMER_MS); +} + +/* MCL specific functions */ +#if defined(DP_CON_MON) +/* + * dp_mon_reap_timer_handler()- timer to reap monitor rings + * reqd as we are not getting ppdu end interrupts + * @arg: SoC Handle + * + * Return: + * + */ +static void dp_mon_reap_timer_handler(void *arg) +{ + struct dp_soc *soc = (struct dp_soc *)arg; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + dp_service_mon_rings(soc, QCA_NAPI_BUDGET); + qdf_timer_mod(&mon_soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); +} +#endif + +#ifdef QCA_HOST2FW_RXBUF_RING +static void dp_mon_reap_timer_init(struct dp_soc *soc) +{ + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + qdf_timer_init(soc->osdev, &mon_soc->mon_reap_timer, + dp_mon_reap_timer_handler, (void *)soc, + QDF_TIMER_TYPE_WAKE_APPS); + mon_soc->reap_timer_init = 1; +} +#else +static void dp_mon_reap_timer_init(struct dp_soc *soc) +{ +} +#endif + +static void dp_mon_reap_timer_deinit(struct dp_mon_soc *mon_soc) +{ + if (mon_soc->reap_timer_init) { + qdf_timer_free(&mon_soc->mon_reap_timer); + mon_soc->reap_timer_init = 0; + } +} + +static void dp_mon_reap_timer_start(struct dp_mon_soc *mon_soc) +{ + if (mon_soc->reap_timer_init) + qdf_timer_mod(&mon_soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); +} + +static bool dp_mon_reap_timer_stop(struct dp_mon_soc *mon_soc) +{ + if (mon_soc->reap_timer_init) { + qdf_timer_sync_cancel(&mon_soc->mon_reap_timer); + return true; + } + + return false; +} + +static void dp_mon_vdev_timer_init(struct dp_soc *soc) +{ + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + qdf_timer_init(soc->osdev, &mon_soc->mon_vdev_timer, + dp_mon_vdev_timer, (void *)soc, + QDF_TIMER_TYPE_WAKE_APPS); + mon_soc->mon_vdev_timer_state |= MON_VDEV_TIMER_INIT; +} + +static void dp_mon_vdev_timer_deinit(struct dp_mon_soc *mon_soc) +{ + if (mon_soc->mon_vdev_timer_state & MON_VDEV_TIMER_INIT) { + qdf_timer_free(&mon_soc->mon_vdev_timer); + mon_soc->mon_vdev_timer_state = 0; + } +} + +static void dp_mon_vdev_timer_start(struct dp_mon_soc *mon_soc) +{ + if (mon_soc->mon_vdev_timer_state & MON_VDEV_TIMER_INIT) { + qdf_timer_mod(&mon_soc->mon_vdev_timer, DP_INTR_POLL_TIMER_MS); + mon_soc->mon_vdev_timer_state |= MON_VDEV_TIMER_RUNNING; + } +} + +static bool dp_mon_vdev_timer_stop(struct dp_mon_soc *mon_soc) +{ + if (mon_soc->mon_vdev_timer_state & MON_VDEV_TIMER_RUNNING) { + qdf_timer_sync_cancel(&mon_soc->mon_vdev_timer); + mon_soc->mon_vdev_timer_state &= ~MON_VDEV_TIMER_RUNNING; + return true; + } + + return false; +} + QDF_STATUS dp_mon_soc_cfg_init(struct dp_soc *soc) { int target_type; @@ -4746,12 +4925,67 @@ QDF_STATUS dp_mon_pdev_deinit(struct dp_pdev *pdev) return QDF_STATUS_SUCCESS; } +QDF_STATUS dp_mon_vdev_attach(struct dp_vdev *vdev) +{ + struct dp_mon_vdev *mon_vdev; + struct dp_pdev *pdev = vdev->pdev; + + mon_vdev = (struct dp_mon_vdev *)qdf_mem_malloc(sizeof(*mon_vdev)); + if (!mon_vdev) { + mon_init_err("%pK: Monitor vdev allocation failed", vdev); + return QDF_STATUS_E_NOMEM; + } + + vdev->monitor_vdev = mon_vdev; + dp_vdev_set_monitor_mode_buf_rings(pdev); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS dp_mon_vdev_detach(struct dp_vdev *vdev) +{ + struct dp_mon_vdev *mon_vdev = vdev->monitor_vdev; + + qdf_mem_free(mon_vdev); + vdev->monitor_vdev = NULL; + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS dp_mon_peer_attach(struct dp_peer *peer) +{ + struct dp_mon_peer *mon_peer; + + mon_peer = (struct dp_mon_peer *)qdf_mem_malloc(sizeof(*mon_peer)); + if (!mon_peer) { + mon_init_err("%pK: MONITOR peer allocation failed", peer); + return QDF_STATUS_E_NOMEM; + } + + peer->monitor_peer = mon_peer; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS dp_mon_peer_detach(struct dp_peer *peer) +{ + struct dp_mon_peer *mon_peer = peer->monitor_peer; + + qdf_mem_free(mon_peer); + peer->monitor_peer = NULL; + + return QDF_STATUS_SUCCESS; +} + static struct dp_mon_ops monitor_ops = { .mon_soc_cfg_init = dp_mon_soc_cfg_init, .mon_pdev_attach = dp_mon_pdev_attach, .mon_pdev_detach = dp_mon_pdev_detach, .mon_pdev_init = dp_mon_pdev_init, .mon_pdev_deinit = dp_mon_pdev_deinit, + .mon_vdev_attach = dp_mon_vdev_attach, + .mon_vdev_detach = dp_mon_vdev_detach, + .mon_peer_attach = dp_mon_peer_attach, + .mon_peer_detach = dp_mon_peer_detach, .mon_config_debug_sniffer = dp_config_debug_sniffer, .mon_flush_rings = dp_flush_monitor_rings, #if !defined(DISABLE_MON_CONFIG) @@ -4812,6 +5046,14 @@ static struct dp_mon_ops monitor_ops = { #ifdef FEATURE_NAC_RSSI .mon_filter_neighbour_peer = dp_filter_neighbour_peer, #endif + .mon_vdev_timer_init = dp_mon_vdev_timer_init, + .mon_vdev_timer_start = dp_mon_vdev_timer_start, + .mon_vdev_timer_stop = dp_mon_vdev_timer_stop, + .mon_vdev_timer_deinit = dp_mon_vdev_timer_deinit, + .mon_reap_timer_init = dp_mon_reap_timer_init, + .mon_reap_timer_start = dp_mon_reap_timer_start, + .mon_reap_timer_stop = dp_mon_reap_timer_stop, + .mon_reap_timer_deinit = dp_mon_reap_timer_deinit, }; static struct cdp_mon_ops dp_ops_mon = { diff --git a/dp/wifi3.0/monitor/dp_mon.h b/dp/wifi3.0/monitor/dp_mon.h index 6934d528fa..e14fe9f6ea 100644 --- a/dp/wifi3.0/monitor/dp_mon.h +++ b/dp/wifi3.0/monitor/dp_mon.h @@ -13,13 +13,26 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define DP_INTR_POLL_TIMER_MS 5 + +#define MON_VDEV_TIMER_INIT 0x1 +#define MON_VDEV_TIMER_RUNNING 0x2 + +/* Budget to reap monitor status ring */ +#define DP_MON_REAP_BUDGET 1024 + #define mon_rx_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_DP_RX, params) + struct dp_mon_ops { QDF_STATUS (*mon_soc_cfg_init)(struct dp_soc *soc); QDF_STATUS (*mon_pdev_attach)(struct dp_pdev *pdev); 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_vdev_attach)(struct dp_vdev *vdev); + QDF_STATUS (*mon_vdev_detach)(struct dp_vdev *vdev); + QDF_STATUS (*mon_peer_attach)(struct dp_peer *peer); + QDF_STATUS (*mon_peer_detach)(struct dp_peer *peer); QDF_STATUS (*mon_config_debug_sniffer)(struct dp_pdev *pdev, int val); void (*mon_flush_rings)(struct dp_soc *soc); #if !defined(DISABLE_MON_CONFIG) @@ -100,12 +113,27 @@ struct dp_mon_ops { QDF_STATUS (*mon_filter_neighbour_peer)(struct dp_pdev *pdev, uint8_t *rx_pkt_hdr); #endif + void (*mon_vdev_timer_init)(struct dp_soc *soc); + void (*mon_vdev_timer_start)(struct dp_mon_soc *mon_soc); + bool (*mon_vdev_timer_stop)(struct dp_mon_soc *mon_soc); + void (*mon_vdev_timer_deinit)(struct dp_mon_soc *mon_soc); + void (*mon_reap_timer_init)(struct dp_soc *soc); + void (*mon_reap_timer_start)(struct dp_mon_soc *mon_soc); + bool (*mon_reap_timer_stop)(struct dp_mon_soc *mon_soc); + void (*mon_reap_timer_deinit)(struct dp_mon_soc *mon_soc); }; struct dp_mon_soc { /* Holds all monitor related fields extracted from dp_soc */ /* Holds pointer to monitor ops */ + /*interrupt timer*/ + qdf_timer_t mon_reap_timer; + uint8_t reap_timer_init; + + qdf_timer_t mon_vdev_timer; + uint8_t mon_vdev_timer_state; + struct dp_mon_ops *mon_ops; }; @@ -113,9 +141,20 @@ struct dp_mon_pdev { }; struct dp_mon_vdev { + /* callback to hand rx monitor 802.11 MPDU to the OS shim */ + ol_txrx_rx_mon_fp osif_rx_mon; }; struct dp_mon_peer { + struct dp_peer_tx_capture tx_capture; +#ifdef FEATURE_PERPKT_INFO + /* delayed ba ppdu stats handling */ + struct cdp_delayed_tx_completion_ppdu_user delayed_ba_ppdu_stats; + /* delayed ba flag */ + bool last_delayed_ba; + /* delayed ba ppdu id */ + uint32_t last_delayed_ba_ppduid; +#endif }; #ifdef FEATURE_PERPKT_INFO @@ -227,6 +266,19 @@ extern uint8_t dp_cpu_ring_map[DP_NSS_CPU_RING_MAP_MAX][WLAN_CFG_INT_NUM_CONTEXTS_MAX]; #endif +int +dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap(uint32_t bitmap); +/** + * dp_ppdu_desc_user_stats_update(): Function to update TX user stats + * @pdev: DP pdev handle + * @ppdu_info: per PPDU TLV descriptor + * + * return: void + */ +void +dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, + struct ppdu_info *ppdu_info); + #ifdef WDI_EVENT_ENABLE void dp_pkt_log_init(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, void *scn); #else @@ -324,6 +376,58 @@ static inline QDF_STATUS monitor_drop_inv_peer_pkts(struct dp_vdev *vdev, } #endif +#ifdef FEATURE_PERPKT_INFO +/* + * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer + * @peer: Datapath peer + * + * return: void + */ +static inline void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer) +{ + struct dp_mon_peer *mon_peer = peer->monitor_peer; + + if (!mon_peer) + return; + + qdf_mem_zero(&mon_peer->delayed_ba_ppdu_stats, + sizeof(struct cdp_delayed_tx_completion_ppdu_user)); + mon_peer->last_delayed_ba = false; + mon_peer->last_delayed_ba_ppduid = 0; +} +#else +/* + * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer + * @peer: Datapath peer + * + * return: void + */ +static inline void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer) +{ +} +#endif + +static inline void monitor_vdev_register_osif(struct dp_vdev *vdev, + struct ol_txrx_ops *txrx_ops) +{ + if (!vdev->monitor_vdev) + return; + + vdev->monitor_vdev->osif_rx_mon = txrx_ops->rx.mon; +} + +static inline bool monitor_is_vdev_timer_running(struct dp_soc *soc) +{ + struct dp_mon_soc *mon_soc; + + if (!soc || !soc->monitor_soc) + return false; + + mon_soc = soc->monitor_soc; + + return mon_soc->mon_vdev_timer_state & MON_VDEV_TIMER_RUNNING; +} + static inline QDF_STATUS monitor_pdev_attach(struct dp_pdev *pdev) { struct dp_mon_ops *monitor_ops; @@ -368,6 +472,76 @@ static inline QDF_STATUS monitor_pdev_detach(struct dp_pdev *pdev) return monitor_ops->mon_pdev_detach(pdev); } +static inline QDF_STATUS monitor_vdev_attach(struct dp_vdev *vdev) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = vdev->pdev->soc->monitor_soc; + + if (!mon_soc) + return QDF_STATUS_E_FAILURE; + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_vdev_attach) { + qdf_err("callback not registered"); + return QDF_STATUS_E_FAILURE; + } + + return monitor_ops->mon_vdev_attach(vdev); +} + +static inline QDF_STATUS monitor_vdev_detach(struct dp_vdev *vdev) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = vdev->pdev->soc->monitor_soc; + + if (!mon_soc) + return QDF_STATUS_E_FAILURE; + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_vdev_detach) { + qdf_err("callback not registered"); + return QDF_STATUS_E_FAILURE; + } + + return monitor_ops->mon_vdev_detach(vdev); +} + +static inline QDF_STATUS monitor_peer_attach(struct dp_soc *soc, + struct dp_peer *peer) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) + return QDF_STATUS_E_FAILURE; + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_peer_attach) { + qdf_print("callback not registered"); + return QDF_STATUS_E_FAILURE; + } + + return monitor_ops->mon_peer_attach(peer); +} + +static inline QDF_STATUS monitor_peer_detach(struct dp_soc *soc, + struct dp_peer *peer) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) + return QDF_STATUS_E_FAILURE; + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_peer_detach) { + qdf_print("callback not registered"); + return QDF_STATUS_E_FAILURE; + } + + return monitor_ops->mon_peer_detach(peer); +} + static inline QDF_STATUS monitor_pdev_init(struct dp_pdev *pdev) { struct dp_mon_ops *monitor_ops; @@ -1221,3 +1395,177 @@ static inline QDF_STATUS monitor_filter_neighbour_peer(struct dp_pdev *pdev, return monitor_ops->mon_filter_neighbour_peer(pdev, rx_pkt_hdr); } #endif + +static inline +void monitor_reap_timer_init(struct dp_soc *soc) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) { + qdf_err("monitor soc is NULL"); + return; + } + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_reap_timer_init) { + qdf_err("callback not registered"); + return; + } + + monitor_ops->mon_reap_timer_init(soc); +} + +static inline +void monitor_reap_timer_deinit(struct dp_soc *soc) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) { + qdf_err("monitor soc is NULL"); + return; + } + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_reap_timer_deinit) { + qdf_err("callback not registered"); + return; + } + + monitor_ops->mon_reap_timer_deinit(mon_soc); +} + +static inline +void monitor_reap_timer_start(struct dp_soc *soc) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) { + qdf_err("monitor soc is NULL"); + return; + } + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_reap_timer_start) { + qdf_err("callback not registered"); + return; + } + + monitor_ops->mon_reap_timer_start(mon_soc); +} + +static inline +bool monitor_reap_timer_stop(struct dp_soc *soc) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) { + qdf_err("monitor soc is NULL"); + return false; + } + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_reap_timer_stop) { + qdf_err("callback not registered"); + return false; + } + + monitor_ops->mon_reap_timer_stop(mon_soc); +} + +static inline +void monitor_vdev_timer_init(struct dp_soc *soc) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) { + qdf_err("monitor soc is NULL"); + return; + } + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_vdev_timer_init) { + qdf_err("callback not registered"); + return; + } + + monitor_ops->mon_vdev_timer_init(soc); +} + +static inline +void monitor_vdev_timer_deinit(struct dp_soc *soc) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) { + qdf_err("monitor soc is NULL"); + return; + } + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_vdev_timer_deinit) { + qdf_err("callback not registered"); + return; + } + + monitor_ops->mon_vdev_timer_deinit(mon_soc); +} + +static inline +void monitor_vdev_timer_start(struct dp_soc *soc) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) { + qdf_err("monitor soc is NULL"); + return; + } + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_vdev_timer_start) { + qdf_err("callback not registered"); + return; + } + + monitor_ops->mon_vdev_timer_start(mon_soc); +} + +static inline +bool monitor_vdev_timer_stop(struct dp_soc *soc) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) { + qdf_err("monitor soc is NULL"); + return false; + } + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_vdev_timer_stop) { + qdf_err("callback not registered"); + return false; + } + + return monitor_ops->mon_vdev_timer_stop(mon_soc); +} + +static inline void monitor_vdev_delete(struct dp_soc *soc, struct dp_vdev *vdev) +{ + if (soc->intr_mode == DP_INTR_POLL) { + qdf_timer_sync_cancel(&soc->int_timer); + monitor_flush_rings(soc); + } else if (soc->intr_mode == DP_INTR_MSI) { + if (monitor_vdev_timer_stop(soc)) + monitor_flush_rings(soc); + } + + monitor_vdev_detach(vdev); +} + diff --git a/dp/wifi3.0/monitor/dp_rx_mon_dest.c b/dp/wifi3.0/monitor/dp_rx_mon_dest.c index 6e43469e74..c80a095a53 100644 --- a/dp/wifi3.0/monitor/dp_rx_mon_dest.c +++ b/dp/wifi3.0/monitor/dp_rx_mon_dest.c @@ -25,6 +25,8 @@ #include "qdf_trace.h" #include "qdf_nbuf.h" #include "hal_api_mon.h" +#include "dp_htt.h" +#include "dp_mon.h" #include "dp_rx_mon.h" #include "wlan_cfg.h" #include "dp_internal.h" @@ -1489,11 +1491,13 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, struct cdp_mon_status *rs = &pdev->rx_mon_recv_status; qdf_nbuf_t mon_skb, skb_next; qdf_nbuf_t mon_mpdu = NULL; + struct dp_vdev *vdev; if (!pdev || (!pdev->monitor_vdev && !pdev->mcopy_mode && !pdev->rx_pktlog_cbf)) goto mon_deliver_fail; + vdev = pdev->monitor_vdev; /* restitch mon MPDU for delivery via monitor interface */ mon_mpdu = dp_rx_mon_restitch_mpdu(soc, mac_id, head_msdu, tail_msdu, rs); @@ -1513,7 +1517,7 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, return dp_send_mgmt_packet_to_stack(soc, mon_mpdu, pdev); if (mon_mpdu && pdev->monitor_vdev && pdev->monitor_vdev->osif_vdev && - pdev->monitor_vdev->osif_rx_mon) { + vdev->monitor_vdev->osif_rx_mon) { pdev->ppdu_info.rx_status.ppdu_id = pdev->ppdu_info.com_info.ppdu_id; pdev->ppdu_info.rx_status.device_id = soc->device_id; @@ -1532,7 +1536,7 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, } dp_rx_mon_update_pf_tag_to_buf_headroom(soc, mon_mpdu); - pdev->monitor_vdev->osif_rx_mon(pdev->monitor_vdev->osif_vdev, + vdev->monitor_vdev->osif_rx_mon(pdev->monitor_vdev->osif_vdev, mon_mpdu, &pdev->ppdu_info.rx_status); } else { @@ -1575,13 +1579,19 @@ QDF_STATUS dp_rx_mon_deliver_non_std(struct dp_soc *soc, struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); ol_txrx_rx_mon_fp osif_rx_mon; qdf_nbuf_t dummy_msdu; + struct dp_vdev *vdev; /* Sanity checking */ - if (!pdev || !pdev->monitor_vdev || !pdev->monitor_vdev->osif_rx_mon) + if (!pdev || !pdev->monitor_vdev) + goto mon_deliver_non_std_fail; + + vdev = pdev->monitor_vdev; + + if (!vdev->monitor_vdev->osif_rx_mon) goto mon_deliver_non_std_fail; /* Generate a dummy skb_buff */ - osif_rx_mon = pdev->monitor_vdev->osif_rx_mon; + osif_rx_mon = vdev->monitor_vdev->osif_rx_mon; dummy_msdu = qdf_nbuf_alloc(soc->osdev, MAX_MONITOR_HEADER, MAX_MONITOR_HEADER, 4, FALSE); if (!dummy_msdu) diff --git a/dp/wifi3.0/monitor/dp_rx_mon_status.c b/dp/wifi3.0/monitor/dp_rx_mon_status.c index c1756ddc82..7f59caa9d5 100644 --- a/dp/wifi3.0/monitor/dp_rx_mon_status.c +++ b/dp/wifi3.0/monitor/dp_rx_mon_status.c @@ -1092,6 +1092,7 @@ dp_rx_handle_smart_mesh_mode(struct dp_soc *soc, struct dp_pdev *pdev, qdf_nbuf_t nbuf) { uint8_t size = 0; + struct dp_vdev *vdev; if (!pdev->monitor_vdev) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, @@ -1099,6 +1100,9 @@ dp_rx_handle_smart_mesh_mode(struct dp_soc *soc, struct dp_pdev *pdev, __func__, __LINE__); return 1; } + + vdev = pdev->monitor_vdev; + if (!ppdu_info->msdu_info.first_msdu_payload) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "[%s]:[%d] First msdu payload not present", @@ -1127,7 +1131,7 @@ dp_rx_handle_smart_mesh_mode(struct dp_soc *soc, struct dp_pdev *pdev, return 1; } - pdev->monitor_vdev->osif_rx_mon(pdev->monitor_vdev->osif_vdev, + vdev->monitor_vdev->osif_rx_mon(pdev->monitor_vdev->osif_vdev, nbuf, NULL); pdev->ppdu_info.rx_status.monitor_direct_used = 0; return 0;