[SCSI] libfc: rearrange code in fc_disc_gpn_ft_resp()
[deliverable/linux.git] / drivers / scsi / libfc / fc_disc.c
index 4c880656990baab8f275b01316f6a691001f5f01..819ec6256a53619a6d7cd4205fbcd77faa17301e 100644 (file)
 #define FC_DISC_RETRY_LIMIT    3       /* max retries */
 #define FC_DISC_RETRY_DELAY    500UL   /* (msecs) delay */
 
-#define        FC_DISC_DELAY           3
-
-static int fc_disc_debug;
-
-#define FC_DEBUG_DISC(fmt...)                  \
-       do {                                    \
-               if (fc_disc_debug)              \
-                       FC_DBG(fmt);            \
-       } while (0)
-
 static void fc_disc_gpn_ft_req(struct fc_disc *);
 static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
-static int fc_disc_new_target(struct fc_disc *, struct fc_rport *,
+static int fc_disc_new_target(struct fc_disc *, struct fc_rport_priv *,
                              struct fc_rport_identifiers *);
-static void fc_disc_del_target(struct fc_disc *, struct fc_rport *);
-static void fc_disc_done(struct fc_disc *);
+static void fc_disc_done(struct fc_disc *, enum fc_disc_event);
 static void fc_disc_timeout(struct work_struct *);
 static void fc_disc_single(struct fc_disc *, struct fc_disc_port *);
 static void fc_disc_restart(struct fc_disc *);
 
-/**
- * fc_disc_lookup_rport() - lookup a remote port by port_id
- * @lport: Fibre Channel host port instance
- * @port_id: remote port port_id to match
- */
-struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport,
-                                     u32 port_id)
-{
-       const struct fc_disc *disc = &lport->disc;
-       struct fc_rport *rport, *found = NULL;
-       struct fc_rport_libfc_priv *rdata;
-       int disc_found = 0;
-
-       list_for_each_entry(rdata, &disc->rports, peers) {
-               rport = PRIV_TO_RPORT(rdata);
-               if (rport->port_id == port_id) {
-                       disc_found = 1;
-                       found = rport;
-                       break;
-               }
-       }
-
-       if (!disc_found)
-               found = NULL;
-
-       return found;
-}
-
 /**
  * fc_disc_stop_rports() - delete all the remote ports associated with the lport
  * @disc: The discovery job to stop rports on
@@ -101,69 +62,16 @@ struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport,
 void fc_disc_stop_rports(struct fc_disc *disc)
 {
        struct fc_lport *lport;
-       struct fc_rport *rport;
-       struct fc_rport_libfc_priv *rdata, *next;
+       struct fc_rport_priv *rdata, *next;
 
        lport = disc->lport;
 
        mutex_lock(&disc->disc_mutex);
-       list_for_each_entry_safe(rdata, next, &disc->rports, peers) {
-               rport = PRIV_TO_RPORT(rdata);
-               list_del(&rdata->peers);
-               lport->tt.rport_logoff(rport);
-       }
-
-       list_for_each_entry_safe(rdata, next, &disc->rogue_rports, peers) {
-               rport = PRIV_TO_RPORT(rdata);
-               lport->tt.rport_logoff(rport);
-       }
-
+       list_for_each_entry_safe(rdata, next, &disc->rports, peers)
+               lport->tt.rport_logoff(rdata);
        mutex_unlock(&disc->disc_mutex);
 }
 
-/**
- * fc_disc_rport_callback() - Event handler for rport events
- * @lport: The lport which is receiving the event
- * @rport: The rport which the event has occured on
- * @event: The event that occured
- *
- * Locking Note: The rport lock should not be held when calling
- *              this function.
- */
-static void fc_disc_rport_callback(struct fc_lport *lport,
-                                  struct fc_rport *rport,
-                                  enum fc_rport_event event)
-{
-       struct fc_rport_libfc_priv *rdata = rport->dd_data;
-       struct fc_disc *disc = &lport->disc;
-
-       FC_DEBUG_DISC("Received a %d event for port (%6x)\n", event,
-                     rport->port_id);
-
-       switch (event) {
-       case RPORT_EV_CREATED:
-               if (disc) {
-                       mutex_lock(&disc->disc_mutex);
-                       list_add_tail(&rdata->peers, &disc->rports);
-                       mutex_unlock(&disc->disc_mutex);
-               }
-               break;
-       case RPORT_EV_LOGO:
-       case RPORT_EV_FAILED:
-       case RPORT_EV_STOP:
-               mutex_lock(&disc->disc_mutex);
-               mutex_lock(&rdata->rp_mutex);
-               if (rdata->trans_state == FC_PORTSTATE_ROGUE)
-                       list_del(&rdata->peers);
-               mutex_unlock(&rdata->rp_mutex);
-               mutex_unlock(&disc->disc_mutex);
-               break;
-       default:
-               break;
-       }
-
-}
-
 /**
  * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
  * @sp: Current sequence of the RSCN exchange
@@ -177,8 +85,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
                                  struct fc_disc *disc)
 {
        struct fc_lport *lport;
-       struct fc_rport *rport;
-       struct fc_rport_libfc_priv *rdata;
+       struct fc_rport_priv *rdata;
        struct fc_els_rscn *rp;
        struct fc_els_rscn_page *pp;
        struct fc_seq_els_data rjt_data;
@@ -191,8 +98,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
 
        lport = disc->lport;
 
-       FC_DEBUG_DISC("Received an RSCN event on port (%6x)\n",
-                     fc_host_port_id(lport->host));
+       FC_DISC_DBG(disc, "Received an RSCN event\n");
 
        /* make sure the frame contains an RSCN message */
        rp = fc_frame_payload_get(fp, sizeof(*rp));
@@ -225,8 +131,8 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
                 */
                switch (fmt) {
                case ELS_ADDR_FMT_PORT:
-                       FC_DEBUG_DISC("Port address format for port (%6x)\n",
-                                     ntoh24(pp->rscn_fid));
+                       FC_DISC_DBG(disc, "Port address format for port "
+                                   "(%6x)\n", ntoh24(pp->rscn_fid));
                        dp = kzalloc(sizeof(*dp), GFP_KERNEL);
                        if (!dp) {
                                redisc = 1;
@@ -243,26 +149,24 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
                case ELS_ADDR_FMT_DOM:
                case ELS_ADDR_FMT_FAB:
                default:
-                       FC_DEBUG_DISC("Address format is (%d)\n", fmt);
+                       FC_DISC_DBG(disc, "Address format is (%d)\n", fmt);
                        redisc = 1;
                        break;
                }
        }
        lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
        if (redisc) {
-               FC_DEBUG_DISC("RSCN received: rediscovering\n");
+               FC_DISC_DBG(disc, "RSCN received: rediscovering\n");
                fc_disc_restart(disc);
        } else {
-               FC_DEBUG_DISC("RSCN received: not rediscovering. "
-                             "redisc %d state %d in_prog %d\n",
-                             redisc, lport->state, disc->pending);
+               FC_DISC_DBG(disc, "RSCN received: not rediscovering. "
+                           "redisc %d state %d in_prog %d\n",
+                           redisc, lport->state, disc->pending);
                list_for_each_entry_safe(dp, next, &disc_ports, peers) {
                        list_del(&dp->peers);
-                       rport = lport->tt.rport_lookup(lport, dp->ids.port_id);
-                       if (rport) {
-                               rdata = rport->dd_data;
-                               list_del(&rdata->peers);
-                               lport->tt.rport_logoff(rport);
+                       rdata = lport->tt.rport_lookup(lport, dp->ids.port_id);
+                       if (rdata) {
+                               lport->tt.rport_logoff(rdata);
                        }
                        fc_disc_single(disc, dp);
                }
@@ -270,7 +174,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
        fc_frame_free(fp);
        return;
 reject:
-       FC_DEBUG_DISC("Received a bad RSCN frame\n");
+       FC_DISC_DBG(disc, "Received a bad RSCN frame\n");
        rjt_data.fp = NULL;
        rjt_data.reason = ELS_RJT_LOGIC;
        rjt_data.explan = ELS_EXPL_NONE;
@@ -302,7 +206,8 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
                mutex_unlock(&disc->disc_mutex);
                break;
        default:
-               FC_DBG("Received an unsupported request. opcode (%x)\n", op);
+               FC_DISC_DBG(disc, "Received an unsupported request, "
+                           "the opcode is (%x)\n", op);
                break;
        }
 }
@@ -316,23 +221,19 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
  */
 static void fc_disc_restart(struct fc_disc *disc)
 {
-       struct fc_rport *rport;
-       struct fc_rport_libfc_priv *rdata, *next;
-       struct fc_lport *lport = disc->lport;
-
-       FC_DEBUG_DISC("Restarting discovery for port (%6x)\n",
-                     fc_host_port_id(lport->host));
-
-       list_for_each_entry_safe(rdata, next, &disc->rports, peers) {
-               rport = PRIV_TO_RPORT(rdata);
-               FC_DEBUG_DISC("list_del(%6x)\n", rport->port_id);
-               list_del(&rdata->peers);
-               lport->tt.rport_logoff(rport);
-       }
+       FC_DISC_DBG(disc, "Restarting discovery\n");
 
        disc->requested = 1;
-       if (!disc->pending)
-               fc_disc_gpn_ft_req(disc);
+       if (disc->pending)
+               return;
+
+       /*
+        * Advance disc_id.  This is an arbitrary non-zero number that will
+        * match the value in the fc_rport_priv after discovery for all
+        * freshly-discovered remote ports.  Avoid wrapping to zero.
+        */
+       disc->disc_id = (disc->disc_id + 2) | 1;
+       fc_disc_gpn_ft_req(disc);
 }
 
 /**
@@ -345,8 +246,7 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
                                                enum fc_disc_event),
                          struct fc_lport *lport)
 {
-       struct fc_rport *rport;
-       struct fc_rport_identifiers ids;
+       struct fc_rport_priv *rdata;
        struct fc_disc *disc = &lport->disc;
 
        /*
@@ -372,55 +272,45 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
         * Handle point-to-point mode as a simple discovery
         * of the remote port. Yucky, yucky, yuck, yuck!
         */
-       rport = disc->lport->ptp_rp;
-       if (rport) {
-               ids.port_id = rport->port_id;
-               ids.port_name = rport->port_name;
-               ids.node_name = rport->node_name;
-               ids.roles = FC_RPORT_ROLE_UNKNOWN;
-               get_device(&rport->dev);
-
-               if (!fc_disc_new_target(disc, rport, &ids)) {
-                       disc->event = DISC_EV_SUCCESS;
-                       fc_disc_done(disc);
+       rdata = disc->lport->ptp_rp;
+       if (rdata) {
+               kref_get(&rdata->kref);
+               if (!fc_disc_new_target(disc, rdata, &rdata->ids)) {
+                       fc_disc_done(disc, DISC_EV_SUCCESS);
                }
-               put_device(&rport->dev);
+               kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
        } else {
+               disc->disc_id = (disc->disc_id + 2) | 1;
                fc_disc_gpn_ft_req(disc);       /* get ports by FC-4 type */
        }
 
        mutex_unlock(&disc->disc_mutex);
 }
 
-static struct fc_rport_operations fc_disc_rport_ops = {
-       .event_callback = fc_disc_rport_callback,
-};
-
 /**
  * fc_disc_new_target() - Handle new target found by discovery
  * @lport: FC local port
- * @rport: The previous FC remote port (NULL if new remote port)
+ * @rdata: The previous FC remote port priv (NULL if new remote port)
  * @ids: Identifiers for the new FC remote port
  *
  * Locking Note: This function expects that the disc_mutex is locked
  *              before it is called.
  */
 static int fc_disc_new_target(struct fc_disc *disc,
-                             struct fc_rport *rport,
+                             struct fc_rport_priv *rdata,
                              struct fc_rport_identifiers *ids)
 {
        struct fc_lport *lport = disc->lport;
-       struct fc_rport_libfc_priv *rdata;
        int error = 0;
 
-       if (rport && ids->port_name) {
-               if (rport->port_name == -1) {
+       if (rdata && ids->port_name) {
+               if (rdata->ids.port_name == -1) {
                        /*
                         * Set WWN and fall through to notify of create.
                         */
-                       fc_rport_set_name(rport, ids->port_name,
-                                         rport->node_name);
-               } else if (rport->port_name != ids->port_name) {
+                       rdata->ids.port_name = ids->port_name;
+                       rdata->ids.node_name = ids->node_name;
+               } else if (rdata->ids.port_name != ids->port_name) {
                        /*
                         * This is a new port with the same FCID as
                         * a previously-discovered port.  Presumably the old
@@ -428,73 +318,60 @@ static int fc_disc_new_target(struct fc_disc *disc,
                         * assigned the same FCID.  This should be rare.
                         * Delete the old one and fall thru to re-create.
                         */
-                       fc_disc_del_target(disc, rport);
-                       rport = NULL;
+                       lport->tt.rport_logoff(rdata);
+                       rdata = NULL;
                }
        }
        if (((ids->port_name != -1) || (ids->port_id != -1)) &&
            ids->port_id != fc_host_port_id(lport->host) &&
            ids->port_name != lport->wwpn) {
-               if (!rport) {
-                       rport = lport->tt.rport_lookup(lport, ids->port_id);
-                       if (!rport) {
-                               struct fc_disc_port dp;
-                               dp.lp = lport;
-                               dp.ids.port_id = ids->port_id;
-                               dp.ids.port_name = ids->port_name;
-                               dp.ids.node_name = ids->node_name;
-                               dp.ids.roles = ids->roles;
-                               rport = lport->tt.rport_create(&dp);
-                       }
-                       if (!rport)
+               if (!rdata) {
+                       rdata = lport->tt.rport_create(lport, ids);
+                       if (!rdata)
                                error = -ENOMEM;
                }
-               if (rport) {
-                       rdata = rport->dd_data;
-                       rdata->ops = &fc_disc_rport_ops;
-                       rdata->rp_state = RPORT_ST_INIT;
-                       list_add_tail(&rdata->peers, &disc->rogue_rports);
-                       lport->tt.rport_login(rport);
-               }
+               if (rdata)
+                       lport->tt.rport_login(rdata);
        }
        return error;
 }
 
-/**
- * fc_disc_del_target() - Delete a target
- * @disc: FC discovery context
- * @rport: The remote port to be removed
- */
-static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport)
-{
-       struct fc_lport *lport = disc->lport;
-       struct fc_rport_libfc_priv *rdata = rport->dd_data;
-       list_del(&rdata->peers);
-       lport->tt.rport_logoff(rport);
-}
-
 /**
  * fc_disc_done() - Discovery has been completed
  * @disc: FC discovery context
+ * @event: discovery completion status
+ *
  * Locking Note: This function expects that the disc mutex is locked before
  * it is called. The discovery callback is then made with the lock released,
  * and the lock is re-taken before returning from this function
  */
-static void fc_disc_done(struct fc_disc *disc)
+static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
 {
        struct fc_lport *lport = disc->lport;
-       enum fc_disc_event event;
+       struct fc_rport_priv *rdata;
 
-       FC_DEBUG_DISC("Discovery complete for port (%6x)\n",
-                     fc_host_port_id(lport->host));
+       FC_DISC_DBG(disc, "Discovery complete\n");
 
-       event = disc->event;
-       disc->event = DISC_EV_NONE;
+       disc->pending = 0;
+       if (disc->requested) {
+               fc_disc_restart(disc);
+               return;
+       }
 
-       if (disc->requested)
-               fc_disc_gpn_ft_req(disc);
-       else
-               disc->pending = 0;
+       /*
+        * Go through all remote ports.  If they were found in the latest
+        * discovery, reverify or log them in.  Otherwise, log them out.
+        * Skip ports which were never discovered.  These are the dNS port
+        * and ports which were created by PLOGI.
+        */
+       list_for_each_entry(rdata, &disc->rports, peers) {
+               if (!rdata->disc_id)
+                       continue;
+               if (rdata->disc_id == disc->disc_id)
+                       lport->tt.rport_login(rdata);
+               else
+                       lport->tt.rport_logoff(rdata);
+       }
 
        mutex_unlock(&disc->disc_mutex);
        disc->disc_callback(lport, event);
@@ -510,10 +387,10 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp)
 {
        struct fc_lport *lport = disc->lport;
        unsigned long delay = 0;
-       if (fc_disc_debug)
-               FC_DBG("Error %ld, retries %d/%d\n",
-                      PTR_ERR(fp), disc->retry_count,
-                      FC_DISC_RETRY_LIMIT);
+
+       FC_DISC_DBG(disc, "Error %ld, retries %d/%d\n",
+                   PTR_ERR(fp), disc->retry_count,
+                   FC_DISC_RETRY_LIMIT);
 
        if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
                /*
@@ -533,11 +410,8 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp)
                        }
                        disc->retry_count++;
                        schedule_delayed_work(&disc->disc_work, delay);
-               } else {
-                       /* exceeded retries */
-                       disc->event = DISC_EV_FAILED;
-                       fc_disc_done(disc);
-               }
+               } else
+                       fc_disc_done(disc, DISC_EV_FAILED);
        }
 }
 
@@ -566,7 +440,7 @@ static void fc_disc_gpn_ft_req(struct fc_disc *disc)
        if (!fp)
                goto err;
 
-       if (lport->tt.elsct_send(lport, NULL, fp,
+       if (lport->tt.elsct_send(lport, 0, fp,
                                 FC_NS_GPN_FT,
                                 fc_disc_gpn_ft_resp,
                                 disc, lport->e_d_tov))
@@ -576,10 +450,12 @@ err:
 }
 
 /**
- * fc_disc_gpn_ft_parse() - Parse the list of IDs and names resulting from a request
+ * fc_disc_gpn_ft_parse() - Parse the body of the dNS GPN_FT response.
  * @lport: Fibre Channel host port instance
  * @buf: GPN_FT response buffer
  * @len: size of response buffer
+ *
+ * Goes through the list of IDs and names resulting from a request.
  */
 static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 {
@@ -589,11 +465,11 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
        size_t plen;
        size_t tlen;
        int error = 0;
-       struct fc_disc_port dp;
-       struct fc_rport *rport;
-       struct fc_rport_libfc_priv *rdata;
+       struct fc_rport_identifiers ids;
+       struct fc_rport_priv *rdata;
 
        lport = disc->lport;
+       disc->seq_count++;
 
        /*
         * Handle partial name record left over from previous call.
@@ -632,31 +508,24 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
         * After the first time through the loop, things return to "normal".
         */
        while (plen >= sizeof(*np)) {
-               dp.lp = lport;
-               dp.ids.port_id = ntoh24(np->fp_fid);
-               dp.ids.port_name = ntohll(np->fp_wwpn);
-               dp.ids.node_name = -1;
-               dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
-
-               if ((dp.ids.port_id != fc_host_port_id(lport->host)) &&
-                   (dp.ids.port_name != lport->wwpn)) {
-                       rport = lport->tt.rport_create(&dp);
-                       if (rport) {
-                               rdata = rport->dd_data;
-                               rdata->ops = &fc_disc_rport_ops;
-                               rdata->local_port = lport;
-                               list_add_tail(&rdata->peers,
-                                             &disc->rogue_rports);
-                               lport->tt.rport_login(rport);
-                       } else
-                               FC_DBG("Failed to allocate memory for "
-                                      "the newly discovered port (%6x)\n",
-                                      dp.ids.port_id);
+               ids.port_id = ntoh24(np->fp_fid);
+               ids.port_name = ntohll(np->fp_wwpn);
+               ids.node_name = -1;
+               ids.roles = FC_RPORT_ROLE_UNKNOWN;
+
+               if (ids.port_id != fc_host_port_id(lport->host) &&
+                   ids.port_name != lport->wwpn) {
+                       rdata = lport->tt.rport_create(lport, &ids);
+                       if (rdata)
+                               rdata->disc_id = disc->disc_id;
+                       else
+                               printk(KERN_WARNING "libfc: Failed to allocate "
+                                      "memory for the newly discovered port "
+                                      "(%6x)\n", ids.port_id);
                }
 
                if (np->fp_flags & FC_NS_FID_LAST) {
-                       disc->event = DISC_EV_SUCCESS;
-                       fc_disc_done(disc);
+                       fc_disc_done(disc, DISC_EV_SUCCESS);
                        len = 0;
                        break;
                }
@@ -671,9 +540,8 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
         */
        if (error == 0 && len > 0 && len < sizeof(*np)) {
                if (np != &disc->partial_buf) {
-                       FC_DEBUG_DISC("Partial buffer remains "
-                                     "for discovery by (%6x)\n",
-                                     fc_host_port_id(lport->host));
+                       FC_DISC_DBG(disc, "Partial buffer remains "
+                                   "for discovery\n");
                        memcpy(&disc->partial_buf, np, len);
                }
                disc->buf_len = (unsigned char) len;
@@ -715,14 +583,13 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
        struct fc_disc *disc = disc_arg;
        struct fc_ct_hdr *cp;
        struct fc_frame_header *fh;
+       enum fc_disc_event event = DISC_EV_NONE;
        unsigned int seq_cnt;
-       void *buf = NULL;
        unsigned int len;
-       int error;
+       int error = 0;
 
        mutex_lock(&disc->disc_mutex);
-       FC_DEBUG_DISC("Received a GPN_FT response on port (%6x)\n",
-                     fc_host_port_id(disc->lport->host));
+       FC_DISC_DBG(disc, "Received a GPN_FT response\n");
 
        if (IS_ERR(fp)) {
                fc_disc_error(disc, fp);
@@ -734,44 +601,37 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
        fh = fc_frame_header_get(fp);
        len = fr_len(fp) - sizeof(*fh);
        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));
                if (!cp) {
-                       FC_DBG("GPN_FT response too short, len %d\n",
-                              fr_len(fp));
+                       FC_DISC_DBG(disc, "GPN_FT response too short, len %d\n",
+                                   fr_len(fp));
                } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
 
                        /* Accepted, parse the response. */
-                       buf = cp + 1;
                        len -= sizeof(*cp);
+                       error = fc_disc_gpn_ft_parse(disc, cp + 1, len);
                } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
-                       FC_DBG("GPN_FT rejected reason %x exp %x "
-                              "(check zoning)\n", cp->ct_reason,
-                              cp->ct_explan);
-                       disc->event = DISC_EV_FAILED;
-                       fc_disc_done(disc);
+                       FC_DISC_DBG(disc, "GPN_FT rejected reason %x exp %x "
+                                   "(check zoning)\n", cp->ct_reason,
+                                   cp->ct_explan);
+                       event = DISC_EV_FAILED;
                } else {
-                       FC_DBG("GPN_FT unexpected response code %x\n",
-                              ntohs(cp->ct_cmd));
+                       FC_DISC_DBG(disc, "GPN_FT unexpected response code "
+                                   "%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 {
-               FC_DBG("GPN_FT unexpected frame - out of sequence? "
-                      "seq_cnt %x expected %x sof %x eof %x\n",
-                      seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp));
-       }
-       if (buf) {
-               error = fc_disc_gpn_ft_parse(disc, buf, len);
-               if (error)
-                       fc_disc_error(disc, fp);
-               else
-                       disc->seq_count++;
+               FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? "
+                           "seq_cnt %x expected %x sof %x eof %x\n",
+                           seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp));
        }
+       if (error)
+               fc_disc_error(disc, fp);
+       else if (event != DISC_EV_NONE)
+               fc_disc_done(disc, event);
        fc_frame_free(fp);
-
        mutex_unlock(&disc->disc_mutex);
 }
 
@@ -786,21 +646,18 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
 static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
 {
        struct fc_lport *lport;
-       struct fc_rport *new_rport;
-       struct fc_rport_libfc_priv *rdata;
+       struct fc_rport_priv *rdata;
 
        lport = disc->lport;
 
        if (dp->ids.port_id == fc_host_port_id(lport->host))
                goto out;
 
-       new_rport = lport->tt.rport_create(dp);
-       if (new_rport) {
-               rdata = new_rport->dd_data;
-               rdata->ops = &fc_disc_rport_ops;
+       rdata = lport->tt.rport_create(lport, &dp->ids);
+       if (rdata) {
+               rdata->disc_id = disc->disc_id;
                kfree(dp);
-               list_add_tail(&rdata->peers, &disc->rogue_rports);
-               lport->tt.rport_login(new_rport);
+               lport->tt.rport_login(rdata);
        }
        return;
 out:
@@ -854,18 +711,12 @@ int fc_disc_init(struct fc_lport *lport)
        if (!lport->tt.disc_recv_req)
                lport->tt.disc_recv_req = fc_disc_recv_req;
 
-       if (!lport->tt.rport_lookup)
-               lport->tt.rport_lookup = fc_disc_lookup_rport;
-
        disc = &lport->disc;
        INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
        mutex_init(&disc->disc_mutex);
        INIT_LIST_HEAD(&disc->rports);
-       INIT_LIST_HEAD(&disc->rogue_rports);
 
        disc->lport = lport;
-       disc->delay = FC_DISC_DELAY;
-       disc->event = DISC_EV_NONE;
 
        return 0;
 }
This page took 0.036954 seconds and 5 git commands to generate.