[Open-FCoE] [PATCH 1/1] fc class: add rogue rport support

michaelc at cs.wisc.edu michaelc at cs.wisc.edu
Thu Sep 11 10:26:38 UTC 2008


From: Mike Christie <michaelc at cs.wisc.edu>

This is a first stab at removing the libfc dummy rport code
and private remote port code in other drivers. I am just sending the
fc class code to make sure I have the basic idea right.

JamesS had presented two possible solutions for how to deal
with rports that exist and how to resolve dd_data state:
http://www.open-fcoe.org/pipermail/devel/2008-July/000401.html

In one proposal we could have the LLD call some fc class
helpers to find existing rports by wwpn/wwnn. And the
alternative, is to try and make fc_remote_port_add figure
things out and call back into the LLD.

I went with the former, because some of the issues like how to handle
if the class finds a rport with a matching port_id that is not in the
blocked state gets complicated from a callback.

This patch was made over scsi-misc, becuase there are some patches
in there not in the fcoe tree. You can pull his tree into the fcoe
one and apply the patch.

Signed-off-by: Mike Christie <michaelc at cs.wisc.edu>
---
 drivers/scsi/scsi_transport_fc.c |  435 ++++++++++++++++++++++----------------
 include/scsi/scsi_transport_fc.h |   12 +-
 2 files changed, 263 insertions(+), 184 deletions(-)

diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index c276d11..a1311b2 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -144,6 +144,7 @@ static struct {
 	{ FC_PORTSTATE_ERROR,		"Error" },
 	{ FC_PORTSTATE_LOOPBACK,	"Loopback" },
 	{ FC_PORTSTATE_DELETED,		"Deleted" },
+	{ FC_PORTSTATE_ROGUE,		"Rogue" },
 };
 fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
 #define FC_PORTSTATE_MAX_NAMELEN	20
@@ -387,6 +388,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
 
 	INIT_LIST_HEAD(&fc_host->rports);
 	INIT_LIST_HEAD(&fc_host->rport_bindings);
+	INIT_LIST_HEAD(&fc_host->rogue_rports);
 	INIT_LIST_HEAD(&fc_host->vports);
 	fc_host->next_rport_number = 0;
 	fc_host->next_target_id = 0;
@@ -1518,7 +1520,7 @@ store_fc_private_host_tgtid_bind_type(struct device *dev,
 		while (!list_empty(&fc_host_rport_bindings(shost))) {
 			get_list_head_entry(rport,
 				&fc_host_rport_bindings(shost), peers);
-			list_del(&rport->peers);
+			list_del_init(&rport->peers);
 			rport->port_state = FC_PORTSTATE_DELETED;
 			fc_queue_work(shost, &rport->rport_delete_work);
 		}
@@ -2294,14 +2296,14 @@ fc_remove_host(struct Scsi_Host *shost)
 	/* Remove any remote ports */
 	list_for_each_entry_safe(rport, next_rport,
 			&fc_host->rports, peers) {
-		list_del(&rport->peers);
+		list_del_init(&rport->peers);
 		rport->port_state = FC_PORTSTATE_DELETED;
 		fc_queue_work(shost, &rport->rport_delete_work);
 	}
 
 	list_for_each_entry_safe(rport, next_rport,
 			&fc_host->rport_bindings, peers) {
-		list_del(&rport->peers);
+		list_del_init(&rport->peers);
 		rport->port_state = FC_PORTSTATE_DELETED;
 		fc_queue_work(shost, &rport->rport_delete_work);
 	}
@@ -2414,51 +2416,41 @@ fc_rport_final_delete(struct work_struct *work)
 	transport_remove_device(dev);
 	device_del(dev);
 	transport_destroy_device(dev);
-	put_device(&shost->shost_gendev);	/* for fc_host->rport list */
-	put_device(dev);			/* for self-reference */
+	fc_remote_port_free(rport);
 }
 
-
 /**
- * fc_rport_create - allocates and creates a remote FC port.
+ * fc_remote_port_alloc - allocates a remote FC port.
  * @shost:	scsi host the remote port is connected to.
  * @channel:	Channel on shost port connected to.
- * @ids:	The world wide names, fc address, and FC4 port
- *		roles for the remote port.
  *
- * Allocates and creates the remoter port structure, including the
- * class and sysfs creation.
+ * Allocates the remoter port structure. It has no binding
+ * and no sysfs representation at this time. It is just used to send
+ * discovery requests through.
  *
  * Notes:
  *	This routine assumes no locks are held on entry.
  */
-static struct fc_rport *
-fc_rport_create(struct Scsi_Host *shost, int channel,
-	struct fc_rport_identifiers  *ids)
+struct fc_rport *fc_remote_port_alloc(struct Scsi_Host *shost, int channel)
 {
 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 	struct fc_internal *fci = to_fc_internal(shost->transportt);
 	struct fc_rport *rport;
 	struct device *dev;
 	unsigned long flags;
-	int error;
-	size_t size;
 
-	size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size);
-	rport = kzalloc(size, GFP_KERNEL);
-	if (unlikely(!rport)) {
+	rport = kzalloc(sizeof(struct fc_rport) + fci->f->dd_fcrport_size,
+			GFP_KERNEL);
+	if (!rport) {
 		printk(KERN_ERR "%s: allocation failure\n", __func__);
 		return NULL;
 	}
 
 	rport->maxframe_size = -1;
 	rport->supported_classes = FC_COS_UNSPECIFIED;
+	rport->roles = FC_PORT_ROLE_UNKNOWN;
 	rport->dev_loss_tmo = fc_dev_loss_tmo;
-	memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
-	memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
-	rport->port_id = ids->port_id;
-	rport->roles = ids->roles;
-	rport->port_state = FC_PORTSTATE_ONLINE;
+	rport->port_state = FC_PORTSTATE_ROGUE;
 	if (fci->f->dd_fcrport_size)
 		rport->dd_data = &rport[1];
 	rport->channel = channel;
@@ -2470,59 +2462,181 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
 	INIT_WORK(&rport->stgt_delete_work, fc_starget_delete);
 	INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete);
 
+	dev = &rport->dev;
+	dev->parent = get_device(&shost->shost_gendev); /* parent reference */
+	dev->release = fc_rport_dev_release;
+	sprintf(dev->bus_id, "rport-%d:%d-%d",
+		shost->host_no, channel, rport->number);
+	device_initialize(dev);			/* takes self reference */
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	rport->number = fc_host->next_rport_number++;
+	list_add_tail(&rport->peers, &fc_host->rogue_rports);
+	get_device(&shost->shost_gendev); /* for fc_host->*rports list */
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	return rport;
+}
+EXPORT_SYMBOL_GPL(fc_remote_port_alloc);
+
+/**
+ * fc_remote_port_free - drop reference from allocation
+ * @rport:	remote port
+ *
+ * This should be called if the LLD has not called
+ * add on the rport and wishes to free the resources for the rogue port.
+ * For example if discovery failed, then the LLD should call this
+ * function to free the rport that was allocated.
+ */
+void fc_remote_port_free(struct fc_rport *rport)
+{
+	struct Scsi_Host *shost = rport_to_shost(rport);
+	unsigned long flags;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	if (!list_empty(&rport->peers))
+		list_del(&rport->peers);
+	/* for fc_host->rogue_rports list */
+	put_device(&rport->dev);
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	/* for self-reference */
+	put_device(&rport->dev);
+}
+EXPORT_SYMBOL_GPL(fc_remote_port_free);
+
+static struct fc_rport *
+rport_lookup(struct fc_host_attrs *fc_host, struct list_head *list, int channel,
+	     enum fc_tgtid_binding_type tgtid_bind_type,
+	     struct fc_rport_identifiers *ids)
+{
+	struct fc_rport *rport;
+
+	list_for_each_entry(rport, list, peers) {
+		if (rport->channel != channel)
+			continue;
+
+		switch (tgtid_bind_type) {
+		case FC_TGTID_BIND_BY_WWPN:
+		case FC_TGTID_BIND_NONE:
+			if (rport->port_name != ids->port_name)
+				continue;
+			break;
+		case FC_TGTID_BIND_BY_WWNN:
+			if (rport->node_name != ids->node_name)
+				continue;
+			break;
+		case FC_TGTID_BIND_BY_ID:
+			if (rport->port_id != ids->port_id)
+				continue;
+			break;
+		default:
+			continue;
+		}
+		get_device(&rport->dev);
+		return rport;
+	}
+	return NULL;
+}
+
+/**
+ * fc_remote_port_lookup - lookup a remote port by id
+ * @shost:		scsi host
+ * @channel:		channel
+ * @tgtid_bind_type:	bind type
+ * @id:			port id
+ *
+ * If a the port is found, it will be returned with a refcount on it.
+ * The caller must do a put_device on the rport when it is done.
+ * This function will check all rports lists, so the caller must
+ * check the rport port_state before processing.
+ *
+ * Caller must hold host lock.
+ */
+static struct fc_rport *
+__fc_remote_port_lookup(struct Scsi_Host *shost, int channel,
+			enum fc_tgtid_binding_type tgtid_bind_type,
+			struct fc_rport_identifiers *ids)
+{
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct fc_rport *rport;
+
+	rport = rport_lookup(fc_host, &fc_host->rports, channel,
+			     tgtid_bind_type, ids);
+	if (rport)
+		return rport;
+
+	rport = rport_lookup(fc_host, &fc_host->rport_bindings, channel,
+			     tgtid_bind_type, ids);
+	if (rport)
+		return rport;
+
+	return rport_lookup(fc_host, &fc_host->rogue_rports, channel,
+			    tgtid_bind_type, ids);
+}
+
+struct fc_rport *
+fc_remote_port_lookup(struct Scsi_Host *shost, int channel,
+		      enum fc_tgtid_binding_type tgtid_bind_type,
+		      struct fc_rport_identifiers *ids)
+{
+	struct fc_rport *rport;
+	unsigned long flags;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	rport = __fc_remote_port_lookup(shost, channel, tgtid_bind_type, ids);
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	return rport;
+}
+EXPORT_SYMBOL_GPL(fc_remote_port_lookup);
+
+static int remote_port_add(struct fc_rport *rport,
+			   struct fc_rport_identifiers *ids)
+{
+	struct Scsi_Host *shost = rport_to_shost(rport);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct device *dev;
+	unsigned long flags;
+	int error;
+
 	spin_lock_irqsave(shost->host_lock, flags);
+	memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
+	memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
+	rport->port_id = ids->port_id;
+	rport->roles = ids->roles;
 
 	rport->number = fc_host->next_rport_number++;
 	if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
 		rport->scsi_target_id = fc_host->next_target_id++;
 	else
 		rport->scsi_target_id = -1;
-	list_add_tail(&rport->peers, &fc_host->rports);
-	get_device(&shost->shost_gendev);	/* for fc_host->rport list */
-
+	list_move_tail(&rport->peers, &fc_host->rports);
 	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	dev = &rport->dev;
-	device_initialize(dev);			/* takes self reference */
-	dev->parent = get_device(&shost->shost_gendev); /* parent reference */
-	dev->release = fc_rport_dev_release;
-	sprintf(dev->bus_id, "rport-%d:%d-%d",
-		shost->host_no, channel, rport->number);
-	transport_setup_device(dev);
-
 	error = device_add(dev);
 	if (error) {
 		printk(KERN_ERR "FC Remote Port device_add failed\n");
-		goto delete_rport;
+		put_device(&shost->shost_gendev);
+		return error;
 	}
-	transport_add_device(dev);
-	transport_configure_device(dev);
+
+	transport_register_device(dev);
 
 	if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
 		/* initiate a scan of the target */
 		rport->flags |= FC_RPORT_SCAN_PENDING;
 		scsi_queue_work(shost, &rport->scan_work);
 	}
-
-	return rport;
-
-delete_rport:
-	transport_destroy_device(dev);
-	spin_lock_irqsave(shost->host_lock, flags);
-	list_del(&rport->peers);
-	put_device(&shost->shost_gendev);	/* for fc_host->rport list */
-	spin_unlock_irqrestore(shost->host_lock, flags);
-	put_device(dev->parent);
-	kfree(rport);
-	return NULL;
+	return 0;
 }
 
 /**
  * fc_remote_port_add - notify fc transport of the existence of a remote FC port.
- * @shost:	scsi host the remote port is connected to.
- * @channel:	Channel on shost port connected to.
- * @ids:	The world wide names, fc address, and FC4 port
- *		roles for the remote port.
+ * @shost:		scsi host the remote port is connected to.
+ * @rogue_rport:	optional rogue rport.
+ * @channel:		Channel on shost port connected to.
+ * @ids:		The world wide names, fc address, and FC4 port
+ *			roles for the remote port.
  *
  * The LLDD calls this routine to notify the transport of the existence
  * of a remote port. The LLDD provides the unique identifiers (wwpn,wwn)
@@ -2552,157 +2666,102 @@ delete_rport:
  *
  * Should not be called from interrupt context.
  *
+ * The caller should have resolved rogue with active or deleted
+ * rports before calling.
+ *
  * Notes:
  *	This routine assumes no locks are held on entry.
  */
 struct fc_rport *
 fc_remote_port_add(struct Scsi_Host *shost, int channel,
-	struct fc_rport_identifiers  *ids)
+		   struct fc_rport *rogue_rport,
+		   struct fc_rport_identifiers  *ids)
 {
 	struct fc_internal *fci = to_fc_internal(shost->transportt);
 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 	struct fc_rport *rport;
 	unsigned long flags;
-	int match = 0;
 
 	/* ensure any stgt delete functions are done */
 	fc_flush_work(shost);
 
-	/*
-	 * Search the list of "active" rports, for an rport that has been
-	 * deleted, but we've held off the real delete while the target
-	 * is in a "blocked" state.
-	 */
 	spin_lock_irqsave(shost->host_lock, flags);
+	rport = __fc_remote_port_lookup(shost, channel,
+					fc_host->tgtid_bind_type, ids);
+	if (rport) {
+		switch (rport->port_state) {
+		/*
+		 * Found rport on the list of "active" rports that has been
+		 * deleted, but we've held off the real delete while the target
+		 * is in a "blocked" state.
+		 */
+		case FC_PORTSTATE_BLOCKED:
+			memcpy(&rport->node_name, &ids->node_name,
+				sizeof(rport->node_name));
+			memcpy(&rport->port_name, &ids->port_name,
+				sizeof(rport->port_name));
+			rport->port_id = ids->port_id;
 
-	list_for_each_entry(rport, &fc_host->rports, peers) {
-
-		if ((rport->port_state == FC_PORTSTATE_BLOCKED) &&
-			(rport->channel == channel)) {
-
-			switch (fc_host->tgtid_bind_type) {
-			case FC_TGTID_BIND_BY_WWPN:
-			case FC_TGTID_BIND_NONE:
-				if (rport->port_name == ids->port_name)
-					match = 1;
-				break;
-			case FC_TGTID_BIND_BY_WWNN:
-				if (rport->node_name == ids->node_name)
-					match = 1;
-				break;
-			case FC_TGTID_BIND_BY_ID:
-				if (rport->port_id == ids->port_id)
-					match = 1;
-				break;
-			}
-
-			if (match) {
-
-				memcpy(&rport->node_name, &ids->node_name,
-					sizeof(rport->node_name));
-				memcpy(&rport->port_name, &ids->port_name,
-					sizeof(rport->port_name));
-				rport->port_id = ids->port_id;
-
-				rport->port_state = FC_PORTSTATE_ONLINE;
-				rport->roles = ids->roles;
-
-				spin_unlock_irqrestore(shost->host_lock, flags);
-
-				if (fci->f->dd_fcrport_size)
-					memset(rport->dd_data, 0,
-						fci->f->dd_fcrport_size);
+			rport->port_state = FC_PORTSTATE_ONLINE;
+			rport->roles = ids->roles;
 
-				/*
-				 * If we were not a target, cancel the
-				 * io terminate and rport timers, and
-				 * we're done.
-				 *
-				 * If we were a target, but our new role
-				 * doesn't indicate a target, leave the
-				 * timers running expecting the role to
-				 * change as the target fully logs in. If
-				 * it doesn't, the target will be torn down.
-				 *
-				 * If we were a target, and our role shows
-				 * we're still a target, cancel the timers
-				 * and kick off a scan.
-				 */
-
-				/* was a target, not in roles */
-				if ((rport->scsi_target_id != -1) &&
-				    (!(ids->roles & FC_PORT_ROLE_FCP_TARGET)))
-					return rport;
-
-				/*
-				 * Stop the fail io and dev_loss timers.
-				 * If they flush, the port_state will
-				 * be checked and will NOOP the function.
-				 */
-				if (!cancel_delayed_work(&rport->fail_io_work))
-					fc_flush_devloss(shost);
-				if (!cancel_delayed_work(&rport->dev_loss_work))
-					fc_flush_devloss(shost);
-
-				spin_lock_irqsave(shost->host_lock, flags);
-
-				rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
-						  FC_RPORT_DEVLOSS_PENDING);
-
-				/* if target, initiate a scan */
-				if (rport->scsi_target_id != -1) {
-					rport->flags |= FC_RPORT_SCAN_PENDING;
-					scsi_queue_work(shost,
-							&rport->scan_work);
-					spin_unlock_irqrestore(shost->host_lock,
-							flags);
-					scsi_target_unblock(&rport->dev);
-				} else
-					spin_unlock_irqrestore(shost->host_lock,
-							flags);
+			spin_unlock_irqrestore(shost->host_lock, flags);
 
+			if (fci->f->dd_fcrport_size)
+				memset(rport->dd_data, 0,
+					fci->f->dd_fcrport_size);
+
+			/*
+			 * If we were not a target, cancel the
+			 * io terminate and rport timers, and
+			 * we're done.
+			 *
+			 * If we were a target, but our new role
+			 * doesn't indicate a target, leave the
+			 * timers running expecting the role to
+			 * change as the target fully logs in. If
+			 * it doesn't, the target will be torn down.
+			 *
+			 * If we were a target, and our role shows
+			 * we're still a target, cancel the timers
+			 * and kick off a scan.
+			 */
+
+			/* was a target, not in roles */
+			if ((rport->scsi_target_id != -1) &&
+			    (!(ids->roles & FC_PORT_ROLE_FCP_TARGET)))
 				return rport;
-			}
-		}
-	}
 
-	/*
-	 * Search the bindings array
-	 * Note: if never a FCP target, you won't be on this list
-	 */
-	if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) {
+			/*
+			 * Stop the fail io and dev_loss timers.
+			 * If they flush, the port_state will
+			 * be checked and will NOOP the function.
+			 */
+			if (!cancel_delayed_work(&rport->fail_io_work))
+				fc_flush_devloss(shost);
+			if (!cancel_delayed_work(&rport->dev_loss_work))
+				fc_flush_devloss(shost);
 
-		/* search for a matching consistent binding */
+			spin_lock_irqsave(shost->host_lock, flags);
 
-		list_for_each_entry(rport, &fc_host->rport_bindings,
-					peers) {
-			if (rport->channel != channel)
-				continue;
+			rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
+					  FC_RPORT_DEVLOSS_PENDING);
 
-			switch (fc_host->tgtid_bind_type) {
-			case FC_TGTID_BIND_BY_WWPN:
-				if (rport->port_name == ids->port_name)
-					match = 1;
-				break;
-			case FC_TGTID_BIND_BY_WWNN:
-				if (rport->node_name == ids->node_name)
-					match = 1;
-				break;
-			case FC_TGTID_BIND_BY_ID:
-				if (rport->port_id == ids->port_id)
-					match = 1;
-				break;
-			case FC_TGTID_BIND_NONE: /* to keep compiler happy */
-				break;
-			}
+			/* if target, initiate a scan */
+			if (rport->scsi_target_id != -1) {
+				rport->flags |= FC_RPORT_SCAN_PENDING;
+				scsi_queue_work(shost, &rport->scan_work);
+				spin_unlock_irqrestore(shost->host_lock, flags);
+				scsi_target_unblock(&rport->dev);
+			} else
+				spin_unlock_irqrestore(shost->host_lock, flags);
 
-			if (match) {
-				list_move_tail(&rport->peers, &fc_host->rports);
+			return rport;
+		/* must have been on rport_bindings */
+		case FC_PORTSTATE_NOTPRESENT:
+			if (fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE)
 				break;
-			}
-		}
 
-		if (match) {
 			memcpy(&rport->node_name, &ids->node_name,
 				sizeof(rport->node_name));
 			memcpy(&rport->port_name, &ids->port_name,
@@ -2726,13 +2785,26 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
 				spin_unlock_irqrestore(shost->host_lock, flags);
 
 			return rport;
+		/* new rport */
+		default:
+			break;
 		}
 	}
-
 	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	/* No consistent binding found - create new remote port entry */
-	rport = fc_rport_create(shost, channel, ids);
+	if (rogue_rport)
+		rport = rogue_rport;
+	else {
+		rport = fc_remote_port_alloc(shost, channel);
+		if (!rport)
+			return NULL;
+	}
+
+	if (remote_port_add(rport, ids)) {
+		fc_remote_port_free(rport);
+		return NULL;
+	}
 
 	return rport;
 }
@@ -2980,7 +3052,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
 
 	if ((fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) ||
 	    (rport->scsi_target_id == -1)) {
-		list_del(&rport->peers);
+		list_del_init(&rport->peers);
 		rport->port_state = FC_PORTSTATE_DELETED;
 		dev_printk(KERN_ERR, &rport->dev,
 			"blocked FC remote port time out: removing"
@@ -3167,7 +3239,6 @@ fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,
 		goto delete_vport;
 	}
 	transport_add_device(dev);
-	transport_configure_device(dev);
 
 	error = fci->f->vport_create(vport, ids->disable);
 	if (error) {
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 49d8913..4d9a655 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -82,6 +82,7 @@ enum fc_port_state {
 	FC_PORTSTATE_ERROR,
 	FC_PORTSTATE_LOOPBACK,
 	FC_PORTSTATE_DELETED,
+	FC_PORTSTATE_ROGUE,
 };
 
 
@@ -502,6 +503,7 @@ struct fc_host_attrs {
 	/* internal data */
 	struct list_head rports;
 	struct list_head rport_bindings;
+	struct list_head rogue_rports;
 	struct list_head vports;
 	u32 next_rport_number;
 	u32 next_target_id;
@@ -741,8 +743,14 @@ struct scsi_transport_template *fc_attach_transport(
 			struct fc_function_template *);
 void fc_release_transport(struct scsi_transport_template *);
 void fc_remove_host(struct Scsi_Host *);
-struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost,
-			int channel, struct fc_rport_identifiers  *ids);
+struct fc_rport *fc_remote_port_lookup(struct Scsi_Host *shost, int channel,
+				enum fc_tgtid_binding_type tgtid_bind_type,
+				struct fc_rport_identifiers *ids);
+struct fc_rport *fc_remote_port_alloc(struct Scsi_Host *shost, int channel);
+void fc_remote_port_free(struct fc_rport *rport);
+struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost, int channel,
+			struct fc_rport *rogue_rport,
+			struct fc_rport_identifiers  *ids);
 void fc_remote_port_delete(struct fc_rport  *rport);
 void fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles);
 int scsi_is_fc_rport(const struct device *);
-- 
1.5.5.1




More information about the devel mailing list