Commit c76ae845 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

scsi: qla2xxx: Add error handling for PLOGI ELS passthrough

Add error handling logic to ELS Passthrough relating to NVME devices.
Current code does not parse error code to take proper recovery action,
instead it re-logins with the same login parameters that encountered the
error. Ex: nport handle collision.

Link: https://lore.kernel.org/r/20190912180918.6436-10-hmadhani@marvell.comSigned-off-by: default avatarQuinn Tran <qutran@marvell.com>
Signed-off-by: default avatarHimanshu Madhani <hmadhani@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 84ed362a
......@@ -2740,6 +2740,10 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
struct scsi_qla_host *vha = sp->vha;
struct event_arg ea;
struct qla_work_evt *e;
struct fc_port *conflict_fcport;
port_id_t cid; /* conflict Nport id */
u32 *fw_status = sp->u.iocb_cmd.u.els_plogi.fw_status;
u16 lid;
ql_dbg(ql_dbg_disc, vha, 0x3072,
"%s ELS done rc %d hdl=%x, portid=%06x %8phC\n",
......@@ -2751,14 +2755,99 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
if (sp->flags & SRB_WAKEUP_ON_COMP)
complete(&lio->u.els_plogi.comp);
else {
if (res) {
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
} else {
switch (fw_status[0]) {
case CS_DATA_UNDERRUN:
case CS_COMPLETE:
memset(&ea, 0, sizeof(ea));
ea.fcport = fcport;
ea.data[0] = MBS_COMMAND_COMPLETE;
ea.sp = sp;
qla24xx_handle_plogi_done_event(vha, &ea);
break;
case CS_IOCB_ERROR:
switch (fw_status[1]) {
case LSC_SCODE_PORTID_USED:
lid = fw_status[2] & 0xffff;
qlt_find_sess_invalidate_other(vha,
wwn_to_u64(fcport->port_name),
fcport->d_id, lid, &conflict_fcport);
if (conflict_fcport) {
/*
* Another fcport shares the same
* loop_id & nport id; conflict
* fcport needs to finish cleanup
* before this fcport can proceed
* to login.
*/
conflict_fcport->conflict = fcport;
fcport->login_pause = 1;
ql_dbg(ql_dbg_disc, vha, 0x20ed,
"%s %d %8phC pid %06x inuse with lid %#x post gidpn\n",
__func__, __LINE__,
fcport->port_name,
fcport->d_id.b24, lid);
} else {
ql_dbg(ql_dbg_disc, vha, 0x20ed,
"%s %d %8phC pid %06x inuse with lid %#x sched del\n",
__func__, __LINE__,
fcport->port_name,
fcport->d_id.b24, lid);
qla2x00_clear_loop_id(fcport);
set_bit(lid, vha->hw->loop_id_map);
fcport->loop_id = lid;
fcport->keep_nport_handle = 0;
qlt_schedule_sess_for_deletion(fcport);
}
break;
case LSC_SCODE_NPORT_USED:
cid.b.domain = (fw_status[2] >> 16) & 0xff;
cid.b.area = (fw_status[2] >> 8) & 0xff;
cid.b.al_pa = fw_status[2] & 0xff;
cid.b.rsvd_1 = 0;
ql_dbg(ql_dbg_disc, vha, 0x20ec,
"%s %d %8phC lid %#x in use with pid %06x post gnl\n",
__func__, __LINE__, fcport->port_name,
fcport->loop_id, cid.b24);
set_bit(fcport->loop_id,
vha->hw->loop_id_map);
fcport->loop_id = FC_NO_LOOP_ID;
qla24xx_post_gnl_work(vha, fcport);
break;
case LSC_SCODE_NOXCB:
vha->hw->exch_starvation++;
if (vha->hw->exch_starvation > 5) {
ql_log(ql_log_warn, vha, 0xd046,
"Exchange starvation. Resetting RISC\n");
vha->hw->exch_starvation = 0;
set_bit(ISP_ABORT_NEEDED,
&vha->dpc_flags);
qla2xxx_wake_dpc(vha);
}
/* fall through */
default:
ql_dbg(ql_dbg_disc, vha, 0x20eb,
"%s %8phC cmd error fw_status 0x%x 0x%x 0x%x\n",
__func__, sp->fcport->port_name,
fw_status[0], fw_status[1], fw_status[2]);
fcport->flags &= ~FCF_ASYNC_SENT;
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
break;
}
break;
default:
ql_dbg(ql_dbg_disc, vha, 0x20eb,
"%s %8phC cmd error 2 fw_status 0x%x 0x%x 0x%x\n",
__func__, sp->fcport->port_name,
fw_status[0], fw_status[1], fw_status[2]);
sp->fcport->flags &= ~FCF_ASYNC_SENT;
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
break;
}
e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment