[Open-FCoE] [RFC PATCH 3/5] libfc: lport maintains list of rports

Robert Love robert.w.love at intel.com
Thu Oct 2 18:25:57 UTC 2008


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

 drivers/scsi/libfc/fc_lport.c |   67 +++++++++++++++++++++++++++++++----------
 drivers/scsi/libfc/fc_rport.c |   34 ++++-----------------
 include/scsi/libfc/libfc.h    |    2 +
 3 files changed, 60 insertions(+), 43 deletions(-)

diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index a270b75..752291a 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -66,6 +66,31 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)
 }
 
 /**
+ * fc_lport_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_lport_lookup_rport(const struct fc_lport *lport, u32 port_id)
+{
+	struct fc_rport *rport, *found;
+	struct fc_rport_libfc_priv *rdata;
+	
+	found = NULL;	
+	
+	list_for_each_entry(rdata, &lport->rports, peers) {
+		rport = PRIV_TO_RPORT(rdata);
+		if (rport->port_id == port_id) {
+			found = rport;
+			get_device(&found->dev);
+			break;
+		}
+	}
+	return found;
+}
+
+
+
+/**
  * fc_lport_rport_event - Event handler for rport events
  * @lport: The lport which is receiving the event
  * @rport: The rport which the event has occured on
@@ -78,29 +103,35 @@ static void fc_lport_rport_event(struct fc_lport *lport,
 				 struct fc_rport *rport,
 				 enum fc_lport_event event)
 {
+	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+
 	if (fc_lport_debug)
 		FC_DBG("Received a %d event for port (%6x)\n", event,
 		       rport->port_id);
 
-	if (rport->port_id == FC_FID_DIR_SERV) {
-		mutex_lock(&lport->lp_mutex);
-		switch (event) {
-		case LPORT_EV_RPORT_CREATED:
-			if (rport) {
-				lport->dns_rp = rport;
-				fc_lport_enter_rpn_id(lport);
-			}
-			break;
-		case LPORT_EV_RPORT_LOGO:
-		case LPORT_EV_RPORT_FAILED:
+	mutex_lock(&lport->lp_mutex);
+	switch (event) {
+	case LPORT_EV_RPORT_CREATED:
+		if (rport->port_id == FC_FID_DIR_SERV) {
+			lport->dns_rp = rport;
+			fc_lport_enter_rpn_id(lport);
+		} else {
+			list_add_tail(&rdata->peers, &lport->rports);
+		}
+		break;
+	case LPORT_EV_RPORT_LOGO:
+	case LPORT_EV_RPORT_FAILED:
+		if (rport->port_id == FC_FID_DIR_SERV) {
 			lport->dns_rp = NULL;
 			fc_lport_enter_dns(lport);
-			break;
-		case LPORT_EV_RPORT_NONE:
-			break;
+		} else {
+			list_del(&rdata->peers);
 		}
-		mutex_unlock(&lport->lp_mutex);
+		break;
+	case LPORT_EV_RPORT_NONE:
+		break;
 	}
+	mutex_unlock(&lport->lp_mutex);
 }
 
 /**
@@ -733,7 +764,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
 			s_id = ntoh24(fh->fh_s_id);
 			d_id = ntoh24(fh->fh_d_id);
 
-			rport = lport->tt.rport_lookup(lport, s_id);
+			rport = fc_lport_lookup_rport(lport, s_id);
 			if (rport) {
 				lport->tt.rport_recv_req(sp, fp, rport);
 				put_device(&rport->dev); /* hold from lookup */
@@ -1436,6 +1467,7 @@ int fc_lport_config(struct fc_lport *lport)
 {
 	INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
 	mutex_init(&lport->lp_mutex);
+	INIT_LIST_HEAD(&lport->rports);
 
 	fc_lport_state_enter(lport, LPORT_ST_NONE);
 
@@ -1456,6 +1488,9 @@ int fc_lport_init(struct fc_lport *lport)
 	if (!lport->tt.lport_reset)
 		lport->tt.lport_reset = fc_lport_reset;
 
+	if (!lport->tt.rport_lookup)
+		lport->tt.rport_lookup = fc_lport_lookup_rport;
+
 	if (!lport->tt.event_callback)
 		lport->tt.event_callback = fc_lport_rport_event;
 
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 282e124..66a55c6 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -92,6 +92,12 @@ struct fc_rport *fc_rport_dummy_create(struct fc_disc_port *dp)
 	rdata->r_a_tov = dp->lp->r_a_tov;
 	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
 
+	/*
+	 * For good measure, but not necessary as we should only
+	 * add REAL rport to the lport list.
+	 */
+	INIT_LIST_HEAD(&rdata->peers);
+
 	return rport;
 }
 
@@ -116,30 +122,6 @@ static const char *fc_rport_state(struct fc_rport *rport)
 }
 
 /**
- * fc_rport_lookup - lookup a remote port by port_id
- * @lp: Fibre Channel host port instance
- * @fid: remote port port_id to match
- */
-struct fc_rport *fc_rport_lookup(const struct fc_lport *lp, u32 fid)
-{
-	struct Scsi_Host *shost = lp->host;
-	struct fc_rport *rport, *found;
-	unsigned long flags;
-
-	found = NULL;
-	spin_lock_irqsave(shost->host_lock, flags);
-	list_for_each_entry(rport, &fc_host_rports(shost), peers)
-		if (rport->port_id == fid &&
-		    rport->port_state == FC_PORTSTATE_ONLINE) {
-			found = rport;
-			get_device(&found->dev);
-			break;
-		}
-	spin_unlock_irqrestore(shost->host_lock, flags);
-	return found;
-}
-
-/**
  * fc_set_rport_loss_tmo - Set the remote port loss timeout in seconds.
  * @rport: Pointer to Fibre Channel remote port structure
  * @timeout: timeout in seconds
@@ -266,6 +248,7 @@ static void fc_rport_unlock(struct fc_rport *rport)
 			mutex_init(&new_rdata->rp_mutex);
 			INIT_DELAYED_WORK(&new_rdata->retry_work,
 					  fc_rport_timeout);
+			INIT_LIST_HEAD(&new_rdata->peers);
 
 			fc_rport_state_enter(new_rport, RPORT_ST_READY);
 			fc_remote_port_rolechg(new_rport, rdata->roles);
@@ -1329,9 +1312,6 @@ int fc_rport_init(struct fc_lport *lport)
 	if (!lport->tt.rport_recv_req)
 		lport->tt.rport_recv_req = fc_rport_recv_req;
 
-	if (!lport->tt.rport_lookup)
-		lport->tt.rport_lookup = fc_rport_lookup;
-
 	if (!lport->tt.rport_reset)
 		lport->tt.rport_reset = fc_rport_reset;
 
diff --git a/include/scsi/libfc/libfc.h b/include/scsi/libfc/libfc.h
index 67c1e15..13aacdd 100644
--- a/include/scsi/libfc/libfc.h
+++ b/include/scsi/libfc/libfc.h
@@ -167,6 +167,7 @@ struct fc_rport_libfc_priv {
 			       struct fc_rport *,
 			       enum fc_lport_event);
 	u32 roles;
+	struct list_head         peers;
 };
 
 #define PRIV_TO_RPORT(x)						\
@@ -430,6 +431,7 @@ struct fc_lport {
 	struct fc_rport		*dns_rp;
 	struct fc_rport		*ptp_rp;
 	void			*scsi_priv;
+	struct list_head         rports;
 
 	/* Operational Information */
 	struct libfc_function_template tt;




More information about the devel mailing list