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

Commit ab5ff1a3 authored by Chaitanya Pratapa's avatar Chaitanya Pratapa Committed by Praveen Kurapati
Browse files

msm: ipa: Fix not sending any packets in suspend mode



When rmnet_ipa driver is suspending, there can be a race
where the netdev queue is active and packets are sent out.
Make a change to avoid sending packets when device is
suspending.

Change-Id: Iab6b4ce0857504468ca45f06c570e5a4c60ffc61
Signed-off-by: default avatarPraveen Kurapati <pkurapat@codeaurora.org>
Signed-off-by: default avatarChaitanya Pratapa <cpratapa@codeaurora.org>
parent 231ab5f2
Loading
Loading
Loading
Loading
+23 −13
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ struct rmnet_ipa3_context {
	u32 outstanding_low;
	struct rmnet_ipa_debugfs dbgfs;
	bool dl_csum_offload_enabled;
	atomic_t suspend_pend;
	atomic_t ap_suspend;
};

static struct rmnet_ipa3_context *rmnet_ipa3_ctx;
@@ -1161,19 +1161,25 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev)

	qmap_check = RMNET_MAP_GET_CD_BIT(skb);
	spin_lock_irqsave(&wwan_ptr->lock, flags);
	if (netif_queue_stopped(dev)) {
		/*
		 * Checking rmnet suspend in progress or not, because in suspend
		 * clock will be disabled, without clock transferring data
		 * not possible.
	/* There can be a race between enabling the wake queue and
	 * suspend in progress. Check if suspend is pending and
	 * return from here itself.
	 */
		if (!atomic_read(&rmnet_ipa3_ctx->suspend_pend) && qmap_check &&
	if (atomic_read(&rmnet_ipa3_ctx->ap_suspend)) {
		netif_stop_queue(dev);
		spin_unlock_irqrestore(&wwan_ptr->lock, flags);
		return NETDEV_TX_BUSY;
	}
	if (netif_queue_stopped(dev)) {
		if (qmap_check &&
			atomic_read(&wwan_ptr->outstanding_pkts) <
				rmnet_ipa3_ctx->outstanding_high_ctl) {
			pr_err("[%s]Queue stop, send ctrl pkts\n", dev->name);
			IPAWANERR("[%s]Queue stop, send ctrl pkts\n",
							dev->name);
			goto send;
		} else {
			pr_err("[%s]fatal: %s stopped\n", dev->name, __func__);
			IPAWANERR("[%s]fatal: %s stopped\n", dev->name,
							__func__);
			spin_unlock_irqrestore(&wwan_ptr->lock, flags);
			return NETDEV_TX_BUSY;
		}
@@ -1209,7 +1215,7 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev)
		return NETDEV_TX_BUSY;
	}
	if (ret) {
		pr_err("[%s] fatal: ipa rm timer request resource failed %d\n",
		IPAWANERR("[%s] fatal: ipa rm timer req resource failed %d\n",
		       dev->name, ret);
		dev_kfree_skb_any(skb);
		dev->stats.tx_dropped++;
@@ -2232,6 +2238,7 @@ static void ipa3_wake_tx_queue(struct work_struct *work)
{
	if (IPA_NETDEV()) {
		__netif_tx_lock_bh(netdev_get_tx_queue(IPA_NETDEV(), 0));
		IPAWANDBG("Waking up the workqueue.\n");
		netif_wake_queue(IPA_NETDEV());
		__netif_tx_unlock_bh(netdev_get_tx_queue(IPA_NETDEV(), 0));
	}
@@ -2642,7 +2649,7 @@ static int ipa3_wwan_probe(struct platform_device *pdev)
		ipa3_proxy_clk_unvote();
	}
	atomic_set(&rmnet_ipa3_ctx->is_ssr, 0);
	atomic_set(&rmnet_ipa3_ctx->suspend_pend, 0);
	atomic_set(&rmnet_ipa3_ctx->ap_suspend, 0);

	IPAWANERR("rmnet_ipa completed initialization\n");
	return 0;
@@ -2764,12 +2771,13 @@ static int rmnet_ipa_ap_suspend(struct device *dev)
	 * scenarios observing the data was processed when IPA clock are off.
	 * Added changes to synchronize rmnet supend and xmit.
	 */
	atomic_set(&rmnet_ipa3_ctx->suspend_pend, 1);
	atomic_set(&rmnet_ipa3_ctx->ap_suspend, 1);
	spin_lock_irqsave(&wwan_ptr->lock, flags);
	/* Do not allow A7 to suspend in case there are outstanding packets */
	if (atomic_read(&wwan_ptr->outstanding_pkts) != 0) {
		IPAWANDBG("Outstanding packets, postponing AP suspend.\n");
		ret = -EAGAIN;
		atomic_set(&rmnet_ipa3_ctx->ap_suspend, 0);
		spin_unlock_irqrestore(&wwan_ptr->lock, flags);
		goto bail;
	}
@@ -2778,11 +2786,11 @@ static int rmnet_ipa_ap_suspend(struct device *dev)
	netif_stop_queue(netdev);
	spin_unlock_irqrestore(&wwan_ptr->lock, flags);

	IPAWANDBG("De-activating the PM/RM resource.\n");
	if (ipa3_ctx->use_ipa_pm)
		ipa_pm_deactivate_sync(rmnet_ipa3_ctx->pm_hdl);
	else
		ipa_rm_release_resource(IPA_RM_RESOURCE_WWAN_0_PROD);
	atomic_set(&rmnet_ipa3_ctx->suspend_pend, 0);
	ret = 0;
bail:
	IPAWANDBG("Exit with %d\n", ret);
@@ -2804,6 +2812,8 @@ static int rmnet_ipa_ap_resume(struct device *dev)
	struct net_device *netdev = IPA_NETDEV();

	IPAWANDBG("Enter...\n");
	/* Clear the suspend in progress flag. */
	atomic_set(&rmnet_ipa3_ctx->ap_suspend, 0);
	if (netdev)
		netif_wake_queue(netdev);
	IPAWANDBG("Exit\n");