aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_disc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libfc/fc_disc.c')
-rw-r--r--drivers/scsi/libfc/fc_disc.c28
1 files changed, 12 insertions, 16 deletions
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index fd3a6b287e98..819ec6256a53 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -469,6 +469,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
469 struct fc_rport_priv *rdata; 469 struct fc_rport_priv *rdata;
470 470
471 lport = disc->lport; 471 lport = disc->lport;
472 disc->seq_count++;
472 473
473 /* 474 /*
474 * Handle partial name record left over from previous call. 475 * Handle partial name record left over from previous call.
@@ -582,10 +583,10 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
582 struct fc_disc *disc = disc_arg; 583 struct fc_disc *disc = disc_arg;
583 struct fc_ct_hdr *cp; 584 struct fc_ct_hdr *cp;
584 struct fc_frame_header *fh; 585 struct fc_frame_header *fh;
586 enum fc_disc_event event = DISC_EV_NONE;
585 unsigned int seq_cnt; 587 unsigned int seq_cnt;
586 void *buf = NULL;
587 unsigned int len; 588 unsigned int len;
588 int error; 589 int error = 0;
589 590
590 mutex_lock(&disc->disc_mutex); 591 mutex_lock(&disc->disc_mutex);
591 FC_DISC_DBG(disc, "Received a GPN_FT response\n"); 592 FC_DISC_DBG(disc, "Received a GPN_FT response\n");
@@ -600,8 +601,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
600 fh = fc_frame_header_get(fp); 601 fh = fc_frame_header_get(fp);
601 len = fr_len(fp) - sizeof(*fh); 602 len = fr_len(fp) - sizeof(*fh);
602 seq_cnt = ntohs(fh->fh_seq_cnt); 603 seq_cnt = ntohs(fh->fh_seq_cnt);
603 if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 && 604 if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 && disc->seq_count == 0) {
604 disc->seq_count == 0) {
605 cp = fc_frame_payload_get(fp, sizeof(*cp)); 605 cp = fc_frame_payload_get(fp, sizeof(*cp));
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",
@@ -609,33 +609,29 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
609 } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) { 609 } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
610 610
611 /* Accepted, parse the response. */ 611 /* Accepted, parse the response. */
612 buf = cp + 1;
613 len -= sizeof(*cp); 612 len -= sizeof(*cp);
613 error = fc_disc_gpn_ft_parse(disc, cp + 1, len);
614 } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { 614 } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
615 FC_DISC_DBG(disc, "GPN_FT rejected reason %x exp %x " 615 FC_DISC_DBG(disc, "GPN_FT rejected reason %x exp %x "
616 "(check zoning)\n", cp->ct_reason, 616 "(check zoning)\n", cp->ct_reason,
617 cp->ct_explan); 617 cp->ct_explan);
618 fc_disc_done(disc, DISC_EV_FAILED); 618 event = DISC_EV_FAILED;
619 } else { 619 } else {
620 FC_DISC_DBG(disc, "GPN_FT unexpected response code " 620 FC_DISC_DBG(disc, "GPN_FT unexpected response code "
621 "%x\n", ntohs(cp->ct_cmd)); 621 "%x\n", ntohs(cp->ct_cmd));
622 } 622 }
623 } else if (fr_sof(fp) == FC_SOF_N3 && 623 } else if (fr_sof(fp) == FC_SOF_N3 && seq_cnt == disc->seq_count) {
624 seq_cnt == disc->seq_count) { 624 error = fc_disc_gpn_ft_parse(disc, fh + 1, len);
625 buf = fh + 1;
626 } else { 625 } else {
627 FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? " 626 FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? "
628 "seq_cnt %x expected %x sof %x eof %x\n", 627 "seq_cnt %x expected %x sof %x eof %x\n",
629 seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp)); 628 seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp));
630 } 629 }
631 if (buf) { 630 if (error)
632 disc->seq_count++; 631 fc_disc_error(disc, fp);
633 error = fc_disc_gpn_ft_parse(disc, buf, len); 632 else if (event != DISC_EV_NONE)
634 if (error) 633 fc_disc_done(disc, event);
635 fc_disc_error(disc, fp);
636 }
637 fc_frame_free(fp); 634 fc_frame_free(fp);
638
639 mutex_unlock(&disc->disc_mutex); 635 mutex_unlock(&disc->disc_mutex);
640} 636}
641 637