diff options
author | Joe Eykholt <jeykholt@cisco.com> | 2009-08-25 17:03:36 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-09-10 13:08:01 -0400 |
commit | feab4ae73031699fcf92a88f4b1e4ec1b14157a5 (patch) | |
tree | 9552f8c00ec9dfc75e279788d6d079df1caff2e0 /drivers | |
parent | 83fe6a93465750d1a20221aaa9a253d9ea7fe45c (diff) |
[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: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 04e9846ad1b5..dc97c603744f 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -1340,6 +1340,8 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, | |||
1340 | struct fc_rport_priv *rdata; | 1340 | struct fc_rport_priv *rdata; |
1341 | u32 sid; | 1341 | u32 sid; |
1342 | 1342 | ||
1343 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); | ||
1344 | |||
1343 | fh = fc_frame_header_get(fp); | 1345 | fh = fc_frame_header_get(fp); |
1344 | sid = ntoh24(fh->fh_s_id); | 1346 | sid = ntoh24(fh->fh_s_id); |
1345 | 1347 | ||
@@ -1349,13 +1351,20 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, | |||
1349 | mutex_lock(&rdata->rp_mutex); | 1351 | mutex_lock(&rdata->rp_mutex); |
1350 | FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", | 1352 | FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", |
1351 | fc_rport_state(rdata)); | 1353 | fc_rport_state(rdata)); |
1352 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | 1354 | |
1355 | /* | ||
1356 | * If the remote port was created due to discovery, | ||
1357 | * log back in. It may have seen a stale RSCN about us. | ||
1358 | */ | ||
1359 | if (rdata->rp_state != RPORT_ST_DELETE && rdata->disc_id) | ||
1360 | fc_rport_enter_plogi(rdata); | ||
1361 | else | ||
1362 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | ||
1353 | mutex_unlock(&rdata->rp_mutex); | 1363 | mutex_unlock(&rdata->rp_mutex); |
1354 | } else | 1364 | } else |
1355 | FC_RPORT_ID_DBG(lport, sid, | 1365 | FC_RPORT_ID_DBG(lport, sid, |
1356 | "Received LOGO from non-logged-in port\n"); | 1366 | "Received LOGO from non-logged-in port\n"); |
1357 | mutex_unlock(&lport->disc.disc_mutex); | 1367 | mutex_unlock(&lport->disc.disc_mutex); |
1358 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); | ||
1359 | fc_frame_free(fp); | 1368 | fc_frame_free(fp); |
1360 | } | 1369 | } |
1361 | 1370 | ||