[Open-FCoE] [RFC PATCH 14/28] libfc: remove gnn_id and gpn_id from the rport state machine

Robert Love robert.w.love at intel.com
Thu Sep 11 23:36:21 UTC 2008


Signed-off-by: Robert Love <robert.w.love at intel.com>
---

 drivers/scsi/libfc/fc_lport.c |    2 
 drivers/scsi/libfc/fc_ns.c    |  325 +++--------------------------------------
 drivers/scsi/libfc/fc_rport.c |  108 +++++++++++---
 include/scsi/libfc/libfc.h    |    4 -
 4 files changed, 114 insertions(+), 325 deletions(-)

diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 63fb7ff..2931931 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -65,10 +65,12 @@ static void fc_lport_rport_event(struct fc_lport *lport, struct fc_rport *rport,
 	if (rport->port_id == FC_FID_DIR_SERV) {
 		switch (event) {
 		case LPORT_EV_RPORT_CREATED:
+			lport->dns_rp = rport;
 			lport->tt.dns_register(lport);
 			break;
 		case LPORT_EV_RPORT_LOGO:
 		case LPORT_EV_RPORT_FAILED:
+			lport->dns_rp = NULL;
 			fc_lport_enter_reset(lport);
 			break;
 		}
diff --git a/drivers/scsi/libfc/fc_ns.c b/drivers/scsi/libfc/fc_ns.c
index d086b9d..f1bc512 100644
--- a/drivers/scsi/libfc/fc_ns.c
+++ b/drivers/scsi/libfc/fc_ns.c
@@ -43,14 +43,6 @@ static void fc_ns_del_target(struct fc_lport *, struct fc_rport *);
 static void fc_ns_disc_done(struct fc_lport *);
 static void fcdt_ns_error(struct fc_lport *, struct fc_frame *);
 static void fc_ns_timeout(struct work_struct *);
-
-static void fc_ns_gpn_id_req(struct fc_rport *);
-static void fc_ns_gpn_id_resp(struct fc_seq *, struct fc_frame *, void *);
-static void fc_ns_gpn_id_error(struct fc_rport *, struct fc_frame *);
-
-static void fc_ns_gnn_id_req(struct fc_rport *);
-static void fc_ns_gnn_id_resp(struct fc_seq *, struct fc_frame *, void *);
-static void fc_ns_gnn_id_error(struct fc_rport *, struct fc_frame *);
 static void fc_ns_enter_reg_pn(struct fc_lport *lp);
 static void fc_ns_error(struct fc_lport *lp, struct fc_frame *fp);
 static void fc_ns_resp(struct fc_seq *sp, struct fc_frame *fp,
@@ -59,37 +51,6 @@ static void fc_ns_retry(struct fc_lport *lp);
 static void fc_ns_single(struct fc_lport *, struct fc_ns_port *);
 static int fc_ns_restart(struct fc_lport *);
 
-struct fc_rport *fc_ns_create_dummy_rport(struct fc_ns_port *dp)
-{
-	struct fc_rport *rp;
-	struct fc_rport_libfc_priv *rpp;
-	rp = kzalloc(sizeof(*rp) + sizeof(*rpp), GFP_KERNEL);
-
-	if (!rp)
-		return NULL;
-
-	rpp = ((void *)rp + sizeof(struct fc_rport));
-
-	rp->dd_data = rpp;
-	rp->port_id = dp->ids.port_id;
-	rp->port_name = dp->ids.port_name;
-	rp->node_name = dp->ids.node_name;
-	rp->roles = dp->ids.roles;
-
-	mutex_init(&rpp->rp_mutex);
-	rpp->local_port = dp->lp;
-	rpp->rp_state = RPORT_ST_INIT;
-	rpp->flags = FC_RP_FLAGS_REC_SUPPORTED;
-	INIT_DELAYED_WORK(&rpp->retry_work, fc_ns_timeout);
-
-	return rp;
-}
-
-void fc_ns_destroy_dummy_rport(struct fc_rport *rp)
-{
-	kfree(rp);
-}
-
 /**
  * fc_ns_rscn_req - Handle Registered State Change Notification (RSCN)
  * @sp: Current sequence of the RSCN exchange
@@ -776,15 +737,19 @@ static int fc_ns_gpn_ft_parse(struct fc_lport *lp, void *buf, size_t len)
 		dp.ids.port_name = ntohll(np->fp_wwpn);
 		dp.ids.node_name = -1;
 		dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
-		rp = fc_ns_create_dummy_rport(&dp);
-
-		if (rp) {
-			rpp = rp->dd_data;
-			fc_ns_gnn_id_req(rp);
-		} else
-			FC_DBG("Failed to allocate memory for "
-			       "the newly discovered port (%6x)\n",
-			       dp.ids.port_id);
+
+		if ((dp.ids.port_id != lp->fid) &&
+		    (dp.ids.port_name != lp->wwpn)) {
+			rp = fc_rport_dummy_create(&dp);
+			if (rp) {
+				rpp = rp->dd_data;
+				rpp->local_port = lp;
+				lp->tt.rport_login(rp);
+			} else
+				FC_DBG("Failed to allocate memory for "
+				       "the newly discovered port (%6x)\n",
+				       dp.ids.port_id);
+		}
 			
 		if (np->fp_flags & FC_NS_FID_LAST) {
 			fc_ns_disc_done(lp);
@@ -912,127 +877,17 @@ static void fc_ns_single(struct fc_lport *lp, struct fc_ns_port *dp)
 		put_device(&rport->dev); /* hold from lookup */
 	}
 
-	rp = fc_ns_create_dummy_rport(dp);
+	rp = fc_rport_dummy_create(dp);
 	if (rp) {
 		rpp = rp->dd_data;
 		kfree(dp);
-		fc_ns_gpn_id_req(rp);
+		lp->tt.rport_login(rp);
 	}
 	return;
 out:
 	kfree(dp);
 }
 
-/**
- * fc_ns_gpn_id_req - Send Get Port Name by ID (GPN_ID) request
- * @rp: A temporary fc_rport
- *
- * XXX - this the following statement still valid?
- * The remote port is held by the caller for us.
- */
-static void fc_ns_gpn_id_req(struct fc_rport *rp)
-{
-	struct fc_rport_libfc_priv *rpp = rp->dd_data;
-	struct fc_lport *lp = rpp->local_port;
-	struct fc_frame *fp;
-	struct req {
-		struct fc_ct_hdr ct;
-		struct fc_ns_fid fid;
-	} *cp;
-
-	fp = fc_frame_alloc(lp, sizeof(*cp));
-	if (!fp)
-		return;
-
-	cp = fc_frame_payload_get(fp, sizeof(*cp));
-	fc_fill_dns_hdr(lp, &cp->ct, FC_NS_GPN_ID, sizeof(cp->fid));
-	hton24(cp->fid.fp_fid, rp->port_id);
-
-	WARN_ON(!fc_lport_test_ready(lp));
-
-	fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
-	lp->tt.exch_seq_send(lp, fp,
-			     fc_ns_gpn_id_resp,
-			     rp, lp->e_d_tov,
-			     lp->fid,
-			     lp->dns_rp->port_id,
-			     FC_FC_SEQ_INIT | FC_FC_END_SEQ);
-}
-
-/**
- * fc_ns_gpn_id_resp - Handle response to GPN_ID
- * @sp: Current sequence of GPN_ID exchange
- * @fp: response frame
- * @dp_arg: Temporary discovery port for holding IDs and world wide names
- */
-static void fc_ns_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
-			      void *rp_arg)
-{
-	struct fc_rport *rp = rp_arg;
-	struct fc_rport_libfc_priv *rpp = rp->dd_data;
-
-	struct fc_lport *lp;
-	struct resp {
-		struct fc_ct_hdr ct;
-		__be64 wwn;
-	} *cp;
-	unsigned int cmd;
-
-	if (IS_ERR(fp)) {
-		fc_ns_gpn_id_error(rp, fp);
-		return;
-	}
-
-	lp = rpp->local_port;
-	WARN_ON(!fc_frame_is_linear(fp));	/* buffer must be contiguous */
-
-	cp = fc_frame_payload_get(fp, sizeof(cp->ct));
-	if (cp == NULL) {
-		FC_DBG("GPN_ID response too short, len %d\n", fr_len(fp));
-		return;
-	}
-	cmd = ntohs(cp->ct.ct_cmd);
-	switch (cmd) {
-	case FC_FS_ACC:
-		cp = fc_frame_payload_get(fp, sizeof(*cp));
-		if (cp == NULL) {
-			FC_DBG("GPN_ID response payload too short, len %d\n",
-			       fr_len(fp));
-			break;
-		}
-		rp->port_name = ntohll(cp->wwn);
-		fc_ns_gnn_id_req(rp);
-		break;
-	case FC_FS_RJT:
-		fc_ns_restart(lp);
-		break;
-	default:
-		FC_DBG("GPN_ID unexpected CT response cmd %x\n", cmd);
-		break;
-	}
-	fc_frame_free(fp);
-}
-
-/**
- * fc_ns_gpn_id_error - Handle error from GPN_ID
- * @dp: Temporary discovery port for holding IDs and world wide names
- * @fp: response frame
- */
-static void fc_ns_gpn_id_error(struct fc_rport *rp, struct fc_frame *fp)
-{
-	struct fc_rport_libfc_priv *rpp = rp->dd_data;
-	struct fc_lport *lp = rpp->local_port;
-
-	switch (PTR_ERR(fp)) {
-	case -FC_EX_TIMEOUT:
-		fc_ns_restart(lp);
-		break;
-	case -FC_EX_CLOSED:
-	default:
-		break;
-	}
-}
-
 /*
  * Setup session to dNS if not already set up.
  */
@@ -1040,12 +895,12 @@ static void fc_ns_enter_dns(struct fc_lport *lp)
 {
 	struct fc_rport *rport;
 	struct fc_rport_libfc_priv *rp;
-	struct fc_rport_identifiers ids = {
-		.port_id = FC_FID_DIR_SERV,
-		.port_name = -1,
-		.node_name = -1,
-		.roles = FC_RPORT_ROLE_UNKNOWN,
-	};
+	struct fc_ns_port dp;
+
+	dp.ids.port_id = FC_FID_DIR_SERV;
+	dp.ids.port_name = -1;
+	dp.ids.node_name = -1;
+	dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
 
 	if (fc_ns_debug)
 		FC_DBG("Processing DNS state\n");
@@ -1053,18 +908,9 @@ static void fc_ns_enter_dns(struct fc_lport *lp)
 	fc_lport_state_enter(lp, LPORT_ST_DNS);
 
 	if (!lp->dns_rp) {
-		/*
-		 * Set up remote port to directory server.
-		 */
-
-		/*
-		 * we are called with the state_lock, but if rport_lookup_create
-		 * needs to create a rport then it will sleep.
-		 */
+		/* Set up a dummy rport to directory server */
 		fc_lport_unlock(lp);
-		rport = lp->tt.rport_lookup(lp, ids.port_id);
-		if (rport == NULL)
-			rport = lp->tt.rport_create(lp, &ids);
+		rport = fc_rport_dummy_create(&dp);
 		fc_lport_lock(lp);
 		if (!rport)
 			goto err;
@@ -1073,6 +919,7 @@ static void fc_ns_enter_dns(struct fc_lport *lp)
 
 	rport = lp->dns_rp;
 	rp = rport->dd_data;
+	rp->local_port = lp;
 
 	/*
 	 * If dNS session isn't ready, start its logon.
@@ -1166,127 +1013,3 @@ int fc_ns_init(struct fc_lport *lp)
 	return 0;
 }
 EXPORT_SYMBOL(fc_ns_init);
-
-/**
- * fc_ns_gnn_id_req - Send Get Node Name by ID (GNN_ID) request
- * @rp: Temporary fc_rport
- *
- * XXX- Is the following statement still true?
- * The remote port is held by the caller for us.
- */
-static void fc_ns_gnn_id_req(struct fc_rport *rp)
-{
-	struct fc_rport_libfc_priv *rpp = rp->dd_data;
-	struct fc_lport *lp = rpp->local_port;
-	struct fc_frame *fp;
-	struct req {
-		struct fc_ct_hdr ct;
-		struct fc_ns_fid fid;
-	} *cp;
-
-	fp = fc_frame_alloc(lp, sizeof(*cp));
-	if (!fp)
-		return;
-
-	cp = fc_frame_payload_get(fp, sizeof(*cp));
-	fc_fill_dns_hdr(lp, &cp->ct, FC_NS_GNN_ID, sizeof(cp->fid));
-	hton24(cp->fid.fp_fid, rp->port_id);
-
-	WARN_ON(!fc_lport_test_ready(lp));
-
-	fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
-	lp->tt.exch_seq_send(lp, fp,
-			     fc_ns_gnn_id_resp,
-			     rp, lp->e_d_tov,
-			     lp->fid,
-			     lp->dns_rp->port_id,
-			     FC_FC_SEQ_INIT | FC_FC_END_SEQ);
-}
-
-/**
- * fc_ns_gnn_id_resp - Handle response to GNN_ID
- * @sp: Current sequence of GNN_ID exchange
- * @fp: response frame
- * @dp_arg: Temporary discovery port for holding IDs and world wide names
- */
-static void fc_ns_gnn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
-			      void *rp_arg)
-{
-	struct fc_rport *rp = rp_arg;
-	struct fc_rport_libfc_priv *rpp;
-	struct fc_lport *lp;
-	struct fc_rport_identifiers ids;
-
-	struct resp {
-		struct fc_ct_hdr ct;
-		__be64 wwn;
-	} *cp;
-	unsigned int cmd;
-
-	rpp = rp->dd_data;
-
-	if (IS_ERR(fp)) {
-		fc_ns_gnn_id_error(rp, fp);
-		return;
-	}
-
-	lp = rpp->local_port;
-	WARN_ON(!fc_frame_is_linear(fp));	/* buffer must be contiguous */
-
-	cp = fc_frame_payload_get(fp, sizeof(cp->ct));
-	if (cp == NULL) {
-		FC_DBG("GNN_ID response too short, len %d\n", fr_len(fp));
-		return;
-	}
-
-	cmd = ntohs(cp->ct.ct_cmd);
-	switch (cmd) {
-	case FC_FS_ACC:
-		cp = fc_frame_payload_get(fp, sizeof(*cp));
-		if (cp == NULL) {
-			FC_DBG("GNN_ID response payload too short, len %d\n",
-			       fr_len(fp));
-			break;
-		}
-		rp->node_name = ntohll(cp->wwn);
-
-		ids.port_id = rp->port_id;
-		ids.port_name = rp->port_name;
-		ids.node_name = rp->node_name;
-		ids.roles = rp->roles;
-
-		fc_ns_destroy_dummy_rport(rp);
-
-		fc_ns_new_target(lp, NULL, &ids);
-		break;
-	case FC_FS_RJT:
-		fc_ns_restart(lp);
-		break;
-	default:
-		FC_DBG("GNN_ID unexpected CT response cmd %x\n", cmd);
-		break;
-	}
-
-	fc_frame_free(fp);
-}
-
-/**
- * fc_ns_gnn_id_error - Handle error from GNN_ID
- * @dp: Temporary discovery port for holding IDs and world wide names
- * @fp: response frame
- */
-static void fc_ns_gnn_id_error(struct fc_rport *rp, struct fc_frame *fp)
-{
-	struct fc_rport_libfc_priv *rpp = rp->dd_data;
-	struct fc_lport *lp = rpp->local_port;
-
-	switch (PTR_ERR(fp)) {
-	case -FC_EX_TIMEOUT:
-		fc_ns_restart(lp);
-		break;
-	case -FC_EX_CLOSED:
-	default:
-		break;
-	}
-}
-
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index ff46c8a..45e614d 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -65,6 +65,37 @@ static const char *fc_rport_state_names[] = {
 	[RPORT_ST_LOGO] = "LOGO",
 };
 
+struct fc_rport *fc_rport_dummy_create(struct fc_ns_port *dp)
+{
+	struct fc_rport *rport;
+	struct fc_rport_libfc_priv *rdata;
+	rport = kzalloc(sizeof(*rport) + sizeof(*rdata), GFP_KERNEL);
+
+	if (!rport)
+		return NULL;
+
+	rdata = ((void *)rport + sizeof(struct fc_rport));
+
+	rport->dd_data = rdata;
+	rport->port_id = dp->ids.port_id;
+	rport->port_name = dp->ids.port_name;
+	rport->node_name = dp->ids.node_name;
+	rport->roles = dp->ids.roles;
+
+	mutex_init(&rdata->rp_mutex);
+	rdata->local_port = dp->lp;
+	rdata->rp_state = RPORT_ST_INIT;
+	rdata->flags = FC_RP_FLAGS_REC_SUPPORTED;
+	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
+
+	return rport;
+}
+
+void fc_rport_dummy_destroy(struct fc_rport *rport)
+{
+	kfree(rport);
+}
+
 /**
  * fc_rport_state - return a string for the state the rport is in
  * @rport: The rport whose state we want to get a string for
@@ -437,9 +468,9 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 {
 	struct fc_rport *rport = rp_arg;
 	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_lport *lport = rdata->local_port;
 	struct fc_els_ls_rjt *rjp;
 	struct fc_els_flogi *plp;
-	u64 wwpn, wwnn;
 	unsigned int tov;
 	u16 csp_seq;
 	u16 cssp_seq;
@@ -464,32 +495,65 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 	op = fc_frame_payload_op(fp);
 	if (op == ELS_LS_ACC &&
 	    (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
-		wwpn = get_unaligned_be64(&plp->fl_wwpn);
-		wwnn = get_unaligned_be64(&plp->fl_wwnn);
+		struct fc_rport_identifiers ids;
+		struct fc_rport *new_rport;
+		struct fc_rport_libfc_priv *new_rdata;
+
+		ids.port_id = rport->port_id;
+		ids.roles = rport->roles;
+		ids.port_name = get_unaligned_be64(&plp->fl_wwpn);
+		ids.node_name = get_unaligned_be64(&plp->fl_wwnn);
+
+		new_rport = lport->tt.rport_lookup(lport, ids.port_id);
+		if (!new_rport)
+			new_rport = lport->tt.rport_create(lport, &ids);
+
+		if (!new_rport) {
+			FC_DBG("Failed to create the rport for port "
+			       "(%6x).\n", ids.port_id);
+			fc_rport_dummy_destroy(rport);
+			goto out;
+		}
+
+		/*
+		 * Switch from the dummy rport to the rport
+		 * returned by the FC class.
+		 */
+		new_rdata = new_rport->dd_data;
+
+		mutex_lock(&new_rdata->rp_mutex);
+
+		new_rdata->event_callback = rdata->event_callback;
+		new_rdata->local_port = rdata->local_port;
+		fc_rport_state_enter(new_rport, RPORT_ST_PLOGI);
+
+		mutex_unlock(&rdata->rp_mutex);
+		fc_rport_dummy_destroy(rport);
 
-		fc_rport_set_name(rport, wwpn, wwnn);
 		tov = ntohl(plp->fl_csp.sp_e_d_tov);
 		if (ntohs(plp->fl_csp.sp_features) & FC_SP_FT_EDTR)
 			tov /= 1000;
-			if (tov > rdata->e_d_tov)
-				rdata->e_d_tov = tov;
-			csp_seq = ntohs(plp->fl_csp.sp_tot_seq);
-			cssp_seq = ntohs(plp->fl_cssp[3 - 1].cp_con_seq);
-			if (cssp_seq < csp_seq)
-				csp_seq = cssp_seq;
-			rdata->max_seq = csp_seq;
-			rport->maxframe_size =
-				fc_plogi_get_maxframe(plp,
-						      rdata->local_port->mfs);
+		if (tov > rdata->e_d_tov)
+			new_rdata->e_d_tov = tov;
+		csp_seq = ntohs(plp->fl_csp.sp_tot_seq);
+		cssp_seq = ntohs(plp->fl_cssp[3 - 1].cp_con_seq);
+		if (cssp_seq < csp_seq)
+			csp_seq = cssp_seq;
+		new_rdata->max_seq = csp_seq;
+		new_rport->maxframe_size =
+			fc_plogi_get_maxframe(plp, new_rdata->local_port->mfs);
 
-			/*
-			 * If the rport is one of the well known addresses
-			 * we skip PRLI and RTV and go straight to READY.
-			 */
-			if (rport->port_id >= FC_FID_DOM_MGR)
-				fc_rport_enter_ready(rport);
-			else
-				fc_rport_enter_prli(rport);
+		/*
+		 * If the rport is one of the well known addresses
+		 * we skip PRLI and RTV and go straight to READY.
+		 */
+		if (new_rport->port_id >= FC_FID_DOM_MGR)
+			fc_rport_enter_ready(new_rport);
+		else
+			fc_rport_enter_prli(new_rport);
+
+		rdata = new_rdata;
+		rport = new_rport;
 	} else {
 		if (fc_rp_debug)
 			FC_DBG("bad PLOGI response\n");
diff --git a/include/scsi/libfc/libfc.h b/include/scsi/libfc/libfc.h
index 9ec715d..66fb5af 100644
--- a/include/scsi/libfc/libfc.h
+++ b/include/scsi/libfc/libfc.h
@@ -164,8 +164,8 @@ struct fc_rport_libfc_priv {
 	u32 roles;
 };
 
-struct fc_rport *fc_ns_create_dummy_rport(struct fc_ns_port *);
-void fc_ns_destroy_dummy_rport(struct fc_rport *);
+struct fc_rport *fc_rport_dummy_create(struct fc_ns_port *);
+void fc_rport_dummy_destroy(struct fc_rport *);
 
 static inline void fc_rport_set_name(struct fc_rport *rport, u64 wwpn, u64 wwnn)
 {




More information about the devel mailing list