diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/ipr.c | 63 |
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 | **/ |
4826 | static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, | 4825 | static 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; |