[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>
This commit is contained in:
parent
bddd2d65a4
commit
b1d46989c1
|
@ -706,6 +706,11 @@ typedef struct {
|
||||||
#define MBC_SET_PORT_CONFIG 0x122 /* Set port configuration */
|
#define MBC_SET_PORT_CONFIG 0x122 /* Set port configuration */
|
||||||
#define MBC_GET_PORT_CONFIG 0x123 /* Get port configuration */
|
#define MBC_GET_PORT_CONFIG 0x123 /* Get port configuration */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ISP81xx mailbox commands
|
||||||
|
*/
|
||||||
|
#define MBC_WRITE_MPI_REGISTER 0x01 /* Write MPI Register. */
|
||||||
|
|
||||||
/* Firmware return data sizes */
|
/* Firmware return data sizes */
|
||||||
#define FCAL_MAP_SIZE 128
|
#define FCAL_MAP_SIZE 128
|
||||||
|
|
||||||
|
@ -2858,6 +2863,7 @@ typedef struct scsi_qla_host {
|
||||||
#define NPIV_CONFIG_NEEDED 16
|
#define NPIV_CONFIG_NEEDED 16
|
||||||
#define ISP_UNRECOVERABLE 17
|
#define ISP_UNRECOVERABLE 17
|
||||||
#define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */
|
#define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */
|
||||||
|
#define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */
|
||||||
|
|
||||||
uint32_t device_flags;
|
uint32_t device_flags;
|
||||||
#define SWITCH_FOUND BIT_0
|
#define SWITCH_FOUND BIT_0
|
||||||
|
|
|
@ -352,6 +352,8 @@ qla2x00_read_ram_word(scsi_qla_host_t *, uint32_t, uint32_t *);
|
||||||
extern int
|
extern int
|
||||||
qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
|
qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
qla81xx_write_mpi_register(scsi_qla_host_t *, uint16_t *);
|
||||||
extern int qla2x00_get_data_rate(scsi_qla_host_t *);
|
extern int qla2x00_get_data_rate(scsi_qla_host_t *);
|
||||||
extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
|
extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
|
||||||
uint16_t *);
|
uint16_t *);
|
||||||
|
|
|
@ -943,6 +943,19 @@ qla2x00_reset_chip(scsi_qla_host_t *vha)
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qla81xx_reset_mpi() - Reset's MPI FW via Write MPI Register MBC.
|
||||||
|
*
|
||||||
|
* Returns 0 on success.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
qla81xx_reset_mpi(scsi_qla_host_t *vha)
|
||||||
|
{
|
||||||
|
uint16_t mb[4] = {0x1010, 0, 1, 0};
|
||||||
|
|
||||||
|
return qla81xx_write_mpi_register(vha, mb);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qla24xx_reset_risc() - Perform full reset of ISP24xx RISC.
|
* qla24xx_reset_risc() - Perform full reset of ISP24xx RISC.
|
||||||
* @ha: HA context
|
* @ha: HA context
|
||||||
|
@ -957,6 +970,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
|
||||||
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
||||||
uint32_t cnt, d2;
|
uint32_t cnt, d2;
|
||||||
uint16_t wd;
|
uint16_t wd;
|
||||||
|
static int abts_cnt; /* ISP abort retry counts */
|
||||||
|
|
||||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
|
|
||||||
|
@ -990,6 +1004,23 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
|
||||||
barrier();
|
barrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If required, do an MPI FW reset now */
|
||||||
|
if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) {
|
||||||
|
if (qla81xx_reset_mpi(vha) != QLA_SUCCESS) {
|
||||||
|
if (++abts_cnt < 5) {
|
||||||
|
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
||||||
|
set_bit(MPI_RESET_NEEDED, &vha->dpc_flags);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* We exhausted the ISP abort retries. We have to
|
||||||
|
* set the board offline.
|
||||||
|
*/
|
||||||
|
abts_cnt = 0;
|
||||||
|
vha->flags.online = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET);
|
WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET);
|
||||||
RD_REG_DWORD(®->hccr);
|
RD_REG_DWORD(®->hccr);
|
||||||
|
|
||||||
|
|
|
@ -412,8 +412,14 @@ skip_rio:
|
||||||
"Unrecoverable Hardware Error: adapter "
|
"Unrecoverable Hardware Error: adapter "
|
||||||
"marked OFFLINE!\n");
|
"marked OFFLINE!\n");
|
||||||
vha->flags.online = 0;
|
vha->flags.online = 0;
|
||||||
} else
|
} else {
|
||||||
|
/* Check to see if MPI timeout occured */
|
||||||
|
if ((mbx & MBX_3) && (ha->flags.port0))
|
||||||
|
set_bit(MPI_RESET_NEEDED,
|
||||||
|
&vha->dpc_flags);
|
||||||
|
|
||||||
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
||||||
|
}
|
||||||
} else if (mb[1] == 0) {
|
} else if (mb[1] == 0) {
|
||||||
qla_printk(KERN_INFO, ha,
|
qla_printk(KERN_INFO, ha,
|
||||||
"Unrecoverable Hardware Error: adapter marked "
|
"Unrecoverable Hardware Error: adapter marked "
|
||||||
|
|
|
@ -3948,6 +3948,67 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
|
||||||
|
{
|
||||||
|
int rval;
|
||||||
|
uint32_t stat, timer;
|
||||||
|
uint16_t mb0 = 0;
|
||||||
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
||||||
|
|
||||||
|
rval = QLA_SUCCESS;
|
||||||
|
|
||||||
|
DEBUG11(qla_printk(KERN_INFO, ha,
|
||||||
|
"%s(%ld): entered.\n", __func__, vha->host_no));
|
||||||
|
|
||||||
|
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
|
||||||
|
|
||||||
|
/* Write the MBC data to the registers */
|
||||||
|
WRT_REG_WORD(®->mailbox0, MBC_WRITE_MPI_REGISTER);
|
||||||
|
WRT_REG_WORD(®->mailbox1, mb[0]);
|
||||||
|
WRT_REG_WORD(®->mailbox2, mb[1]);
|
||||||
|
WRT_REG_WORD(®->mailbox3, mb[2]);
|
||||||
|
WRT_REG_WORD(®->mailbox4, mb[3]);
|
||||||
|
|
||||||
|
WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT);
|
||||||
|
|
||||||
|
/* Poll for MBC interrupt */
|
||||||
|
for (timer = 6000000; timer; timer--) {
|
||||||
|
/* Check for pending interrupts. */
|
||||||
|
stat = RD_REG_DWORD(®->host_status);
|
||||||
|
if (stat & HSRX_RISC_INT) {
|
||||||
|
stat &= 0xff;
|
||||||
|
|
||||||
|
if (stat == 0x1 || stat == 0x2 ||
|
||||||
|
stat == 0x10 || stat == 0x11) {
|
||||||
|
set_bit(MBX_INTERRUPT,
|
||||||
|
&ha->mbx_cmd_flags);
|
||||||
|
mb0 = RD_REG_WORD(®->mailbox0);
|
||||||
|
WRT_REG_DWORD(®->hccr,
|
||||||
|
HCCRX_CLR_RISC_INT);
|
||||||
|
RD_REG_DWORD(®->hccr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
udelay(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags))
|
||||||
|
rval = mb0 & MBS_MASK;
|
||||||
|
else
|
||||||
|
rval = QLA_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
if (rval != QLA_SUCCESS) {
|
||||||
|
DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n",
|
||||||
|
__func__, vha->host_no, rval, mb[0]));
|
||||||
|
} else {
|
||||||
|
DEBUG11(printk(KERN_INFO
|
||||||
|
"%s(%ld): done.\n", __func__, vha->host_no));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
int
|
int
|
||||||
qla2x00_get_data_rate(scsi_qla_host_t *vha)
|
qla2x00_get_data_rate(scsi_qla_host_t *vha)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue