]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: mpt3sas: Fix sync irqs
authorTomas Henzl <thenzl@redhat.com>
Thu, 10 Sep 2020 14:21:26 +0000 (16:21 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Oct 2020 09:07:38 +0000 (10:07 +0100)
[ Upstream commit 45181eab8ba79ed7a41b549f00500c0093828521 ]

_base_process_reply_queue() called from _base_interrupt() may schedule a
new irq poll. Fix this by calling synchronize_irq() first.

Also ensure that enable_irq() is called only when necessary to avoid
"Unbalanced enable for IRQ..." errors.

Link: https://lore.kernel.org/r/20200910142126.8147-1-thenzl@redhat.com
Fixes: 320e77acb327 ("scsi: mpt3sas: Irq poll to avoid CPU hard lockups")
Acked-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
Signed-off-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/mpt3sas/mpt3sas_base.c

index a85c9672c6ea3c535101c1f418a05bc74e34bc6d..a67749c8f4ab395938aa84fd4feeb67b66f33608 100644 (file)
@@ -1808,18 +1808,22 @@ mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc)
                /* TMs are on msix_index == 0 */
                if (reply_q->msix_index == 0)
                        continue;
+               synchronize_irq(pci_irq_vector(ioc->pdev, reply_q->msix_index));
                if (reply_q->irq_poll_scheduled) {
                        /* Calling irq_poll_disable will wait for any pending
                         * callbacks to have completed.
                         */
                        irq_poll_disable(&reply_q->irqpoll);
                        irq_poll_enable(&reply_q->irqpoll);
-                       reply_q->irq_poll_scheduled = false;
-                       reply_q->irq_line_enable = true;
-                       enable_irq(reply_q->os_irq);
-                       continue;
+                       /* check how the scheduled poll has ended,
+                        * clean up only if necessary
+                        */
+                       if (reply_q->irq_poll_scheduled) {
+                               reply_q->irq_poll_scheduled = false;
+                               reply_q->irq_line_enable = true;
+                               enable_irq(reply_q->os_irq);
+                       }
                }
-               synchronize_irq(pci_irq_vector(ioc->pdev, reply_q->msix_index));
        }
 }