diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_disc.c')
-rw-r--r-- | drivers/scsi/libfc/fc_disc.c | 28 |
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 | ||