From: Steve Best <sbest@redhat.com> Date: Thu, 16 Sep 2010 19:45:52 -0400 Subject: [scsi] ipr: back out isr optimization changes Message-id: <20100916193342.9480.41251.sendpatchset@squad5-lp1.lab.bos.redhat.com> Patchwork-id: 28272 O-Subject: [PATCH RHEL5.6 BZ634213 2/2] [SCSI] ipr: reverse the isr optimization changes Bugzilla: 634213 RHBZ#: ------ https://bugzilla.redhat.com/show_bug.cgi?id=634213 Description: ------------ 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> RHEL Version Found: ------------------- 5.6 Brew: ----- Built on all platforms. All patches brewed together. http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2766428 Upstream Status: ---------------- http://git.kernel.org/?p=linux/kernel/git/jejb/scsi-misc-2.6.git; a=commit;h=634651fab36dc8d7c3b1a1aa14f9ec1e29de9f0f --------------------------------------- Steve Best IBM on-site partner Proposed Patch: --------------- Signed-off-by: Jarod Wilson <jarod@redhat.com> diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 8e6b43d..1cfa525 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4908,39 +4908,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 */ @@ -5002,7 +4978,7 @@ static irqreturn_t ipr_isr(int irq, void *devp, struct pt_regs *regs) { 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; @@ -5017,6 +4993,33 @@ static irqreturn_t ipr_isr(int irq, void *devp, struct pt_regs *regs) 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; @@ -5056,7 +5059,7 @@ static irqreturn_t ipr_isr(int irq, void *devp, struct pt_regs *regs) /* 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); @@ -5071,7 +5074,7 @@ static irqreturn_t ipr_isr(int irq, void *devp, struct pt_regs *regs) } 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;