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

Commit 98468677 authored by Kai Liu's avatar Kai Liu
Browse files

cnss2: retry mhi suspend in case packets are pending in MHI layer



Platform driver sends QMI message to query device status,
after it receives response, it will suspend device,
but at that time QRTR might been sending some flow control packets,
so mhi layer will reject suspend because packets are still pending,
platform driver retry suspend to cover this corner case.

Change-Id: Iec0cbe7b019d7be8e14096aca1861b28309a6141
Signed-off-by: default avatarKai Liu <kaliu@codeaurora.org>
parent 5c205e81
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */

#include <linux/cma.h>
#include <linux/firmware.h>
@@ -79,6 +79,8 @@ static DEFINE_SPINLOCK(time_sync_lock);
#define HST_HANG_DATA_OFFSET		((3 * 1024 * 1024) - HANG_DATA_LENGTH)
#define HSP_HANG_DATA_OFFSET		((2 * 1024 * 1024) - HANG_DATA_LENGTH)

#define MHI_SUSPEND_RETRY_CNT		3

static struct cnss_pci_reg ce_src[] = {
	{ "SRC_RING_BASE_LSB", QCA6390_CE_SRC_RING_BASE_LSB_OFFSET },
	{ "SRC_RING_BASE_MSB", QCA6390_CE_SRC_RING_BASE_MSB_OFFSET },
@@ -1100,6 +1102,7 @@ static int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv,
				  enum cnss_mhi_state mhi_state)
{
	int ret = 0;
	u8 retry = 0;

	if (pci_priv->device_id == QCA6174_DEVICE_ID)
		return 0;
@@ -1147,10 +1150,21 @@ static int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv,
		break;
	case CNSS_MHI_SUSPEND:
		mutex_lock(&pci_priv->mhi_ctrl->pm_mutex);
		if (pci_priv->drv_connected_last)
		if (pci_priv->drv_connected_last) {
			ret = mhi_pm_fast_suspend(pci_priv->mhi_ctrl, true);
		else
		} else {
			ret = mhi_pm_suspend(pci_priv->mhi_ctrl);
			/* in some corner case, when cnss try to suspend,
			 * there is still packets pending in mhi layer,
			 * so retry suspend to save roll back effort.
			 */
			while (ret == -EBUSY && retry < MHI_SUSPEND_RETRY_CNT) {
				usleep_range(5000, 6000);
				retry++;
				cnss_pr_err("mhi is busy, retry #%u", retry);
				ret = mhi_pm_suspend(pci_priv->mhi_ctrl);
			}
		}
		mutex_unlock(&pci_priv->mhi_ctrl->pm_mutex);
		break;
	case CNSS_MHI_RESUME:
@@ -1179,8 +1193,8 @@ static int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv,
	return 0;

out:
	cnss_pr_err("Failed to set MHI state: %s(%d)\n",
		    cnss_mhi_state_to_str(mhi_state), mhi_state);
	cnss_pr_err("Failed to set MHI state: %s(%d) ret: %d\n",
		    cnss_mhi_state_to_str(mhi_state), mhi_state, ret);

	if (mhi_state == CNSS_MHI_RESUME)
		cnss_force_fw_assert_async(&pci_priv->pci_dev->dev);