qcacmn: Optimize force free logic in dp_find_missing_tx_comp()
Currently during runtime suspend, in dp_find_missing_tx_comp(), TX descriptors are freed forcefully if the TX completions for those descriptors do not arrive within 60 seconds. In certain rare corner cases, there is a chance of TX buffer (that is in the enqueue path) getting freed in the TX completion path due to delayed completions. This results in NULL pointer dereference. Following is the sequence of events for such a case, 1. dp_find_missing_tx_comp() frees a TX descriptor 2. Different buffer gets attached to the same TX descriptor 3. Delayed completion for the previous TX arrives and frees the buffer in point 2. Defer the free in dp_find_missing_tx_comp() when there is a delta in HP/TP for the TX/COMP rings. If HP & TP are not same, then there is high chance of processing the delayed completion beforehand, thus avoiding the aforementioned race. Change-Id: Ia835928f85ea0f79d0187a55333cb8959d0a72e9 CRs-Fixed: 3721341
This commit is contained in:

committed by
Ravindra Konda

parent
f7205e9662
commit
7e58813e0e
@@ -12689,6 +12689,42 @@ static struct cdp_sawf_ops dp_ops_sawf = {
|
||||
#ifdef DP_TX_TRACKING
|
||||
|
||||
#define DP_TX_COMP_MAX_LATENCY_MS 60000
|
||||
|
||||
static bool dp_check_pending_tx(struct dp_soc *soc)
|
||||
{
|
||||
hal_soc_handle_t hal_soc = soc->hal_soc;
|
||||
uint32_t hp, tp, i;
|
||||
|
||||
for (i = 0; i < soc->num_tcl_data_rings; i++) {
|
||||
if (dp_ipa_is_ring_ipa_tx(soc, i))
|
||||
continue;
|
||||
|
||||
hal_get_sw_hptp(hal_soc, soc->tcl_data_ring[i].hal_srng,
|
||||
&tp, &hp);
|
||||
|
||||
if (hp != tp) {
|
||||
dp_info_rl("Pending transactions in TCL DATA Ring[%d] hp=0x%x, tp=0x%x",
|
||||
i, hp, tp);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (wlan_cfg_get_wbm_ring_num_for_index(soc->wlan_cfg_ctx, i) ==
|
||||
INVALID_WBM_RING_NUM)
|
||||
continue;
|
||||
|
||||
hal_get_sw_hptp(hal_soc, soc->tx_comp_ring[i].hal_srng,
|
||||
&tp, &hp);
|
||||
|
||||
if (hp != tp) {
|
||||
dp_info_rl("Pending transactions in TX comp Ring[%d] hp=0x%x, tp=0x%x",
|
||||
i, hp, tp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_tx_comp_delay_check() - calculate time latency for tx completion per pkt
|
||||
* @tx_desc: tx descriptor
|
||||
@@ -12742,6 +12778,9 @@ void dp_find_missing_tx_comp(struct dp_soc *soc)
|
||||
struct dp_tx_desc_s *tx_desc = NULL;
|
||||
struct dp_tx_desc_pool_s *tx_desc_pool = NULL;
|
||||
|
||||
if (dp_check_pending_tx(soc))
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_TXDESC_POOLS; i++) {
|
||||
tx_desc_pool = &soc->tx_desc[i];
|
||||
if (!(tx_desc_pool->pool_size) ||
|
||||
|
Reference in New Issue
Block a user