Skip to content

Commit

Permalink
[SCSI] qla2xxx: Handle MPI timeout indicated by AE8002
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Madhuranath Iyengar authored and James Bottomley committed Sep 5, 2010
1 parent bddd2d6 commit b1d4698
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 1 deletion.
6 changes: 6 additions & 0 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,11 @@ typedef struct {
#define MBC_SET_PORT_CONFIG 0x122 /* Set 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 */
#define FCAL_MAP_SIZE 128

Expand Down Expand Up @@ -2858,6 +2863,7 @@ typedef struct scsi_qla_host {
#define NPIV_CONFIG_NEEDED 16
#define ISP_UNRECOVERABLE 17
#define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */
#define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */

uint32_t device_flags;
#define SWITCH_FOUND BIT_0
Expand Down
2 changes: 2 additions & 0 deletions drivers/scsi/qla2xxx/qla_gbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ qla2x00_read_ram_word(scsi_qla_host_t *, uint32_t, uint32_t *);
extern int
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 qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
uint16_t *);
Expand Down
31 changes: 31 additions & 0 deletions drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,19 @@ qla2x00_reset_chip(scsi_qla_host_t *vha)
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.
* @ha: HA context
Expand All @@ -957,6 +970,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
uint32_t cnt, d2;
uint16_t wd;
static int abts_cnt; /* ISP abort retry counts */

spin_lock_irqsave(&ha->hardware_lock, flags);

Expand Down Expand Up @@ -990,6 +1004,23 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
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(&reg->hccr, HCCRX_SET_RISC_RESET);
RD_REG_DWORD(&reg->hccr);

Expand Down
8 changes: 7 additions & 1 deletion drivers/scsi/qla2xxx/qla_isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,8 +412,14 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
"Unrecoverable Hardware Error: adapter "
"marked OFFLINE!\n");
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);
}
} else if (mb[1] == 0) {
qla_printk(KERN_INFO, ha,
"Unrecoverable Hardware Error: adapter marked "
Expand Down
61 changes: 61 additions & 0 deletions drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -3948,6 +3948,67 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
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(&reg->mailbox0, MBC_WRITE_MPI_REGISTER);
WRT_REG_WORD(&reg->mailbox1, mb[0]);
WRT_REG_WORD(&reg->mailbox2, mb[1]);
WRT_REG_WORD(&reg->mailbox3, mb[2]);
WRT_REG_WORD(&reg->mailbox4, mb[3]);

WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);

/* Poll for MBC interrupt */
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
stat = RD_REG_DWORD(&reg->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(&reg->mailbox0);
WRT_REG_DWORD(&reg->hccr,
HCCRX_CLR_RISC_INT);
RD_REG_DWORD(&reg->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
qla2x00_get_data_rate(scsi_qla_host_t *vha)
{
Expand Down

0 comments on commit b1d4698

Please sign in to comment.