mhi: core: Extend mhi_device_get_sync_atomic() for panic cases
In case of a kernel panic, interrupts are not handled and hence, any attempt to assert device wake and wait for an M0 state change relying on interrupts will fail. In order to help solve this issue for cases where the controller needs to assert device wake in panic path, extend the mhi_device_get_sync_atomic() API and allow it to poll the MHI STATUS register for an M0 state change. Make the appropriate changes wherever the API is in use. Change-Id: I920d76d1cec879c29180438072e32e18370cf8ff Signed-off-by: Bhaumik Bhatt <bbhatt@codeaurora.org>
This commit is contained in:
@@ -1670,7 +1670,8 @@ int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote)
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_device_get_sync);
|
||||
|
||||
int mhi_device_get_sync_atomic(struct mhi_device *mhi_dev, int timeout_us)
|
||||
int mhi_device_get_sync_atomic(struct mhi_device *mhi_dev, int timeout_us,
|
||||
bool in_panic)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
|
||||
@@ -1696,11 +1697,20 @@ int mhi_device_get_sync_atomic(struct mhi_device *mhi_dev, int timeout_us)
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (mhi_cntrl->pm_state != MHI_PM_M0 &&
|
||||
!MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) &&
|
||||
timeout_us > 0) {
|
||||
udelay(MHI_FORCE_WAKE_DELAY_US);
|
||||
timeout_us -= MHI_FORCE_WAKE_DELAY_US;
|
||||
if (in_panic) {
|
||||
while (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M0 &&
|
||||
!MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) &&
|
||||
timeout_us > 0) {
|
||||
udelay(MHI_FORCE_WAKE_DELAY_US);
|
||||
timeout_us -= MHI_FORCE_WAKE_DELAY_US;
|
||||
}
|
||||
} else {
|
||||
while (mhi_cntrl->pm_state != MHI_PM_M0 &&
|
||||
!MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) &&
|
||||
timeout_us > 0) {
|
||||
udelay(MHI_FORCE_WAKE_DELAY_US);
|
||||
timeout_us -= MHI_FORCE_WAKE_DELAY_US;
|
||||
}
|
||||
}
|
||||
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || timeout_us <= 0) {
|
||||
|
||||
@@ -3069,7 +3069,7 @@ int cnss_pci_force_wake_request_sync(struct device *dev, int timeout_us)
|
||||
if (timeout_us) {
|
||||
/* Busy wait for timeout_us */
|
||||
return mhi_device_get_sync_atomic(mhi_ctrl->mhi_dev,
|
||||
timeout_us);
|
||||
timeout_us, false);
|
||||
} else {
|
||||
/* Sleep wait for mhi_ctrl->timeout_ms */
|
||||
return mhi_device_get_sync(mhi_ctrl->mhi_dev, MHI_VOTE_DEVICE);
|
||||
|
||||
@@ -616,6 +616,7 @@ int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote);
|
||||
* mhi_device_get_sync_atomic - Asserts device_wait and moves device to M0
|
||||
* @mhi_dev: Device associated with the channels
|
||||
* @timeout_us: timeout, in micro-seconds
|
||||
* @in_panic: If requested while kernel is in panic state and no ISRs expected
|
||||
*
|
||||
* The device_wake is asserted to keep device in M0 or bring it to M0.
|
||||
* If device is not in M0 state, then this function will wait for device to
|
||||
@@ -627,6 +628,8 @@ int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote);
|
||||
* Clients can ignore that transition after this function returns as the device
|
||||
* is expected to immediately move from M2 to M0 as wake is asserted and
|
||||
* wouldn't enter low power state.
|
||||
* If in_panic boolean is set, no ISRs are expected, hence this API will have to
|
||||
* resort to reading the MHI status register and poll on M0 state change.
|
||||
*
|
||||
* Returns:
|
||||
* 0 if operation was successful (however, M0 -> M2 -> M0 is possible later) as
|
||||
@@ -634,7 +637,9 @@ int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote);
|
||||
* -ETIMEDOUT is device faled to move to M0 before @timeout_us elapsed
|
||||
* -EIO if the MHI state is one of the ERROR states.
|
||||
*/
|
||||
int mhi_device_get_sync_atomic(struct mhi_device *mhi_dev, int timeout_us);
|
||||
int mhi_device_get_sync_atomic(struct mhi_device *mhi_dev,
|
||||
int timeout_us,
|
||||
bool in_panic);
|
||||
|
||||
/**
|
||||
* mhi_device_put - re-enable low power modes
|
||||
|
||||
Reference in New Issue
Block a user