Commit feab4ae7 authored by Joe Eykholt's avatar Joe Eykholt Committed by James Bottomley

[SCSI] libfc: re-login to remote ports that send us LOGO

After a quick link flap, a target was seen to send us a LOGO.
Apparently, it saw an RSCN reporting that we had dropped out of the
fabric after we had logged back into it.

This is likely in larger fabrics (more than 2 FC switches) after
a quick link flap at the initiator.  Each link transition causes
an port-specific RSCN to the target.  After the link comes back up,
the initiator successfully discovers and does a PLOGI to the target
before the target sees the first RSCN reporting the initiator is gone,
and it sends a LOGO.  The target may see a subsequent RSCN saying the
port is back, but probably wouldn't send a PLOGI and leaves it
up to the initiator to re-login.

An RSCN can be delayed by the switches due to software layers but a
PLOGI is forwarded in hardware causing the PLOGI to beat the RSCN.

If a remote port is in the discovered set and sends a LOGO, re-login to it.
Signed-off-by: default avatarJoe Eykholt <jeykholt@cisco.com>
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 83fe6a93
...@@ -1340,6 +1340,8 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, ...@@ -1340,6 +1340,8 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport,
struct fc_rport_priv *rdata; struct fc_rport_priv *rdata;
u32 sid; u32 sid;
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
fh = fc_frame_header_get(fp); fh = fc_frame_header_get(fp);
sid = ntoh24(fh->fh_s_id); sid = ntoh24(fh->fh_s_id);
...@@ -1349,13 +1351,20 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, ...@@ -1349,13 +1351,20 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport,
mutex_lock(&rdata->rp_mutex); mutex_lock(&rdata->rp_mutex);
FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",
fc_rport_state(rdata)); fc_rport_state(rdata));
fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
/*
* If the remote port was created due to discovery,
* log back in. It may have seen a stale RSCN about us.
*/
if (rdata->rp_state != RPORT_ST_DELETE && rdata->disc_id)
fc_rport_enter_plogi(rdata);
else
fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
mutex_unlock(&rdata->rp_mutex); mutex_unlock(&rdata->rp_mutex);
} else } else
FC_RPORT_ID_DBG(lport, sid, FC_RPORT_ID_DBG(lport, sid,
"Received LOGO from non-logged-in port\n"); "Received LOGO from non-logged-in port\n");
mutex_unlock(&lport->disc.disc_mutex); mutex_unlock(&lport->disc.disc_mutex);
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
fc_frame_free(fp); fc_frame_free(fp);
} }
......
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