diff options
author | Wayne Boyer <wayneb@linux.vnet.ibm.com> | 2010-08-27 17:45:07 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-09-09 16:36:15 -0400 |
commit | 634651fab36dc8d7c3b1a1aa14f9ec1e29de9f0f (patch) | |
tree | aeb10cc042b9fde8cf935d70a92d778de02508b5 /drivers/scsi/ipr.c | |
parent | 6014759c929b4ce8c068810b8d05f31969df5897 (diff) |
[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) | |||
4939 | /** | 4939 | /** |
4940 | * ipr_handle_other_interrupt - Handle "other" interrupts | 4940 | * ipr_handle_other_interrupt - Handle "other" interrupts |
4941 | * @ioa_cfg: ioa config struct | 4941 | * @ioa_cfg: ioa config struct |
4942 | * @int_reg: interrupt register | ||
4942 | * | 4943 | * |
4943 | * Return value: | 4944 | * Return value: |
4944 | * IRQ_NONE / IRQ_HANDLED | 4945 | * IRQ_NONE / IRQ_HANDLED |
4945 | **/ | 4946 | **/ |
4946 | static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg) | 4947 | static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, |
4948 | volatile u32 int_reg) | ||
4947 | { | 4949 | { |
4948 | irqreturn_t rc = IRQ_HANDLED; | 4950 | irqreturn_t rc = IRQ_HANDLED; |
4949 | volatile u32 int_reg, int_mask_reg; | ||
4950 | |||
4951 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); | ||
4952 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; | ||
4953 | |||
4954 | /* If an interrupt on the adapter did not occur, ignore it. | ||
4955 | * Or in the case of SIS 64, check for a stage change interrupt. | ||
4956 | */ | ||
4957 | if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) { | ||
4958 | if (ioa_cfg->sis64) { | ||
4959 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); | ||
4960 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
4961 | if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { | ||
4962 | |||
4963 | /* clear stage change */ | ||
4964 | writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); | ||
4965 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
4966 | list_del(&ioa_cfg->reset_cmd->queue); | ||
4967 | del_timer(&ioa_cfg->reset_cmd->timer); | ||
4968 | ipr_reset_ioa_job(ioa_cfg->reset_cmd); | ||
4969 | return IRQ_HANDLED; | ||
4970 | } | ||
4971 | } | ||
4972 | |||
4973 | return IRQ_NONE; | ||
4974 | } | ||
4975 | 4951 | ||
4976 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { | 4952 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { |
4977 | /* Mask the interrupt */ | 4953 | /* Mask the interrupt */ |
@@ -5032,7 +5008,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
5032 | { | 5008 | { |
5033 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; | 5009 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; |
5034 | unsigned long lock_flags = 0; | 5010 | unsigned long lock_flags = 0; |
5035 | volatile u32 int_reg; | 5011 | volatile u32 int_reg, int_mask_reg; |
5036 | u32 ioasc; | 5012 | u32 ioasc; |
5037 | u16 cmd_index; | 5013 | u16 cmd_index; |
5038 | int num_hrrq = 0; | 5014 | int num_hrrq = 0; |
@@ -5047,6 +5023,33 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
5047 | return IRQ_NONE; | 5023 | return IRQ_NONE; |
5048 | } | 5024 | } |
5049 | 5025 | ||
5026 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); | ||
5027 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; | ||
5028 | |||
5029 | /* If an interrupt on the adapter did not occur, ignore it. | ||
5030 | * Or in the case of SIS 64, check for a stage change interrupt. | ||
5031 | */ | ||
5032 | if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) { | ||
5033 | if (ioa_cfg->sis64) { | ||
5034 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); | ||
5035 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
5036 | if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { | ||
5037 | |||
5038 | /* clear stage change */ | ||
5039 | writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); | ||
5040 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
5041 | list_del(&ioa_cfg->reset_cmd->queue); | ||
5042 | del_timer(&ioa_cfg->reset_cmd->timer); | ||
5043 | ipr_reset_ioa_job(ioa_cfg->reset_cmd); | ||
5044 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
5045 | return IRQ_HANDLED; | ||
5046 | } | ||
5047 | } | ||
5048 | |||
5049 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
5050 | return IRQ_NONE; | ||
5051 | } | ||
5052 | |||
5050 | while (1) { | 5053 | while (1) { |
5051 | ipr_cmd = NULL; | 5054 | ipr_cmd = NULL; |
5052 | 5055 | ||
@@ -5086,7 +5089,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
5086 | /* Clear the PCI interrupt */ | 5089 | /* Clear the PCI interrupt */ |
5087 | do { | 5090 | do { |
5088 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); | 5091 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); |
5089 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); | 5092 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; |
5090 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && | 5093 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && |
5091 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); | 5094 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); |
5092 | 5095 | ||
@@ -5101,7 +5104,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
5101 | } | 5104 | } |
5102 | 5105 | ||
5103 | if (unlikely(rc == IRQ_NONE)) | 5106 | if (unlikely(rc == IRQ_NONE)) |
5104 | rc = ipr_handle_other_interrupt(ioa_cfg); | 5107 | rc = ipr_handle_other_interrupt(ioa_cfg, int_reg); |
5105 | 5108 | ||
5106 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 5109 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
5107 | return rc; | 5110 | return rc; |