diff options
author | Madhuranath Iyengar <madhuranath.iyengar@qlogic.com> | 2010-09-03 18:20:54 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-09-05 14:35:01 -0400 |
commit | b1d46989c12ec4d93f274ca8378bb1a6014d244a (patch) | |
tree | 3bcae91b1470f09add485e7fcfa5a149d206e29d | |
parent | bddd2d65a48c492d3e585e65df0be89c58b4acda (diff) |
[SCSI] qla2xxx: Handle MPI timeout indicated by AE8002
In case the MPI times out, the FW issues an async event AE8002
to indicate this to every FCoE function. The FC/FCoE driver is
required to handle this, by doing a soft reset and issuing a
Write MPI register mailbox command to reset the MPI.
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 6 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 31 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 8 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 61 |
5 files changed, 107 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3a432ea0c7a3..ee15f4f10fec 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -706,6 +706,11 @@ typedef struct { | |||
706 | #define MBC_SET_PORT_CONFIG 0x122 /* Set port configuration */ | 706 | #define MBC_SET_PORT_CONFIG 0x122 /* Set port configuration */ |
707 | #define MBC_GET_PORT_CONFIG 0x123 /* Get port configuration */ | 707 | #define MBC_GET_PORT_CONFIG 0x123 /* Get port configuration */ |
708 | 708 | ||
709 | /* | ||
710 | * ISP81xx mailbox commands | ||
711 | */ | ||
712 | #define MBC_WRITE_MPI_REGISTER 0x01 /* Write MPI Register. */ | ||
713 | |||
709 | /* Firmware return data sizes */ | 714 | /* Firmware return data sizes */ |
710 | #define FCAL_MAP_SIZE 128 | 715 | #define FCAL_MAP_SIZE 128 |
711 | 716 | ||
@@ -2858,6 +2863,7 @@ typedef struct scsi_qla_host { | |||
2858 | #define NPIV_CONFIG_NEEDED 16 | 2863 | #define NPIV_CONFIG_NEEDED 16 |
2859 | #define ISP_UNRECOVERABLE 17 | 2864 | #define ISP_UNRECOVERABLE 17 |
2860 | #define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ | 2865 | #define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ |
2866 | #define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ | ||
2861 | 2867 | ||
2862 | uint32_t device_flags; | 2868 | uint32_t device_flags; |
2863 | #define SWITCH_FOUND BIT_0 | 2869 | #define SWITCH_FOUND BIT_0 |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 967bc9278bf7..c33dec827e1e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -352,6 +352,8 @@ qla2x00_read_ram_word(scsi_qla_host_t *, uint32_t, uint32_t *); | |||
352 | extern int | 352 | extern int |
353 | qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); | 353 | qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); |
354 | 354 | ||
355 | extern int | ||
356 | qla81xx_write_mpi_register(scsi_qla_host_t *, uint16_t *); | ||
355 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); | 357 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); |
356 | extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t, | 358 | extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t, |
357 | uint16_t *); | 359 | uint16_t *); |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f2da5c5dacdd..c2d7bb8cd53f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -944,6 +944,19 @@ qla2x00_reset_chip(scsi_qla_host_t *vha) | |||
944 | } | 944 | } |
945 | 945 | ||
946 | /** | 946 | /** |
947 | * qla81xx_reset_mpi() - Reset's MPI FW via Write MPI Register MBC. | ||
948 | * | ||
949 | * Returns 0 on success. | ||
950 | */ | ||
951 | int | ||
952 | qla81xx_reset_mpi(scsi_qla_host_t *vha) | ||
953 | { | ||
954 | uint16_t mb[4] = {0x1010, 0, 1, 0}; | ||
955 | |||
956 | return qla81xx_write_mpi_register(vha, mb); | ||
957 | } | ||
958 | |||
959 | /** | ||
947 | * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC. | 960 | * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC. |
948 | * @ha: HA context | 961 | * @ha: HA context |
949 | * | 962 | * |
@@ -957,6 +970,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha) | |||
957 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 970 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
958 | uint32_t cnt, d2; | 971 | uint32_t cnt, d2; |
959 | uint16_t wd; | 972 | uint16_t wd; |
973 | static int abts_cnt; /* ISP abort retry counts */ | ||
960 | 974 | ||
961 | spin_lock_irqsave(&ha->hardware_lock, flags); | 975 | spin_lock_irqsave(&ha->hardware_lock, flags); |
962 | 976 | ||
@@ -990,6 +1004,23 @@ qla24xx_reset_risc(scsi_qla_host_t *vha) | |||
990 | barrier(); | 1004 | barrier(); |
991 | } | 1005 | } |
992 | 1006 | ||
1007 | /* If required, do an MPI FW reset now */ | ||
1008 | if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) { | ||
1009 | if (qla81xx_reset_mpi(vha) != QLA_SUCCESS) { | ||
1010 | if (++abts_cnt < 5) { | ||
1011 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
1012 | set_bit(MPI_RESET_NEEDED, &vha->dpc_flags); | ||
1013 | } else { | ||
1014 | /* | ||
1015 | * We exhausted the ISP abort retries. We have to | ||
1016 | * set the board offline. | ||
1017 | */ | ||
1018 | abts_cnt = 0; | ||
1019 | vha->flags.online = 0; | ||
1020 | } | ||
1021 | } | ||
1022 | } | ||
1023 | |||
993 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET); | 1024 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET); |
994 | RD_REG_DWORD(®->hccr); | 1025 | RD_REG_DWORD(®->hccr); |
995 | 1026 | ||
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6982ba70e12a..bb4d63a792aa 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -412,8 +412,14 @@ skip_rio: | |||
412 | "Unrecoverable Hardware Error: adapter " | 412 | "Unrecoverable Hardware Error: adapter " |
413 | "marked OFFLINE!\n"); | 413 | "marked OFFLINE!\n"); |
414 | vha->flags.online = 0; | 414 | vha->flags.online = 0; |
415 | } else | 415 | } else { |
416 | /* Check to see if MPI timeout occured */ | ||
417 | if ((mbx & MBX_3) && (ha->flags.port0)) | ||
418 | set_bit(MPI_RESET_NEEDED, | ||
419 | &vha->dpc_flags); | ||
420 | |||
416 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 421 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
422 | } | ||
417 | } else if (mb[1] == 0) { | 423 | } else if (mb[1] == 0) { |
418 | qla_printk(KERN_INFO, ha, | 424 | qla_printk(KERN_INFO, ha, |
419 | "Unrecoverable Hardware Error: adapter marked " | 425 | "Unrecoverable Hardware Error: adapter marked " |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index d0413d56887c..52024080c393 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -3949,6 +3949,67 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) | |||
3949 | } | 3949 | } |
3950 | 3950 | ||
3951 | int | 3951 | int |
3952 | qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb) | ||
3953 | { | ||
3954 | int rval; | ||
3955 | uint32_t stat, timer; | ||
3956 | uint16_t mb0 = 0; | ||
3957 | struct qla_hw_data *ha = vha->hw; | ||
3958 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
3959 | |||
3960 | rval = QLA_SUCCESS; | ||
3961 | |||
3962 | DEBUG11(qla_printk(KERN_INFO, ha, | ||
3963 | "%s(%ld): entered.\n", __func__, vha->host_no)); | ||
3964 | |||
3965 | clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
3966 | |||
3967 | /* Write the MBC data to the registers */ | ||
3968 | WRT_REG_WORD(®->mailbox0, MBC_WRITE_MPI_REGISTER); | ||
3969 | WRT_REG_WORD(®->mailbox1, mb[0]); | ||
3970 | WRT_REG_WORD(®->mailbox2, mb[1]); | ||
3971 | WRT_REG_WORD(®->mailbox3, mb[2]); | ||
3972 | WRT_REG_WORD(®->mailbox4, mb[3]); | ||
3973 | |||
3974 | WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); | ||
3975 | |||
3976 | /* Poll for MBC interrupt */ | ||
3977 | for (timer = 6000000; timer; timer--) { | ||
3978 | /* Check for pending interrupts. */ | ||
3979 | stat = RD_REG_DWORD(®->host_status); | ||
3980 | if (stat & HSRX_RISC_INT) { | ||
3981 | stat &= 0xff; | ||
3982 | |||
3983 | if (stat == 0x1 || stat == 0x2 || | ||
3984 | stat == 0x10 || stat == 0x11) { | ||
3985 | set_bit(MBX_INTERRUPT, | ||
3986 | &ha->mbx_cmd_flags); | ||
3987 | mb0 = RD_REG_WORD(®->mailbox0); | ||
3988 | WRT_REG_DWORD(®->hccr, | ||
3989 | HCCRX_CLR_RISC_INT); | ||
3990 | RD_REG_DWORD(®->hccr); | ||
3991 | break; | ||
3992 | } | ||
3993 | } | ||
3994 | udelay(5); | ||
3995 | } | ||
3996 | |||
3997 | if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) | ||
3998 | rval = mb0 & MBS_MASK; | ||
3999 | else | ||
4000 | rval = QLA_FUNCTION_FAILED; | ||
4001 | |||
4002 | if (rval != QLA_SUCCESS) { | ||
4003 | DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n", | ||
4004 | __func__, vha->host_no, rval, mb[0])); | ||
4005 | } else { | ||
4006 | DEBUG11(printk(KERN_INFO | ||
4007 | "%s(%ld): done.\n", __func__, vha->host_no)); | ||
4008 | } | ||
4009 | |||
4010 | return rval; | ||
4011 | } | ||
4012 | int | ||
3952 | qla2x00_get_data_rate(scsi_qla_host_t *vha) | 4013 | qla2x00_get_data_rate(scsi_qla_host_t *vha) |
3953 | { | 4014 | { |
3954 | int rval; | 4015 | int rval; |