bus: mhi: host: Fix up null pointer access in mhi_irq_handler
authorQiang Yu <quic_qianyu@quicinc.com>
Fri, 22 Jul 2022 03:17:18 +0000 (11:17 +0800)
committerManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Mon, 29 Aug 2022 17:03:46 +0000 (22:33 +0530)
The irq handler for a shared IRQ ought to be prepared for running
even now it's being freed. So let's check the pointer used by
mhi_irq_handler to avoid null pointer access since it is probably
released before freeing IRQ.

Fixes: 1227d2a20cd7 ("bus: mhi: host: Move IRQ allocation to controller registration phase")
Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Tested-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/1658459838-30802-1-git-send-email-quic_qianyu@quicinc.com
[mani: added fixes tag]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
drivers/bus/mhi/host/main.c

index f3aef77..df0fbfe 100644 (file)
@@ -430,12 +430,25 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev)
 {
        struct mhi_event *mhi_event = dev;
        struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl;
-       struct mhi_event_ctxt *er_ctxt =
-               &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+       struct mhi_event_ctxt *er_ctxt;
        struct mhi_ring *ev_ring = &mhi_event->ring;
-       dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
+       dma_addr_t ptr;
        void *dev_rp;
 
+       /*
+        * If CONFIG_DEBUG_SHIRQ is set, the IRQ handler will get invoked during __free_irq()
+        * and by that time mhi_ctxt() would've freed. So check for the existence of mhi_ctxt
+        * before handling the IRQs.
+        */
+       if (!mhi_cntrl->mhi_ctxt) {
+               dev_dbg(&mhi_cntrl->mhi_dev->dev,
+                       "mhi_ctxt has been freed\n");
+               return IRQ_HANDLED;
+       }
+
+       er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+       ptr = le64_to_cpu(er_ctxt->rp);
+
        if (!is_valid_ring_ptr(ev_ring, ptr)) {
                dev_err(&mhi_cntrl->mhi_dev->dev,
                        "Event ring rp points outside of the event ring\n");