diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 2d38c45b5d..0543f25619 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -248,6 +248,9 @@ static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc, int ring_num); #define DP_INTR_POLL_TIMER_MS 5 +#define MON_VDEV_TIMER_INIT 0x1 +#define MON_VDEV_TIMER_RUNNING 0x2 + /* Generic AST entry aging timer value */ #define DP_AST_AGING_TIMER_DEFAULT_MS 1000 #define DP_MCS_LENGTH (6*MAX_MCS) @@ -2030,12 +2033,14 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) int_ctx->intr_stats.num_reo_status_ring_masks++; } - work_done = dp_process_lmac_rings(int_ctx, remaining_quota); - if (work_done) { - budget -= work_done; - if (budget <= 0) - goto budget_done; - remaining_quota = budget; + if (qdf_unlikely(!(soc->mon_vdev_timer_state & MON_VDEV_TIMER_RUNNING))) { + work_done = dp_process_lmac_rings(int_ctx, remaining_quota); + if (work_done) { + budget -= work_done; + if (budget <= 0) + goto budget_done; + remaining_quota = budget; + } } qdf_lro_flush(int_ctx->lro_ctx); @@ -2045,6 +2050,70 @@ budget_done: return dp_budget - budget; } +/* 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 = dp_mon_process( + soc, NULL, + lmac_iter, remaining_quota); + else + work_done = + dp_mon_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 @@ -4668,6 +4737,10 @@ static void dp_soc_detach(struct cdp_soc_t *txrx_soc) dp_hw_link_desc_pool_banks_free(soc, WLAN_INVALID_PDEV_ID); wlan_cfg_soc_detach(soc->wlan_cfg_ctx); dp_soc_rx_history_detach(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); } @@ -4873,6 +4946,10 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc) 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; return status; } #else @@ -5382,6 +5459,11 @@ static QDF_STATUS dp_vdev_attach_wifi3(struct cdp_soc_t *cdp_soc, if ((pdev->vdev_count == 0) || (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; } dp_vdev_id_map_tbl_add(soc, vdev, vdev_id); @@ -6643,6 +6725,11 @@ void dp_vdev_unref_delete(struct dp_soc *soc, struct dp_vdev *vdev, if (soc->intr_mode == DP_INTR_POLL) { qdf_timer_sync_cancel(&soc->int_timer); dp_flush_monitor_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); + dp_flush_monitor_rings(soc); + soc->mon_vdev_timer_state &= ~MON_VDEV_TIMER_RUNNING; } pdev->monitor_vdev = NULL; goto free_vdev; diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index bbb5ab91f9..a44c4272a1 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1538,6 +1538,8 @@ struct dp_soc { 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;