[SCSI] ipr: fix possible false positive detection of stuck interrupt
authorWayne Boyer <wayneb@linux.vnet.ibm.com>
Tue, 17 May 2011 16:18:53 +0000 (09:18 -0700)
committerJames Bottomley <jbottomley@parallels.com>
Tue, 24 May 2011 16:37:50 +0000 (12:37 -0400)
If the driver is getting flooded with interrupts, there's a possibility
that the interrupt service routine could falsely detect a stuck interrupt
condition and reset the adapter.

This patch changes the logic such that the routine will loop back into
the command processing code one more time after detecting the stuck
interrupt signature.  If there are no commands to process after that pass,
and the interrupt is still not cleared, then the driver will print the
"Error clearing HRRQ" message and reset the adapter.

Signed-off-by: Wayne Boyer <wayneb@linux.vnet.ibm.com>
Acked-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <jbottomley@parallels.com>
drivers/scsi/ipr.c

index 12868ca461108547d2eafdbc1e9c5e1d95219501..888086c4e709497e6d8c7ae9e02dcf06b5bbca18 100644 (file)
@@ -5149,21 +5149,21 @@ static irqreturn_t ipr_isr(int irq, void *devp)
 
                if (ipr_cmd != NULL) {
                        /* Clear the PCI interrupt */
+                       num_hrrq = 0;
                        do {
                                writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
                                int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
                        } while (int_reg & IPR_PCII_HRRQ_UPDATED &&
                                        num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
 
-                       if (int_reg & IPR_PCII_HRRQ_UPDATED) {
-                               ipr_isr_eh(ioa_cfg, "Error clearing HRRQ");
-                               spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-                               return IRQ_HANDLED;
-                       }
-
                } else if (rc == IRQ_NONE && irq_none == 0) {
                        int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
                        irq_none++;
+               } else if (num_hrrq == IPR_MAX_HRRQ_RETRIES &&
+                          int_reg & IPR_PCII_HRRQ_UPDATED) {
+                       ipr_isr_eh(ioa_cfg, "Error clearing HRRQ");
+                       spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+                       return IRQ_HANDLED;
                } else
                        break;
        }