summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrking@us.ibm.com <brking@us.ibm.com>2005-11-17 16:35:12 +0100
committerJames Bottomley <jejb@mulgrave.(none)>2005-12-14 02:10:58 +0100
commitce155ccecd4094e7b5e68058d26db691713240fc (patch)
tree1bc690d3f0555b05c3be587267c01135fa829563
parent[SCSI] megaraid_{mbox,mm} : remove PCI Id overlaping between megaraid_legacy ... (diff)
downloadlinux-ce155ccecd4094e7b5e68058d26db691713240fc.tar.xz
linux-ce155ccecd4094e7b5e68058d26db691713240fc.zip
[SCSI] ipr: Driver initialization fix for kexec/kdump
When kexec booting a kernel when the previous kernel did not call ipr's shutdown method, the ipr adapter does not get properly initialized, which can result in the ipr adapter completing commands issued by the previous kernel. Fix ipr to detect this scenario by reading the adapter's interrupt mask register and the microprocessor interrupt register. If the interrupt mask register indicates that interrupts are enabled or the reset alert bit is set when the card is probed, this means the card is in an unknown state and we hard reset the card. Signed-off-by: Brian King <brking@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/ipr.c17
-rw-r--r--drivers/scsi/ipr.h5
2 files changed, 19 insertions, 3 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index fa2cb3582cfa..b6714da4d6e2 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -5887,7 +5887,12 @@ static int __devinit ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
ENTER;
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
dev_dbg(&ioa_cfg->pdev->dev, "ioa_cfg adx: 0x%p\n", ioa_cfg);
- _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_enable_ioa, IPR_SHUTDOWN_NONE);
+ if (ioa_cfg->needs_hard_reset) {
+ ioa_cfg->needs_hard_reset = 0;
+ ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
+ } else
+ _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_enable_ioa,
+ IPR_SHUTDOWN_NONE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
@@ -6264,6 +6269,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
unsigned long ipr_regs_pci;
void __iomem *ipr_regs;
u32 rc = PCIBIOS_SUCCESSFUL;
+ volatile u32 mask, uproc;
ENTER;
@@ -6356,6 +6362,15 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
goto cleanup_nomem;
}
+ /*
+ * If HRRQ updated interrupt is not masked, or reset alert is set,
+ * the card is in an unknown state and needs a hard reset
+ */
+ mask = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+ uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg);
+ if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT))
+ ioa_cfg->needs_hard_reset = 1;
+
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
rc = request_irq(pdev->irq, ipr_isr, SA_SHIRQ, IPR_NAME, ioa_cfg);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 6bec673c925c..b639332131f1 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.1.0"
-#define IPR_DRIVER_DATE "(October 31, 2005)"
+#define IPR_DRIVER_VERSION "2.1.1"
+#define IPR_DRIVER_DATE "(November 15, 2005)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -922,6 +922,7 @@ struct ipr_ioa_cfg {
u8 dump_taken:1;
u8 allow_cmds:1;
u8 allow_ml_add_del:1;
+ u8 needs_hard_reset:1;
enum ipr_cache_state cache_state;
u16 type; /* CCIN of the card */