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 5f045505a1f4..76d294fc7846 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
| @@ -4189,6 +4189,25 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, | |||
| 4189 | } | 4189 | } |
| 4190 | 4190 | ||
| 4191 | /** | 4191 | /** |
| 4192 | * ipr_isr_eh - Interrupt service routine error handler | ||
| 4193 | * @ioa_cfg: ioa config struct | ||
| 4194 | * @msg: message to log | ||
| 4195 | * | ||
| 4196 | * Return value: | ||
| 4197 | * none | ||
| 4198 | **/ | ||
| 4199 | static void ipr_isr_eh(struct ipr_ioa_cfg *ioa_cfg, char *msg) | ||
| 4200 | { | ||
| 4201 | ioa_cfg->errors_logged++; | ||
| 4202 | dev_err(&ioa_cfg->pdev->dev, "%s\n", msg); | ||
| 4203 | |||
| 4204 | if (WAIT_FOR_DUMP == ioa_cfg->sdt_state) | ||
| 4205 | ioa_cfg->sdt_state = GET_DUMP; | ||
| 4206 | |||
| 4207 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); | ||
| 4208 | } | ||
| 4209 | |||
| 4210 | /** | ||
| 4192 | * ipr_isr - Interrupt service routine | 4211 | * ipr_isr - Interrupt service routine |
| 4193 | * @irq: irq number | 4212 | * @irq: irq number |
| 4194 | * @devp: pointer to ioa config struct | 4213 | * @devp: pointer to ioa config struct |
| @@ -4203,6 +4222,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
| 4203 | volatile u32 int_reg, int_mask_reg; | 4222 | volatile u32 int_reg, int_mask_reg; |
| 4204 | u32 ioasc; | 4223 | u32 ioasc; |
| 4205 | u16 cmd_index; | 4224 | u16 cmd_index; |
| 4225 | int num_hrrq = 0; | ||
| 4206 | struct ipr_cmnd *ipr_cmd; | 4226 | struct ipr_cmnd *ipr_cmd; |
| 4207 | irqreturn_t rc = IRQ_NONE; | 4227 | irqreturn_t rc = IRQ_NONE; |
| 4208 | 4228 | ||
| @@ -4233,13 +4253,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
| 4233 | IPR_HRRQ_REQ_RESP_HANDLE_MASK) >> IPR_HRRQ_REQ_RESP_HANDLE_SHIFT; | 4253 | IPR_HRRQ_REQ_RESP_HANDLE_MASK) >> IPR_HRRQ_REQ_RESP_HANDLE_SHIFT; |
| 4234 | 4254 | ||
| 4235 | if (unlikely(cmd_index >= IPR_NUM_CMD_BLKS)) { | 4255 | if (unlikely(cmd_index >= IPR_NUM_CMD_BLKS)) { |
| 4236 | ioa_cfg->errors_logged++; | 4256 | ipr_isr_eh(ioa_cfg, "Invalid response handle from IOA"); |
| 4237 | dev_err(&ioa_cfg->pdev->dev, "Invalid response handle from IOA\n"); | ||
| 4238 | |||
| 4239 | if (WAIT_FOR_DUMP == ioa_cfg->sdt_state) | ||
| 4240 | ioa_cfg->sdt_state = GET_DUMP; | ||
| 4241 | |||
| 4242 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); | ||
| 4243 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 4257 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
| 4244 | return IRQ_HANDLED; | 4258 | return IRQ_HANDLED; |
| 4245 | } | 4259 | } |
| @@ -4266,8 +4280,18 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
| 4266 | 4280 | ||
| 4267 | if (ipr_cmd != NULL) { | 4281 | if (ipr_cmd != NULL) { |
| 4268 | /* Clear the PCI interrupt */ | 4282 | /* Clear the PCI interrupt */ |
| 4269 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg); | 4283 | do { |
| 4270 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | 4284 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg); |
| 4285 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
| 4286 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && | ||
| 4287 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); | ||
| 4288 | |||
| 4289 | if (int_reg & IPR_PCII_HRRQ_UPDATED) { | ||
| 4290 | ipr_isr_eh(ioa_cfg, "Error clearing HRRQ"); | ||
| 4291 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
| 4292 | return IRQ_HANDLED; | ||
| 4293 | } | ||
| 4294 | |||
| 4271 | } else | 4295 | } else |
| 4272 | break; | 4296 | break; |
| 4273 | } | 4297 | } |
