diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index 6ffd5433576c..3fc8d89427dc 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -2709,4 +2709,25 @@ cdp_wds_ext_set_peer_rx(ol_txrx_soc_handle soc, uint8_t vdev_id, (soc, vdev_id, mac, rx, osif_peer); } #endif /* QCA_SUPPORT_WDS_EXTENDED */ + +/** + * cdp_drain_txrx() - drain TX/RX SRNGs + * @soc: opaque soc handle + */ +static inline void +cdp_drain_txrx(ol_txrx_soc_handle soc) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_drain) + return; + + return soc->ops->cmn_drv_ops->txrx_drain(soc); +} #endif /* _CDP_TXRX_CMN_H_ */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index f208d1951a96..235dc91012a5 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -566,6 +566,7 @@ struct cdp_cmn_ops { ol_txrx_rx_fp rx, ol_osif_peer_handle osif_peer); #endif /* QCA_SUPPORT_WDS_EXTENDED */ + void (*txrx_drain)(ol_txrx_soc_handle soc); }; struct cdp_ctrl_ops { diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 558cf112545a..c2267781e8de 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -9978,11 +9978,25 @@ void dp_update_rx_soft_irq_limit_params(struct dp_soc *soc, soc->wlan_cfg_ctx->rx_enable_eol_data_check, soc->wlan_cfg_ctx->rx_hp_oos_update_limit); } + +static void dp_update_soft_irq_limits(struct dp_soc *soc, uint32_t tx_limit, + uint32_t rx_limit) +{ + soc->wlan_cfg_ctx->tx_comp_loop_pkt_limit = tx_limit; + soc->wlan_cfg_ctx->rx_reap_loop_pkt_limit = rx_limit; +} + #else static inline void dp_update_rx_soft_irq_limit_params(struct dp_soc *soc, struct cdp_config_params *params) { } + +static inline +void dp_update_soft_irq_limits(struct dp_soc *soc, uint32_t tx_limit, + uint32_t rx_limit) +{ +} #endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */ /** @@ -11016,6 +11030,32 @@ dp_config_full_mon_mode(struct cdp_soc_t *soc_handle, } #endif +#if defined(FEATURE_RUNTIME_PM) || defined(DP_POWER_SAVE) +static void dp_drain_txrx(struct cdp_soc_t *soc_handle) +{ + struct dp_soc *soc = (struct dp_soc *)soc_handle; + uint32_t cur_tx_limit, cur_rx_limit; + uint32_t budget = 0xffff; + int i; + + cur_tx_limit = soc->wlan_cfg_ctx->tx_comp_loop_pkt_limit; + cur_rx_limit = soc->wlan_cfg_ctx->rx_reap_loop_pkt_limit; + + /* Temporarily increase soft irq limits when going to drain + * the UMAC/LMAC SRNGs and restore them after polling. + * Though the budget is on higher side, the TX/RX reaping loops + * will not execute longer as both TX and RX would be suspended + * by the time this API is called. + */ + 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_update_soft_irq_limits(soc, cur_tx_limit, cur_rx_limit); +} +#endif + static struct cdp_cmn_ops dp_ops_cmn = { .txrx_soc_attach_target = dp_soc_attach_target_wifi3, .txrx_vdev_attach = dp_vdev_attach_wifi3, @@ -11114,6 +11154,10 @@ static struct cdp_cmn_ops dp_ops_cmn = { .get_wds_ext_peer_id = dp_wds_ext_get_peer_id, .set_wds_ext_peer_rx = dp_wds_ext_set_peer_rx, #endif /* QCA_SUPPORT_WDS_EXTENDED */ + +#if defined(FEATURE_RUNTIME_PM) || defined(DP_POWER_SAVE) + .txrx_drain = dp_drain_txrx, +#endif }; static struct cdp_ctrl_ops dp_ops_ctrl = { diff --git a/hif/inc/hif.h b/hif/inc/hif.h index d3c3ff4d5533..9e2d3e16fed1 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -1698,4 +1698,36 @@ static inline void hif_config_irq_set_perf_affinity_hint( { } #endif + +/** + * hif_apps_grp_irqs_enable() - enable ext grp irqs + * @hif - HIF opaque context + * + * Return: 0 on success. Error code on failure. + */ +int hif_apps_grp_irqs_enable(struct hif_opaque_softc *hif_ctx); + +/** + * hif_apps_grp_irqs_disable() - disable ext grp irqs + * @hif - HIF opaque context + * + * Return: 0 on success. Error code on failure. + */ +int hif_apps_grp_irqs_disable(struct hif_opaque_softc *hif_ctx); + +/** + * hif_disable_grp_irqs() - disable ext grp irqs + * @hif - HIF opaque context + * + * Return: 0 on success. Error code on failure. + */ +int hif_disable_grp_irqs(struct hif_opaque_softc *scn); + +/** + * hif_enable_grp_irqs() - enable ext grp irqs + * @hif - HIF opaque context + * + * Return: 0 on success. Error code on failure. + */ +int hif_enable_grp_irqs(struct hif_opaque_softc *scn); #endif /* _HIF_H_ */ diff --git a/hif/src/dispatcher/dummy.c b/hif/src/dispatcher/dummy.c index b32a18273276..0d8a66b56f79 100644 --- a/hif/src/dispatcher/dummy.c +++ b/hif/src/dispatcher/dummy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -389,3 +389,23 @@ void hif_dummy_log_bus_info(struct hif_softc *scn, uint8_t *data, unsigned int *offset) { } + +/** + * hif_dummy_enable_grp_irqs - dummy call + * @scn: hif context + * Return: EOPNOTSUPP + */ +int hif_dummy_enable_grp_irqs(struct hif_softc *scn) +{ + return -EOPNOTSUPP; +} + +/** + * hif_dummy_disable_grp_irqs - dummy call + * @scn: hif context + * Return: EOPNOTSUPP + */ +int hif_dummy_disable_grp_irqs(struct hif_softc *scn) +{ + return -EOPNOTSUPP; +} diff --git a/hif/src/dispatcher/dummy.h b/hif/src/dispatcher/dummy.h index d7a28fff7e91..ea66a27a2d00 100644 --- a/hif/src/dispatcher/dummy.h +++ b/hif/src/dispatcher/dummy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -62,3 +62,5 @@ int hif_dummy_addr_in_boundary(struct hif_softc *scn, uint32_t offset); void hif_dummy_config_irq_affinity(struct hif_softc *scn); void hif_dummy_log_bus_info(struct hif_softc *scn, uint8_t *data, unsigned int *offset); +int hif_dummy_enable_grp_irqs(struct hif_softc *scn); +int hif_dummy_disable_grp_irqs(struct hif_softc *scn); diff --git a/hif/src/dispatcher/ipci_api.h b/hif/src/dispatcher/ipci_api.h index 897e21e4e1d2..7952db3dde6b 100644 --- a/hif/src/dispatcher/ipci_api.h +++ b/hif/src/dispatcher/ipci_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -240,4 +240,23 @@ bool hif_ipci_needs_bmi(struct hif_softc *scn); */ const char *hif_ipci_get_irq_name(int irq_no); +/** + * hif_ipci_enable_grp_irqs(): enable grp IRQs + * @scn: struct hif_softc + * + * This function enables grp irqs + * + * Return: 0 if success, error code if failure + */ +int hif_ipci_enable_grp_irqs(struct hif_softc *scn); + +/** + * hif_ipci_disable_grp_irqs(): disable grp IRQs + * @scn: struct hif_softc + * + * This function disables grp irqs + * + * Return: 0 if success, error code if failure + */ +int hif_ipci_disable_grp_irqs(struct hif_softc *scn); #endif /* _IPCI_API_H_ */ diff --git a/hif/src/dispatcher/multibus.c b/hif/src/dispatcher/multibus.c index 0ba0b4db1100..8ca93da4901c 100644 --- a/hif/src/dispatcher/multibus.c +++ b/hif/src/dispatcher/multibus.c @@ -60,6 +60,8 @@ static void hif_initialize_default_ops(struct hif_softc *hif_sc) bus_ops->hif_grp_irq_configure = &hif_dummy_grp_irq_configure; bus_ops->hif_config_irq_affinity = &hif_dummy_config_irq_affinity; + bus_ops->hif_enable_grp_irqs = &hif_dummy_enable_grp_irqs; + bus_ops->hif_disable_grp_irqs = &hif_dummy_enable_grp_irqs; } #define NUM_OPS (sizeof(struct hif_bus_ops) / sizeof(void *)) @@ -617,3 +619,61 @@ void hif_log_bus_info(struct hif_softc *hif_sc, uint8_t *data, hif_sc->bus_ops.hif_log_bus_info(hif_sc, data, offset); } #endif + +int hif_apps_grp_irqs_enable(struct hif_opaque_softc *hif_ctx) +{ + struct hif_exec_context *hif_exec; + struct hif_softc *scn; + int i; + + QDF_BUG(hif_ctx); + scn = HIF_GET_SOFTC(hif_ctx); + if (!scn) + return -EINVAL; + + for (i = 0 ; i < HIF_MAX_GROUP; i++) { + hif_exec = hif_exec_get_ctx(hif_ctx, i); + if (!hif_exec) + continue; + + hif_exec->irq_enable(hif_exec); + } + + return 0; +} + +int hif_apps_grp_irqs_disable(struct hif_opaque_softc *hif_ctx) +{ + struct hif_exec_context *hif_exec; + struct hif_softc *scn; + int i; + + QDF_BUG(hif_ctx); + scn = HIF_GET_SOFTC(hif_ctx); + if (!scn) + return -EINVAL; + + for (i = 0 ; i < HIF_MAX_GROUP; i++) { + hif_exec = hif_exec_get_ctx(hif_ctx, i); + if (!hif_exec) + continue; + + hif_exec->irq_disable(hif_exec); + } + + return 0; +} + +int hif_disable_grp_irqs(struct hif_opaque_softc *scn) +{ + struct hif_softc *hif_sc = HIF_GET_SOFTC(scn); + + return hif_sc->bus_ops.hif_disable_grp_irqs(hif_sc); +} + +int hif_enable_grp_irqs(struct hif_opaque_softc *scn) +{ + struct hif_softc *hif_sc = HIF_GET_SOFTC(scn); + + return hif_sc->bus_ops.hif_enable_grp_irqs(hif_sc); +} diff --git a/hif/src/dispatcher/multibus.h b/hif/src/dispatcher/multibus.h index e797531c391f..3c1f901381b1 100644 --- a/hif/src/dispatcher/multibus.h +++ b/hif/src/dispatcher/multibus.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, 2020-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -88,6 +88,8 @@ struct hif_bus_ops { void (*hif_config_irq_affinity)(struct hif_softc *hif_sc); void (*hif_log_bus_info)(struct hif_softc *scn, uint8_t *data, unsigned int *offset); + int (*hif_enable_grp_irqs)(struct hif_softc *scn); + int (*hif_disable_grp_irqs)(struct hif_softc *scn); }; #ifdef HIF_SNOC diff --git a/hif/src/dispatcher/multibus_ipci.c b/hif/src/dispatcher/multibus_ipci.c index d30fd74b5d9d..bef2a131bd3f 100644 --- a/hif/src/dispatcher/multibus_ipci.c +++ b/hif/src/dispatcher/multibus_ipci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -78,6 +78,8 @@ QDF_STATUS hif_initialize_ipci_ops(struct hif_softc *hif_sc) bus_ops->hif_config_irq_affinity = &hif_dummy_config_irq_affinity; bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info; + bus_ops->hif_enable_grp_irqs = hif_ipci_enable_grp_irqs; + bus_ops->hif_disable_grp_irqs = hif_ipci_disable_grp_irqs; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/ipcie/if_ipci.c b/hif/src/ipcie/if_ipci.c index 4d0bc168f89f..f20a3ce59e27 100644 --- a/hif/src/ipcie/if_ipci.c +++ b/hif/src/ipcie/if_ipci.c @@ -826,3 +826,13 @@ void hif_allow_link_low_power_states(struct hif_opaque_softc *hif) { } #endif + +int hif_ipci_enable_grp_irqs(struct hif_softc *scn) +{ + return hif_apps_grp_irqs_enable(GET_HIF_OPAQUE_HDL(scn)); +} + +int hif_ipci_disable_grp_irqs(struct hif_softc *scn) +{ + return hif_apps_grp_irqs_disable(GET_HIF_OPAQUE_HDL(scn)); +}