diff options
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index d40d5c79fff1..206c2fa8c1ba 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -4194,6 +4194,25 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, | |||
4194 | } | 4194 | } |
4195 | 4195 | ||
4196 | /** | 4196 | /** |
4197 | * ipr_isr_eh - Interrupt service routine error handler | ||
4198 | * @ioa_cfg: ioa config struct | ||
4199 | * @msg: message to log | ||
4200 | * | ||
4201 | * Return value: | ||
4202 | * none | ||
4203 | **/ | ||
4204 | static void ipr_isr_eh(struct ipr_ioa_cfg *ioa_cfg, char *msg) | ||
4205 | { | ||
4206 | ioa_cfg->errors_logged++; | ||
4207 | dev_err(&ioa_cfg->pdev->dev, "%s\n", msg); | ||
4208 | |||
4209 | if (WAIT_FOR_DUMP == ioa_cfg->sdt_state) | ||
4210 | ioa_cfg->sdt_state = GET_DUMP; | ||
4211 | |||
4212 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); | ||
4213 | } | ||
4214 | |||
4215 | /** | ||
4197 | * ipr_isr - Interrupt service routine | 4216 | * ipr_isr - Interrupt service routine |
4198 | * @irq: irq number | 4217 | * @irq: irq number |
4199 | * @devp: pointer to ioa config struct | 4218 | * @devp: pointer to ioa config struct |
@@ -4208,6 +4227,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
4208 | volatile u32 int_reg, int_mask_reg; | 4227 | volatile u32 int_reg, int_mask_reg; |
4209 | u32 ioasc; | 4228 | u32 ioasc; |
4210 | u16 cmd_index; | 4229 | u16 cmd_index; |
4230 | int num_hrrq = 0; | ||
4211 | struct ipr_cmnd *ipr_cmd; | 4231 | struct ipr_cmnd *ipr_cmd; |
4212 | irqreturn_t rc = IRQ_NONE; | 4232 | irqreturn_t rc = IRQ_NONE; |
4213 | 4233 | ||
@@ -4238,13 +4258,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
4238 | IPR_HRRQ_REQ_RESP_HANDLE_MASK) >> IPR_HRRQ_REQ_RESP_HANDLE_SHIFT; | 4258 | IPR_HRRQ_REQ_RESP_HANDLE_MASK) >> IPR_HRRQ_REQ_RESP_HANDLE_SHIFT; |
4239 | 4259 | ||
4240 | if (unlikely(cmd_index >= IPR_NUM_CMD_BLKS)) { | 4260 | if (unlikely(cmd_index >= IPR_NUM_CMD_BLKS)) { |
4241 | ioa_cfg->errors_logged++; | 4261 | ipr_isr_eh(ioa_cfg, "Invalid response handle from IOA"); |
4242 | dev_err(&ioa_cfg->pdev->dev, "Invalid response handle from IOA\n"); | ||
4243 | |||
4244 | if (WAIT_FOR_DUMP == ioa_cfg->sdt_state) | ||
4245 | ioa_cfg->sdt_state = GET_DUMP; | ||
4246 | |||
4247 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); | ||
4248 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 4262 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
4249 | return IRQ_HANDLED; | 4263 | return IRQ_HANDLED; |
4250 | } | 4264 | } |
@@ -4271,8 +4285,18 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
4271 | 4285 | ||
4272 | if (ipr_cmd != NULL) { | 4286 | if (ipr_cmd != NULL) { |
4273 | /* Clear the PCI interrupt */ | 4287 | /* Clear the PCI interrupt */ |
4274 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg); | 4288 | do { |
4275 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | 4289 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg); |
4290 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
4291 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && | ||
4292 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); | ||
4293 | |||
4294 | if (int_reg & IPR_PCII_HRRQ_UPDATED) { | ||
4295 | ipr_isr_eh(ioa_cfg, "Error clearing HRRQ"); | ||
4296 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
4297 | return IRQ_HANDLED; | ||
4298 | } | ||
4299 | |||
4276 | } else | 4300 | } else |
4277 | break; | 4301 | break; |
4278 | } | 4302 | } |