msm: mhi_dev: Avoid BME check while sending ready

On some x86 based Root complex devices we observe that BME gets set
during PBL initialization sequence and gets cleared if the BAR
configuration is yet to be complete. So depending on the timing of
AMSS boot duration, when we read the PCIE20_COMMAND_STATUS register
bit(5) during BME IRQ, three scenarios can happen.

1. AMSS boots quicker: The BME bit is set, we set dev->enumerated flag
and indicate EP_PCIE_LINK_ENABLED and initiate MHI which in turn
continues to do MMIO initialization sequence. This sequence involves
call to mhi_dev_sm_set_ready() and mhi_dev_sm_init() APIs which check
for ep_pcie_get_linkstatus() API which might end up failing thus
preventing MHI from moving to ready state.
2. The BME bit is already cleared and set again before the first BME
IRQ. So there is no disruption in the code flow.
3. The BME bit is cleared and hence we do not set dev->enumerated. The
normal code flow happens as part of 2nd BME IRQ.

In (2) and (3) there are no issues, but in (1) during
mhi_dev_resume_mmio_mhi_init() we call ep_pcie_register_event() which
will overwrite the previous EP_PCIE_EVENT_LINKUP registration. So
during the 2nd BME IRQ that gets fired, EP PCIE driver does not give
a callback to MHI as EP_PCIE_EVENT_LINKUP is not registered by MHI
anymore.

In current implementation, APIs mhi_dev_sm_set_ready() or
mhi_dev_sm_init() fail as BME is deasserted. This results in MHI host
driver not getting ready state. mhi_dev_resume_mmio_mhi_init() is called
only if BME is set, mhi_dev_sm_set_ready() and mhi_dev_sm_init() APIs
are called as part of this. As these APIs are called only if BME is set,
BME check inside these APIs is not really needed.

To avoid the issue of not sending ready state, removing checks for BME
in mhi_dev_sm_set_ready() and mhi_dev_sm_init() APIs, so that ready
state is sent to host and M0 is received after this. Added a warning log
before polling for M0 to know if BME is not set again by host.

Change-Id: I211e9e20e05211d2a0c6f0972e1468a4d452ff5d
Signed-off-by: Subramanian Ananthanarayanan <skananth@codeaurora.org>
Signed-off-by: Sai Chaitanya Kaveti <quic_skaveti@quicinc.com>
This commit is contained in:
Subramanian Ananthanarayanan 2021-01-12 10:39:18 +05:30 • committed by Sai Chaitanya Kaveti
commit 487f688a87
3 changed files with 13 additions and 24 deletions

View file

@ -3936,6 +3936,9 @@ static void mhi_dev_enable(struct work_struct *work)
"Cleared reset before waiting for M0\n");
}
if (ep_pcie_get_linkstatus(mhi->phandle) != EP_PCIE_LINK_ENABLED)
mhi_log(MHI_MSG_ERROR, "warning: PCIe BME unset error");
while (state != MHI_DEV_M0_STATE &&
((max_cnt < MHI_SUSPEND_TIMEOUT) || mhi->no_m0_timeout)) {
/* Wait for Host to set the M0 state */

View file

@ -96,12 +96,6 @@ static inline const char *mhi_sm_mstate_str(enum mhi_dev_state state)
return str;
}
enum mhi_sm_ep_pcie_state {
MHI_SM_EP_PCIE_LINK_DISABLE,
MHI_SM_EP_PCIE_D0_STATE,
MHI_SM_EP_PCIE_D3_HOT_STATE,
MHI_SM_EP_PCIE_D3_COLD_STATE,
};
static inline const char *mhi_sm_dstate_str(enum mhi_sm_ep_pcie_state state)
{
@ -1106,8 +1100,6 @@ unlock_and_exit:
int mhi_dev_sm_init(struct mhi_dev *mhi_dev)
{
int res;
enum ep_pcie_link_status link_state;
MHI_SM_FUNC_ENTRY();
if (!mhi_dev) {
@ -1137,11 +1129,7 @@ int mhi_dev_sm_init(struct mhi_dev *mhi_dev)
atomic_set(&mhi_sm_ctx->pending_device_events, 0);
atomic_set(&mhi_sm_ctx->pending_pcie_events, 0);
link_state = ep_pcie_get_linkstatus(mhi_sm_ctx->mhi_dev->phandle);
if (link_state == EP_PCIE_LINK_ENABLED)
mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_D0_STATE;
else
mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_LINK_DISABLE;
mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_D0_STATE;
MHI_SM_FUNC_EXIT();
return 0;
@ -1238,16 +1226,7 @@ int mhi_dev_sm_set_ready(void)
goto unlock_and_exit;
}
if (mhi_sm_ctx->d_state != MHI_SM_EP_PCIE_D0_STATE) {
if (ep_pcie_get_linkstatus(mhi_sm_ctx->mhi_dev->phandle) ==
EP_PCIE_LINK_ENABLED) {
mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_D0_STATE;
} else {
MHI_SM_ERR("ERROR: ep-pcie link is not enabled\n");
res = -EPERM;
goto unlock_and_exit;
}
}
mhi_sm_ctx->d_state = MHI_SM_EP_PCIE_D0_STATE;
/* verify that MHISTATUS is configured to RESET*/
mhi_dev_mmio_masked_read(mhi_sm_ctx->mhi_dev,

View file

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2015,2017-2018,2020 The Linux Foundation. All rights reserved.*/
/* Copyright (c) 2015,2017-2018,2020-2021 The Linux Foundation. All rights reserved.*/
#ifndef MHI_SM_H
#define MHI_SM_H
@ -31,6 +31,13 @@ enum mhi_dev_event {
MHI_DEV_EVENT_MAX
};
enum mhi_sm_ep_pcie_state {
MHI_SM_EP_PCIE_LINK_DISABLE,
MHI_SM_EP_PCIE_D0_STATE,
MHI_SM_EP_PCIE_D3_HOT_STATE,
MHI_SM_EP_PCIE_D3_COLD_STATE,
};
int mhi_dev_sm_init(struct mhi_dev *dev);
int mhi_dev_sm_exit(struct mhi_dev *dev);
int mhi_dev_sm_set_ready(void);