Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77e968a2 authored by Mohammed Javid's avatar Mohammed Javid Committed by Gerrit - the friendly Code Review server
Browse files

msm: ipa: ipa_tx_dp issued after suspend



Suspend request issued by GSB interface
to ipa-sw. While suspend is in progress, data
transmit also initiated before ipa completes
its suspend sequence. Due to which, we see
un-clocked access on NOC, since IPA-sw submits desc to
IPA-hw after clock is GATED.
So, prevent data transfer if the iface's suspend
in progress or completed.

Change-Id: I9d2c1d0803352dcc1907777d03403722afb879db
Signed-off-by: default avatarMohammed Javid <mjavid@codeaurora.org>
parent 1e5b6117
Loading
Loading
Loading
Loading
+18 −1
Original line number Original line Diff line number Diff line
@@ -161,6 +161,7 @@ struct ipa_gsb_context {
	spinlock_t iface_spinlock[MAX_SUPPORTED_IFACE];
	spinlock_t iface_spinlock[MAX_SUPPORTED_IFACE];
	u32 pm_hdl;
	u32 pm_hdl;
	atomic_t disconnect_in_progress;
	atomic_t disconnect_in_progress;
	atomic_t suspend_in_progress;
};
};


static struct ipa_gsb_context *ipa_gsb_ctx;
static struct ipa_gsb_context *ipa_gsb_ctx;
@@ -1079,20 +1080,24 @@ int ipa_bridge_suspend(u32 hdl)
	IPA_GSB_DBG_LOW("client hdl: %d\n", hdl);
	IPA_GSB_DBG_LOW("client hdl: %d\n", hdl);


	mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]);
	mutex_lock(&ipa_gsb_ctx->iface_lock[hdl]);
	atomic_set(&ipa_gsb_ctx->suspend_in_progress, 1);
	if (!ipa_gsb_ctx->iface[hdl]) {
	if (!ipa_gsb_ctx->iface[hdl]) {
		IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl);
		IPA_GSB_ERR("fail to find interface, hdl: %d\n", hdl);
		atomic_set(&ipa_gsb_ctx->suspend_in_progress, 0);
		mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
		mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
		return -EFAULT;
		return -EFAULT;
	}
	}


	if (!ipa_gsb_ctx->iface[hdl]->is_connected) {
	if (!ipa_gsb_ctx->iface[hdl]->is_connected) {
		IPA_GSB_ERR("iface is not connected\n");
		IPA_GSB_ERR("iface is not connected\n");
		atomic_set(&ipa_gsb_ctx->suspend_in_progress, 0);
		mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
		mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
		return -EFAULT;
		return -EFAULT;
	}
	}


	if (!ipa_gsb_ctx->iface[hdl]->is_resumed) {
	if (!ipa_gsb_ctx->iface[hdl]->is_resumed) {
		IPA_GSB_DBG_LOW("iface was already suspended\n");
		IPA_GSB_DBG_LOW("iface was already suspended\n");
		atomic_set(&ipa_gsb_ctx->suspend_in_progress, 0);
		mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
		mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
		return 0;
		return 0;
	}
	}
@@ -1105,6 +1110,7 @@ int ipa_bridge_suspend(u32 hdl)
			IPA_GSB_ERR(
			IPA_GSB_ERR(
				"fail to stop cons ep %d\n",
				"fail to stop cons ep %d\n",
				ret);
				ret);
			atomic_set(&ipa_gsb_ctx->suspend_in_progress, 0);
			mutex_unlock(&ipa_gsb_ctx->lock);
			mutex_unlock(&ipa_gsb_ctx->lock);
			mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
			mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
			return ret;
			return ret;
@@ -1114,6 +1120,7 @@ int ipa_bridge_suspend(u32 hdl)
		if (ret) {
		if (ret) {
			IPA_GSB_ERR("fail to deactivate ipa pm\n");
			IPA_GSB_ERR("fail to deactivate ipa pm\n");
			ipa_start_gsi_channel(ipa_gsb_ctx->cons_hdl);
			ipa_start_gsi_channel(ipa_gsb_ctx->cons_hdl);
			atomic_set(&ipa_gsb_ctx->suspend_in_progress, 0);
			mutex_unlock(&ipa_gsb_ctx->lock);
			mutex_unlock(&ipa_gsb_ctx->lock);
			mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
			mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
			return ret;
			return ret;
@@ -1124,7 +1131,7 @@ int ipa_bridge_suspend(u32 hdl)
	ipa_gsb_ctx->num_resumed_iface--;
	ipa_gsb_ctx->num_resumed_iface--;
	IPA_GSB_DBG_LOW("num resumed iface: %d\n",
	IPA_GSB_DBG_LOW("num resumed iface: %d\n",
		ipa_gsb_ctx->num_resumed_iface);
		ipa_gsb_ctx->num_resumed_iface);

	atomic_set(&ipa_gsb_ctx->suspend_in_progress, 0);
	mutex_unlock(&ipa_gsb_ctx->lock);
	mutex_unlock(&ipa_gsb_ctx->lock);
	mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
	mutex_unlock(&ipa_gsb_ctx->iface_lock[hdl]);
	return 0;
	return 0;
@@ -1180,6 +1187,16 @@ int ipa_bridge_tx_dp(u32 hdl, struct sk_buff *skb,
		return -EFAULT;
		return -EFAULT;
	}
	}


	if (unlikely(atomic_read(&ipa_gsb_ctx->suspend_in_progress))) {
		IPA_GSB_ERR("ipa bridge suspend_in_progress\n");
		return -EFAULT;
	}

	if (unlikely(!ipa_gsb_ctx->iface[hdl]->is_resumed)) {
		IPA_GSB_ERR("iface %d was suspended\n", hdl);
		return -EFAULT;
	}

	/* make sure skb has enough headroom */
	/* make sure skb has enough headroom */
	if (unlikely(skb_headroom(skb) < sizeof(struct ipa_gsb_mux_hdr))) {
	if (unlikely(skb_headroom(skb) < sizeof(struct ipa_gsb_mux_hdr))) {
		IPA_GSB_DBG_LOW("skb doesn't have enough headroom\n");
		IPA_GSB_DBG_LOW("skb doesn't have enough headroom\n");