diff options
author | Wayne Boyer <wayneb@linux.vnet.ibm.com> | 2010-08-28 01:45:07 +0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-09-10 00:36:15 +0400 |
commit | 634651fab36dc8d7c3b1a1aa14f9ec1e29de9f0f (patch) | |
tree | aeb10cc042b9fde8cf935d70a92d778de02508b5 /drivers/scsi/ipr.c | |
parent | 6014759c929b4ce8c068810b8d05f31969df5897 (diff) | |
download | linux-634651fab36dc8d7c3b1a1aa14f9ec1e29de9f0f.tar.xz |
[SCSI] ipr: reverse the isr optimization changes
The isr optimization patch that was submitted a few months ago
exposed problems with receiving and handling spurious HRRQ interrutps.
commit 64ffdb762241c0a9c0c8fac7ea92aa0ba1529334
Author: Wayne Boyer <wayneb@linux.vnet.ibm.com>
Date: Wed May 19 11:56:13 2010 -0700
[SCSI] ipr: improve interrupt service routine performance
That patch is reverted with this one. A new patch will be submitted
once the issue is better understood and properly handled in the driver.
Signed-off-by: Wayne Boyer <wayneb@linux.vnet.ibm.com>
Acked-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 67875d41345f..3b28e8728131 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4939,39 +4939,15 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd) /** * ipr_handle_other_interrupt - Handle "other" interrupts * @ioa_cfg: ioa config struct + * @int_reg: interrupt register * * Return value: * IRQ_NONE / IRQ_HANDLED **/ -static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg) +static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, + volatile u32 int_reg) { irqreturn_t rc = IRQ_HANDLED; - volatile u32 int_reg, int_mask_reg; - - int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; - - /* If an interrupt on the adapter did not occur, ignore it. - * Or in the case of SIS 64, check for a stage change interrupt. - */ - if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) { - if (ioa_cfg->sis64) { - int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; - if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { - - /* clear stage change */ - writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; - list_del(&ioa_cfg->reset_cmd->queue); - del_timer(&ioa_cfg->reset_cmd->timer); - ipr_reset_ioa_job(ioa_cfg->reset_cmd); - return IRQ_HANDLED; - } - } - - return IRQ_NONE; - } if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { /* Mask the interrupt */ @@ -5032,7 +5008,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) { struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; unsigned long lock_flags = 0; - volatile u32 int_reg; + volatile u32 int_reg, int_mask_reg; u32 ioasc; u16 cmd_index; int num_hrrq = 0; @@ -5047,6 +5023,33 @@ static irqreturn_t ipr_isr(int irq, void *devp) return IRQ_NONE; } + int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; + + /* If an interrupt on the adapter did not occur, ignore it. + * Or in the case of SIS 64, check for a stage change interrupt. + */ + if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) { + if (ioa_cfg->sis64) { + int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; + if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { + + /* clear stage change */ + writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; + list_del(&ioa_cfg->reset_cmd->queue); + del_timer(&ioa_cfg->reset_cmd->timer); + ipr_reset_ioa_job(ioa_cfg->reset_cmd); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return IRQ_HANDLED; + } + } + + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return IRQ_NONE; + } + while (1) { ipr_cmd = NULL; @@ -5086,7 +5089,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) /* Clear the PCI interrupt */ do { writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; } while (int_reg & IPR_PCII_HRRQ_UPDATED && num_hrrq++ < IPR_MAX_HRRQ_RETRIES); @@ -5101,7 +5104,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) } if (unlikely(rc == IRQ_NONE)) - rc = ipr_handle_other_interrupt(ioa_cfg); + rc = ipr_handle_other_interrupt(ioa_cfg, int_reg); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); return rc; |