diff mbox series

mpt3sas: fix sync irqs

Message ID 20200910142126.8147-1-thenzl@redhat.com
State New
Headers show
Series mpt3sas: fix sync irqs | expand

Commit Message

Tomas Henzl Sept. 10, 2020, 2:21 p.m. UTC
- _base_process_reply_queue called from _base_interrupt
may schedule a new irq poll, fix this by calling
synchronize_irq first
- a fix for "Unbalanced enable for IRQ..."
enable_irq should be called only when necessary

Fixes: 320e77acb327 ("scsi: mpt3sas: Irq poll to avoid CPU hard lockups")
Signed-off-by: Tomas Henzl <thenzl@redhat.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 14 +++++++++-----
 drivers/scsi/scsi_scan.c            |  8 ++++++++
 2 files changed, 17 insertions(+), 5 deletions(-)

Comments

Martin K. Petersen Sept. 15, 2020, 10:38 p.m. UTC | #1
Tomas,

> - _base_process_reply_queue called from _base_interrupt may schedule a

> new irq poll, fix this by calling synchronize_irq first


Applied to 5.10/scsi-staging, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering
Martin K. Petersen Sept. 22, 2020, 3:56 a.m. UTC | #2
On Thu, 10 Sep 2020 16:21:26 +0200, Tomas Henzl wrote:

> - _base_process_reply_queue called from _base_interrupt

> may schedule a new irq poll, fix this by calling

> synchronize_irq first

> - a fix for "Unbalanced enable for IRQ..."

> enable_irq should be called only when necessary


Applied to 5.10/scsi-queue, thanks!

[1/1] scsi: mpt3sas: Fix sync irqs
      https://git.kernel.org/mkp/scsi/c/45181eab8ba7

-- 
Martin K. Petersen	Oracle Linux Engineering
diff mbox series

Patch

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index a85c9672c6ea..a67749c8f4ab 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -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));
 	}
 }