mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-15 01:01:56 -04:00
msm: mhi_dev: Handle host wakeup in M3/D0
When a MHI WAKE request (that is request to bring MHI from M3 to M0) is
received while device is in D0, this request is being dropped as there
is no way to notify host about this event. This is leading to failure at
client drivers as they unable to wakeup mhi and perform write operation.
Fix the issue by waiting for D3hot in MHI before sending the wake
request:
- If M0 is received while waiting, exit the function.
- If D3hot/D3cold is received, send the wake request.
- Else return failure.
Increase the timeout value of mhi_dev_write_channel() from 2s to 2.5s
to accommodate the waiting time for D state transition to D3hot/D3cold.
Change-Id: Idd58bb664d31bc1e5615119284c6cba924fe17b6
Signed-off-by: Sumit Kumar <quic_sumk@quicinc.com>
This commit is contained in:
parent
b0eaa6a4e4
commit
a92f080134
2 changed files with 32 additions and 4 deletions
|
|
@ -39,7 +39,7 @@
|
|||
/* Wait time on the device for Host to set BHI_INTVEC */
|
||||
#define MHI_BHI_INTVEC_MAX_CNT 200
|
||||
#define MHI_BHI_INTVEC_WAIT_MS 50
|
||||
#define MHI_WAKEUP_TIMEOUT_CNT 20
|
||||
#define MHI_WAKEUP_TIMEOUT_CNT 25
|
||||
#define MHI_MASK_CH_EV_LEN 32
|
||||
#define MHI_RING_CMD_ID 0
|
||||
#define MHI_RING_PRIMARY_EVT_ID 1
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "mhi_hwio.h"
|
||||
#include "mhi_sm.h"
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define MHI_SM_DBG(fmt, args...) \
|
||||
mhi_log(MHI_MSG_DBG, fmt, ##args)
|
||||
|
|
@ -28,6 +29,8 @@
|
|||
#define PCIE_EP_TIMER_US 500000000
|
||||
#define MHI_IPA_DISABLE_DELAY_MS 10
|
||||
#define MHI_IPA_DISABLE_COUNTER 20
|
||||
/* Maximum wait time for D state transitions to D3hot */
|
||||
#define M3_DO_WAKEUP_TIMEOUT_MS 2500
|
||||
|
||||
|
||||
static inline const char *mhi_sm_dev_event_str(enum mhi_dev_event state)
|
||||
|
|
@ -734,7 +737,7 @@ exit:
|
|||
* mhi_sm_wakeup_host() - wakeup MHI-host
|
||||
*@event: MHI state chenge event
|
||||
*
|
||||
* Sends wekup event to MHI-host via EP-PCIe, in case MHI is in M3 state.
|
||||
* Sends wakeup event to MHI-host via EP-PCIe, in case MHI is in M3 state.
|
||||
*
|
||||
* Return: 0:success
|
||||
* negative: failure
|
||||
|
|
@ -742,6 +745,7 @@ exit:
|
|||
static int mhi_sm_wakeup_host(enum mhi_dev_event event)
|
||||
{
|
||||
int res = 0;
|
||||
int timeout = 0;
|
||||
enum ep_pcie_event pcie_event;
|
||||
|
||||
MHI_SM_FUNC_ENTRY();
|
||||
|
|
@ -753,9 +757,33 @@ static int mhi_sm_wakeup_host(enum mhi_dev_event event)
|
|||
MHI_SM_ERR("Failed switching to M0 state\n");
|
||||
} else if (mhi_sm_ctx->mhi_state == MHI_DEV_M3_STATE) {
|
||||
/*
|
||||
* Check and send D3_HOT to enable waking up the host
|
||||
* using inband PME.
|
||||
* Handle host wakeup in M3 + D0 states.
|
||||
*
|
||||
* When a MHI WAKE request is received while device is in D0,
|
||||
* wait for D3 and wakeup the host using inband PME.
|
||||
* If the MHI state changes to M0 while waiting for D3,
|
||||
* exit, since both MHI and the device are in active state.
|
||||
*/
|
||||
if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D0_STATE) {
|
||||
timeout = ktime_add_ms(ktime_get(), M3_DO_WAKEUP_TIMEOUT_MS);
|
||||
while (1) {
|
||||
/* Received M0 */
|
||||
if (mhi_sm_ctx->mhi_state == MHI_DEV_M0_STATE)
|
||||
goto exit;
|
||||
/* Received D3 state */
|
||||
if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_HOT_STATE ||
|
||||
mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_COLD_STATE)
|
||||
goto wakeup_host;
|
||||
if (ktime_after(ktime_get(), timeout)) {
|
||||
MHI_SM_ERR(mhi->vf_id,
|
||||
"M3, D0 wakeup host is not supported %d\n", res);
|
||||
goto exit;
|
||||
}
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
}
|
||||
wakeup_host:
|
||||
/* Received D3hot or D3cold, send the wakeup request */
|
||||
if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_HOT_STATE)
|
||||
pcie_event = EP_PCIE_EVENT_PM_D3_HOT;
|
||||
else
|
||||
|
|
|
|||
Loading…
Reference in a new issue