diff options
author | Vikas Chaudhary <vikas.chaudhary@qlogic.com> | 2012-11-23 15:58:38 +0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-01-29 06:55:06 +0400 |
commit | 5c19b92ae82a2b39add78b2d2bc1c4e4d7c4d2ec (patch) | |
tree | 6c90d253925988191a522e0f718a871110fe646a /drivers/scsi/qla4xxx/ql4_83xx.c | |
parent | 8108de9739abeec72f4811532109695e245df42a (diff) | |
download | linux-5c19b92ae82a2b39add78b2d2bc1c4e4d7c4d2ec.tar.xz |
[SCSI] qla4xxx: Fix MBOX intr switching from polling to intr mode for ISP83XX
Issue:
Mailbox command timed out after switching from polling mode to interrupt mode.
Events:-
1. Mailbox interrupts are disabled
2. FW generates AEN and at same time driver enables Mailbox Interrupt
3. Driver issues new mailbox to Firmware
In above case driver will not get AEN interrupts generated by FW in step #2 as
FW generated this AEN when interrupts are disabled. During the same time
driver enabled the mailbox interrupt, so driver will not poll for interrupt.
Driver will never process AENs generated in step #2 and issues new mailbox to
FW, but now FW is not able to post mailbox completion as AENs generated before
are not processed by driver.
Fix:
Enable Mailbox / AEN interrupts before initializing FW in case of ISP83XX.
This will make sure we process all Mailbox and AENs in interrupt mode.
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_83xx.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_83xx.c | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.c b/drivers/scsi/qla4xxx/ql4_83xx.c index 6e9af20be12f..417738366c1f 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.c +++ b/drivers/scsi/qla4xxx/ql4_83xx.c @@ -1351,31 +1351,58 @@ exit_start_fw: /*----------------------Interrupt Related functions ---------------------*/ -void qla4_83xx_disable_intrs(struct scsi_qla_host *ha) +static void qla4_83xx_disable_iocb_intrs(struct scsi_qla_host *ha) +{ + if (test_and_clear_bit(AF_83XX_IOCB_INTR_ON, &ha->flags)) + qla4_8xxx_intr_disable(ha); +} + +static void qla4_83xx_disable_mbox_intrs(struct scsi_qla_host *ha) { uint32_t mb_int, ret; - if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags)) - qla4_8xxx_mbx_intr_disable(ha); + if (test_and_clear_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) { + ret = readl(&ha->qla4_83xx_reg->mbox_int); + mb_int = ret & ~INT_ENABLE_FW_MB; + writel(mb_int, &ha->qla4_83xx_reg->mbox_int); + writel(1, &ha->qla4_83xx_reg->leg_int_mask); + } +} - ret = readl(&ha->qla4_83xx_reg->mbox_int); - mb_int = ret & ~INT_ENABLE_FW_MB; - writel(mb_int, &ha->qla4_83xx_reg->mbox_int); - writel(1, &ha->qla4_83xx_reg->leg_int_mask); +void qla4_83xx_disable_intrs(struct scsi_qla_host *ha) +{ + qla4_83xx_disable_mbox_intrs(ha); + qla4_83xx_disable_iocb_intrs(ha); } -void qla4_83xx_enable_intrs(struct scsi_qla_host *ha) +static void qla4_83xx_enable_iocb_intrs(struct scsi_qla_host *ha) +{ + if (!test_bit(AF_83XX_IOCB_INTR_ON, &ha->flags)) { + qla4_8xxx_intr_enable(ha); + set_bit(AF_83XX_IOCB_INTR_ON, &ha->flags); + } +} + +void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha) { uint32_t mb_int; - qla4_8xxx_mbx_intr_enable(ha); - mb_int = INT_ENABLE_FW_MB; - writel(mb_int, &ha->qla4_83xx_reg->mbox_int); - writel(0, &ha->qla4_83xx_reg->leg_int_mask); + if (!test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) { + mb_int = INT_ENABLE_FW_MB; + writel(mb_int, &ha->qla4_83xx_reg->mbox_int); + writel(0, &ha->qla4_83xx_reg->leg_int_mask); + set_bit(AF_83XX_MBOX_INTR_ON, &ha->flags); + } +} - set_bit(AF_INTERRUPTS_ON, &ha->flags); + +void qla4_83xx_enable_intrs(struct scsi_qla_host *ha) +{ + qla4_83xx_enable_mbox_intrs(ha); + qla4_83xx_enable_iocb_intrs(ha); } + void qla4_83xx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd, int incount) { |