aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx
diff options
context:
space:
mode:
authorVikas Chaudhary <vikas.chaudhary@qlogic.com>2012-11-23 06:58:38 -0500
committerJames Bottomley <JBottomley@Parallels.com>2013-01-28 21:55:06 -0500
commit5c19b92ae82a2b39add78b2d2bc1c4e4d7c4d2ec (patch)
tree6c90d253925988191a522e0f718a871110fe646a /drivers/scsi/qla4xxx
parent8108de9739abeec72f4811532109695e245df42a (diff)
[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')
-rw-r--r--drivers/scsi/qla4xxx/ql4_83xx.c53
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h5
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c10
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c17
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c41
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c8
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c10
8 files changed, 103 insertions, 43 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:
1351 1351
1352/*----------------------Interrupt Related functions ---------------------*/ 1352/*----------------------Interrupt Related functions ---------------------*/
1353 1353
1354void qla4_83xx_disable_intrs(struct scsi_qla_host *ha) 1354static void qla4_83xx_disable_iocb_intrs(struct scsi_qla_host *ha)
1355{
1356 if (test_and_clear_bit(AF_83XX_IOCB_INTR_ON, &ha->flags))
1357 qla4_8xxx_intr_disable(ha);
1358}
1359
1360static void qla4_83xx_disable_mbox_intrs(struct scsi_qla_host *ha)
1355{ 1361{
1356 uint32_t mb_int, ret; 1362 uint32_t mb_int, ret;
1357 1363
1358 if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags)) 1364 if (test_and_clear_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) {
1359 qla4_8xxx_mbx_intr_disable(ha); 1365 ret = readl(&ha->qla4_83xx_reg->mbox_int);
1366 mb_int = ret & ~INT_ENABLE_FW_MB;
1367 writel(mb_int, &ha->qla4_83xx_reg->mbox_int);
1368 writel(1, &ha->qla4_83xx_reg->leg_int_mask);
1369 }
1370}
1360 1371
1361 ret = readl(&ha->qla4_83xx_reg->mbox_int); 1372void qla4_83xx_disable_intrs(struct scsi_qla_host *ha)
1362 mb_int = ret & ~INT_ENABLE_FW_MB; 1373{
1363 writel(mb_int, &ha->qla4_83xx_reg->mbox_int); 1374 qla4_83xx_disable_mbox_intrs(ha);
1364 writel(1, &ha->qla4_83xx_reg->leg_int_mask); 1375 qla4_83xx_disable_iocb_intrs(ha);
1365} 1376}
1366 1377
1367void qla4_83xx_enable_intrs(struct scsi_qla_host *ha) 1378static void qla4_83xx_enable_iocb_intrs(struct scsi_qla_host *ha)
1379{
1380 if (!test_bit(AF_83XX_IOCB_INTR_ON, &ha->flags)) {
1381 qla4_8xxx_intr_enable(ha);
1382 set_bit(AF_83XX_IOCB_INTR_ON, &ha->flags);
1383 }
1384}
1385
1386void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha)
1368{ 1387{
1369 uint32_t mb_int; 1388 uint32_t mb_int;
1370 1389
1371 qla4_8xxx_mbx_intr_enable(ha); 1390 if (!test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) {
1372 mb_int = INT_ENABLE_FW_MB; 1391 mb_int = INT_ENABLE_FW_MB;
1373 writel(mb_int, &ha->qla4_83xx_reg->mbox_int); 1392 writel(mb_int, &ha->qla4_83xx_reg->mbox_int);
1374 writel(0, &ha->qla4_83xx_reg->leg_int_mask); 1393 writel(0, &ha->qla4_83xx_reg->leg_int_mask);
1394 set_bit(AF_83XX_MBOX_INTR_ON, &ha->flags);
1395 }
1396}
1375 1397
1376 set_bit(AF_INTERRUPTS_ON, &ha->flags); 1398
1399void qla4_83xx_enable_intrs(struct scsi_qla_host *ha)
1400{
1401 qla4_83xx_enable_mbox_intrs(ha);
1402 qla4_83xx_enable_iocb_intrs(ha);
1377} 1403}
1378 1404
1405
1379void qla4_83xx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd, 1406void qla4_83xx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,
1380 int incount) 1407 int incount)
1381{ 1408{
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 329d553eae94..c71a371c452b 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -516,6 +516,8 @@ struct scsi_qla_host {
516#define AF_8XXX_RST_OWNER 25 /* 0x02000000 */ 516#define AF_8XXX_RST_OWNER 25 /* 0x02000000 */
517#define AF_82XX_DUMP_READING 26 /* 0x04000000 */ 517#define AF_82XX_DUMP_READING 26 /* 0x04000000 */
518#define AF_83XX_NO_FW_DUMP 27 /* 0x08000000 */ 518#define AF_83XX_NO_FW_DUMP 27 /* 0x08000000 */
519#define AF_83XX_IOCB_INTR_ON 28 /* 0x10000000 */
520#define AF_83XX_MBOX_INTR_ON 29 /* 0x20000000 */
519 521
520 unsigned long dpc_flags; 522 unsigned long dpc_flags;
521 523
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 57a5a3cf5770..7a2a35a4aed3 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -253,12 +253,13 @@ void qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha);
253void qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha); 253void qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha);
254int qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha); 254int qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha);
255void qla4_8xxx_get_minidump(struct scsi_qla_host *ha); 255void qla4_8xxx_get_minidump(struct scsi_qla_host *ha);
256int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha); 256int qla4_8xxx_intr_disable(struct scsi_qla_host *ha);
257int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha); 257int qla4_8xxx_intr_enable(struct scsi_qla_host *ha);
258int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param); 258int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param);
259int qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha); 259int qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha);
260int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha); 260int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha);
261void qla4_83xx_disable_pause(struct scsi_qla_host *ha); 261void qla4_83xx_disable_pause(struct scsi_qla_host *ha);
262void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha);
262 263
263extern int ql4xextended_error_logging; 264extern int ql4xextended_error_logging;
264extern int ql4xdontresethba; 265extern int ql4xdontresethba;
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 1aca1b4f70b8..2045fd79095f 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -935,6 +935,16 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset)
935 if (ha->isp_ops->start_firmware(ha) == QLA_ERROR) 935 if (ha->isp_ops->start_firmware(ha) == QLA_ERROR)
936 goto exit_init_hba; 936 goto exit_init_hba;
937 937
938 /*
939 * For ISP83XX, mailbox and IOCB interrupts are enabled separately.
940 * Mailbox interrupts must be enabled prior to issuing any mailbox
941 * command in order to prevent the possibility of losing interrupts
942 * while switching from polling to interrupt mode. IOCB interrupts are
943 * enabled via isp_ops->enable_intrs.
944 */
945 if (is_qla8032(ha))
946 qla4_83xx_enable_mbox_intrs(ha);
947
938 if (qla4xxx_about_firmware(ha) == QLA_ERROR) 948 if (qla4xxx_about_firmware(ha) == QLA_ERROR)
939 goto exit_init_hba; 949 goto exit_init_hba;
940 950
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 15ea81465ce4..acbc2feaa005 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -1437,11 +1437,14 @@ irq_not_attached:
1437 1437
1438void qla4xxx_free_irqs(struct scsi_qla_host *ha) 1438void qla4xxx_free_irqs(struct scsi_qla_host *ha)
1439{ 1439{
1440 if (test_bit(AF_MSIX_ENABLED, &ha->flags)) 1440 if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) {
1441 qla4_8xxx_disable_msix(ha); 1441 if (test_bit(AF_MSIX_ENABLED, &ha->flags)) {
1442 else if (test_and_clear_bit(AF_MSI_ENABLED, &ha->flags)) { 1442 qla4_8xxx_disable_msix(ha);
1443 free_irq(ha->pdev->irq, ha); 1443 } else if (test_and_clear_bit(AF_MSI_ENABLED, &ha->flags)) {
1444 pci_disable_msi(ha->pdev); 1444 free_irq(ha->pdev->irq, ha);
1445 } else if (test_and_clear_bit(AF_INTx_ENABLED, &ha->flags)) 1445 pci_disable_msi(ha->pdev);
1446 free_irq(ha->pdev->irq, ha); 1446 } else if (test_and_clear_bit(AF_INTx_ENABLED, &ha->flags)) {
1447 free_irq(ha->pdev->irq, ha);
1448 }
1449 }
1447} 1450}
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 3d41034191f0..1c57c227c808 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -44,6 +44,30 @@ void qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count)
44} 44}
45 45
46/** 46/**
47 * qla4xxx_is_intr_poll_mode – Are we allowed to poll for interrupts?
48 * @ha: Pointer to host adapter structure.
49 * @ret: 1=polling mode, 0=non-polling mode
50 **/
51static int qla4xxx_is_intr_poll_mode(struct scsi_qla_host *ha)
52{
53 int rval = 1;
54
55 if (is_qla8032(ha)) {
56 if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
57 test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags))
58 rval = 0;
59 } else {
60 if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
61 test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
62 test_bit(AF_ONLINE, &ha->flags) &&
63 !test_bit(AF_HA_REMOVAL, &ha->flags))
64 rval = 0;
65 }
66
67 return rval;
68}
69
70/**
47 * qla4xxx_mailbox_command - issues mailbox commands 71 * qla4xxx_mailbox_command - issues mailbox commands
48 * @ha: Pointer to host adapter structure. 72 * @ha: Pointer to host adapter structure.
49 * @inCount: number of mailbox registers to load. 73 * @inCount: number of mailbox registers to load.
@@ -153,33 +177,28 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
153 /* 177 /*
154 * Wait for completion: Poll or completion queue 178 * Wait for completion: Poll or completion queue
155 */ 179 */
156 if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && 180 if (qla4xxx_is_intr_poll_mode(ha)) {
157 test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
158 test_bit(AF_ONLINE, &ha->flags) &&
159 !test_bit(AF_HA_REMOVAL, &ha->flags)) {
160 /* Do not poll for completion. Use completion queue */
161 set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
162 wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
163 clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
164 } else {
165 /* Poll for command to complete */ 181 /* Poll for command to complete */
166 wait_count = jiffies + MBOX_TOV * HZ; 182 wait_count = jiffies + MBOX_TOV * HZ;
167 while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { 183 while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
168 if (time_after_eq(jiffies, wait_count)) 184 if (time_after_eq(jiffies, wait_count))
169 break; 185 break;
170
171 /* 186 /*
172 * Service the interrupt. 187 * Service the interrupt.
173 * The ISR will save the mailbox status registers 188 * The ISR will save the mailbox status registers
174 * to a temporary storage location in the adapter 189 * to a temporary storage location in the adapter
175 * structure. 190 * structure.
176 */ 191 */
177
178 spin_lock_irqsave(&ha->hardware_lock, flags); 192 spin_lock_irqsave(&ha->hardware_lock, flags);
179 ha->isp_ops->process_mailbox_interrupt(ha, outCount); 193 ha->isp_ops->process_mailbox_interrupt(ha, outCount);
180 spin_unlock_irqrestore(&ha->hardware_lock, flags); 194 spin_unlock_irqrestore(&ha->hardware_lock, flags);
181 msleep(10); 195 msleep(10);
182 } 196 }
197 } else {
198 /* Do not poll for completion. Use completion queue */
199 set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
200 wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
201 clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
183 } 202 }
184 203
185 /* Check for mailbox timeout. */ 204 /* Check for mailbox timeout. */
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 499a92db1cf6..491668d439a2 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -3463,7 +3463,7 @@ exit_validate_mac82:
3463 3463
3464/* Interrupt handling helpers. */ 3464/* Interrupt handling helpers. */
3465 3465
3466int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha) 3466int qla4_8xxx_intr_enable(struct scsi_qla_host *ha)
3467{ 3467{
3468 uint32_t mbox_cmd[MBOX_REG_COUNT]; 3468 uint32_t mbox_cmd[MBOX_REG_COUNT];
3469 uint32_t mbox_sts[MBOX_REG_COUNT]; 3469 uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -3484,7 +3484,7 @@ int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha)
3484 return QLA_SUCCESS; 3484 return QLA_SUCCESS;
3485} 3485}
3486 3486
3487int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha) 3487int qla4_8xxx_intr_disable(struct scsi_qla_host *ha)
3488{ 3488{
3489 uint32_t mbox_cmd[MBOX_REG_COUNT]; 3489 uint32_t mbox_cmd[MBOX_REG_COUNT];
3490 uint32_t mbox_sts[MBOX_REG_COUNT]; 3490 uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -3509,7 +3509,7 @@ int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha)
3509void 3509void
3510qla4_82xx_enable_intrs(struct scsi_qla_host *ha) 3510qla4_82xx_enable_intrs(struct scsi_qla_host *ha)
3511{ 3511{
3512 qla4_8xxx_mbx_intr_enable(ha); 3512 qla4_8xxx_intr_enable(ha);
3513 3513
3514 spin_lock_irq(&ha->hardware_lock); 3514 spin_lock_irq(&ha->hardware_lock);
3515 /* BIT 10 - reset */ 3515 /* BIT 10 - reset */
@@ -3522,7 +3522,7 @@ void
3522qla4_82xx_disable_intrs(struct scsi_qla_host *ha) 3522qla4_82xx_disable_intrs(struct scsi_qla_host *ha)
3523{ 3523{
3524 if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags)) 3524 if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags))
3525 qla4_8xxx_mbx_intr_disable(ha); 3525 qla4_8xxx_intr_disable(ha);
3526 3526
3527 spin_lock_irq(&ha->hardware_lock); 3527 spin_lock_irq(&ha->hardware_lock);
3528 /* BIT 10 - set */ 3528 /* BIT 10 - set */
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 4cec123a6a6a..bfd1e68654ab 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -2978,6 +2978,7 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
2978 if (status == QLA_SUCCESS) { 2978 if (status == QLA_SUCCESS) {
2979 if (!test_bit(AF_FW_RECOVERY, &ha->flags)) 2979 if (!test_bit(AF_FW_RECOVERY, &ha->flags))
2980 qla4xxx_cmd_wait(ha); 2980 qla4xxx_cmd_wait(ha);
2981
2981 ha->isp_ops->disable_intrs(ha); 2982 ha->isp_ops->disable_intrs(ha);
2982 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); 2983 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
2983 qla4xxx_abort_active_cmds(ha, DID_RESET << 16); 2984 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
@@ -3508,10 +3509,8 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
3508{ 3509{
3509 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); 3510 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
3510 3511
3511 if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { 3512 /* Turn-off interrupts on the card. */
3512 /* Turn-off interrupts on the card. */ 3513 ha->isp_ops->disable_intrs(ha);
3513 ha->isp_ops->disable_intrs(ha);
3514 }
3515 3514
3516 if (is_qla40XX(ha)) { 3515 if (is_qla40XX(ha)) {
3517 writel(set_rmask(CSR_SCSI_PROCESSOR_INTR), 3516 writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
@@ -3547,8 +3546,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
3547 } 3546 }
3548 3547
3549 /* Detach interrupts */ 3548 /* Detach interrupts */
3550 if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) 3549 qla4xxx_free_irqs(ha);
3551 qla4xxx_free_irqs(ha);
3552 3550
3553 /* free extra memory */ 3551 /* free extra memory */
3554 qla4xxx_mem_free(ha); 3552 qla4xxx_mem_free(ha);