aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/ipr.c63
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 **/
4946static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg) 4947static 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;