All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc
@ 2009-08-25 20:58 Robert Love
  2009-08-25 20:58 ` [PATCH 01/64] fcoe: Add format spacing to FCOE_NETDEV_DBG debug macro Robert Love
                   ` (63 more replies)
  0 siblings, 64 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:58 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi

These patches are targeting the 2.6.32 merge window.

There are three main focuses in this patch series. First,
there are contributions that modify the stack for VLANs
and prepare for NPIV. For both of those technologies resources
need to be shared between VLANs on a physical port or
VN_Ports on an N_Port. Second, there are improvements to
the discovery and remote port layers. Discovery is now much
more graceful (ADISC) and there is a cleaner division between
fc_rports that are used by the FC transport and libfc's
internal remote port tracking structures. Third, there is
a performance optomization for the exchange manager where
per-CPU exchange ID (XID) pools are created so that each CPU
is not contending for a shared lock when trying to acquire a
new XID.

Other than these primary changes there are other smaller
contributions. A user-tunable DDP limit has been added.
There are various improvements to the debug logging macros
and uses of them. FC headers are exported for user space
tools. The fcoe create/destroy path has been improved.

---

Chris Leech (15):
      fcoe: use rtnl mutex in place of hostlist lock
      fcoe: Fix module ref count bug by adding NETDEV UNREGISTER handling
      fcoe: move the host-list add/remove to keep out VN_Ports
      fcoe: add mutex to protect create and destroy
      fcoe: split out per interface setup
      fcoe: fcoe_interface create, destroy and refcounting
      fcoe: remove fcoe_interface->priv pointer
      fcoe: move offload exchange manager pointer from fcoe_port to fcoe_interface
      fcoe: move FIP controller from fcoe_port to fcoe_interface
      fcoe: move packet handlers from fcoe_port to fcoe_interface
      fcoe: move netdev to fcoe_interface
      fcoe: Introduce and allocate fcoe_interface structure, 1:1 with net_device
      fcoe: interface changes to fcoe_if_create and fcoe_if_destroy
      fcoe: fix missing error check in call to fcoe_if_init
      libfcoe: fcoe_ctlr_destroy use cancel_work_sync instead of flush_work

Joe Eykholt (41):
      fcoe: flush per-cpu thread work when destroying interface
      libfc: don't swap OX_ID and RX_ID when sending BA_RJT
      libfc: send GPN_ID in reaction to single-port RSCNs.
      libfc: fix handling of incoming Discover Address (ADISC) requests
      libfc: use ADISC to verify rport login state
      libfc: LOGO response code had extraeous enter_rtv
      libfc: re-login to remote ports that send us LOGO
      libfc: fix rport error handling for login-required and invalid ops
      libfc: correctly handle incoming PLOGI request.
      libfc: improve debug messages for ELS response handlers
      libfc: fix: rport_recv_req needs disc_mutex when calling rport_lookup
      libfc: move remote port lookup for ELS requests into fc_rport.c.
      libfc: don't do discovery before callback is set
      libfc: clean up point-to-point discovery code.
      libfc: discovery gpn_ft parse bug
      libfc: discovery retry should clear pending first.
      libfc: fix: empty zone causes endless discovery retries.
      libfc: handle discovery failure more correctly.
      libfc: rearrange code in fc_disc_gpn_ft_resp()
      libfc: discovery restart sequence error fix
      libfc: do not log off rports before or after discovery
      libfc: move rport_lookup into fc_rport.c
      libfc: change to make remote port callback optional
      libfc: have rport_create do a lookup for pre-existing rports first
      libfc: make rport module maintain the rport list
      libfc: simplify fc_lport_rport_callback
      libfc: rport debug messages were printing pointer values
      libfc: remove unused disc->delay element
      libfc: eliminate disc->event
      libfc: fix rport event race between READY and LOGO
      libfc: don't create dummy (rogue) remote ports
      libfc: rename rport event CREATED to READY
      libfc: rearrange code in fc_rport_work
      libfc: make rport structure optional
      libfc: change elsct to use FC_ID instead of rdata
      libfc: make fc_rport_priv the primary rport interface.
      libfc: fix RPORT_TO_PRIV and PRIV_TO_RPORT() macros.
      libfc: change interface for rport_create
      libfc: prepare to split off struct fc_rport_priv from fc_rport_libfc_priv
      fcoe: remove unnecessary list and lock initializations.
      fcoe: libfcoe: extra semicolon in CHECK_LOGGING macros causes compile error

Robert Love (5):
      libfc: Always reset remote port roles when receiving PRLI
      libfc: Initialize fc_rport_identifiers inside fc_rport_create
      libfc: Export FC headers
      libfc: Fix misleading debug statement
      fcoe: Add format spacing to FCOE_NETDEV_DBG debug macro

Vasu Dev (2):
      fcoe, libfc: fully makes use of per cpu exch pool and then removes em_lock
      fcoe, libfc: adds per cpu exch pool within exchange manager(EM)

Yi Zou (1):
      fcoe: Add sysfs parameter to fcoe for minimum DDP read I/O size


 drivers/scsi/fcoe/fcoe.c      |  948 ++++++++++++++++++++----------------
 drivers/scsi/fcoe/fcoe.h      |   32 +
 drivers/scsi/fcoe/libfcoe.c   |   10 
 drivers/scsi/libfc/fc_disc.c  |  523 ++++++++------------
 drivers/scsi/libfc/fc_elsct.c |   49 ++
 drivers/scsi/libfc/fc_exch.c  |  286 +++++++----
 drivers/scsi/libfc/fc_fcp.c   |    2 
 drivers/scsi/libfc/fc_lport.c |  222 ++------
 drivers/scsi/libfc/fc_rport.c | 1091 +++++++++++++++++++++++++----------------
 include/scsi/Kbuild           |    1 
 include/scsi/fc/Kbuild        |    4 
 include/scsi/fc/fc_gs.h       |    1 
 include/scsi/fc_encode.h      |   60 ++
 include/scsi/libfc.h          |  122 +++--
 14 files changed, 1824 insertions(+), 1527 deletions(-)
 create mode 100644 include/scsi/fc/Kbuild

-- 
//Rob

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 01/64] fcoe: Add format spacing to FCOE_NETDEV_DBG debug macro
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
@ 2009-08-25 20:58 ` Robert Love
  2009-08-25 20:58 ` [PATCH 02/64] libfc: Fix misleading debug statement Robert Love
                   ` (62 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:58 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Robert Love

There's currently no space between the interface name and the
user specified format/string. This patch adds a space and a colon
to the output to separate the interface name and the user
specified string.

So, instead of "ethXfoo" it will read "ethX: foo".

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

 drivers/scsi/fcoe/fcoe.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 5ae8ca7..68b9f85 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -61,7 +61,7 @@ do {                                                            	\
 
 #define FCOE_NETDEV_DBG(netdev, fmt, args...)			\
 	FCOE_CHECK_LOGGING(FCOE_NETDEV_LOGGING,			\
-			   printk(KERN_INFO "fcoe: %s" fmt,	\
+			   printk(KERN_INFO "fcoe: %s: " fmt,	\
 				  netdev->name, ##args);)
 
 /*


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 02/64] libfc: Fix misleading debug statement
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
  2009-08-25 20:58 ` [PATCH 01/64] fcoe: Add format spacing to FCOE_NETDEV_DBG debug macro Robert Love
@ 2009-08-25 20:58 ` Robert Love
  2009-08-25 20:58 ` [PATCH 03/64] fcoe: libfcoe: extra semicolon in CHECK_LOGGING macros causes compile error Robert Love
                   ` (61 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:58 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Robert Love

The statement reads, "Exchange timed out, notifying the upper layer",
however, this statement is printed whenever the timer is armed. This
is confusing to someone debugging the code because every time an
exchange is initialized, there is an incorrect statement stating that
the timer has already timed out. This patch changes the statement to
read, "Exchange timer armed" which is more accurate.

This patch also adds a debug statement in the timeout handler to
properly indicate that the exchange has timed out.

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

 drivers/scsi/libfc/fc_exch.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 11ddd11..40c3427 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -326,7 +326,7 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep,
 	if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
 		return;
 
-	FC_EXCH_DBG(ep, "Exchange timed out, notifying the upper layer\n");
+	FC_EXCH_DBG(ep, "Exchange timer armed\n");
 
 	if (schedule_delayed_work(&ep->timeout_work,
 				  msecs_to_jiffies(timer_msec)))
@@ -412,6 +412,8 @@ static void fc_exch_timeout(struct work_struct *work)
 	u32 e_stat;
 	int rc = 1;
 
+	FC_EXCH_DBG(ep, "Exchange timed out\n");
+
 	spin_lock_bh(&ep->ex_lock);
 	if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
 		goto unlock;


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 03/64] fcoe: libfcoe: extra semicolon in CHECK_LOGGING macros causes compile error
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
  2009-08-25 20:58 ` [PATCH 01/64] fcoe: Add format spacing to FCOE_NETDEV_DBG debug macro Robert Love
  2009-08-25 20:58 ` [PATCH 02/64] libfc: Fix misleading debug statement Robert Love
@ 2009-08-25 20:58 ` Robert Love
  2009-08-25 20:58 ` [PATCH 04/64] fcoe, libfc: adds per cpu exch pool within exchange manager(EM) Robert Love
                   ` (60 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:58 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

If using code like this:
	if (foo)
		FCOE_DBG("foo\n);
	else
		FCOE_DBG("bar\n");

one gets compile errors because FCOE_DBG expands with its own semicolon,
making one too many for the if-statement.

Remove the offending semicolon in fcoe.h and also a similar case
in libfcoe.c.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.h    |    2 +-
 drivers/scsi/fcoe/libfcoe.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 68b9f85..65120e2 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -53,7 +53,7 @@ do {                                                            	\
 		do {							\
 			CMD;						\
 		} while (0);						\
-} while (0);
+} while (0)
 
 #define FCOE_DBG(fmt, args...)						\
 	FCOE_CHECK_LOGGING(FCOE_LOGGING,				\
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 4db719d..d0b5208 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -69,7 +69,7 @@ do {                                                            	\
 		do {							\
 			CMD;						\
 		} while (0);						\
-} while (0);
+} while (0)
 
 #define LIBFCOE_DBG(fmt, args...)					\
 	LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING,				\


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 04/64] fcoe, libfc: adds per cpu exch pool within exchange manager(EM)
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (2 preceding siblings ...)
  2009-08-25 20:58 ` [PATCH 03/64] fcoe: libfcoe: extra semicolon in CHECK_LOGGING macros causes compile error Robert Love
@ 2009-08-25 20:58 ` Robert Love
  2009-08-25 20:58 ` [PATCH 05/64] fcoe, libfc: fully makes use of per cpu exch pool and then removes em_lock Robert Love
                   ` (59 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:58 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Vasu Dev, Robert Love

From: Vasu Dev <vasu.dev@intel.com>

Adds per cpu exch pool for these reasons:-

 1. Currently an EM instance is shared across all cpus to manage
    all exches for all cpus. This required em_lock across all
    cpus for an exch alloc, free, lookup and reset each frame
    and that made em_lock expensive, so instead having per cpu
    exch pool with their own per cpu pool lock will likely reduce
    locking contention in fast path for an exch alloc, free and
    lookup.

 2. Per cpu exch pool will likely improve cache hit ratio since
    all frames of an exch will be processed on the same cpu on
    which exch originated.

This patch is only prep work to help in keeping complexity of next
patch low, so this patch only sets up per cpu exch pool and related
helper funcs to be used by next patch. The next patch fully makes
use of per cpu exch pool in all code paths ie. tx, rx and reset.

Divides per EM exch id range equally across all cpus to setup per
cpu exch pool. This division is such that lower bits of exch id
carries cpu number info on which exch originated, later a simple
bitwise AND operation on exch id of incoming frame with fc_cpu_mask
retrieves cpu number info to direct all frames to same cpu on which
exch originated. This required a global fc_cpu_mask and fc_cpu_order
initialized to max possible cpus number nr_cpu_ids rounded up to 2's
power, this will be used in mapping exch id and exch ptr array
index in pool during exch allocation, find or reset code paths.

Adds a check in fc_exch_mgr_alloc() to ensure specified min_xid
lower bits are zero since these bits are used to carry cpu info.

Adds and initializes struct fc_exch_pool with all required fields
to manage exches in pool.

Allocates per cpu struct fc_exch_pool with memory for exches array
for range of exches per pool. The exches array memory is followed
by struct fc_exch_pool.

Adds fc_exch_ptr_get/set() helper functions to get/set exch ptr in
pool exches array at specified array index.

Increases default FCOE_MAX_XID to 0x0FFF from 0x07EF, so that more
exches are available per cpu after above described exch id range
division across all cpus to each pool.

Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.h     |    2 -
 drivers/scsi/libfc/fc_exch.c |   89 +++++++++++++++++++++++++++++++++++++++++-
 include/scsi/libfc.h         |    1 
 3 files changed, 88 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 65120e2..550d1e4 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -38,7 +38,7 @@
 #define FCOE_MAX_OUTSTANDING_COMMANDS	1024
 
 #define FCOE_MIN_XID		0x0000	/* the min xid supported by fcoe_sw */
-#define FCOE_MAX_XID		0x07ef	/* the max xid supported by fcoe_sw */
+#define FCOE_MAX_XID		0x0FFF	/* the max xid supported by fcoe_sw */
 
 unsigned int fcoe_debug_logging;
 module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 40c3427..9cbe8d6 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -32,6 +32,9 @@
 #include <scsi/libfc.h>
 #include <scsi/fc_encode.h>
 
+u16	fc_cpu_mask;		/* cpu mask for possible cpus */
+EXPORT_SYMBOL(fc_cpu_mask);
+static u16	fc_cpu_order;	/* 2's power to represent total possible cpus */
 static struct kmem_cache *fc_em_cachep;        /* cache for exchanges */
 
 /*
@@ -48,6 +51,20 @@ static struct kmem_cache *fc_em_cachep;        /* cache for exchanges */
  */
 
 /*
+ * Per cpu exchange pool
+ *
+ * This structure manages per cpu exchanges in array of exchange pointers.
+ * This array is allocated followed by struct fc_exch_pool memory for
+ * assigned range of exchanges to per cpu pool.
+ */
+struct fc_exch_pool {
+	u16		next_index;	/* next possible free exchange index */
+	u16		total_exches;	/* total allocated exchanges */
+	spinlock_t	lock;		/* exch pool lock */
+	struct list_head	ex_list;	/* allocated exchanges list */
+};
+
+/*
  * Exchange manager.
  *
  * This structure is the center for creating exchanges and sequences.
@@ -66,6 +83,8 @@ struct fc_exch_mgr {
 	u32	total_exches;		/* total allocated exchanges */
 	struct list_head	ex_list;	/* allocated exchanges list */
 	mempool_t	*ep_pool;	/* reserve ep's */
+	u16		pool_max_index;	/* max exch array index in exch pool */
+	struct fc_exch_pool *pool;	/* per cpu exch pool */
 
 	/*
 	 * currently exchange mgr stats are updated but not used.
@@ -303,6 +322,19 @@ static int fc_exch_done_locked(struct fc_exch *ep)
 	return rc;
 }
 
+static inline struct fc_exch *fc_exch_ptr_get(struct fc_exch_pool *pool,
+					      u16 index)
+{
+	struct fc_exch **exches = (struct fc_exch **)(pool + 1);
+	return exches[index];
+}
+
+static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index,
+				   struct fc_exch *ep)
+{
+	((struct fc_exch **)(pool + 1))[index] = ep;
+}
+
 static void fc_exch_mgr_delete_ep(struct fc_exch *ep)
 {
 	struct fc_exch_mgr *mp;
@@ -1751,6 +1783,7 @@ static void fc_exch_mgr_destroy(struct kref *kref)
 	 */
 	WARN_ON(mp->total_exches != 0);
 	mempool_destroy(mp->ep_pool);
+	free_percpu(mp->pool);
 	kfree(mp);
 }
 
@@ -1770,8 +1803,13 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
 {
 	struct fc_exch_mgr *mp;
 	size_t len;
+	u16 pool_exch_range;
+	size_t pool_size;
+	unsigned int cpu;
+	struct fc_exch_pool *pool;
 
-	if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN) {
+	if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN ||
+	    (min_xid & fc_cpu_mask) != 0) {
 		FC_LPORT_DBG(lp, "Invalid min_xid 0x:%x and max_xid 0x:%x\n",
 			     min_xid, max_xid);
 		return NULL;
@@ -1802,10 +1840,31 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
 	if (!mp->ep_pool)
 		goto free_mp;
 
+	/*
+	 * Setup per cpu exch pool with entire exchange id range equally
+	 * divided across all cpus. The exch pointers array memory is
+	 * allocated for exch range per pool.
+	 */
+	pool_exch_range = (mp->max_xid - mp->min_xid + 1) / (fc_cpu_mask + 1);
+	mp->pool_max_index = pool_exch_range - 1;
+
+	/*
+	 * Allocate and initialize per cpu exch pool
+	 */
+	pool_size = sizeof(*pool) + pool_exch_range * sizeof(struct fc_exch *);
+	mp->pool = __alloc_percpu(pool_size, __alignof__(struct fc_exch_pool));
+	if (!mp->pool)
+		goto free_mempool;
+	for_each_possible_cpu(cpu) {
+		pool = per_cpu_ptr(mp->pool, cpu);
+		spin_lock_init(&pool->lock);
+		INIT_LIST_HEAD(&pool->ex_list);
+	}
+
 	kref_init(&mp->kref);
 	if (!fc_exch_mgr_add(lp, mp, match)) {
-		mempool_destroy(mp->ep_pool);
-		goto free_mp;
+		free_percpu(mp->pool);
+		goto free_mempool;
 	}
 
 	/*
@@ -1816,6 +1875,8 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
 	kref_put(&mp->kref, fc_exch_mgr_destroy);
 	return mp;
 
+free_mempool:
+	mempool_destroy(mp->ep_pool);
 free_mp:
 	kfree(mp);
 	return NULL;
@@ -1975,6 +2036,28 @@ int fc_exch_init(struct fc_lport *lp)
 	if (!lp->tt.seq_exch_abort)
 		lp->tt.seq_exch_abort = fc_seq_exch_abort;
 
+	/*
+	 * Initialize fc_cpu_mask and fc_cpu_order. The
+	 * fc_cpu_mask is set for nr_cpu_ids rounded up
+	 * to order of 2's * power and order is stored
+	 * in fc_cpu_order as this is later required in
+	 * mapping between an exch id and exch array index
+	 * in per cpu exch pool.
+	 *
+	 * This round up is required to align fc_cpu_mask
+	 * to exchange id's lower bits such that all incoming
+	 * frames of an exchange gets delivered to the same
+	 * cpu on which exchange originated by simple bitwise
+	 * AND operation between fc_cpu_mask and exchange id.
+	 */
+	fc_cpu_mask = 1;
+	fc_cpu_order = 0;
+	while (fc_cpu_mask < nr_cpu_ids) {
+		fc_cpu_mask <<= 1;
+		fc_cpu_order++;
+	}
+	fc_cpu_mask--;
+
 	return 0;
 }
 EXPORT_SYMBOL(fc_exch_init);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index c2b928c..3206338 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -343,6 +343,7 @@ static inline bool fc_fcp_is_read(const struct fc_fcp_pkt *fsp)
 
 struct fc_exch_mgr;
 struct fc_exch_mgr_anchor;
+extern u16	fc_cpu_mask;	/* cpu mask for possible cpus */
 
 /*
  * Sequence.


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 05/64] fcoe, libfc: fully makes use of per cpu exch pool and then removes em_lock
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (3 preceding siblings ...)
  2009-08-25 20:58 ` [PATCH 04/64] fcoe, libfc: adds per cpu exch pool within exchange manager(EM) Robert Love
@ 2009-08-25 20:58 ` Robert Love
  2009-08-25 20:58 ` [PATCH 06/64] libfc: Export FC headers Robert Love
                   ` (58 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:58 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Vasu Dev, Robert Love

From: Vasu Dev <vasu.dev@intel.com>

1. Updates fcoe_rcv() to queue incoming frames to the fcoe per
   cpu thread on which this frame's exch was originated and simply
   use current cpu for request exch not originated by initiator.
   It is redundant to add this code under CONFIG_SMP, so removes
   CONFIG_SMP uses around this code.

2. Updates fc_exch_em_alloc, fc_exch_delete, fc_exch_find to use
   per cpu exch pools, here fc_exch_delete is rename of older
   fc_exch_mgr_delete_ep since ep/exch are now deleted in pools
   of EM and so brief new name is sufficient and better name.

   Updates these functions to map exch id to their index into exch
   pool using fc_cpu_mask, fc_cpu_order and EM min_xid.
   This mapping is as per detailed explanation about this in
   last patch and basically this is just as lower fc_cpu_mask
   bits of exch id as cpu number and upper bit sum of EM min_xid
   and exch index in pool.

   Uses pool next_index to keep track of exch allocation from
   pool along with pool_max_index as upper bound of exches array
   in pool.

3. Adds exch pool ptr to fc_exch to free exch to its pool in
   fc_exch_delete.

4. Updates fc_exch_mgr_reset to reset all exch pools of an EM,
   this required adding fc_exch_pool_reset func to reset exches
   in pool and then have fc_exch_mgr_reset call fc_exch_pool_reset
   for each pool within each EM for a lport.

5. Removes no longer needed exches array, em_lock, next_xid, and
   total_exches from struct fc_exch_mgr, these are not needed after
   use of per cpu exch pool, also removes not used max_read,
   last_read from struct fc_exch_mgr.

6. Updates locking notes for exch pool lock with fc_exch lock and
   uses pool lock in exch allocation, lookup and reset.

Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c     |   19 ++--
 drivers/scsi/libfc/fc_exch.c |  189 ++++++++++++++++++++++--------------------
 include/scsi/libfc.h         |    9 +-
 3 files changed, 115 insertions(+), 102 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 757aa28..e32a0ed 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -912,8 +912,7 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
 	struct fcoe_softc *fc;
 	struct fc_frame_header *fh;
 	struct fcoe_percpu_s *fps;
-	unsigned short oxid;
-	unsigned int cpu = 0;
+	unsigned int cpu;
 
 	fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type);
 	lp = fc->ctlr.lp;
@@ -947,20 +946,20 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
 	skb_set_transport_header(skb, sizeof(struct fcoe_hdr));
 	fh = (struct fc_frame_header *) skb_transport_header(skb);
 
-	oxid = ntohs(fh->fh_ox_id);
-
 	fr = fcoe_dev_from_skb(skb);
 	fr->fr_dev = lp;
 	fr->ptype = ptype;
 
-#ifdef CONFIG_SMP
 	/*
-	 * The incoming frame exchange id(oxid) is ANDed with num of online
-	 * cpu bits to get cpu and then this cpu is used for selecting
-	 * a per cpu kernel thread from fcoe_percpu.
+	 * In case the incoming frame's exchange is originated from
+	 * the initiator, then received frame's exchange id is ANDed
+	 * with fc_cpu_mask bits to get the same cpu on which exchange
+	 * was originated, otherwise just use the current cpu.
 	 */
-	cpu = oxid & (num_online_cpus() - 1);
-#endif
+	if (ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)
+		cpu = ntohs(fh->fh_ox_id) & fc_cpu_mask;
+	else
+		cpu = smp_processor_id();
 
 	fps = &per_cpu(fcoe_percpu, cpu);
 	spin_lock_bh(&fps->fcoe_rx_list.lock);
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 9cbe8d6..b51db15 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -73,14 +73,8 @@ struct fc_exch_pool {
 struct fc_exch_mgr {
 	enum fc_class	class;		/* default class for sequences */
 	struct kref	kref;		/* exchange mgr reference count */
-	spinlock_t	em_lock;	/* exchange manager lock,
-					   must be taken before ex_lock */
-	u16		next_xid;	/* next possible free exchange ID */
 	u16		min_xid;	/* min exchange ID */
 	u16		max_xid;	/* max exchange ID */
-	u16		max_read;	/* max exchange ID for read */
-	u16		last_read;	/* last xid allocated for read */
-	u32	total_exches;		/* total allocated exchanges */
 	struct list_head	ex_list;	/* allocated exchanges list */
 	mempool_t	*ep_pool;	/* reserve ep's */
 	u16		pool_max_index;	/* max exch array index in exch pool */
@@ -99,7 +93,6 @@ struct fc_exch_mgr {
 		atomic_t seq_not_found;
 		atomic_t non_bls_resp;
 	} stats;
-	struct fc_exch **exches;	/* for exch pointers indexed by xid */
 };
 #define	fc_seq_exch(sp) container_of(sp, struct fc_exch, seq)
 
@@ -192,8 +185,8 @@ static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp);
  * sequence allocation and deallocation must be locked.
  *  - exchange refcnt can be done atomicly without locks.
  *  - sequence allocation must be locked by exch lock.
- *  - If the em_lock and ex_lock must be taken at the same time, then the
- *    em_lock must be taken before the ex_lock.
+ *  - If the EM pool lock and ex_lock must be taken at the same time, then the
+ *    EM pool lock must be taken before the ex_lock.
  */
 
 /*
@@ -335,17 +328,18 @@ static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index,
 	((struct fc_exch **)(pool + 1))[index] = ep;
 }
 
-static void fc_exch_mgr_delete_ep(struct fc_exch *ep)
+static void fc_exch_delete(struct fc_exch *ep)
 {
-	struct fc_exch_mgr *mp;
+	struct fc_exch_pool *pool;
 
-	mp = ep->em;
-	spin_lock_bh(&mp->em_lock);
-	WARN_ON(mp->total_exches <= 0);
-	mp->total_exches--;
-	mp->exches[ep->xid - mp->min_xid] = NULL;
+	pool = ep->pool;
+	spin_lock_bh(&pool->lock);
+	WARN_ON(pool->total_exches <= 0);
+	pool->total_exches--;
+	fc_exch_ptr_set(pool, (ep->xid - ep->em->min_xid) >> fc_cpu_order,
+			NULL);
 	list_del(&ep->ex_list);
-	spin_unlock_bh(&mp->em_lock);
+	spin_unlock_bh(&pool->lock);
 	fc_exch_release(ep);	/* drop hold for exch in mp */
 }
 
@@ -465,7 +459,7 @@ static void fc_exch_timeout(struct work_struct *work)
 			rc = fc_exch_done_locked(ep);
 		spin_unlock_bh(&ep->ex_lock);
 		if (!rc)
-			fc_exch_mgr_delete_ep(ep);
+			fc_exch_delete(ep);
 		if (resp)
 			resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg);
 		fc_seq_exch_abort(sp, 2 * ep->r_a_tov);
@@ -509,10 +503,9 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
 					struct fc_exch_mgr *mp)
 {
 	struct fc_exch *ep;
-	u16 min, max, xid;
-
-	min = mp->min_xid;
-	max = mp->max_xid;
+	unsigned int cpu;
+	u16 index;
+	struct fc_exch_pool *pool;
 
 	/* allocate memory for exchange */
 	ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC);
@@ -522,15 +515,17 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
 	}
 	memset(ep, 0, sizeof(*ep));
 
-	spin_lock_bh(&mp->em_lock);
-	xid = mp->next_xid;
-	/* alloc a new xid */
-	while (mp->exches[xid - min]) {
-		xid = (xid == max) ? min : xid + 1;
-		if (xid == mp->next_xid)
+	cpu = smp_processor_id();
+	pool = per_cpu_ptr(mp->pool, cpu);
+	spin_lock_bh(&pool->lock);
+	index = pool->next_index;
+	/* allocate new exch from pool */
+	while (fc_exch_ptr_get(pool, index)) {
+		index = index == mp->pool_max_index ? 0 : index + 1;
+		if (index == pool->next_index)
 			goto err;
 	}
-	mp->next_xid = (xid == max) ? min : xid + 1;
+	pool->next_index = index == mp->pool_max_index ? 0 : index + 1;
 
 	fc_exch_hold(ep);	/* hold for exch in mp */
 	spin_lock_init(&ep->ex_lock);
@@ -541,17 +536,18 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
 	 */
 	spin_lock_bh(&ep->ex_lock);
 
-	mp->exches[xid - mp->min_xid] = ep;
-	list_add_tail(&ep->ex_list, &mp->ex_list);
+	fc_exch_ptr_set(pool, index, ep);
+	list_add_tail(&ep->ex_list, &pool->ex_list);
 	fc_seq_alloc(ep, ep->seq_id++);
-	mp->total_exches++;
-	spin_unlock_bh(&mp->em_lock);
+	pool->total_exches++;
+	spin_unlock_bh(&pool->lock);
 
 	/*
 	 *  update exchange
 	 */
-	ep->oxid = ep->xid = xid;
+	ep->oxid = ep->xid = (index << fc_cpu_order | cpu) + mp->min_xid;
 	ep->em = mp;
+	ep->pool = pool;
 	ep->lp = lport;
 	ep->f_ctl = FC_FC_FIRST_SEQ;	/* next seq is first seq */
 	ep->rxid = FC_XID_UNKNOWN;
@@ -560,7 +556,7 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
 out:
 	return ep;
 err:
-	spin_unlock_bh(&mp->em_lock);
+	spin_unlock_bh(&pool->lock);
 	atomic_inc(&mp->stats.no_free_exch_xid);
 	mempool_free(ep, mp->ep_pool);
 	return NULL;
@@ -597,16 +593,18 @@ EXPORT_SYMBOL(fc_exch_alloc);
  */
 static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
 {
+	struct fc_exch_pool *pool;
 	struct fc_exch *ep = NULL;
 
 	if ((xid >= mp->min_xid) && (xid <= mp->max_xid)) {
-		spin_lock_bh(&mp->em_lock);
-		ep = mp->exches[xid - mp->min_xid];
+		pool = per_cpu_ptr(mp->pool, xid & fc_cpu_mask);
+		spin_lock_bh(&pool->lock);
+		ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order);
 		if (ep) {
 			fc_exch_hold(ep);
 			WARN_ON(ep->xid != xid);
 		}
-		spin_unlock_bh(&mp->em_lock);
+		spin_unlock_bh(&pool->lock);
 	}
 	return ep;
 }
@@ -620,7 +618,7 @@ void fc_exch_done(struct fc_seq *sp)
 	rc = fc_exch_done_locked(ep);
 	spin_unlock_bh(&ep->ex_lock);
 	if (!rc)
-		fc_exch_mgr_delete_ep(ep);
+		fc_exch_delete(ep);
 }
 EXPORT_SYMBOL(fc_exch_done);
 
@@ -1213,7 +1211,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
 		WARN_ON(fc_seq_exch(sp) != ep);
 		spin_unlock_bh(&ep->ex_lock);
 		if (!rc)
-			fc_exch_mgr_delete_ep(ep);
+			fc_exch_delete(ep);
 	}
 
 	/*
@@ -1323,7 +1321,7 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
 		rc = fc_exch_done_locked(ep);
 	spin_unlock_bh(&ep->ex_lock);
 	if (!rc)
-		fc_exch_mgr_delete_ep(ep);
+		fc_exch_delete(ep);
 
 	if (resp)
 		resp(sp, fp, ex_resp_arg);
@@ -1466,48 +1464,76 @@ static void fc_exch_reset(struct fc_exch *ep)
 	rc = fc_exch_done_locked(ep);
 	spin_unlock_bh(&ep->ex_lock);
 	if (!rc)
-		fc_exch_mgr_delete_ep(ep);
+		fc_exch_delete(ep);
 
 	if (resp)
 		resp(sp, ERR_PTR(-FC_EX_CLOSED), arg);
 }
 
-/*
- * Reset an exchange manager, releasing all sequences and exchanges.
- * If sid is non-zero, reset only exchanges we source from that FID.
- * If did is non-zero, reset only exchanges destined to that FID.
+/**
+ * fc_exch_pool_reset() - Resets an per cpu exches pool.
+ * @lport:	ptr to the local port
+ * @pool:	ptr to the per cpu exches pool
+ * @sid:	source FC ID
+ * @did:	destination FC ID
+ *
+ * Resets an per cpu exches pool, releasing its all sequences
+ * and exchanges. If sid is non-zero, then reset only exchanges
+ * we sourced from that FID. If did is non-zero, reset only
+ * exchanges destined to that FID.
  */
-void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
+static void fc_exch_pool_reset(struct fc_lport *lport,
+			       struct fc_exch_pool *pool,
+			       u32 sid, u32 did)
 {
 	struct fc_exch *ep;
 	struct fc_exch *next;
-	struct fc_exch_mgr *mp;
-	struct fc_exch_mgr_anchor *ema;
 
-	list_for_each_entry(ema, &lp->ema_list, ema_list) {
-		mp = ema->mp;
-		spin_lock_bh(&mp->em_lock);
+	spin_lock_bh(&pool->lock);
 restart:
-		list_for_each_entry_safe(ep, next, &mp->ex_list, ex_list) {
-			if ((lp == ep->lp) &&
-			    (sid == 0 || sid == ep->sid) &&
-			    (did == 0 || did == ep->did)) {
-				fc_exch_hold(ep);
-				spin_unlock_bh(&mp->em_lock);
-
-				fc_exch_reset(ep);
-
-				fc_exch_release(ep);
-				spin_lock_bh(&mp->em_lock);
-
-				/*
-				 * must restart loop incase while lock
-				 * was down multiple eps were released.
-				 */
-				goto restart;
-			}
+	list_for_each_entry_safe(ep, next, &pool->ex_list, ex_list) {
+		if ((lport == ep->lp) &&
+		    (sid == 0 || sid == ep->sid) &&
+		    (did == 0 || did == ep->did)) {
+			fc_exch_hold(ep);
+			spin_unlock_bh(&pool->lock);
+
+			fc_exch_reset(ep);
+
+			fc_exch_release(ep);
+			spin_lock_bh(&pool->lock);
+
+			/*
+			 * must restart loop incase while lock
+			 * was down multiple eps were released.
+			 */
+			goto restart;
 		}
-		spin_unlock_bh(&mp->em_lock);
+	}
+	spin_unlock_bh(&pool->lock);
+}
+
+/**
+ * fc_exch_mgr_reset() - Resets all EMs of a lport
+ * @lport:	ptr to the local port
+ * @sid:	source FC ID
+ * @did:	destination FC ID
+ *
+ * Reset all EMs of a lport, releasing its all sequences and
+ * exchanges. If sid is non-zero, then reset only exchanges
+ * we sourced from that FID. If did is non-zero, reset only
+ * exchanges destined to that FID.
+ */
+void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did)
+{
+	struct fc_exch_mgr_anchor *ema;
+	unsigned int cpu;
+
+	list_for_each_entry(ema, &lport->ema_list, ema_list) {
+		for_each_possible_cpu(cpu)
+			fc_exch_pool_reset(lport,
+					   per_cpu_ptr(ema->mp->pool, cpu),
+					   sid, did);
 	}
 }
 EXPORT_SYMBOL(fc_exch_mgr_reset);
@@ -1777,11 +1803,6 @@ static void fc_exch_mgr_destroy(struct kref *kref)
 {
 	struct fc_exch_mgr *mp = container_of(kref, struct fc_exch_mgr, kref);
 
-	/*
-	 * The total exch count must be zero
-	 * before freeing exchange manager.
-	 */
-	WARN_ON(mp->total_exches != 0);
 	mempool_destroy(mp->ep_pool);
 	free_percpu(mp->pool);
 	kfree(mp);
@@ -1802,7 +1823,6 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
 				      bool (*match)(struct fc_frame *))
 {
 	struct fc_exch_mgr *mp;
-	size_t len;
 	u16 pool_exch_range;
 	size_t pool_size;
 	unsigned int cpu;
@@ -1816,25 +1836,16 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
 	}
 
 	/*
-	 * Memory need for EM
+	 * allocate memory for EM
 	 */
-	len = (max_xid - min_xid + 1) * (sizeof(struct fc_exch *));
-	len += sizeof(struct fc_exch_mgr);
-
-	mp = kzalloc(len, GFP_ATOMIC);
+	mp = kzalloc(sizeof(struct fc_exch_mgr), GFP_ATOMIC);
 	if (!mp)
 		return NULL;
 
 	mp->class = class;
-	mp->total_exches = 0;
-	mp->exches = (struct fc_exch **)(mp + 1);
 	/* adjust em exch xid range for offload */
 	mp->min_xid = min_xid;
 	mp->max_xid = max_xid;
-	mp->next_xid = min_xid;
-
-	INIT_LIST_HEAD(&mp->ex_list);
-	spin_lock_init(&mp->em_lock);
 
 	mp->ep_pool = mempool_create_slab_pool(2, fc_em_cachep);
 	if (!mp->ep_pool)
@@ -1944,7 +1955,7 @@ err:
 	rc = fc_exch_done_locked(ep);
 	spin_unlock_bh(&ep->ex_lock);
 	if (!rc)
-		fc_exch_mgr_delete_ep(ep);
+		fc_exch_delete(ep);
 	return NULL;
 }
 EXPORT_SYMBOL(fc_exch_seq_send);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 3206338..53b3881 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -368,6 +368,7 @@ struct fc_seq {
  */
 struct fc_exch {
 	struct fc_exch_mgr *em;		/* exchange manager */
+	struct fc_exch_pool *pool;	/* per cpu exches pool */
 	u32		state;		/* internal driver state */
 	u16		xid;		/* our exchange ID */
 	struct list_head	ex_list;	/* free or busy list linkage */
@@ -1045,10 +1046,12 @@ struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp);
  */
 struct fc_seq *fc_seq_start_next(struct fc_seq *sp);
 
+
 /*
- * Reset an exchange manager, completing all sequences and exchanges.
- * If s_id is non-zero, reset only exchanges originating from that FID.
- * If d_id is non-zero, reset only exchanges sending to that FID.
+ * Reset all EMs of a lport, releasing its all sequences and
+ * exchanges. If sid is non-zero, then reset only exchanges
+ * we sourced from that FID. If did is non-zero, reset only
+ * exchanges destined to that FID.
  */
 void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id);
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 06/64] libfc: Export FC headers
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (4 preceding siblings ...)
  2009-08-25 20:58 ` [PATCH 05/64] fcoe, libfc: fully makes use of per cpu exch pool and then removes em_lock Robert Love
@ 2009-08-25 20:58 ` Robert Love
  2009-08-27 10:27   ` Christof Schmitt
  2009-08-25 20:59 ` [PATCH 07/64] fcoe: Add sysfs parameter to fcoe for minimum DDP read I/O size Robert Love
                   ` (57 subsequent siblings)
  63 siblings, 1 reply; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:58 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Robert Love

Export fc_els.h, fc_fs.h, fc_gs.h and fc_ns.h so that they
may be used by applications.

This will be needed for FC Passthrough applications like fcping,
but could be used by other applications.

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

 include/scsi/Kbuild    |    1 +
 include/scsi/fc/Kbuild |    4 ++++
 2 files changed, 5 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/fc/Kbuild

diff --git a/include/scsi/Kbuild b/include/scsi/Kbuild
index 33b2750..b3a0ee6 100644
--- a/include/scsi/Kbuild
+++ b/include/scsi/Kbuild
@@ -2,3 +2,4 @@ header-y += scsi.h
 header-y += scsi_netlink.h
 header-y += scsi_netlink_fc.h
 header-y += scsi_bsg_fc.h
+header-y += fc/
diff --git a/include/scsi/fc/Kbuild b/include/scsi/fc/Kbuild
new file mode 100644
index 0000000..5660381
--- /dev/null
+++ b/include/scsi/fc/Kbuild
@@ -0,0 +1,4 @@
+header-y += fc_els.h
+header-y += fc_fs.h
+header-y += fc_gs.h
+header-y += fc_ns.h


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 07/64] fcoe: Add sysfs parameter to fcoe for minimum DDP read I/O size
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (5 preceding siblings ...)
  2009-08-25 20:58 ` [PATCH 06/64] libfc: Export FC headers Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 08/64] libfcoe: fcoe_ctlr_destroy use cancel_work_sync instead of flush_work Robert Love
                   ` (56 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Yi Zou, Robert Love

From: Yi Zou <yi.zou@intel.com>

This adds fcoe_ddp_min as a module parameter for fcoe module to:
/sys/module/fcoe/parameters/ddp_min

It is observed that for some hardware, particularly Intel 82599, there is too
much overhead in setting up context for direct data placement (DDP) read when
the requested read I/O size is small. This is added as a module parameter for
performance tuning and is set as 0 by default and user can change this based
on their own hardware.

Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index e32a0ed..a39d370 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -49,6 +49,12 @@ MODULE_AUTHOR("Open-FCoE.org");
 MODULE_DESCRIPTION("FCoE");
 MODULE_LICENSE("GPL v2");
 
+/* Performance tuning parameters for fcoe */
+static unsigned int fcoe_ddp_min;
+module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for "	\
+		 "Direct Data Placement (DDP).");
+
 /* fcoe host list */
 LIST_HEAD(fcoe_hostlist);
 DEFINE_RWLOCK(fcoe_hostlist_lock);
@@ -414,7 +420,8 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
  */
 bool fcoe_oem_match(struct fc_frame *fp)
 {
-	return fc_fcp_is_read(fr_fsp(fp));
+	return fc_fcp_is_read(fr_fsp(fp)) &&
+		(fr_fsp(fp)->data_len > fcoe_ddp_min);
 }
 
 /**


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 08/64] libfcoe: fcoe_ctlr_destroy use cancel_work_sync instead of flush_work
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (6 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 07/64] fcoe: Add sysfs parameter to fcoe for minimum DDP read I/O size Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 09/64] fcoe: fix missing error check in call to fcoe_if_init Robert Love
                   ` (55 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

Use cancel_work_sync() in place of flush_work(), so that
fcoe_ctlr_destroy() can be called from a workqueue.

Also, purge the receive queue after the recv_work has been cancled because
if recv_work isn't run it's not guaranteed to be empty now.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/libfcoe.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index d0b5208..62a4c20 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -148,13 +148,17 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)
  */
 void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
 {
-	flush_work(&fip->recv_work);
+	cancel_work_sync(&fip->recv_work);
+	spin_lock_bh(&fip->fip_recv_list.lock);
+	__skb_queue_purge(&fip->fip_recv_list);
+	spin_unlock_bh(&fip->fip_recv_list.lock);
+
 	spin_lock_bh(&fip->lock);
 	fip->state = FIP_ST_DISABLED;
 	fcoe_ctlr_reset_fcfs(fip);
 	spin_unlock_bh(&fip->lock);
 	del_timer_sync(&fip->timer);
-	flush_work(&fip->link_work);
+	cancel_work_sync(&fip->link_work);
 }
 EXPORT_SYMBOL(fcoe_ctlr_destroy);
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 09/64] fcoe: fix missing error check in call to fcoe_if_init
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (7 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 08/64] libfcoe: fcoe_ctlr_destroy use cancel_work_sync instead of flush_work Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 10/64] fcoe: remove unnecessary list and lock initializations Robert Love
                   ` (54 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

fcoe_if_init() can fail, but it's return value wasn't checked

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index a39d370..d205ac0 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -1900,7 +1900,9 @@ static int __init fcoe_init(void)
 	/* Setup link change notification */
 	fcoe_dev_setup();
 
-	fcoe_if_init();
+	rc = fcoe_if_init();
+	if (rc)
+		goto out_free;
 
 	return 0;
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 10/64] fcoe: remove unnecessary list and lock initializations.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (8 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 09/64] fcoe: fix missing error check in call to fcoe_if_init Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 11/64] fcoe: interface changes to fcoe_if_create and fcoe_if_destroy Robert Love
                   ` (53 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Chris Leech, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

The hostlist and the hostlist_lock were initialized both in
the delcaration and in fcoe_init().  Remove the unneeded code.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index d205ac0..e481882 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -1881,9 +1881,6 @@ static int __init fcoe_init(void)
 	int rc = 0;
 	struct fcoe_percpu_s *p;
 
-	INIT_LIST_HEAD(&fcoe_hostlist);
-	rwlock_init(&fcoe_hostlist_lock);
-
 	for_each_possible_cpu(cpu) {
 		p = &per_cpu(fcoe_percpu, cpu);
 		skb_queue_head_init(&p->fcoe_rx_list);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 11/64] fcoe: interface changes to fcoe_if_create and fcoe_if_destroy
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (9 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 10/64] fcoe: remove unnecessary list and lock initializations Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 12/64] fcoe: Introduce and allocate fcoe_interface structure, 1:1 with net_device Robert Love
                   ` (52 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

By passing in the parent device instead of assuming the netdev is what
should be used, fcoe_if_create becomes usable for NPIV vports as well.
You still need a netdev, because that's how FCoE works.  Also removed some
duplicate checks from fcoe_if_create that are already in fcoe_create.

fcoe_if_destroy needs to take an lport as it's only argument, not a netdev.
That removes the 1:1 netdev:lport assumption from the destroy path.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |  113 ++++++++++++++++++++--------------------------
 1 files changed, 48 insertions(+), 65 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index e481882..7492796 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -506,30 +506,20 @@ skip_oem:
 
 /**
  * fcoe_if_destroy() - FCoE software HBA tear-down function
- * @netdev: ptr to the associated net_device
- *
- * Returns: 0 if link is OK for use by FCoE.
+ * @lport: fc_lport to destroy
  */
-static int fcoe_if_destroy(struct net_device *netdev)
+static void fcoe_if_destroy(struct fc_lport *lport)
 {
-	struct fc_lport *lp = NULL;
-	struct fcoe_softc *fc;
-
-	BUG_ON(!netdev);
+	struct fcoe_softc *fc = lport_priv(lport);
+	struct net_device *netdev = fc->netdev;
 
 	FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
 
-	lp = fcoe_hostlist_lookup(netdev);
-	if (!lp)
-		return -ENODEV;
-
-	fc = lport_priv(lp);
-
 	/* Logout of the fabric */
-	fc_fabric_logoff(lp);
+	fc_fabric_logoff(lport);
 
 	/* Remove the instance from fcoe's list */
-	fcoe_hostlist_remove(lp);
+	fcoe_hostlist_remove(lport);
 
 	/* clean up netdev configurations */
 	fcoe_netdev_cleanup(fc);
@@ -538,33 +528,31 @@ static int fcoe_if_destroy(struct net_device *netdev)
 	fcoe_ctlr_destroy(&fc->ctlr);
 
 	/* Free queued packets for the per-CPU receive threads */
-	fcoe_percpu_clean(lp);
+	fcoe_percpu_clean(lport);
 
 	/* Cleanup the fc_lport */
-	fc_lport_destroy(lp);
-	fc_fcp_destroy(lp);
+	fc_lport_destroy(lport);
+	fc_fcp_destroy(lport);
 
 	/* Detach from the scsi-ml */
-	fc_remove_host(lp->host);
-	scsi_remove_host(lp->host);
+	fc_remove_host(lport->host);
+	scsi_remove_host(lport->host);
 
 	/* There are no more rports or I/O, free the EM */
-	fc_exch_mgr_free(lp);
+	fc_exch_mgr_free(lport);
 
 	/* Free existing skbs */
-	fcoe_clean_pending_queue(lp);
+	fcoe_clean_pending_queue(lport);
 
 	/* Stop the timer */
 	del_timer_sync(&fc->timer);
 
 	/* Free memory used by statistical counters */
-	fc_lport_free_stats(lp);
+	fc_lport_free_stats(lport);
 
 	/* Release the net_device and Scsi_Host */
 	dev_put(netdev);
-	scsi_host_put(lp->host);
-
-	return 0;
+	scsi_host_put(lport->host);
 }
 
 /*
@@ -612,38 +600,35 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
 /**
  * fcoe_if_create() - this function creates the fcoe interface
  * @netdev: pointer the associated netdevice
+ * @parent: device pointer to be the parent in sysfs for the SCSI host
  *
  * Creates fc_lport struct and scsi_host for lport, configures lport
  * and starts fabric login.
  *
- * Returns : 0 on success
+ * Returns : The allocated fc_lport or an error pointer
  */
-static int fcoe_if_create(struct net_device *netdev)
+static struct fc_lport *fcoe_if_create(struct net_device *netdev,
+				       struct device *parent)
 {
 	int rc;
-	struct fc_lport *lp = NULL;
+	struct fc_lport *lport = NULL;
 	struct fcoe_softc *fc;
 	struct Scsi_Host *shost;
 
-	BUG_ON(!netdev);
-
 	FCOE_NETDEV_DBG(netdev, "Create Interface\n");
 
-	lp = fcoe_hostlist_lookup(netdev);
-	if (lp)
-		return -EEXIST;
-
 	shost = libfc_host_alloc(&fcoe_shost_template,
 				 sizeof(struct fcoe_softc));
 	if (!shost) {
 		FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out;
 	}
-	lp = shost_priv(shost);
-	fc = lport_priv(lp);
+	lport = shost_priv(shost);
+	fc = lport_priv(lport);
 
 	/* configure fc_lport, e.g., em */
-	rc = fcoe_lport_config(lp);
+	rc = fcoe_lport_config(lport);
 	if (rc) {
 		FCOE_NETDEV_DBG(netdev, "Could not configure lport for the "
 				"interface\n");
@@ -658,7 +643,7 @@ static int fcoe_if_create(struct net_device *netdev)
 	fc->ctlr.update_mac = fcoe_update_src_mac;
 
 	/* configure lport network properties */
-	rc = fcoe_netdev_config(lp, netdev);
+	rc = fcoe_netdev_config(lport, netdev);
 	if (rc) {
 		FCOE_NETDEV_DBG(netdev, "Could not configure netdev for the "
 				"interface\n");
@@ -666,7 +651,7 @@ static int fcoe_if_create(struct net_device *netdev)
 	}
 
 	/* configure lport scsi host properties */
-	rc = fcoe_shost_config(lp, shost, &netdev->dev);
+	rc = fcoe_shost_config(lport, shost, parent);
 	if (rc) {
 		FCOE_NETDEV_DBG(netdev, "Could not configure shost for the "
 				"interface\n");
@@ -674,7 +659,7 @@ static int fcoe_if_create(struct net_device *netdev)
 	}
 
 	/* Initialize the library */
-	rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
+	rc = fcoe_libfc_config(lport, &fcoe_libfc_fcn_templ);
 	if (rc) {
 		FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the "
 				"interface\n");
@@ -689,7 +674,7 @@ static int fcoe_if_create(struct net_device *netdev)
 	 */
 	write_lock(&fcoe_hostlist_lock);
 	/* lport exch manager allocation */
-	rc = fcoe_em_config(lp);
+	rc = fcoe_em_config(lport);
 	if (rc) {
 		FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the "
 				"interface\n");
@@ -697,27 +682,28 @@ static int fcoe_if_create(struct net_device *netdev)
 	}
 
 	/* add to lports list */
-	fcoe_hostlist_add(lp);
+	fcoe_hostlist_add(lport);
 	write_unlock(&fcoe_hostlist_lock);
 
-	lp->boot_time = jiffies;
+	lport->boot_time = jiffies;
 
-	fc_fabric_login(lp);
+	fc_fabric_login(lport);
 
-	if (!fcoe_link_ok(lp))
+	if (!fcoe_link_ok(lport))
 		fcoe_ctlr_link_up(&fc->ctlr);
 
 	dev_hold(netdev);
 
-	return rc;
+	return lport;
 
 out_lp_destroy:
-	fc_exch_mgr_free(lp);
+	fc_exch_mgr_free(lport);
 out_netdev_cleanup:
 	fcoe_netdev_cleanup(fc);
 out_host_put:
-	scsi_host_put(lp->host);
-	return rc;
+	scsi_host_put(lport->host);
+out:
+	return ERR_PTR(rc);
 }
 
 /**
@@ -1616,8 +1602,9 @@ static int fcoe_ethdrv_put(const struct net_device *netdev)
  */
 static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 {
-	int rc;
 	struct net_device *netdev;
+	struct fc_lport *lport;
+	int rc;
 
 	netdev = fcoe_if_to_netdev(buffer);
 	if (!netdev) {
@@ -1625,17 +1612,12 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 		goto out_nodev;
 	}
 	/* look for existing lport */
-	if (!fcoe_hostlist_lookup(netdev)) {
+	lport = fcoe_hostlist_lookup(netdev);
+	if (!lport) {
 		rc = -ENODEV;
 		goto out_putdev;
 	}
-	rc = fcoe_if_destroy(netdev);
-	if (rc) {
-		printk(KERN_ERR "fcoe: Failed to destroy interface (%s)\n",
-		       netdev->name);
-		rc = -EIO;
-		goto out_putdev;
-	}
+	fcoe_if_destroy(lport);
 	fcoe_ethdrv_put(netdev);
 	rc = 0;
 out_putdev:
@@ -1654,6 +1636,7 @@ out_nodev:
 static int fcoe_create(const char *buffer, struct kernel_param *kp)
 {
 	int rc;
+	struct fc_lport *lport;
 	struct net_device *netdev;
 
 	netdev = fcoe_if_to_netdev(buffer);
@@ -1668,8 +1651,8 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 	}
 	fcoe_ethdrv_get(netdev);
 
-	rc = fcoe_if_create(netdev);
-	if (rc) {
+	lport = fcoe_if_create(netdev, &netdev->dev);
+	if (IS_ERR(lport)) {
 		printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
 		       netdev->name);
 		fcoe_ethdrv_put(netdev);
@@ -1926,7 +1909,7 @@ static void __exit fcoe_exit(void)
 
 	/* releases the associated fcoe hosts */
 	list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
-		fcoe_if_destroy(fc->netdev);
+		fcoe_if_destroy(fc->ctlr.lp);
 
 	unregister_hotcpu_notifier(&fcoe_cpu_notifier);
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 12/64] fcoe: Introduce and allocate fcoe_interface structure, 1:1 with net_device
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (10 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 11/64] fcoe: interface changes to fcoe_if_create and fcoe_if_destroy Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 13/64] fcoe: move netdev to fcoe_interface Robert Love
                   ` (51 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

In preparation for NPIV support, I'm splitting the fcoe instance structure
into two to remove the assumptions about it being 1:1 with the net_device.
There will now be two structures, one which is 1:1 with the underlying
net_device and one which is allocated per virtual SCSI/FC host.

fcoe_softc is renamed to fcoe_port for the per Scsi_Host FCoE private data.

Later patches with start moving shared stuff from fcoe_port to fcoe_interface

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |  326 ++++++++++++++++++++++++----------------------
 drivers/scsi/fcoe/fcoe.h |   19 ++-
 2 files changed, 188 insertions(+), 157 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 7492796..0ae54b2 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -151,10 +151,10 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
 			 struct packet_type *ptype,
 			 struct net_device *orig_dev)
 {
-	struct fcoe_softc *fc;
+	struct fcoe_port *port;
 
-	fc = container_of(ptype, struct fcoe_softc, fip_packet_type);
-	fcoe_ctlr_recv(&fc->ctlr, skb);
+	port = container_of(ptype, struct fcoe_port, fip_packet_type);
+	fcoe_ctlr_recv(&port->ctlr, skb);
 	return 0;
 }
 
@@ -180,13 +180,13 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
  */
 static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new)
 {
-	struct fcoe_softc *fc;
+	struct fcoe_port *port;
 
-	fc = fcoe_from_ctlr(fip);
+	port = fcoe_from_ctlr(fip);
 	rtnl_lock();
 	if (!is_zero_ether_addr(old))
-		dev_unicast_delete(fc->netdev, old);
-	dev_unicast_add(fc->netdev, new);
+		dev_unicast_delete(port->netdev, old);
+	dev_unicast_add(port->netdev, new);
 	rtnl_unlock();
 }
 
@@ -224,25 +224,25 @@ static int fcoe_lport_config(struct fc_lport *lp)
 
 /**
  * fcoe_netdev_cleanup() - clean up netdev configurations
- * @fc: ptr to the fcoe_softc
+ * @port: ptr to the fcoe_port
  */
-void fcoe_netdev_cleanup(struct fcoe_softc *fc)
+void fcoe_netdev_cleanup(struct fcoe_port *port)
 {
 	u8 flogi_maddr[ETH_ALEN];
 
 	/* Don't listen for Ethernet packets anymore */
-	dev_remove_pack(&fc->fcoe_packet_type);
-	dev_remove_pack(&fc->fip_packet_type);
+	dev_remove_pack(&port->fcoe_packet_type);
+	dev_remove_pack(&port->fip_packet_type);
 
 	/* Delete secondary MAC addresses */
 	rtnl_lock();
 	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
-	dev_unicast_delete(fc->netdev, flogi_maddr);
-	if (!is_zero_ether_addr(fc->ctlr.data_src_addr))
-		dev_unicast_delete(fc->netdev, fc->ctlr.data_src_addr);
-	if (fc->ctlr.spma)
-		dev_unicast_delete(fc->netdev, fc->ctlr.ctl_src_addr);
-	dev_mc_delete(fc->netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
+	dev_unicast_delete(port->netdev, flogi_maddr);
+	if (!is_zero_ether_addr(port->ctlr.data_src_addr))
+		dev_unicast_delete(port->netdev, port->ctlr.data_src_addr);
+	if (port->ctlr.spma)
+		dev_unicast_delete(port->netdev, port->ctlr.ctl_src_addr);
+	dev_mc_delete(port->netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
 	rtnl_unlock();
 }
 
@@ -271,14 +271,14 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 {
 	u32 mfs;
 	u64 wwnn, wwpn;
-	struct fcoe_softc *fc;
+	struct fcoe_port *port;
 	u8 flogi_maddr[ETH_ALEN];
 	struct netdev_hw_addr *ha;
 
 	/* Setup lport private data to point to fcoe softc */
-	fc = lport_priv(lp);
-	fc->ctlr.lp = lp;
-	fc->netdev = netdev;
+	port = lport_priv(lp);
+	port->ctlr.lp = lp;
+	port->netdev = netdev;
 
 	/* Do not support for bonding device */
 	if ((netdev->priv_flags & IFF_MASTER_ALB) ||
@@ -317,27 +317,27 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 		FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n",
 				lp->lro_xid);
 	}
-	skb_queue_head_init(&fc->fcoe_pending_queue);
-	fc->fcoe_pending_queue_active = 0;
-	setup_timer(&fc->timer, fcoe_queue_timer, (unsigned long)lp);
+	skb_queue_head_init(&port->fcoe_pending_queue);
+	port->fcoe_pending_queue_active = 0;
+	setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lp);
 
 	/* look for SAN MAC address, if multiple SAN MACs exist, only
 	 * use the first one for SPMA */
 	rcu_read_lock();
 	for_each_dev_addr(netdev, ha) {
 		if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
-		    (is_valid_ether_addr(ha->addr))) {
-			memcpy(fc->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
-			fc->ctlr.spma = 1;
+		    (is_valid_ether_addr(port->ctlr.ctl_src_addr))) {
+			memcpy(port->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
+			port->ctlr.spma = 1;
 			break;
 		}
 	}
 	rcu_read_unlock();
 
 	/* setup Source Mac Address */
-	if (!fc->ctlr.spma)
-		memcpy(fc->ctlr.ctl_src_addr, netdev->dev_addr,
-		       fc->netdev->addr_len);
+	if (!port->ctlr.spma)
+		memcpy(port->ctlr.ctl_src_addr, netdev->dev_addr,
+		       netdev->addr_len);
 
 	wwnn = fcoe_wwn_from_mac(netdev->dev_addr, 1, 0);
 	fc_set_wwnn(lp, wwnn);
@@ -353,8 +353,8 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 	rtnl_lock();
 	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
 	dev_unicast_add(netdev, flogi_maddr);
-	if (fc->ctlr.spma)
-		dev_unicast_add(netdev, fc->ctlr.ctl_src_addr);
+	if (port->ctlr.spma)
+		dev_unicast_add(netdev, port->ctlr.ctl_src_addr);
 	dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
 	rtnl_unlock();
 
@@ -362,15 +362,15 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 	 * setup the receive function from ethernet driver
 	 * on the ethertype for the given device
 	 */
-	fc->fcoe_packet_type.func = fcoe_rcv;
-	fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
-	fc->fcoe_packet_type.dev = netdev;
-	dev_add_pack(&fc->fcoe_packet_type);
+	port->fcoe_packet_type.func = fcoe_rcv;
+	port->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
+	port->fcoe_packet_type.dev = netdev;
+	dev_add_pack(&port->fcoe_packet_type);
 
-	fc->fip_packet_type.func = fcoe_fip_recv;
-	fc->fip_packet_type.type = htons(ETH_P_FIP);
-	fc->fip_packet_type.dev = netdev;
-	dev_add_pack(&fc->fip_packet_type);
+	port->fip_packet_type.func = fcoe_fip_recv;
+	port->fip_packet_type.type = htons(ETH_P_FIP);
+	port->fip_packet_type.dev = netdev;
+	dev_add_pack(&port->fip_packet_type);
 
 	return 0;
 }
@@ -426,7 +426,7 @@ bool fcoe_oem_match(struct fc_frame *fp)
 
 /**
  * fcoe_em_config() - allocates em for this lport
- * @lp: the port that em is to allocated for
+ * @lp: the fcoe that em is to allocated for
  *
  * Called with write fcoe_hostlist_lock held.
  *
@@ -434,8 +434,9 @@ bool fcoe_oem_match(struct fc_frame *fp)
  */
 static inline int fcoe_em_config(struct fc_lport *lp)
 {
-	struct fcoe_softc *fc = lport_priv(lp);
-	struct fcoe_softc *oldfc = NULL;
+	struct fcoe_interface *fcoe;
+	struct fcoe_port *port = lport_priv(lp);
+	struct fcoe_port *oldfc = NULL;
 	struct net_device *old_real_dev, *cur_real_dev;
 	u16 min_xid = FCOE_MIN_XID;
 	u16 max_xid = FCOE_MAX_XID;
@@ -453,38 +454,39 @@ static inline int fcoe_em_config(struct fc_lport *lp)
 	 * Reuse existing offload em instance in case
 	 * it is already allocated on real eth device
 	 */
-	if (fc->netdev->priv_flags & IFF_802_1Q_VLAN)
-		cur_real_dev = vlan_dev_real_dev(fc->netdev);
+	if (port->netdev->priv_flags & IFF_802_1Q_VLAN)
+		cur_real_dev = vlan_dev_real_dev(port->netdev);
 	else
-		cur_real_dev = fc->netdev;
+		cur_real_dev = port->netdev;
 
-	list_for_each_entry(oldfc, &fcoe_hostlist, list) {
+	list_for_each_entry(fcoe, &fcoe_hostlist, list) {
+		oldfc = fcoe->priv;
 		if (oldfc->netdev->priv_flags & IFF_802_1Q_VLAN)
 			old_real_dev = vlan_dev_real_dev(oldfc->netdev);
 		else
 			old_real_dev = oldfc->netdev;
 
 		if (cur_real_dev == old_real_dev) {
-			fc->oem = oldfc->oem;
+			port->oem = oldfc->oem;
 			break;
 		}
 	}
 
-	if (fc->oem) {
-		if (!fc_exch_mgr_add(lp, fc->oem, fcoe_oem_match)) {
+	if (port->oem) {
+		if (!fc_exch_mgr_add(lp, port->oem, fcoe_oem_match)) {
 			printk(KERN_ERR "fcoe_em_config: failed to add "
 			       "offload em:%p on interface:%s\n",
-			       fc->oem, fc->netdev->name);
+			       port->oem, port->netdev->name);
 			return -ENOMEM;
 		}
 	} else {
-		fc->oem = fc_exch_mgr_alloc(lp, FC_CLASS_3,
+		port->oem = fc_exch_mgr_alloc(lp, FC_CLASS_3,
 					    FCOE_MIN_XID, lp->lro_xid,
 					    fcoe_oem_match);
-		if (!fc->oem) {
+		if (!port->oem) {
 			printk(KERN_ERR "fcoe_em_config: failed to allocate "
 			       "em for offload exches on interface:%s\n",
-			       fc->netdev->name);
+			       port->netdev->name);
 			return -ENOMEM;
 		}
 	}
@@ -497,7 +499,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
 skip_oem:
 	if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, min_xid, max_xid, NULL)) {
 		printk(KERN_ERR "fcoe_em_config: failed to "
-		       "allocate em on interface %s\n", fc->netdev->name);
+		       "allocate em on interface %s\n", port->netdev->name);
 		return -ENOMEM;
 	}
 
@@ -510,8 +512,9 @@ skip_oem:
  */
 static void fcoe_if_destroy(struct fc_lport *lport)
 {
-	struct fcoe_softc *fc = lport_priv(lport);
-	struct net_device *netdev = fc->netdev;
+	struct fcoe_port *port = lport_priv(lport);
+	struct fcoe_interface *fcoe = port->fcoe;
+	struct net_device *netdev = port->netdev;
 
 	FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
 
@@ -522,10 +525,10 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 	fcoe_hostlist_remove(lport);
 
 	/* clean up netdev configurations */
-	fcoe_netdev_cleanup(fc);
+	fcoe_netdev_cleanup(port);
 
 	/* tear-down the FCoE controller */
-	fcoe_ctlr_destroy(&fc->ctlr);
+	fcoe_ctlr_destroy(&port->ctlr);
 
 	/* Free queued packets for the per-CPU receive threads */
 	fcoe_percpu_clean(lport);
@@ -545,7 +548,7 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 	fcoe_clean_pending_queue(lport);
 
 	/* Stop the timer */
-	del_timer_sync(&fc->timer);
+	del_timer_sync(&port->timer);
 
 	/* Free memory used by statistical counters */
 	fc_lport_free_stats(lport);
@@ -553,6 +556,7 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 	/* Release the net_device and Scsi_Host */
 	dev_put(netdev);
 	scsi_host_put(lport->host);
+	kfree(fcoe);		/* TODO, should be refcounted */
 }
 
 /*
@@ -612,20 +616,31 @@ static struct fc_lport *fcoe_if_create(struct net_device *netdev,
 {
 	int rc;
 	struct fc_lport *lport = NULL;
-	struct fcoe_softc *fc;
+	struct fcoe_port *port;
+	struct fcoe_interface *fcoe;
 	struct Scsi_Host *shost;
 
 	FCOE_NETDEV_DBG(netdev, "Create Interface\n");
 
+	fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL);
+	if (!fcoe) {
+		FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
 	shost = libfc_host_alloc(&fcoe_shost_template,
-				 sizeof(struct fcoe_softc));
+				 sizeof(struct fcoe_port));
 	if (!shost) {
 		FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n");
 		rc = -ENOMEM;
-		goto out;
+		goto out_kfree_port;
 	}
 	lport = shost_priv(shost);
-	fc = lport_priv(lport);
+	port = lport_priv(lport);
+
+	port->fcoe = fcoe;
+	fcoe->priv = port;
 
 	/* configure fc_lport, e.g., em */
 	rc = fcoe_lport_config(lport);
@@ -638,9 +653,9 @@ static struct fc_lport *fcoe_if_create(struct net_device *netdev,
 	/*
 	 * Initialize FIP.
 	 */
-	fcoe_ctlr_init(&fc->ctlr);
-	fc->ctlr.send = fcoe_fip_send;
-	fc->ctlr.update_mac = fcoe_update_src_mac;
+	fcoe_ctlr_init(&port->ctlr);
+	port->ctlr.send = fcoe_fip_send;
+	port->ctlr.update_mac = fcoe_update_src_mac;
 
 	/* configure lport network properties */
 	rc = fcoe_netdev_config(lport, netdev);
@@ -690,7 +705,7 @@ static struct fc_lport *fcoe_if_create(struct net_device *netdev,
 	fc_fabric_login(lport);
 
 	if (!fcoe_link_ok(lport))
-		fcoe_ctlr_link_up(&fc->ctlr);
+		fcoe_ctlr_link_up(&port->ctlr);
 
 	dev_hold(netdev);
 
@@ -699,9 +714,11 @@ static struct fc_lport *fcoe_if_create(struct net_device *netdev,
 out_lp_destroy:
 	fc_exch_mgr_free(lport);
 out_netdev_cleanup:
-	fcoe_netdev_cleanup(fc);
+	fcoe_netdev_cleanup(port);
 out_host_put:
 	scsi_host_put(lport->host);
+out_kfree_port:
+	kfree(fcoe);
 out:
 	return ERR_PTR(rc);
 }
@@ -902,13 +919,13 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
 {
 	struct fc_lport *lp;
 	struct fcoe_rcv_info *fr;
-	struct fcoe_softc *fc;
+	struct fcoe_port *port;
 	struct fc_frame_header *fh;
 	struct fcoe_percpu_s *fps;
 	unsigned int cpu;
 
-	fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type);
-	lp = fc->ctlr.lp;
+	port = container_of(ptype, struct fcoe_port, fcoe_packet_type);
+	lp = port->ctlr.lp;
 	if (unlikely(lp == NULL)) {
 		FCOE_NETDEV_DBG(dev, "Cannot find hba structure");
 		goto err2;
@@ -1059,7 +1076,7 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
  * fcoe_fc_crc() - calculates FC CRC in this fcoe skb
  * @fp: the fc_frame containing data to be checksummed
  *
- * This uses crc32() to calculate the crc for fc frame
+ * This uses crc32() to calculate the crc for port frame
  * Return   : 32 bit crc
  */
 u32 fcoe_fc_crc(struct fc_frame *fp)
@@ -1092,7 +1109,7 @@ u32 fcoe_fc_crc(struct fc_frame *fp)
 
 /**
  * fcoe_xmit() - FCoE frame transmit function
- * @lp:	the associated local port
+ * @lp:	the associated local fcoe
  * @fp: the fc_frame to be transmitted
  *
  * Return   : 0 for success
@@ -1109,13 +1126,13 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 	unsigned int hlen;		/* header length implies the version */
 	unsigned int tlen;		/* trailer length */
 	unsigned int elen;		/* eth header, may include vlan */
-	struct fcoe_softc *fc;
+	struct fcoe_port *port;
 	u8 sof, eof;
 	struct fcoe_hdr *hp;
 
 	WARN_ON((fr_len(fp) % sizeof(u32)) != 0);
 
-	fc = lport_priv(lp);
+	port = lport_priv(lp);
 	fh = fc_frame_header_get(fp);
 	skb = fp_skb(fp);
 	wlen = skb->len / FCOE_WORD_TO_BYTE;
@@ -1126,7 +1143,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 	}
 
 	if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
-	    fcoe_ctlr_els_send(&fc->ctlr, skb))
+	    fcoe_ctlr_els_send(&port->ctlr, skb))
 		return 0;
 
 	sof = fr_sof(fp);
@@ -1148,7 +1165,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 		crc = fcoe_fc_crc(fp);
 	}
 
-	/* copy fc crc and eof to the skb buff */
+	/* copy port crc and eof to the skb buff */
 	if (skb_is_nonlinear(skb)) {
 		skb_frag_t *frag;
 		if (fcoe_get_paged_crc_eof(skb, tlen)) {
@@ -1171,27 +1188,27 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 		cp = NULL;
 	}
 
-	/* adjust skb network/transport offsets to match mac/fcoe/fc */
+	/* adjust skb network/transport offsets to match mac/fcoe/port */
 	skb_push(skb, elen + hlen);
 	skb_reset_mac_header(skb);
 	skb_reset_network_header(skb);
 	skb->mac_len = elen;
 	skb->protocol = htons(ETH_P_FCOE);
-	skb->dev = fc->netdev;
+	skb->dev = port->netdev;
 
 	/* fill up mac and fcoe headers */
 	eh = eth_hdr(skb);
 	eh->h_proto = htons(ETH_P_FCOE);
-	if (fc->ctlr.map_dest)
+	if (port->ctlr.map_dest)
 		fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
 	else
 		/* insert GW address */
-		memcpy(eh->h_dest, fc->ctlr.dest_addr, ETH_ALEN);
+		memcpy(eh->h_dest, port->ctlr.dest_addr, ETH_ALEN);
 
-	if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN))
-		memcpy(eh->h_source, fc->ctlr.ctl_src_addr, ETH_ALEN);
+	if (unlikely(port->ctlr.flogi_oxid != FC_XID_UNKNOWN))
+		memcpy(eh->h_source, port->ctlr.ctl_src_addr, ETH_ALEN);
 	else
-		memcpy(eh->h_source, fc->ctlr.data_src_addr, ETH_ALEN);
+		memcpy(eh->h_source, port->ctlr.data_src_addr, ETH_ALEN);
 
 	hp = (struct fcoe_hdr *)(eh + 1);
 	memset(hp, 0, sizeof(*hp));
@@ -1214,7 +1231,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 
 	/* send down to lld */
 	fr_dev(fp) = lp;
-	if (fc->fcoe_pending_queue.qlen)
+	if (port->fcoe_pending_queue.qlen)
 		fcoe_check_wait_queue(lp, skb);
 	else if (fcoe_start_io(skb))
 		fcoe_check_wait_queue(lp, skb);
@@ -1240,7 +1257,7 @@ int fcoe_percpu_receive_thread(void *arg)
 	struct fcoe_crc_eof crc_eof;
 	struct fc_frame *fp;
 	u8 *mac = NULL;
-	struct fcoe_softc *fc;
+	struct fcoe_port *port;
 	struct fcoe_hdr *hp;
 
 	set_user_nice(current, -20);
@@ -1276,7 +1293,7 @@ int fcoe_percpu_receive_thread(void *arg)
 		/*
 		 * Save source MAC address before discarding header.
 		 */
-		fc = lport_priv(lp);
+		port = lport_priv(lp);
 		if (skb_is_nonlinear(skb))
 			skb_linearize(skb);	/* not ideal */
 		mac = eth_hdr(skb)->h_source;
@@ -1354,8 +1371,8 @@ int fcoe_percpu_receive_thread(void *arg)
 			}
 			fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
 		}
-		if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN) &&
-		    fcoe_ctlr_recv_flogi(&fc->ctlr, fp, mac)) {
+		if (unlikely(port->ctlr.flogi_oxid != FC_XID_UNKNOWN) &&
+		    fcoe_ctlr_recv_flogi(&port->ctlr, fp, mac)) {
 			fc_frame_free(fp);
 			continue;
 		}
@@ -1379,46 +1396,46 @@ int fcoe_percpu_receive_thread(void *arg)
  */
 static void fcoe_check_wait_queue(struct fc_lport *lp, struct sk_buff *skb)
 {
-	struct fcoe_softc *fc = lport_priv(lp);
+	struct fcoe_port *port = lport_priv(lp);
 	int rc;
 
-	spin_lock_bh(&fc->fcoe_pending_queue.lock);
+	spin_lock_bh(&port->fcoe_pending_queue.lock);
 
 	if (skb)
-		__skb_queue_tail(&fc->fcoe_pending_queue, skb);
+		__skb_queue_tail(&port->fcoe_pending_queue, skb);
 
-	if (fc->fcoe_pending_queue_active)
+	if (port->fcoe_pending_queue_active)
 		goto out;
-	fc->fcoe_pending_queue_active = 1;
+	port->fcoe_pending_queue_active = 1;
 
-	while (fc->fcoe_pending_queue.qlen) {
+	while (port->fcoe_pending_queue.qlen) {
 		/* keep qlen > 0 until fcoe_start_io succeeds */
-		fc->fcoe_pending_queue.qlen++;
-		skb = __skb_dequeue(&fc->fcoe_pending_queue);
+		port->fcoe_pending_queue.qlen++;
+		skb = __skb_dequeue(&port->fcoe_pending_queue);
 
-		spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+		spin_unlock_bh(&port->fcoe_pending_queue.lock);
 		rc = fcoe_start_io(skb);
-		spin_lock_bh(&fc->fcoe_pending_queue.lock);
+		spin_lock_bh(&port->fcoe_pending_queue.lock);
 
 		if (rc) {
-			__skb_queue_head(&fc->fcoe_pending_queue, skb);
+			__skb_queue_head(&port->fcoe_pending_queue, skb);
 			/* undo temporary increment above */
-			fc->fcoe_pending_queue.qlen--;
+			port->fcoe_pending_queue.qlen--;
 			break;
 		}
 		/* undo temporary increment above */
-		fc->fcoe_pending_queue.qlen--;
+		port->fcoe_pending_queue.qlen--;
 	}
 
-	if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
+	if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
 		lp->qfull = 0;
-	if (fc->fcoe_pending_queue.qlen && !timer_pending(&fc->timer))
-		mod_timer(&fc->timer, jiffies + 2);
-	fc->fcoe_pending_queue_active = 0;
+	if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
+		mod_timer(&port->timer, jiffies + 2);
+	port->fcoe_pending_queue_active = 0;
 out:
-	if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
+	if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
 		lp->qfull = 1;
-	spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+	spin_unlock_bh(&port->fcoe_pending_queue.lock);
 	return;
 }
 
@@ -1453,16 +1470,18 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 {
 	struct fc_lport *lp = NULL;
 	struct net_device *netdev = ptr;
-	struct fcoe_softc *fc;
+	struct fcoe_interface *fcoe;
+	struct fcoe_port *port = NULL;
 	struct fcoe_dev_stats *stats;
 	u32 link_possible = 1;
 	u32 mfs;
 	int rc = NOTIFY_OK;
 
 	read_lock(&fcoe_hostlist_lock);
-	list_for_each_entry(fc, &fcoe_hostlist, list) {
-		if (fc->netdev == netdev) {
-			lp = fc->ctlr.lp;
+	list_for_each_entry(fcoe, &fcoe_hostlist, list) {
+		port = fcoe->priv;
+		if (port->netdev == netdev) {
+			lp = port->ctlr.lp;
 			break;
 		}
 	}
@@ -1493,8 +1512,8 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 				"from netdev netlink\n", event);
 	}
 	if (link_possible && !fcoe_link_ok(lp))
-		fcoe_ctlr_link_up(&fc->ctlr);
-	else if (fcoe_ctlr_link_down(&fc->ctlr)) {
+		fcoe_ctlr_link_up(&port->ctlr);
+	else if (fcoe_ctlr_link_down(&port->ctlr)) {
 		stats = fc_lport_get_stats(lp);
 		stats->LinkFailureCount++;
 		fcoe_clean_pending_queue(lp);
@@ -1668,10 +1687,10 @@ out_nodev:
 
 module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
 __MODULE_PARM_TYPE(create, "string");
-MODULE_PARM_DESC(create, "Create fcoe port using net device passed in.");
+MODULE_PARM_DESC(create, "Create fcoe fcoe using net device passed in.");
 module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
 __MODULE_PARM_TYPE(destroy, "string");
-MODULE_PARM_DESC(destroy, "Destroy fcoe port");
+MODULE_PARM_DESC(destroy, "Destroy fcoe fcoe");
 
 /**
  * fcoe_link_ok() - Check if link is ok for the fc_lport
@@ -1689,8 +1708,8 @@ MODULE_PARM_DESC(destroy, "Destroy fcoe port");
  */
 int fcoe_link_ok(struct fc_lport *lp)
 {
-	struct fcoe_softc *fc = lport_priv(lp);
-	struct net_device *dev = fc->netdev;
+	struct fcoe_port *port = lport_priv(lp);
+	struct net_device *dev = port->netdev;
 	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
 
 	if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) &&
@@ -1752,16 +1771,16 @@ void fcoe_percpu_clean(struct fc_lport *lp)
  */
 void fcoe_clean_pending_queue(struct fc_lport *lp)
 {
-	struct fcoe_softc  *fc = lport_priv(lp);
+	struct fcoe_port  *port = lport_priv(lp);
 	struct sk_buff *skb;
 
-	spin_lock_bh(&fc->fcoe_pending_queue.lock);
-	while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) {
-		spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+	spin_lock_bh(&port->fcoe_pending_queue.lock);
+	while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
+		spin_unlock_bh(&port->fcoe_pending_queue.lock);
 		kfree_skb(skb);
-		spin_lock_bh(&fc->fcoe_pending_queue.lock);
+		spin_lock_bh(&port->fcoe_pending_queue.lock);
 	}
-	spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+	spin_unlock_bh(&port->fcoe_pending_queue.lock);
 }
 
 /**
@@ -1778,21 +1797,21 @@ int fcoe_reset(struct Scsi_Host *shost)
 }
 
 /**
- * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device
+ * fcoe_hostlist_lookup_port() - find the corresponding lport by a given device
  * @dev: this is currently ptr to net_device
  *
  * Called with fcoe_hostlist_lock held.
  *
- * Returns: NULL or the located fcoe_softc
+ * Returns: NULL or the located fcoe_port
  */
-static struct fcoe_softc *
-fcoe_hostlist_lookup_softc(const struct net_device *dev)
+static struct fcoe_interface *
+fcoe_hostlist_lookup_port(const struct net_device *dev)
 {
-	struct fcoe_softc *fc;
+	struct fcoe_interface *fcoe;
 
-	list_for_each_entry(fc, &fcoe_hostlist, list) {
-		if (fc->netdev == dev)
-			return fc;
+	list_for_each_entry(fcoe, &fcoe_hostlist, list) {
+		if (fcoe->priv->netdev == dev)
+			return fcoe;
 	}
 	return NULL;
 }
@@ -1805,13 +1824,13 @@ fcoe_hostlist_lookup_softc(const struct net_device *dev)
  */
 struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
 {
-	struct fcoe_softc *fc;
+	struct fcoe_interface *fcoe;
 
 	read_lock(&fcoe_hostlist_lock);
-	fc = fcoe_hostlist_lookup_softc(netdev);
+	fcoe = fcoe_hostlist_lookup_port(netdev);
 	read_unlock(&fcoe_hostlist_lock);
 
-	return (fc) ? fc->ctlr.lp : NULL;
+	return (fcoe) ? fcoe->priv->ctlr.lp : NULL;
 }
 
 /**
@@ -1822,14 +1841,16 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
  *
  * Returns: 0 for success
  */
-int fcoe_hostlist_add(const struct fc_lport *lp)
+int fcoe_hostlist_add(const struct fc_lport *lport)
 {
-	struct fcoe_softc *fc;
-
-	fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
-	if (!fc) {
-		fc = lport_priv(lp);
-		list_add_tail(&fc->list, &fcoe_hostlist);
+	struct fcoe_interface *fcoe;
+	struct fcoe_port *port;
+
+	fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
+	if (!fcoe) {
+		port = lport_priv(lport);
+		fcoe = port->fcoe;
+		list_add_tail(&fcoe->list, &fcoe_hostlist);
 	}
 	return 0;
 }
@@ -1840,14 +1861,14 @@ int fcoe_hostlist_add(const struct fc_lport *lp)
  *
  * Returns: 0 for success
  */
-int fcoe_hostlist_remove(const struct fc_lport *lp)
+int fcoe_hostlist_remove(const struct fc_lport *lport)
 {
-	struct fcoe_softc *fc;
+	struct fcoe_interface *fcoe;
 
 	write_lock_bh(&fcoe_hostlist_lock);
-	fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
-	BUG_ON(!fc);
-	list_del(&fc->list);
+	fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
+	BUG_ON(!fcoe);
+	list_del(&fcoe->list);
 	write_unlock_bh(&fcoe_hostlist_lock);
 
 	return 0;
@@ -1903,19 +1924,18 @@ module_init(fcoe_init);
 static void __exit fcoe_exit(void)
 {
 	unsigned int cpu;
-	struct fcoe_softc *fc, *tmp;
+	struct fcoe_interface *fcoe, *tmp;
 
 	fcoe_dev_cleanup();
 
 	/* releases the associated fcoe hosts */
-	list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
-		fcoe_if_destroy(fc->ctlr.lp);
+	list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list)
+		fcoe_if_destroy(fcoe->priv->ctlr.lp);
 
 	unregister_hotcpu_notifier(&fcoe_cpu_notifier);
 
-	for_each_online_cpu(cpu) {
+	for_each_online_cpu(cpu)
 		fcoe_percpu_thread_destroy(cpu);
-	}
 
 	/* detach from scsi transport */
 	fcoe_if_exit();
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 550d1e4..060a6dc 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -75,10 +75,21 @@ struct fcoe_percpu_s {
 };
 
 /*
- * the fcoe sw transport private data
+ * an FCoE interface, 1:1 with netdev
  */
-struct fcoe_softc {
+struct fcoe_interface {
 	struct list_head list;
+	/* This will be removed once all the shared values are
+	 * moved out of fcoe_port */
+	struct fcoe_port *priv;
+};
+
+/*
+ * the FCoE private structure that's allocated along with the
+ * Scsi_Host and libfc fc_lport structures
+ */
+struct fcoe_port {
+	struct fcoe_interface *fcoe;
 	struct net_device *netdev;
 	struct fc_exch_mgr *oem;		/* offload exchange manger */
 	struct packet_type  fcoe_packet_type;
@@ -89,12 +100,12 @@ struct fcoe_softc {
 	struct fcoe_ctlr ctlr;
 };
 
-#define fcoe_from_ctlr(fc) container_of(fc, struct fcoe_softc, ctlr)
+#define fcoe_from_ctlr(port) container_of(port, struct fcoe_port, ctlr)
 
 static inline struct net_device *fcoe_netdev(
 	const struct fc_lport *lp)
 {
-	return ((struct fcoe_softc *)lport_priv(lp))->netdev;
+	return ((struct fcoe_port *)lport_priv(lp))->netdev;
 }
 
 #endif /* _FCOE_H_ */


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 13/64] fcoe: move netdev to fcoe_interface
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (11 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 12/64] fcoe: Introduce and allocate fcoe_interface structure, 1:1 with net_device Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 14/64] fcoe: move packet handlers from fcoe_port " Robert Love
                   ` (50 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

The network interface needs to be shared between all NPIV VN_Ports, therefor
it should be tracked in the fcoe_interface and not for each SCSI host in
fcoe_port.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   61 ++++++++++++++++++++++++++--------------------
 drivers/scsi/fcoe/fcoe.h |    9 +++----
 2 files changed, 38 insertions(+), 32 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 0ae54b2..44c963c 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -165,7 +165,7 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
  */
 static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
 {
-	skb->dev = fcoe_from_ctlr(fip)->netdev;
+	skb->dev = fcoe_from_ctlr(fip)->fcoe->netdev;
 	dev_queue_xmit(skb);
 }
 
@@ -180,13 +180,16 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
  */
 static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new)
 {
+	struct fcoe_interface *fcoe;
 	struct fcoe_port *port;
 
 	port = fcoe_from_ctlr(fip);
+	fcoe = port->fcoe;
+
 	rtnl_lock();
 	if (!is_zero_ether_addr(old))
-		dev_unicast_delete(port->netdev, old);
-	dev_unicast_add(port->netdev, new);
+		dev_unicast_delete(fcoe->netdev, old);
+	dev_unicast_add(fcoe->netdev, new);
 	rtnl_unlock();
 }
 
@@ -229,6 +232,7 @@ static int fcoe_lport_config(struct fc_lport *lp)
 void fcoe_netdev_cleanup(struct fcoe_port *port)
 {
 	u8 flogi_maddr[ETH_ALEN];
+	struct fcoe_interface *fcoe = port->fcoe;
 
 	/* Don't listen for Ethernet packets anymore */
 	dev_remove_pack(&port->fcoe_packet_type);
@@ -237,12 +241,12 @@ void fcoe_netdev_cleanup(struct fcoe_port *port)
 	/* Delete secondary MAC addresses */
 	rtnl_lock();
 	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
-	dev_unicast_delete(port->netdev, flogi_maddr);
+	dev_unicast_delete(fcoe->netdev, flogi_maddr);
 	if (!is_zero_ether_addr(port->ctlr.data_src_addr))
-		dev_unicast_delete(port->netdev, port->ctlr.data_src_addr);
+		dev_unicast_delete(fcoe->netdev, port->ctlr.data_src_addr);
 	if (port->ctlr.spma)
-		dev_unicast_delete(port->netdev, port->ctlr.ctl_src_addr);
-	dev_mc_delete(port->netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
+		dev_unicast_delete(fcoe->netdev, port->ctlr.ctl_src_addr);
+	dev_mc_delete(fcoe->netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
 	rtnl_unlock();
 }
 
@@ -271,14 +275,16 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 {
 	u32 mfs;
 	u64 wwnn, wwpn;
+	struct fcoe_interface *fcoe;
 	struct fcoe_port *port;
 	u8 flogi_maddr[ETH_ALEN];
 	struct netdev_hw_addr *ha;
 
 	/* Setup lport private data to point to fcoe softc */
 	port = lport_priv(lp);
+	fcoe = port->fcoe;
 	port->ctlr.lp = lp;
-	port->netdev = netdev;
+	fcoe->netdev = netdev;
 
 	/* Do not support for bonding device */
 	if ((netdev->priv_flags & IFF_MASTER_ALB) ||
@@ -434,9 +440,10 @@ bool fcoe_oem_match(struct fc_frame *fp)
  */
 static inline int fcoe_em_config(struct fc_lport *lp)
 {
-	struct fcoe_interface *fcoe;
 	struct fcoe_port *port = lport_priv(lp);
-	struct fcoe_port *oldfc = NULL;
+	struct fcoe_port *oldport = NULL;
+	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *oldfcoe = NULL;
 	struct net_device *old_real_dev, *cur_real_dev;
 	u16 min_xid = FCOE_MIN_XID;
 	u16 max_xid = FCOE_MAX_XID;
@@ -454,20 +461,20 @@ static inline int fcoe_em_config(struct fc_lport *lp)
 	 * Reuse existing offload em instance in case
 	 * it is already allocated on real eth device
 	 */
-	if (port->netdev->priv_flags & IFF_802_1Q_VLAN)
-		cur_real_dev = vlan_dev_real_dev(port->netdev);
+	if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN)
+		cur_real_dev = vlan_dev_real_dev(fcoe->netdev);
 	else
-		cur_real_dev = port->netdev;
+		cur_real_dev = fcoe->netdev;
 
-	list_for_each_entry(fcoe, &fcoe_hostlist, list) {
-		oldfc = fcoe->priv;
-		if (oldfc->netdev->priv_flags & IFF_802_1Q_VLAN)
-			old_real_dev = vlan_dev_real_dev(oldfc->netdev);
+	list_for_each_entry(oldfcoe, &fcoe_hostlist, list) {
+		oldport = oldfcoe->priv;
+		if (oldfcoe->netdev->priv_flags & IFF_802_1Q_VLAN)
+			old_real_dev = vlan_dev_real_dev(oldfcoe->netdev);
 		else
-			old_real_dev = oldfc->netdev;
+			old_real_dev = oldfcoe->netdev;
 
 		if (cur_real_dev == old_real_dev) {
-			port->oem = oldfc->oem;
+			port->oem = oldport->oem;
 			break;
 		}
 	}
@@ -476,7 +483,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
 		if (!fc_exch_mgr_add(lp, port->oem, fcoe_oem_match)) {
 			printk(KERN_ERR "fcoe_em_config: failed to add "
 			       "offload em:%p on interface:%s\n",
-			       port->oem, port->netdev->name);
+			       port->oem, fcoe->netdev->name);
 			return -ENOMEM;
 		}
 	} else {
@@ -486,7 +493,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
 		if (!port->oem) {
 			printk(KERN_ERR "fcoe_em_config: failed to allocate "
 			       "em for offload exches on interface:%s\n",
-			       port->netdev->name);
+			       fcoe->netdev->name);
 			return -ENOMEM;
 		}
 	}
@@ -499,7 +506,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
 skip_oem:
 	if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, min_xid, max_xid, NULL)) {
 		printk(KERN_ERR "fcoe_em_config: failed to "
-		       "allocate em on interface %s\n", port->netdev->name);
+		       "allocate em on interface %s\n", fcoe->netdev->name);
 		return -ENOMEM;
 	}
 
@@ -514,7 +521,7 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 {
 	struct fcoe_port *port = lport_priv(lport);
 	struct fcoe_interface *fcoe = port->fcoe;
-	struct net_device *netdev = port->netdev;
+	struct net_device *netdev = fcoe->netdev;
 
 	FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
 
@@ -1194,7 +1201,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 	skb_reset_network_header(skb);
 	skb->mac_len = elen;
 	skb->protocol = htons(ETH_P_FCOE);
-	skb->dev = port->netdev;
+	skb->dev = port->fcoe->netdev;
 
 	/* fill up mac and fcoe headers */
 	eh = eth_hdr(skb);
@@ -1480,7 +1487,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 	read_lock(&fcoe_hostlist_lock);
 	list_for_each_entry(fcoe, &fcoe_hostlist, list) {
 		port = fcoe->priv;
-		if (port->netdev == netdev) {
+		if (fcoe->netdev == netdev) {
 			lp = port->ctlr.lp;
 			break;
 		}
@@ -1709,7 +1716,7 @@ MODULE_PARM_DESC(destroy, "Destroy fcoe fcoe");
 int fcoe_link_ok(struct fc_lport *lp)
 {
 	struct fcoe_port *port = lport_priv(lp);
-	struct net_device *dev = port->netdev;
+	struct net_device *dev = port->fcoe->netdev;
 	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
 
 	if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) &&
@@ -1810,7 +1817,7 @@ fcoe_hostlist_lookup_port(const struct net_device *dev)
 	struct fcoe_interface *fcoe;
 
 	list_for_each_entry(fcoe, &fcoe_hostlist, list) {
-		if (fcoe->priv->netdev == dev)
+		if (fcoe->netdev == dev)
 			return fcoe;
 	}
 	return NULL;
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 060a6dc..3b3886e 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -82,6 +82,7 @@ struct fcoe_interface {
 	/* This will be removed once all the shared values are
 	 * moved out of fcoe_port */
 	struct fcoe_port *priv;
+	struct net_device *netdev;
 };
 
 /*
@@ -90,7 +91,6 @@ struct fcoe_interface {
  */
 struct fcoe_port {
 	struct fcoe_interface *fcoe;
-	struct net_device *netdev;
 	struct fc_exch_mgr *oem;		/* offload exchange manger */
 	struct packet_type  fcoe_packet_type;
 	struct packet_type  fip_packet_type;
@@ -100,12 +100,11 @@ struct fcoe_port {
 	struct fcoe_ctlr ctlr;
 };
 
-#define fcoe_from_ctlr(port) container_of(port, struct fcoe_port, ctlr)
+#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_port, ctlr)
 
-static inline struct net_device *fcoe_netdev(
-	const struct fc_lport *lp)
+static inline struct net_device *fcoe_netdev(const struct fc_lport *lp)
 {
-	return ((struct fcoe_port *)lport_priv(lp))->netdev;
+	return ((struct fcoe_port *)lport_priv(lp))->fcoe->netdev;
 }
 
 #endif /* _FCOE_H_ */


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 14/64] fcoe: move packet handlers from fcoe_port to fcoe_interface
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (12 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 13/64] fcoe: move netdev to fcoe_interface Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 15/64] fcoe: move FIP controller " Robert Love
                   ` (49 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

The packet handlers need to be tracked in fcoe_interface so there is only one
set per net_device.  When NPIV is enabled there will be multiple SCSI hosts
and multiple fcoe_port structures on a single net_device.

The packet handlers match by ethertype and netdev.  If the same handler gets
registered on a single netdev multiple times, the receive function will be
called multiple times for each frame.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   28 ++++++++++++++++------------
 drivers/scsi/fcoe/fcoe.h |    4 ++--
 2 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 44c963c..c215235 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -151,9 +151,11 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
 			 struct packet_type *ptype,
 			 struct net_device *orig_dev)
 {
+	struct fcoe_interface *fcoe;
 	struct fcoe_port *port;
 
-	port = container_of(ptype, struct fcoe_port, fip_packet_type);
+	fcoe = container_of(ptype, struct fcoe_interface, fip_packet_type);
+	port = fcoe->priv;
 	fcoe_ctlr_recv(&port->ctlr, skb);
 	return 0;
 }
@@ -235,8 +237,8 @@ void fcoe_netdev_cleanup(struct fcoe_port *port)
 	struct fcoe_interface *fcoe = port->fcoe;
 
 	/* Don't listen for Ethernet packets anymore */
-	dev_remove_pack(&port->fcoe_packet_type);
-	dev_remove_pack(&port->fip_packet_type);
+	dev_remove_pack(&fcoe->fcoe_packet_type);
+	dev_remove_pack(&fcoe->fip_packet_type);
 
 	/* Delete secondary MAC addresses */
 	rtnl_lock();
@@ -368,15 +370,15 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 	 * setup the receive function from ethernet driver
 	 * on the ethertype for the given device
 	 */
-	port->fcoe_packet_type.func = fcoe_rcv;
-	port->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
-	port->fcoe_packet_type.dev = netdev;
-	dev_add_pack(&port->fcoe_packet_type);
+	fcoe->fcoe_packet_type.func = fcoe_rcv;
+	fcoe->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
+	fcoe->fcoe_packet_type.dev = netdev;
+	dev_add_pack(&fcoe->fcoe_packet_type);
 
-	port->fip_packet_type.func = fcoe_fip_recv;
-	port->fip_packet_type.type = htons(ETH_P_FIP);
-	port->fip_packet_type.dev = netdev;
-	dev_add_pack(&port->fip_packet_type);
+	fcoe->fip_packet_type.func = fcoe_fip_recv;
+	fcoe->fip_packet_type.type = htons(ETH_P_FIP);
+	fcoe->fip_packet_type.dev = netdev;
+	dev_add_pack(&fcoe->fip_packet_type);
 
 	return 0;
 }
@@ -926,12 +928,14 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
 {
 	struct fc_lport *lp;
 	struct fcoe_rcv_info *fr;
+	struct fcoe_interface *fcoe;
 	struct fcoe_port *port;
 	struct fc_frame_header *fh;
 	struct fcoe_percpu_s *fps;
 	unsigned int cpu;
 
-	port = container_of(ptype, struct fcoe_port, fcoe_packet_type);
+	fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type);
+	port = fcoe->priv;
 	lp = port->ctlr.lp;
 	if (unlikely(lp == NULL)) {
 		FCOE_NETDEV_DBG(dev, "Cannot find hba structure");
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 3b3886e..685aa9d 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -83,6 +83,8 @@ struct fcoe_interface {
 	 * moved out of fcoe_port */
 	struct fcoe_port *priv;
 	struct net_device *netdev;
+	struct packet_type  fcoe_packet_type;
+	struct packet_type  fip_packet_type;
 };
 
 /*
@@ -92,8 +94,6 @@ struct fcoe_interface {
 struct fcoe_port {
 	struct fcoe_interface *fcoe;
 	struct fc_exch_mgr *oem;		/* offload exchange manger */
-	struct packet_type  fcoe_packet_type;
-	struct packet_type  fip_packet_type;
 	struct sk_buff_head fcoe_pending_queue;
 	u8	fcoe_pending_queue_active;
 	struct timer_list timer;		/* queue timer */


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 15/64] fcoe: move FIP controller from fcoe_port to fcoe_interface
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (13 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 14/64] fcoe: move packet handlers from fcoe_port " Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 16/64] fcoe: move offload exchange manager pointer " Robert Love
                   ` (48 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

There is only one FIP state per net_device, so the FIP controller needs to be
moved from the per-SCSI-host fcoe_port to the per-net_device fcoe_interface
structure.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   83 +++++++++++++++++++++-------------------------
 drivers/scsi/fcoe/fcoe.h |    4 +-
 2 files changed, 39 insertions(+), 48 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index c215235..01519c7 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -152,11 +152,9 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
 			 struct net_device *orig_dev)
 {
 	struct fcoe_interface *fcoe;
-	struct fcoe_port *port;
 
 	fcoe = container_of(ptype, struct fcoe_interface, fip_packet_type);
-	port = fcoe->priv;
-	fcoe_ctlr_recv(&port->ctlr, skb);
+	fcoe_ctlr_recv(&fcoe->ctlr, skb);
 	return 0;
 }
 
@@ -167,7 +165,7 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
  */
 static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
 {
-	skb->dev = fcoe_from_ctlr(fip)->fcoe->netdev;
+	skb->dev = fcoe_from_ctlr(fip)->netdev;
 	dev_queue_xmit(skb);
 }
 
@@ -183,11 +181,8 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
 static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new)
 {
 	struct fcoe_interface *fcoe;
-	struct fcoe_port *port;
-
-	port = fcoe_from_ctlr(fip);
-	fcoe = port->fcoe;
 
+	fcoe = fcoe_from_ctlr(fip);
 	rtnl_lock();
 	if (!is_zero_ether_addr(old))
 		dev_unicast_delete(fcoe->netdev, old);
@@ -244,10 +239,10 @@ void fcoe_netdev_cleanup(struct fcoe_port *port)
 	rtnl_lock();
 	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
 	dev_unicast_delete(fcoe->netdev, flogi_maddr);
-	if (!is_zero_ether_addr(port->ctlr.data_src_addr))
-		dev_unicast_delete(fcoe->netdev, port->ctlr.data_src_addr);
-	if (port->ctlr.spma)
-		dev_unicast_delete(fcoe->netdev, port->ctlr.ctl_src_addr);
+	if (!is_zero_ether_addr(fcoe->ctlr.data_src_addr))
+		dev_unicast_delete(fcoe->netdev, fcoe->ctlr.data_src_addr);
+	if (fcoe->ctlr.spma)
+		dev_unicast_delete(fcoe->netdev, fcoe->ctlr.ctl_src_addr);
 	dev_mc_delete(fcoe->netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
 	rtnl_unlock();
 }
@@ -285,7 +280,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 	/* Setup lport private data to point to fcoe softc */
 	port = lport_priv(lp);
 	fcoe = port->fcoe;
-	port->ctlr.lp = lp;
+	fcoe->ctlr.lp = lp;
 	fcoe->netdev = netdev;
 
 	/* Do not support for bonding device */
@@ -334,17 +329,17 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 	rcu_read_lock();
 	for_each_dev_addr(netdev, ha) {
 		if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
-		    (is_valid_ether_addr(port->ctlr.ctl_src_addr))) {
-			memcpy(port->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
-			port->ctlr.spma = 1;
+		    (is_valid_ether_addr(fcoe->ctlr.ctl_src_addr))) {
+			memcpy(fcoe->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
+			fcoe->ctlr.spma = 1;
 			break;
 		}
 	}
 	rcu_read_unlock();
 
 	/* setup Source Mac Address */
-	if (!port->ctlr.spma)
-		memcpy(port->ctlr.ctl_src_addr, netdev->dev_addr,
+	if (!fcoe->ctlr.spma)
+		memcpy(fcoe->ctlr.ctl_src_addr, netdev->dev_addr,
 		       netdev->addr_len);
 
 	wwnn = fcoe_wwn_from_mac(netdev->dev_addr, 1, 0);
@@ -361,8 +356,8 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 	rtnl_lock();
 	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
 	dev_unicast_add(netdev, flogi_maddr);
-	if (port->ctlr.spma)
-		dev_unicast_add(netdev, port->ctlr.ctl_src_addr);
+	if (fcoe->ctlr.spma)
+		dev_unicast_add(netdev, fcoe->ctlr.ctl_src_addr);
 	dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
 	rtnl_unlock();
 
@@ -537,7 +532,7 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 	fcoe_netdev_cleanup(port);
 
 	/* tear-down the FCoE controller */
-	fcoe_ctlr_destroy(&port->ctlr);
+	fcoe_ctlr_destroy(&fcoe->ctlr);
 
 	/* Free queued packets for the per-CPU receive threads */
 	fcoe_percpu_clean(lport);
@@ -662,9 +657,9 @@ static struct fc_lport *fcoe_if_create(struct net_device *netdev,
 	/*
 	 * Initialize FIP.
 	 */
-	fcoe_ctlr_init(&port->ctlr);
-	port->ctlr.send = fcoe_fip_send;
-	port->ctlr.update_mac = fcoe_update_src_mac;
+	fcoe_ctlr_init(&fcoe->ctlr);
+	fcoe->ctlr.send = fcoe_fip_send;
+	fcoe->ctlr.update_mac = fcoe_update_src_mac;
 
 	/* configure lport network properties */
 	rc = fcoe_netdev_config(lport, netdev);
@@ -714,7 +709,7 @@ static struct fc_lport *fcoe_if_create(struct net_device *netdev,
 	fc_fabric_login(lport);
 
 	if (!fcoe_link_ok(lport))
-		fcoe_ctlr_link_up(&port->ctlr);
+		fcoe_ctlr_link_up(&fcoe->ctlr);
 
 	dev_hold(netdev);
 
@@ -929,14 +924,12 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
 	struct fc_lport *lp;
 	struct fcoe_rcv_info *fr;
 	struct fcoe_interface *fcoe;
-	struct fcoe_port *port;
 	struct fc_frame_header *fh;
 	struct fcoe_percpu_s *fps;
 	unsigned int cpu;
 
 	fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type);
-	port = fcoe->priv;
-	lp = port->ctlr.lp;
+	lp = fcoe->ctlr.lp;
 	if (unlikely(lp == NULL)) {
 		FCOE_NETDEV_DBG(dev, "Cannot find hba structure");
 		goto err2;
@@ -1137,13 +1130,13 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 	unsigned int hlen;		/* header length implies the version */
 	unsigned int tlen;		/* trailer length */
 	unsigned int elen;		/* eth header, may include vlan */
-	struct fcoe_port *port;
+	struct fcoe_port *port = lport_priv(lp);
+	struct fcoe_interface *fcoe = port->fcoe;
 	u8 sof, eof;
 	struct fcoe_hdr *hp;
 
 	WARN_ON((fr_len(fp) % sizeof(u32)) != 0);
 
-	port = lport_priv(lp);
 	fh = fc_frame_header_get(fp);
 	skb = fp_skb(fp);
 	wlen = skb->len / FCOE_WORD_TO_BYTE;
@@ -1154,7 +1147,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 	}
 
 	if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
-	    fcoe_ctlr_els_send(&port->ctlr, skb))
+	    fcoe_ctlr_els_send(&fcoe->ctlr, skb))
 		return 0;
 
 	sof = fr_sof(fp);
@@ -1205,21 +1198,21 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 	skb_reset_network_header(skb);
 	skb->mac_len = elen;
 	skb->protocol = htons(ETH_P_FCOE);
-	skb->dev = port->fcoe->netdev;
+	skb->dev = fcoe->netdev;
 
 	/* fill up mac and fcoe headers */
 	eh = eth_hdr(skb);
 	eh->h_proto = htons(ETH_P_FCOE);
-	if (port->ctlr.map_dest)
+	if (fcoe->ctlr.map_dest)
 		fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
 	else
 		/* insert GW address */
-		memcpy(eh->h_dest, port->ctlr.dest_addr, ETH_ALEN);
+		memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN);
 
-	if (unlikely(port->ctlr.flogi_oxid != FC_XID_UNKNOWN))
-		memcpy(eh->h_source, port->ctlr.ctl_src_addr, ETH_ALEN);
+	if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN))
+		memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN);
 	else
-		memcpy(eh->h_source, port->ctlr.data_src_addr, ETH_ALEN);
+		memcpy(eh->h_source, fcoe->ctlr.data_src_addr, ETH_ALEN);
 
 	hp = (struct fcoe_hdr *)(eh + 1);
 	memset(hp, 0, sizeof(*hp));
@@ -1382,8 +1375,8 @@ int fcoe_percpu_receive_thread(void *arg)
 			}
 			fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
 		}
-		if (unlikely(port->ctlr.flogi_oxid != FC_XID_UNKNOWN) &&
-		    fcoe_ctlr_recv_flogi(&port->ctlr, fp, mac)) {
+		if (unlikely(port->fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN) &&
+		    fcoe_ctlr_recv_flogi(&port->fcoe->ctlr, fp, mac)) {
 			fc_frame_free(fp);
 			continue;
 		}
@@ -1482,7 +1475,6 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 	struct fc_lport *lp = NULL;
 	struct net_device *netdev = ptr;
 	struct fcoe_interface *fcoe;
-	struct fcoe_port *port = NULL;
 	struct fcoe_dev_stats *stats;
 	u32 link_possible = 1;
 	u32 mfs;
@@ -1490,9 +1482,8 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 
 	read_lock(&fcoe_hostlist_lock);
 	list_for_each_entry(fcoe, &fcoe_hostlist, list) {
-		port = fcoe->priv;
 		if (fcoe->netdev == netdev) {
-			lp = port->ctlr.lp;
+			lp = fcoe->ctlr.lp;
 			break;
 		}
 	}
@@ -1523,8 +1514,8 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 				"from netdev netlink\n", event);
 	}
 	if (link_possible && !fcoe_link_ok(lp))
-		fcoe_ctlr_link_up(&port->ctlr);
-	else if (fcoe_ctlr_link_down(&port->ctlr)) {
+		fcoe_ctlr_link_up(&fcoe->ctlr);
+	else if (fcoe_ctlr_link_down(&fcoe->ctlr)) {
 		stats = fc_lport_get_stats(lp);
 		stats->LinkFailureCount++;
 		fcoe_clean_pending_queue(lp);
@@ -1841,7 +1832,7 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
 	fcoe = fcoe_hostlist_lookup_port(netdev);
 	read_unlock(&fcoe_hostlist_lock);
 
-	return (fcoe) ? fcoe->priv->ctlr.lp : NULL;
+	return (fcoe) ? fcoe->ctlr.lp : NULL;
 }
 
 /**
@@ -1941,7 +1932,7 @@ static void __exit fcoe_exit(void)
 
 	/* releases the associated fcoe hosts */
 	list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list)
-		fcoe_if_destroy(fcoe->priv->ctlr.lp);
+		fcoe_if_destroy(fcoe->ctlr.lp);
 
 	unregister_hotcpu_notifier(&fcoe_cpu_notifier);
 
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 685aa9d..5b190b5 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -85,6 +85,7 @@ struct fcoe_interface {
 	struct net_device *netdev;
 	struct packet_type  fcoe_packet_type;
 	struct packet_type  fip_packet_type;
+	struct fcoe_ctlr ctlr;
 };
 
 /*
@@ -97,10 +98,9 @@ struct fcoe_port {
 	struct sk_buff_head fcoe_pending_queue;
 	u8	fcoe_pending_queue_active;
 	struct timer_list timer;		/* queue timer */
-	struct fcoe_ctlr ctlr;
 };
 
-#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_port, ctlr)
+#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr)
 
 static inline struct net_device *fcoe_netdev(const struct fc_lport *lp)
 {


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 16/64] fcoe: move offload exchange manager pointer from fcoe_port to fcoe_interface
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (14 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 15/64] fcoe: move FIP controller " Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 20:59 ` [PATCH 17/64] fcoe: remove fcoe_interface->priv pointer Robert Love
                   ` (47 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

The offload EM pointer is only used when setting up a new libfc instance, but
as it's designed to be shared among NPIV VN_Ports it should be tracked in
fcoe_interface.

With the host-list changed to track fcoe_interfaces as well, this is needed
before we can remove the priv pointer from that structure (which is only there
to help in the transition, and stops making sense once NPIV is enabled).

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   14 ++++++--------
 drivers/scsi/fcoe/fcoe.h |    2 +-
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 01519c7..bb59a7a 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -438,7 +438,6 @@ bool fcoe_oem_match(struct fc_frame *fp)
 static inline int fcoe_em_config(struct fc_lport *lp)
 {
 	struct fcoe_port *port = lport_priv(lp);
-	struct fcoe_port *oldport = NULL;
 	struct fcoe_interface *fcoe = port->fcoe;
 	struct fcoe_interface *oldfcoe = NULL;
 	struct net_device *old_real_dev, *cur_real_dev;
@@ -464,30 +463,29 @@ static inline int fcoe_em_config(struct fc_lport *lp)
 		cur_real_dev = fcoe->netdev;
 
 	list_for_each_entry(oldfcoe, &fcoe_hostlist, list) {
-		oldport = oldfcoe->priv;
 		if (oldfcoe->netdev->priv_flags & IFF_802_1Q_VLAN)
 			old_real_dev = vlan_dev_real_dev(oldfcoe->netdev);
 		else
 			old_real_dev = oldfcoe->netdev;
 
 		if (cur_real_dev == old_real_dev) {
-			port->oem = oldport->oem;
+			fcoe->oem = oldfcoe->oem;
 			break;
 		}
 	}
 
-	if (port->oem) {
-		if (!fc_exch_mgr_add(lp, port->oem, fcoe_oem_match)) {
+	if (fcoe->oem) {
+		if (!fc_exch_mgr_add(lp, fcoe->oem, fcoe_oem_match)) {
 			printk(KERN_ERR "fcoe_em_config: failed to add "
 			       "offload em:%p on interface:%s\n",
-			       port->oem, fcoe->netdev->name);
+			       fcoe->oem, fcoe->netdev->name);
 			return -ENOMEM;
 		}
 	} else {
-		port->oem = fc_exch_mgr_alloc(lp, FC_CLASS_3,
+		fcoe->oem = fc_exch_mgr_alloc(lp, FC_CLASS_3,
 					    FCOE_MIN_XID, lp->lro_xid,
 					    fcoe_oem_match);
-		if (!port->oem) {
+		if (!fcoe->oem) {
 			printk(KERN_ERR "fcoe_em_config: failed to allocate "
 			       "em for offload exches on interface:%s\n",
 			       fcoe->netdev->name);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 5b190b5..26e8595 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -86,6 +86,7 @@ struct fcoe_interface {
 	struct packet_type  fcoe_packet_type;
 	struct packet_type  fip_packet_type;
 	struct fcoe_ctlr ctlr;
+	struct fc_exch_mgr *oem;		/* offload exchange manager */
 };
 
 /*
@@ -94,7 +95,6 @@ struct fcoe_interface {
  */
 struct fcoe_port {
 	struct fcoe_interface *fcoe;
-	struct fc_exch_mgr *oem;		/* offload exchange manger */
 	struct sk_buff_head fcoe_pending_queue;
 	u8	fcoe_pending_queue_active;
 	struct timer_list timer;		/* queue timer */


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 17/64] fcoe: remove fcoe_interface->priv pointer
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (15 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 16/64] fcoe: move offload exchange manager pointer " Robert Love
@ 2009-08-25 20:59 ` Robert Love
  2009-08-25 21:00 ` [PATCH 18/64] fcoe: fcoe_interface create, destroy and refcounting Robert Love
                   ` (46 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 20:59 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

The priv pointer is no longer needed, and once NPIV is enabled
fcoe_interface:fc_lport becomes a one-to-many relationship.

Remove the single pointer.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |    2 --
 drivers/scsi/fcoe/fcoe.h |    3 ---
 2 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index bb59a7a..7f14c63 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -640,9 +640,7 @@ static struct fc_lport *fcoe_if_create(struct net_device *netdev,
 	}
 	lport = shost_priv(shost);
 	port = lport_priv(lport);
-
 	port->fcoe = fcoe;
-	fcoe->priv = port;
 
 	/* configure fc_lport, e.g., em */
 	rc = fcoe_lport_config(lport);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 26e8595..673e70e 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -79,9 +79,6 @@ struct fcoe_percpu_s {
  */
 struct fcoe_interface {
 	struct list_head list;
-	/* This will be removed once all the shared values are
-	 * moved out of fcoe_port */
-	struct fcoe_port *priv;
 	struct net_device *netdev;
 	struct packet_type  fcoe_packet_type;
 	struct packet_type  fip_packet_type;


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 18/64] fcoe: fcoe_interface create, destroy and refcounting
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (16 preceding siblings ...)
  2009-08-25 20:59 ` [PATCH 17/64] fcoe: remove fcoe_interface->priv pointer Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 19/64] fcoe: split out per interface setup Robert Love
                   ` (45 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

Up to this point the fcoe_instance structure was simply kzalloc/kfreed.  This
patch introduces create and destroy functions as well as kref based reference
counting.  The create function will grow as the initialization code is moved
there.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   97 +++++++++++++++++++++++++++++++++++++---------
 drivers/scsi/fcoe/fcoe.h |    1 
 2 files changed, 79 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 7f14c63..d1d6b3b 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -139,6 +139,58 @@ static struct scsi_host_template fcoe_shost_template = {
 };
 
 /**
+ * fcoe_interface_create()
+ * @netdev: network interface
+ *
+ * Returns: pointer to a struct fcoe_interface or NULL on error
+ */
+static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
+{
+	struct fcoe_interface *fcoe;
+
+	fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL);
+	if (!fcoe) {
+		FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n");
+		return NULL;
+	}
+
+	kref_init(&fcoe->kref);
+	fcoe->netdev = netdev;
+
+	return fcoe;
+}
+
+/**
+ * fcoe_interface_release() - fcoe_port kref release function
+ * @kref: embedded reference count in an fcoe_interface struct
+ */
+static void fcoe_interface_release(struct kref *kref)
+{
+	struct fcoe_interface *fcoe;
+
+	fcoe = container_of(kref, struct fcoe_interface, kref);
+	kfree(fcoe);
+}
+
+/**
+ * fcoe_interface_get()
+ * @fcoe:
+ */
+static inline void fcoe_interface_get(struct fcoe_interface *fcoe)
+{
+	kref_get(&fcoe->kref);
+}
+
+/**
+ * fcoe_interface_put()
+ * @fcoe:
+ */
+static inline void fcoe_interface_put(struct fcoe_interface *fcoe)
+{
+	kref_put(&fcoe->kref, fcoe_interface_release);
+}
+
+/**
  * fcoe_fip_recv - handle a received FIP frame.
  * @skb: the receive skb
  * @dev: associated &net_device
@@ -558,7 +610,7 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 	/* Release the net_device and Scsi_Host */
 	dev_put(netdev);
 	scsi_host_put(lport->host);
-	kfree(fcoe);		/* TODO, should be refcounted */
+	fcoe_interface_put(fcoe);
 }
 
 /*
@@ -604,8 +656,8 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
 };
 
 /**
- * fcoe_if_create() - this function creates the fcoe interface
- * @netdev: pointer the associated netdevice
+ * fcoe_if_create() - this function creates the fcoe port
+ * @fcoe: fcoe_interface structure to create an fc_lport instance on
  * @parent: device pointer to be the parent in sysfs for the SCSI host
  *
  * Creates fc_lport struct and scsi_host for lport, configures lport
@@ -613,30 +665,23 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
  *
  * Returns : The allocated fc_lport or an error pointer
  */
-static struct fc_lport *fcoe_if_create(struct net_device *netdev,
+static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 				       struct device *parent)
 {
 	int rc;
 	struct fc_lport *lport = NULL;
 	struct fcoe_port *port;
-	struct fcoe_interface *fcoe;
 	struct Scsi_Host *shost;
+	struct net_device *netdev = fcoe->netdev;
 
 	FCOE_NETDEV_DBG(netdev, "Create Interface\n");
 
-	fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL);
-	if (!fcoe) {
-		FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n");
-		rc = -ENOMEM;
-		goto out;
-	}
-
 	shost = libfc_host_alloc(&fcoe_shost_template,
 				 sizeof(struct fcoe_port));
 	if (!shost) {
 		FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n");
 		rc = -ENOMEM;
-		goto out_kfree_port;
+		goto out;
 	}
 	lport = shost_priv(shost);
 	port = lport_priv(lport);
@@ -708,7 +753,7 @@ static struct fc_lport *fcoe_if_create(struct net_device *netdev,
 		fcoe_ctlr_link_up(&fcoe->ctlr);
 
 	dev_hold(netdev);
-
+	fcoe_interface_get(fcoe);
 	return lport;
 
 out_lp_destroy:
@@ -717,8 +762,6 @@ out_netdev_cleanup:
 	fcoe_netdev_cleanup(port);
 out_host_put:
 	scsi_host_put(lport->host);
-out_kfree_port:
-	kfree(fcoe);
 out:
 	return ERR_PTR(rc);
 }
@@ -1620,6 +1663,8 @@ static int fcoe_ethdrv_put(const struct net_device *netdev)
 static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 {
 	struct net_device *netdev;
+	struct fcoe_interface *fcoe;
+	struct fcoe_port *port;
 	struct fc_lport *lport;
 	int rc;
 
@@ -1634,6 +1679,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 		rc = -ENODEV;
 		goto out_putdev;
 	}
+	port = lport_priv(lport);
+	fcoe = port->fcoe;
 	fcoe_if_destroy(lport);
 	fcoe_ethdrv_put(netdev);
 	rc = 0;
@@ -1653,6 +1700,7 @@ out_nodev:
 static int fcoe_create(const char *buffer, struct kernel_param *kp)
 {
 	int rc;
+	struct fcoe_interface *fcoe;
 	struct fc_lport *lport;
 	struct net_device *netdev;
 
@@ -1668,15 +1716,26 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 	}
 	fcoe_ethdrv_get(netdev);
 
-	lport = fcoe_if_create(netdev, &netdev->dev);
+	fcoe = fcoe_interface_create(netdev);
+	if (!fcoe) {
+		rc = -ENOMEM;
+		goto out_putdev;
+	}
+
+	lport = fcoe_if_create(fcoe, &netdev->dev);
 	if (IS_ERR(lport)) {
 		printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
 		       netdev->name);
 		fcoe_ethdrv_put(netdev);
 		rc = -EIO;
-		goto out_putdev;
+		goto out_free;
 	}
-	rc = 0;
+
+	dev_put(netdev);
+	return 0;
+
+out_free:
+	fcoe_interface_put(fcoe);
 out_putdev:
 	dev_put(netdev);
 out_nodev:
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 673e70e..ff22928 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -84,6 +84,7 @@ struct fcoe_interface {
 	struct packet_type  fip_packet_type;
 	struct fcoe_ctlr ctlr;
 	struct fc_exch_mgr *oem;		/* offload exchange manager */
+	struct kref kref;
 };
 
 /*


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 19/64] fcoe: split out per interface setup
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (17 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 18/64] fcoe: fcoe_interface create, destroy and refcounting Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 20/64] fcoe: add mutex to protect create and destroy Robert Love
                   ` (44 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

fcoe_netdev_config() is called during initialization of a libfc instance.
Much of what was there only needs to be done once for each net_device.
The same goes for the corresponding cleanup.

The FIP controller initialization is moved to interface creation time.
Otherwise it will keep getting re-initialized for every VN_Port once NPIV is
enabled.

fcoe_if_destroy() has some reordering to deal with the changes.  Receives are
not stopped until after fcoe_interface_put() is called, but transmits must be
stopped before.  So there is some care to stop libfc transmits and the
transmit backlog timer, then call fcoe_interface_put which will stop receives
and cleanup the FIP controller, then the receive queues can be cleaned and the
port freed.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |  267 +++++++++++++++++++++++++---------------------
 1 files changed, 148 insertions(+), 119 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index d1d6b3b..63aeeca 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -138,6 +138,82 @@ static struct scsi_host_template fcoe_shost_template = {
 	.max_sectors = 0xffff,
 };
 
+static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
+			 struct packet_type *ptype,
+			 struct net_device *orig_dev);
+/**
+ * fcoe_interface_setup()
+ * @fcoe: new fcoe_interface
+ * @netdev : ptr to the associated netdevice struct
+ *
+ * Returns : 0 for success
+ */
+static int fcoe_interface_setup(struct fcoe_interface *fcoe,
+				struct net_device *netdev)
+{
+	struct fcoe_ctlr *fip = &fcoe->ctlr;
+	struct netdev_hw_addr *ha;
+	u8 flogi_maddr[ETH_ALEN];
+
+	fcoe->netdev = netdev;
+
+	/* Do not support for bonding device */
+	if ((netdev->priv_flags & IFF_MASTER_ALB) ||
+	    (netdev->priv_flags & IFF_SLAVE_INACTIVE) ||
+	    (netdev->priv_flags & IFF_MASTER_8023AD)) {
+		return -EOPNOTSUPP;
+	}
+
+	/* look for SAN MAC address, if multiple SAN MACs exist, only
+	 * use the first one for SPMA */
+	rcu_read_lock();
+	for_each_dev_addr(netdev, ha) {
+		if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
+		    (is_valid_ether_addr(fip->ctl_src_addr))) {
+			memcpy(fip->ctl_src_addr, ha->addr, ETH_ALEN);
+			fip->spma = 1;
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	/* setup Source Mac Address */
+	if (!fip->spma)
+		memcpy(fip->ctl_src_addr, netdev->dev_addr, netdev->addr_len);
+
+	/*
+	 * Add FCoE MAC address as second unicast MAC address
+	 * or enter promiscuous mode if not capable of listening
+	 * for multiple unicast MACs.
+	 */
+	rtnl_lock();
+	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
+	dev_unicast_add(netdev, flogi_maddr);
+	if (fip->spma)
+		dev_unicast_add(netdev, fip->ctl_src_addr);
+	dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
+	rtnl_unlock();
+
+	/*
+	 * setup the receive function from ethernet driver
+	 * on the ethertype for the given device
+	 */
+	fcoe->fcoe_packet_type.func = fcoe_rcv;
+	fcoe->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
+	fcoe->fcoe_packet_type.dev = netdev;
+	dev_add_pack(&fcoe->fcoe_packet_type);
+
+	fcoe->fip_packet_type.func = fcoe_fip_recv;
+	fcoe->fip_packet_type.type = htons(ETH_P_FIP);
+	fcoe->fip_packet_type.dev = netdev;
+	dev_add_pack(&fcoe->fip_packet_type);
+
+	return 0;
+}
+
+static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb);
+static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new);
+
 /**
  * fcoe_interface_create()
  * @netdev: network interface
@@ -155,12 +231,55 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
 	}
 
 	kref_init(&fcoe->kref);
-	fcoe->netdev = netdev;
+
+	/*
+	 * Initialize FIP.
+	 */
+	fcoe_ctlr_init(&fcoe->ctlr);
+	fcoe->ctlr.send = fcoe_fip_send;
+	fcoe->ctlr.update_mac = fcoe_update_src_mac;
+
+	fcoe_interface_setup(fcoe, netdev);
 
 	return fcoe;
 }
 
 /**
+ * fcoe_interface_cleanup() - clean up netdev configurations
+ * @fcoe:
+ */
+void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
+{
+	struct net_device *netdev = fcoe->netdev;
+	struct fcoe_ctlr *fip = &fcoe->ctlr;
+	u8 flogi_maddr[ETH_ALEN];
+
+	/*
+	 * Don't listen for Ethernet packets anymore.
+	 * synchronize_net() ensures that the packet handlers are not running
+	 * on another CPU. dev_remove_pack() would do that, this calls the
+	 * unsyncronized version __dev_remove_pack() to avoid multiple delays.
+	 */
+	__dev_remove_pack(&fcoe->fcoe_packet_type);
+	__dev_remove_pack(&fcoe->fip_packet_type);
+	synchronize_net();
+
+	/* tear-down the FCoE controller */
+	fcoe_ctlr_destroy(&fcoe->ctlr);
+
+	/* Delete secondary MAC addresses */
+	rtnl_lock();
+	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
+	dev_unicast_delete(netdev, flogi_maddr);
+	if (!is_zero_ether_addr(fip->data_src_addr))
+		dev_unicast_delete(netdev, fip->data_src_addr);
+	if (fip->spma)
+		dev_unicast_delete(netdev, fip->ctl_src_addr);
+	dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
+	rtnl_unlock();
+}
+
+/**
  * fcoe_interface_release() - fcoe_port kref release function
  * @kref: embedded reference count in an fcoe_interface struct
  */
@@ -169,6 +288,7 @@ static void fcoe_interface_release(struct kref *kref)
 	struct fcoe_interface *fcoe;
 
 	fcoe = container_of(kref, struct fcoe_interface, kref);
+	fcoe_interface_cleanup(fcoe);
 	kfree(fcoe);
 }
 
@@ -275,31 +395,6 @@ static int fcoe_lport_config(struct fc_lport *lp)
 }
 
 /**
- * fcoe_netdev_cleanup() - clean up netdev configurations
- * @port: ptr to the fcoe_port
- */
-void fcoe_netdev_cleanup(struct fcoe_port *port)
-{
-	u8 flogi_maddr[ETH_ALEN];
-	struct fcoe_interface *fcoe = port->fcoe;
-
-	/* Don't listen for Ethernet packets anymore */
-	dev_remove_pack(&fcoe->fcoe_packet_type);
-	dev_remove_pack(&fcoe->fip_packet_type);
-
-	/* Delete secondary MAC addresses */
-	rtnl_lock();
-	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
-	dev_unicast_delete(fcoe->netdev, flogi_maddr);
-	if (!is_zero_ether_addr(fcoe->ctlr.data_src_addr))
-		dev_unicast_delete(fcoe->netdev, fcoe->ctlr.data_src_addr);
-	if (fcoe->ctlr.spma)
-		dev_unicast_delete(fcoe->netdev, fcoe->ctlr.ctl_src_addr);
-	dev_mc_delete(fcoe->netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
-	rtnl_unlock();
-}
-
-/**
  * fcoe_queue_timer() - fcoe queue timer
  * @lp: the fc_lport pointer
  *
@@ -326,21 +421,10 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 	u64 wwnn, wwpn;
 	struct fcoe_interface *fcoe;
 	struct fcoe_port *port;
-	u8 flogi_maddr[ETH_ALEN];
-	struct netdev_hw_addr *ha;
 
 	/* Setup lport private data to point to fcoe softc */
 	port = lport_priv(lp);
 	fcoe = port->fcoe;
-	fcoe->ctlr.lp = lp;
-	fcoe->netdev = netdev;
-
-	/* Do not support for bonding device */
-	if ((netdev->priv_flags & IFF_MASTER_ALB) ||
-	    (netdev->priv_flags & IFF_SLAVE_INACTIVE) ||
-	    (netdev->priv_flags & IFF_MASTER_8023AD)) {
-		return -EOPNOTSUPP;
-	}
 
 	/*
 	 * Determine max frame size based on underlying device and optional
@@ -376,57 +460,12 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
 	port->fcoe_pending_queue_active = 0;
 	setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lp);
 
-	/* look for SAN MAC address, if multiple SAN MACs exist, only
-	 * use the first one for SPMA */
-	rcu_read_lock();
-	for_each_dev_addr(netdev, ha) {
-		if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
-		    (is_valid_ether_addr(fcoe->ctlr.ctl_src_addr))) {
-			memcpy(fcoe->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
-			fcoe->ctlr.spma = 1;
-			break;
-		}
-	}
-	rcu_read_unlock();
-
-	/* setup Source Mac Address */
-	if (!fcoe->ctlr.spma)
-		memcpy(fcoe->ctlr.ctl_src_addr, netdev->dev_addr,
-		       netdev->addr_len);
-
 	wwnn = fcoe_wwn_from_mac(netdev->dev_addr, 1, 0);
 	fc_set_wwnn(lp, wwnn);
 	/* XXX - 3rd arg needs to be vlan id */
 	wwpn = fcoe_wwn_from_mac(netdev->dev_addr, 2, 0);
 	fc_set_wwpn(lp, wwpn);
 
-	/*
-	 * Add FCoE MAC address as second unicast MAC address
-	 * or enter promiscuous mode if not capable of listening
-	 * for multiple unicast MACs.
-	 */
-	rtnl_lock();
-	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
-	dev_unicast_add(netdev, flogi_maddr);
-	if (fcoe->ctlr.spma)
-		dev_unicast_add(netdev, fcoe->ctlr.ctl_src_addr);
-	dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
-	rtnl_unlock();
-
-	/*
-	 * setup the receive function from ethernet driver
-	 * on the ethertype for the given device
-	 */
-	fcoe->fcoe_packet_type.func = fcoe_rcv;
-	fcoe->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
-	fcoe->fcoe_packet_type.dev = netdev;
-	dev_add_pack(&fcoe->fcoe_packet_type);
-
-	fcoe->fip_packet_type.func = fcoe_fip_recv;
-	fcoe->fip_packet_type.type = htons(ETH_P_FIP);
-	fcoe->fip_packet_type.dev = netdev;
-	dev_add_pack(&fcoe->fip_packet_type);
-
 	return 0;
 }
 
@@ -578,19 +617,22 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 	/* Remove the instance from fcoe's list */
 	fcoe_hostlist_remove(lport);
 
-	/* clean up netdev configurations */
-	fcoe_netdev_cleanup(port);
+	/* Cleanup the fc_lport */
+	fc_lport_destroy(lport);
+	fc_fcp_destroy(lport);
+
+	/* Stop the transmit retry timer */
+	del_timer_sync(&port->timer);
 
-	/* tear-down the FCoE controller */
-	fcoe_ctlr_destroy(&fcoe->ctlr);
+	/* Free existing transmit skbs */
+	fcoe_clean_pending_queue(lport);
+
+	/* receives may not be stopped until after this */
+	fcoe_interface_put(fcoe);
 
 	/* Free queued packets for the per-CPU receive threads */
 	fcoe_percpu_clean(lport);
 
-	/* Cleanup the fc_lport */
-	fc_lport_destroy(lport);
-	fc_fcp_destroy(lport);
-
 	/* Detach from the scsi-ml */
 	fc_remove_host(lport->host);
 	scsi_remove_host(lport->host);
@@ -598,19 +640,12 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 	/* There are no more rports or I/O, free the EM */
 	fc_exch_mgr_free(lport);
 
-	/* Free existing skbs */
-	fcoe_clean_pending_queue(lport);
-
-	/* Stop the timer */
-	del_timer_sync(&port->timer);
-
 	/* Free memory used by statistical counters */
 	fc_lport_free_stats(lport);
 
 	/* Release the net_device and Scsi_Host */
 	dev_put(netdev);
 	scsi_host_put(lport->host);
-	fcoe_interface_put(fcoe);
 }
 
 /*
@@ -660,8 +695,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
  * @fcoe: fcoe_interface structure to create an fc_lport instance on
  * @parent: device pointer to be the parent in sysfs for the SCSI host
  *
- * Creates fc_lport struct and scsi_host for lport, configures lport
- * and starts fabric login.
+ * Creates fc_lport struct and scsi_host for lport, configures lport.
  *
  * Returns : The allocated fc_lport or an error pointer
  */
@@ -695,19 +729,12 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 		goto out_host_put;
 	}
 
-	/*
-	 * Initialize FIP.
-	 */
-	fcoe_ctlr_init(&fcoe->ctlr);
-	fcoe->ctlr.send = fcoe_fip_send;
-	fcoe->ctlr.update_mac = fcoe_update_src_mac;
-
 	/* configure lport network properties */
 	rc = fcoe_netdev_config(lport, netdev);
 	if (rc) {
 		FCOE_NETDEV_DBG(netdev, "Could not configure netdev for the "
 				"interface\n");
-		goto out_netdev_cleanup;
+		goto out_lp_destroy;
 	}
 
 	/* configure lport scsi host properties */
@@ -715,7 +742,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 	if (rc) {
 		FCOE_NETDEV_DBG(netdev, "Could not configure shost for the "
 				"interface\n");
-		goto out_netdev_cleanup;
+		goto out_lp_destroy;
 	}
 
 	/* Initialize the library */
@@ -745,21 +772,12 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 	fcoe_hostlist_add(lport);
 	write_unlock(&fcoe_hostlist_lock);
 
-	lport->boot_time = jiffies;
-
-	fc_fabric_login(lport);
-
-	if (!fcoe_link_ok(lport))
-		fcoe_ctlr_link_up(&fcoe->ctlr);
-
 	dev_hold(netdev);
 	fcoe_interface_get(fcoe);
 	return lport;
 
 out_lp_destroy:
 	fc_exch_mgr_free(lport);
-out_netdev_cleanup:
-	fcoe_netdev_cleanup(port);
 out_host_put:
 	scsi_host_put(lport->host);
 out:
@@ -1731,10 +1749,21 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 		goto out_free;
 	}
 
-	dev_put(netdev);
-	return 0;
+	/* Make this the "master" N_Port */
+	fcoe->ctlr.lp = lport;
+
+	/* start FIP Discovery and FLOGI */
+	lport->boot_time = jiffies;
+	fc_fabric_login(lport);
+	if (!fcoe_link_ok(lport))
+		fcoe_ctlr_link_up(&fcoe->ctlr);
 
+	rc = 0;
 out_free:
+	/*
+	 * Release from init in fcoe_interface_create(), on success lport
+	 * should be holding a reference taken in fcoe_if_create().
+	 */
 	fcoe_interface_put(fcoe);
 out_putdev:
 	dev_put(netdev);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 20/64] fcoe: add mutex to protect create and destroy
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (18 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 19/64] fcoe: split out per interface setup Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 21/64] fcoe: move the host-list add/remove to keep out VN_Ports Robert Love
                   ` (43 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

Rather than rely on the hostlist_lock to be held while creating exchange
managers, serialize fcoe instance creation and destruction with a mutex.
This will allow the hostlist addition to be moved out of fcoe_if_create(),
which will simplify NPIV support.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   40 +++++++++++++++++++++++++++++++++++++++-
 1 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 63aeeca..43added 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -55,6 +55,8 @@ module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for "	\
 		 "Direct Data Placement (DDP).");
 
+DEFINE_MUTEX(fcoe_config_mutex);
+
 /* fcoe host list */
 LIST_HEAD(fcoe_hostlist);
 DEFINE_RWLOCK(fcoe_hostlist_lock);
@@ -811,6 +813,7 @@ static int __init fcoe_if_init(void)
 int __exit fcoe_if_exit(void)
 {
 	fc_release_transport(scsi_transport_fcoe_sw);
+	scsi_transport_fcoe_sw = NULL;
 	return 0;
 }
 
@@ -1686,6 +1689,19 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 	struct fc_lport *lport;
 	int rc;
 
+	mutex_lock(&fcoe_config_mutex);
+#ifdef CONFIG_FCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module paramter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+		rc = -ENODEV;
+		goto out_nodev;
+	}
+#endif
+
 	netdev = fcoe_if_to_netdev(buffer);
 	if (!netdev) {
 		rc = -ENODEV;
@@ -1705,6 +1721,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 out_putdev:
 	dev_put(netdev);
 out_nodev:
+	mutex_unlock(&fcoe_config_mutex);
 	return rc;
 }
 
@@ -1722,6 +1739,19 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 	struct fc_lport *lport;
 	struct net_device *netdev;
 
+	mutex_lock(&fcoe_config_mutex);
+#ifdef CONFIG_FCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module paramter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+		rc = -ENODEV;
+		goto out_nodev;
+	}
+#endif
+
 	netdev = fcoe_if_to_netdev(buffer);
 	if (!netdev) {
 		rc = -ENODEV;
@@ -1768,6 +1798,7 @@ out_free:
 out_putdev:
 	dev_put(netdev);
 out_nodev:
+	mutex_unlock(&fcoe_config_mutex);
 	return rc;
 }
 
@@ -1971,6 +2002,8 @@ static int __init fcoe_init(void)
 	int rc = 0;
 	struct fcoe_percpu_s *p;
 
+	mutex_lock(&fcoe_config_mutex);
+
 	for_each_possible_cpu(cpu) {
 		p = &per_cpu(fcoe_percpu, cpu);
 		skb_queue_head_init(&p->fcoe_rx_list);
@@ -1991,13 +2024,14 @@ static int __init fcoe_init(void)
 	if (rc)
 		goto out_free;
 
+	mutex_unlock(&fcoe_config_mutex);
 	return 0;
 
 out_free:
 	for_each_online_cpu(cpu) {
 		fcoe_percpu_thread_destroy(cpu);
 	}
-
+	mutex_unlock(&fcoe_config_mutex);
 	return rc;
 }
 module_init(fcoe_init);
@@ -2012,6 +2046,8 @@ static void __exit fcoe_exit(void)
 	unsigned int cpu;
 	struct fcoe_interface *fcoe, *tmp;
 
+	mutex_lock(&fcoe_config_mutex);
+
 	fcoe_dev_cleanup();
 
 	/* releases the associated fcoe hosts */
@@ -2025,5 +2061,7 @@ static void __exit fcoe_exit(void)
 
 	/* detach from scsi transport */
 	fcoe_if_exit();
+
+	mutex_unlock(&fcoe_config_mutex);
 }
 module_exit(fcoe_exit);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 21/64] fcoe: move the host-list add/remove to keep out VN_Ports
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (19 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 20/64] fcoe: add mutex to protect create and destroy Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 22/64] fcoe: Fix module ref count bug by adding NETDEV UNREGISTER handling Robert Love
                   ` (42 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

We only want the FCoE create and destroy routines to deal with top level
N_Ports, the VN_Ports are tracked on the vport list (see scsi_transport_fc).

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   31 +++++++++++++++++++------------
 1 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 43added..c9a0346 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -616,9 +616,6 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 	/* Logout of the fabric */
 	fc_fabric_logoff(lport);
 
-	/* Remove the instance from fcoe's list */
-	fcoe_hostlist_remove(lport);
-
 	/* Cleanup the fc_lport */
 	fc_lport_destroy(lport);
 	fc_fcp_destroy(lport);
@@ -757,11 +754,13 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 
 	/*
 	 * fcoe_em_alloc() and fcoe_hostlist_add() both
-	 * need to be atomic under fcoe_hostlist_lock
+	 * need to be atomic with respect to other changes to the hostlist
 	 * since fcoe_em_alloc() looks for an existing EM
 	 * instance on host list updated by fcoe_hostlist_add().
+	 *
+	 * This is currently handled through the fcoe_config_mutex begin held.
 	 */
-	write_lock(&fcoe_hostlist_lock);
+
 	/* lport exch manager allocation */
 	rc = fcoe_em_config(lport);
 	if (rc) {
@@ -770,10 +769,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 		goto out_lp_destroy;
 	}
 
-	/* add to lports list */
-	fcoe_hostlist_add(lport);
-	write_unlock(&fcoe_hostlist_lock);
-
 	dev_hold(netdev);
 	fcoe_interface_get(fcoe);
 	return lport;
@@ -1713,6 +1708,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 		rc = -ENODEV;
 		goto out_putdev;
 	}
+	/* Remove the instance from fcoe's list */
+	fcoe_hostlist_remove(lport);
 	port = lport_priv(lport);
 	fcoe = port->fcoe;
 	fcoe_if_destroy(lport);
@@ -1782,6 +1779,9 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 	/* Make this the "master" N_Port */
 	fcoe->ctlr.lp = lport;
 
+	/* add to lports list */
+	fcoe_hostlist_add(lport);
+
 	/* start FIP Discovery and FLOGI */
 	lport->boot_time = jiffies;
 	fc_fabric_login(lport);
@@ -1954,8 +1954,6 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
  * fcoe_hostlist_add() - Add a lport to lports list
  * @lp: ptr to the fc_lport to be added
  *
- * Called with write fcoe_hostlist_lock held.
- *
  * Returns: 0 for success
  */
 int fcoe_hostlist_add(const struct fc_lport *lport)
@@ -1963,12 +1961,14 @@ int fcoe_hostlist_add(const struct fc_lport *lport)
 	struct fcoe_interface *fcoe;
 	struct fcoe_port *port;
 
+	write_lock_bh(&fcoe_hostlist_lock);
 	fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
 	if (!fcoe) {
 		port = lport_priv(lport);
 		fcoe = port->fcoe;
 		list_add_tail(&fcoe->list, &fcoe_hostlist);
 	}
+	write_unlock_bh(&fcoe_hostlist_lock);
 	return 0;
 }
 
@@ -2045,14 +2045,21 @@ static void __exit fcoe_exit(void)
 {
 	unsigned int cpu;
 	struct fcoe_interface *fcoe, *tmp;
+	LIST_HEAD(local_list);
 
 	mutex_lock(&fcoe_config_mutex);
 
 	fcoe_dev_cleanup();
 
 	/* releases the associated fcoe hosts */
-	list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list)
+	write_lock_bh(&fcoe_hostlist_lock);
+	list_splice_init(&fcoe_hostlist, &local_list);
+	write_unlock_bh(&fcoe_hostlist_lock);
+
+	list_for_each_entry_safe(fcoe, tmp, &local_list, list) {
+		list_del(&fcoe->list);
 		fcoe_if_destroy(fcoe->ctlr.lp);
+	}
 
 	unregister_hotcpu_notifier(&fcoe_cpu_notifier);
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 22/64] fcoe: Fix module ref count bug by adding NETDEV UNREGISTER handling
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (20 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 21/64] fcoe: move the host-list add/remove to keep out VN_Ports Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 23/64] fcoe: use rtnl mutex in place of hostlist lock Robert Love
                   ` (41 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

Fixes reference counting on fcoe_instance and net_device, and adds
NETDEV_UNREGISTER notifier handling so that you can unload network drivers.
FCoE no longer increments the module use count for the network driver.

On an NETDEV_UNREGISTER event, destroying the FCoE instance is deferred to a
workqueue context to avoid RTNL deadlocks.

Based in part by an earlier patch from John Fastabend

John's patch description:
Currently, the netdev module ref count is not decremented with module_put()
when the module is unloaded while fcoe instances are present. To fix this
removed reference count on netdev module completely and added functionality to
netdev event handling for NETDEV_UNREGISTER events.

This allows fcoe to remove devices cleanly when the netdev module is unloaded
so we no longer need to hold a reference count for the netdev module.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |  186 ++++++++++++++++------------------------------
 drivers/scsi/fcoe/fcoe.h |    2 
 2 files changed, 67 insertions(+), 121 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index c9a0346..c0264a9 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -74,12 +74,13 @@ static int fcoe_link_ok(struct fc_lport *lp);
 
 static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
 static int fcoe_hostlist_add(const struct fc_lport *);
-static int fcoe_hostlist_remove(const struct fc_lport *);
 
 static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *);
 static int fcoe_device_notification(struct notifier_block *, ulong, void *);
 static void fcoe_dev_setup(void);
 static void fcoe_dev_cleanup(void);
+static struct fcoe_interface *
+	fcoe_hostlist_lookup_port(const struct net_device *dev);
 
 /* notification function from net device */
 static struct notifier_block fcoe_notifier = {
@@ -149,6 +150,7 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
  * @netdev : ptr to the associated netdevice struct
  *
  * Returns : 0 for success
+ * Locking: must be called with the RTNL mutex held
  */
 static int fcoe_interface_setup(struct fcoe_interface *fcoe,
 				struct net_device *netdev)
@@ -188,13 +190,11 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
 	 * or enter promiscuous mode if not capable of listening
 	 * for multiple unicast MACs.
 	 */
-	rtnl_lock();
 	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
 	dev_unicast_add(netdev, flogi_maddr);
 	if (fip->spma)
 		dev_unicast_add(netdev, fip->ctl_src_addr);
 	dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
-	rtnl_unlock();
 
 	/*
 	 * setup the receive function from ethernet driver
@@ -215,6 +215,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
 
 static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb);
 static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new);
+static void fcoe_destroy_work(struct work_struct *work);
 
 /**
  * fcoe_interface_create()
@@ -232,6 +233,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
 		return NULL;
 	}
 
+	dev_hold(netdev);
 	kref_init(&fcoe->kref);
 
 	/*
@@ -249,6 +251,8 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
 /**
  * fcoe_interface_cleanup() - clean up netdev configurations
  * @fcoe:
+ *
+ * Caller must be holding the RTNL mutex
  */
 void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 {
@@ -266,11 +270,7 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 	__dev_remove_pack(&fcoe->fip_packet_type);
 	synchronize_net();
 
-	/* tear-down the FCoE controller */
-	fcoe_ctlr_destroy(&fcoe->ctlr);
-
 	/* Delete secondary MAC addresses */
-	rtnl_lock();
 	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
 	dev_unicast_delete(netdev, flogi_maddr);
 	if (!is_zero_ether_addr(fip->data_src_addr))
@@ -278,7 +278,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 	if (fip->spma)
 		dev_unicast_delete(netdev, fip->ctl_src_addr);
 	dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
-	rtnl_unlock();
 }
 
 /**
@@ -288,10 +287,14 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 static void fcoe_interface_release(struct kref *kref)
 {
 	struct fcoe_interface *fcoe;
+	struct net_device *netdev;
 
 	fcoe = container_of(kref, struct fcoe_interface, kref);
-	fcoe_interface_cleanup(fcoe);
+	netdev = fcoe->netdev;
+	/* tear-down the FCoE controller */
+	fcoe_ctlr_destroy(&fcoe->ctlr);
 	kfree(fcoe);
+	dev_put(netdev);
 }
 
 /**
@@ -642,8 +645,7 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 	/* Free memory used by statistical counters */
 	fc_lport_free_stats(lport);
 
-	/* Release the net_device and Scsi_Host */
-	dev_put(netdev);
+	/* Release the Scsi_Host */
 	scsi_host_put(lport->host);
 }
 
@@ -718,7 +720,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 	}
 	lport = shost_priv(shost);
 	port = lport_priv(lport);
+	port->lport = lport;
 	port->fcoe = fcoe;
+	INIT_WORK(&port->destroy_work, fcoe_destroy_work);
 
 	/* configure fc_lport, e.g., em */
 	rc = fcoe_lport_config(lport);
@@ -769,7 +773,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 		goto out_lp_destroy;
 	}
 
-	dev_hold(netdev);
 	fcoe_interface_get(fcoe);
 	return lport;
 
@@ -1530,19 +1533,19 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 	struct fc_lport *lp = NULL;
 	struct net_device *netdev = ptr;
 	struct fcoe_interface *fcoe;
+	struct fcoe_port *port;
 	struct fcoe_dev_stats *stats;
 	u32 link_possible = 1;
 	u32 mfs;
 	int rc = NOTIFY_OK;
 
-	read_lock(&fcoe_hostlist_lock);
+	write_lock(&fcoe_hostlist_lock);
 	list_for_each_entry(fcoe, &fcoe_hostlist, list) {
 		if (fcoe->netdev == netdev) {
 			lp = fcoe->ctlr.lp;
 			break;
 		}
 	}
-	read_unlock(&fcoe_hostlist_lock);
 	if (lp == NULL) {
 		rc = NOTIFY_DONE;
 		goto out;
@@ -1564,6 +1567,13 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 		break;
 	case NETDEV_REGISTER:
 		break;
+	case NETDEV_UNREGISTER:
+		list_del(&fcoe->list);
+		port = lport_priv(fcoe->ctlr.lp);
+		fcoe_interface_cleanup(fcoe);
+		schedule_work(&port->destroy_work);
+		goto out;
+		break;
 	default:
 		FCOE_NETDEV_DBG(netdev, "Unknown event %ld "
 				"from netdev netlink\n", event);
@@ -1576,6 +1586,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 		fcoe_clean_pending_queue(lp);
 	}
 out:
+	write_unlock(&fcoe_hostlist_lock);
 	return rc;
 }
 
@@ -1601,75 +1612,6 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
 }
 
 /**
- * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev
- * @netdev: the target netdev
- *
- * Returns: ptr to the struct module, NULL for failure
- */
-static struct module *
-fcoe_netdev_to_module_owner(const struct net_device *netdev)
-{
-	struct device *dev;
-
-	if (!netdev)
-		return NULL;
-
-	dev = netdev->dev.parent;
-	if (!dev)
-		return NULL;
-
-	if (!dev->driver)
-		return NULL;
-
-	return dev->driver->owner;
-}
-
-/**
- * fcoe_ethdrv_get() - Hold the Ethernet driver
- * @netdev: the target netdev
- *
- * Holds the Ethernet driver module by try_module_get() for
- * the corresponding netdev.
- *
- * Returns: 0 for success
- */
-static int fcoe_ethdrv_get(const struct net_device *netdev)
-{
-	struct module *owner;
-
-	owner = fcoe_netdev_to_module_owner(netdev);
-	if (owner) {
-		FCOE_NETDEV_DBG(netdev, "Hold driver module %s\n",
-				module_name(owner));
-		return  try_module_get(owner);
-	}
-	return -ENODEV;
-}
-
-/**
- * fcoe_ethdrv_put() - Release the Ethernet driver
- * @netdev: the target netdev
- *
- * Releases the Ethernet driver module by module_put for
- * the corresponding netdev.
- *
- * Returns: 0 for success
- */
-static int fcoe_ethdrv_put(const struct net_device *netdev)
-{
-	struct module *owner;
-
-	owner = fcoe_netdev_to_module_owner(netdev);
-	if (owner) {
-		FCOE_NETDEV_DBG(netdev, "Release driver module %s\n",
-				module_name(owner));
-		module_put(owner);
-		return 0;
-	}
-	return -ENODEV;
-}
-
-/**
  * fcoe_destroy() - handles the destroy from sysfs
  * @buffer: expected to be an eth if name
  * @kp: associated kernel param
@@ -1678,10 +1620,8 @@ static int fcoe_ethdrv_put(const struct net_device *netdev)
  */
 static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 {
-	struct net_device *netdev;
 	struct fcoe_interface *fcoe;
-	struct fcoe_port *port;
-	struct fc_lport *lport;
+	struct net_device *netdev;
 	int rc;
 
 	mutex_lock(&fcoe_config_mutex);
@@ -1702,19 +1642,20 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 		rc = -ENODEV;
 		goto out_nodev;
 	}
-	/* look for existing lport */
-	lport = fcoe_hostlist_lookup(netdev);
-	if (!lport) {
+
+	write_lock(&fcoe_hostlist_lock);
+	fcoe = fcoe_hostlist_lookup_port(netdev);
+	if (!fcoe) {
+		write_unlock(&fcoe_hostlist_lock);
 		rc = -ENODEV;
 		goto out_putdev;
 	}
-	/* Remove the instance from fcoe's list */
-	fcoe_hostlist_remove(lport);
-	port = lport_priv(lport);
-	fcoe = port->fcoe;
-	fcoe_if_destroy(lport);
-	fcoe_ethdrv_put(netdev);
-	rc = 0;
+	list_del(&fcoe->list);
+	write_unlock(&fcoe_hostlist_lock);
+	rtnl_lock();
+	fcoe_interface_cleanup(fcoe);
+	rtnl_unlock();
+	fcoe_if_destroy(fcoe->ctlr.lp);
 out_putdev:
 	dev_put(netdev);
 out_nodev:
@@ -1722,6 +1663,16 @@ out_nodev:
 	return rc;
 }
 
+static void fcoe_destroy_work(struct work_struct *work)
+{
+	struct fcoe_port *port;
+
+	port = container_of(work, struct fcoe_port, destroy_work);
+	mutex_lock(&fcoe_config_mutex);
+	fcoe_if_destroy(port->lport);
+	mutex_unlock(&fcoe_config_mutex);
+}
+
 /**
  * fcoe_create() - Handles the create call from sysfs
  * @buffer: expected to be an eth if name
@@ -1749,17 +1700,18 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 	}
 #endif
 
+	rtnl_lock();
 	netdev = fcoe_if_to_netdev(buffer);
 	if (!netdev) {
 		rc = -ENODEV;
 		goto out_nodev;
 	}
+
 	/* look for existing lport */
 	if (fcoe_hostlist_lookup(netdev)) {
 		rc = -EEXIST;
 		goto out_putdev;
 	}
-	fcoe_ethdrv_get(netdev);
 
 	fcoe = fcoe_interface_create(netdev);
 	if (!fcoe) {
@@ -1771,8 +1723,8 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 	if (IS_ERR(lport)) {
 		printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
 		       netdev->name);
-		fcoe_ethdrv_put(netdev);
 		rc = -EIO;
+		fcoe_interface_cleanup(fcoe);
 		goto out_free;
 	}
 
@@ -1798,6 +1750,7 @@ out_free:
 out_putdev:
 	dev_put(netdev);
 out_nodev:
+	rtnl_unlock();
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
 }
@@ -1973,25 +1926,6 @@ int fcoe_hostlist_add(const struct fc_lport *lport)
 }
 
 /**
- * fcoe_hostlist_remove() - remove a lport from lports list
- * @lp: ptr to the fc_lport to be removed
- *
- * Returns: 0 for success
- */
-int fcoe_hostlist_remove(const struct fc_lport *lport)
-{
-	struct fcoe_interface *fcoe;
-
-	write_lock_bh(&fcoe_hostlist_lock);
-	fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
-	BUG_ON(!fcoe);
-	list_del(&fcoe->list);
-	write_unlock_bh(&fcoe_hostlist_lock);
-
-	return 0;
-}
-
-/**
  * fcoe_init() - fcoe module loading initialization
  *
  * Returns 0 on success, negative on failure
@@ -2046,6 +1980,7 @@ static void __exit fcoe_exit(void)
 	unsigned int cpu;
 	struct fcoe_interface *fcoe, *tmp;
 	LIST_HEAD(local_list);
+	struct fcoe_port *port;
 
 	mutex_lock(&fcoe_config_mutex);
 
@@ -2058,7 +1993,11 @@ static void __exit fcoe_exit(void)
 
 	list_for_each_entry_safe(fcoe, tmp, &local_list, list) {
 		list_del(&fcoe->list);
-		fcoe_if_destroy(fcoe->ctlr.lp);
+		port = lport_priv(fcoe->ctlr.lp);
+		rtnl_lock();
+		fcoe_interface_cleanup(fcoe);
+		rtnl_unlock();
+		schedule_work(&port->destroy_work);
 	}
 
 	unregister_hotcpu_notifier(&fcoe_cpu_notifier);
@@ -2066,9 +2005,14 @@ static void __exit fcoe_exit(void)
 	for_each_online_cpu(cpu)
 		fcoe_percpu_thread_destroy(cpu);
 
-	/* detach from scsi transport */
-	fcoe_if_exit();
-
 	mutex_unlock(&fcoe_config_mutex);
+
+	/* flush any asyncronous interface destroys,
+	 * this should happen after the netdev notifier is unregistered */
+	flush_scheduled_work();
+
+	/* detach from scsi transport
+	 * must happen after all destroys are done, therefor after the flush */
+	fcoe_if_exit();
 }
 module_exit(fcoe_exit);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index ff22928..ce7f60f 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -93,9 +93,11 @@ struct fcoe_interface {
  */
 struct fcoe_port {
 	struct fcoe_interface *fcoe;
+	struct fc_lport *lport;
 	struct sk_buff_head fcoe_pending_queue;
 	u8	fcoe_pending_queue_active;
 	struct timer_list timer;		/* queue timer */
+	struct work_struct destroy_work;	/* to prevent rtnl deadlocks */
 };
 
 #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr)


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 23/64] fcoe: use rtnl mutex in place of hostlist lock
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (21 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 22/64] fcoe: Fix module ref count bug by adding NETDEV UNREGISTER handling Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 24/64] libfc: prepare to split off struct fc_rport_priv from fc_rport_libfc_priv Robert Love
                   ` (40 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Chris Leech, Robert Love

From: Chris Leech <christopher.leech@intel.com>

This just cuts down on the number of locks we're dealing with, and
eliminates the need to take another lock in the netdev notifier.

Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   37 +++++++++++--------------------------
 1 files changed, 11 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index c0264a9..ac481ad 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -58,8 +58,8 @@ MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for "	\
 DEFINE_MUTEX(fcoe_config_mutex);
 
 /* fcoe host list */
+/* must only by accessed under the RTNL mutex */
 LIST_HEAD(fcoe_hostlist);
-DEFINE_RWLOCK(fcoe_hostlist_lock);
 DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
 
 /* Function Prototypes */
@@ -527,8 +527,6 @@ bool fcoe_oem_match(struct fc_frame *fp)
  * fcoe_em_config() - allocates em for this lport
  * @lp: the fcoe that em is to allocated for
  *
- * Called with write fcoe_hostlist_lock held.
- *
  * Returns : 0 on success
  */
 static inline int fcoe_em_config(struct fc_lport *lp)
@@ -1539,7 +1537,6 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 	u32 mfs;
 	int rc = NOTIFY_OK;
 
-	write_lock(&fcoe_hostlist_lock);
 	list_for_each_entry(fcoe, &fcoe_hostlist, list) {
 		if (fcoe->netdev == netdev) {
 			lp = fcoe->ctlr.lp;
@@ -1586,7 +1583,6 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 		fcoe_clean_pending_queue(lp);
 	}
 out:
-	write_unlock(&fcoe_hostlist_lock);
 	return rc;
 }
 
@@ -1643,16 +1639,14 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 		goto out_nodev;
 	}
 
-	write_lock(&fcoe_hostlist_lock);
+	rtnl_lock();
 	fcoe = fcoe_hostlist_lookup_port(netdev);
 	if (!fcoe) {
-		write_unlock(&fcoe_hostlist_lock);
+		rtnl_unlock();
 		rc = -ENODEV;
 		goto out_putdev;
 	}
 	list_del(&fcoe->list);
-	write_unlock(&fcoe_hostlist_lock);
-	rtnl_lock();
 	fcoe_interface_cleanup(fcoe);
 	rtnl_unlock();
 	fcoe_if_destroy(fcoe->ctlr.lp);
@@ -1870,9 +1864,8 @@ int fcoe_reset(struct Scsi_Host *shost)
  * fcoe_hostlist_lookup_port() - find the corresponding lport by a given device
  * @dev: this is currently ptr to net_device
  *
- * Called with fcoe_hostlist_lock held.
- *
  * Returns: NULL or the located fcoe_port
+ * Locking: must be called with the RNL mutex held
  */
 static struct fcoe_interface *
 fcoe_hostlist_lookup_port(const struct net_device *dev)
@@ -1891,15 +1884,13 @@ fcoe_hostlist_lookup_port(const struct net_device *dev)
  * @netdev: ptr to net_device
  *
  * Returns: 0 for success
+ * Locking: must be called with the RTNL mutex held
  */
-struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
+static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
 {
 	struct fcoe_interface *fcoe;
 
-	read_lock(&fcoe_hostlist_lock);
 	fcoe = fcoe_hostlist_lookup_port(netdev);
-	read_unlock(&fcoe_hostlist_lock);
-
 	return (fcoe) ? fcoe->ctlr.lp : NULL;
 }
 
@@ -1908,20 +1899,19 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
  * @lp: ptr to the fc_lport to be added
  *
  * Returns: 0 for success
+ * Locking: must be called with the RTNL mutex held
  */
-int fcoe_hostlist_add(const struct fc_lport *lport)
+static int fcoe_hostlist_add(const struct fc_lport *lport)
 {
 	struct fcoe_interface *fcoe;
 	struct fcoe_port *port;
 
-	write_lock_bh(&fcoe_hostlist_lock);
 	fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
 	if (!fcoe) {
 		port = lport_priv(lport);
 		fcoe = port->fcoe;
 		list_add_tail(&fcoe->list, &fcoe_hostlist);
 	}
-	write_unlock_bh(&fcoe_hostlist_lock);
 	return 0;
 }
 
@@ -1979,7 +1969,6 @@ static void __exit fcoe_exit(void)
 {
 	unsigned int cpu;
 	struct fcoe_interface *fcoe, *tmp;
-	LIST_HEAD(local_list);
 	struct fcoe_port *port;
 
 	mutex_lock(&fcoe_config_mutex);
@@ -1987,18 +1976,14 @@ static void __exit fcoe_exit(void)
 	fcoe_dev_cleanup();
 
 	/* releases the associated fcoe hosts */
-	write_lock_bh(&fcoe_hostlist_lock);
-	list_splice_init(&fcoe_hostlist, &local_list);
-	write_unlock_bh(&fcoe_hostlist_lock);
-
-	list_for_each_entry_safe(fcoe, tmp, &local_list, list) {
+	rtnl_lock();
+	list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) {
 		list_del(&fcoe->list);
 		port = lport_priv(fcoe->ctlr.lp);
-		rtnl_lock();
 		fcoe_interface_cleanup(fcoe);
-		rtnl_unlock();
 		schedule_work(&port->destroy_work);
 	}
+	rtnl_unlock();
 
 	unregister_hotcpu_notifier(&fcoe_cpu_notifier);
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 24/64] libfc: prepare to split off struct fc_rport_priv from fc_rport_libfc_priv
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (22 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 23/64] fcoe: use rtnl mutex in place of hostlist lock Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 25/64] libfc: change interface for rport_create Robert Love
                   ` (39 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

While the I/O and LLD interfaces use fc_rport_libfc_priv, the
disc and rport interfaces will use fc_rport_priv, which will
be separately allocated.

Change the disc and rport usage of fc_rport_libfc_priv to fc_rport_priv.

Use #define temporarily to make both names equivalent until a
subsequent patch splits them.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |   18 ++++++------
 drivers/scsi/libfc/fc_lport.c |    2 +
 drivers/scsi/libfc/fc_rport.c |   60 +++++++++++++++++++++--------------------
 include/scsi/libfc.h          |   10 ++++++-
 4 files changed, 49 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 6fabf66..4c8d893 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -65,7 +65,7 @@ struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport,
 {
 	const struct fc_disc *disc = &lport->disc;
 	struct fc_rport *rport, *found = NULL;
-	struct fc_rport_libfc_priv *rdata;
+	struct fc_rport_priv *rdata;
 	int disc_found = 0;
 
 	list_for_each_entry(rdata, &disc->rports, peers) {
@@ -94,7 +94,7 @@ 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;
 
@@ -126,7 +126,7 @@ 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_rport_priv *rdata = rport->dd_data;
 	struct fc_disc *disc = &lport->disc;
 
 	FC_DISC_DBG(disc, "Received a %d event for port (%6x)\n", event,
@@ -170,7 +170,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
 {
 	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;
@@ -309,7 +309,7 @@ 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_rport_priv *rdata, *next;
 	struct fc_lport *lport = disc->lport;
 
 	FC_DISC_DBG(disc, "Restarting discovery\n");
@@ -400,7 +400,7 @@ static int fc_disc_new_target(struct fc_disc *disc,
 			      struct fc_rport_identifiers *ids)
 {
 	struct fc_lport *lport = disc->lport;
-	struct fc_rport_libfc_priv *rdata;
+	struct fc_rport_priv *rdata;
 	int error = 0;
 
 	if (rport && ids->port_name) {
@@ -458,7 +458,7 @@ static int fc_disc_new_target(struct fc_disc *disc,
 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;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	list_del(&rdata->peers);
 	lport->tt.rport_logoff(rport);
 }
@@ -580,7 +580,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 	int error = 0;
 	struct fc_disc_port dp;
 	struct fc_rport *rport;
-	struct fc_rport_libfc_priv *rdata;
+	struct fc_rport_priv *rdata;
 
 	lport = disc->lport;
 
@@ -774,7 +774,7 @@ 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;
 
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index ca8ea26..f7f328f 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1306,7 +1306,7 @@ static struct fc_rport_operations fc_lport_rport_ops = {
 static void fc_lport_enter_dns(struct fc_lport *lport)
 {
 	struct fc_rport *rport;
-	struct fc_rport_libfc_priv *rdata;
+	struct fc_rport_priv *rdata;
 	struct fc_disc_port dp;
 
 	dp.ids.port_id = FC_FID_DIR_SERV;
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 90cc90d..5f8f437 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -96,7 +96,7 @@ static void fc_rport_rogue_destroy(struct device *dev)
 struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp)
 {
 	struct fc_rport *rport;
-	struct fc_rport_libfc_priv *rdata;
+	struct fc_rport_priv *rdata;
 	rport = kzalloc(sizeof(*rport) + sizeof(*rdata), GFP_KERNEL);
 
 	if (!rport)
@@ -144,7 +144,7 @@ struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp)
 static const char *fc_rport_state(struct fc_rport *rport)
 {
 	const char *cp;
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 
 	cp = fc_rport_state_names[rdata->rp_state];
 	if (!cp)
@@ -199,7 +199,7 @@ static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp,
 static void fc_rport_state_enter(struct fc_rport *rport,
 				 enum fc_rport_state new)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	if (rdata->rp_state != new)
 		rdata->retries = 0;
 	rdata->rp_state = new;
@@ -208,8 +208,8 @@ static void fc_rport_state_enter(struct fc_rport *rport,
 static void fc_rport_work(struct work_struct *work)
 {
 	u32 port_id;
-	struct fc_rport_libfc_priv *rdata =
-		container_of(work, struct fc_rport_libfc_priv, event_work);
+	struct fc_rport_priv *rdata =
+		container_of(work, struct fc_rport_priv, event_work);
 	enum fc_rport_event event;
 	enum fc_rport_trans_state trans_state;
 	struct fc_lport *lport = rdata->local_port;
@@ -222,7 +222,7 @@ static void fc_rport_work(struct work_struct *work)
 
 	if (event == RPORT_EV_CREATED) {
 		struct fc_rport *new_rport;
-		struct fc_rport_libfc_priv *new_rdata;
+		struct fc_rport_priv *new_rdata;
 		struct fc_rport_identifiers ids;
 
 		ids.port_id = rport->port_id;
@@ -299,7 +299,7 @@ static void fc_rport_work(struct work_struct *work)
  */
 int fc_rport_login(struct fc_rport *rport)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 
 	mutex_lock(&rdata->rp_mutex);
 
@@ -329,7 +329,7 @@ int fc_rport_login(struct fc_rport *rport)
 static void fc_rport_enter_delete(struct fc_rport *rport,
 				  enum fc_rport_event event)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 
 	if (rdata->rp_state == RPORT_ST_DELETE)
 		return;
@@ -353,7 +353,7 @@ static void fc_rport_enter_delete(struct fc_rport *rport,
  */
 int fc_rport_logoff(struct fc_rport *rport)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 
 	mutex_lock(&rdata->rp_mutex);
 
@@ -387,7 +387,7 @@ out:
  */
 static void fc_rport_enter_ready(struct fc_rport *rport)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 
 	fc_rport_state_enter(rport, RPORT_ST_READY);
 
@@ -400,7 +400,7 @@ static void fc_rport_enter_ready(struct fc_rport *rport)
 
 /**
  * fc_rport_timeout() - Handler for the retry_work timer.
- * @work: The work struct of the fc_rport_libfc_priv
+ * @work: The work struct of the fc_rport_priv
  *
  * Locking Note: Called without the rport lock held. This
  * function will hold the rport lock, call an _enter_*
@@ -408,8 +408,8 @@ static void fc_rport_enter_ready(struct fc_rport *rport)
  */
 static void fc_rport_timeout(struct work_struct *work)
 {
-	struct fc_rport_libfc_priv *rdata =
-		container_of(work, struct fc_rport_libfc_priv, retry_work.work);
+	struct fc_rport_priv *rdata =
+		container_of(work, struct fc_rport_priv, retry_work.work);
 	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 
 	mutex_lock(&rdata->rp_mutex);
@@ -446,7 +446,7 @@ static void fc_rport_timeout(struct work_struct *work)
  */
 static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 
 	FC_RPORT_DBG(rport, "Error %ld in state %s, retries %d\n",
 		     PTR_ERR(fp), fc_rport_state(rport), rdata->retries);
@@ -480,7 +480,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
  */
 static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	unsigned long delay = FC_DEF_E_D_TOV;
 
 	/* make sure this isn't an FC_EX_CLOSED error, never retry those */
@@ -515,7 +515,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 				void *rp_arg)
 {
 	struct fc_rport *rport = rp_arg;
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_els_flogi *plp = NULL;
 	unsigned int tov;
@@ -586,7 +586,7 @@ err:
  */
 static void fc_rport_enter_plogi(struct fc_rport *rport)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_frame *fp;
 
@@ -624,7 +624,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 			       void *rp_arg)
 {
 	struct fc_rport *rport = rp_arg;
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct {
 		struct fc_els_prli prli;
 		struct fc_els_spp spp;
@@ -694,7 +694,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
 			       void *rp_arg)
 {
 	struct fc_rport *rport = rp_arg;
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	u8 op;
 
 	mutex_lock(&rdata->rp_mutex);
@@ -738,7 +738,7 @@ err:
  */
 static void fc_rport_enter_prli(struct fc_rport *rport)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 	struct {
 		struct fc_els_prli prli;
@@ -780,7 +780,7 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
 			      void *rp_arg)
 {
 	struct fc_rport *rport = rp_arg;
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	u8 op;
 
 	mutex_lock(&rdata->rp_mutex);
@@ -841,7 +841,7 @@ err:
 static void fc_rport_enter_rtv(struct fc_rport *rport)
 {
 	struct fc_frame *fp;
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 
 	FC_RPORT_DBG(rport, "Port entered RTV state from %s state\n",
@@ -871,7 +871,7 @@ static void fc_rport_enter_rtv(struct fc_rport *rport)
  */
 static void fc_rport_enter_logo(struct fc_rport *rport)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_frame *fp;
 
@@ -907,7 +907,7 @@ static void fc_rport_enter_logo(struct fc_rport *rport)
 void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 		       struct fc_rport *rport)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 
 	struct fc_frame_header *fh;
@@ -967,7 +967,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 static void fc_rport_recv_plogi_req(struct fc_rport *rport,
 				    struct fc_seq *sp, struct fc_frame *rx_fp)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_frame *fp = rx_fp;
 	struct fc_exch *ep;
@@ -1090,7 +1090,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
 static void fc_rport_recv_prli_req(struct fc_rport *rport,
 				   struct fc_seq *sp, struct fc_frame *rx_fp)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_exch *ep;
 	struct fc_frame *fp;
@@ -1242,7 +1242,7 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
 static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
 				   struct fc_frame *fp)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 
 	struct fc_frame_header *fh;
@@ -1278,7 +1278,7 @@ static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp,
 				   struct fc_frame *fp)
 {
 	struct fc_frame_header *fh;
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 
 	fh = fc_frame_header_get(fp);
@@ -1342,8 +1342,8 @@ EXPORT_SYMBOL(fc_destroy_rport);
 
 void fc_rport_terminate_io(struct fc_rport *rport)
 {
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;
-	struct fc_lport *lport = rdata->local_port;
+	struct fc_rport_libfc_priv *rp = rport->dd_data;
+	struct fc_lport *lport = rp->local_port;
 
 	lport->tt.exch_mgr_reset(lport, 0, rport->port_id);
 	lport->tt.exch_mgr_reset(lport, rport->port_id, 0);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 53b3881..aa21951 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -77,7 +77,7 @@ do {								\
 
 #define FC_RPORT_DBG(rport, fmt, args...)				\
 do {									\
-	struct fc_rport_libfc_priv *rdata = rport->dd_data;		\
+	struct fc_rport_priv *rdata = rport->dd_data;			\
 	struct fc_lport *lport = rdata->local_port;			\
 	FC_RPORT_ID_DBG(lport, rport->port_id, fmt, ##args);		\
 } while (0)
@@ -177,6 +177,14 @@ enum fc_rport_event {
 	RPORT_EV_LOGO
 };
 
+/*
+ * Temporary definition to prepare for split off from fc_rport_libfc_priv
+ * of a separately-allocated structure called fc_rport_priv.  This will
+ * be the primary object for the discovery and rport state machines.
+ * This definition is just to make this patch series easier to review.
+ */
+#define fc_rport_priv fc_rport_libfc_priv
+
 struct fc_rport_operations {
 	void (*event_callback)(struct fc_lport *, struct fc_rport *,
 			       enum fc_rport_event);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 25/64] libfc: change interface for rport_create
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (23 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 24/64] libfc: prepare to split off struct fc_rport_priv from fc_rport_libfc_priv Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 26/64] libfc: fix RPORT_TO_PRIV and PRIV_TO_RPORT() macros Robert Love
                   ` (38 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

The interface for lport->tt.rport_create() takes a fc_disc_port arg,
which is unnatural for most calls.   The only reason for this was
to avoid passing in the local port as an argument, but otherwise
added to complexity.

Simplify by just using lport and fc_rport_identifiers.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |   31 ++++++++++++-------------------
 drivers/scsi/libfc/fc_lport.c |   26 ++++++++++++--------------
 drivers/scsi/libfc/fc_rport.c |   17 +++++++++--------
 include/scsi/libfc.h          |    5 ++---
 4 files changed, 35 insertions(+), 44 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 4c8d893..ecc625c 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -428,13 +428,7 @@ static int fc_disc_new_target(struct fc_disc *disc,
 		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);
+				rport = lport->tt.rport_create(lport, ids);
 			}
 			if (!rport)
 				error = -ENOMEM;
@@ -578,7 +572,7 @@ 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_identifiers ids;
 	struct fc_rport *rport;
 	struct fc_rport_priv *rdata;
 
@@ -621,15 +615,14 @@ 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);
+		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) {
+			rport = lport->tt.rport_create(lport, &ids);
 			if (rport) {
 				rdata = rport->dd_data;
 				rdata->ops = &fc_disc_rport_ops;
@@ -640,7 +633,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 			} else
 				printk(KERN_WARNING "libfc: Failed to allocate "
 				       "memory for the newly discovered port "
-				       "(%6x)\n", dp.ids.port_id);
+				       "(%6x)\n", ids.port_id);
 		}
 
 		if (np->fp_flags & FC_NS_FID_LAST) {
@@ -781,7 +774,7 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
 	if (dp->ids.port_id == fc_host_port_id(lport->host))
 		goto out;
 
-	new_rport = lport->tt.rport_create(dp);
+	new_rport = lport->tt.rport_create(lport, &dp->ids);
 	if (new_rport) {
 		rdata = new_rport->dd_data;
 		rdata->ops = &fc_disc_rport_ops;
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index f7f328f..a78161c 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -211,20 +211,19 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
 			       u32 remote_fid, u64 remote_wwpn,
 			       u64 remote_wwnn)
 {
-	struct fc_disc_port dp;
+	struct fc_rport_identifiers ids;
 
-	dp.lp = lport;
-	dp.ids.port_id = remote_fid;
-	dp.ids.port_name = remote_wwpn;
-	dp.ids.node_name = remote_wwnn;
-	dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
+	ids.port_id = remote_fid;
+	ids.port_name = remote_wwpn;
+	ids.node_name = remote_wwnn;
+	ids.roles = FC_RPORT_ROLE_UNKNOWN;
 
 	if (lport->ptp_rp) {
 		lport->tt.rport_logoff(lport->ptp_rp);
 		lport->ptp_rp = NULL;
 	}
 
-	lport->ptp_rp = lport->tt.rport_create(&dp);
+	lport->ptp_rp = lport->tt.rport_create(lport, &ids);
 
 	lport->tt.rport_login(lport->ptp_rp);
 
@@ -1307,20 +1306,19 @@ static void fc_lport_enter_dns(struct fc_lport *lport)
 {
 	struct fc_rport *rport;
 	struct fc_rport_priv *rdata;
-	struct fc_disc_port dp;
+	struct fc_rport_identifiers ids;
 
-	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;
-	dp.lp = lport;
+	ids.port_id = FC_FID_DIR_SERV;
+	ids.port_name = -1;
+	ids.node_name = -1;
+	ids.roles = FC_RPORT_ROLE_UNKNOWN;
 
 	FC_LPORT_DBG(lport, "Entered DNS state from %s state\n",
 		     fc_lport_state(lport));
 
 	fc_lport_state_enter(lport, LPORT_ST_DNS);
 
-	rport = lport->tt.rport_create(&dp);
+	rport = lport->tt.rport_create(lport, &ids);
 	if (!rport)
 		goto err;
 
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 5f8f437..2fbc94a 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -93,7 +93,8 @@ static void fc_rport_rogue_destroy(struct device *dev)
 	kfree(rport);
 }
 
-struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp)
+struct fc_rport *fc_rport_rogue_create(struct fc_lport *lport,
+				       struct fc_rport_identifiers *ids)
 {
 	struct fc_rport *rport;
 	struct fc_rport_priv *rdata;
@@ -105,10 +106,10 @@ struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp)
 	rdata = RPORT_TO_PRIV(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;
+	rport->port_id = ids->port_id;
+	rport->port_name = ids->port_name;
+	rport->node_name = ids->node_name;
+	rport->roles = ids->roles;
 	rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	/*
 	 * Note: all this libfc rogue rport code will be removed for
@@ -118,14 +119,14 @@ struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp)
 	rport->dev.release = fc_rport_rogue_destroy;
 
 	mutex_init(&rdata->rp_mutex);
-	rdata->local_port = dp->lp;
+	rdata->local_port = lport;
 	rdata->trans_state = FC_PORTSTATE_ROGUE;
 	rdata->rp_state = RPORT_ST_INIT;
 	rdata->event = RPORT_EV_NONE;
 	rdata->flags = FC_RP_FLAGS_REC_SUPPORTED;
 	rdata->ops = NULL;
-	rdata->e_d_tov = dp->lp->e_d_tov;
-	rdata->r_a_tov = dp->lp->r_a_tov;
+	rdata->e_d_tov = lport->e_d_tov;
+	rdata->r_a_tov = lport->r_a_tov;
 	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
 	INIT_WORK(&rdata->event_work, fc_rport_work);
 	/*
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index aa21951..d888cbe 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -227,8 +227,6 @@ struct fc_rport_libfc_priv {
 #define RPORT_TO_PRIV(x)						\
 	(struct fc_rport_libfc_priv *)((void *)x + sizeof(struct fc_rport));
 
-struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *);
-
 static inline void fc_rport_set_name(struct fc_rport *rport, u64 wwpn, u64 wwnn)
 {
 	rport->node_name = wwnn;
@@ -569,7 +567,8 @@ struct libfc_function_template {
 	/*
 	 * Create a remote port
 	 */
-	struct fc_rport *(*rport_create)(struct fc_disc_port *);
+	struct fc_rport *(*rport_create)(struct fc_lport *,
+					 struct fc_rport_identifiers *);
 
 	/*
 	 * Initiates the RP state machine. It is called from the LP module.


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 26/64] libfc: fix RPORT_TO_PRIV and PRIV_TO_RPORT() macros.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (24 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 25/64] libfc: change interface for rport_create Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 27/64] libfc: make fc_rport_priv the primary rport interface Robert Love
                   ` (37 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

These macros introduce extra undesirable semicolons that keep
them from being used in expressions, and they don't protect
against being passed an expression.

Add parens and remove the semicolons.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 include/scsi/libfc.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index d888cbe..2fdd8ac 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -223,9 +223,9 @@ struct fc_rport_libfc_priv {
 };
 
 #define PRIV_TO_RPORT(x)						\
-	(struct fc_rport *)((void *)x - sizeof(struct fc_rport));
+	((struct fc_rport *)((void *)(x) - sizeof(struct fc_rport)))
 #define RPORT_TO_PRIV(x)						\
-	(struct fc_rport_libfc_priv *)((void *)x + sizeof(struct fc_rport));
+	((struct fc_rport_libfc_priv *)((void *)(x) + sizeof(struct fc_rport)))
 
 static inline void fc_rport_set_name(struct fc_rport *rport, u64 wwpn, u64 wwnn)
 {


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 27/64] libfc: make fc_rport_priv the primary rport interface.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (25 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 26/64] libfc: fix RPORT_TO_PRIV and PRIV_TO_RPORT() macros Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:00 ` [PATCH 28/64] libfc: change elsct to use FC_ID instead of rdata Robert Love
                   ` (36 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

The rport and discovery modules deal with remote ports
before fc_remote_port_add() can be done, because the
full set of rport identifiers is not known at early stages.

In preparation for splitting the fc_rport/fc_rport_priv allocation,
make fc_rport_priv the primary interface for the remote port and
discovery engines.

The FCP / SCSI layers still deal with fc_rport and
fc_rport_libfc_priv, however.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |   95 ++++-------
 drivers/scsi/libfc/fc_elsct.c |    4 
 drivers/scsi/libfc/fc_fcp.c   |    2 
 drivers/scsi/libfc/fc_lport.c |   26 +--
 drivers/scsi/libfc/fc_rport.c |  364 ++++++++++++++++++++---------------------
 include/scsi/fc_encode.h      |    7 +
 include/scsi/libfc.h          |   26 ++-
 7 files changed, 245 insertions(+), 279 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index ecc625c..448ffc3 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -49,7 +49,6 @@ 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 *,
 			      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_timeout(struct work_struct *);
 static void fc_disc_single(struct fc_disc *, struct fc_disc_port *);
@@ -60,27 +59,19 @@ static void fc_disc_restart(struct fc_disc *);
  * @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)
+struct fc_rport_priv *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 *rport;
 	struct fc_rport_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 (rport->port_id == port_id)
+			return rdata;
 	}
-
-	if (!disc_found)
-		found = NULL;
-
-	return found;
+	return NULL;
 }
 
 /**
@@ -93,21 +84,18 @@ 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_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);
+		lport->tt.rport_logoff(rdata);
 	}
 
 	list_for_each_entry_safe(rdata, next, &disc->rogue_rports, peers) {
-		rport = PRIV_TO_RPORT(rdata);
-		lport->tt.rport_logoff(rport);
+		lport->tt.rport_logoff(rdata);
 	}
 
 	mutex_unlock(&disc->disc_mutex);
@@ -116,18 +104,18 @@ void fc_disc_stop_rports(struct fc_disc *disc)
 /**
  * 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
+ * @rdata: private remote port data
  * @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,
+				   struct fc_rport_priv *rdata,
 				   enum fc_rport_event event)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_disc *disc = &lport->disc;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 
 	FC_DISC_DBG(disc, "Received a %d event for port (%6x)\n", event,
 		    rport->port_id);
@@ -169,7 +157,6 @@ 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_priv *rdata;
 	struct fc_els_rscn *rp;
 	struct fc_els_rscn_page *pp;
@@ -249,11 +236,10 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
 			    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;
+			rdata = lport->tt.rport_lookup(lport, dp->ids.port_id);
+			if (rdata) {
 				list_del(&rdata->peers);
-				lport->tt.rport_logoff(rport);
+				lport->tt.rport_logoff(rdata);
 			}
 			fc_disc_single(disc, dp);
 		}
@@ -308,16 +294,14 @@ 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_priv *rdata, *next;
 	struct fc_lport *lport = disc->lport;
 
 	FC_DISC_DBG(disc, "Restarting discovery\n");
 
 	list_for_each_entry_safe(rdata, next, &disc->rports, peers) {
-		rport = PRIV_TO_RPORT(rdata);
 		list_del(&rdata->peers);
-		lport->tt.rport_logoff(rport);
+		lport->tt.rport_logoff(rdata);
 	}
 
 	disc->requested = 1;
@@ -335,6 +319,7 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
 						enum fc_disc_event),
 			  struct fc_lport *lport)
 {
+	struct fc_rport_priv *rdata;
 	struct fc_rport *rport;
 	struct fc_rport_identifiers ids;
 	struct fc_disc *disc = &lport->disc;
@@ -362,8 +347,9 @@ 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) {
+	rdata = disc->lport->ptp_rp;
+	if (rdata) {
+		rport = PRIV_TO_RPORT(rdata);
 		ids.port_id = rport->port_id;
 		ids.port_name = rport->port_name;
 		ids.node_name = rport->node_name;
@@ -418,7 +404,9 @@ 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);
+			rdata = rport->dd_data;
+			list_del(&rdata->peers);
+			lport->tt.rport_logoff(rdata);
 			rport = NULL;
 		}
 	}
@@ -426,38 +414,27 @@ static int fc_disc_new_target(struct fc_disc *disc,
 	    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);
+			rdata = lport->tt.rport_lookup(lport, ids->port_id);
 			if (!rport) {
-				rport = lport->tt.rport_create(lport, ids);
+				rdata = lport->tt.rport_create(lport, ids);
 			}
-			if (!rport)
+			if (!rdata)
 				error = -ENOMEM;
+			else
+				rport = PRIV_TO_RPORT(rdata);
 		}
 		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);
+			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_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
  * Locking Note: This function expects that the disc mutex is locked before
@@ -573,7 +550,6 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 	size_t tlen;
 	int error = 0;
 	struct fc_rport_identifiers ids;
-	struct fc_rport *rport;
 	struct fc_rport_priv *rdata;
 
 	lport = disc->lport;
@@ -622,14 +598,13 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 
 		if (ids.port_id != fc_host_port_id(lport->host) &&
 		    ids.port_name != lport->wwpn) {
-			rport = lport->tt.rport_create(lport, &ids);
-			if (rport) {
-				rdata = rport->dd_data;
+			rdata = lport->tt.rport_create(lport, &ids);
+			if (rdata) {
 				rdata->ops = &fc_disc_rport_ops;
 				rdata->local_port = lport;
 				list_add_tail(&rdata->peers,
 					      &disc->rogue_rports);
-				lport->tt.rport_login(rport);
+				lport->tt.rport_login(rdata);
 			} else
 				printk(KERN_WARNING "libfc: Failed to allocate "
 				       "memory for the newly discovered port "
@@ -766,7 +741,6 @@ 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_priv *rdata;
 
 	lport = disc->lport;
@@ -774,13 +748,12 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
 	if (dp->ids.port_id == fc_host_port_id(lport->host))
 		goto out;
 
-	new_rport = lport->tt.rport_create(lport, &dp->ids);
-	if (new_rport) {
-		rdata = new_rport->dd_data;
+	rdata = lport->tt.rport_create(lport, &dp->ids);
+	if (rdata) {
 		rdata->ops = &fc_disc_rport_ops;
 		kfree(dp);
 		list_add_tail(&rdata->peers, &disc->rogue_rports);
-		lport->tt.rport_login(new_rport);
+		lport->tt.rport_login(rdata);
 	}
 	return;
 out:
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index 5878b34..2b8a3bb 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -32,7 +32,7 @@
  * fc_elsct_send - sends ELS/CT frame
  */
 static struct fc_seq *fc_elsct_send(struct fc_lport *lport,
-				    struct fc_rport *rport,
+				    struct fc_rport_priv *rdata,
 				    struct fc_frame *fp,
 				    unsigned int op,
 				    void (*resp)(struct fc_seq *,
@@ -47,7 +47,7 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport,
 
 	/* ELS requests */
 	if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS))
-		rc = fc_els_fill(lport, rport, fp, op, &r_ctl, &did, &fh_type);
+		rc = fc_els_fill(lport, rdata, fp, op, &r_ctl, &did, &fh_type);
 	else
 		/* CT requests */
 		rc = fc_ct_fill(lport, fp, op, &r_ctl, &did, &fh_type);
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 7d5ffcb..a622096 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1308,7 +1308,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
 	fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id,
 		       fc_host_port_id(rp->local_port->host), FC_TYPE_ELS,
 		       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
-	if (lp->tt.elsct_send(lp, rport, fp, ELS_REC, fc_fcp_rec_resp,
+	if (lp->tt.elsct_send(lp, rport->dd_data, fp, ELS_REC, fc_fcp_rec_resp,
 			      fsp, jiffies_to_msecs(FC_SCSI_REC_TOV))) {
 		fc_fcp_pkt_hold(fsp);		/* hold while REC outstanding */
 		return;
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index a78161c..3c15abd 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -133,16 +133,18 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)
 /**
  * fc_lport_rport_callback() - Event handler for rport events
  * @lport: The lport which is receiving the event
- * @rport: The rport which the event has occured on
+ * @rdata: private remote port data
  * @event: The event that occured
  *
  * Locking Note: The rport lock should not be held when calling
  *		 this function.
  */
 static void fc_lport_rport_callback(struct fc_lport *lport,
-				    struct fc_rport *rport,
+				    struct fc_rport_priv *rdata,
 				    enum fc_rport_event event)
 {
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
+
 	FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event,
 		     rport->port_id);
 
@@ -151,7 +153,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
 		if (rport->port_id == FC_FID_DIR_SERV) {
 			mutex_lock(&lport->lp_mutex);
 			if (lport->state == LPORT_ST_DNS) {
-				lport->dns_rp = rport;
+				lport->dns_rp = rdata;
 				fc_lport_enter_rpn_id(lport);
 			} else {
 				FC_LPORT_DBG(lport, "Received an CREATED event "
@@ -160,7 +162,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
 					     "in the DNS state, it's in the "
 					     "%d state", rport->port_id,
 					     lport->state);
-				lport->tt.rport_logoff(rport);
+				lport->tt.rport_logoff(rdata);
 			}
 			mutex_unlock(&lport->lp_mutex);
 		} else
@@ -832,7 +834,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
 {
 	struct fc_frame_header *fh = fc_frame_header_get(fp);
 	void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *);
-	struct fc_rport *rport;
+	struct fc_rport_priv *rdata;
 	u32 s_id;
 	u32 d_id;
 	struct fc_seq_els_data rjt_data;
@@ -888,9 +890,9 @@ 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);
-			if (rport)
-				lport->tt.rport_recv_req(sp, fp, rport);
+			rdata = lport->tt.rport_lookup(lport, s_id);
+			if (rdata)
+				lport->tt.rport_recv_req(sp, fp, rdata);
 			else {
 				rjt_data.fp = NULL;
 				rjt_data.reason = ELS_RJT_UNAB;
@@ -1304,7 +1306,6 @@ static struct fc_rport_operations fc_lport_rport_ops = {
  */
 static void fc_lport_enter_dns(struct fc_lport *lport)
 {
-	struct fc_rport *rport;
 	struct fc_rport_priv *rdata;
 	struct fc_rport_identifiers ids;
 
@@ -1318,13 +1319,12 @@ static void fc_lport_enter_dns(struct fc_lport *lport)
 
 	fc_lport_state_enter(lport, LPORT_ST_DNS);
 
-	rport = lport->tt.rport_create(lport, &ids);
-	if (!rport)
+	rdata = lport->tt.rport_create(lport, &ids);
+	if (!rdata)
 		goto err;
 
-	rdata = rport->dd_data;
 	rdata->ops = &fc_lport_rport_ops;
-	lport->tt.rport_login(rport);
+	lport->tt.rport_login(rdata);
 	return;
 
 err:
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 2fbc94a..13d3d75 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -57,23 +57,23 @@
 
 struct workqueue_struct *rport_event_queue;
 
-static void fc_rport_enter_plogi(struct fc_rport *);
-static void fc_rport_enter_prli(struct fc_rport *);
-static void fc_rport_enter_rtv(struct fc_rport *);
-static void fc_rport_enter_ready(struct fc_rport *);
-static void fc_rport_enter_logo(struct fc_rport *);
+static void fc_rport_enter_plogi(struct fc_rport_priv *);
+static void fc_rport_enter_prli(struct fc_rport_priv *);
+static void fc_rport_enter_rtv(struct fc_rport_priv *);
+static void fc_rport_enter_ready(struct fc_rport_priv *);
+static void fc_rport_enter_logo(struct fc_rport_priv *);
 
-static void fc_rport_recv_plogi_req(struct fc_rport *,
+static void fc_rport_recv_plogi_req(struct fc_rport_priv *,
 				    struct fc_seq *, struct fc_frame *);
-static void fc_rport_recv_prli_req(struct fc_rport *,
+static void fc_rport_recv_prli_req(struct fc_rport_priv *,
 				   struct fc_seq *, struct fc_frame *);
-static void fc_rport_recv_prlo_req(struct fc_rport *,
+static void fc_rport_recv_prlo_req(struct fc_rport_priv *,
 				   struct fc_seq *, struct fc_frame *);
-static void fc_rport_recv_logo_req(struct fc_rport *,
+static void fc_rport_recv_logo_req(struct fc_rport_priv *,
 				   struct fc_seq *, struct fc_frame *);
 static void fc_rport_timeout(struct work_struct *);
-static void fc_rport_error(struct fc_rport *, struct fc_frame *);
-static void fc_rport_error_retry(struct fc_rport *, struct fc_frame *);
+static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *);
+static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *);
 static void fc_rport_work(struct work_struct *);
 
 static const char *fc_rport_state_names[] = {
@@ -89,12 +89,14 @@ static const char *fc_rport_state_names[] = {
 static void fc_rport_rogue_destroy(struct device *dev)
 {
 	struct fc_rport *rport = dev_to_rport(dev);
-	FC_RPORT_DBG(rport, "Destroying rogue rport\n");
+	struct fc_rport_priv *rdata = RPORT_TO_PRIV(rport);
+
+	FC_RPORT_DBG(rdata, "Destroying rogue rport\n");
 	kfree(rport);
 }
 
-struct fc_rport *fc_rport_rogue_create(struct fc_lport *lport,
-				       struct fc_rport_identifiers *ids)
+struct fc_rport_priv *fc_rport_rogue_create(struct fc_lport *lport,
+					    struct fc_rport_identifiers *ids)
 {
 	struct fc_rport *rport;
 	struct fc_rport_priv *rdata;
@@ -135,17 +137,16 @@ struct fc_rport *fc_rport_rogue_create(struct fc_lport *lport,
 	 */
 	INIT_LIST_HEAD(&rdata->peers);
 
-	return rport;
+	return rdata;
 }
 
 /**
  * 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
+ * @rdata: remote port private data
  */
-static const char *fc_rport_state(struct fc_rport *rport)
+static const char *fc_rport_state(struct fc_rport_priv *rdata)
 {
 	const char *cp;
-	struct fc_rport_priv *rdata = rport->dd_data;
 
 	cp = fc_rport_state_names[rdata->rp_state];
 	if (!cp)
@@ -192,15 +193,14 @@ static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp,
 
 /**
  * fc_rport_state_enter() - Change the rport's state
- * @rport: The rport whose state should change
+ * @rdata: The rport whose state should change
  * @new: The new state of the rport
  *
  * Locking Note: Called with the rport lock held
  */
-static void fc_rport_state_enter(struct fc_rport *rport,
+static void fc_rport_state_enter(struct fc_rport_priv *rdata,
 				 enum fc_rport_state new)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
 	if (rdata->rp_state != new)
 		rdata->retries = 0;
 	rdata->rp_state = new;
@@ -255,7 +255,7 @@ static void fc_rport_work(struct work_struct *work)
 			INIT_LIST_HEAD(&new_rdata->peers);
 			INIT_WORK(&new_rdata->event_work, fc_rport_work);
 
-			fc_rport_state_enter(new_rport, RPORT_ST_READY);
+			fc_rport_state_enter(new_rdata, RPORT_ST_READY);
 		} else {
 			printk(KERN_WARNING "libfc: Failed to allocate "
 			       " memory for rport (%6x)\n", ids.port_id);
@@ -263,20 +263,20 @@ static void fc_rport_work(struct work_struct *work)
 		}
 		if (rport->port_id != FC_FID_DIR_SERV)
 			if (rport_ops->event_callback)
-				rport_ops->event_callback(lport, rport,
+				rport_ops->event_callback(lport, rdata,
 							  RPORT_EV_FAILED);
 		put_device(&rport->dev);
 		rport = new_rport;
 		rdata = new_rport->dd_data;
 		if (rport_ops->event_callback)
-			rport_ops->event_callback(lport, rport, event);
+			rport_ops->event_callback(lport, rdata, event);
 	} else if ((event == RPORT_EV_FAILED) ||
 		   (event == RPORT_EV_LOGO) ||
 		   (event == RPORT_EV_STOP)) {
 		trans_state = rdata->trans_state;
 		mutex_unlock(&rdata->rp_mutex);
 		if (rport_ops->event_callback)
-			rport_ops->event_callback(lport, rport, event);
+			rport_ops->event_callback(lport, rdata, event);
 		cancel_delayed_work_sync(&rdata->retry_work);
 		if (trans_state == FC_PORTSTATE_ROGUE)
 			put_device(&rport->dev);
@@ -292,21 +292,19 @@ static void fc_rport_work(struct work_struct *work)
 
 /**
  * fc_rport_login() - Start the remote port login state machine
- * @rport: Fibre Channel remote port
+ * @rdata: private remote port
  *
  * Locking Note: Called without the rport lock held. This
  * function will hold the rport lock, call an _enter_*
  * function and then unlock the rport.
  */
-int fc_rport_login(struct fc_rport *rport)
+int fc_rport_login(struct fc_rport_priv *rdata)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
-
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rport, "Login to port\n");
+	FC_RPORT_DBG(rdata, "Login to port\n");
 
-	fc_rport_enter_plogi(rport);
+	fc_rport_enter_plogi(rdata);
 
 	mutex_unlock(&rdata->rp_mutex);
 
@@ -315,7 +313,7 @@ int fc_rport_login(struct fc_rport *rport)
 
 /**
  * fc_rport_enter_delete() - schedule a remote port to be deleted.
- * @rport: Fibre Channel remote port
+ * @rdata: private remote port
  * @event: event to report as the reason for deletion
  *
  * Locking Note: Called with the rport lock held.
@@ -327,17 +325,15 @@ int fc_rport_login(struct fc_rport *rport)
  * Since we have the mutex, even if fc_rport_work() is already started,
  * it'll see the new event.
  */
-static void fc_rport_enter_delete(struct fc_rport *rport,
+static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
 				  enum fc_rport_event event)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
-
 	if (rdata->rp_state == RPORT_ST_DELETE)
 		return;
 
-	FC_RPORT_DBG(rport, "Delete port\n");
+	FC_RPORT_DBG(rdata, "Delete port\n");
 
-	fc_rport_state_enter(rport, RPORT_ST_DELETE);
+	fc_rport_state_enter(rdata, RPORT_ST_DELETE);
 
 	if (rdata->event == RPORT_EV_NONE)
 		queue_work(rport_event_queue, &rdata->event_work);
@@ -346,33 +342,31 @@ static void fc_rport_enter_delete(struct fc_rport *rport,
 
 /**
  * fc_rport_logoff() - Logoff and remove an rport
- * @rport: Fibre Channel remote port to be removed
+ * @rdata: private remote port
  *
  * Locking Note: Called without the rport lock held. This
  * function will hold the rport lock, call an _enter_*
  * function and then unlock the rport.
  */
-int fc_rport_logoff(struct fc_rport *rport)
+int fc_rport_logoff(struct fc_rport_priv *rdata)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
-
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rport, "Remove port\n");
+	FC_RPORT_DBG(rdata, "Remove port\n");
 
 	if (rdata->rp_state == RPORT_ST_DELETE) {
-		FC_RPORT_DBG(rport, "Port in Delete state, not removing\n");
+		FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n");
 		mutex_unlock(&rdata->rp_mutex);
 		goto out;
 	}
 
-	fc_rport_enter_logo(rport);
+	fc_rport_enter_logo(rdata);
 
 	/*
 	 * Change the state to Delete so that we discard
 	 * the response.
 	 */
-	fc_rport_enter_delete(rport, RPORT_EV_STOP);
+	fc_rport_enter_delete(rdata, RPORT_EV_STOP);
 	mutex_unlock(&rdata->rp_mutex);
 
 out:
@@ -381,18 +375,16 @@ out:
 
 /**
  * fc_rport_enter_ready() - The rport is ready
- * @rport: Fibre Channel remote port that is ready
+ * @rdata: private remote port
  *
  * Locking Note: The rport lock is expected to be held before calling
  * this routine.
  */
-static void fc_rport_enter_ready(struct fc_rport *rport)
+static void fc_rport_enter_ready(struct fc_rport_priv *rdata)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
-
-	fc_rport_state_enter(rport, RPORT_ST_READY);
+	fc_rport_state_enter(rdata, RPORT_ST_READY);
 
-	FC_RPORT_DBG(rport, "Port is Ready\n");
+	FC_RPORT_DBG(rdata, "Port is Ready\n");
 
 	if (rdata->event == RPORT_EV_NONE)
 		queue_work(rport_event_queue, &rdata->event_work);
@@ -411,22 +403,21 @@ static void fc_rport_timeout(struct work_struct *work)
 {
 	struct fc_rport_priv *rdata =
 		container_of(work, struct fc_rport_priv, retry_work.work);
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 
 	mutex_lock(&rdata->rp_mutex);
 
 	switch (rdata->rp_state) {
 	case RPORT_ST_PLOGI:
-		fc_rport_enter_plogi(rport);
+		fc_rport_enter_plogi(rdata);
 		break;
 	case RPORT_ST_PRLI:
-		fc_rport_enter_prli(rport);
+		fc_rport_enter_prli(rdata);
 		break;
 	case RPORT_ST_RTV:
-		fc_rport_enter_rtv(rport);
+		fc_rport_enter_rtv(rdata);
 		break;
 	case RPORT_ST_LOGO:
-		fc_rport_enter_logo(rport);
+		fc_rport_enter_logo(rdata);
 		break;
 	case RPORT_ST_READY:
 	case RPORT_ST_INIT:
@@ -439,27 +430,25 @@ static void fc_rport_timeout(struct work_struct *work)
 
 /**
  * fc_rport_error() - Error handler, called once retries have been exhausted
- * @rport: The fc_rport object
+ * @rdata: private remote port
  * @fp: The frame pointer
  *
  * Locking Note: The rport lock is expected to be held before
  * calling this routine
  */
-static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
+static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
-
-	FC_RPORT_DBG(rport, "Error %ld in state %s, retries %d\n",
-		     PTR_ERR(fp), fc_rport_state(rport), rdata->retries);
+	FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n",
+		     PTR_ERR(fp), fc_rport_state(rdata), rdata->retries);
 
 	switch (rdata->rp_state) {
 	case RPORT_ST_PLOGI:
 	case RPORT_ST_PRLI:
 	case RPORT_ST_LOGO:
-		fc_rport_enter_delete(rport, RPORT_EV_FAILED);
+		fc_rport_enter_delete(rdata, RPORT_EV_FAILED);
 		break;
 	case RPORT_ST_RTV:
-		fc_rport_enter_ready(rport);
+		fc_rport_enter_ready(rdata);
 		break;
 	case RPORT_ST_DELETE:
 	case RPORT_ST_READY:
@@ -470,7 +459,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
 
 /**
  * fc_rport_error_retry() - Error handler when retries are desired
- * @rport: The fc_rport object
+ * @rdata: private remote port data
  * @fp: The frame pointer
  *
  * If the error was an exchange timeout retry immediately,
@@ -479,18 +468,18 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
  * Locking Note: The rport lock is expected to be held before
  * calling this routine
  */
-static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp)
+static void fc_rport_error_retry(struct fc_rport_priv *rdata,
+				 struct fc_frame *fp)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
 	unsigned long delay = FC_DEF_E_D_TOV;
 
 	/* make sure this isn't an FC_EX_CLOSED error, never retry those */
 	if (PTR_ERR(fp) == -FC_EX_CLOSED)
-		return fc_rport_error(rport, fp);
+		return fc_rport_error(rdata, fp);
 
 	if (rdata->retries < rdata->local_port->max_rport_retry_count) {
-		FC_RPORT_DBG(rport, "Error %ld in state %s, retrying\n",
-			     PTR_ERR(fp), fc_rport_state(rport));
+		FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n",
+			     PTR_ERR(fp), fc_rport_state(rdata));
 		rdata->retries++;
 		/* no additional delay on exchange timeouts */
 		if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
@@ -499,24 +488,24 @@ static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp)
 		return;
 	}
 
-	return fc_rport_error(rport, fp);
+	return fc_rport_error(rdata, fp);
 }
 
 /**
  * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response
  * @sp: current sequence in the PLOGI exchange
  * @fp: response frame
- * @rp_arg: Fibre Channel remote port
+ * @rdata_arg: private remote port data
  *
  * Locking Note: This function will be called without the rport lock
  * held, but it will lock, call an _enter_* function or fc_rport_error
  * and then unlock the rport.
  */
 static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
-				void *rp_arg)
+				void *rdata_arg)
 {
-	struct fc_rport *rport = rp_arg;
-	struct fc_rport_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rdata_arg;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_els_flogi *plp = NULL;
 	unsigned int tov;
@@ -526,18 +515,18 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rport, "Received a PLOGI response\n");
+	FC_RPORT_DBG(rdata, "Received a PLOGI response\n");
 
 	if (rdata->rp_state != RPORT_ST_PLOGI) {
-		FC_RPORT_DBG(rport, "Received a PLOGI response, but in state "
-			     "%s\n", fc_rport_state(rport));
+		FC_RPORT_DBG(rdata, "Received a PLOGI response, but in state "
+			     "%s\n", fc_rport_state(rdata));
 		if (IS_ERR(fp))
 			goto err;
 		goto out;
 	}
 
 	if (IS_ERR(fp)) {
-		fc_rport_error_retry(rport, fp);
+		fc_rport_error_retry(rdata, fp);
 		goto err;
 	}
 
@@ -565,11 +554,11 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 		 * we skip PRLI and RTV and go straight to READY.
 		 */
 		if (rport->port_id >= FC_FID_DOM_MGR)
-			fc_rport_enter_ready(rport);
+			fc_rport_enter_ready(rdata);
 		else
-			fc_rport_enter_prli(rport);
+			fc_rport_enter_prli(rdata);
 	} else
-		fc_rport_error_retry(rport, fp);
+		fc_rport_error_retry(rdata, fp);
 
 out:
 	fc_frame_free(fp);
@@ -580,33 +569,33 @@ err:
 
 /**
  * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer
- * @rport: Fibre Channel remote port to send PLOGI to
+ * @rdata: private remote port data
  *
  * Locking Note: The rport lock is expected to be held before calling
  * this routine.
  */
-static void fc_rport_enter_plogi(struct fc_rport *rport)
+static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_frame *fp;
 
-	FC_RPORT_DBG(rport, "Port entered PLOGI state from %s state\n",
-		     fc_rport_state(rport));
+	FC_RPORT_DBG(rdata, "Port entered PLOGI state from %s state\n",
+		     fc_rport_state(rdata));
 
-	fc_rport_state_enter(rport, RPORT_ST_PLOGI);
+	fc_rport_state_enter(rdata, RPORT_ST_PLOGI);
 
 	rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
 	if (!fp) {
-		fc_rport_error_retry(rport, fp);
+		fc_rport_error_retry(rdata, fp);
 		return;
 	}
 	rdata->e_d_tov = lport->e_d_tov;
 
-	if (!lport->tt.elsct_send(lport, rport, fp, ELS_PLOGI,
-				  fc_rport_plogi_resp, rport, lport->e_d_tov))
-		fc_rport_error_retry(rport, fp);
+	if (!lport->tt.elsct_send(lport, rdata, fp, ELS_PLOGI,
+				  fc_rport_plogi_resp, rdata, lport->e_d_tov))
+		fc_rport_error_retry(rdata, fp);
 	else
 		get_device(&rport->dev);
 }
@@ -615,17 +604,17 @@ static void fc_rport_enter_plogi(struct fc_rport *rport)
  * fc_rport_prli_resp() - Process Login (PRLI) response handler
  * @sp: current sequence in the PRLI exchange
  * @fp: response frame
- * @rp_arg: Fibre Channel remote port
+ * @rdata_arg: private remote port data
  *
  * Locking Note: This function will be called without the rport lock
  * held, but it will lock, call an _enter_* function or fc_rport_error
  * and then unlock the rport.
  */
 static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
-			       void *rp_arg)
+			       void *rdata_arg)
 {
-	struct fc_rport *rport = rp_arg;
-	struct fc_rport_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rdata_arg;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct {
 		struct fc_els_prli prli;
 		struct fc_els_spp spp;
@@ -636,18 +625,18 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rport, "Received a PRLI response\n");
+	FC_RPORT_DBG(rdata, "Received a PRLI response\n");
 
 	if (rdata->rp_state != RPORT_ST_PRLI) {
-		FC_RPORT_DBG(rport, "Received a PRLI response, but in state "
-			     "%s\n", fc_rport_state(rport));
+		FC_RPORT_DBG(rdata, "Received a PRLI response, but in state "
+			     "%s\n", fc_rport_state(rdata));
 		if (IS_ERR(fp))
 			goto err;
 		goto out;
 	}
 
 	if (IS_ERR(fp)) {
-		fc_rport_error_retry(rport, fp);
+		fc_rport_error_retry(rdata, fp);
 		goto err;
 	}
 
@@ -667,11 +656,11 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 			roles |= FC_RPORT_ROLE_FCP_TARGET;
 
 		rport->roles = roles;
-		fc_rport_enter_rtv(rport);
+		fc_rport_enter_rtv(rdata);
 
 	} else {
-		FC_RPORT_DBG(rport, "Bad ELS response for PRLI command\n");
-		fc_rport_enter_delete(rport, RPORT_EV_FAILED);
+		FC_RPORT_DBG(rdata, "Bad ELS response for PRLI command\n");
+		fc_rport_enter_delete(rdata, RPORT_EV_FAILED);
 	}
 
 out:
@@ -685,42 +674,42 @@ err:
  * fc_rport_logo_resp() - Logout (LOGO) response handler
  * @sp: current sequence in the LOGO exchange
  * @fp: response frame
- * @rp_arg: Fibre Channel remote port
+ * @rdata_arg: private remote port data
  *
  * Locking Note: This function will be called without the rport lock
  * held, but it will lock, call an _enter_* function or fc_rport_error
  * and then unlock the rport.
  */
 static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
-			       void *rp_arg)
+			       void *rdata_arg)
 {
-	struct fc_rport *rport = rp_arg;
-	struct fc_rport_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rdata_arg;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	u8 op;
 
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rport, "Received a LOGO response\n");
+	FC_RPORT_DBG(rdata, "Received a LOGO response\n");
 
 	if (rdata->rp_state != RPORT_ST_LOGO) {
-		FC_RPORT_DBG(rport, "Received a LOGO response, but in state "
-			     "%s\n", fc_rport_state(rport));
+		FC_RPORT_DBG(rdata, "Received a LOGO response, but in state "
+			     "%s\n", fc_rport_state(rdata));
 		if (IS_ERR(fp))
 			goto err;
 		goto out;
 	}
 
 	if (IS_ERR(fp)) {
-		fc_rport_error_retry(rport, fp);
+		fc_rport_error_retry(rdata, fp);
 		goto err;
 	}
 
 	op = fc_frame_payload_op(fp);
 	if (op == ELS_LS_ACC) {
-		fc_rport_enter_rtv(rport);
+		fc_rport_enter_rtv(rdata);
 	} else {
-		FC_RPORT_DBG(rport, "Bad ELS response for LOGO command\n");
-		fc_rport_enter_delete(rport, RPORT_EV_LOGO);
+		FC_RPORT_DBG(rdata, "Bad ELS response for LOGO command\n");
+		fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
 	}
 
 out:
@@ -732,14 +721,14 @@ err:
 
 /**
  * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer
- * @rport: Fibre Channel remote port to send PRLI to
+ * @rdata: private remote port data
  *
  * Locking Note: The rport lock is expected to be held before calling
  * this routine.
  */
-static void fc_rport_enter_prli(struct fc_rport *rport)
+static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_lport *lport = rdata->local_port;
 	struct {
 		struct fc_els_prli prli;
@@ -747,20 +736,20 @@ static void fc_rport_enter_prli(struct fc_rport *rport)
 	} *pp;
 	struct fc_frame *fp;
 
-	FC_RPORT_DBG(rport, "Port entered PRLI state from %s state\n",
-		     fc_rport_state(rport));
+	FC_RPORT_DBG(rdata, "Port entered PRLI state from %s state\n",
+		     fc_rport_state(rdata));
 
-	fc_rport_state_enter(rport, RPORT_ST_PRLI);
+	fc_rport_state_enter(rdata, RPORT_ST_PRLI);
 
 	fp = fc_frame_alloc(lport, sizeof(*pp));
 	if (!fp) {
-		fc_rport_error_retry(rport, fp);
+		fc_rport_error_retry(rdata, fp);
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rport, fp, ELS_PRLI,
-				  fc_rport_prli_resp, rport, lport->e_d_tov))
-		fc_rport_error_retry(rport, fp);
+	if (!lport->tt.elsct_send(lport, rdata, fp, ELS_PRLI,
+				  fc_rport_prli_resp, rdata, lport->e_d_tov))
+		fc_rport_error_retry(rdata, fp);
 	else
 		get_device(&rport->dev);
 }
@@ -769,7 +758,7 @@ static void fc_rport_enter_prli(struct fc_rport *rport)
  * fc_rport_els_rtv_resp() - Request Timeout Value response handler
  * @sp: current sequence in the RTV exchange
  * @fp: response frame
- * @rp_arg: Fibre Channel remote port
+ * @rdata_arg: private remote port data
  *
  * Many targets don't seem to support this.
  *
@@ -778,26 +767,26 @@ static void fc_rport_enter_prli(struct fc_rport *rport)
  * and then unlock the rport.
  */
 static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
-			      void *rp_arg)
+			      void *rdata_arg)
 {
-	struct fc_rport *rport = rp_arg;
-	struct fc_rport_priv *rdata = rport->dd_data;
+	struct fc_rport_priv *rdata = rdata_arg;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	u8 op;
 
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rport, "Received a RTV response\n");
+	FC_RPORT_DBG(rdata, "Received a RTV response\n");
 
 	if (rdata->rp_state != RPORT_ST_RTV) {
-		FC_RPORT_DBG(rport, "Received a RTV response, but in state "
-			     "%s\n", fc_rport_state(rport));
+		FC_RPORT_DBG(rdata, "Received a RTV response, but in state "
+			     "%s\n", fc_rport_state(rdata));
 		if (IS_ERR(fp))
 			goto err;
 		goto out;
 	}
 
 	if (IS_ERR(fp)) {
-		fc_rport_error(rport, fp);
+		fc_rport_error(rdata, fp);
 		goto err;
 	}
 
@@ -823,7 +812,7 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
 		}
 	}
 
-	fc_rport_enter_ready(rport);
+	fc_rport_enter_ready(rdata);
 
 out:
 	fc_frame_free(fp);
@@ -834,62 +823,62 @@ err:
 
 /**
  * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer
- * @rport: Fibre Channel remote port to send RTV to
+ * @rdata: private remote port data
  *
  * Locking Note: The rport lock is expected to be held before calling
  * this routine.
  */
-static void fc_rport_enter_rtv(struct fc_rport *rport)
+static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
 {
 	struct fc_frame *fp;
-	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 
-	FC_RPORT_DBG(rport, "Port entered RTV state from %s state\n",
-		     fc_rport_state(rport));
+	FC_RPORT_DBG(rdata, "Port entered RTV state from %s state\n",
+		     fc_rport_state(rdata));
 
-	fc_rport_state_enter(rport, RPORT_ST_RTV);
+	fc_rport_state_enter(rdata, RPORT_ST_RTV);
 
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv));
 	if (!fp) {
-		fc_rport_error_retry(rport, fp);
+		fc_rport_error_retry(rdata, fp);
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rport, fp, ELS_RTV,
-				     fc_rport_rtv_resp, rport, lport->e_d_tov))
-		fc_rport_error_retry(rport, fp);
+	if (!lport->tt.elsct_send(lport, rdata, fp, ELS_RTV,
+				     fc_rport_rtv_resp, rdata, lport->e_d_tov))
+		fc_rport_error_retry(rdata, fp);
 	else
 		get_device(&rport->dev);
 }
 
 /**
  * fc_rport_enter_logo() - Send Logout (LOGO) request to peer
- * @rport: Fibre Channel remote port to send LOGO to
+ * @rdata: private remote port data
  *
  * Locking Note: The rport lock is expected to be held before calling
  * this routine.
  */
-static void fc_rport_enter_logo(struct fc_rport *rport)
+static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_frame *fp;
 
-	FC_RPORT_DBG(rport, "Port entered LOGO state from %s state\n",
-		     fc_rport_state(rport));
+	FC_RPORT_DBG(rdata, "Port entered LOGO state from %s state\n",
+		     fc_rport_state(rdata));
 
-	fc_rport_state_enter(rport, RPORT_ST_LOGO);
+	fc_rport_state_enter(rdata, RPORT_ST_LOGO);
 
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo));
 	if (!fp) {
-		fc_rport_error_retry(rport, fp);
+		fc_rport_error_retry(rdata, fp);
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rport, fp, ELS_LOGO,
-				  fc_rport_logo_resp, rport, lport->e_d_tov))
-		fc_rport_error_retry(rport, fp);
+	if (!lport->tt.elsct_send(lport, rdata, fp, ELS_LOGO,
+				  fc_rport_logo_resp, rdata, lport->e_d_tov))
+		fc_rport_error_retry(rdata, fp);
 	else
 		get_device(&rport->dev);
 }
@@ -899,16 +888,15 @@ static void fc_rport_enter_logo(struct fc_rport *rport)
  * fc_rport_recv_req() - Receive a request from a rport
  * @sp: current sequence in the PLOGI exchange
  * @fp: response frame
- * @rp_arg: Fibre Channel remote port
+ * @rdata_arg: private remote port data
  *
  * Locking Note: Called without the rport lock held. This
  * function will hold the rport lock, call an _enter_*
  * function and then unlock the rport.
  */
 void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
-		       struct fc_rport *rport)
+		       struct fc_rport_priv *rdata)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 
 	struct fc_frame_header *fh;
@@ -927,16 +915,16 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 		op = fc_frame_payload_op(fp);
 		switch (op) {
 		case ELS_PLOGI:
-			fc_rport_recv_plogi_req(rport, sp, fp);
+			fc_rport_recv_plogi_req(rdata, sp, fp);
 			break;
 		case ELS_PRLI:
-			fc_rport_recv_prli_req(rport, sp, fp);
+			fc_rport_recv_prli_req(rdata, sp, fp);
 			break;
 		case ELS_PRLO:
-			fc_rport_recv_prlo_req(rport, sp, fp);
+			fc_rport_recv_prlo_req(rdata, sp, fp);
 			break;
 		case ELS_LOGO:
-			fc_rport_recv_logo_req(rport, sp, fp);
+			fc_rport_recv_logo_req(rdata, sp, fp);
 			break;
 		case ELS_RRQ:
 			els_data.fp = fp;
@@ -958,17 +946,17 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 
 /**
  * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request
- * @rport: Fibre Channel remote port that initiated PLOGI
+ * @rdata: private remote port data
  * @sp: current sequence in the PLOGI exchange
  * @fp: PLOGI request frame
  *
  * Locking Note: The rport lock is exected to be held before calling
  * this function.
  */
-static void fc_rport_recv_plogi_req(struct fc_rport *rport,
+static void fc_rport_recv_plogi_req(struct fc_rport_priv *rdata,
 				    struct fc_seq *sp, struct fc_frame *rx_fp)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_frame *fp = rx_fp;
 	struct fc_exch *ep;
@@ -984,13 +972,13 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
 
 	fh = fc_frame_header_get(fp);
 
-	FC_RPORT_DBG(rport, "Received PLOGI request while in state %s\n",
-		     fc_rport_state(rport));
+	FC_RPORT_DBG(rdata, "Received PLOGI request while in state %s\n",
+		     fc_rport_state(rdata));
 
 	sid = ntoh24(fh->fh_s_id);
 	pl = fc_frame_payload_get(fp, sizeof(*pl));
 	if (!pl) {
-		FC_RPORT_DBG(rport, "Received PLOGI too short\n");
+		FC_RPORT_DBG(rdata, "Received PLOGI too short\n");
 		WARN_ON(1);
 		/* XXX TBD: send reject? */
 		fc_frame_free(fp);
@@ -1012,25 +1000,25 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
 	 */
 	switch (rdata->rp_state) {
 	case RPORT_ST_INIT:
-		FC_RPORT_DBG(rport, "Received PLOGI, wwpn %llx state INIT "
+		FC_RPORT_DBG(rdata, "Received PLOGI, wwpn %llx state INIT "
 			     "- reject\n", (unsigned long long)wwpn);
 		reject = ELS_RJT_UNSUP;
 		break;
 	case RPORT_ST_PLOGI:
-		FC_RPORT_DBG(rport, "Received PLOGI in PLOGI state %d\n",
+		FC_RPORT_DBG(rdata, "Received PLOGI in PLOGI state %d\n",
 			     rdata->rp_state);
 		if (wwpn < lport->wwpn)
 			reject = ELS_RJT_INPROG;
 		break;
 	case RPORT_ST_PRLI:
 	case RPORT_ST_READY:
-		FC_RPORT_DBG(rport, "Received PLOGI in logged-in state %d "
+		FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d "
 			     "- ignored for now\n", rdata->rp_state);
 		/* XXX TBD - should reset */
 		break;
 	case RPORT_ST_DELETE:
 	default:
-		FC_RPORT_DBG(rport, "Received PLOGI in unexpected "
+		FC_RPORT_DBG(rdata, "Received PLOGI in unexpected "
 			     "state %d\n", rdata->rp_state);
 		fc_frame_free(fp);
 		return;
@@ -1074,24 +1062,24 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
 				       FC_TYPE_ELS, f_ctl, 0);
 			lport->tt.seq_send(lport, sp, fp);
 			if (rdata->rp_state == RPORT_ST_PLOGI)
-				fc_rport_enter_prli(rport);
+				fc_rport_enter_prli(rdata);
 		}
 	}
 }
 
 /**
  * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request
- * @rport: Fibre Channel remote port that initiated PRLI
+ * @rdata: private remote port data
  * @sp: current sequence in the PRLI exchange
  * @fp: PRLI request frame
  *
  * Locking Note: The rport lock is exected to be held before calling
  * this function.
  */
-static void fc_rport_recv_prli_req(struct fc_rport *rport,
+static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 				   struct fc_seq *sp, struct fc_frame *rx_fp)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_exch *ep;
 	struct fc_frame *fp;
@@ -1115,8 +1103,8 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
 
 	fh = fc_frame_header_get(rx_fp);
 
-	FC_RPORT_DBG(rport, "Received PRLI request while in state %s\n",
-		     fc_rport_state(rport));
+	FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n",
+		     fc_rport_state(rdata));
 
 	switch (rdata->rp_state) {
 	case RPORT_ST_PRLI:
@@ -1220,7 +1208,7 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
 		 */
 		switch (rdata->rp_state) {
 		case RPORT_ST_PRLI:
-			fc_rport_enter_ready(rport);
+			fc_rport_enter_ready(rdata);
 			break;
 		case RPORT_ST_READY:
 			break;
@@ -1233,17 +1221,17 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
 
 /**
  * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request
- * @rport: Fibre Channel remote port that initiated PRLO
+ * @rdata: private remote port data
  * @sp: current sequence in the PRLO exchange
  * @fp: PRLO request frame
  *
  * Locking Note: The rport lock is exected to be held before calling
  * this function.
  */
-static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
+static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
+				   struct fc_seq *sp,
 				   struct fc_frame *fp)
 {
-	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 
 	struct fc_frame_header *fh;
@@ -1251,8 +1239,8 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
 
 	fh = fc_frame_header_get(fp);
 
-	FC_RPORT_DBG(rport, "Received PRLO request while in state %s\n",
-		     fc_rport_state(rport));
+	FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n",
+		     fc_rport_state(rdata));
 
 	if (rdata->rp_state == RPORT_ST_DELETE) {
 		fc_frame_free(fp);
@@ -1268,24 +1256,24 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
 
 /**
  * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request
- * @rport: Fibre Channel remote port that initiated LOGO
+ * @rdata: private remote port data
  * @sp: current sequence in the LOGO exchange
  * @fp: LOGO request frame
  *
  * Locking Note: The rport lock is exected to be held before calling
  * this function.
  */
-static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp,
+static void fc_rport_recv_logo_req(struct fc_rport_priv *rdata,
+				   struct fc_seq *sp,
 				   struct fc_frame *fp)
 {
 	struct fc_frame_header *fh;
-	struct fc_rport_priv *rdata = rport->dd_data;
 	struct fc_lport *lport = rdata->local_port;
 
 	fh = fc_frame_header_get(fp);
 
-	FC_RPORT_DBG(rport, "Received LOGO request while in state %s\n",
-		     fc_rport_state(rport));
+	FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",
+		     fc_rport_state(rdata));
 
 	if (rdata->rp_state == RPORT_ST_DELETE) {
 		fc_frame_free(fp);
@@ -1293,7 +1281,7 @@ static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp,
 	}
 
 	rdata->event = RPORT_EV_LOGO;
-	fc_rport_state_enter(rport, RPORT_ST_DELETE);
+	fc_rport_state_enter(rdata, RPORT_ST_DELETE);
 	queue_work(rport_event_queue, &rdata->event_work);
 
 	lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index a0ff61c..3ede1ab 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -249,10 +249,13 @@ static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
 /**
  * fc_els_fill - Fill in an ELS  request frame
  */
-static inline int fc_els_fill(struct fc_lport *lport, struct fc_rport *rport,
+static inline int fc_els_fill(struct fc_lport *lport,
+		       struct fc_rport_priv *rdata,
 		       struct fc_frame *fp, unsigned int op,
 		       enum fc_rctl *r_ctl, u32 *did, enum fc_fh_type *fh_type)
 {
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
+
 	switch (op) {
 	case ELS_PLOGI:
 		fc_plogi_fill(lport, fp, ELS_PLOGI);
@@ -272,7 +275,7 @@ static inline int fc_els_fill(struct fc_lport *lport, struct fc_rport *rport,
 		 * is port logo, therefore
 		 * set did to rport id.
 		 */
-		if (rport)
+		if (rdata)
 			*did = rport->port_id;
 		break;
 
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 2fdd8ac..df57cb7 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -75,10 +75,10 @@ do {								\
 				(lport)->host->host_no,			\
 				(port_id), ##args))
 
-#define FC_RPORT_DBG(rport, fmt, args...)				\
+#define FC_RPORT_DBG(rdata, fmt, args...)				\
 do {									\
-	struct fc_rport_priv *rdata = rport->dd_data;			\
 	struct fc_lport *lport = rdata->local_port;			\
+	struct fc_rport *rport = PRIV_TO_RPORT(rdata);			\
 	FC_RPORT_ID_DBG(lport, rport->port_id, fmt, ##args);		\
 } while (0)
 
@@ -185,8 +185,10 @@ enum fc_rport_event {
  */
 #define fc_rport_priv fc_rport_libfc_priv
 
+struct fc_rport_priv;
+
 struct fc_rport_operations {
-	void (*event_callback)(struct fc_lport *, struct fc_rport *,
+	void (*event_callback)(struct fc_lport *, struct fc_rport_priv *,
 			       enum fc_rport_event);
 };
 
@@ -422,7 +424,7 @@ struct libfc_function_template {
 	 * STATUS: OPTIONAL
 	 */
 	struct fc_seq *(*elsct_send)(struct fc_lport *lport,
-				     struct fc_rport *rport,
+				     struct fc_rport_priv *,
 				     struct fc_frame *fp,
 				     unsigned int op,
 				     void (*resp)(struct fc_seq *,
@@ -567,8 +569,8 @@ struct libfc_function_template {
 	/*
 	 * Create a remote port
 	 */
-	struct fc_rport *(*rport_create)(struct fc_lport *,
-					 struct fc_rport_identifiers *);
+	struct fc_rport_priv *(*rport_create)(struct fc_lport *,
+					      struct fc_rport_identifiers *);
 
 	/*
 	 * Initiates the RP state machine. It is called from the LP module.
@@ -581,7 +583,7 @@ struct libfc_function_template {
 	 *
 	 * STATUS: OPTIONAL
 	 */
-	int (*rport_login)(struct fc_rport *rport);
+	int (*rport_login)(struct fc_rport_priv *);
 
 	/*
 	 * Logoff, and remove the rport from the transport if
@@ -589,7 +591,7 @@ struct libfc_function_template {
 	 *
 	 * STATUS: OPTIONAL
 	 */
-	int (*rport_logoff)(struct fc_rport *rport);
+	int (*rport_logoff)(struct fc_rport_priv *);
 
 	/*
 	 * Recieve a request from a remote port.
@@ -597,14 +599,14 @@ struct libfc_function_template {
 	 * STATUS: OPTIONAL
 	 */
 	void (*rport_recv_req)(struct fc_seq *, struct fc_frame *,
-			       struct fc_rport *);
+			       struct fc_rport_priv *);
 
 	/*
 	 * lookup an rport by it's port ID.
 	 *
 	 * STATUS: OPTIONAL
 	 */
-	struct fc_rport *(*rport_lookup)(const struct fc_lport *, u32);
+	struct fc_rport_priv *(*rport_lookup)(const struct fc_lport *, u32);
 
 	/*
 	 * Send a fcp cmd from fsp pkt.
@@ -694,8 +696,8 @@ struct fc_lport {
 	/* Associations */
 	struct Scsi_Host	*host;
 	struct list_head	ema_list;
-	struct fc_rport		*dns_rp;
-	struct fc_rport		*ptp_rp;
+	struct fc_rport_priv	*dns_rp;
+	struct fc_rport_priv	*ptp_rp;
 	void			*scsi_priv;
 	struct fc_disc          disc;
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 28/64] libfc: change elsct to use FC_ID instead of rdata
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (26 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 27/64] libfc: make fc_rport_priv the primary rport interface Robert Love
@ 2009-08-25 21:00 ` Robert Love
  2009-08-25 21:01 ` [PATCH 29/64] libfc: make rport structure optional Robert Love
                   ` (35 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:00 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

tt.elsct_send is used by both FCP and by the rport state machine.
After further patches, these two modules will use different
structures for the remote port.

So, change elsct_send to use the FC_ID instead of the fc_rport_priv
as its argument.  It currently only uses the FC_ID anyway.

For CT requests the destination FC_ID is still implicitly 0xfffffc.
After further patches the did arg on CT requests will be used to
specify the FC_ID being inquired about for GPN_ID or other queries.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |    2 +-
 drivers/scsi/libfc/fc_elsct.c |   11 ++++++-----
 drivers/scsi/libfc/fc_fcp.c   |    2 +-
 drivers/scsi/libfc/fc_lport.c |   12 ++++++------
 drivers/scsi/libfc/fc_rport.c |    8 ++++----
 include/scsi/fc_encode.h      |   26 +++++---------------------
 include/scsi/libfc.h          |    2 +-
 7 files changed, 24 insertions(+), 39 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 448ffc3..4b1f9fa 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -526,7 +526,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))
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index 2b8a3bb..5e8b011 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -32,7 +32,7 @@
  * fc_elsct_send - sends ELS/CT frame
  */
 static struct fc_seq *fc_elsct_send(struct fc_lport *lport,
-				    struct fc_rport_priv *rdata,
+				    u32 did,
 				    struct fc_frame *fp,
 				    unsigned int op,
 				    void (*resp)(struct fc_seq *,
@@ -41,16 +41,17 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport,
 				    void *arg, u32 timer_msec)
 {
 	enum fc_rctl r_ctl;
-	u32 did = FC_FID_NONE;
 	enum fc_fh_type fh_type;
 	int rc;
 
 	/* ELS requests */
 	if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS))
-		rc = fc_els_fill(lport, rdata, fp, op, &r_ctl, &did, &fh_type);
-	else
+		rc = fc_els_fill(lport, did, fp, op, &r_ctl, &fh_type);
+	else {
 		/* CT requests */
-		rc = fc_ct_fill(lport, fp, op, &r_ctl, &did, &fh_type);
+		rc = fc_ct_fill(lport, fp, op, &r_ctl, &fh_type);
+		did = FC_FID_DIR_SERV;
+	}
 
 	if (rc)
 		return NULL;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index a622096..59a4408 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1308,7 +1308,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
 	fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id,
 		       fc_host_port_id(rp->local_port->host), FC_TYPE_ELS,
 		       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
-	if (lp->tt.elsct_send(lp, rport->dd_data, fp, ELS_REC, fc_fcp_rec_resp,
+	if (lp->tt.elsct_send(lp, rport->port_id, fp, ELS_REC, fc_fcp_rec_resp,
 			      fsp, jiffies_to_msecs(FC_SCSI_REC_TOV))) {
 		fc_fcp_pkt_hold(fsp);		/* hold while REC outstanding */
 		return;
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 3c15abd..aa605d2 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1217,7 +1217,7 @@ static void fc_lport_enter_scr(struct fc_lport *lport)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, NULL, fp, ELS_SCR,
+	if (!lport->tt.elsct_send(lport, FC_FID_FCTRL, fp, ELS_SCR,
 				  fc_lport_scr_resp, lport, lport->e_d_tov))
 		fc_lport_error(lport, fp);
 }
@@ -1258,7 +1258,7 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, NULL, fp, FC_NS_RFT_ID,
+	if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RFT_ID,
 				  fc_lport_rft_id_resp,
 				  lport, lport->e_d_tov))
 		fc_lport_error(lport, fp);
@@ -1287,7 +1287,7 @@ static void fc_lport_enter_rpn_id(struct fc_lport *lport)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, NULL, fp, FC_NS_RPN_ID,
+	if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RPN_ID,
 				  fc_lport_rpn_id_resp,
 				  lport, lport->e_d_tov))
 		fc_lport_error(lport, fp);
@@ -1443,8 +1443,8 @@ static void fc_lport_enter_logo(struct fc_lport *lport)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, NULL, fp, ELS_LOGO, fc_lport_logo_resp,
-				  lport, lport->e_d_tov))
+	if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_LOGO,
+				  fc_lport_logo_resp, lport, lport->e_d_tov))
 		fc_lport_error(lport, fp);
 }
 
@@ -1567,7 +1567,7 @@ void fc_lport_enter_flogi(struct fc_lport *lport)
 	if (!fp)
 		return fc_lport_error(lport, fp);
 
-	if (!lport->tt.elsct_send(lport, NULL, fp, ELS_FLOGI,
+	if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_FLOGI,
 				  fc_lport_flogi_resp, lport, lport->e_d_tov))
 		fc_lport_error(lport, fp);
 }
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 13d3d75..20371b4 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -593,7 +593,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
 	}
 	rdata->e_d_tov = lport->e_d_tov;
 
-	if (!lport->tt.elsct_send(lport, rdata, fp, ELS_PLOGI,
+	if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_PLOGI,
 				  fc_rport_plogi_resp, rdata, lport->e_d_tov))
 		fc_rport_error_retry(rdata, fp);
 	else
@@ -747,7 +747,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rdata, fp, ELS_PRLI,
+	if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_PRLI,
 				  fc_rport_prli_resp, rdata, lport->e_d_tov))
 		fc_rport_error_retry(rdata, fp);
 	else
@@ -845,7 +845,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rdata, fp, ELS_RTV,
+	if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_RTV,
 				     fc_rport_rtv_resp, rdata, lport->e_d_tov))
 		fc_rport_error_retry(rdata, fp);
 	else
@@ -876,7 +876,7 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rdata, fp, ELS_LOGO,
+	if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_LOGO,
 				  fc_rport_logo_resp, rdata, lport->e_d_tov))
 		fc_rport_error_retry(rdata, fp);
 	else
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index 3ede1ab..24bf764 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -79,8 +79,9 @@ static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp,
 /**
  * fc_ct_fill - Fill in a name service request frame
  */
-static inline int fc_ct_fill(struct fc_lport *lport, struct fc_frame *fp,
-		      unsigned int op, enum fc_rctl *r_ctl, u32 *did,
+static inline int fc_ct_fill(struct fc_lport *lport,
+		      struct fc_frame *fp,
+		      unsigned int op, enum fc_rctl *r_ctl,
 		      enum fc_fh_type *fh_type)
 {
 	struct fc_ct_req *ct;
@@ -110,7 +111,6 @@ static inline int fc_ct_fill(struct fc_lport *lport, struct fc_frame *fp,
 		return -EINVAL;
 	}
 	*r_ctl = FC_RCTL_DD_UNSOL_CTL;
-	*did = FC_FID_DIR_SERV;
 	*fh_type = FC_TYPE_CT;
 	return 0;
 }
@@ -250,53 +250,37 @@ static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
  * fc_els_fill - Fill in an ELS  request frame
  */
 static inline int fc_els_fill(struct fc_lport *lport,
-		       struct fc_rport_priv *rdata,
+		       u32 did,
 		       struct fc_frame *fp, unsigned int op,
-		       enum fc_rctl *r_ctl, u32 *did, enum fc_fh_type *fh_type)
+		       enum fc_rctl *r_ctl, enum fc_fh_type *fh_type)
 {
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
-
 	switch (op) {
 	case ELS_PLOGI:
 		fc_plogi_fill(lport, fp, ELS_PLOGI);
-		*did = rport->port_id;
 		break;
 
 	case ELS_FLOGI:
 		fc_flogi_fill(lport, fp);
-		*did = FC_FID_FLOGI;
 		break;
 
 	case ELS_LOGO:
 		fc_logo_fill(lport, fp);
-		*did = FC_FID_FLOGI;
-		/*
-		 * if rport is valid then it
-		 * is port logo, therefore
-		 * set did to rport id.
-		 */
-		if (rdata)
-			*did = rport->port_id;
 		break;
 
 	case ELS_RTV:
 		fc_rtv_fill(lport, fp);
-		*did = rport->port_id;
 		break;
 
 	case ELS_REC:
 		fc_rec_fill(lport, fp);
-		*did = rport->port_id;
 		break;
 
 	case ELS_PRLI:
 		fc_prli_fill(lport, fp);
-		*did = rport->port_id;
 		break;
 
 	case ELS_SCR:
 		fc_scr_fill(lport, fp);
-		*did = FC_FID_FCTRL;
 		break;
 
 	default:
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index df57cb7..2473167 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -424,7 +424,7 @@ struct libfc_function_template {
 	 * STATUS: OPTIONAL
 	 */
 	struct fc_seq *(*elsct_send)(struct fc_lport *lport,
-				     struct fc_rport_priv *,
+				     u32 did,
 				     struct fc_frame *fp,
 				     unsigned int op,
 				     void (*resp)(struct fc_seq *,


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 29/64] libfc: make rport structure optional
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (27 preceding siblings ...)
  2009-08-25 21:00 ` [PATCH 28/64] libfc: change elsct to use FC_ID instead of rdata Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 30/64] libfc: rearrange code in fc_rport_work Robert Love
                   ` (34 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Allow a struct fc_rport_priv to have no fc_rport associated with it.
This sets up to remove the need for "rogue" rports.

Add a few fields to fc_rport_priv that are needed before the fc_rport
is created.  These are the ids, maxframe_size, classes, and rport pointer.

Remove the macro PRIV_TO_RPORT().  Just use rdata->rport where appropriate.

To take the place of the get_device()/put_device ops that were used to
hold both the rport and rdata, add a reference count to rdata structures
using kref.  When kref_get decrements the refcount to zero, a new template
function releasing the rdata should be called.  This will take care of
freeing the rdata and releasing the hold on the rport (for now).  After
subsequent patches make the rport truly optional, this release function
will simply free the rdata.

Remove the simple inline function fc_rport_set_name(), which becomes
semanticly ambiguous otherwise.  The caller will set the port_name and
node_name in the rdata->Ids, which will later be copied to the rport
when it its created.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |   54 ++++++++--------------
 drivers/scsi/libfc/fc_lport.c |   14 ++----
 drivers/scsi/libfc/fc_rport.c |  102 +++++++++++++++++++++++------------------
 include/scsi/libfc.h          |   29 ++++++------
 4 files changed, 98 insertions(+), 101 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 4b1f9fa..5f839b6 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -47,7 +47,7 @@
 
 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_done(struct fc_disc *);
 static void fc_disc_timeout(struct work_struct *);
@@ -63,12 +63,10 @@ struct fc_rport_priv *fc_disc_lookup_rport(const struct fc_lport *lport,
 					   u32 port_id)
 {
 	const struct fc_disc *disc = &lport->disc;
-	struct fc_rport *rport;
 	struct fc_rport_priv *rdata;
 
 	list_for_each_entry(rdata, &disc->rports, peers) {
-		rport = PRIV_TO_RPORT(rdata);
-		if (rport->port_id == port_id)
+		if (rdata->ids.port_id == port_id)
 			return rdata;
 	}
 	return NULL;
@@ -115,10 +113,9 @@ static void fc_disc_rport_callback(struct fc_lport *lport,
 				   enum fc_rport_event event)
 {
 	struct fc_disc *disc = &lport->disc;
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 
 	FC_DISC_DBG(disc, "Received a %d event for port (%6x)\n", event,
-		    rport->port_id);
+		    rdata->ids.port_id);
 
 	switch (event) {
 	case RPORT_EV_CREATED:
@@ -320,8 +317,6 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
 			  struct fc_lport *lport)
 {
 	struct fc_rport_priv *rdata;
-	struct fc_rport *rport;
-	struct fc_rport_identifiers ids;
 	struct fc_disc *disc = &lport->disc;
 
 	/*
@@ -349,18 +344,12 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
 	 */
 	rdata = disc->lport->ptp_rp;
 	if (rdata) {
-		rport = PRIV_TO_RPORT(rdata);
-		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)) {
+		kref_get(&rdata->kref);
+		if (!fc_disc_new_target(disc, rdata, &rdata->ids)) {
 			disc->event = DISC_EV_SUCCESS;
 			fc_disc_done(disc);
 		}
-		put_device(&rport->dev);
+		kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
 	} else {
 		fc_disc_gpn_ft_req(disc);	/* get ports by FC-4 type */
 	}
@@ -375,28 +364,27 @@ static struct fc_rport_operations fc_disc_rport_ops = {
 /**
  * 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_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
@@ -404,27 +392,23 @@ 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.
 			 */
-			rdata = rport->dd_data;
 			list_del(&rdata->peers);
 			lport->tt.rport_logoff(rdata);
-			rport = NULL;
+			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) {
+		if (!rdata) {
 			rdata = lport->tt.rport_lookup(lport, ids->port_id);
-			if (!rport) {
+			if (!rdata) {
 				rdata = lport->tt.rport_create(lport, ids);
+				if (!rdata)
+					error = -ENOMEM;
 			}
-			if (!rdata)
-				error = -ENOMEM;
-			else
-				rport = PRIV_TO_RPORT(rdata);
 		}
-		if (rport) {
-			rdata = rport->dd_data;
+		if (rdata) {
 			rdata->ops = &fc_disc_rport_ops;
 			rdata->rp_state = RPORT_ST_INIT;
 			list_add_tail(&rdata->peers, &disc->rogue_rports);
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index aa605d2..a7fe6b8 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -143,14 +143,12 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
 				    struct fc_rport_priv *rdata,
 				    enum fc_rport_event event)
 {
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
-
 	FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event,
-		     rport->port_id);
+		     rdata->ids.port_id);
 
 	switch (event) {
 	case RPORT_EV_CREATED:
-		if (rport->port_id == FC_FID_DIR_SERV) {
+		if (rdata->ids.port_id == FC_FID_DIR_SERV) {
 			mutex_lock(&lport->lp_mutex);
 			if (lport->state == LPORT_ST_DNS) {
 				lport->dns_rp = rdata;
@@ -160,7 +158,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
 					     "on port (%6x) for the directory "
 					     "server, but the lport is not "
 					     "in the DNS state, it's in the "
-					     "%d state", rport->port_id,
+					     "%d state", rdata->ids.port_id,
 					     lport->state);
 				lport->tt.rport_logoff(rdata);
 			}
@@ -168,12 +166,12 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
 		} else
 			FC_LPORT_DBG(lport, "Received an event for port (%6x) "
 				     "which is not the directory server\n",
-				     rport->port_id);
+				     rdata->ids.port_id);
 		break;
 	case RPORT_EV_LOGO:
 	case RPORT_EV_FAILED:
 	case RPORT_EV_STOP:
-		if (rport->port_id == FC_FID_DIR_SERV) {
+		if (rdata->ids.port_id == FC_FID_DIR_SERV) {
 			mutex_lock(&lport->lp_mutex);
 			lport->dns_rp = NULL;
 			mutex_unlock(&lport->lp_mutex);
@@ -181,7 +179,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
 		} else
 			FC_LPORT_DBG(lport, "Received an event for port (%6x) "
 				     "which is not the directory server\n",
-				     rport->port_id);
+				     rdata->ids.port_id);
 		break;
 	case RPORT_EV_NONE:
 		break;
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 20371b4..69f6e58 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -120,7 +120,10 @@ struct fc_rport_priv *fc_rport_rogue_create(struct fc_lport *lport,
 	device_initialize(&rport->dev);
 	rport->dev.release = fc_rport_rogue_destroy;
 
+	rdata->ids = *ids;
+	kref_init(&rdata->kref);
 	mutex_init(&rdata->rp_mutex);
+	rdata->rport = rport;
 	rdata->local_port = lport;
 	rdata->trans_state = FC_PORTSTATE_ROGUE;
 	rdata->rp_state = RPORT_ST_INIT;
@@ -129,6 +132,7 @@ struct fc_rport_priv *fc_rport_rogue_create(struct fc_lport *lport,
 	rdata->ops = NULL;
 	rdata->e_d_tov = lport->e_d_tov;
 	rdata->r_a_tov = lport->r_a_tov;
+	rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
 	INIT_WORK(&rdata->event_work, fc_rport_work);
 	/*
@@ -141,6 +145,20 @@ struct fc_rport_priv *fc_rport_rogue_create(struct fc_lport *lport,
 }
 
 /**
+ * fc_rport_destroy() - free a remote port after last reference is released.
+ * @kref: pointer to kref inside struct fc_rport_priv
+ */
+static void fc_rport_destroy(struct kref *kref)
+{
+	struct fc_rport_priv *rdata;
+	struct fc_rport *rport;
+
+	rdata = container_of(kref, struct fc_rport_priv, kref);
+	rport = rdata->rport;
+	put_device(&rport->dev);
+}
+
+/**
  * fc_rport_state() - return a string for the state the rport is in
  * @rdata: remote port private data
  */
@@ -215,22 +233,19 @@ static void fc_rport_work(struct work_struct *work)
 	enum fc_rport_trans_state trans_state;
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_rport_operations *rport_ops;
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
+	struct fc_rport *rport;
 
 	mutex_lock(&rdata->rp_mutex);
 	event = rdata->event;
 	rport_ops = rdata->ops;
+	rport = rdata->rport;
 
 	if (event == RPORT_EV_CREATED) {
 		struct fc_rport *new_rport;
 		struct fc_rport_priv *new_rdata;
 		struct fc_rport_identifiers ids;
 
-		ids.port_id = rport->port_id;
-		ids.roles = rport->roles;
-		ids.port_name = rport->port_name;
-		ids.node_name = rport->node_name;
-
+		ids = rdata->ids;
 		rdata->event = RPORT_EV_NONE;
 		mutex_unlock(&rdata->rp_mutex);
 
@@ -240,15 +255,20 @@ static void fc_rport_work(struct work_struct *work)
 			 * Switch from the rogue rport to the rport
 			 * returned by the FC class.
 			 */
-			new_rport->maxframe_size = rport->maxframe_size;
+			new_rport->maxframe_size = rdata->maxframe_size;
 
 			new_rdata = new_rport->dd_data;
+			new_rdata->rport = new_rport;
+			new_rdata->ids = ids;
 			new_rdata->e_d_tov = rdata->e_d_tov;
 			new_rdata->r_a_tov = rdata->r_a_tov;
 			new_rdata->ops = rdata->ops;
 			new_rdata->local_port = rdata->local_port;
 			new_rdata->flags = FC_RP_FLAGS_REC_SUPPORTED;
 			new_rdata->trans_state = FC_PORTSTATE_REAL;
+			new_rdata->maxframe_size = rdata->maxframe_size;
+			new_rdata->supported_classes = rdata->supported_classes;
+			kref_init(&new_rdata->kref);
 			mutex_init(&new_rdata->rp_mutex);
 			INIT_DELAYED_WORK(&new_rdata->retry_work,
 					  fc_rport_timeout);
@@ -261,12 +281,11 @@ static void fc_rport_work(struct work_struct *work)
 			       " memory for rport (%6x)\n", ids.port_id);
 			event = RPORT_EV_FAILED;
 		}
-		if (rport->port_id != FC_FID_DIR_SERV)
+		if (rdata->ids.port_id != FC_FID_DIR_SERV)
 			if (rport_ops->event_callback)
 				rport_ops->event_callback(lport, rdata,
 							  RPORT_EV_FAILED);
-		put_device(&rport->dev);
-		rport = new_rport;
+		kref_put(&rdata->kref, lport->tt.rport_destroy);
 		rdata = new_rport->dd_data;
 		if (rport_ops->event_callback)
 			rport_ops->event_callback(lport, rdata, event);
@@ -279,7 +298,7 @@ static void fc_rport_work(struct work_struct *work)
 			rport_ops->event_callback(lport, rdata, event);
 		cancel_delayed_work_sync(&rdata->retry_work);
 		if (trans_state == FC_PORTSTATE_ROGUE)
-			put_device(&rport->dev);
+			kref_put(&rdata->kref, lport->tt.rport_destroy);
 		else {
 			port_id = rport->port_id;
 			fc_remote_port_delete(rport);
@@ -505,7 +524,6 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 				void *rdata_arg)
 {
 	struct fc_rport_priv *rdata = rdata_arg;
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_els_flogi *plp = NULL;
 	unsigned int tov;
@@ -533,8 +551,8 @@ 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) {
-		rport->port_name = get_unaligned_be64(&plp->fl_wwpn);
-		rport->node_name = get_unaligned_be64(&plp->fl_wwnn);
+		rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn);
+		rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn);
 
 		tov = ntohl(plp->fl_csp.sp_e_d_tov);
 		if (ntohs(plp->fl_csp.sp_features) & FC_SP_FT_EDTR)
@@ -546,14 +564,13 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 		if (cssp_seq < csp_seq)
 			csp_seq = cssp_seq;
 		rdata->max_seq = csp_seq;
-		rport->maxframe_size =
-			fc_plogi_get_maxframe(plp, lport->mfs);
+		rdata->maxframe_size = fc_plogi_get_maxframe(plp, lport->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)
+		if (rdata->ids.port_id >= FC_FID_DOM_MGR)
 			fc_rport_enter_ready(rdata);
 		else
 			fc_rport_enter_prli(rdata);
@@ -564,7 +581,7 @@ out:
 	fc_frame_free(fp);
 err:
 	mutex_unlock(&rdata->rp_mutex);
-	put_device(&rport->dev);
+	kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
 }
 
 /**
@@ -577,7 +594,6 @@ err:
 static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
 {
 	struct fc_lport *lport = rdata->local_port;
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_frame *fp;
 
 	FC_RPORT_DBG(rdata, "Port entered PLOGI state from %s state\n",
@@ -585,7 +601,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
 
 	fc_rport_state_enter(rdata, RPORT_ST_PLOGI);
 
-	rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
+	rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
 	if (!fp) {
 		fc_rport_error_retry(rdata, fp);
@@ -593,11 +609,11 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
 	}
 	rdata->e_d_tov = lport->e_d_tov;
 
-	if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_PLOGI,
+	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI,
 				  fc_rport_plogi_resp, rdata, lport->e_d_tov))
 		fc_rport_error_retry(rdata, fp);
 	else
-		get_device(&rport->dev);
+		kref_get(&rdata->kref);
 }
 
 /**
@@ -614,7 +630,6 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 			       void *rdata_arg)
 {
 	struct fc_rport_priv *rdata = rdata_arg;
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct {
 		struct fc_els_prli prli;
 		struct fc_els_spp spp;
@@ -649,13 +664,13 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 				rdata->flags |= FC_RP_FLAGS_RETRY;
 		}
 
-		rport->supported_classes = FC_COS_CLASS3;
+		rdata->supported_classes = FC_COS_CLASS3;
 		if (fcp_parm & FCP_SPPF_INIT_FCN)
 			roles |= FC_RPORT_ROLE_FCP_INITIATOR;
 		if (fcp_parm & FCP_SPPF_TARG_FCN)
 			roles |= FC_RPORT_ROLE_FCP_TARGET;
 
-		rport->roles = roles;
+		rdata->ids.roles = roles;
 		fc_rport_enter_rtv(rdata);
 
 	} else {
@@ -667,7 +682,7 @@ out:
 	fc_frame_free(fp);
 err:
 	mutex_unlock(&rdata->rp_mutex);
-	put_device(&rport->dev);
+	kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
 }
 
 /**
@@ -684,7 +699,6 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
 			       void *rdata_arg)
 {
 	struct fc_rport_priv *rdata = rdata_arg;
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	u8 op;
 
 	mutex_lock(&rdata->rp_mutex);
@@ -716,7 +730,7 @@ out:
 	fc_frame_free(fp);
 err:
 	mutex_unlock(&rdata->rp_mutex);
-	put_device(&rport->dev);
+	kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
 }
 
 /**
@@ -728,7 +742,6 @@ err:
  */
 static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 {
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_lport *lport = rdata->local_port;
 	struct {
 		struct fc_els_prli prli;
@@ -747,11 +760,11 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_PRLI,
+	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI,
 				  fc_rport_prli_resp, rdata, lport->e_d_tov))
 		fc_rport_error_retry(rdata, fp);
 	else
-		get_device(&rport->dev);
+		kref_get(&rdata->kref);
 }
 
 /**
@@ -770,7 +783,6 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
 			      void *rdata_arg)
 {
 	struct fc_rport_priv *rdata = rdata_arg;
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	u8 op;
 
 	mutex_lock(&rdata->rp_mutex);
@@ -818,7 +830,7 @@ out:
 	fc_frame_free(fp);
 err:
 	mutex_unlock(&rdata->rp_mutex);
-	put_device(&rport->dev);
+	kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
 }
 
 /**
@@ -832,7 +844,6 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
 {
 	struct fc_frame *fp;
 	struct fc_lport *lport = rdata->local_port;
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 
 	FC_RPORT_DBG(rdata, "Port entered RTV state from %s state\n",
 		     fc_rport_state(rdata));
@@ -845,11 +856,11 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_RTV,
+	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV,
 				     fc_rport_rtv_resp, rdata, lport->e_d_tov))
 		fc_rport_error_retry(rdata, fp);
 	else
-		get_device(&rport->dev);
+		kref_get(&rdata->kref);
 }
 
 /**
@@ -862,7 +873,6 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
 static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
 {
 	struct fc_lport *lport = rdata->local_port;
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_frame *fp;
 
 	FC_RPORT_DBG(rdata, "Port entered LOGO state from %s state\n",
@@ -876,11 +886,11 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_LOGO,
+	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO,
 				  fc_rport_logo_resp, rdata, lport->e_d_tov))
 		fc_rport_error_retry(rdata, fp);
 	else
-		get_device(&rport->dev);
+		kref_get(&rdata->kref);
 }
 
 
@@ -956,7 +966,6 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 static void fc_rport_recv_plogi_req(struct fc_rport_priv *rdata,
 				    struct fc_seq *sp, struct fc_frame *rx_fp)
 {
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_frame *fp = rx_fp;
 	struct fc_exch *ep;
@@ -1041,12 +1050,13 @@ static void fc_rport_recv_plogi_req(struct fc_rport_priv *rdata,
 		} else {
 			sp = lport->tt.seq_start_next(sp);
 			WARN_ON(!sp);
-			fc_rport_set_name(rport, wwpn, wwnn);
+			rdata->ids.port_name = wwpn;
+			rdata->ids.node_name = wwnn;
 
 			/*
 			 * Get session payload size from incoming PLOGI.
 			 */
-			rport->maxframe_size =
+			rdata->maxframe_size =
 				fc_plogi_get_maxframe(pl, lport->mfs);
 			fc_frame_free(rx_fp);
 			fc_plogi_fill(lport, fp, ELS_LS_ACC);
@@ -1079,7 +1089,6 @@ static void fc_rport_recv_plogi_req(struct fc_rport_priv *rdata,
 static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 				   struct fc_seq *sp, struct fc_frame *rx_fp)
 {
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_exch *ep;
 	struct fc_frame *fp;
@@ -1173,12 +1182,12 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 				fcp_parm = ntohl(rspp->spp_params);
 				if (fcp_parm * FCP_SPPF_RETRY)
 					rdata->flags |= FC_RP_FLAGS_RETRY;
-				rport->supported_classes = FC_COS_CLASS3;
+				rdata->supported_classes = FC_COS_CLASS3;
 				if (fcp_parm & FCP_SPPF_INIT_FCN)
 					roles |= FC_RPORT_ROLE_FCP_INITIATOR;
 				if (fcp_parm & FCP_SPPF_TARG_FCN)
 					roles |= FC_RPORT_ROLE_FCP_TARGET;
-				rport->roles = roles;
+				rdata->ids.roles = roles;
 
 				spp->spp_params =
 					htonl(lport->service_params);
@@ -1310,6 +1319,9 @@ int fc_rport_init(struct fc_lport *lport)
 	if (!lport->tt.rport_flush_queue)
 		lport->tt.rport_flush_queue = fc_rport_flush_queue;
 
+	if (!lport->tt.rport_destroy)
+		lport->tt.rport_destroy = fc_rport_destroy;
+
 	return 0;
 }
 EXPORT_SYMBOL(fc_rport_init);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 2473167..a94d216 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -76,11 +76,7 @@ do {								\
 				(port_id), ##args))
 
 #define FC_RPORT_DBG(rdata, fmt, args...)				\
-do {									\
-	struct fc_lport *lport = rdata->local_port;			\
-	struct fc_rport *rport = PRIV_TO_RPORT(rdata);			\
-	FC_RPORT_ID_DBG(lport, rport->port_id, fmt, ##args);		\
-} while (0)
+	FC_RPORT_ID_DBG((rdata)->local_port, (rdata)->ids.port_id, fmt, ##args)
 
 #define FC_FCP_DBG(pkt, fmt, args...)					\
 	FC_CHECK_LOGGING(FC_FCP_LOGGING,				\
@@ -195,9 +191,13 @@ struct fc_rport_operations {
 /**
  * struct fc_rport_libfc_priv - libfc internal information about a remote port
  * @local_port: Fibre Channel host port instance
+ * @rport: transport remote port
+ * @kref: reference counter
  * @rp_state: state tracks progress of PLOGI, PRLI, and RTV exchanges
+ * @ids: remote port identifiers and roles
  * @flags: REC and RETRY supported flags
  * @max_seq: maximum number of concurrent sequences
+ * @maxframe_size: maximum frame size
  * @retries: retry count in current state
  * @e_d_tov: error detect timeout value (in msec)
  * @r_a_tov: resource allocation timeout value (in msec)
@@ -207,11 +207,15 @@ struct fc_rport_operations {
  */
 struct fc_rport_libfc_priv {
 	struct fc_lport		   *local_port;
+	struct fc_rport		   *rport;
+	struct kref		   kref;
 	enum fc_rport_state        rp_state;
+	struct fc_rport_identifiers ids;
 	u16			   flags;
 	#define FC_RP_FLAGS_REC_SUPPORTED	(1 << 0)
 	#define FC_RP_FLAGS_RETRY		(1 << 1)
 	u16		           max_seq;
+	u16			   maxframe_size;
 	unsigned int	           retries;
 	unsigned int	           e_d_tov;
 	unsigned int	           r_a_tov;
@@ -222,19 +226,12 @@ struct fc_rport_libfc_priv {
 	struct fc_rport_operations *ops;
 	struct list_head           peers;
 	struct work_struct         event_work;
+	u32			   supported_classes;
 };
 
-#define PRIV_TO_RPORT(x)						\
-	((struct fc_rport *)((void *)(x) - sizeof(struct fc_rport)))
 #define RPORT_TO_PRIV(x)						\
 	((struct fc_rport_libfc_priv *)((void *)(x) + sizeof(struct fc_rport)))
 
-static inline void fc_rport_set_name(struct fc_rport *rport, u64 wwpn, u64 wwnn)
-{
-	rport->node_name = wwnn;
-	rport->port_name = wwpn;
-}
-
 /*
  * fcoe stats structure
  */
@@ -609,6 +606,12 @@ struct libfc_function_template {
 	struct fc_rport_priv *(*rport_lookup)(const struct fc_lport *, u32);
 
 	/*
+	 * Destroy an rport after final kref_put().
+	 * The argument is a pointer to the kref inside the fc_rport_priv.
+	 */
+	void (*rport_destroy)(struct kref *);
+
+	/*
 	 * Send a fcp cmd from fsp pkt.
 	 * Called with the SCSI host lock unlocked and irqs disabled.
 	 *


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 30/64] libfc: rearrange code in fc_rport_work
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (28 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 29/64] libfc: make rport structure optional Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 31/64] libfc: rename rport event CREATED to READY Robert Love
                   ` (33 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

This is a cleanup without semantic changes to use a switch
statement instead of a series of if-statements in fc_rport_work(),
and to move some declarations up to the top.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_rport.c |   24 +++++++++++++++---------
 1 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 69f6e58..d0a4542 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -233,6 +233,9 @@ static void fc_rport_work(struct work_struct *work)
 	enum fc_rport_trans_state trans_state;
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_rport_operations *rport_ops;
+	struct fc_rport *new_rport;
+	struct fc_rport_priv *new_rdata;
+	struct fc_rport_identifiers ids;
 	struct fc_rport *rport;
 
 	mutex_lock(&rdata->rp_mutex);
@@ -240,11 +243,8 @@ static void fc_rport_work(struct work_struct *work)
 	rport_ops = rdata->ops;
 	rport = rdata->rport;
 
-	if (event == RPORT_EV_CREATED) {
-		struct fc_rport *new_rport;
-		struct fc_rport_priv *new_rdata;
-		struct fc_rport_identifiers ids;
-
+	switch (event) {
+	case RPORT_EV_CREATED:
 		ids = rdata->ids;
 		rdata->event = RPORT_EV_NONE;
 		mutex_unlock(&rdata->rp_mutex);
@@ -289,9 +289,11 @@ static void fc_rport_work(struct work_struct *work)
 		rdata = new_rport->dd_data;
 		if (rport_ops->event_callback)
 			rport_ops->event_callback(lport, rdata, event);
-	} else if ((event == RPORT_EV_FAILED) ||
-		   (event == RPORT_EV_LOGO) ||
-		   (event == RPORT_EV_STOP)) {
+		break;
+
+	case RPORT_EV_FAILED:
+	case RPORT_EV_LOGO:
+	case RPORT_EV_STOP:
 		trans_state = rdata->trans_state;
 		mutex_unlock(&rdata->rp_mutex);
 		if (rport_ops->event_callback)
@@ -305,8 +307,12 @@ static void fc_rport_work(struct work_struct *work)
 			lport->tt.exch_mgr_reset(lport, 0, port_id);
 			lport->tt.exch_mgr_reset(lport, port_id, 0);
 		}
-	} else
+		break;
+
+	default:
 		mutex_unlock(&rdata->rp_mutex);
+		break;
+	}
 }
 
 /**


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 31/64] libfc: rename rport event CREATED to READY
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (29 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 30/64] libfc: rearrange code in fc_rport_work Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 32/64] libfc: don't create dummy (rogue) remote ports Robert Love
                   ` (32 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Remote ports will become READY more than once after
ADISC is implemented in a later patch.

The event callback that has been called "CREATED" will mean "READY".
Rename it now in preparation for those changes.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |    2 +-
 drivers/scsi/libfc/fc_lport.c |    4 ++--
 drivers/scsi/libfc/fc_rport.c |    4 ++--
 include/scsi/libfc.h          |    2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 5f839b6..e5e5b26 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -118,7 +118,7 @@ static void fc_disc_rport_callback(struct fc_lport *lport,
 		    rdata->ids.port_id);
 
 	switch (event) {
-	case RPORT_EV_CREATED:
+	case RPORT_EV_READY:
 		if (disc) {
 			mutex_lock(&disc->disc_mutex);
 			list_add_tail(&rdata->peers, &disc->rports);
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index a7fe6b8..016f771 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -147,14 +147,14 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
 		     rdata->ids.port_id);
 
 	switch (event) {
-	case RPORT_EV_CREATED:
+	case RPORT_EV_READY:
 		if (rdata->ids.port_id == FC_FID_DIR_SERV) {
 			mutex_lock(&lport->lp_mutex);
 			if (lport->state == LPORT_ST_DNS) {
 				lport->dns_rp = rdata;
 				fc_lport_enter_rpn_id(lport);
 			} else {
-				FC_LPORT_DBG(lport, "Received an CREATED event "
+				FC_LPORT_DBG(lport, "Received an READY event "
 					     "on port (%6x) for the directory "
 					     "server, but the lport is not "
 					     "in the DNS state, it's in the "
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index d0a4542..50959ba 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -244,7 +244,7 @@ static void fc_rport_work(struct work_struct *work)
 	rport = rdata->rport;
 
 	switch (event) {
-	case RPORT_EV_CREATED:
+	case RPORT_EV_READY:
 		ids = rdata->ids;
 		rdata->event = RPORT_EV_NONE;
 		mutex_unlock(&rdata->rp_mutex);
@@ -413,7 +413,7 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata)
 
 	if (rdata->event == RPORT_EV_NONE)
 		queue_work(rport_event_queue, &rdata->event_work);
-	rdata->event = RPORT_EV_CREATED;
+	rdata->event = RPORT_EV_READY;
 }
 
 /**
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index a94d216..d324df8 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -167,7 +167,7 @@ struct fc_disc_port {
 
 enum fc_rport_event {
 	RPORT_EV_NONE = 0,
-	RPORT_EV_CREATED,
+	RPORT_EV_READY,
 	RPORT_EV_FAILED,
 	RPORT_EV_STOP,
 	RPORT_EV_LOGO


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 32/64] libfc: don't create dummy (rogue) remote ports
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (30 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 31/64] libfc: rename rport event CREATED to READY Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 33/64] libfc: fix rport event race between READY and LOGO Robert Love
                   ` (31 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Don't create a "dummy" remote port to go with fc_rport_priv.

Make the rport truly optional by allocating fc_rport_priv separately
and not requiring a dummy rport to be there if we haven't yet done
fc_remote_port_add().

The fc_rport_libfc_priv remains as a structure attached to the
rport for I/O purposes.

Be sure to hold references on rdata when the lock is dropped in
fc_rport_work().

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |   40 +++--------
 drivers/scsi/libfc/fc_rport.c |  154 +++++++++++++++++------------------------
 include/scsi/libfc.h          |   40 +++++------
 3 files changed, 92 insertions(+), 142 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index e5e5b26..bbea41e 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -66,7 +66,8 @@ struct fc_rport_priv *fc_disc_lookup_rport(const struct fc_lport *lport,
 	struct fc_rport_priv *rdata;
 
 	list_for_each_entry(rdata, &disc->rports, peers) {
-		if (rdata->ids.port_id == port_id)
+		if (rdata->ids.port_id == port_id &&
+		    rdata->rp_state != RPORT_ST_DELETE)
 			return rdata;
 	}
 	return NULL;
@@ -87,15 +88,8 @@ void fc_disc_stop_rports(struct fc_disc *disc)
 	lport = disc->lport;
 
 	mutex_lock(&disc->disc_mutex);
-	list_for_each_entry_safe(rdata, next, &disc->rports, peers) {
-		list_del(&rdata->peers);
+	list_for_each_entry_safe(rdata, next, &disc->rports, peers)
 		lport->tt.rport_logoff(rdata);
-	}
-
-	list_for_each_entry_safe(rdata, next, &disc->rogue_rports, peers) {
-		lport->tt.rport_logoff(rdata);
-	}
-
 	mutex_unlock(&disc->disc_mutex);
 }
 
@@ -119,20 +113,12 @@ static void fc_disc_rport_callback(struct fc_lport *lport,
 
 	switch (event) {
 	case RPORT_EV_READY:
-		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);
+		list_del(&rdata->peers);
 		mutex_unlock(&disc->disc_mutex);
 		break;
 	default:
@@ -235,7 +221,6 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
 			list_del(&dp->peers);
 			rdata = lport->tt.rport_lookup(lport, dp->ids.port_id);
 			if (rdata) {
-				list_del(&rdata->peers);
 				lport->tt.rport_logoff(rdata);
 			}
 			fc_disc_single(disc, dp);
@@ -296,10 +281,8 @@ static void fc_disc_restart(struct fc_disc *disc)
 
 	FC_DISC_DBG(disc, "Restarting discovery\n");
 
-	list_for_each_entry_safe(rdata, next, &disc->rports, peers) {
-		list_del(&rdata->peers);
+	list_for_each_entry_safe(rdata, next, &disc->rports, peers)
 		lport->tt.rport_logoff(rdata);
-	}
 
 	disc->requested = 1;
 	if (!disc->pending)
@@ -392,7 +375,6 @@ 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.
 			 */
-			list_del(&rdata->peers);
 			lport->tt.rport_logoff(rdata);
 			rdata = NULL;
 		}
@@ -406,12 +388,13 @@ static int fc_disc_new_target(struct fc_disc *disc,
 				rdata = lport->tt.rport_create(lport, ids);
 				if (!rdata)
 					error = -ENOMEM;
+				else
+					list_add_tail(&rdata->peers,
+						      &disc->rports);
 			}
 		}
 		if (rdata) {
 			rdata->ops = &fc_disc_rport_ops;
-			rdata->rp_state = RPORT_ST_INIT;
-			list_add_tail(&rdata->peers, &disc->rogue_rports);
 			lport->tt.rport_login(rdata);
 		}
 	}
@@ -585,9 +568,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 			rdata = lport->tt.rport_create(lport, &ids);
 			if (rdata) {
 				rdata->ops = &fc_disc_rport_ops;
-				rdata->local_port = lport;
-				list_add_tail(&rdata->peers,
-					      &disc->rogue_rports);
+				list_add_tail(&rdata->peers, &disc->rports);
 				lport->tt.rport_login(rdata);
 			} else
 				printk(KERN_WARNING "libfc: Failed to allocate "
@@ -736,7 +717,7 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
 	if (rdata) {
 		rdata->ops = &fc_disc_rport_ops;
 		kfree(dp);
-		list_add_tail(&rdata->peers, &disc->rogue_rports);
+		list_add_tail(&rdata->peers, &disc->rports);
 		lport->tt.rport_login(rdata);
 	}
 	return;
@@ -798,7 +779,6 @@ int fc_disc_init(struct fc_lport *lport)
 	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;
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 50959ba..a1794a3 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -86,61 +86,35 @@ static const char *fc_rport_state_names[] = {
 	[RPORT_ST_DELETE] = "Delete",
 };
 
-static void fc_rport_rogue_destroy(struct device *dev)
-{
-	struct fc_rport *rport = dev_to_rport(dev);
-	struct fc_rport_priv *rdata = RPORT_TO_PRIV(rport);
-
-	FC_RPORT_DBG(rdata, "Destroying rogue rport\n");
-	kfree(rport);
-}
-
-struct fc_rport_priv *fc_rport_rogue_create(struct fc_lport *lport,
-					    struct fc_rport_identifiers *ids)
+/**
+ * fc_rport_create() - create remote port in INIT state.
+ * @lport: local port.
+ * @ids: remote port identifiers.
+ *
+ * Locking note: this may be called without locks held, but
+ * is usually called from discovery with the disc_mutex held.
+ */
+static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
+					     struct fc_rport_identifiers *ids)
 {
-	struct fc_rport *rport;
 	struct fc_rport_priv *rdata;
-	rport = kzalloc(sizeof(*rport) + sizeof(*rdata), GFP_KERNEL);
 
-	if (!rport)
+	rdata = kzalloc(sizeof(*rdata), GFP_KERNEL);
+	if (!rdata)
 		return NULL;
 
-	rdata = RPORT_TO_PRIV(rport);
-
-	rport->dd_data = rdata;
-	rport->port_id = ids->port_id;
-	rport->port_name = ids->port_name;
-	rport->node_name = ids->node_name;
-	rport->roles = ids->roles;
-	rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
-	/*
-	 * Note: all this libfc rogue rport code will be removed for
-	 * upstream so it fine that this is really ugly and hacky right now.
-	 */
-	device_initialize(&rport->dev);
-	rport->dev.release = fc_rport_rogue_destroy;
-
 	rdata->ids = *ids;
 	kref_init(&rdata->kref);
 	mutex_init(&rdata->rp_mutex);
-	rdata->rport = rport;
 	rdata->local_port = lport;
-	rdata->trans_state = FC_PORTSTATE_ROGUE;
 	rdata->rp_state = RPORT_ST_INIT;
 	rdata->event = RPORT_EV_NONE;
 	rdata->flags = FC_RP_FLAGS_REC_SUPPORTED;
-	rdata->ops = NULL;
 	rdata->e_d_tov = lport->e_d_tov;
 	rdata->r_a_tov = lport->r_a_tov;
 	rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
 	INIT_WORK(&rdata->event_work, fc_rport_work);
-	/*
-	 * For good measure, but not necessary as we should only
-	 * add REAL rport to the lport list.
-	 */
-	INIT_LIST_HEAD(&rdata->peers);
-
 	return rdata;
 }
 
@@ -151,11 +125,9 @@ struct fc_rport_priv *fc_rport_rogue_create(struct fc_lport *lport,
 static void fc_rport_destroy(struct kref *kref)
 {
 	struct fc_rport_priv *rdata;
-	struct fc_rport *rport;
 
 	rdata = container_of(kref, struct fc_rport_priv, kref);
-	rport = rdata->rport;
-	put_device(&rport->dev);
+	kfree(rdata);
 }
 
 /**
@@ -229,12 +201,10 @@ static void fc_rport_work(struct work_struct *work)
 	u32 port_id;
 	struct fc_rport_priv *rdata =
 		container_of(work, struct fc_rport_priv, event_work);
+	struct fc_rport_libfc_priv *rp;
 	enum fc_rport_event event;
-	enum fc_rport_trans_state trans_state;
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_rport_operations *rport_ops;
-	struct fc_rport *new_rport;
-	struct fc_rport_priv *new_rdata;
 	struct fc_rport_identifiers ids;
 	struct fc_rport *rport;
 
@@ -243,70 +213,72 @@ static void fc_rport_work(struct work_struct *work)
 	rport_ops = rdata->ops;
 	rport = rdata->rport;
 
+	FC_RPORT_DBG(rdata, "work event %u\n", event);
+
 	switch (event) {
 	case RPORT_EV_READY:
 		ids = rdata->ids;
 		rdata->event = RPORT_EV_NONE;
+		kref_get(&rdata->kref);
 		mutex_unlock(&rdata->rp_mutex);
 
-		new_rport = fc_remote_port_add(lport->host, 0, &ids);
-		if (new_rport) {
-			/*
-			 * Switch from the rogue rport to the rport
-			 * returned by the FC class.
-			 */
-			new_rport->maxframe_size = rdata->maxframe_size;
-
-			new_rdata = new_rport->dd_data;
-			new_rdata->rport = new_rport;
-			new_rdata->ids = ids;
-			new_rdata->e_d_tov = rdata->e_d_tov;
-			new_rdata->r_a_tov = rdata->r_a_tov;
-			new_rdata->ops = rdata->ops;
-			new_rdata->local_port = rdata->local_port;
-			new_rdata->flags = FC_RP_FLAGS_REC_SUPPORTED;
-			new_rdata->trans_state = FC_PORTSTATE_REAL;
-			new_rdata->maxframe_size = rdata->maxframe_size;
-			new_rdata->supported_classes = rdata->supported_classes;
-			kref_init(&new_rdata->kref);
-			mutex_init(&new_rdata->rp_mutex);
-			INIT_DELAYED_WORK(&new_rdata->retry_work,
-					  fc_rport_timeout);
-			INIT_LIST_HEAD(&new_rdata->peers);
-			INIT_WORK(&new_rdata->event_work, fc_rport_work);
-
-			fc_rport_state_enter(new_rdata, RPORT_ST_READY);
-		} else {
-			printk(KERN_WARNING "libfc: Failed to allocate "
-			       " memory for rport (%6x)\n", ids.port_id);
-			event = RPORT_EV_FAILED;
+		if (!rport)
+			rport = fc_remote_port_add(lport->host, 0, &ids);
+		if (!rport) {
+			FC_RPORT_DBG(rdata, "Failed to add the rport\n");
+			lport->tt.rport_logoff(rdata);
+			kref_put(&rdata->kref, lport->tt.rport_destroy);
+			return;
 		}
-		if (rdata->ids.port_id != FC_FID_DIR_SERV)
-			if (rport_ops->event_callback)
-				rport_ops->event_callback(lport, rdata,
-							  RPORT_EV_FAILED);
-		kref_put(&rdata->kref, lport->tt.rport_destroy);
-		rdata = new_rport->dd_data;
-		if (rport_ops->event_callback)
+		mutex_lock(&rdata->rp_mutex);
+		if (rdata->rport)
+			FC_RPORT_DBG(rdata, "rport already allocated\n");
+		rdata->rport = rport;
+		rport->maxframe_size = rdata->maxframe_size;
+		rport->supported_classes = rdata->supported_classes;
+
+		rp = rport->dd_data;
+		rp->local_port = lport;
+		rp->rp_state = rdata->rp_state;
+		rp->flags = rdata->flags;
+		rp->e_d_tov = rdata->e_d_tov;
+		rp->r_a_tov = rdata->r_a_tov;
+		mutex_unlock(&rdata->rp_mutex);
+
+		if (rport_ops->event_callback) {
+			FC_RPORT_DBG(rdata, "callback ev %d\n", event);
 			rport_ops->event_callback(lport, rdata, event);
+		}
+		kref_put(&rdata->kref, lport->tt.rport_destroy);
 		break;
 
 	case RPORT_EV_FAILED:
 	case RPORT_EV_LOGO:
 	case RPORT_EV_STOP:
-		trans_state = rdata->trans_state;
+		port_id = rdata->ids.port_id;
 		mutex_unlock(&rdata->rp_mutex);
-		if (rport_ops->event_callback)
+
+		if (rport_ops->event_callback) {
+			FC_RPORT_DBG(rdata, "callback ev %d\n", event);
 			rport_ops->event_callback(lport, rdata, event);
+		}
 		cancel_delayed_work_sync(&rdata->retry_work);
-		if (trans_state == FC_PORTSTATE_ROGUE)
-			kref_put(&rdata->kref, lport->tt.rport_destroy);
-		else {
-			port_id = rport->port_id;
+
+		/*
+		 * Reset any outstanding exchanges before freeing rport.
+		 */
+		lport->tt.exch_mgr_reset(lport, 0, port_id);
+		lport->tt.exch_mgr_reset(lport, port_id, 0);
+
+		if (rport) {
+			rp = rport->dd_data;
+			rp->rp_state = RPORT_ST_DELETE;
+			mutex_lock(&rdata->rp_mutex);
+			rdata->rport = NULL;
+			mutex_unlock(&rdata->rp_mutex);
 			fc_remote_port_delete(rport);
-			lport->tt.exch_mgr_reset(lport, 0, port_id);
-			lport->tt.exch_mgr_reset(lport, port_id, 0);
 		}
+		kref_put(&rdata->kref, lport->tt.rport_destroy);
 		break;
 
 	default:
@@ -1311,7 +1283,7 @@ static void fc_rport_flush_queue(void)
 int fc_rport_init(struct fc_lport *lport)
 {
 	if (!lport->tt.rport_create)
-		lport->tt.rport_create = fc_rport_rogue_create;
+		lport->tt.rport_create = fc_rport_create;
 
 	if (!lport->tt.rport_login)
 		lport->tt.rport_login = fc_rport_login;
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index d324df8..bf4b1c2 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -146,11 +146,6 @@ enum fc_rport_state {
 	RPORT_ST_DELETE,	/* port being deleted */
 };
 
-enum fc_rport_trans_state {
-	FC_PORTSTATE_ROGUE,
-	FC_PORTSTATE_REAL,
-};
-
 /**
  * struct fc_disc_port - temporary discovery port to hold rport identifiers
  * @lp: Fibre Channel host port instance
@@ -173,14 +168,6 @@ enum fc_rport_event {
 	RPORT_EV_LOGO
 };
 
-/*
- * Temporary definition to prepare for split off from fc_rport_libfc_priv
- * of a separately-allocated structure called fc_rport_priv.  This will
- * be the primary object for the discovery and rport state machines.
- * This definition is just to make this patch series easier to review.
- */
-#define fc_rport_priv fc_rport_libfc_priv
-
 struct fc_rport_priv;
 
 struct fc_rport_operations {
@@ -191,6 +178,24 @@ struct fc_rport_operations {
 /**
  * struct fc_rport_libfc_priv - libfc internal information about a remote port
  * @local_port: Fibre Channel host port instance
+ * @rp_state: indicates READY for I/O or DELETE when blocked.
+ * @flags: REC and RETRY supported flags
+ * @e_d_tov: error detect timeout value (in msec)
+ * @r_a_tov: resource allocation timeout value (in msec)
+ */
+struct fc_rport_libfc_priv {
+	struct fc_lport		   *local_port;
+	enum fc_rport_state        rp_state;
+	u16			   flags;
+	#define FC_RP_FLAGS_REC_SUPPORTED	(1 << 0)
+	#define FC_RP_FLAGS_RETRY		(1 << 1)
+	unsigned int	           e_d_tov;
+	unsigned int	           r_a_tov;
+};
+
+/**
+ * struct fc_rport_priv - libfc rport and discovery info about a remote port
+ * @local_port: Fibre Channel host port instance
  * @rport: transport remote port
  * @kref: reference counter
  * @rp_state: state tracks progress of PLOGI, PRLI, and RTV exchanges
@@ -205,21 +210,18 @@ struct fc_rport_operations {
  * @retry_work:
  * @event_callback: Callback for rport READY, FAILED or LOGO
  */
-struct fc_rport_libfc_priv {
+struct fc_rport_priv {
 	struct fc_lport		   *local_port;
 	struct fc_rport		   *rport;
 	struct kref		   kref;
 	enum fc_rport_state        rp_state;
 	struct fc_rport_identifiers ids;
 	u16			   flags;
-	#define FC_RP_FLAGS_REC_SUPPORTED	(1 << 0)
-	#define FC_RP_FLAGS_RETRY		(1 << 1)
 	u16		           max_seq;
 	u16			   maxframe_size;
 	unsigned int	           retries;
 	unsigned int	           e_d_tov;
 	unsigned int	           r_a_tov;
-	enum fc_rport_trans_state  trans_state;
 	struct mutex               rp_mutex;
 	struct delayed_work	   retry_work;
 	enum fc_rport_event        event;
@@ -229,9 +231,6 @@ struct fc_rport_libfc_priv {
 	u32			   supported_classes;
 };
 
-#define RPORT_TO_PRIV(x)						\
-	((struct fc_rport_libfc_priv *)((void *)(x) + sizeof(struct fc_rport)))
-
 /*
  * fcoe stats structure
  */
@@ -686,7 +685,6 @@ struct fc_disc {
 			      enum fc_disc_event);
 
 	struct list_head	 rports;
-	struct list_head	 rogue_rports;
 	struct fc_lport		*lport;
 	struct mutex		disc_mutex;
 	struct fc_gpn_ft_resp	partial_buf;	/* partial name buffer */


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 33/64] libfc: fix rport event race between READY and LOGO
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (31 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 32/64] libfc: don't create dummy (rogue) remote ports Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 34/64] libfc: eliminate disc->event Robert Love
                   ` (30 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

When a remote port becomes ready and a LOGO is received before
the READY event is in rport_work waiting on the mutex, the
event is changed to LOGO and the work queued, so both the
calls to rport_work see the LOGO event, and both try to do
the list_del(), causing a crash.

Don't change the event if it is already set.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_rport.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a1794a3..cbf6c9f 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1267,9 +1267,7 @@ static void fc_rport_recv_logo_req(struct fc_rport_priv *rdata,
 		return;
 	}
 
-	rdata->event = RPORT_EV_LOGO;
-	fc_rport_state_enter(rdata, RPORT_ST_DELETE);
-	queue_work(rport_event_queue, &rdata->event_work);
+	fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
 
 	lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
 	fc_frame_free(fp);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 34/64] libfc: eliminate disc->event
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (32 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 33/64] libfc: fix rport event race between READY and LOGO Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 35/64] libfc: remove unused disc->delay element Robert Love
                   ` (29 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

There was no need to have the discovery status stored in struct fc_disc.

Change fc_disc_done() to take the discovery status as an argument
and just pass it on to the discovery callback.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |   31 ++++++++++++-------------------
 include/scsi/libfc.h         |    1 -
 2 files changed, 12 insertions(+), 20 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index bbea41e..736f917 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -49,7 +49,7 @@ 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_priv *,
 			      struct fc_rport_identifiers *);
-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 *);
@@ -329,8 +329,7 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
 	if (rdata) {
 		kref_get(&rdata->kref);
 		if (!fc_disc_new_target(disc, rdata, &rdata->ids)) {
-			disc->event = DISC_EV_SUCCESS;
-			fc_disc_done(disc);
+			fc_disc_done(disc, DISC_EV_SUCCESS);
 		}
 		kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
 	} else {
@@ -404,20 +403,18 @@ static int fc_disc_new_target(struct fc_disc *disc,
 /**
  * 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;
 
 	FC_DISC_DBG(disc, "Discovery complete\n");
 
-	event = disc->event;
-	disc->event = DISC_EV_NONE;
-
 	if (disc->requested)
 		fc_disc_gpn_ft_req(disc);
 	else
@@ -460,11 +457,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);
 	}
 }
 
@@ -503,10 +497,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)
 {
@@ -577,8 +573,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 		}
 
 		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;
 		}
@@ -669,8 +664,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
 			FC_DISC_DBG(disc, "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_done(disc, DISC_EV_FAILED);
 		} else {
 			FC_DISC_DBG(disc, "GPN_FT unexpected response code "
 				    "%x\n", ntohs(cp->ct_cmd));
@@ -782,7 +776,6 @@ int fc_disc_init(struct fc_lport *lport)
 
 	disc->lport = lport;
 	disc->delay = FC_DISC_DELAY;
-	disc->event = DISC_EV_NONE;
 
 	return 0;
 }
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index bf4b1c2..f3f320f 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -679,7 +679,6 @@ struct fc_disc {
 	unsigned char		requested;
 	unsigned short		seq_count;
 	unsigned char		buf_len;
-	enum fc_disc_event	event;
 
 	void (*disc_callback)(struct fc_lport *,
 			      enum fc_disc_event);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 35/64] libfc: remove unused disc->delay element
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (33 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 34/64] libfc: eliminate disc->event Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 36/64] libfc: rport debug messages were printing pointer values Robert Love
                   ` (28 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Delete unused disc->delay element.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |    3 ---
 include/scsi/libfc.h         |    1 -
 2 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 736f917..8427396 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -43,8 +43,6 @@
 #define FC_DISC_RETRY_LIMIT	3	/* max retries */
 #define FC_DISC_RETRY_DELAY	500UL	/* (msecs) delay */
 
-#define	FC_DISC_DELAY		3
-
 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_priv *,
@@ -775,7 +773,6 @@ int fc_disc_init(struct fc_lport *lport)
 	INIT_LIST_HEAD(&disc->rports);
 
 	disc->lport = lport;
-	disc->delay = FC_DISC_DELAY;
 
 	return 0;
 }
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index f3f320f..093b043 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -674,7 +674,6 @@ struct libfc_function_template {
 /* information used by the discovery layer */
 struct fc_disc {
 	unsigned char		retry_count;
-	unsigned char		delay;
 	unsigned char		pending;
 	unsigned char		requested;
 	unsigned short		seq_count;


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 36/64] libfc: rport debug messages were printing pointer values
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (34 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 35/64] libfc: remove unused disc->delay element Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 37/64] libfc: simplify fc_lport_rport_callback Robert Love
                   ` (27 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Don't print large negative decimal numbers for frame pointers in
the debug messages from fc_rport_error().  Just print 0 if its a
frame pointer, and print the error numbers as positive.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_rport.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index cbf6c9f..6ecf36d 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -436,7 +436,8 @@ static void fc_rport_timeout(struct work_struct *work)
 static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
 {
 	FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n",
-		     PTR_ERR(fp), fc_rport_state(rdata), rdata->retries);
+		     IS_ERR(fp) ? -PTR_ERR(fp) : 0,
+		     fc_rport_state(rdata), rdata->retries);
 
 	switch (rdata->rp_state) {
 	case RPORT_ST_PLOGI:


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 37/64] libfc: simplify fc_lport_rport_callback
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (35 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 36/64] libfc: rport debug messages were printing pointer values Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 38/64] libfc: make rport module maintain the rport list Robert Love
                   ` (26 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

The lport rport callback can only be called for the dNS rport,
since its the only rport who's ops point to that function.

Remove unnecessary checking and debug messages.
Put the locking outside the switch statement as a simplification.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_lport.c |   43 ++++++++++++++---------------------------
 1 files changed, 15 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 016f771..22c0f7b 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -146,44 +146,31 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
 	FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event,
 		     rdata->ids.port_id);
 
+	mutex_lock(&lport->lp_mutex);
 	switch (event) {
 	case RPORT_EV_READY:
-		if (rdata->ids.port_id == FC_FID_DIR_SERV) {
-			mutex_lock(&lport->lp_mutex);
-			if (lport->state == LPORT_ST_DNS) {
-				lport->dns_rp = rdata;
-				fc_lport_enter_rpn_id(lport);
-			} else {
-				FC_LPORT_DBG(lport, "Received an READY event "
-					     "on port (%6x) for the directory "
-					     "server, but the lport is not "
-					     "in the DNS state, it's in the "
-					     "%d state", rdata->ids.port_id,
-					     lport->state);
-				lport->tt.rport_logoff(rdata);
-			}
-			mutex_unlock(&lport->lp_mutex);
-		} else
-			FC_LPORT_DBG(lport, "Received an event for port (%6x) "
-				     "which is not the directory server\n",
-				     rdata->ids.port_id);
+		if (lport->state == LPORT_ST_DNS) {
+			lport->dns_rp = rdata;
+			fc_lport_enter_rpn_id(lport);
+		} else {
+			FC_LPORT_DBG(lport, "Received an READY event "
+				     "on port (%6x) for the directory "
+				     "server, but the lport is not "
+				     "in the DNS state, it's in the "
+				     "%d state", rdata->ids.port_id,
+				     lport->state);
+			lport->tt.rport_logoff(rdata);
+		}
 		break;
 	case RPORT_EV_LOGO:
 	case RPORT_EV_FAILED:
 	case RPORT_EV_STOP:
-		if (rdata->ids.port_id == FC_FID_DIR_SERV) {
-			mutex_lock(&lport->lp_mutex);
-			lport->dns_rp = NULL;
-			mutex_unlock(&lport->lp_mutex);
-
-		} else
-			FC_LPORT_DBG(lport, "Received an event for port (%6x) "
-				     "which is not the directory server\n",
-				     rdata->ids.port_id);
+		lport->dns_rp = NULL;
 		break;
 	case RPORT_EV_NONE:
 		break;
 	}
+	mutex_unlock(&lport->lp_mutex);
 }
 
 /**


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 38/64] libfc: make rport module maintain the rport list
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (36 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 37/64] libfc: simplify fc_lport_rport_callback Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:01 ` [PATCH 39/64] libfc: have rport_create do a lookup for pre-existing rports first Robert Love
                   ` (25 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

The list of remote ports (struct fc_rport_priv) has been
maintained by the discovery module.  In preparation for having
lport->tt.rport_create() do a lookup first, maintain the
rports list in the rport module.  It will still be protected
by the disc_mutex.

The DNS rport is an exception for until after further patches.
For now, do not add it to the list.

The point-to-point rport will be in the discovery list.
So at shutdown, it doesn't need to be separately logged out.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |    8 --------
 drivers/scsi/libfc/fc_lport.c |   14 ++++++--------
 drivers/scsi/libfc/fc_rport.c |   11 +++++++++--
 3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 8427396..e6b13bf 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -115,9 +115,6 @@ static void fc_disc_rport_callback(struct fc_lport *lport,
 	case RPORT_EV_LOGO:
 	case RPORT_EV_FAILED:
 	case RPORT_EV_STOP:
-		mutex_lock(&disc->disc_mutex);
-		list_del(&rdata->peers);
-		mutex_unlock(&disc->disc_mutex);
 		break;
 	default:
 		break;
@@ -385,9 +382,6 @@ static int fc_disc_new_target(struct fc_disc *disc,
 				rdata = lport->tt.rport_create(lport, ids);
 				if (!rdata)
 					error = -ENOMEM;
-				else
-					list_add_tail(&rdata->peers,
-						      &disc->rports);
 			}
 		}
 		if (rdata) {
@@ -562,7 +556,6 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 			rdata = lport->tt.rport_create(lport, &ids);
 			if (rdata) {
 				rdata->ops = &fc_disc_rport_ops;
-				list_add_tail(&rdata->peers, &disc->rports);
 				lport->tt.rport_login(rdata);
 			} else
 				printk(KERN_WARNING "libfc: Failed to allocate "
@@ -709,7 +702,6 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
 	if (rdata) {
 		rdata->ops = &fc_disc_rport_ops;
 		kfree(dp);
-		list_add_tail(&rdata->peers, &disc->rports);
 		lport->tt.rport_login(rdata);
 	}
 	return;
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 22c0f7b..f33e573 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -205,12 +205,11 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
 	ids.node_name = remote_wwnn;
 	ids.roles = FC_RPORT_ROLE_UNKNOWN;
 
-	if (lport->ptp_rp) {
+	mutex_lock(&lport->disc.disc_mutex);
+	if (lport->ptp_rp)
 		lport->tt.rport_logoff(lport->ptp_rp);
-		lport->ptp_rp = NULL;
-	}
-
 	lport->ptp_rp = lport->tt.rport_create(lport, &ids);
+	mutex_unlock(&lport->disc.disc_mutex);
 
 	lport->tt.rport_login(lport->ptp_rp);
 
@@ -931,10 +930,7 @@ static void fc_lport_reset_locked(struct fc_lport *lport)
 	if (lport->dns_rp)
 		lport->tt.rport_logoff(lport->dns_rp);
 
-	if (lport->ptp_rp) {
-		lport->tt.rport_logoff(lport->ptp_rp);
-		lport->ptp_rp = NULL;
-	}
+	lport->ptp_rp = NULL;
 
 	lport->tt.disc_stop(lport);
 
@@ -1304,7 +1300,9 @@ static void fc_lport_enter_dns(struct fc_lport *lport)
 
 	fc_lport_state_enter(lport, LPORT_ST_DNS);
 
+	mutex_lock(&lport->disc.disc_mutex);
 	rdata = lport->tt.rport_create(lport, &ids);
+	mutex_unlock(&lport->disc.disc_mutex);
 	if (!rdata)
 		goto err;
 
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 6ecf36d..a9087b3 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -91,8 +91,7 @@ static const char *fc_rport_state_names[] = {
  * @lport: local port.
  * @ids: remote port identifiers.
  *
- * Locking note: this may be called without locks held, but
- * is usually called from discovery with the disc_mutex held.
+ * Locking note:  must be called with the disc_mutex held.
  */
 static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
 					     struct fc_rport_identifiers *ids)
@@ -115,6 +114,8 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
 	rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
 	INIT_WORK(&rdata->event_work, fc_rport_work);
+	if (ids->port_id != FC_FID_DIR_SERV)
+		list_add(&rdata->peers, &lport->disc.rports);
 	return rdata;
 }
 
@@ -258,6 +259,12 @@ static void fc_rport_work(struct work_struct *work)
 		port_id = rdata->ids.port_id;
 		mutex_unlock(&rdata->rp_mutex);
 
+		if (port_id != FC_FID_DIR_SERV) {
+			mutex_lock(&lport->disc.disc_mutex);
+			list_del(&rdata->peers);
+			mutex_unlock(&lport->disc.disc_mutex);
+		}
+
 		if (rport_ops->event_callback) {
 			FC_RPORT_DBG(rdata, "callback ev %d\n", event);
 			rport_ops->event_callback(lport, rdata, event);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 39/64] libfc: have rport_create do a lookup for pre-existing rports first
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (37 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 38/64] libfc: make rport module maintain the rport list Robert Love
@ 2009-08-25 21:01 ` Robert Love
  2009-08-25 21:02 ` [PATCH 40/64] libfc: change to make remote port callback optional Robert Love
                   ` (24 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:01 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

For future discovery patches, change rport_create to return a previously
created rport_priv that has the FC_ID as long as it isn't in deleted state.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |    9 +++------
 drivers/scsi/libfc/fc_rport.c |    4 ++++
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index e6b13bf..266aa1e 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -377,12 +377,9 @@ static int fc_disc_new_target(struct fc_disc *disc,
 	    ids->port_id != fc_host_port_id(lport->host) &&
 	    ids->port_name != lport->wwpn) {
 		if (!rdata) {
-			rdata = lport->tt.rport_lookup(lport, ids->port_id);
-			if (!rdata) {
-				rdata = lport->tt.rport_create(lport, ids);
-				if (!rdata)
-					error = -ENOMEM;
-			}
+			rdata = lport->tt.rport_create(lport, ids);
+			if (!rdata)
+				error = -ENOMEM;
 		}
 		if (rdata) {
 			rdata->ops = &fc_disc_rport_ops;
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a9087b3..29bb6fd 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -98,6 +98,10 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
 {
 	struct fc_rport_priv *rdata;
 
+	rdata = lport->tt.rport_lookup(lport, ids->port_id);
+	if (rdata)
+		return rdata;
+
 	rdata = kzalloc(sizeof(*rdata), GFP_KERNEL);
 	if (!rdata)
 		return NULL;


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 40/64] libfc: change to make remote port callback optional
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (38 preceding siblings ...)
  2009-08-25 21:01 ` [PATCH 39/64] libfc: have rport_create do a lookup for pre-existing rports first Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 41/64] libfc: move rport_lookup into fc_rport.c Robert Love
                   ` (23 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Since the rport list maintenance is now done in the rport module,
the callback (and ops) are usually not necessary.

Allow rdata->ops to be left NULL if nothing needs
to be done in an event callback.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |   45 +++--------------------------------------
 drivers/scsi/libfc/fc_rport.c |    4 ++--
 2 files changed, 5 insertions(+), 44 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 266aa1e..3fcbba1 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -92,37 +92,6 @@ void fc_disc_stop_rports(struct fc_disc *disc)
 }
 
 /**
- * fc_disc_rport_callback() - Event handler for rport events
- * @lport: The lport which is receiving the event
- * @rdata: private remote port data
- * @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_priv *rdata,
-				   enum fc_rport_event event)
-{
-	struct fc_disc *disc = &lport->disc;
-
-	FC_DISC_DBG(disc, "Received a %d event for port (%6x)\n", event,
-		    rdata->ids.port_id);
-
-	switch (event) {
-	case RPORT_EV_READY:
-		break;
-	case RPORT_EV_LOGO:
-	case RPORT_EV_FAILED:
-	case RPORT_EV_STOP:
-		break;
-	default:
-		break;
-	}
-
-}
-
-/**
  * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
  * @sp: Current sequence of the RSCN exchange
  * @fp: RSCN Frame
@@ -334,10 +303,6 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
 	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
@@ -381,10 +346,8 @@ static int fc_disc_new_target(struct fc_disc *disc,
 			if (!rdata)
 				error = -ENOMEM;
 		}
-		if (rdata) {
-			rdata->ops = &fc_disc_rport_ops;
+		if (rdata)
 			lport->tt.rport_login(rdata);
-		}
 	}
 	return error;
 }
@@ -551,10 +514,9 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 		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->ops = &fc_disc_rport_ops;
+			if (rdata)
 				lport->tt.rport_login(rdata);
-			} else
+			else
 				printk(KERN_WARNING "libfc: Failed to allocate "
 				       "memory for the newly discovered port "
 				       "(%6x)\n", ids.port_id);
@@ -697,7 +659,6 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
 
 	rdata = lport->tt.rport_create(lport, &dp->ids);
 	if (rdata) {
-		rdata->ops = &fc_disc_rport_ops;
 		kfree(dp);
 		lport->tt.rport_login(rdata);
 	}
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 29bb6fd..406049c 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -250,7 +250,7 @@ static void fc_rport_work(struct work_struct *work)
 		rp->r_a_tov = rdata->r_a_tov;
 		mutex_unlock(&rdata->rp_mutex);
 
-		if (rport_ops->event_callback) {
+		if (rport_ops && rport_ops->event_callback) {
 			FC_RPORT_DBG(rdata, "callback ev %d\n", event);
 			rport_ops->event_callback(lport, rdata, event);
 		}
@@ -269,7 +269,7 @@ static void fc_rport_work(struct work_struct *work)
 			mutex_unlock(&lport->disc.disc_mutex);
 		}
 
-		if (rport_ops->event_callback) {
+		if (rport_ops && rport_ops->event_callback) {
 			FC_RPORT_DBG(rdata, "callback ev %d\n", event);
 			rport_ops->event_callback(lport, rdata, event);
 		}


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 41/64] libfc: move rport_lookup into fc_rport.c
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (39 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 40/64] libfc: change to make remote port callback optional Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 42/64] libfc: do not log off rports before or after discovery Robert Love
                   ` (22 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Move the libfc remote port lookup function into fc_rport.c.
This seems like the best place for it.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |   22 ----------------------
 drivers/scsi/libfc/fc_rport.c |   20 ++++++++++++++++++++
 2 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 3fcbba1..f6762a5 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -53,25 +53,6 @@ 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_priv *fc_disc_lookup_rport(const struct fc_lport *lport,
-					   u32 port_id)
-{
-	const struct fc_disc *disc = &lport->disc;
-	struct fc_rport_priv *rdata;
-
-	list_for_each_entry(rdata, &disc->rports, peers) {
-		if (rdata->ids.port_id == port_id &&
-		    rdata->rp_state != RPORT_ST_DELETE)
-			return rdata;
-	}
-	return NULL;
-}
-
-/**
  * fc_disc_stop_rports() - delete all the remote ports associated with the lport
  * @disc: The discovery job to stop rports on
  *
@@ -714,9 +695,6 @@ 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);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 406049c..99ac056 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -87,6 +87,23 @@ static const char *fc_rport_state_names[] = {
 };
 
 /**
+ * fc_rport_lookup() - lookup a remote port by port_id
+ * @lport: Fibre Channel host port instance
+ * @port_id: remote port port_id to match
+ */
+static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport,
+					     u32 port_id)
+{
+	struct fc_rport_priv *rdata;
+
+	list_for_each_entry(rdata, &lport->disc.rports, peers)
+		if (rdata->ids.port_id == port_id &&
+		    rdata->rp_state != RPORT_ST_DELETE)
+			return rdata;
+	return NULL;
+}
+
+/**
  * fc_rport_create() - create remote port in INIT state.
  * @lport: local port.
  * @ids: remote port identifiers.
@@ -1292,6 +1309,9 @@ static void fc_rport_flush_queue(void)
 
 int fc_rport_init(struct fc_lport *lport)
 {
+	if (!lport->tt.rport_lookup)
+		lport->tt.rport_lookup = fc_rport_lookup;
+
 	if (!lport->tt.rport_create)
 		lport->tt.rport_create = fc_rport_create;
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 42/64] libfc: do not log off rports before or after discovery
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (40 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 41/64] libfc: move rport_lookup into fc_rport.c Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 43/64] libfc: discovery restart sequence error fix Robert Love
                   ` (21 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

When receiving an RSCN, do not log off all rports.  This is
extremely disruptive.  If, after the GPN_FT response, some
rports haven't been listed, delete them.

Add field disc_id to structs fc_rport_priv and fc_disc.
disc_id is an arbitrary serial number used to identify the
rports found by the latest discovery.  This eliminates the need
to go through the rport list when restarting discovery.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |   47 ++++++++++++++++++++++++++++++------------
 include/scsi/libfc.h         |    3 +++
 2 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index f6762a5..ddf4944 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -221,17 +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_priv *rdata, *next;
-	struct fc_lport *lport = disc->lport;
-
 	FC_DISC_DBG(disc, "Restarting discovery\n");
 
-	list_for_each_entry_safe(rdata, next, &disc->rports, peers)
-		lport->tt.rport_logoff(rdata);
-
 	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);
 }
 
 /**
@@ -278,6 +280,7 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
 		}
 		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 */
 	}
 
@@ -345,13 +348,30 @@ static int fc_disc_new_target(struct fc_disc *disc,
 static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
 {
 	struct fc_lport *lport = disc->lport;
+	struct fc_rport_priv *rdata;
 
 	FC_DISC_DBG(disc, "Discovery complete\n");
 
-	if (disc->requested)
-		fc_disc_gpn_ft_req(disc);
-	else
-		disc->pending = 0;
+	disc->pending = 0;
+	if (disc->requested) {
+		fc_disc_restart(disc);
+		return;
+	}
+
+	/*
+	 * 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);
@@ -496,7 +516,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 		    ids.port_name != lport->wwpn) {
 			rdata = lport->tt.rport_create(lport, &ids);
 			if (rdata)
-				lport->tt.rport_login(rdata);
+				rdata->disc_id = disc->disc_id;
 			else
 				printk(KERN_WARNING "libfc: Failed to allocate "
 				       "memory for the newly discovered port "
@@ -640,6 +660,7 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
 
 	rdata = lport->tt.rport_create(lport, &dp->ids);
 	if (rdata) {
+		rdata->disc_id = disc->disc_id;
 		kfree(dp);
 		lport->tt.rport_login(rdata);
 	}
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 093b043..517dce5 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -202,6 +202,7 @@ struct fc_rport_libfc_priv {
  * @ids: remote port identifiers and roles
  * @flags: REC and RETRY supported flags
  * @max_seq: maximum number of concurrent sequences
+ * @disc_id: discovery identifier
  * @maxframe_size: maximum frame size
  * @retries: retry count in current state
  * @e_d_tov: error detect timeout value (in msec)
@@ -218,6 +219,7 @@ struct fc_rport_priv {
 	struct fc_rport_identifiers ids;
 	u16			   flags;
 	u16		           max_seq;
+	u16			   disc_id;
 	u16			   maxframe_size;
 	unsigned int	           retries;
 	unsigned int	           e_d_tov;
@@ -678,6 +680,7 @@ struct fc_disc {
 	unsigned char		requested;
 	unsigned short		seq_count;
 	unsigned char		buf_len;
+	u16			disc_id;
 
 	void (*disc_callback)(struct fc_lport *,
 			      enum fc_disc_event);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 43/64] libfc: discovery restart sequence error fix
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (41 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 42/64] libfc: do not log off rports before or after discovery Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 44/64] libfc: rearrange code in fc_disc_gpn_ft_resp() Robert Love
                   ` (20 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

When an RSCN is received during fabric discovery, it restarts.
After the restart, disc->seq_count was incremented, so when
the first frame was received, it was considered "out of sequence".
That left the state disc->active, preventing further discoveries.

Change to advance the sequence count before parsing, so that it
won't be changed after a potential restart.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index ddf4944..fd3a6b2 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -629,11 +629,10 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
 			    seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp));
 	}
 	if (buf) {
+		disc->seq_count++;
 		error = fc_disc_gpn_ft_parse(disc, buf, len);
 		if (error)
 			fc_disc_error(disc, fp);
-		else
-			disc->seq_count++;
 	}
 	fc_frame_free(fp);
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 44/64] libfc: rearrange code in fc_disc_gpn_ft_resp()
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (42 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 43/64] libfc: discovery restart sequence error fix Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 45/64] libfc: handle discovery failure more correctly Robert Love
                   ` (19 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Code cleanup for fc_disc_gpn_ft_resp().

Some of the fc_disc.c code was poorly formatted. For example, some lines
in fc_disc.c were unnecessarily truncated and the buf variable could
be eliminated.

Also moved the increment of seq_count into fc_disc_gpn_ft_parse(), to
avoid doing it separately before each call.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |   28 ++++++++++++----------------
 1 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index fd3a6b2..819ec62 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -469,6 +469,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 	struct fc_rport_priv *rdata;
 
 	lport = disc->lport;
+	disc->seq_count++;
 
 	/*
 	 * Handle partial name record left over from previous call.
@@ -582,10 +583,10 @@ 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_DISC_DBG(disc, "Received a GPN_FT response\n");
@@ -600,8 +601,7 @@ 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_DISC_DBG(disc, "GPN_FT response too short, len %d\n",
@@ -609,33 +609,29 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *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_DISC_DBG(disc, "GPN_FT rejected reason %x exp %x "
 				    "(check zoning)\n", cp->ct_reason,
 				    cp->ct_explan);
-			fc_disc_done(disc, DISC_EV_FAILED);
+			event = DISC_EV_FAILED;
 		} else {
 			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_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 (buf) {
-		disc->seq_count++;
-		error = fc_disc_gpn_ft_parse(disc, buf, len);
-		if (error)
-			fc_disc_error(disc, 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);
 }
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 45/64] libfc: handle discovery failure more correctly.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (43 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 44/64] libfc: rearrange code in fc_disc_gpn_ft_resp() Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 46/64] libfc: fix: empty zone causes endless discovery retries Robert Love
                   ` (18 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Abhijeet Joglekar wrote: "In gpn_ft_resp, if the payload is short,
or unexpected response or out of sequence frame, then we just
return and do nothing. We should either enter fc_disc_done()
with DISC_EV_FAIL which will then restart any queued discovery
requests or call lport module which will reset local port,
or we should call fc_disc_error() so that the gpn_ft is retried.

The situation as is causes discovery to remain pending and never
get restarted, in these rare cases.  We saw this due to a coding
bug in fc_disc before.  The only ways it could happen would be
bugs, packet corruption or an FC fabric problem.

Change it to fail discovery.  The local port will restart
discovery, although it probably should just give up until
the next link flap.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 819ec62..844376c 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -606,6 +606,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
 		if (!cp) {
 			FC_DISC_DBG(disc, "GPN_FT response too short, len %d\n",
 				    fr_len(fp));
+			event = DISC_EV_FAILED;
 		} else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
 
 			/* Accepted, parse the response. */
@@ -619,6 +620,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
 		} else {
 			FC_DISC_DBG(disc, "GPN_FT unexpected response code "
 				    "%x\n", ntohs(cp->ct_cmd));
+			event = DISC_EV_FAILED;
 		}
 	} else if (fr_sof(fp) == FC_SOF_N3 && seq_cnt == disc->seq_count) {
 		error = fc_disc_gpn_ft_parse(disc, fh + 1, len);
@@ -626,6 +628,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
 		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));
+		event = DISC_EV_FAILED;
 	}
 	if (error)
 		fc_disc_error(disc, fp);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 46/64] libfc: fix: empty zone causes endless discovery retries.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (44 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 45/64] libfc: handle discovery failure more correctly Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 47/64] libfc: discovery retry should clear pending first Robert Love
                   ` (17 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

On some switches, an empty zone causes GPN_FT to be rejected
with reason 9 (unable) explanation 7 (FC-4 types not registered),
which causes discovery to be retried endlessly.  Treat this as
just an empty response and consider discovery complete.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |    3 +++
 include/scsi/fc/fc_gs.h      |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 844376c..9b8043b 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -617,6 +617,9 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
 				    "(check zoning)\n", cp->ct_reason,
 				    cp->ct_explan);
 			event = DISC_EV_FAILED;
+			if (cp->ct_reason == FC_FS_RJT_UNABL &&
+			    cp->ct_explan == FC_FS_EXP_FTNR)
+				event = DISC_EV_SUCCESS;
 		} else {
 			FC_DISC_DBG(disc, "GPN_FT unexpected response code "
 				    "%x\n", ntohs(cp->ct_cmd));
diff --git a/include/scsi/fc/fc_gs.h b/include/scsi/fc/fc_gs.h
index ffab027..324dd0e 100644
--- a/include/scsi/fc/fc_gs.h
+++ b/include/scsi/fc/fc_gs.h
@@ -87,6 +87,7 @@ enum fc_ct_explan {
 	FC_FS_EXP_PNAM =	0x02,	/* port name not registered */
 	FC_FS_EXP_NNAM =	0x03,	/* node name not registered */
 	FC_FS_EXP_COS =		0x04,	/* class of service not registered */
+	FC_FS_EXP_FTNR =	0x07,	/* FC-4 types not registered */
 	/* definitions not complete */
 };
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 47/64] libfc: discovery retry should clear pending first.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (45 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 46/64] libfc: fix: empty zone causes endless discovery retries Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 48/64] libfc: discovery gpn_ft parse bug Robert Love
                   ` (16 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Currently fc_disc_timeout() restarts discovery only if it is not pending.
When the timer is scheduled, the discovery is left pending, so the
timeout never restarts it.

Fix by not checking for pending in the timeout handler.

If discovery is stopped and restarted in the meantime, the timeout will
be canceled.

Also, when a new discovery is started, the retry count wasn't cleared.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 9b8043b..3efdbba 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -233,6 +233,7 @@ static void fc_disc_restart(struct fc_disc *disc)
 	 * freshly-discovered remote ports.  Avoid wrapping to zero.
 	 */
 	disc->disc_id = (disc->disc_id + 2) | 1;
+	disc->retry_count = 0;
 	fc_disc_gpn_ft_req(disc);
 }
 
@@ -563,8 +564,7 @@ static void fc_disc_timeout(struct work_struct *work)
 					    struct fc_disc,
 					    disc_work.work);
 	mutex_lock(&disc->disc_mutex);
-	if (disc->requested && !disc->pending)
-		fc_disc_gpn_ft_req(disc);
+	fc_disc_gpn_ft_req(disc);
 	mutex_unlock(&disc->disc_mutex);
 }
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 48/64] libfc: discovery gpn_ft parse bug
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (46 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 47/64] libfc: discovery retry should clear pending first Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 49/64] libfc: clean up point-to-point discovery code Robert Love
                   ` (15 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

In fc_disc_gpn_ft_parse(), after fc_disc_done() is called, the
disc state is changed by setting buf_len = 0.  This is wrong
since the discovery may have restarted.   Instead, return
after calling fc_disc_done.

Also, return an error on memory allocation failure.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 3efdbba..a2410dc 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -479,6 +479,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 	plen = len;
 	np = (struct fc_gpn_ft_resp *)bp;
 	tlen = disc->buf_len;
+	disc->buf_len = 0;
 	if (tlen) {
 		WARN_ON(tlen >= sizeof(*np));
 		plen = sizeof(*np) - tlen;
@@ -519,10 +520,12 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 			rdata = lport->tt.rport_create(lport, &ids);
 			if (rdata)
 				rdata->disc_id = disc->disc_id;
-			else
+			else {
 				printk(KERN_WARNING "libfc: Failed to allocate "
 				       "memory for the newly discovered port "
 				       "(%6x)\n", ids.port_id);
+				error = -ENOMEM;
+			}
 		}
 
 		if (np->fp_flags & FC_NS_FID_LAST) {
@@ -546,8 +549,6 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 			memcpy(&disc->partial_buf, np, len);
 		}
 		disc->buf_len = (unsigned char) len;
-	} else {
-		disc->buf_len = 0;
 	}
 	return error;
 }


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 49/64] libfc: clean up point-to-point discovery code.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (47 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 48/64] libfc: discovery gpn_ft parse bug Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 50/64] libfc: don't do discovery before callback is set Robert Love
                   ` (14 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

The discovery code had a special-case for the point-to-point mode,
which used a bunch of code that wasn't really needed.

Now that rport_create adds the rport to the discovery list,
completely skip discovery for the point-to-point case.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |   84 +----------------------------------------
 drivers/scsi/libfc/fc_lport.c |   13 +-----
 2 files changed, 4 insertions(+), 93 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index a2410dc..4284218 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -45,8 +45,6 @@
 
 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_priv *,
-			      struct fc_rport_identifiers *);
 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 *);
@@ -240,14 +238,12 @@ static void fc_disc_restart(struct fc_disc *disc)
 /**
  * fc_disc_start() - Fibre Channel Target discovery
  * @lport: FC local port
- *
- * Returns non-zero if discovery cannot be started.
+ * @disc_callback: function to be called when discovery is complete
  */
 static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
 						enum fc_disc_event),
 			  struct fc_lport *lport)
 {
-	struct fc_rport_priv *rdata;
 	struct fc_disc *disc = &lport->disc;
 
 	/*
@@ -256,88 +252,12 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
 	 * and send the GPN_FT request.
 	 */
 	mutex_lock(&disc->disc_mutex);
-
 	disc->disc_callback = disc_callback;
-
-	/*
-	 * If not ready, or already running discovery, just set request flag.
-	 */
-	disc->requested = 1;
-
-	if (disc->pending) {
-		mutex_unlock(&disc->disc_mutex);
-		return;
-	}
-
-	/*
-	 * Handle point-to-point mode as a simple discovery
-	 * of the remote port. Yucky, yucky, yuck, yuck!
-	 */
-	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);
-		}
-		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 */
-	}
-
+	fc_disc_restart(disc);
 	mutex_unlock(&disc->disc_mutex);
 }
 
 /**
- * fc_disc_new_target() - Handle new target found by discovery
- * @lport: FC local 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_priv *rdata,
-			      struct fc_rport_identifiers *ids)
-{
-	struct fc_lport *lport = disc->lport;
-	int error = 0;
-
-	if (rdata && ids->port_name) {
-		if (rdata->ids.port_name == -1) {
-			/*
-			 * Set WWN and fall through to notify of create.
-			 */
-			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
-			 * port logged out and a new port logged in and was
-			 * assigned the same FCID.  This should be rare.
-			 * Delete the old one and fall thru to re-create.
-			 */
-			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 (!rdata) {
-			rdata = lport->tt.rport_create(lport, ids);
-			if (!rdata)
-				error = -ENOMEM;
-		}
-		if (rdata)
-			lport->tt.rport_login(rdata);
-	}
-	return error;
-}
-
-/**
  * fc_disc_done() - Discovery has been completed
  * @disc: FC discovery context
  * @event: discovery completion status
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index f33e573..7000df5 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -708,7 +708,8 @@ static void fc_lport_enter_ready(struct fc_lport *lport)
 
 	fc_lport_state_enter(lport, LPORT_ST_READY);
 
-	lport->tt.disc_start(fc_lport_disc_callback, lport);
+	if (!lport->ptp_rp)
+		lport->tt.disc_start(fc_lport_disc_callback, lport);
 }
 
 /**
@@ -794,8 +795,6 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
 	fc_lport_ptp_setup(lport, remote_fid, remote_wwpn,
 			   get_unaligned_be64(&flp->fl_wwnn));
 
-	lport->tt.disc_start(fc_lport_disc_callback, lport);
-
 out:
 	sp = fr_seq(rx_fp);
 	fc_frame_free(rx_fp);
@@ -1512,14 +1511,6 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 				fc_lport_enter_dns(lport);
 			}
 		}
-
-		if (flp) {
-			csp_flags = ntohs(flp->fl_csp.sp_features);
-			if ((csp_flags & FC_SP_FT_FPORT) == 0) {
-				lport->tt.disc_start(fc_lport_disc_callback,
-						     lport);
-			}
-		}
 	} else {
 		FC_LPORT_DBG(lport, "Bad FLOGI response\n");
 	}


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 50/64] libfc: don't do discovery before callback is set
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (48 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 49/64] libfc: clean up point-to-point discovery code Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:02 ` [PATCH 51/64] libfc: Initialize fc_rport_identifiers inside fc_rport_create Robert Love
                   ` (13 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

It's possible to "restart" discovery before it was started if
an RSCN is received early enough.  We were jumping to 0
due to the disc_callback function pointer not getting set.

Don't restart discovery if disc_callback is NULL.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 4284218..1a699f4 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -219,6 +219,9 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
  */
 static void fc_disc_restart(struct fc_disc *disc)
 {
+	if (!disc->disc_callback)
+		return;
+
 	FC_DISC_DBG(disc, "Restarting discovery\n");
 
 	disc->requested = 1;


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 51/64] libfc: Initialize fc_rport_identifiers inside fc_rport_create
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (49 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 50/64] libfc: don't do discovery before callback is set Robert Love
@ 2009-08-25 21:02 ` Robert Love
  2009-08-25 21:03 ` [PATCH 52/64] libfc: Always reset remote port roles when receiving PRLI Robert Love
                   ` (12 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:02 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Robert Love

Currently these values are initialized by the callers. This was exposed
by a later patch that adds PLOGI request support. The patch failed to
initialize the new remote port's roles and it caused problems. This patch
has the rport_create routine initialize the identifiers and then the
callers can override them with real values.

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

 drivers/scsi/libfc/fc_disc.c  |   20 ++++++++------------
 drivers/scsi/libfc/fc_lport.c |   19 ++++---------------
 drivers/scsi/libfc/fc_rport.c |   18 +++++++++++-------
 include/scsi/libfc.h          |   17 +++++++++--------
 4 files changed, 32 insertions(+), 42 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 1a699f4..4242894 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -137,10 +137,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
 				break;
 			}
 			dp->lp = lport;
-			dp->ids.port_id = ntoh24(pp->rscn_fid);
-			dp->ids.port_name = -1;
-			dp->ids.node_name = -1;
-			dp->ids.roles = FC_RPORT_ROLE_UNKNOWN;
+			dp->port_id = ntoh24(pp->rscn_fid);
 			list_add_tail(&dp->peers, &disc_ports);
 			break;
 		case ELS_ADDR_FMT_AREA:
@@ -162,7 +159,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
 			    redisc, lport->state, disc->pending);
 		list_for_each_entry_safe(dp, next, &disc_ports, peers) {
 			list_del(&dp->peers);
-			rdata = lport->tt.rport_lookup(lport, dp->ids.port_id);
+			rdata = lport->tt.rport_lookup(lport, dp->port_id);
 			if (rdata) {
 				lport->tt.rport_logoff(rdata);
 			}
@@ -435,15 +432,14 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
 	while (plen >= sizeof(*np)) {
 		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 = lport->tt.rport_create(lport, ids.port_id);
+			if (rdata) {
+				rdata->ids.port_name = ids.port_name;
 				rdata->disc_id = disc->disc_id;
-			else {
+			} else {
 				printk(KERN_WARNING "libfc: Failed to allocate "
 				       "memory for the newly discovered port "
 				       "(%6x)\n", ids.port_id);
@@ -580,10 +576,10 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
 
 	lport = disc->lport;
 
-	if (dp->ids.port_id == fc_host_port_id(lport->host))
+	if (dp->port_id == fc_host_port_id(lport->host))
 		goto out;
 
-	rdata = lport->tt.rport_create(lport, &dp->ids);
+	rdata = lport->tt.rport_create(lport, dp->port_id);
 	if (rdata) {
 		rdata->disc_id = disc->disc_id;
 		kfree(dp);
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 7000df5..caf6824 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -198,17 +198,12 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
 			       u32 remote_fid, u64 remote_wwpn,
 			       u64 remote_wwnn)
 {
-	struct fc_rport_identifiers ids;
-
-	ids.port_id = remote_fid;
-	ids.port_name = remote_wwpn;
-	ids.node_name = remote_wwnn;
-	ids.roles = FC_RPORT_ROLE_UNKNOWN;
-
 	mutex_lock(&lport->disc.disc_mutex);
 	if (lport->ptp_rp)
 		lport->tt.rport_logoff(lport->ptp_rp);
-	lport->ptp_rp = lport->tt.rport_create(lport, &ids);
+	lport->ptp_rp = lport->tt.rport_create(lport, remote_fid);
+	lport->ptp_rp->ids.port_name = remote_wwpn;
+	lport->ptp_rp->ids.node_name = remote_wwnn;
 	mutex_unlock(&lport->disc.disc_mutex);
 
 	lport->tt.rport_login(lport->ptp_rp);
@@ -1287,12 +1282,6 @@ static struct fc_rport_operations fc_lport_rport_ops = {
 static void fc_lport_enter_dns(struct fc_lport *lport)
 {
 	struct fc_rport_priv *rdata;
-	struct fc_rport_identifiers ids;
-
-	ids.port_id = FC_FID_DIR_SERV;
-	ids.port_name = -1;
-	ids.node_name = -1;
-	ids.roles = FC_RPORT_ROLE_UNKNOWN;
 
 	FC_LPORT_DBG(lport, "Entered DNS state from %s state\n",
 		     fc_lport_state(lport));
@@ -1300,7 +1289,7 @@ static void fc_lport_enter_dns(struct fc_lport *lport)
 	fc_lport_state_enter(lport, LPORT_ST_DNS);
 
 	mutex_lock(&lport->disc.disc_mutex);
-	rdata = lport->tt.rport_create(lport, &ids);
+	rdata = lport->tt.rport_create(lport, FC_FID_DIR_SERV);
 	mutex_unlock(&lport->disc.disc_mutex);
 	if (!rdata)
 		goto err;
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 99ac056..c667be8 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -104,18 +104,18 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport,
 }
 
 /**
- * fc_rport_create() - create remote port in INIT state.
- * @lport: local port.
- * @ids: remote port identifiers.
+ * fc_rport_create() - Create a new remote port
+ * @lport:   The local port that the new remote port is for
+ * @port_id: The port ID for the new remote port
  *
  * Locking note:  must be called with the disc_mutex held.
  */
 static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
-					     struct fc_rport_identifiers *ids)
+					     u32 port_id)
 {
 	struct fc_rport_priv *rdata;
 
-	rdata = lport->tt.rport_lookup(lport, ids->port_id);
+	rdata = lport->tt.rport_lookup(lport, port_id);
 	if (rdata)
 		return rdata;
 
@@ -123,7 +123,11 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
 	if (!rdata)
 		return NULL;
 
-	rdata->ids = *ids;
+	rdata->ids.node_name = -1;
+	rdata->ids.port_name = -1;
+	rdata->ids.port_id = port_id;
+	rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
+
 	kref_init(&rdata->kref);
 	mutex_init(&rdata->rp_mutex);
 	rdata->local_port = lport;
@@ -135,7 +139,7 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
 	rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
 	INIT_WORK(&rdata->event_work, fc_rport_work);
-	if (ids->port_id != FC_FID_DIR_SERV)
+	if (port_id != FC_FID_DIR_SERV)
 		list_add(&rdata->peers, &lport->disc.rports);
 	return rdata;
 }
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 517dce5..cd410c1 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -148,16 +148,16 @@ enum fc_rport_state {
 
 /**
  * struct fc_disc_port - temporary discovery port to hold rport identifiers
- * @lp: Fibre Channel host port instance
- * @peers: node for list management during discovery and RSCN processing
- * @ids: identifiers structure to pass to fc_remote_port_add()
- * @rport_work: work struct for starting the rport state machine
+ * @lp:         Fibre Channel host port instance
+ * @peers:      Node for list management during discovery and RSCN processing
+ * @rport_work: Work struct for starting the rport state machine
+ * @port_id:    Port ID of the discovered port
  */
 struct fc_disc_port {
 	struct fc_lport             *lp;
 	struct list_head            peers;
-	struct fc_rport_identifiers ids;
 	struct work_struct	    rport_work;
+	u32                         port_id;
 };
 
 enum fc_rport_event {
@@ -565,10 +565,11 @@ struct libfc_function_template {
 	int (*lport_reset)(struct fc_lport *);
 
 	/*
-	 * Create a remote port
+	 * Create a remote port with a given port ID
+	 *
+	 * STATUS: OPTIONAL
 	 */
-	struct fc_rport_priv *(*rport_create)(struct fc_lport *,
-					      struct fc_rport_identifiers *);
+	struct fc_rport_priv *(*rport_create)(struct fc_lport *, u32);
 
 	/*
 	 * Initiates the RP state machine. It is called from the LP module.


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 52/64] libfc: Always reset remote port roles when receiving PRLI
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (50 preceding siblings ...)
  2009-08-25 21:02 ` [PATCH 51/64] libfc: Initialize fc_rport_identifiers inside fc_rport_create Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 53/64] libfc: move remote port lookup for ELS requests into fc_rport.c Robert Love
                   ` (11 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Robert Love

Don't trust previous roles, reset them when we receive a PRLI.

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

 drivers/scsi/libfc/fc_rport.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index c667be8..cb54115 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -666,6 +666,9 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 		goto err;
 	}
 
+	/* reinitialize remote port roles */
+	rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
+
 	op = fc_frame_payload_op(fp);
 	if (op == ELS_LS_ACC) {
 		pp = fc_frame_payload_get(fp, sizeof(*pp));
@@ -1173,6 +1176,9 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 		pp->prli.prli_len = htons(len);
 		len -= sizeof(struct fc_els_prli);
 
+		/* reinitialize remote port roles */
+		rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
+
 		/*
 		 * Go through all the service parameter pages and build
 		 * response.  If plen indicates longer SPP than standard,


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 53/64] libfc: move remote port lookup for ELS requests into fc_rport.c.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (51 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 52/64] libfc: Always reset remote port roles when receiving PRLI Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 54/64] libfc: fix: rport_recv_req needs disc_mutex when calling rport_lookup Robert Love
                   ` (10 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

This moves the remote port lookup for incoming ELS requests into
fc_rport.c, in preparation for handing PLOGI and LOGO from
unknown rports.

This changes the arg to rport_recv_req from an rdata to an lport.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_lport.c |   30 +---------------
 drivers/scsi/libfc/fc_rport.c |   78 ++++++++++++++++++++++-------------------
 include/scsi/libfc.h          |    2 +
 3 files changed, 44 insertions(+), 66 deletions(-)

diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index caf6824..d3f4e0c 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -812,10 +812,6 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
 {
 	struct fc_frame_header *fh = fc_frame_header_get(fp);
 	void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *);
-	struct fc_rport_priv *rdata;
-	u32 s_id;
-	u32 d_id;
-	struct fc_seq_els_data rjt_data;
 
 	mutex_lock(&lport->lp_mutex);
 
@@ -831,7 +827,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
 		/*
 		 * Check opcode.
 		 */
-		recv = NULL;
+		recv = lport->tt.rport_recv_req;
 		switch (fc_frame_payload_op(fp)) {
 		case ELS_FLOGI:
 			recv = fc_lport_recv_flogi_req;
@@ -858,29 +854,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
 			break;
 		}
 
-		if (recv)
-			recv(sp, fp, lport);
-		else {
-			/*
-			 * Find session.
-			 * If this is a new incoming PLOGI, we won't find it.
-			 */
-			s_id = ntoh24(fh->fh_s_id);
-			d_id = ntoh24(fh->fh_d_id);
-
-			rdata = lport->tt.rport_lookup(lport, s_id);
-			if (rdata)
-				lport->tt.rport_recv_req(sp, fp, rdata);
-			else {
-				rjt_data.fp = NULL;
-				rjt_data.reason = ELS_RJT_UNAB;
-				rjt_data.explan = ELS_EXPL_NONE;
-				lport->tt.seq_els_rsp_send(sp,
-							   ELS_LS_RJT,
-							   &rjt_data);
-				fc_frame_free(fp);
-			}
-		}
+		recv(sp, fp, lport);
 	} else {
 		FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n",
 			     fr_eof(fp));
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index cb54115..acdc72d 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -912,57 +912,61 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
  * fc_rport_recv_req() - Receive a request from a rport
  * @sp: current sequence in the PLOGI exchange
  * @fp: response frame
- * @rdata_arg: private remote port data
+ * @lport: Fibre Channel local port
  *
- * Locking Note: Called without the rport lock held. This
- * function will hold the rport lock, call an _enter_*
- * function and then unlock the rport.
+ * Locking Note: Called with the lport lock held.
  */
 void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
-		       struct fc_rport_priv *rdata)
+		       struct fc_lport *lport)
 {
-	struct fc_lport *lport = rdata->local_port;
-
+	struct fc_rport_priv *rdata;
 	struct fc_frame_header *fh;
 	struct fc_seq_els_data els_data;
+	u32 s_id;
 	u8 op;
 
-	mutex_lock(&rdata->rp_mutex);
-
 	els_data.fp = NULL;
 	els_data.explan = ELS_EXPL_NONE;
 	els_data.reason = ELS_RJT_NONE;
 
 	fh = fc_frame_header_get(fp);
+	s_id = ntoh24(fh->fh_s_id);
 
-	if (fh->fh_r_ctl == FC_RCTL_ELS_REQ && fh->fh_type == FC_TYPE_ELS) {
-		op = fc_frame_payload_op(fp);
-		switch (op) {
-		case ELS_PLOGI:
-			fc_rport_recv_plogi_req(rdata, sp, fp);
-			break;
-		case ELS_PRLI:
-			fc_rport_recv_prli_req(rdata, sp, fp);
-			break;
-		case ELS_PRLO:
-			fc_rport_recv_prlo_req(rdata, sp, fp);
-			break;
-		case ELS_LOGO:
-			fc_rport_recv_logo_req(rdata, sp, fp);
-			break;
-		case ELS_RRQ:
-			els_data.fp = fp;
-			lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data);
-			break;
-		case ELS_REC:
-			els_data.fp = fp;
-			lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data);
-			break;
-		default:
-			els_data.reason = ELS_RJT_UNSUP;
-			lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
-			break;
-		}
+	rdata = lport->tt.rport_lookup(lport, s_id);
+	if (!rdata) {
+		els_data.reason = ELS_RJT_UNAB;
+		lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
+		fc_frame_free(fp);
+		return;
+	}
+	mutex_lock(&rdata->rp_mutex);
+
+	op = fc_frame_payload_op(fp);
+	switch (op) {
+	case ELS_PLOGI:
+		fc_rport_recv_plogi_req(rdata, sp, fp);
+		break;
+	case ELS_PRLI:
+		fc_rport_recv_prli_req(rdata, sp, fp);
+		break;
+	case ELS_PRLO:
+		fc_rport_recv_prlo_req(rdata, sp, fp);
+		break;
+	case ELS_LOGO:
+		fc_rport_recv_logo_req(rdata, sp, fp);
+		break;
+	case ELS_RRQ:
+		els_data.fp = fp;
+		lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data);
+		break;
+	case ELS_REC:
+		els_data.fp = fp;
+		lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data);
+		break;
+	default:
+		els_data.reason = ELS_RJT_UNSUP;
+		lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
+		break;
 	}
 
 	mutex_unlock(&rdata->rp_mutex);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index cd410c1..265f106 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -598,7 +598,7 @@ struct libfc_function_template {
 	 * STATUS: OPTIONAL
 	 */
 	void (*rport_recv_req)(struct fc_seq *, struct fc_frame *,
-			       struct fc_rport_priv *);
+			       struct fc_lport *);
 
 	/*
 	 * lookup an rport by it's port ID.


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 54/64] libfc: fix: rport_recv_req needs disc_mutex when calling rport_lookup
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (52 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 53/64] libfc: move remote port lookup for ELS requests into fc_rport.c Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 55/64] libfc: improve debug messages for ELS response handlers Robert Love
                   ` (9 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

The rport_lookup function must be called while holding the disc_mutex.
Otherwise, the rdata could be deleted just after that by another thread.

All callers now check the state after grabbing the rdata rp_mutex.
Even though rport_lookup skips ports in DELETE state, it does that
without holding the rdata rp_mutex, so that the state may change.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_rport.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index acdc72d..02200b2 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -932,14 +932,17 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 	fh = fc_frame_header_get(fp);
 	s_id = ntoh24(fh->fh_s_id);
 
+	mutex_lock(&lport->disc.disc_mutex);
 	rdata = lport->tt.rport_lookup(lport, s_id);
 	if (!rdata) {
+		mutex_unlock(&lport->disc.disc_mutex);
 		els_data.reason = ELS_RJT_UNAB;
 		lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
 		fc_frame_free(fp);
 		return;
 	}
 	mutex_lock(&rdata->rp_mutex);
+	mutex_unlock(&lport->disc.disc_mutex);
 
 	op = fc_frame_payload_op(fp);
 	switch (op) {


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 55/64] libfc: improve debug messages for ELS response handlers
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (53 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 54/64] libfc: fix: rport_recv_req needs disc_mutex when calling rport_lookup Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 56/64] libfc: correctly handle incoming PLOGI request Robert Love
                   ` (8 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

Improve lport and rport debug messages to indicate whether
the response is LS_ACC, LS_RJT, closed, or timeout.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_elsct.c |   38 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/libfc/fc_lport.c |   20 ++++++++++----------
 drivers/scsi/libfc/fc_rport.c |    8 ++++----
 include/scsi/libfc.h          |    5 +++++
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index 5e8b011..d655924 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -70,3 +70,41 @@ int fc_elsct_init(struct fc_lport *lport)
 	return 0;
 }
 EXPORT_SYMBOL(fc_elsct_init);
+
+/**
+ * fc_els_resp_type() - return string describing ELS response for debug.
+ * @fp: frame pointer with possible error code.
+ */
+const char *fc_els_resp_type(struct fc_frame *fp)
+{
+	const char *msg;
+	if (IS_ERR(fp)) {
+		switch (-PTR_ERR(fp)) {
+		case FC_NO_ERR:
+			msg = "response no error";
+			break;
+		case FC_EX_TIMEOUT:
+			msg = "response timeout";
+			break;
+		case FC_EX_CLOSED:
+			msg = "response closed";
+			break;
+		default:
+			msg = "response unknown error";
+			break;
+		}
+	} else {
+		switch (fc_frame_payload_op(fp)) {
+		case ELS_LS_ACC:
+			msg = "accept";
+			break;
+		case ELS_LS_RJT:
+			msg = "reject";
+			break;
+		default:
+			msg = "response unknown ELS";
+			break;
+		}
+	}
+	return msg;
+}
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index d3f4e0c..3f2f723 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1006,13 +1006,13 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
 	struct fc_frame_header *fh;
 	struct fc_ct_hdr *ct;
 
+	FC_LPORT_DBG(lport, "Received a RFT_ID %s\n", fc_els_resp_type(fp));
+
 	if (fp == ERR_PTR(-FC_EX_CLOSED))
 		return;
 
 	mutex_lock(&lport->lp_mutex);
 
-	FC_LPORT_DBG(lport, "Received a RFT_ID response\n");
-
 	if (lport->state != LPORT_ST_RFT_ID) {
 		FC_LPORT_DBG(lport, "Received a RFT_ID response, but in state "
 			     "%s\n", fc_lport_state(lport));
@@ -1060,13 +1060,13 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
 	struct fc_frame_header *fh;
 	struct fc_ct_hdr *ct;
 
+	FC_LPORT_DBG(lport, "Received a RPN_ID %s\n", fc_els_resp_type(fp));
+
 	if (fp == ERR_PTR(-FC_EX_CLOSED))
 		return;
 
 	mutex_lock(&lport->lp_mutex);
 
-	FC_LPORT_DBG(lport, "Received a RPN_ID response\n");
-
 	if (lport->state != LPORT_ST_RPN_ID) {
 		FC_LPORT_DBG(lport, "Received a RPN_ID response, but in state "
 			     "%s\n", fc_lport_state(lport));
@@ -1112,13 +1112,13 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
 	struct fc_lport *lport = lp_arg;
 	u8 op;
 
+	FC_LPORT_DBG(lport, "Received a SCR %s\n", fc_els_resp_type(fp));
+
 	if (fp == ERR_PTR(-FC_EX_CLOSED))
 		return;
 
 	mutex_lock(&lport->lp_mutex);
 
-	FC_LPORT_DBG(lport, "Received a SCR response\n");
-
 	if (lport->state != LPORT_ST_SCR) {
 		FC_LPORT_DBG(lport, "Received a SCR response, but in state "
 			     "%s\n", fc_lport_state(lport));
@@ -1333,13 +1333,13 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
 	struct fc_lport *lport = lp_arg;
 	u8 op;
 
+	FC_LPORT_DBG(lport, "Received a LOGO %s\n", fc_els_resp_type(fp));
+
 	if (fp == ERR_PTR(-FC_EX_CLOSED))
 		return;
 
 	mutex_lock(&lport->lp_mutex);
 
-	FC_LPORT_DBG(lport, "Received a LOGO response\n");
-
 	if (lport->state != LPORT_ST_LOGO) {
 		FC_LPORT_DBG(lport, "Received a LOGO response, but in state "
 			     "%s\n", fc_lport_state(lport));
@@ -1415,13 +1415,13 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 	unsigned int e_d_tov;
 	u16 mfs;
 
+	FC_LPORT_DBG(lport, "Received a FLOGI %s\n", fc_els_resp_type(fp));
+
 	if (fp == ERR_PTR(-FC_EX_CLOSED))
 		return;
 
 	mutex_lock(&lport->lp_mutex);
 
-	FC_LPORT_DBG(lport, "Received a FLOGI response\n");
-
 	if (lport->state != LPORT_ST_FLOGI) {
 		FC_LPORT_DBG(lport, "Received a FLOGI response, but in state "
 			     "%s\n", fc_lport_state(lport));
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 02200b2..d014b28 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -544,7 +544,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rdata, "Received a PLOGI response\n");
+	FC_RPORT_DBG(rdata, "Received a PLOGI %s\n", fc_els_resp_type(fp));
 
 	if (rdata->rp_state != RPORT_ST_PLOGI) {
 		FC_RPORT_DBG(rdata, "Received a PLOGI response, but in state "
@@ -651,7 +651,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rdata, "Received a PRLI response\n");
+	FC_RPORT_DBG(rdata, "Received a PRLI %s\n", fc_els_resp_type(fp));
 
 	if (rdata->rp_state != RPORT_ST_PRLI) {
 		FC_RPORT_DBG(rdata, "Received a PRLI response, but in state "
@@ -717,7 +717,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
 
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rdata, "Received a LOGO response\n");
+	FC_RPORT_DBG(rdata, "Received a LOGO %s\n", fc_els_resp_type(fp));
 
 	if (rdata->rp_state != RPORT_ST_LOGO) {
 		FC_RPORT_DBG(rdata, "Received a LOGO response, but in state "
@@ -801,7 +801,7 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
 
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rdata, "Received a RTV response\n");
+	FC_RPORT_DBG(rdata, "Received a RTV %s\n", fc_els_resp_type(fp));
 
 	if (rdata->rp_state != RPORT_ST_RTV) {
 		FC_RPORT_DBG(rdata, "Received a RTV response, but in state "
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 265f106..e18e5ce 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -1084,4 +1084,9 @@ void fc_destroy_exch_mgr(void);
 int fc_setup_rport(void);
 void fc_destroy_rport(void);
 
+/*
+ * Internal libfc functions.
+ */
+const char *fc_els_resp_type(struct fc_frame *);
+
 #endif /* _LIBFC_H_ */


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 56/64] libfc: correctly handle incoming PLOGI request.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (54 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 55/64] libfc: improve debug messages for ELS response handlers Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 57/64] libfc: fix rport error handling for login-required and invalid ops Robert Love
                   ` (7 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

libfc receives PLOGIs from switches which are trying to discover what
kind of devices are present, and from other initiators to find out
if we're a target.

As an initiator, some argue we don't need to handle incoming PLOGI
requests, and we currently reject them from unknown remote ports,
but accept them is we're in the middle of a PLOGI to the remote port.

For eventual target implementations, we want to handle them always.

For incoming PLOGI, don't fail if the rport_priv doesn't exist.
Just create it and go become READY without going through PRLI.  If
PRLI occurs, then our roles will be set and we'll become READY again.

Also, allow incoming PRLI in RTV state.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_rport.c |  185 +++++++++++++++++++++--------------------
 1 files changed, 93 insertions(+), 92 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index d014b28..e121ff9 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -63,7 +63,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *);
 static void fc_rport_enter_ready(struct fc_rport_priv *);
 static void fc_rport_enter_logo(struct fc_rport_priv *);
 
-static void fc_rport_recv_plogi_req(struct fc_rport_priv *,
+static void fc_rport_recv_plogi_req(struct fc_lport *,
 				    struct fc_seq *, struct fc_frame *);
 static void fc_rport_recv_prli_req(struct fc_rport_priv *,
 				   struct fc_seq *, struct fc_frame *);
@@ -576,15 +576,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 			csp_seq = cssp_seq;
 		rdata->max_seq = csp_seq;
 		rdata->maxframe_size = fc_plogi_get_maxframe(plp, lport->mfs);
-
-		/*
-		 * If the rport is one of the well known addresses
-		 * we skip PRLI and RTV and go straight to READY.
-		 */
-		if (rdata->ids.port_id >= FC_FID_DOM_MGR)
-			fc_rport_enter_ready(rdata);
-		else
-			fc_rport_enter_prli(rdata);
+		fc_rport_enter_prli(rdata);
 	} else
 		fc_rport_error_retry(rdata, fp);
 
@@ -763,6 +755,15 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 	} *pp;
 	struct fc_frame *fp;
 
+	/*
+	 * If the rport is one of the well known addresses
+	 * we skip PRLI and RTV and go straight to READY.
+	 */
+	if (rdata->ids.port_id >= FC_FID_DOM_MGR) {
+		fc_rport_enter_ready(rdata);
+		return;
+	}
+
 	FC_RPORT_DBG(rdata, "Port entered PRLI state from %s state\n",
 		     fc_rport_state(rdata));
 
@@ -929,6 +930,15 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 	els_data.explan = ELS_EXPL_NONE;
 	els_data.reason = ELS_RJT_NONE;
 
+	op = fc_frame_payload_op(fp);
+	switch (op) {
+	case ELS_PLOGI:
+		fc_rport_recv_plogi_req(lport, sp, fp);
+		return;
+	default:
+		break;
+	}
+
 	fh = fc_frame_header_get(fp);
 	s_id = ntoh24(fh->fh_s_id);
 
@@ -944,11 +954,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 	mutex_lock(&rdata->rp_mutex);
 	mutex_unlock(&lport->disc.disc_mutex);
 
-	op = fc_frame_payload_op(fp);
 	switch (op) {
-	case ELS_PLOGI:
-		fc_rport_recv_plogi_req(rdata, sp, fp);
-		break;
 	case ELS_PRLI:
 		fc_rport_recv_prli_req(rdata, sp, fp);
 		break;
@@ -977,48 +983,56 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 
 /**
  * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request
- * @rdata: private remote port data
+ * @lport: local port
  * @sp: current sequence in the PLOGI exchange
  * @fp: PLOGI request frame
  *
- * Locking Note: The rport lock is exected to be held before calling
- * this function.
+ * Locking Note: The rport lock is held before calling this function.
  */
-static void fc_rport_recv_plogi_req(struct fc_rport_priv *rdata,
+static void fc_rport_recv_plogi_req(struct fc_lport *lport,
 				    struct fc_seq *sp, struct fc_frame *rx_fp)
 {
-	struct fc_lport *lport = rdata->local_port;
+	struct fc_disc *disc;
+	struct fc_rport_priv *rdata;
 	struct fc_frame *fp = rx_fp;
 	struct fc_exch *ep;
 	struct fc_frame_header *fh;
 	struct fc_els_flogi *pl;
 	struct fc_seq_els_data rjt_data;
-	u32 sid;
-	u64 wwpn;
-	u64 wwnn;
-	enum fc_els_rjt_reason reject = 0;
-	u32 f_ctl;
-	rjt_data.fp = NULL;
+	u32 sid, f_ctl;
 
+	rjt_data.fp = NULL;
 	fh = fc_frame_header_get(fp);
+	sid = ntoh24(fh->fh_s_id);
 
-	FC_RPORT_DBG(rdata, "Received PLOGI request while in state %s\n",
-		     fc_rport_state(rdata));
+	FC_RPORT_ID_DBG(lport, sid, "Received PLOGI request\n");
 
-	sid = ntoh24(fh->fh_s_id);
 	pl = fc_frame_payload_get(fp, sizeof(*pl));
 	if (!pl) {
-		FC_RPORT_DBG(rdata, "Received PLOGI too short\n");
-		WARN_ON(1);
-		/* XXX TBD: send reject? */
-		fc_frame_free(fp);
-		return;
+		FC_RPORT_ID_DBG(lport, sid, "Received PLOGI too short\n");
+		rjt_data.reason = ELS_RJT_PROT;
+		rjt_data.explan = ELS_EXPL_INV_LEN;
+		goto reject;
+	}
+
+	disc = &lport->disc;
+	mutex_lock(&disc->disc_mutex);
+	rdata = lport->tt.rport_create(lport, sid);
+	if (!rdata) {
+		mutex_unlock(&disc->disc_mutex);
+		rjt_data.reason = ELS_RJT_UNAB;
+		rjt_data.explan = ELS_EXPL_INSUF_RES;
+		goto reject;
 	}
-	wwpn = get_unaligned_be64(&pl->fl_wwpn);
-	wwnn = get_unaligned_be64(&pl->fl_wwnn);
+
+	mutex_lock(&rdata->rp_mutex);
+	mutex_unlock(&disc->disc_mutex);
+
+	rdata->ids.port_name = get_unaligned_be64(&pl->fl_wwpn);
+	rdata->ids.node_name = get_unaligned_be64(&pl->fl_wwnn);
 
 	/*
-	 * If the session was just created, possibly due to the incoming PLOGI,
+	 * If the rport was just created, possibly due to the incoming PLOGI,
 	 * set the state appropriately and accept the PLOGI.
 	 *
 	 * If we had also sent a PLOGI, and if the received PLOGI is from a
@@ -1030,72 +1044,58 @@ static void fc_rport_recv_plogi_req(struct fc_rport_priv *rdata,
 	 */
 	switch (rdata->rp_state) {
 	case RPORT_ST_INIT:
-		FC_RPORT_DBG(rdata, "Received PLOGI, wwpn %llx state INIT "
-			     "- reject\n", (unsigned long long)wwpn);
-		reject = ELS_RJT_UNSUP;
+		FC_RPORT_DBG(rdata, "Received PLOGI in INIT state\n");
 		break;
 	case RPORT_ST_PLOGI:
-		FC_RPORT_DBG(rdata, "Received PLOGI in PLOGI state %d\n",
-			     rdata->rp_state);
-		if (wwpn < lport->wwpn)
-			reject = ELS_RJT_INPROG;
+		FC_RPORT_DBG(rdata, "Received PLOGI in PLOGI state\n");
+		if (rdata->ids.port_name < lport->wwpn) {
+			mutex_unlock(&rdata->rp_mutex);
+			rjt_data.reason = ELS_RJT_INPROG;
+			rjt_data.explan = ELS_EXPL_NONE;
+			goto reject;
+		}
 		break;
 	case RPORT_ST_PRLI:
 	case RPORT_ST_READY:
-		FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d "
-			     "- ignored for now\n", rdata->rp_state);
-		/* XXX TBD - should reset */
 		break;
 	case RPORT_ST_DELETE:
 	default:
-		FC_RPORT_DBG(rdata, "Received PLOGI in unexpected "
-			     "state %d\n", rdata->rp_state);
-		fc_frame_free(fp);
-		return;
-		break;
+		FC_RPORT_DBG(rdata, "Received PLOGI in unexpected state %d\n",
+			     rdata->rp_state);
+		fc_frame_free(rx_fp);
+		goto out;
 	}
 
-	if (reject) {
-		rjt_data.reason = reject;
-		rjt_data.explan = ELS_EXPL_NONE;
-		lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
-		fc_frame_free(fp);
-	} else {
-		fp = fc_frame_alloc(lport, sizeof(*pl));
-		if (fp == NULL) {
-			fp = rx_fp;
-			rjt_data.reason = ELS_RJT_UNAB;
-			rjt_data.explan = ELS_EXPL_NONE;
-			lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
-			fc_frame_free(fp);
-		} else {
-			sp = lport->tt.seq_start_next(sp);
-			WARN_ON(!sp);
-			rdata->ids.port_name = wwpn;
-			rdata->ids.node_name = wwnn;
-
-			/*
-			 * Get session payload size from incoming PLOGI.
-			 */
-			rdata->maxframe_size =
-				fc_plogi_get_maxframe(pl, lport->mfs);
-			fc_frame_free(rx_fp);
-			fc_plogi_fill(lport, fp, ELS_LS_ACC);
-
-			/*
-			 * Send LS_ACC.	 If this fails,
-			 * the originator should retry.
-			 */
-			f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ;
-			f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT;
-			ep = fc_seq_exch(sp);
-			fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
-				       FC_TYPE_ELS, f_ctl, 0);
-			lport->tt.seq_send(lport, sp, fp);
-			if (rdata->rp_state == RPORT_ST_PLOGI)
-				fc_rport_enter_prli(rdata);
-		}
-	}
+	/*
+	 * Get session payload size from incoming PLOGI.
+	 */
+	rdata->maxframe_size = fc_plogi_get_maxframe(pl, lport->mfs);
+	fc_frame_free(rx_fp);
+
+	/*
+	 * Send LS_ACC.	 If this fails, the originator should retry.
+	 */
+	sp = lport->tt.seq_start_next(sp);
+	if (!sp)
+		goto out;
+	fp = fc_frame_alloc(lport, sizeof(*pl));
+	if (!fp)
+		goto out;
+
+	fc_plogi_fill(lport, fp, ELS_LS_ACC);
+	f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT;
+	ep = fc_seq_exch(sp);
+	fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
+		       FC_TYPE_ELS, f_ctl, 0);
+	lport->tt.seq_send(lport, sp, fp);
+	fc_rport_enter_prli(rdata);
+out:
+	mutex_unlock(&rdata->rp_mutex);
+	return;
+
+reject:
+	lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
+	fc_frame_free(fp);
 }
 
 /**
@@ -1138,6 +1138,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 
 	switch (rdata->rp_state) {
 	case RPORT_ST_PRLI:
+	case RPORT_ST_RTV:
 	case RPORT_ST_READY:
 		reason = ELS_RJT_NONE;
 		break;


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 57/64] libfc: fix rport error handling for login-required and invalid ops
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (55 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 56/64] libfc: correctly handle incoming PLOGI request Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 58/64] libfc: re-login to remote ports that send us LOGO Robert Love
                   ` (6 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

When receiving an ELS request, if the request isn't recognized,
the unsupported operation error should be given even if the port
is not found or not logged in.

Also, the LOGO request shouldn't give the login-required explanation.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_rport.c |  137 ++++++++++++++++++++++++++---------------
 1 files changed, 88 insertions(+), 49 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index e121ff9..04e9846 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -69,7 +69,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *,
 				   struct fc_seq *, struct fc_frame *);
 static void fc_rport_recv_prlo_req(struct fc_rport_priv *,
 				   struct fc_seq *, struct fc_frame *);
-static void fc_rport_recv_logo_req(struct fc_rport_priv *,
+static void fc_rport_recv_logo_req(struct fc_lport *,
 				   struct fc_seq *, struct fc_frame *);
 static void fc_rport_timeout(struct work_struct *);
 static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *);
@@ -908,62 +908,56 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
 		kref_get(&rdata->kref);
 }
 
-
 /**
- * fc_rport_recv_req() - Receive a request from a rport
+ * fc_rport_recv_els_req() - handle a validated ELS request.
+ * @lport: Fibre Channel local port
  * @sp: current sequence in the PLOGI exchange
  * @fp: response frame
- * @lport: Fibre Channel local port
+ *
+ * Handle incoming ELS requests that require port login.
+ * The ELS opcode has already been validated by the caller.
  *
  * Locking Note: Called with the lport lock held.
  */
-void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
-		       struct fc_lport *lport)
+static void fc_rport_recv_els_req(struct fc_lport *lport,
+				  struct fc_seq *sp, struct fc_frame *fp)
 {
 	struct fc_rport_priv *rdata;
 	struct fc_frame_header *fh;
 	struct fc_seq_els_data els_data;
-	u32 s_id;
-	u8 op;
 
 	els_data.fp = NULL;
-	els_data.explan = ELS_EXPL_NONE;
-	els_data.reason = ELS_RJT_NONE;
-
-	op = fc_frame_payload_op(fp);
-	switch (op) {
-	case ELS_PLOGI:
-		fc_rport_recv_plogi_req(lport, sp, fp);
-		return;
-	default:
-		break;
-	}
+	els_data.reason = ELS_RJT_UNAB;
+	els_data.explan = ELS_EXPL_PLOGI_REQD;
 
 	fh = fc_frame_header_get(fp);
-	s_id = ntoh24(fh->fh_s_id);
 
 	mutex_lock(&lport->disc.disc_mutex);
-	rdata = lport->tt.rport_lookup(lport, s_id);
+	rdata = lport->tt.rport_lookup(lport, ntoh24(fh->fh_s_id));
 	if (!rdata) {
 		mutex_unlock(&lport->disc.disc_mutex);
-		els_data.reason = ELS_RJT_UNAB;
-		lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
-		fc_frame_free(fp);
-		return;
+		goto reject;
 	}
 	mutex_lock(&rdata->rp_mutex);
 	mutex_unlock(&lport->disc.disc_mutex);
 
-	switch (op) {
+	switch (rdata->rp_state) {
+	case RPORT_ST_PRLI:
+	case RPORT_ST_RTV:
+	case RPORT_ST_READY:
+		break;
+	default:
+		mutex_unlock(&rdata->rp_mutex);
+		goto reject;
+	}
+
+	switch (fc_frame_payload_op(fp)) {
 	case ELS_PRLI:
 		fc_rport_recv_prli_req(rdata, sp, fp);
 		break;
 	case ELS_PRLO:
 		fc_rport_recv_prlo_req(rdata, sp, fp);
 		break;
-	case ELS_LOGO:
-		fc_rport_recv_logo_req(rdata, sp, fp);
-		break;
 	case ELS_RRQ:
 		els_data.fp = fp;
 		lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data);
@@ -973,12 +967,58 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 		lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data);
 		break;
 	default:
-		els_data.reason = ELS_RJT_UNSUP;
-		lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
+		fc_frame_free(fp);	/* can't happen */
 		break;
 	}
 
 	mutex_unlock(&rdata->rp_mutex);
+	return;
+
+reject:
+	lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
+	fc_frame_free(fp);
+}
+
+/**
+ * fc_rport_recv_req() - Handle a received ELS request from a rport
+ * @sp: current sequence in the PLOGI exchange
+ * @fp: response frame
+ * @lport: Fibre Channel local port
+ *
+ * Locking Note: Called with the lport lock held.
+ */
+void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
+		       struct fc_lport *lport)
+{
+	struct fc_seq_els_data els_data;
+
+	/*
+	 * Handle PLOGI and LOGO requests separately, since they
+	 * don't require prior login.
+	 * Check for unsupported opcodes first and reject them.
+	 * For some ops, it would be incorrect to reject with "PLOGI required".
+	 */
+	switch (fc_frame_payload_op(fp)) {
+	case ELS_PLOGI:
+		fc_rport_recv_plogi_req(lport, sp, fp);
+		break;
+	case ELS_LOGO:
+		fc_rport_recv_logo_req(lport, sp, fp);
+		break;
+	case ELS_PRLI:
+	case ELS_PRLO:
+	case ELS_RRQ:
+	case ELS_REC:
+		fc_rport_recv_els_req(lport, sp, fp);
+		break;
+	default:
+		fc_frame_free(fp);
+		els_data.fp = NULL;
+		els_data.reason = ELS_RJT_UNSUP;
+		els_data.explan = ELS_EXPL_NONE;
+		lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data);
+		break;
+	}
 }
 
 /**
@@ -1276,11 +1316,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
 	FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n",
 		     fc_rport_state(rdata));
 
-	if (rdata->rp_state == RPORT_ST_DELETE) {
-		fc_frame_free(fp);
-		return;
-	}
-
 	rjt_data.fp = NULL;
 	rjt_data.reason = ELS_RJT_UNAB;
 	rjt_data.explan = ELS_EXPL_NONE;
@@ -1290,32 +1325,36 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
 
 /**
  * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request
- * @rdata: private remote port data
+ * @lport: local port.
  * @sp: current sequence in the LOGO exchange
  * @fp: LOGO request frame
  *
  * Locking Note: The rport lock is exected to be held before calling
  * this function.
  */
-static void fc_rport_recv_logo_req(struct fc_rport_priv *rdata,
+static void fc_rport_recv_logo_req(struct fc_lport *lport,
 				   struct fc_seq *sp,
 				   struct fc_frame *fp)
 {
 	struct fc_frame_header *fh;
-	struct fc_lport *lport = rdata->local_port;
+	struct fc_rport_priv *rdata;
+	u32 sid;
 
 	fh = fc_frame_header_get(fp);
+	sid = ntoh24(fh->fh_s_id);
 
-	FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",
-		     fc_rport_state(rdata));
-
-	if (rdata->rp_state == RPORT_ST_DELETE) {
-		fc_frame_free(fp);
-		return;
-	}
-
-	fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
-
+	mutex_lock(&lport->disc.disc_mutex);
+	rdata = lport->tt.rport_lookup(lport, sid);
+	if (rdata) {
+		mutex_lock(&rdata->rp_mutex);
+		FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",
+			     fc_rport_state(rdata));
+		fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
+		mutex_unlock(&rdata->rp_mutex);
+	} else
+		FC_RPORT_ID_DBG(lport, sid,
+				"Received LOGO from non-logged-in port\n");
+	mutex_unlock(&lport->disc.disc_mutex);
 	lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
 	fc_frame_free(fp);
 }


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 58/64] libfc: re-login to remote ports that send us LOGO
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (56 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 57/64] libfc: fix rport error handling for login-required and invalid ops Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 59/64] libfc: LOGO response code had extraeous enter_rtv Robert Love
                   ` (5 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

After a quick link flap, a target was seen to send us a LOGO.
Apparently, it saw an RSCN reporting that we had dropped out of the
fabric after we had logged back into it.

This is likely in larger fabrics (more than 2 FC switches) after
a quick link flap at the initiator.  Each link transition causes
an port-specific RSCN to the target.  After the link comes back up,
the initiator successfully discovers and does a PLOGI to the target
before the target sees the first RSCN reporting the initiator is gone,
and it sends a LOGO.  The target may see a subsequent RSCN saying the
port is back, but probably wouldn't send a PLOGI and leaves it
up to the initiator to re-login.

An RSCN can be delayed by the switches due to software layers but a
PLOGI is forwarded in hardware causing the PLOGI to beat the RSCN.

If a remote port is in the discovered set and sends a LOGO, re-login to it.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_rport.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 04e9846..dc97c60 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1340,6 +1340,8 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport,
 	struct fc_rport_priv *rdata;
 	u32 sid;
 
+	lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
+
 	fh = fc_frame_header_get(fp);
 	sid = ntoh24(fh->fh_s_id);
 
@@ -1349,13 +1351,20 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport,
 		mutex_lock(&rdata->rp_mutex);
 		FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",
 			     fc_rport_state(rdata));
-		fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
+
+		/*
+		 * If the remote port was created due to discovery,
+		 * log back in.  It may have seen a stale RSCN about us.
+		 */
+		if (rdata->rp_state != RPORT_ST_DELETE && rdata->disc_id)
+			fc_rport_enter_plogi(rdata);
+		else
+			fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
 		mutex_unlock(&rdata->rp_mutex);
 	} else
 		FC_RPORT_ID_DBG(lport, sid,
 				"Received LOGO from non-logged-in port\n");
 	mutex_unlock(&lport->disc.disc_mutex);
-	lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
 	fc_frame_free(fp);
 }
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 59/64] libfc: LOGO response code had extraeous enter_rtv
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (57 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 58/64] libfc: re-login to remote ports that send us LOGO Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 60/64] libfc: use ADISC to verify rport login state Robert Love
                   ` (4 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

fc_rport_logo_resp() had a call to fc_rport_enter_rtv() if the
LOGO was accepted.  This must've been a copy/paste mistake, but
it didn't matter since we don't stay in the LOGO state long enough
to hit this code.

Change fc_rport_logo_resp() to just enter the delete state
no matter what.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_rport.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index dc97c60..b5bc872 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -725,12 +725,10 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
 	}
 
 	op = fc_frame_payload_op(fp);
-	if (op == ELS_LS_ACC) {
-		fc_rport_enter_rtv(rdata);
-	} else {
-		FC_RPORT_DBG(rdata, "Bad ELS response for LOGO command\n");
-		fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
-	}
+	if (op != ELS_LS_ACC)
+		FC_RPORT_DBG(rdata, "Bad ELS response op %x for LOGO command\n",
+			     op);
+	fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
 
 out:
 	fc_frame_free(fp);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 60/64] libfc: use ADISC to verify rport login state
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (58 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 59/64] libfc: LOGO response code had extraeous enter_rtv Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 61/64] libfc: fix handling of incoming Discover Address (ADISC) requests Robert Love
                   ` (3 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

When rport_login is called on an rport that is already thought
to be logged in, use ADISC.  If that fails, redo PLOGI.
This is less disruptive after fabric changes that don't affect
the state of the target.

Implement the sending of ADISC via fc_els_fill.

Add ADISC state to the rport state machine.  This is entered from READY
and returns to READY after successful completion.  If it fails, the rport
is either logged off and deleted or re-does PLOGI.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_rport.c |  122 +++++++++++++++++++++++++++++++++++++++--
 include/scsi/fc_encode.h      |   21 +++++++
 include/scsi/libfc.h          |    1 
 3 files changed, 139 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index b5bc872..c33e258 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -62,6 +62,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *);
 static void fc_rport_enter_rtv(struct fc_rport_priv *);
 static void fc_rport_enter_ready(struct fc_rport_priv *);
 static void fc_rport_enter_logo(struct fc_rport_priv *);
+static void fc_rport_enter_adisc(struct fc_rport_priv *);
 
 static void fc_rport_recv_plogi_req(struct fc_lport *,
 				    struct fc_seq *, struct fc_frame *);
@@ -83,6 +84,7 @@ static const char *fc_rport_state_names[] = {
 	[RPORT_ST_RTV] = "RTV",
 	[RPORT_ST_READY] = "Ready",
 	[RPORT_ST_LOGO] = "LOGO",
+	[RPORT_ST_ADISC] = "ADISC",
 	[RPORT_ST_DELETE] = "Delete",
 };
 
@@ -326,15 +328,25 @@ static void fc_rport_work(struct work_struct *work)
  * Locking Note: Called without the rport lock held. This
  * function will hold the rport lock, call an _enter_*
  * function and then unlock the rport.
+ *
+ * This indicates the intent to be logged into the remote port.
+ * If it appears we are already logged in, ADISC is used to verify
+ * the setup.
  */
 int fc_rport_login(struct fc_rport_priv *rdata)
 {
 	mutex_lock(&rdata->rp_mutex);
 
-	FC_RPORT_DBG(rdata, "Login to port\n");
-
-	fc_rport_enter_plogi(rdata);
-
+	switch (rdata->rp_state) {
+	case RPORT_ST_READY:
+		FC_RPORT_DBG(rdata, "ADISC port\n");
+		fc_rport_enter_adisc(rdata);
+		break;
+	default:
+		FC_RPORT_DBG(rdata, "Login to port\n");
+		fc_rport_enter_plogi(rdata);
+		break;
+	}
 	mutex_unlock(&rdata->rp_mutex);
 
 	return 0;
@@ -448,6 +460,9 @@ static void fc_rport_timeout(struct work_struct *work)
 	case RPORT_ST_LOGO:
 		fc_rport_enter_logo(rdata);
 		break;
+	case RPORT_ST_ADISC:
+		fc_rport_enter_adisc(rdata);
+		break;
 	case RPORT_ST_READY:
 	case RPORT_ST_INIT:
 	case RPORT_ST_DELETE:
@@ -473,13 +488,16 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
 
 	switch (rdata->rp_state) {
 	case RPORT_ST_PLOGI:
-	case RPORT_ST_PRLI:
 	case RPORT_ST_LOGO:
 		fc_rport_enter_delete(rdata, RPORT_EV_FAILED);
 		break;
 	case RPORT_ST_RTV:
 		fc_rport_enter_ready(rdata);
 		break;
+	case RPORT_ST_PRLI:
+	case RPORT_ST_ADISC:
+		fc_rport_enter_logo(rdata);
+		break;
 	case RPORT_ST_DELETE:
 	case RPORT_ST_READY:
 	case RPORT_ST_INIT:
@@ -907,6 +925,93 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
 }
 
 /**
+ * fc_rport_els_adisc_resp() - Address Discovery response handler
+ * @sp: current sequence in the ADISC exchange
+ * @fp: response frame
+ * @rdata_arg: remote port private.
+ *
+ * Locking Note: This function will be called without the rport lock
+ * held, but it will lock, call an _enter_* function or fc_rport_error
+ * and then unlock the rport.
+ */
+static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp,
+			      void *rdata_arg)
+{
+	struct fc_rport_priv *rdata = rdata_arg;
+	struct fc_els_adisc *adisc;
+	u8 op;
+
+	mutex_lock(&rdata->rp_mutex);
+
+	FC_RPORT_DBG(rdata, "Received a ADISC response\n");
+
+	if (rdata->rp_state != RPORT_ST_ADISC) {
+		FC_RPORT_DBG(rdata, "Received a ADISC resp but in state %s\n",
+			     fc_rport_state(rdata));
+		if (IS_ERR(fp))
+			goto err;
+		goto out;
+	}
+
+	if (IS_ERR(fp)) {
+		fc_rport_error(rdata, fp);
+		goto err;
+	}
+
+	/*
+	 * If address verification failed.  Consider us logged out of the rport.
+	 * Since the rport is still in discovery, we want to be
+	 * logged in, so go to PLOGI state.  Otherwise, go back to READY.
+	 */
+	op = fc_frame_payload_op(fp);
+	adisc = fc_frame_payload_get(fp, sizeof(*adisc));
+	if (op != ELS_LS_ACC || !adisc ||
+	    ntoh24(adisc->adisc_port_id) != rdata->ids.port_id ||
+	    get_unaligned_be64(&adisc->adisc_wwpn) != rdata->ids.port_name ||
+	    get_unaligned_be64(&adisc->adisc_wwnn) != rdata->ids.node_name) {
+		FC_RPORT_DBG(rdata, "ADISC error or mismatch\n");
+		fc_rport_enter_plogi(rdata);
+	} else {
+		FC_RPORT_DBG(rdata, "ADISC OK\n");
+		fc_rport_enter_ready(rdata);
+	}
+out:
+	fc_frame_free(fp);
+err:
+	mutex_unlock(&rdata->rp_mutex);
+	kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
+}
+
+/**
+ * fc_rport_enter_adisc() - Send Address Discover (ADISC) request to peer
+ * @rdata: remote port private data
+ *
+ * Locking Note: The rport lock is expected to be held before calling
+ * this routine.
+ */
+static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
+{
+	struct fc_lport *lport = rdata->local_port;
+	struct fc_frame *fp;
+
+	FC_RPORT_DBG(rdata, "sending ADISC from %s state\n",
+		     fc_rport_state(rdata));
+
+	fc_rport_state_enter(rdata, RPORT_ST_ADISC);
+
+	fp = fc_frame_alloc(lport, sizeof(struct fc_els_adisc));
+	if (!fp) {
+		fc_rport_error_retry(rdata, fp);
+		return;
+	}
+	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC,
+				  fc_rport_adisc_resp, rdata, lport->e_d_tov))
+		fc_rport_error_retry(rdata, fp);
+	else
+		kref_get(&rdata->kref);
+}
+
+/**
  * fc_rport_recv_els_req() - handle a validated ELS request.
  * @lport: Fibre Channel local port
  * @sp: current sequence in the PLOGI exchange
@@ -943,6 +1048,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport,
 	case RPORT_ST_PRLI:
 	case RPORT_ST_RTV:
 	case RPORT_ST_READY:
+	case RPORT_ST_ADISC:
 		break;
 	default:
 		mutex_unlock(&rdata->rp_mutex);
@@ -1095,6 +1201,10 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport,
 		break;
 	case RPORT_ST_PRLI:
 	case RPORT_ST_READY:
+	case RPORT_ST_ADISC:
+		FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d "
+			     "- ignored for now\n", rdata->rp_state);
+		/* XXX TBD - should reset */
 		break;
 	case RPORT_ST_DELETE:
 	default:
@@ -1178,6 +1288,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 	case RPORT_ST_PRLI:
 	case RPORT_ST_RTV:
 	case RPORT_ST_READY:
+	case RPORT_ST_ADISC:
 		reason = ELS_RJT_NONE;
 		break;
 	default:
@@ -1283,6 +1394,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 			fc_rport_enter_ready(rdata);
 			break;
 		case RPORT_ST_READY:
+		case RPORT_ST_ADISC:
 			break;
 		default:
 			break;
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index 24bf764..c5ee6bb 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -57,6 +57,23 @@ static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl,
 }
 
 /**
+ * fc_adisc_fill() - Fill in adisc request frame
+ * @lport: local port.
+ * @fp: fc frame where payload will be placed.
+ */
+static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
+{
+	struct fc_els_adisc *adisc;
+
+	adisc = fc_frame_payload_get(fp, sizeof(*adisc));
+	memset(adisc, 0, sizeof(*adisc));
+	adisc->adisc_cmd = ELS_ADISC;
+	put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn);
+	put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn);
+	hton24(adisc->adisc_port_id, fc_host_port_id(lport->host));
+}
+
+/**
  * fc_ct_hdr_fill- fills ct header and reset ct payload
  * returns pointer to ct request.
  */
@@ -255,6 +272,10 @@ static inline int fc_els_fill(struct fc_lport *lport,
 		       enum fc_rctl *r_ctl, enum fc_fh_type *fh_type)
 {
 	switch (op) {
+	case ELS_ADISC:
+		fc_adisc_fill(lport, fp);
+		break;
+
 	case ELS_PLOGI:
 		fc_plogi_fill(lport, fp, ELS_PLOGI);
 		break;
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index e18e5ce..65dc9aa 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -143,6 +143,7 @@ enum fc_rport_state {
 	RPORT_ST_RTV,		/* waiting for RTV completion */
 	RPORT_ST_READY,		/* ready for use */
 	RPORT_ST_LOGO,		/* port logout sent */
+	RPORT_ST_ADISC,		/* Discover Address sent */
 	RPORT_ST_DELETE,	/* port being deleted */
 };
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 61/64] libfc: fix handling of incoming Discover Address (ADISC) requests
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (59 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 60/64] libfc: use ADISC to verify rport login state Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:03 ` [PATCH 62/64] libfc: send GPN_ID in reaction to single-port RSCNs Robert Love
                   ` (2 subsequent siblings)
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

The local port facility has been replying to ADISC requests without
looking to see if the remote port is logged in.  This is incorrect.
An ADISC request requires PLOGI first.  It should be rejected if
the sending remote port is not logged in.

This is like other incoming requests that require login, all of
which should be handled in the remote port module.

Move the ADISC request handling from fc_lport.c to fc_rport.c.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_lport.c |   53 -----------------------------------------
 drivers/scsi/libfc/fc_rport.c |   48 +++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 53 deletions(-)

diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 3f2f723..bd2f771 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -452,56 +452,6 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
 }
 
 /**
- * fc_lport_recv_adisc_req() - Handle received Address Discovery Request
- * @lport: Fibre Channel local port recieving the ADISC
- * @sp: current sequence in the ADISC exchange
- * @fp: ADISC request frame
- *
- * Locking Note: The lport lock is expected to be held before calling
- * this function.
- */
-static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp,
-				    struct fc_lport *lport)
-{
-	struct fc_frame *fp;
-	struct fc_exch *ep = fc_seq_exch(sp);
-	struct fc_els_adisc *req, *rp;
-	struct fc_seq_els_data rjt_data;
-	size_t len;
-	u32 f_ctl;
-
-	FC_LPORT_DBG(lport, "Received ADISC request while in state %s\n",
-		     fc_lport_state(lport));
-
-	req = fc_frame_payload_get(in_fp, sizeof(*req));
-	if (!req) {
-		rjt_data.fp = NULL;
-		rjt_data.reason = ELS_RJT_LOGIC;
-		rjt_data.explan = ELS_EXPL_NONE;
-		lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
-	} else {
-		len = sizeof(*rp);
-		fp = fc_frame_alloc(lport, len);
-		if (fp) {
-			rp = fc_frame_payload_get(fp, len);
-			memset(rp, 0, len);
-			rp->adisc_cmd = ELS_LS_ACC;
-			rp->adisc_wwpn = htonll(lport->wwpn);
-			rp->adisc_wwnn = htonll(lport->wwnn);
-			hton24(rp->adisc_port_id,
-			       fc_host_port_id(lport->host));
-			sp = lport->tt.seq_start_next(sp);
-			f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ;
-			f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT;
-			fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
-				       FC_TYPE_ELS, f_ctl, 0);
-			lport->tt.seq_send(lport, sp, fp);
-		}
-	}
-	fc_frame_free(in_fp);
-}
-
-/**
  * fc_lport_recv_logo_req() - Handle received fabric LOGO request
  * @lport: Fibre Channel local port recieving the LOGO
  * @sp: current sequence in the LOGO exchange
@@ -849,9 +799,6 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
 		case ELS_RNID:
 			recv = fc_lport_recv_rnid_req;
 			break;
-		case ELS_ADISC:
-			recv = fc_lport_recv_adisc_req;
-			break;
 		}
 
 		recv(sp, fp, lport);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index c33e258..03ea674 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1012,6 +1012,50 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
 }
 
 /**
+ * fc_rport_recv_adisc_req() - Handle incoming Address Discovery (ADISC) Request
+ * @rdata: remote port private
+ * @sp: current sequence in the ADISC exchange
+ * @in_fp: ADISC request frame
+ *
+ * Locking Note:  Called with the lport and rport locks held.
+ */
+static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata,
+				    struct fc_seq *sp, struct fc_frame *in_fp)
+{
+	struct fc_lport *lport = rdata->local_port;
+	struct fc_frame *fp;
+	struct fc_exch *ep = fc_seq_exch(sp);
+	struct fc_els_adisc *adisc;
+	struct fc_seq_els_data rjt_data;
+	u32 f_ctl;
+
+	FC_RPORT_DBG(rdata, "Received ADISC request\n");
+
+	adisc = fc_frame_payload_get(in_fp, sizeof(*adisc));
+	if (!adisc) {
+		rjt_data.fp = NULL;
+		rjt_data.reason = ELS_RJT_PROT;
+		rjt_data.explan = ELS_EXPL_INV_LEN;
+		lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
+		goto drop;
+	}
+
+	fp = fc_frame_alloc(lport, sizeof(*adisc));
+	if (!fp)
+		goto drop;
+	fc_adisc_fill(lport, fp);
+	adisc = fc_frame_payload_get(fp, sizeof(*adisc));
+	adisc->adisc_cmd = ELS_LS_ACC;
+	sp = lport->tt.seq_start_next(sp);
+	f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT;
+	fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
+		       FC_TYPE_ELS, f_ctl, 0);
+	lport->tt.seq_send(lport, sp, fp);
+drop:
+	fc_frame_free(in_fp);
+}
+
+/**
  * fc_rport_recv_els_req() - handle a validated ELS request.
  * @lport: Fibre Channel local port
  * @sp: current sequence in the PLOGI exchange
@@ -1062,6 +1106,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport,
 	case ELS_PRLO:
 		fc_rport_recv_prlo_req(rdata, sp, fp);
 		break;
+	case ELS_ADISC:
+		fc_rport_recv_adisc_req(rdata, sp, fp);
+		break;
 	case ELS_RRQ:
 		els_data.fp = fp;
 		lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data);
@@ -1111,6 +1158,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
 		break;
 	case ELS_PRLI:
 	case ELS_PRLO:
+	case ELS_ADISC:
 	case ELS_RRQ:
 	case ELS_REC:
 		fc_rport_recv_els_req(lport, sp, fp);


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 62/64] libfc: send GPN_ID in reaction to single-port RSCNs.
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (60 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 61/64] libfc: fix handling of incoming Discover Address (ADISC) requests Robert Love
@ 2009-08-25 21:03 ` Robert Love
  2009-08-25 21:04 ` [PATCH 63/64] libfc: don't swap OX_ID and RX_ID when sending BA_RJT Robert Love
  2009-08-25 21:04 ` [PATCH 64/64] fcoe: flush per-cpu thread work when destroying interface Robert Love
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:03 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

When an RSCN indicates changes to individual remote ports,
don't blindly log them out and then back in.  Instead, determine
whether they're still in the directory, by doing GPN_ID.

If that is successful, call login, which will send ADISC and reverify,
otherwise, call logoff.  Perhaps we should just delete the rport,
not send LOGO, but it seems safer.

Also, fix a possible issue where if a mix of records in the RSCN
cause us to queue disc_ports for disc_single and then we decide
to do full rediscovery, we leak memory for those disc_ports queued.

So, go through the list of disc_ports even if doing full discovery.
Free the disc_ports in any case.  If any of the disc_single() calls
return error, do a full discovery.

The ability to fill in GPN_ID requests was added to fc_ct_fill().
For this, it needs the FC_ID to be passed in as an arg.
The did parameter for fc_elsct_send() is used for that, since the
actual D_DID will always be 0xfffffc for all CT requests so far.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_disc.c  |  137 ++++++++++++++++++++++++++++++++++-------
 drivers/scsi/libfc/fc_elsct.c |    2 -
 include/scsi/fc_encode.h      |   16 ++++-
 3 files changed, 128 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 4242894..c48799e 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -47,7 +47,7 @@ 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 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 int fc_disc_single(struct fc_lport *, struct fc_disc_port *);
 static void fc_disc_restart(struct fc_disc *);
 
 /**
@@ -83,7 +83,6 @@ 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_priv *rdata;
 	struct fc_els_rscn *rp;
 	struct fc_els_rscn_page *pp;
 	struct fc_seq_els_data rjt_data;
@@ -150,6 +149,19 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
 		}
 	}
 	lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
+
+	/*
+	 * If not doing a complete rediscovery, do GPN_ID on
+	 * the individual ports mentioned in the list.
+	 * If any of these get an error, do a full rediscovery.
+	 * In any case, go through the list and free the entries.
+	 */
+	list_for_each_entry_safe(dp, next, &disc_ports, peers) {
+		list_del(&dp->peers);
+		if (!redisc)
+			redisc = fc_disc_single(lport, dp);
+		kfree(dp);
+	}
 	if (redisc) {
 		FC_DISC_DBG(disc, "RSCN received: rediscovering\n");
 		fc_disc_restart(disc);
@@ -157,14 +169,6 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
 		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);
-			rdata = lport->tt.rport_lookup(lport, dp->port_id);
-			if (rdata) {
-				lport->tt.rport_logoff(rdata);
-			}
-			fc_disc_single(disc, dp);
-		}
 	}
 	fc_frame_free(fp);
 	return;
@@ -562,32 +566,117 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
 }
 
 /**
- * fc_disc_single() - Discover the directory information for a single target
- * @lport: FC local port
- * @dp: The port to rediscover
+ * fc_disc_gpn_id_resp() - Handle a response frame from Get Port Names (GPN_ID)
+ * @sp: exchange sequence
+ * @fp: response frame
+ * @rdata_arg: remote port private data
  *
- * Locking Note: This function expects that the disc_mutex is locked
- *		 before it is called.
+ * Locking Note: This function is called without disc mutex held.
  */
-static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
+static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
+				void *rdata_arg)
 {
+	struct fc_rport_priv *rdata = rdata_arg;
+	struct fc_rport_priv *new_rdata;
 	struct fc_lport *lport;
-	struct fc_rport_priv *rdata;
+	struct fc_disc *disc;
+	struct fc_ct_hdr *cp;
+	struct fc_ns_gid_pn *pn;
+	u64 port_name;
 
-	lport = disc->lport;
+	lport = rdata->local_port;
+	disc = &lport->disc;
 
-	if (dp->port_id == fc_host_port_id(lport->host))
+	mutex_lock(&disc->disc_mutex);
+	if (PTR_ERR(fp) == -FC_EX_CLOSED)
 		goto out;
+	if (IS_ERR(fp))
+		goto redisc;
+
+	cp = fc_frame_payload_get(fp, sizeof(*cp));
+	if (!cp)
+		goto redisc;
+	if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
+		if (fr_len(fp) < sizeof(struct fc_frame_header) +
+		    sizeof(*cp) + sizeof(*pn))
+			goto redisc;
+		pn = (struct fc_ns_gid_pn *)(cp + 1);
+		port_name = get_unaligned_be64(&pn->fn_wwpn);
+		if (rdata->ids.port_name == -1)
+			rdata->ids.port_name = port_name;
+		else if (rdata->ids.port_name != port_name) {
+			FC_DISC_DBG(disc, "GPN_ID accepted.  WWPN changed. "
+				    "Port-id %x wwpn %llx\n",
+				    rdata->ids.port_id, port_name);
+			lport->tt.rport_logoff(rdata);
 
-	rdata = lport->tt.rport_create(lport, dp->port_id);
-	if (rdata) {
+			new_rdata = lport->tt.rport_create(lport,
+							   rdata->ids.port_id);
+			if (new_rdata) {
+				new_rdata->disc_id = disc->disc_id;
+				lport->tt.rport_login(new_rdata);
+			}
+			goto out;
+		}
 		rdata->disc_id = disc->disc_id;
-		kfree(dp);
 		lport->tt.rport_login(rdata);
+	} else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
+		FC_DISC_DBG(disc, "GPN_ID rejected reason %x exp %x\n",
+			    cp->ct_reason, cp->ct_explan);
+		lport->tt.rport_logoff(rdata);
+	} else {
+		FC_DISC_DBG(disc, "GPN_ID unexpected response code %x\n",
+			    ntohs(cp->ct_cmd));
+redisc:
+		fc_disc_restart(disc);
 	}
-	return;
 out:
-	kfree(dp);
+	mutex_unlock(&disc->disc_mutex);
+	kref_put(&rdata->kref, lport->tt.rport_destroy);
+}
+
+/**
+ * fc_disc_gpn_id_req() - Send Get Port Names by ID (GPN_ID) request
+ * @lport: local port
+ * @rdata: remote port private data
+ *
+ * Locking Note: This function expects that the disc_mutex is locked
+ *		 before it is called.
+ * On failure, an error code is returned.
+ */
+static int fc_disc_gpn_id_req(struct fc_lport *lport,
+			      struct fc_rport_priv *rdata)
+{
+	struct fc_frame *fp;
+
+	fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
+			    sizeof(struct fc_ns_fid));
+	if (!fp)
+		return -ENOMEM;
+	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, FC_NS_GPN_ID,
+				 fc_disc_gpn_id_resp, rdata, lport->e_d_tov))
+		return -ENOMEM;
+	kref_get(&rdata->kref);
+	return 0;
+}
+
+/**
+ * fc_disc_single() - Discover the directory information for a single target
+ * @lport: local port
+ * @dp: The port to rediscover
+ *
+ * Locking Note: This function expects that the disc_mutex is locked
+ *		 before it is called.
+ */
+static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp)
+{
+	struct fc_rport_priv *rdata;
+
+	rdata = lport->tt.rport_create(lport, dp->port_id);
+	if (!rdata)
+		return -ENOMEM;
+	rdata->disc_id = 0;
+	return fc_disc_gpn_id_req(lport, rdata);
 }
 
 /**
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index d655924..5cfa687 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -49,7 +49,7 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport,
 		rc = fc_els_fill(lport, did, fp, op, &r_ctl, &fh_type);
 	else {
 		/* CT requests */
-		rc = fc_ct_fill(lport, fp, op, &r_ctl, &fh_type);
+		rc = fc_ct_fill(lport, did, fp, op, &r_ctl, &fh_type);
 		did = FC_FID_DIR_SERV;
 	}
 
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index c5ee6bb..27dad70 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -32,6 +32,7 @@ struct fc_ct_req {
 		struct fc_ns_gid_ft gid;
 		struct fc_ns_rn_id  rn;
 		struct fc_ns_rft rft;
+		struct fc_ns_fid fid;
 	} payload;
 };
 
@@ -94,10 +95,16 @@ static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp,
 }
 
 /**
- * fc_ct_fill - Fill in a name service request frame
+ * fc_ct_fill() - Fill in a name service request frame
+ * @lport: local port.
+ * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
+ * @fp: frame to contain payload.
+ * @op: CT opcode.
+ * @r_ctl: pointer to FC header R_CTL.
+ * @fh_type: pointer to FC-4 type.
  */
 static inline int fc_ct_fill(struct fc_lport *lport,
-		      struct fc_frame *fp,
+		      u32 fc_id, struct fc_frame *fp,
 		      unsigned int op, enum fc_rctl *r_ctl,
 		      enum fc_fh_type *fh_type)
 {
@@ -109,6 +116,11 @@ static inline int fc_ct_fill(struct fc_lport *lport,
 		ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
 		break;
 
+	case FC_NS_GPN_ID:
+		ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid));
+		hton24(ct->payload.fid.fp_fid, fc_id);
+		break;
+
 	case FC_NS_RFT_ID:
 		ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft));
 		hton24(ct->payload.rft.fid.fp_fid,


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 63/64] libfc: don't swap OX_ID and RX_ID when sending BA_RJT
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (61 preceding siblings ...)
  2009-08-25 21:03 ` [PATCH 62/64] libfc: send GPN_ID in reaction to single-port RSCNs Robert Love
@ 2009-08-25 21:04 ` Robert Love
  2009-08-25 21:04 ` [PATCH 64/64] fcoe: flush per-cpu thread work when destroying interface Robert Love
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:04 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

I saw an lport debug message from the exchange manager saying:
"lport  70500: Received response for out of range oxid:ffff"

A trace showed this was a BA_RJT sent due to an incoming ABTS
which arrived on an unknown exchange.  So, the sender of the
BA_RJT was in error, but in this case, both the initiator and
responder were the same machine.

The OX_ID and RX_ID should not have been reversed in this case.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/libfc/fc_exch.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index b51db15..c1c1574 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1017,8 +1017,8 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
 	 */
 	memcpy(fh->fh_s_id, rx_fh->fh_d_id, 3);
 	memcpy(fh->fh_d_id, rx_fh->fh_s_id, 3);
-	fh->fh_ox_id = rx_fh->fh_rx_id;
-	fh->fh_rx_id = rx_fh->fh_ox_id;
+	fh->fh_ox_id = rx_fh->fh_ox_id;
+	fh->fh_rx_id = rx_fh->fh_rx_id;
 	fh->fh_seq_cnt = rx_fh->fh_seq_cnt;
 	fh->fh_r_ctl = FC_RCTL_BA_RJT;
 	fh->fh_type = FC_TYPE_BLS;


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 64/64] fcoe: flush per-cpu thread work when destroying interface
  2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
                   ` (62 preceding siblings ...)
  2009-08-25 21:04 ` [PATCH 63/64] libfc: don't swap OX_ID and RX_ID when sending BA_RJT Robert Love
@ 2009-08-25 21:04 ` Robert Love
  63 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-25 21:04 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love

From: Joe Eykholt <jeykholt@cisco.com>

This fixes one cause of an occational problem when unloading
libfc where the exchange manager pool doesn't have all items freed.

The existing WARN_ON(mp->total_exches <= 0) isn't hit.
However, note that total_exches is decremented when the
exchange is completed, and it can be held with a refcnt
for a while after that.

I'm not sure what the offending exchange is, but I suspect
it is an incoming request, because outgoing state machines
should be all stopped at this point.

Note that although receive is stopped before the exchange
manager is freed, there could still be active threads
handling received frames.

This patch flushes the queues by allocating a new skb
and sending it through, and have the thread handle
this new skb specially.  This is similar to the way the work
queues are flushed now by putting work items in them and waiting
until they make it through the queue.

An skb->destructor function is used to inform us of
the completion of the flush, and the fr_dev() is left
NULL to indicate to fcoe_percpu_receive_thread() that
the skb should be just freed.  There's already a check
for the lp being NULL which prints a message.
We skip printing the message if the destructor is for flushing.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c |   42 ++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index ac481ad..704b8e0 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -57,6 +57,9 @@ MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for "	\
 
 DEFINE_MUTEX(fcoe_config_mutex);
 
+/* fcoe_percpu_clean completion.  Waiter protected by fcoe_create_mutex */
+static DECLARE_COMPLETION(fcoe_flush_completion);
+
 /* fcoe host list */
 /* must only by accessed under the RTNL mutex */
 LIST_HEAD(fcoe_hostlist);
@@ -827,7 +830,7 @@ static void fcoe_percpu_thread_create(unsigned int cpu)
 	thread = kthread_create(fcoe_percpu_receive_thread,
 				(void *)p, "fcoethread/%d", cpu);
 
-	if (likely(!IS_ERR(p->thread))) {
+	if (likely(!IS_ERR(thread))) {
 		kthread_bind(thread, cpu);
 		wake_up_process(thread);
 
@@ -1300,6 +1303,15 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
 }
 
 /**
+ * fcoe_percpu_flush_done() - Indicate percpu queue flush completion.
+ * @skb: the skb being completed.
+ */
+static void fcoe_percpu_flush_done(struct sk_buff *skb)
+{
+	complete(&fcoe_flush_completion);
+}
+
+/**
  * fcoe_percpu_receive_thread() - recv thread per cpu
  * @arg: ptr to the fcoe per cpu struct
  *
@@ -1338,7 +1350,8 @@ int fcoe_percpu_receive_thread(void *arg)
 		fr = fcoe_dev_from_skb(skb);
 		lp = fr->fr_dev;
 		if (unlikely(lp == NULL)) {
-			FCOE_NETDEV_DBG(skb->dev, "Invalid HBA Structure");
+			if (skb->destructor != fcoe_percpu_flush_done)
+				FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb");
 			kfree_skb(skb);
 			continue;
 		}
@@ -1799,6 +1812,13 @@ int fcoe_link_ok(struct fc_lport *lp)
 /**
  * fcoe_percpu_clean() - Clear the pending skbs for an lport
  * @lp: the fc_lport
+ *
+ * Must be called with fcoe_create_mutex held to single-thread completion.
+ *
+ * This flushes the pending skbs by adding a new skb to each queue and
+ * waiting until they are all freed.  This assures us that not only are
+ * there no packets that will be handled by the lport, but also that any
+ * threads already handling packet have returned.
  */
 void fcoe_percpu_clean(struct fc_lport *lp)
 {
@@ -1823,7 +1843,25 @@ void fcoe_percpu_clean(struct fc_lport *lp)
 				kfree_skb(skb);
 			}
 		}
+
+		if (!pp->thread || !cpu_online(cpu)) {
+			spin_unlock_bh(&pp->fcoe_rx_list.lock);
+			continue;
+		}
+
+		skb = dev_alloc_skb(0);
+		if (!skb) {
+			spin_unlock_bh(&pp->fcoe_rx_list.lock);
+			continue;
+		}
+		skb->destructor = fcoe_percpu_flush_done;
+
+		__skb_queue_tail(&pp->fcoe_rx_list, skb);
+		if (pp->fcoe_rx_list.qlen == 1)
+			wake_up_process(pp->thread);
 		spin_unlock_bh(&pp->fcoe_rx_list.lock);
+
+		wait_for_completion(&fcoe_flush_completion);
 	}
 }
 


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* Re: [PATCH 06/64] libfc: Export FC headers
  2009-08-25 20:58 ` [PATCH 06/64] libfc: Export FC headers Robert Love
@ 2009-08-27 10:27   ` Christof Schmitt
  2009-08-27 17:42     ` Robert Love
  0 siblings, 1 reply; 69+ messages in thread
From: Christof Schmitt @ 2009-08-27 10:27 UTC (permalink / raw)
  To: Robert Love; +Cc: James.Bottomley, linux-scsi

On Tue, Aug 25, 2009 at 01:58:58PM -0700, Robert Love wrote:
> Export fc_els.h, fc_fs.h, fc_gs.h and fc_ns.h so that they
> may be used by applications.
> 
> This will be needed for FC Passthrough applications like fcping,
> but could be used by other applications.

Are there already plans to implement tools like fcping? I have heard
people thinking about the idea, but i am not aware of a project
working on this.

--
Christof Schmitt

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 06/64] libfc: Export FC headers
  2009-08-27 10:27   ` Christof Schmitt
@ 2009-08-27 17:42     ` Robert Love
  2009-08-28  8:32       ` Swen Schillig
  0 siblings, 1 reply; 69+ messages in thread
From: Robert Love @ 2009-08-27 17:42 UTC (permalink / raw)
  To: Christof Schmitt; +Cc: James.Bottomley, linux-scsi

On Thu, 2009-08-27 at 03:27 -0700, Christof Schmitt wrote:
> On Tue, Aug 25, 2009 at 01:58:58PM -0700, Robert Love wrote:
> > Export fc_els.h, fc_fs.h, fc_gs.h and fc_ns.h so that they
> > may be used by applications.
> > 
> > This will be needed for FC Passthrough applications like fcping,
> > but could be used by other applications.
> 
> Are there already plans to implement tools like fcping? I have heard
> people thinking about the idea, but i am not aware of a project
> working on this.
> 
Yeah, we have an implementation in our fcoe-utils package. You can
download that package here- git://open-fcoe.org/openfc/fcoe-utils.git.

//Rob


^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 06/64] libfc: Export FC headers
  2009-08-27 17:42     ` Robert Love
@ 2009-08-28  8:32       ` Swen Schillig
  2009-08-28 16:58         ` Robert Love
  0 siblings, 1 reply; 69+ messages in thread
From: Swen Schillig @ 2009-08-28  8:32 UTC (permalink / raw)
  To: Robert Love; +Cc: Christof Schmitt, James.Bottomley, linux-scsi

On Thu, 2009-08-27 at 10:42 -0700, Robert Love wrote:
> On Thu, 2009-08-27 at 03:27 -0700, Christof Schmitt wrote:
> > On Tue, Aug 25, 2009 at 01:58:58PM -0700, Robert Love wrote:
> > > Export fc_els.h, fc_fs.h, fc_gs.h and fc_ns.h so that they
> > > may be used by applications.
> > > 
> > > This will be needed for FC Passthrough applications like fcping,
> > > but could be used by other applications.
> > 
> > Are there already plans to implement tools like fcping? I have heard
> > people thinking about the idea, but i am not aware of a project
> > working on this.
> > 
> Yeah, we have an implementation in our fcoe-utils package. You can
> download that package here- git://open-fcoe.org/openfc/fcoe-utils.git.
> 
> //Rob
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Hi Rob

Are there any plans to extend your fcoe-utils package with some more
tools or functionality ?
Maybe something like fctrace, ...

If so, would you be interested in code contributions in this area ?
Not sure about legal so far, but will see.

Cheers Swen


^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 06/64] libfc: Export FC headers
  2009-08-28  8:32       ` Swen Schillig
@ 2009-08-28 16:58         ` Robert Love
  0 siblings, 0 replies; 69+ messages in thread
From: Robert Love @ 2009-08-28 16:58 UTC (permalink / raw)
  To: swen; +Cc: Christof Schmitt, James.Bottomley, linux-scsi, ; christopher.leech

On Fri, 2009-08-28 at 01:32 -0700, Swen Schillig wrote:
> On Thu, 2009-08-27 at 10:42 -0700, Robert Love wrote:
> > On Thu, 2009-08-27 at 03:27 -0700, Christof Schmitt wrote:
> > > On Tue, Aug 25, 2009 at 01:58:58PM -0700, Robert Love wrote:
> > > > Export fc_els.h, fc_fs.h, fc_gs.h and fc_ns.h so that they
> > > > may be used by applications.
> > > > 
> > > > This will be needed for FC Passthrough applications like fcping,
> > > > but could be used by other applications.
> > > 
> > > Are there already plans to implement tools like fcping? I have heard
> > > people thinking about the idea, but i am not aware of a project
> > > working on this.
> > > 
> > Yeah, we have an implementation in our fcoe-utils package. You can
> > download that package here- git://open-fcoe.org/openfc/fcoe-utils.git.
> > 
> > //Rob
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> Hi Rob
> 
> Are there any plans to extend your fcoe-utils package with some more
> tools or functionality ?
> Maybe something like fctrace, ...
> 
There aren't any specific plans for new user space tools at the moment.
Most of our time is being spent on adding functionality to libfc,
libfcoe and fcoe. We're also making some improvements to the other tools
in fcoe-utils that you might not care about as much. fcoeadm (interacts
with fcoe.ko) and fcoemon (DCB monitoring ans fcoe system service
daemon) are the primary applications in that package.

Regarding other applications- Chris Leech is working on patches to add
more registration commands (to the directory server) to libfc and to
test those changes he has a modified fcping to do directory server
queries, using FC passthrough. We'll probably check that tool in too.

> If so, would you be interested in code contributions in this area ?
> Not sure about legal so far, but will see.
> 
I would definitely be interested contributions. fctrace would be great.
Also, if you want to patch fcping or another application so that it
works with ZFCP I'd be glad to accept those patches too.

//Rob


^ permalink raw reply	[flat|nested] 69+ messages in thread

end of thread, other threads:[~2009-08-28 16:58 UTC | newest]

Thread overview: 69+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
2009-08-25 20:58 ` [PATCH 01/64] fcoe: Add format spacing to FCOE_NETDEV_DBG debug macro Robert Love
2009-08-25 20:58 ` [PATCH 02/64] libfc: Fix misleading debug statement Robert Love
2009-08-25 20:58 ` [PATCH 03/64] fcoe: libfcoe: extra semicolon in CHECK_LOGGING macros causes compile error Robert Love
2009-08-25 20:58 ` [PATCH 04/64] fcoe, libfc: adds per cpu exch pool within exchange manager(EM) Robert Love
2009-08-25 20:58 ` [PATCH 05/64] fcoe, libfc: fully makes use of per cpu exch pool and then removes em_lock Robert Love
2009-08-25 20:58 ` [PATCH 06/64] libfc: Export FC headers Robert Love
2009-08-27 10:27   ` Christof Schmitt
2009-08-27 17:42     ` Robert Love
2009-08-28  8:32       ` Swen Schillig
2009-08-28 16:58         ` Robert Love
2009-08-25 20:59 ` [PATCH 07/64] fcoe: Add sysfs parameter to fcoe for minimum DDP read I/O size Robert Love
2009-08-25 20:59 ` [PATCH 08/64] libfcoe: fcoe_ctlr_destroy use cancel_work_sync instead of flush_work Robert Love
2009-08-25 20:59 ` [PATCH 09/64] fcoe: fix missing error check in call to fcoe_if_init Robert Love
2009-08-25 20:59 ` [PATCH 10/64] fcoe: remove unnecessary list and lock initializations Robert Love
2009-08-25 20:59 ` [PATCH 11/64] fcoe: interface changes to fcoe_if_create and fcoe_if_destroy Robert Love
2009-08-25 20:59 ` [PATCH 12/64] fcoe: Introduce and allocate fcoe_interface structure, 1:1 with net_device Robert Love
2009-08-25 20:59 ` [PATCH 13/64] fcoe: move netdev to fcoe_interface Robert Love
2009-08-25 20:59 ` [PATCH 14/64] fcoe: move packet handlers from fcoe_port " Robert Love
2009-08-25 20:59 ` [PATCH 15/64] fcoe: move FIP controller " Robert Love
2009-08-25 20:59 ` [PATCH 16/64] fcoe: move offload exchange manager pointer " Robert Love
2009-08-25 20:59 ` [PATCH 17/64] fcoe: remove fcoe_interface->priv pointer Robert Love
2009-08-25 21:00 ` [PATCH 18/64] fcoe: fcoe_interface create, destroy and refcounting Robert Love
2009-08-25 21:00 ` [PATCH 19/64] fcoe: split out per interface setup Robert Love
2009-08-25 21:00 ` [PATCH 20/64] fcoe: add mutex to protect create and destroy Robert Love
2009-08-25 21:00 ` [PATCH 21/64] fcoe: move the host-list add/remove to keep out VN_Ports Robert Love
2009-08-25 21:00 ` [PATCH 22/64] fcoe: Fix module ref count bug by adding NETDEV UNREGISTER handling Robert Love
2009-08-25 21:00 ` [PATCH 23/64] fcoe: use rtnl mutex in place of hostlist lock Robert Love
2009-08-25 21:00 ` [PATCH 24/64] libfc: prepare to split off struct fc_rport_priv from fc_rport_libfc_priv Robert Love
2009-08-25 21:00 ` [PATCH 25/64] libfc: change interface for rport_create Robert Love
2009-08-25 21:00 ` [PATCH 26/64] libfc: fix RPORT_TO_PRIV and PRIV_TO_RPORT() macros Robert Love
2009-08-25 21:00 ` [PATCH 27/64] libfc: make fc_rport_priv the primary rport interface Robert Love
2009-08-25 21:00 ` [PATCH 28/64] libfc: change elsct to use FC_ID instead of rdata Robert Love
2009-08-25 21:01 ` [PATCH 29/64] libfc: make rport structure optional Robert Love
2009-08-25 21:01 ` [PATCH 30/64] libfc: rearrange code in fc_rport_work Robert Love
2009-08-25 21:01 ` [PATCH 31/64] libfc: rename rport event CREATED to READY Robert Love
2009-08-25 21:01 ` [PATCH 32/64] libfc: don't create dummy (rogue) remote ports Robert Love
2009-08-25 21:01 ` [PATCH 33/64] libfc: fix rport event race between READY and LOGO Robert Love
2009-08-25 21:01 ` [PATCH 34/64] libfc: eliminate disc->event Robert Love
2009-08-25 21:01 ` [PATCH 35/64] libfc: remove unused disc->delay element Robert Love
2009-08-25 21:01 ` [PATCH 36/64] libfc: rport debug messages were printing pointer values Robert Love
2009-08-25 21:01 ` [PATCH 37/64] libfc: simplify fc_lport_rport_callback Robert Love
2009-08-25 21:01 ` [PATCH 38/64] libfc: make rport module maintain the rport list Robert Love
2009-08-25 21:01 ` [PATCH 39/64] libfc: have rport_create do a lookup for pre-existing rports first Robert Love
2009-08-25 21:02 ` [PATCH 40/64] libfc: change to make remote port callback optional Robert Love
2009-08-25 21:02 ` [PATCH 41/64] libfc: move rport_lookup into fc_rport.c Robert Love
2009-08-25 21:02 ` [PATCH 42/64] libfc: do not log off rports before or after discovery Robert Love
2009-08-25 21:02 ` [PATCH 43/64] libfc: discovery restart sequence error fix Robert Love
2009-08-25 21:02 ` [PATCH 44/64] libfc: rearrange code in fc_disc_gpn_ft_resp() Robert Love
2009-08-25 21:02 ` [PATCH 45/64] libfc: handle discovery failure more correctly Robert Love
2009-08-25 21:02 ` [PATCH 46/64] libfc: fix: empty zone causes endless discovery retries Robert Love
2009-08-25 21:02 ` [PATCH 47/64] libfc: discovery retry should clear pending first Robert Love
2009-08-25 21:02 ` [PATCH 48/64] libfc: discovery gpn_ft parse bug Robert Love
2009-08-25 21:02 ` [PATCH 49/64] libfc: clean up point-to-point discovery code Robert Love
2009-08-25 21:02 ` [PATCH 50/64] libfc: don't do discovery before callback is set Robert Love
2009-08-25 21:02 ` [PATCH 51/64] libfc: Initialize fc_rport_identifiers inside fc_rport_create Robert Love
2009-08-25 21:03 ` [PATCH 52/64] libfc: Always reset remote port roles when receiving PRLI Robert Love
2009-08-25 21:03 ` [PATCH 53/64] libfc: move remote port lookup for ELS requests into fc_rport.c Robert Love
2009-08-25 21:03 ` [PATCH 54/64] libfc: fix: rport_recv_req needs disc_mutex when calling rport_lookup Robert Love
2009-08-25 21:03 ` [PATCH 55/64] libfc: improve debug messages for ELS response handlers Robert Love
2009-08-25 21:03 ` [PATCH 56/64] libfc: correctly handle incoming PLOGI request Robert Love
2009-08-25 21:03 ` [PATCH 57/64] libfc: fix rport error handling for login-required and invalid ops Robert Love
2009-08-25 21:03 ` [PATCH 58/64] libfc: re-login to remote ports that send us LOGO Robert Love
2009-08-25 21:03 ` [PATCH 59/64] libfc: LOGO response code had extraeous enter_rtv Robert Love
2009-08-25 21:03 ` [PATCH 60/64] libfc: use ADISC to verify rport login state Robert Love
2009-08-25 21:03 ` [PATCH 61/64] libfc: fix handling of incoming Discover Address (ADISC) requests Robert Love
2009-08-25 21:03 ` [PATCH 62/64] libfc: send GPN_ID in reaction to single-port RSCNs Robert Love
2009-08-25 21:04 ` [PATCH 63/64] libfc: don't swap OX_ID and RX_ID when sending BA_RJT Robert Love
2009-08-25 21:04 ` [PATCH 64/64] fcoe: flush per-cpu thread work when destroying interface Robert Love

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.