summaryrefslogtreecommitdiff
path: root/drivers/bus/mhi/ep/main.c
diff options
context:
space:
mode:
authorManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>2023-01-23 10:29:45 +0300
committerManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>2023-01-27 10:01:41 +0300
commit1ddc7618294084fff8d673217a9479550990ee84 (patch)
treea1c166517bd8d83b03148acd64d76d7d0cbf551a /drivers/bus/mhi/ep/main.c
parent8a1c24bb908f9ecbc4be0fea014df67d43161551 (diff)
downloadlinux-1ddc7618294084fff8d673217a9479550990ee84.tar.xz
bus: mhi: ep: Change state_lock to mutex
state_lock, the spinlock type is meant to protect race against concurrent MHI state transitions. In mhi_ep_set_m0_state(), while the state_lock is being held, the channels are resumed in mhi_ep_resume_channels() if the previous state was M3. This causes sleeping in atomic bug, since mhi_ep_resume_channels() use mutex internally. Since the state_lock is supposed to be held throughout the state change, it is not ideal to drop the lock before calling mhi_ep_resume_channels(). So to fix this issue, let's change the type of state_lock to mutex. This would also allow holding the lock throughout all state transitions thereby avoiding any potential race. Cc: <stable@vger.kernel.org> # 5.19 Fixes: e4b7b5f0f30a ("bus: mhi: ep: Add support for suspending and resuming channels") Reported-by: Dan Carpenter <error27@gmail.com> Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Diffstat (limited to 'drivers/bus/mhi/ep/main.c')
-rw-r--r--drivers/bus/mhi/ep/main.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c
index bcaaba97ef63..528c00b232bf 100644
--- a/drivers/bus/mhi/ep/main.c
+++ b/drivers/bus/mhi/ep/main.c
@@ -1001,11 +1001,11 @@ static void mhi_ep_reset_worker(struct work_struct *work)
mhi_ep_power_down(mhi_cntrl);
- spin_lock_bh(&mhi_cntrl->state_lock);
+ mutex_lock(&mhi_cntrl->state_lock);
+
/* Reset MMIO to signal host that the MHI_RESET is completed in endpoint */
mhi_ep_mmio_reset(mhi_cntrl);
cur_state = mhi_cntrl->mhi_state;
- spin_unlock_bh(&mhi_cntrl->state_lock);
/*
* Only proceed further if the reset is due to SYS_ERR. The host will
@@ -1014,6 +1014,8 @@ static void mhi_ep_reset_worker(struct work_struct *work)
*/
if (cur_state == MHI_STATE_SYS_ERR)
mhi_ep_power_up(mhi_cntrl);
+
+ mutex_unlock(&mhi_cntrl->state_lock);
}
/*
@@ -1386,8 +1388,8 @@ int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl,
INIT_LIST_HEAD(&mhi_cntrl->st_transition_list);
INIT_LIST_HEAD(&mhi_cntrl->ch_db_list);
- spin_lock_init(&mhi_cntrl->state_lock);
spin_lock_init(&mhi_cntrl->list_lock);
+ mutex_init(&mhi_cntrl->state_lock);
mutex_init(&mhi_cntrl->event_lock);
/* Set MHI version and AMSS EE before enumeration */