Commit 3feeb89d authored by Wayne Boyer's avatar Wayne Boyer Committed by James Bottomley

[SCSI] ipr: add workaround for MSI interrupts on P7

This patch adds some additional logic to the interrupt service routine to fix
a potential problem where an MSI interrupt does not get cleared the first time.
Signed-off-by: default avatarWayne Boyer <wayneb@linux.vnet.ibm.com>
Acked-by: default avatarBrian King <brking@linux.vnet.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 61ec33eb
...@@ -4188,6 +4188,25 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, ...@@ -4188,6 +4188,25 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
return rc; return rc;
} }
/**
* ipr_isr_eh - Interrupt service routine error handler
* @ioa_cfg: ioa config struct
* @msg: message to log
*
* Return value:
* none
**/
static void ipr_isr_eh(struct ipr_ioa_cfg *ioa_cfg, char *msg)
{
ioa_cfg->errors_logged++;
dev_err(&ioa_cfg->pdev->dev, "%s\n", msg);
if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
ioa_cfg->sdt_state = GET_DUMP;
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
}
/** /**
* ipr_isr - Interrupt service routine * ipr_isr - Interrupt service routine
* @irq: irq number * @irq: irq number
...@@ -4203,6 +4222,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) ...@@ -4203,6 +4222,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
volatile u32 int_reg, int_mask_reg; volatile u32 int_reg, int_mask_reg;
u32 ioasc; u32 ioasc;
u16 cmd_index; u16 cmd_index;
int num_hrrq = 0;
struct ipr_cmnd *ipr_cmd; struct ipr_cmnd *ipr_cmd;
irqreturn_t rc = IRQ_NONE; irqreturn_t rc = IRQ_NONE;
...@@ -4233,13 +4253,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) ...@@ -4233,13 +4253,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
IPR_HRRQ_REQ_RESP_HANDLE_MASK) >> IPR_HRRQ_REQ_RESP_HANDLE_SHIFT; IPR_HRRQ_REQ_RESP_HANDLE_MASK) >> IPR_HRRQ_REQ_RESP_HANDLE_SHIFT;
if (unlikely(cmd_index >= IPR_NUM_CMD_BLKS)) { if (unlikely(cmd_index >= IPR_NUM_CMD_BLKS)) {
ioa_cfg->errors_logged++; ipr_isr_eh(ioa_cfg, "Invalid response handle from IOA");
dev_err(&ioa_cfg->pdev->dev, "Invalid response handle from IOA\n");
if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
ioa_cfg->sdt_state = GET_DUMP;
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -4266,8 +4280,18 @@ static irqreturn_t ipr_isr(int irq, void *devp) ...@@ -4266,8 +4280,18 @@ static irqreturn_t ipr_isr(int irq, void *devp)
if (ipr_cmd != NULL) { if (ipr_cmd != NULL) {
/* Clear the PCI interrupt */ /* Clear the PCI interrupt */
writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg); do {
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
} 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 } else
break; break;
} }
......
...@@ -144,6 +144,7 @@ ...@@ -144,6 +144,7 @@
#define IPR_IOA_MAX_SECTORS 32767 #define IPR_IOA_MAX_SECTORS 32767
#define IPR_VSET_MAX_SECTORS 512 #define IPR_VSET_MAX_SECTORS 512
#define IPR_MAX_CDB_LEN 16 #define IPR_MAX_CDB_LEN 16
#define IPR_MAX_HRRQ_RETRIES 3
#define IPR_DEFAULT_BUS_WIDTH 16 #define IPR_DEFAULT_BUS_WIDTH 16
#define IPR_80MBs_SCSI_RATE ((80 * 10) / (IPR_DEFAULT_BUS_WIDTH / 8)) #define IPR_80MBs_SCSI_RATE ((80 * 10) / (IPR_DEFAULT_BUS_WIDTH / 8))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment