summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CORE/HDD/src/wlan_hdd_ipa.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/CORE/HDD/src/wlan_hdd_ipa.c b/CORE/HDD/src/wlan_hdd_ipa.c
index a2742be3575e..37eae808bdc6 100644
--- a/CORE/HDD/src/wlan_hdd_ipa.c
+++ b/CORE/HDD/src/wlan_hdd_ipa.c
@@ -287,6 +287,7 @@ struct hdd_ipa_priv {
struct work_struct rm_work;
enum ipa_client_type prod_client;
+ atomic_t tx_ref_cnt;
uint32_t pending_hw_desc_cnt;
uint32_t hw_desc_cnt;
spinlock_t q_lock;
@@ -893,6 +894,9 @@ static int hdd_ipa_rm_try_release(struct hdd_ipa_priv *hdd_ipa)
if (!hdd_ipa_is_rm_enabled(hdd_ipa))
return 0;
+ if (atomic_read(&hdd_ipa->tx_ref_cnt))
+ return -EAGAIN;
+
spin_lock_bh(&hdd_ipa->q_lock);
if (hdd_ipa->pending_hw_desc_cnt || hdd_ipa->pend_q_cnt) {
spin_unlock_bh(&hdd_ipa->q_lock);
@@ -1138,6 +1142,7 @@ static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa)
adf_os_spinlock_init(&hdd_ipa->rm_lock);
hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
+ atomic_set(&hdd_ipa->tx_ref_cnt, 0);
return ret;
@@ -1553,6 +1558,10 @@ static void hdd_ipa_nbuf_cb(adf_nbuf_t skb)
ipa_free_skb((struct ipa_rx_data *) NBUF_OWNER_PRIV_DATA(skb));
hdd_ipa->stats.num_tx_comp_cnt++;
+
+ atomic_dec(&hdd_ipa->tx_ref_cnt);
+
+ hdd_ipa_rm_try_release(hdd_ipa);
}
static void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt,
@@ -1624,6 +1633,17 @@ static void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt,
return;
}
+ atomic_inc(&hdd_ipa->tx_ref_cnt);
+
+ /*
+ * If PROD resource is not requested here then there may be cases where
+ * IPA hardware may be clocked down because of not having proper
+ * dependency graph between WLAN CONS and modem PROD pipes. Adding the
+ * workaround to request PROD resource while data is going over CONS
+ * pipe to prevent the IPA hardware clockdown.
+ */
+ hdd_ipa_rm_request(hdd_ipa);
+
iface_context->stats.num_tx++;
}
@@ -2373,6 +2393,9 @@ static ssize_t hdd_ipa_debugfs_read_ipa_stats(struct file *file,
len += scnprintf(buf + len, buf_len - len, "%30s: %s\n", "rm_state",
hdd_ipa_rm_state_to_str(hdd_ipa->rm_state));
+ len += scnprintf(buf + len, buf_len - len, "%30s: %d\n", "tx_ref_cnt",
+ atomic_read(&hdd_ipa->tx_ref_cnt));
+
len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, num_rm_grant);
len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, num_rm_release);
len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa,