Signed-off-by: Robert Love <[EMAIL PROTECTED]>
---
drivers/scsi/libfc/fc_lport.c | 2
drivers/scsi/libfc/fc_ns.c | 309 ++---------------------------------------
drivers/scsi/libfc/fc_rport.c | 104 +++++++++++---
include/scsi/libfc/libfc.h | 4 -
4 files changed, 104 insertions(+), 315 deletions(-)
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index ec2f1f3..a8a930e 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 65dff77..71e31e3 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,33 +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);
- 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;
-
- spin_lock_init(&rpp->rp_lock);
- 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
@@ -772,10 +737,14 @@ 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);
- rpp = rp->dd_data;
- fc_ns_gnn_id_req(rp);
+ if ((dp.ids.port_id != lp->fid) &&
+ (dp.ids.port_name != lp->wwpn)) {
+ rp = fc_rport_dummy_create(&dp);
+ rpp = rp->dd_data;
+ rpp->local_port = lp;
+ lp->tt.rport_login(rp);
+ }
if (np->fp_flags & FC_NS_FID_LAST) {
fc_ns_disc_done(lp);
@@ -903,126 +872,16 @@ 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);
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.
*/
@@ -1030,12 +889,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");
@@ -1043,18 +902,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;
@@ -1063,6 +913,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.
@@ -1156,127 +1007,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 7231a11..7a355d1 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -65,6 +65,33 @@ 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);
+ 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;
+
+ spin_lock_init(&rdata->rp_lock);
+ 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
@@ -440,9 +467,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;
@@ -467,32 +494,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) {
+ spin_unlock_bh(&rdata->rp_lock);
+ new_rport = lport->tt.rport_create(lport, &ids);
+ spin_lock_bh(&rdata->rp_lock);
+ }
+
+ 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;
+ spin_lock_bh(&new_rdata->rp_lock);
+ new_rdata->event_callback = rdata->event_callback;
+ new_rdata->local_port = rdata->local_port;
+ fc_rport_state_enter(new_rport, RPORT_ST_PLOGI);
+ spin_unlock_bh(&rdata->rp_lock);
+ 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 d738ebc..c1154ef 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)
{
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel