diff --git a/dp/wifi3.0/dp_ipa.c b/dp/wifi3.0/dp_ipa.c index 465c5c2c4c..19c12c73d0 100644 --- a/dp/wifi3.0/dp_ipa.c +++ b/dp/wifi3.0/dp_ipa.c @@ -1778,11 +1778,40 @@ QDF_STATUS dp_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) return QDF_STATUS_SUCCESS; } +/* + * dp_ipa_get_tx_comp_pending_check() - Check if tx completions are pending. + * @soc: DP pdev Context + * + * Ring full condition is checked to find if buffers are left for + * processing as host only allocates buffers in this ring and IPA HW processes + * the buffer. + * + * Return: True if tx completions are pending + */ +static bool dp_ipa_get_tx_comp_pending_check(struct dp_soc *soc) +{ + struct dp_srng *tx_comp_ring = + &soc->tx_comp_ring[IPA_TX_COMP_RING_IDX]; + uint32_t hp, tp, entry_size, buf_cnt; + + hal_get_hw_hptp(soc->hal_soc, tx_comp_ring->hal_srng, &hp, &tp, + WBM2SW_RELEASE); + entry_size = hal_srng_get_entrysize(soc->hal_soc, WBM2SW_RELEASE) >> 2; + + if (hp > tp) + buf_cnt = (hp - tp) / entry_size; + else + buf_cnt = (tx_comp_ring->num_entries - tp + hp) / entry_size; + + return (soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt != buf_cnt); +} + QDF_STATUS dp_ipa_disable_pipes(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 = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + int timeout = TX_COMP_DRAIN_WAIT_TIMEOUT_MS; QDF_STATUS result; if (!pdev) { @@ -1790,6 +1819,15 @@ QDF_STATUS dp_ipa_disable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) return QDF_STATUS_E_FAILURE; } + while (dp_ipa_get_tx_comp_pending_check(soc)) { + qdf_sleep(TX_COMP_DRAIN_WAIT_MS); + timeout -= TX_COMP_DRAIN_WAIT_MS; + if (timeout <= 0) { + dp_err("Tx completions pending. Force Disabling pipes"); + break; + } + } + result = qdf_ipa_wdi_disable_pipes(); if (result) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, diff --git a/dp/wifi3.0/dp_ipa.h b/dp/wifi3.0/dp_ipa.h index bfefc509e3..353414c168 100644 --- a/dp/wifi3.0/dp_ipa.h +++ b/dp/wifi3.0/dp_ipa.h @@ -24,6 +24,10 @@ #define IPA_REO_DEST_RING_IDX 3 #define IPA_RX_REFILL_BUF_RING_IDX 2 +/* Adding delay before disabling ipa pipes if any Tx Completions are pending */ +#define TX_COMP_DRAIN_WAIT_MS 50 +#define TX_COMP_DRAIN_WAIT_TIMEOUT_MS 200 + /** * struct dp_ipa_uc_tx_hdr - full tx header registered to IPA hardware * @eth: ether II header