aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorWayne Boyer <wayneb@linux.vnet.ibm.com>2010-05-19 14:56:13 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-05-24 12:11:06 -0400
commit64ffdb762241c0a9c0c8fac7ea92aa0ba1529334 (patch)
tree725809ab8f69e6df498ae51b58193d9fa38f702b /drivers/scsi
parentb8803b1cef28af785c4e903b9b1449898d68c758 (diff)
[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: 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')
-rw-r--r--drivers/scsi/ipr.c63
1 files changed, 30 insertions, 33 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5244282cd97f..82ea4a8226b0 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -4818,15 +4818,39 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd)
4818/** 4818/**
4819 * ipr_handle_other_interrupt - Handle "other" interrupts 4819 * ipr_handle_other_interrupt - Handle "other" interrupts
4820 * @ioa_cfg: ioa config struct 4820 * @ioa_cfg: ioa config struct
4821 * @int_reg: interrupt register
4822 * 4821 *
4823 * Return value: 4822 * Return value:
4824 * IRQ_NONE / IRQ_HANDLED 4823 * IRQ_NONE / IRQ_HANDLED
4825 **/ 4824 **/
4826static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, 4825static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg)
4827 volatile u32 int_reg)
4828{ 4826{
4829 irqreturn_t rc = IRQ_HANDLED; 4827 irqreturn_t rc = IRQ_HANDLED;
4828 volatile u32 int_reg, int_mask_reg;
4829
4830 int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
4831 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
4832
4833 /* If an interrupt on the adapter did not occur, ignore it.
4834 * Or in the case of SIS 64, check for a stage change interrupt.
4835 */
4836 if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) {
4837 if (ioa_cfg->sis64) {
4838 int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
4839 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
4840 if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
4841
4842 /* clear stage change */
4843 writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
4844 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
4845 list_del(&ioa_cfg->reset_cmd->queue);
4846 del_timer(&ioa_cfg->reset_cmd->timer);
4847 ipr_reset_ioa_job(ioa_cfg->reset_cmd);
4848 return IRQ_HANDLED;
4849 }
4850 }
4851
4852 return IRQ_NONE;
4853 }
4830 4854
4831 if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { 4855 if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
4832 /* Mask the interrupt */ 4856 /* Mask the interrupt */
@@ -4887,7 +4911,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
4887{ 4911{
4888 struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; 4912 struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
4889 unsigned long lock_flags = 0; 4913 unsigned long lock_flags = 0;
4890 volatile u32 int_reg, int_mask_reg; 4914 volatile u32 int_reg;
4891 u32 ioasc; 4915 u32 ioasc;
4892 u16 cmd_index; 4916 u16 cmd_index;
4893 int num_hrrq = 0; 4917 int num_hrrq = 0;
@@ -4902,33 +4926,6 @@ static irqreturn_t ipr_isr(int irq, void *devp)
4902 return IRQ_NONE; 4926 return IRQ_NONE;
4903 } 4927 }
4904 4928
4905 int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
4906 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
4907
4908 /* If an interrupt on the adapter did not occur, ignore it.
4909 * Or in the case of SIS 64, check for a stage change interrupt.
4910 */
4911 if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) {
4912 if (ioa_cfg->sis64) {
4913 int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
4914 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
4915 if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
4916
4917 /* clear stage change */
4918 writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
4919 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
4920 list_del(&ioa_cfg->reset_cmd->queue);
4921 del_timer(&ioa_cfg->reset_cmd->timer);
4922 ipr_reset_ioa_job(ioa_cfg->reset_cmd);
4923 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
4924 return IRQ_HANDLED;
4925 }
4926 }
4927
4928 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
4929 return IRQ_NONE;
4930 }
4931
4932 while (1) { 4929 while (1) {
4933 ipr_cmd = NULL; 4930 ipr_cmd = NULL;
4934 4931
@@ -4968,7 +4965,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
4968 /* Clear the PCI interrupt */ 4965 /* Clear the PCI interrupt */
4969 do { 4966 do {
4970 writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); 4967 writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
4971 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; 4968 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
4972 } while (int_reg & IPR_PCII_HRRQ_UPDATED && 4969 } while (int_reg & IPR_PCII_HRRQ_UPDATED &&
4973 num_hrrq++ < IPR_MAX_HRRQ_RETRIES); 4970 num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
4974 4971
@@ -4983,7 +4980,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
4983 } 4980 }
4984 4981
4985 if (unlikely(rc == IRQ_NONE)) 4982 if (unlikely(rc == IRQ_NONE))
4986 rc = ipr_handle_other_interrupt(ioa_cfg, int_reg); 4983 rc = ipr_handle_other_interrupt(ioa_cfg);
4987 4984
4988 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); 4985 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
4989 return rc; 4986 return rc;