Commit 64ffdb76 authored by Wayne Boyer's avatar Wayne Boyer Committed by James Bottomley

[SCSI] ipr: improve interrupt service routine performance

During performance testing on P7 machines it was observed that the interrupt
service routine was doing unnecessary MMIO operations.

This patch rearranges the logic of the routine and moves some of the code out
of the main routine.  The result is that there are now fewer MMIO operations in
the performance path of the code.
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 b8803b1c
...@@ -4818,15 +4818,39 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd) ...@@ -4818,15 +4818,39 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd)
/** /**
* ipr_handle_other_interrupt - Handle "other" interrupts * ipr_handle_other_interrupt - Handle "other" interrupts
* @ioa_cfg: ioa config struct * @ioa_cfg: ioa config struct
* @int_reg: interrupt register
* *
* Return value: * Return value:
* IRQ_NONE / IRQ_HANDLED * 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; 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) { if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
/* Mask the interrupt */ /* Mask the interrupt */
...@@ -4887,7 +4911,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) ...@@ -4887,7 +4911,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
{ {
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
unsigned long lock_flags = 0; unsigned long lock_flags = 0;
volatile u32 int_reg, int_mask_reg; volatile u32 int_reg;
u32 ioasc; u32 ioasc;
u16 cmd_index; u16 cmd_index;
int num_hrrq = 0; int num_hrrq = 0;
...@@ -4902,33 +4926,6 @@ static irqreturn_t ipr_isr(int irq, void *devp) ...@@ -4902,33 +4926,6 @@ static irqreturn_t ipr_isr(int irq, void *devp)
return IRQ_NONE; 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) { while (1) {
ipr_cmd = NULL; ipr_cmd = NULL;
...@@ -4968,7 +4965,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) ...@@ -4968,7 +4965,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
/* Clear the PCI interrupt */ /* Clear the PCI interrupt */
do { do {
writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
} while (int_reg & IPR_PCII_HRRQ_UPDATED && } while (int_reg & IPR_PCII_HRRQ_UPDATED &&
num_hrrq++ < IPR_MAX_HRRQ_RETRIES); num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
...@@ -4983,7 +4980,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) ...@@ -4983,7 +4980,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
} }
if (unlikely(rc == IRQ_NONE)) if (unlikely(rc == IRQ_NONE))
rc = ipr_handle_other_interrupt(ioa_cfg, int_reg); rc = ipr_handle_other_interrupt(ioa_cfg);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return rc; return rc;
......
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