aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_disc.c
diff options
context:
space:
mode:
authorJoe Eykholt <jeykholt@cisco.com>2009-08-25 17:02:27 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-09-10 13:07:50 -0400
commit883a337cf8969b2906ffd8aeb838d875f7338190 (patch)
treeda818ca65c3c1726d0af4521b8069d2f0cf73b20 /drivers/scsi/libfc/fc_disc.c
parenta1c1e4e76c68f564cddc0b43842b895464f7865f (diff)
[SCSI] libfc: handle discovery failure more correctly.
Abhijeet Joglekar wrote: "In gpn_ft_resp, if the payload is short, or unexpected response or out of sequence frame, then we just return and do nothing. We should either enter fc_disc_done() with DISC_EV_FAIL which will then restart any queued discovery requests or call lport module which will reset local port, or we should call fc_disc_error() so that the gpn_ft is retried. The situation as is causes discovery to remain pending and never get restarted, in these rare cases. We saw this due to a coding bug in fc_disc before. The only ways it could happen would be bugs, packet corruption or an FC fabric problem. Change it to fail discovery. The local port will restart discovery, although it probably should just give up until the next link flap. 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/scsi/libfc/fc_disc.c')
-rw-r--r--drivers/scsi/libfc/fc_disc.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 819ec6256a53..844376c1d8dc 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -606,6 +606,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
606 if (!cp) { 606 if (!cp) {
607 FC_DISC_DBG(disc, "GPN_FT response too short, len %d\n", 607 FC_DISC_DBG(disc, "GPN_FT response too short, len %d\n",
608 fr_len(fp)); 608 fr_len(fp));
609 event = DISC_EV_FAILED;
609 } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) { 610 } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
610 611
611 /* Accepted, parse the response. */ 612 /* Accepted, parse the response. */
@@ -619,6 +620,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
619 } else { 620 } else {
620 FC_DISC_DBG(disc, "GPN_FT unexpected response code " 621 FC_DISC_DBG(disc, "GPN_FT unexpected response code "
621 "%x\n", ntohs(cp->ct_cmd)); 622 "%x\n", ntohs(cp->ct_cmd));
623 event = DISC_EV_FAILED;
622 } 624 }
623 } else if (fr_sof(fp) == FC_SOF_N3 && seq_cnt == disc->seq_count) { 625 } else if (fr_sof(fp) == FC_SOF_N3 && seq_cnt == disc->seq_count) {
624 error = fc_disc_gpn_ft_parse(disc, fh + 1, len); 626 error = fc_disc_gpn_ft_parse(disc, fh + 1, len);
@@ -626,6 +628,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
626 FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? " 628 FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? "
627 "seq_cnt %x expected %x sof %x eof %x\n", 629 "seq_cnt %x expected %x sof %x eof %x\n",
628 seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp)); 630 seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp));
631 event = DISC_EV_FAILED;
629 } 632 }
630 if (error) 633 if (error)
631 fc_disc_error(disc, fp); 634 fc_disc_error(disc, fp);