scsi: qla2xxx: Add error handling for PLOGI ELS passthrough
[ Upstream commit c76ae845ea
]
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.com
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
ac55936905
commit
abc15be19f
|
@ -2749,6 +2749,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",
|
||||
|
@ -2760,14 +2764,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);
|
||||
|
|
Loading…
Reference in New Issue