|
@@ -469,6 +469,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
|
|
struct fc_rport_priv *rdata;
|
|
struct fc_rport_priv *rdata;
|
|
|
|
|
|
lport = disc->lport;
|
|
lport = disc->lport;
|
|
|
|
+ disc->seq_count++;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Handle partial name record left over from previous call.
|
|
* 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,
|
|
struct fc_disc *disc = disc_arg;
|
|
struct fc_disc *disc = disc_arg;
|
|
struct fc_ct_hdr *cp;
|
|
struct fc_ct_hdr *cp;
|
|
struct fc_frame_header *fh;
|
|
struct fc_frame_header *fh;
|
|
|
|
+ enum fc_disc_event event = DISC_EV_NONE;
|
|
unsigned int seq_cnt;
|
|
unsigned int seq_cnt;
|
|
- void *buf = NULL;
|
|
|
|
unsigned int len;
|
|
unsigned int len;
|
|
- int error;
|
|
|
|
|
|
+ int error = 0;
|
|
|
|
|
|
mutex_lock(&disc->disc_mutex);
|
|
mutex_lock(&disc->disc_mutex);
|
|
FC_DISC_DBG(disc, "Received a GPN_FT response\n");
|
|
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,
|
|
fh = fc_frame_header_get(fp);
|
|
fh = fc_frame_header_get(fp);
|
|
len = fr_len(fp) - sizeof(*fh);
|
|
len = fr_len(fp) - sizeof(*fh);
|
|
seq_cnt = ntohs(fh->fh_seq_cnt);
|
|
seq_cnt = ntohs(fh->fh_seq_cnt);
|
|
- if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 &&
|
|
|
|
- disc->seq_count == 0) {
|
|
|
|
|
|
+ if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 && disc->seq_count == 0) {
|
|
cp = fc_frame_payload_get(fp, sizeof(*cp));
|
|
cp = fc_frame_payload_get(fp, sizeof(*cp));
|
|
if (!cp) {
|
|
if (!cp) {
|
|
FC_DISC_DBG(disc, "GPN_FT response too short, len %d\n",
|
|
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,
|
|
} else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
|
|
} else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
|
|
|
|
|
|
/* Accepted, parse the response. */
|
|
/* Accepted, parse the response. */
|
|
- buf = cp + 1;
|
|
|
|
len -= sizeof(*cp);
|
|
len -= sizeof(*cp);
|
|
|
|
+ error = fc_disc_gpn_ft_parse(disc, cp + 1, len);
|
|
} else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
|
|
} else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
|
|
FC_DISC_DBG(disc, "GPN_FT rejected reason %x exp %x "
|
|
FC_DISC_DBG(disc, "GPN_FT rejected reason %x exp %x "
|
|
"(check zoning)\n", cp->ct_reason,
|
|
"(check zoning)\n", cp->ct_reason,
|
|
cp->ct_explan);
|
|
cp->ct_explan);
|
|
- fc_disc_done(disc, DISC_EV_FAILED);
|
|
|
|
|
|
+ event = DISC_EV_FAILED;
|
|
} else {
|
|
} else {
|
|
FC_DISC_DBG(disc, "GPN_FT unexpected response code "
|
|
FC_DISC_DBG(disc, "GPN_FT unexpected response code "
|
|
"%x\n", ntohs(cp->ct_cmd));
|
|
"%x\n", ntohs(cp->ct_cmd));
|
|
}
|
|
}
|
|
- } else if (fr_sof(fp) == FC_SOF_N3 &&
|
|
|
|
- seq_cnt == disc->seq_count) {
|
|
|
|
- buf = fh + 1;
|
|
|
|
|
|
+ } else if (fr_sof(fp) == FC_SOF_N3 && seq_cnt == disc->seq_count) {
|
|
|
|
+ error = fc_disc_gpn_ft_parse(disc, fh + 1, len);
|
|
} else {
|
|
} else {
|
|
FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? "
|
|
FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? "
|
|
"seq_cnt %x expected %x sof %x eof %x\n",
|
|
"seq_cnt %x expected %x sof %x eof %x\n",
|
|
seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp));
|
|
seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp));
|
|
}
|
|
}
|
|
- if (buf) {
|
|
|
|
- disc->seq_count++;
|
|
|
|
- error = fc_disc_gpn_ft_parse(disc, buf, len);
|
|
|
|
- if (error)
|
|
|
|
- fc_disc_error(disc, fp);
|
|
|
|
- }
|
|
|
|
|
|
+ if (error)
|
|
|
|
+ fc_disc_error(disc, fp);
|
|
|
|
+ else if (event != DISC_EV_NONE)
|
|
|
|
+ fc_disc_done(disc, event);
|
|
fc_frame_free(fp);
|
|
fc_frame_free(fp);
|
|
-
|
|
|
|
mutex_unlock(&disc->disc_mutex);
|
|
mutex_unlock(&disc->disc_mutex);
|
|
}
|
|
}
|
|
|
|
|