diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 1df7b7a923..d41e884897 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -1063,6 +1063,15 @@ struct ol_txrx_ops { ol_txrx_get_tsf_time get_tsf_time; }; +/** + * ol_txrx_hardtart_ctxt - handlers for dp tx path + * + */ +struct ol_txrx_hardtart_ctxt { + ol_txrx_tx_fp tx; + ol_txrx_tx_exc_fp tx_exception; +}; + /** * ol_txrx_stats_req - specifications of the requested * statistics diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index d0ed2a4ef7..15d75adea9 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -1457,6 +1457,11 @@ struct ol_if_ops { uint8_t vdev_id, uint32_t rule_id, uint8_t *peer_mac); #endif +#ifdef DP_UMAC_HW_RESET_SUPPORT + void (*dp_update_tx_hardstart)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t vdev_id, + struct ol_txrx_hardtart_ctxt *ctxt); +#endif }; #ifdef DP_PEER_EXTENDED_API diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index 06a615a681..707432d4be 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -1731,6 +1731,7 @@ struct cdp_rx_stats { * @dma_error: dma fail * @res_full: Resource Full: Congestion Control * @fail_per_pkt_vdev_id_check: Per pkt vdev id check + * @drop_ingress: Packets dropped during Umac reset * @exception_fw: packets sent to fw * @completion_fw: packets completions received from fw * @cce_classified:Number of packets classified by CCE @@ -1792,6 +1793,7 @@ struct cdp_tx_ingress_stats { /* headroom insufficient */ uint32_t headroom_insufficient; uint32_t fail_per_pkt_vdev_id_check; + uint32_t drop_ingress; } dropped; /* Mesh packets info */ diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 451323f65a..5f4c0bc0dd 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -2149,6 +2149,12 @@ extern QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid, uint32_t ba_window_size, uint32_t start_seq); +#ifdef DP_UMAC_HW_RESET_SUPPORT +void dp_pause_reo_send_cmd(struct dp_soc *soc); + +void dp_resume_reo_send_cmd(struct dp_soc *soc); +#endif + extern QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, enum hal_reo_cmd_type type, struct hal_reo_cmd_params *params, void (*callback_fn), void *data); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 42619e1fc6..a917d5c7f4 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -268,11 +268,14 @@ static QDF_STATUS dp_alloc_tx_ring_pair_by_index(struct dp_soc *soc, static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc, enum hal_ring_type ring_type, int ring_num); - #ifdef FEATURE_AST void dp_print_mlo_ast_stats(struct dp_soc *soc); #endif +#ifdef DP_UMAC_HW_RESET_SUPPORT +static QDF_STATUS dp_umac_reset_handle_pre_reset(struct dp_soc *soc); +#endif + #define DP_INTR_POLL_TIMER_MS 5 #define MON_VDEV_TIMER_INIT 0x1 @@ -2551,10 +2554,12 @@ budget_done: * @dp_ctx: Datapath SoC handle * @dp_budget: Number of SRNGs which can be processed in a single attempt * without rescheduling + * @cpu: cpu id * * Return: remaining budget/quota for the soc device */ -static uint32_t dp_service_near_full_srngs(void *dp_ctx, uint32_t dp_budget) +static +uint32_t dp_service_near_full_srngs(void *dp_ctx, uint32_t dp_budget, int cpu) { struct dp_intr *int_ctx = (struct dp_intr *)dp_ctx; struct dp_soc *soc = int_ctx->soc; @@ -2574,10 +2579,11 @@ static uint32_t dp_service_near_full_srngs(void *dp_ctx, uint32_t dp_budget) * dp_service_srngs() - Top level interrupt handler for DP Ring interrupts * @dp_ctx: DP SOC handle * @budget: Number of frames/descriptors that can be processed in one shot + * @cpu: CPU on which this instance is running * * Return: remaining budget/quota for the soc device */ -static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) +static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget, int cpu) { struct dp_intr *int_ctx = (struct dp_intr *)dp_ctx; struct dp_intr_stats *intr_stats = &int_ctx->intr_stats; @@ -2593,6 +2599,8 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) uint8_t reo_status_mask = int_ctx->reo_status_ring_mask; uint32_t remaining_quota = dp_budget; + qdf_atomic_set_bit(cpu, &soc->service_rings_running); + dp_verbose_debug("tx %x rx %x rx_err %x rx_wbm_rel %x reo_status %x rx_mon_ring %x host2rxdma %x rxdma2host %x\n", tx_mask, rx_mask, rx_err_mask, rx_wbm_rel_mask, reo_status_mask, @@ -2700,6 +2708,11 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) intr_stats->num_masks++; budget_done: + qdf_atomic_clear_bit(cpu, &soc->service_rings_running); + + if (soc->notify_fw_callback) + soc->notify_fw_callback(soc); + return dp_budget - budget; } @@ -2712,7 +2725,7 @@ budget_done: * * Return: remaining budget/quota for the soc device */ -static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) +static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget, int cpu) { struct dp_intr *int_ctx = (struct dp_intr *)dp_ctx; struct dp_intr_stats *intr_stats = &int_ctx->intr_stats; @@ -2767,6 +2780,7 @@ static void dp_interrupt_timer(void *arg) uint32_t lmac_iter; int max_mac_rings = wlan_cfg_get_num_mac_rings(pdev->wlan_cfg_ctx); enum reg_wifi_band mon_band; + int cpu = smp_processor_id(); /* * this logic makes all data path interfacing rings (UMAC/LMAC) @@ -2777,7 +2791,8 @@ static void dp_interrupt_timer(void *arg) if (qdf_atomic_read(&soc->cmn_init_done)) { for (i = 0; i < wlan_cfg_get_num_contexts( soc->wlan_cfg_ctx); i++) - dp_service_srngs(&soc->intr_ctx[i], 0xffff); + dp_service_srngs(&soc->intr_ctx[i], 0xffff, + cpu); qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS); } @@ -6507,6 +6522,17 @@ QDF_STATUS dp_soc_target_ppe_rxole_rxdma_cfg(struct dp_soc *soc) } #endif /* WLAN_SUPPORT_PPEDS */ +#ifdef DP_UMAC_HW_RESET_SUPPORT +static void dp_register_umac_reset_handlers(struct dp_soc *soc) +{ + dp_umac_reset_register_rx_action_callback(soc, + dp_umac_reset_handle_pre_reset, UMAC_RESET_ACTION_DO_PRE_RESET); +} +#else +static void dp_register_umac_reset_handlers(struct dp_soc *soc) +{ +} +#endif /* * dp_soc_attach_target_wifi3() - SOC initialization in the target * @cdp_soc: Opaque Datapath SOC handle @@ -6546,6 +6572,8 @@ dp_soc_attach_target_wifi3(struct cdp_soc_t *cdp_soc) return status; } + dp_register_umac_reset_handlers(soc); + status = dp_rx_target_fst_config(soc); if (status != QDF_STATUS_SUCCESS && status != QDF_STATUS_E_NOSUPPORT) { @@ -6911,6 +6939,33 @@ fail0: } #ifndef QCA_HOST_MODE_WIFI_DISABLED +/** + * dp_vdev_fetch_tx_handlers() - Fetch Tx handlers + * @vdev: struct dp_vdev * + * @soc: struct dp_soc * + * @ctx: struct ol_txrx_hardtart_ctxt * + */ +static inline void dp_vdev_fetch_tx_handler(struct dp_vdev *vdev, + struct dp_soc *soc, + struct ol_txrx_hardtart_ctxt *ctx) +{ + /* Enable vdev_id check only for ap, if flag is enabled */ + if (vdev->mesh_vdev) + ctx->tx = dp_tx_send_mesh; + else if ((wlan_cfg_is_tx_per_pkt_vdev_id_check_enabled(soc->wlan_cfg_ctx)) && + (vdev->opmode == wlan_op_mode_ap)) + ctx->tx = dp_tx_send_vdev_id_check; + else + ctx->tx = dp_tx_send; + + /* Avoid check in regular exception Path */ + if ((wlan_cfg_is_tx_per_pkt_vdev_id_check_enabled(soc->wlan_cfg_ctx)) && + (vdev->opmode == wlan_op_mode_ap)) + ctx->tx_exception = dp_tx_send_exception_vdev_id_check; + else + ctx->tx_exception = dp_tx_send_exception; +} + /** * dp_vdev_register_tx_handler() - Register Tx handler * @vdev: struct dp_vdev * @@ -6921,21 +6976,12 @@ static inline void dp_vdev_register_tx_handler(struct dp_vdev *vdev, struct dp_soc *soc, struct ol_txrx_ops *txrx_ops) { - /* Enable vdev_id check only for ap, if flag is enabled */ - if (vdev->mesh_vdev) - txrx_ops->tx.tx = dp_tx_send_mesh; - else if ((wlan_cfg_is_tx_per_pkt_vdev_id_check_enabled(soc->wlan_cfg_ctx)) && - (vdev->opmode == wlan_op_mode_ap)) - txrx_ops->tx.tx = dp_tx_send_vdev_id_check; - else - txrx_ops->tx.tx = dp_tx_send; + struct ol_txrx_hardtart_ctxt ctx = {0}; - /* Avoid check in regular exception Path */ - if ((wlan_cfg_is_tx_per_pkt_vdev_id_check_enabled(soc->wlan_cfg_ctx)) && - (vdev->opmode == wlan_op_mode_ap)) - txrx_ops->tx.tx_exception = dp_tx_send_exception_vdev_id_check; - else - txrx_ops->tx.tx_exception = dp_tx_send_exception; + dp_vdev_fetch_tx_handler(vdev, soc, &ctx); + + txrx_ops->tx.tx = ctx.tx; + txrx_ops->tx.tx_exception = ctx.tx_exception; dp_info("Configure tx_vdev_id_chk_handler Feature Flag: %d and mode:%d for vdev_id:%d", wlan_cfg_is_tx_per_pkt_vdev_id_check_enabled(soc->wlan_cfg_ctx), @@ -6947,6 +6993,12 @@ static inline void dp_vdev_register_tx_handler(struct dp_vdev *vdev, struct ol_txrx_ops *txrx_ops) { } + +static inline void dp_vdev_fetch_tx_handler(struct dp_vdev *vdev, + struct dp_soc *soc, + struct ol_txrx_hardtart_ctxt *ctx) +{ +} #endif /* QCA_HOST_MODE_WIFI_DISABLED */ /** @@ -12660,6 +12712,7 @@ static void dp_drain_txrx(struct cdp_soc_t *soc_handle) uint32_t budget = 0xffff; uint32_t val; int i; + int cpu = smp_processor_id(); cur_tx_limit = soc->wlan_cfg_ctx->tx_comp_loop_pkt_limit; cur_rx_limit = soc->wlan_cfg_ctx->rx_reap_loop_pkt_limit; @@ -12673,7 +12726,7 @@ static void dp_drain_txrx(struct cdp_soc_t *soc_handle) dp_update_soft_irq_limits(soc, budget, budget); for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) - dp_service_srngs(&soc->intr_ctx[i], budget); + dp_service_srngs(&soc->intr_ctx[i], budget, cpu); dp_update_soft_irq_limits(soc, cur_tx_limit, cur_rx_limit); @@ -12685,6 +12738,184 @@ static void dp_drain_txrx(struct cdp_soc_t *soc_handle) } #endif +#ifdef DP_UMAC_HW_RESET_SUPPORT +/** + * dp_reset_interrupt_ring_masks(): Reset rx interrupt masks + * @soc: dp soc handle + * + * Return: void + */ +static void dp_reset_interrupt_ring_masks(struct dp_soc *soc) +{ + struct dp_intr_bkp *intr_bkp; + struct dp_intr *intr_ctx; + int num_ctxt = wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); + int i; + + intr_bkp = + (struct dp_intr_bkp *)qdf_mem_malloc_atomic(sizeof(struct dp_intr_bkp) * + num_ctxt); + + qdf_assert_always(intr_bkp); + + soc->umac_reset_ctx.intr_ctx_bkp = intr_bkp; + for (i = 0; i < num_ctxt; i++) { + intr_ctx = &soc->intr_ctx[i]; + + intr_bkp->tx_ring_mask = intr_ctx->tx_ring_mask; + intr_bkp->rx_ring_mask = intr_ctx->rx_ring_mask; + intr_bkp->rx_mon_ring_mask = intr_ctx->rx_mon_ring_mask; + intr_bkp->rx_err_ring_mask = intr_ctx->rx_err_ring_mask; + intr_bkp->rx_wbm_rel_ring_mask = intr_ctx->rx_wbm_rel_ring_mask; + intr_bkp->reo_status_ring_mask = intr_ctx->reo_status_ring_mask; + intr_bkp->rxdma2host_ring_mask = intr_ctx->rxdma2host_ring_mask; + intr_bkp->host2rxdma_ring_mask = intr_ctx->host2rxdma_ring_mask; + intr_bkp->host2rxdma_mon_ring_mask = + intr_ctx->host2rxdma_mon_ring_mask; + intr_bkp->tx_mon_ring_mask = intr_ctx->tx_mon_ring_mask; + + intr_ctx->tx_ring_mask = 0; + intr_ctx->rx_ring_mask = 0; + intr_ctx->rx_mon_ring_mask = 0; + intr_ctx->rx_err_ring_mask = 0; + intr_ctx->rx_wbm_rel_ring_mask = 0; + intr_ctx->reo_status_ring_mask = 0; + intr_ctx->rxdma2host_ring_mask = 0; + intr_ctx->host2rxdma_ring_mask = 0; + intr_ctx->host2rxdma_mon_ring_mask = 0; + intr_ctx->tx_mon_ring_mask = 0; + + intr_bkp = (struct dp_intr_bkp *)((char *)intr_bkp + + (sizeof(struct dp_intr_bkp))); + } +} + +/** + * dp_resume_tx_hardstart(): Restore the old Tx hardstart functions + * @soc: dp soc handle + * + * Return: void + */ +static void dp_resume_tx_hardstart(struct dp_soc *soc) +{ + struct dp_vdev *vdev; + struct ol_txrx_hardtart_ctxt ctxt = {0}; + struct cdp_ctrl_objmgr_psoc *psoc = soc->ctrl_psoc; + int i; + + for (i = 0; i < MAX_PDEV_CNT; i++) { + struct dp_pdev *pdev = soc->pdev_list[i]; + + if (!pdev) + continue; + + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + uint8_t vdev_id = vdev->vdev_id; + + dp_vdev_fetch_tx_handler(vdev, soc, &ctxt); + soc->cdp_soc.ol_ops->dp_update_tx_hardstart(psoc, + vdev_id, + &ctxt); + } + } +} + +/** + * dp_pause_tx_hardstart(): Register Tx hardstart functions to drop packets + * @soc: dp soc handle + * + * Return: void + */ +static void dp_pause_tx_hardstart(struct dp_soc *soc) +{ + struct dp_vdev *vdev; + struct ol_txrx_hardtart_ctxt ctxt; + struct cdp_ctrl_objmgr_psoc *psoc = soc->ctrl_psoc; + int i; + + ctxt.tx = &dp_tx_drop; + ctxt.tx_exception = &dp_tx_exc_drop; + + for (i = 0; i < MAX_PDEV_CNT; i++) { + struct dp_pdev *pdev = soc->pdev_list[i]; + + if (!pdev) + continue; + + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + uint8_t vdev_id = vdev->vdev_id; + + soc->cdp_soc.ol_ops->dp_update_tx_hardstart(psoc, + vdev_id, + &ctxt); + } + } +} + +/** + * dp_unregister_notify_umac_pre_reset_fw_callback(): unregister notify_fw_cb + * @soc: dp soc handle + * + * Return: void + */ +static inline +void dp_unregister_notify_umac_pre_reset_fw_callback(struct dp_soc *soc) +{ + soc->notify_fw_callback = NULL; +} + +/** + * dp_check_n_notify_umac_prereset_done(): Send pre reset done to firmware + * @soc: dp soc handle + * + * Return: void + */ +static inline +void dp_check_n_notify_umac_prereset_done(struct dp_soc *soc) +{ + /* Some Cpu(s) is processing the umac rings*/ + if (soc->service_rings_running) + return; + + /* Notify the firmware that Umac pre reset is complete */ + dp_umac_reset_notify_action_completion(soc, + UMAC_RESET_ACTION_DO_PRE_RESET); + + /* Unregister the callback */ + dp_unregister_notify_umac_pre_reset_fw_callback(soc); +} + +/** + * dp_register_notify_umac_pre_reset_fw_callback(): register notify_fw_cb + * @soc: dp soc handle + * + * Return: void + */ +static inline +void dp_register_notify_umac_pre_reset_fw_callback(struct dp_soc *soc) +{ + soc->notify_fw_callback = dp_check_n_notify_umac_prereset_done; +} + +/** + * dp_umac_reset_handle_pre_reset(): Handle Umac prereset interrupt from FW + * @soc: dp soc handle + * + * Return: QDF_STATUS + */ +static QDF_STATUS dp_umac_reset_handle_pre_reset(struct dp_soc *soc) +{ + dp_reset_interrupt_ring_masks(soc); + + dp_pause_tx_hardstart(soc); + dp_pause_reo_send_cmd(soc); + + dp_check_n_notify_umac_prereset_done(soc); + + return QDF_STATUS_SUCCESS; +} +#endif + #ifdef WLAN_FEATURE_PKT_CAPTURE_V2 static void dp_set_pkt_capture_mode(struct cdp_soc_t *soc_handle, bool val) diff --git a/dp/wifi3.0/dp_reo.c b/dp/wifi3.0/dp_reo.c index 6071117021..46f4d674b2 100644 --- a/dp/wifi3.0/dp_reo.c +++ b/dp/wifi3.0/dp_reo.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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 @@ -64,6 +65,30 @@ void dp_reo_cmd_srng_event_record(struct dp_soc *soc, } #endif /*WLAN_FEATURE_DP_EVENT_HISTORY */ +#ifdef DP_UMAC_HW_RESET_SUPPORT +/** + * dp_pause_reo_send_cmd() - Pause Reo send commands. + * @soc: dp soc + * + * Return: status + */ +void dp_pause_reo_send_cmd(struct dp_soc *soc) +{ + hal_unregister_reo_send_cmd(soc->hal_soc); +} + +/** + * dp_resume_reo_send_cmd() - Resume Reo send commands. + * @soc: dp soc + * + * Return: status + */ +void dp_resume_reo_send_cmd(struct dp_soc *soc) +{ + hal_register_reo_send_cmd(soc->hal_soc); +} +#endif + QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, enum hal_reo_cmd_type type, struct hal_reo_cmd_params *params, void (*callback_fn), void *data) diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index e29cdafd3e..94ea4a780e 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -7084,6 +7084,8 @@ void dp_txrx_path_stats(struct dp_soc *soc) pdev->stats.tx_i.dropped.fail_per_pkt_vdev_id_check); DP_PRINT_STATS("DMA Error: %u", pdev->stats.tx_i.dropped.dma_error); + DP_PRINT_STATS("Drop Ingress: %u", + pdev->stats.tx_i.dropped.drop_ingress); DP_PRINT_STATS("Dropped in hardware:"); DP_PRINT_STATS("total packets dropped: %u", @@ -7345,6 +7347,8 @@ dp_print_pdev_tx_stats(struct dp_pdev *pdev) pdev->stats.tx_i.dropped.fail_per_pkt_vdev_id_check); DP_PRINT_STATS(" Resources Full = %u", pdev->stats.tx_i.dropped.res_full); + DP_PRINT_STATS(" Drop Ingress = %u", + pdev->stats.tx_i.dropped.drop_ingress); DP_PRINT_STATS("Tx failed = %u", pdev->stats.tx.tx_failed); DP_PRINT_STATS(" FW removed Pkts = %u", @@ -8628,6 +8632,7 @@ void dp_update_vdev_ingress_stats(struct dp_vdev *tgtobj) tgtobj->stats.tx_i.dropped.fail_per_pkt_vdev_id_check + tgtobj->stats.tx_i.dropped.desc_na.num + tgtobj->stats.tx_i.dropped.res_full + + tgtobj->stats.tx_i.dropped.drop_ingress + tgtobj->stats.tx_i.dropped.headroom_insufficient; } @@ -8672,6 +8677,7 @@ void dp_update_pdev_ingress_stats(struct dp_pdev *tgtobj, DP_STATS_AGGR(tgtobj, srcobj, tx_i.dropped.fail_per_pkt_vdev_id_check); DP_STATS_AGGR(tgtobj, srcobj, tx_i.dropped.desc_na.num); DP_STATS_AGGR(tgtobj, srcobj, tx_i.dropped.res_full); + DP_STATS_AGGR(tgtobj, srcobj, tx_i.dropped.drop_ingress); DP_STATS_AGGR(tgtobj, srcobj, tx_i.dropped.headroom_insufficient); DP_STATS_AGGR(tgtobj, srcobj, tx_i.cce_classified); DP_STATS_AGGR(tgtobj, srcobj, tx_i.cce_classified_raw); @@ -8690,6 +8696,7 @@ void dp_update_pdev_ingress_stats(struct dp_pdev *tgtobj, tgtobj->stats.tx_i.dropped.fail_per_pkt_vdev_id_check + tgtobj->stats.tx_i.dropped.desc_na.num + tgtobj->stats.tx_i.dropped.res_full + + tgtobj->stats.tx_i.dropped.drop_ingress + tgtobj->stats.tx_i.dropped.headroom_insufficient; } diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 6224d11c9e..bd20a38e0f 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -3292,7 +3292,53 @@ void dp_tx_prefetch_nbuf_data(qdf_nbuf_t nbuf) } #endif -/** +#ifdef DP_UMAC_HW_RESET_SUPPORT +/* + * dp_tx_drop() - Drop the frame on a given VAP + * @soc: DP soc handle + * @vdev_id: id of DP vdev handle + * @nbuf: skb + * + * Drop all the incoming packets + * + * Return: nbuf + * + */ +qdf_nbuf_t dp_tx_drop(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t nbuf) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = NULL; + + vdev = soc->vdev_id_map[vdev_id]; + if (qdf_unlikely(!vdev)) + return nbuf; + + DP_STATS_INC(vdev, tx_i.dropped.drop_ingress, 1); + return nbuf; +} + +/* + * dp_tx_exc_drop() - Drop the frame on a given VAP + * @soc: DP soc handle + * @vdev_id: id of DP vdev handle + * @nbuf: skb + * @tx_exc_metadata: Handle that holds exception path meta data + * + * Drop all the incoming packets + * + * Return: nbuf + * + */ +qdf_nbuf_t dp_tx_exc_drop(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t nbuf, + struct cdp_tx_exception_metadata *tx_exc_metadata) +{ + return dp_tx_drop(soc_hdl, vdev_id, nbuf); +} +#endif + +/* * dp_tx_send() - Transmit a frame on a given VAP * @soc: DP soc handle * @vdev_id: id of DP vdev handle diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h index 5cbac8bcb0..87c641c5b4 100644 --- a/dp/wifi3.0/dp_tx.h +++ b/dp/wifi3.0/dp_tx.h @@ -271,6 +271,13 @@ void dp_tx_update_peer_basic_stats(struct dp_txrx_peer *txrx_peer, uint32_t length, uint8_t tx_status, bool update); +#ifdef DP_UMAC_HW_RESET_SUPPORT +qdf_nbuf_t dp_tx_drop(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t nbuf); + +qdf_nbuf_t dp_tx_exc_drop(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t nbuf, + struct cdp_tx_exception_metadata *tx_exc_metadata); +#endif #ifndef QCA_HOST_MODE_WIFI_DISABLED /** * dp_tso_attach() - TSO Attach handler diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 3fd96a69c3..3365a77d3b 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -942,6 +942,37 @@ struct dp_intr_stats { uint32_t num_tx_mon_ring_masks; }; +#ifdef DP_UMAC_HW_RESET_SUPPORT +/** + * struct dp_intr_bkp - DP per interrupt context ring masks old state + * @tx_ring_mask: WBM Tx completion rings (0-2) associated with this napi ctxt + * @rx_ring_mask: Rx REO rings (0-3) associated with this interrupt context + * @rx_mon_ring_mask: Rx monitor ring mask (0-2) + * @rx_err_ring_mask: REO Exception Ring + * @rx_wbm_rel_ring_mask: WBM2SW Rx Release Ring + * @reo_status_ring_mask: REO command response ring + * @rxdma2host_ring_mask: RXDMA to host destination ring + * @host2rxdma_ring_mask: Host to RXDMA buffer ring + * @host2rxdma_mon_ring_mask: Host to RXDMA monitor buffer ring + * @host2txmon_ring_mask: Tx monitor buffer ring + * @tx_mon_ring_mask: Tx monitor ring mask (0-2) + * + */ +struct dp_intr_bkp { + uint8_t tx_ring_mask; + uint8_t rx_ring_mask; + uint8_t rx_mon_ring_mask; + uint8_t rx_err_ring_mask; + uint8_t rx_wbm_rel_ring_mask; + uint8_t reo_status_ring_mask; + uint8_t rxdma2host_ring_mask; + uint8_t host2rxdma_ring_mask; + uint8_t host2rxdma_mon_ring_mask; + uint8_t host2txmon_ring_mask; + uint8_t tx_mon_ring_mask; +}; +#endif + /* per interrupt context */ struct dp_intr { uint8_t tx_ring_mask; /* WBM Tx completion rings (0-2) @@ -1925,6 +1956,13 @@ enum sysfs_printing_mode { PRINTING_MODE_ENABLED }; +/** + * @typedef tx_pause_callback + * @brief OSIF function registered with the data path + */ + +typedef void (*notify_pre_reset_fw_callback)(struct dp_soc *soc); + #ifdef WLAN_SYSFS_DP_STATS /** * struct sysfs_stats_config: Data structure holding stats sysfs config. @@ -2126,6 +2164,10 @@ struct dp_soc { struct dp_txrx_pool_stats pool_stats; #endif /* !QCA_LL_TX_FLOW_CONTROL_V2 */ + notify_pre_reset_fw_callback notify_fw_callback; + + unsigned long service_rings_running; + uint32_t wbm_idle_scatter_buf_size; /* VDEVs on this SOC */ diff --git a/dp/wifi3.0/dp_umac_reset.h b/dp/wifi3.0/dp_umac_reset.h index bf27456b30..e53a608724 100644 --- a/dp/wifi3.0/dp_umac_reset.h +++ b/dp/wifi3.0/dp_umac_reset.h @@ -134,6 +134,7 @@ struct umac_reset_rx_actions { * @current_state: current state of the UMAC reset state machine * @shmem_exp_magic_num: Expected magic number in the shared memory * @rx_actions: callbacks for handling UMAC reset actions + * @intr_ctx_bkp: DP Interrupts ring masks backup */ struct dp_soc_umac_reset_ctx { qdf_dma_addr_t shmem_paddr_unaligned; @@ -145,6 +146,7 @@ struct dp_soc_umac_reset_ctx { enum umac_reset_state current_state; uint32_t shmem_exp_magic_num; struct umac_reset_rx_actions rx_actions; + struct dp_intr_bkp *intr_ctx_bkp; }; /** diff --git a/hal/wifi3.0/be/hal_be_generic_api.c b/hal/wifi3.0/be/hal_be_generic_api.c index d7ccba5b7b..1f3c0c4598 100644 --- a/hal/wifi3.0/be/hal_be_generic_api.c +++ b/hal/wifi3.0/be/hal_be_generic_api.c @@ -775,6 +775,32 @@ hal_rx_wbm_rel_buf_paddr_get_be(hal_ring_desc_t rx_desc, } #endif +#ifdef DP_UMAC_HW_RESET_SUPPORT +/** + * hal_unregister_reo_send_cmd_be() - Unregister Reo send command callback. + * @hal_soc_hdl: HAL soc handle + * + * Return: status + */ +static +void hal_unregister_reo_send_cmd_be(struct hal_soc *hal_soc) +{ + hal_soc->ops->hal_reo_send_cmd = NULL; +} + +/** + * hal_register_reo_send_cmd_be() - Register Reo send command callback. + * @hal_soc_hdl: HAL soc handle + * + * Return: status + */ +static +void hal_register_reo_send_cmd_be(struct hal_soc *hal_soc) +{ + hal_soc->ops->hal_reo_send_cmd = hal_reo_send_cmd_be; +} +#endif + /** * hal_hw_txrx_default_ops_attach_be() - Attach the default hal ops for * beryllium chipsets. @@ -828,4 +854,9 @@ void hal_hw_txrx_default_ops_attach_be(struct hal_soc *hal_soc) hal_rx_msdu_ext_desc_info_get_ptr_be; hal_soc->ops->hal_msdu_desc_info_set = hal_msdu_desc_info_set_be; hal_soc->ops->hal_mpdu_desc_info_set = hal_mpdu_desc_info_set_be; +#ifdef DP_UMAC_HW_RESET_SUPPORT + hal_soc->ops->hal_unregister_reo_send_cmd = + hal_unregister_reo_send_cmd_be; + hal_soc->ops->hal_register_reo_send_cmd = hal_register_reo_send_cmd_be; +#endif } diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 06ed043826..d55cc76bd5 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -1074,6 +1074,10 @@ struct hal_hw_txrx_ops { uint32_t nbuf_len); void (*hal_mpdu_desc_info_set)(hal_soc_handle_t hal_soc_hdl, void *mpdu_desc_info, uint32_t seq_no); +#ifdef DP_UMAC_HW_RESET_SUPPORT + void (*hal_unregister_reo_send_cmd)(struct hal_soc *hal_soc); + void (*hal_register_reo_send_cmd)(struct hal_soc *hal_soc); +#endif uint32_t (*hal_rx_tlv_sgi_get)(uint8_t *buf); uint32_t (*hal_rx_tlv_get_freq)(uint8_t *buf); uint8_t (*hal_rx_msdu_get_keyid)(uint8_t *buf); diff --git a/hal/wifi3.0/hal_reo.h b/hal/wifi3.0/hal_reo.h index 90ff8fce5f..90cfa9ddd0 100644 --- a/hal/wifi3.0/hal_reo.h +++ b/hal/wifi3.0/hal_reo.h @@ -567,7 +567,7 @@ hal_uniform_desc_hdr_setup(uint32_t *desc, uint32_t owner, uint32_t buffer_type) /** * hal_reo_send_cmd() - Send reo cmd using the params provided. * @hal_soc_hdl: HAL soc handle - * @hal_soc_hdl: srng handle + * @hal_ring_hdl: srng handle * @cmd: cmd ID * @cmd_params: command params * @@ -594,6 +594,49 @@ hal_reo_send_cmd(hal_soc_handle_t hal_soc_hdl, return -EINVAL; } +#ifdef DP_UMAC_HW_RESET_SUPPORT +/** + * hal_register_reo_send_cmd() - Register Reo send command callback. + * @hal_soc_hdl: HAL soc handle + * + * Return: void + */ +static inline void hal_register_reo_send_cmd(hal_soc_handle_t hal_soc_hdl) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return; + } + + if (hal_soc->ops->hal_register_reo_send_cmd) + hal_soc->ops->hal_register_reo_send_cmd(hal_soc); +} + +/** + * hal_unregister_reo_send_cmd() - Unregister Reo send command callback. + * @hal_soc_hdl: HAL soc handle + * + * Return: void + */ +static inline void +hal_unregister_reo_send_cmd(hal_soc_handle_t hal_soc_hdl) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return; + } + + if (hal_soc->ops->hal_unregister_reo_send_cmd) + return hal_soc->ops->hal_unregister_reo_send_cmd(hal_soc); +} +#endif + static inline QDF_STATUS hal_reo_status_update(hal_soc_handle_t hal_soc_hdl, hal_ring_desc_t reo_desc, void *st_handle,