FAILED: patch "[PATCH] bus: mhi: core: Fix race while handling SYS_ERR at power up" failed to apply to 5.10-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From d651ce8e917fa1bf6cfab8dca74c512edffc35d3 Mon Sep 17 00:00:00 2001
From: Manivannan Sadhasivam <[email protected]>
Date: Thu, 16 Dec 2021 13:42:24 +0530
Subject: [PATCH] bus: mhi: core: Fix race while handling SYS_ERR at power up
During SYS_ERR condition, as a response to the MHI_RESET from host, some devices tend to issue BHI interrupt without clearing the SYS_ERR state in the device. This creates a race condition and causes a failure in booting up the device.
The issue is seen on the Sierra Wireless EM9191 modem during SYS_ERR handling in mhi_async_power_up(). Once the host detects that the device is in SYS_ERR state, it issues MHI_RESET and waits for the device to process the reset request. During this time, the device triggers the BHI interrupt to the host without clearing SYS_ERR condition. So the host starts handling the SYS_ERR condition again.
To fix this issue, let's register the IRQ handler only after handling the SYS_ERR check to avoid getting spurious IRQs from the device.
drivers/bus/mhi/core/pm.c +12 -23
@@ -1053,7 +1053,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)enum mhi_ee_type current_ee;enum dev_st_transition next_state;struct device *dev = &mhi_cntrl->mhi_dev->dev; -u32 val; +u32 interval_us =25000 ;/* poll register field every 25 milliseconds */ int ret;dev_info (dev,"Requested to power ON\n" );
@@ -1070,10 +1070,6 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)mutex_lock (&mhi_cntrl->pm_mutex); mhi_cntrl->pm_state =MHI_PM_DISABLE ; - ret =mhi_init_irq_setup (mhi_cntrl); -if (ret) - goto error_setup_irq; -/* Setup BHI INTVEC */ write_lock_irq (&mhi_cntrl->pm_lock);mhi_write_reg (mhi_cntrl, mhi_cntrl->bhi,BHI_INTVEC ,0 );
@@ -1087,7 +1083,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)dev_err (dev,"%s is not a valid EE for power on\n" ,TO_MHI_EXEC_STR (current_ee)); ret = -EIO ; - goto error_async_power_up; + goto error_exit; } state =mhi_get_mhi_state (mhi_cntrl);
@@ -1096,20 +1092,12 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)if (state ==MHI_STATE_SYS_ERR ) {mhi_set_mhi_state (mhi_cntrl,MHI_STATE_RESET ); - ret =wait_event_timeout (mhi_cntrl->state_event, -MHI_PM_IN_FATAL_STATE (mhi_cntrl->pm_state) || -mhi_read_reg_field (mhi_cntrl, - mhi_cntrl->regs, -MHICTRL , -MHICTRL_RESET_MASK , -MHICTRL_RESET_SHIFT , - &val) || - !val, -msecs_to_jiffies (mhi_cntrl->timeout_ms)); -if (!ret) { - ret = -EIO ; + ret =mhi_poll_reg_field (mhi_cntrl, mhi_cntrl->regs,MHICTRL , +MHICTRL_RESET_MASK ,MHICTRL_RESET_SHIFT ,0 , + interval_us); +if (ret) {dev_info (dev,"Failed to reset MHI due to syserr state\n" ); - goto error_async_power_up; + goto error_exit; }/*
@@ -1119,6 +1107,10 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)mhi_write_reg (mhi_cntrl, mhi_cntrl->bhi,BHI_INTVEC ,0 ); } + ret =mhi_init_irq_setup (mhi_cntrl); +if (ret) + goto error_exit; +/* Transition to next state */ next_state =MHI_IN_PBL (current_ee) ?DEV_ST_TRANSITION_PBL :DEV_ST_TRANSITION_READY ;
@@ -1131,10 +1123,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)return 0 ; -error_async_power_up: -mhi_deinit_free_irq (mhi_cntrl); - -error_setup_irq: +error_exit: mhi_cntrl->pm_state =MHI_PM_DISABLE ;mutex_unlock (&mhi_cntrl->pm_mutex);