This is a note to let you know that I've just added the patch titled
bus: mhi: ep: Move chan->lock to the start of processing queued ch
to my char-misc git tree which can be found at git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git in the char-misc-next branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will also be merged in the next major kernel release during the merge window.
If you have any questions about this process, please let me know.
From 8d6a1fea53864cd9545741f48f4ae4df804db557 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Date: Wed, 28 Dec 2022 21:47:03 +0530 Subject: bus: mhi: ep: Move chan->lock to the start of processing queued ch ring
There is a good chance that while the channel ring gets processed, the STOP or RESET command for the channel might be received from the MHI host. In those cases, the entire channel ring processing needs to be protected by chan->lock to prevent the race where the corresponding channel ring might be reset.
While at it, let's also add a sanity check to make sure that the ring is started before processing it. Because, if the STOP/RESET command gets processed while mhi_ep_ch_ring_worker() waited for chan->lock, the ring would've been reset.
Cc: stable@vger.kernel.org # 5.19 Fixes: 03c0bb8ec983 ("bus: mhi: ep: Add support for processing channel rings") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Reviewed-by: Jeffrey Hugo quic_jhugo@quicinc.com Link: https://lore.kernel.org/r/20221228161704.255268-6-manivannan.sadhasivam@lina... Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org --- drivers/bus/mhi/ep/main.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c index 0bce6610ebf1..2362fcc8b32c 100644 --- a/drivers/bus/mhi/ep/main.c +++ b/drivers/bus/mhi/ep/main.c @@ -730,24 +730,37 @@ static void mhi_ep_ch_ring_worker(struct work_struct *work) list_del(&itr->node); ring = itr->ring;
+ chan = &mhi_cntrl->mhi_chan[ring->ch_id]; + mutex_lock(&chan->lock); + + /* + * The ring could've stopped while we waited to grab the (chan->lock), so do + * a sanity check before going further. + */ + if (!ring->started) { + mutex_unlock(&chan->lock); + kfree(itr); + continue; + } + /* Update the write offset for the ring */ ret = mhi_ep_update_wr_offset(ring); if (ret) { dev_err(dev, "Error updating write offset for ring\n"); + mutex_unlock(&chan->lock); kfree(itr); continue; }
/* Sanity check to make sure there are elements in the ring */ if (ring->rd_offset == ring->wr_offset) { + mutex_unlock(&chan->lock); kfree(itr); continue; }
el = &ring->ring_cache[ring->rd_offset]; - chan = &mhi_cntrl->mhi_chan[ring->ch_id];
- mutex_lock(&chan->lock); dev_dbg(dev, "Processing the ring for channel (%u)\n", ring->ch_id); ret = mhi_ep_process_ch_ring(ring, el); if (ret) {
linux-stable-mirror@lists.linaro.org