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

Reply via email to