[Open-FCoE] [RFC PATCH 28/28] libfc: re-work lport locking using semaphores

Robert Love robert.w.love at intel.com
Thu Sep 11 23:37:37 UTC 2008


Action Functions (called without LP lock, locks, calls an _enter_ and unlocks)
 fc_lport_rport_event
 fc_fabric_login
 fc_linkup
 fc_linkdown
 fc_pause
 fc_unpause
 fc_fabric_logoff
 fc_lport_destroy
 fc_lport_timeout
        - needs to be called from a work thread

 fc_lport_recv
        - Calls one of the request handlers with the lock held
        - should it just call fc_lport_recv_req or call rport_recv?

Request Handlers (called without lock, will lock process and unlock)
 fc_lport_rlir_req
 fc_lport_echo_req
 fc_lport_rnid_req
 fc_lport_recv_logo_req
 fc_lport_recv_flogi_req

Response Handlers (called without lock, lock, call an _enter_ function and unlock)
 fc_lport_rpn_id_resp
 fc_lport_rft_id_resp
 fc_lport_scr_resp
 fc_lport_logo_resp
 fc_lport_flogi_resp

Enter Functions (called with lock held)
 fc_lport_enter_reset
 fc_lport_enter_flogi
 fc_lport_enter_scr
 fc_lport_enter_rft_id
 fc_lport_enter_rpn_id
 fc_lport_enter_dns
 fc_lport_enter_ready
 fc_lport_enter_logo

Helper Functions (need lock held)
 fc_lport_flogi_fill (mfs, wwnn, wwpn, tovs)
 fc_lport_set_fid
 fc_lport_add_fc4_type
 fc_set_mfs
 fc_lport_error
 - should start a work thread for fc_lport_timeout or call fc_lport_reject
 - rename fc_lport_enter_reject to fc_lport_reject

Helper Functions (don't need lock held)
 fc_frame_drop
 fc_lport_state
 fc_lport_ptp_setup
 fc_lport_ptp_clear
 fc_lport_dns_acc
 fc_lport_config
 fc_lport_init

Unknown
 fc_lport_enter_retry (likely to merge into fc_lport_error)
 fc_lport_retry (likely to merge into fc_lport_error)
 fc_lport_enter_reject
 fc_lport_flogi_send
        - Do we need a "send" function? Can't enter_flogi() do this?

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

 drivers/scsi/fcoe/fcoeinit.c  |    4 
 drivers/scsi/libfc/fc_lport.c |  674 +++++++++++++++++++++++++++--------------
 drivers/scsi/libfc/fc_ns.c    |   10 -
 include/scsi/libfc/libfc.h    |   33 --
 4 files changed, 449 insertions(+), 272 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoeinit.c b/drivers/scsi/fcoe/fcoeinit.c
index e069835..38dd8cc 100644
--- a/drivers/scsi/fcoe/fcoeinit.c
+++ b/drivers/scsi/fcoe/fcoeinit.c
@@ -53,8 +53,8 @@ struct scsi_transport_template *fcoe_transport_template;
 
 static int fcoe_reset(struct Scsi_Host *shost)
 {
-	struct fc_lport *lp = shost_priv(shost);
-	fc_lport_enter_reset(lp);
+	struct fc_lport *lport = shost_priv(shost);
+	fc_lport_reset(lport);
 	return 0;
 }
 
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 708332f..6f1e890 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -38,10 +38,11 @@ static int fc_lport_debug;
 
 static void fc_lport_error(struct fc_lport *, struct fc_frame *);
 
+static void fc_lport_enter_reset(struct fc_lport *);
 static void fc_lport_enter_flogi(struct fc_lport *);
 static void fc_lport_enter_dns(struct fc_lport *);
-static void fc_lport_enter_reg_pn(struct fc_lport *);
-static void fc_lport_enter_reg_ft(struct fc_lport *);
+static void fc_lport_enter_rpn_id(struct fc_lport *);
+static void fc_lport_enter_rft_id(struct fc_lport *);
 static void fc_lport_enter_scr(struct fc_lport *);
 static void fc_lport_enter_ready(struct fc_lport *);
 static void fc_lport_enter_logo(struct fc_lport *);
@@ -50,8 +51,8 @@ static const char *fc_lport_state_names[] = {
 	[LPORT_ST_NONE] =     "none",
 	[LPORT_ST_FLOGI] =    "FLOGI",
 	[LPORT_ST_DNS] =      "dNS",
-	[LPORT_ST_REG_PN] =   "REG_PN",
-	[LPORT_ST_REG_FT] =   "REG_FT",
+	[LPORT_ST_RPN_ID] =   "RPN_ID",
+	[LPORT_ST_RFT_ID] =   "RFT_ID",
 	[LPORT_ST_SCR] =      "SCR",
 	[LPORT_ST_READY] =    "Ready",
 	[LPORT_ST_LOGO] =     "LOGO",
@@ -67,23 +68,22 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)
 static void fc_lport_rport_event(struct fc_lport *lport, struct fc_rport *rport,
 				 enum fc_lport_event event)
 {
-	fc_lport_lock(lport);
+	mutex_lock(&lport->lp_mutex);
+
 	if (rport->port_id == FC_FID_DIR_SERV) {
 		switch (event) {
 		case LPORT_EV_RPORT_CREATED:
 			lport->dns_rp = rport;
-			fc_lport_enter_dns(lport);
+			fc_lport_enter_rpn_id(lport);
 			break;
 		case LPORT_EV_RPORT_LOGO:
 		case LPORT_EV_RPORT_FAILED:
 			lport->dns_rp = NULL;
-			fc_lport_lock(lport);
-			fc_lport_enter_reset(lport);
-			fc_lport_unlock(lport);
+			fc_lport_enter_dns(lport);
 			break;
 		}
 	}
-	fc_lport_unlock(lport);
+	mutex_unlock(&lport->lp_mutex);
 }
 
 static const char *fc_lport_state(struct fc_lport *lport)
@@ -111,11 +111,11 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
 	 * if we have to create a rport the fc class can sleep so we must
 	 * drop the lock here
 	 */
-	fc_lport_unlock(lport);
+
 	rport = lport->tt.rport_lookup(lport, ids.port_id); /* lookup and hold */
 	if (!rport)
 		rport = lport->tt.rport_create(lport, &ids); /* create and hold */
-	fc_lport_lock(lport);
+
 	if (rport) {
 		if (lport->ptp_rp)
 			fc_remote_port_delete(lport->ptp_rp);
@@ -147,26 +147,6 @@ void fc_get_host_port_state(struct Scsi_Host *shost)
 EXPORT_SYMBOL(fc_get_host_port_state);
 
 /*
- * Test for dNS accept in response payload.
- */
-static int fc_lport_dns_acc(struct fc_frame *fp)
-{
-	struct fc_frame_header *fh;
-	struct fc_ct_hdr *ct;
-	int rc = 0;
-
-	fh = fc_frame_header_get(fp);
-	ct = fc_frame_payload_get(fp, sizeof(*ct));
-	if (fh && ct && fh->fh_type == FC_TYPE_CT &&
-	    ct->ct_fs_type == FC_FST_DIR &&
-	    ct->ct_fs_subtype == FC_NS_SUBTYPE &&
-	    ntohs(ct->ct_cmd) == FC_FS_ACC) {
-		rc = 1;
-	}
-	return rc;
-}
-
-/*
  * Fill in FLOGI command for request.
  */
 static void
@@ -210,21 +190,37 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type)
 	*mp = htonl(ntohl(*mp) | 1UL << (type % FC_NS_BPW));
 }
 
-/*
- * Handle received RLIR - registered link incident report.
+/**
+ * fc_lport_recv_rlir_req - Handle received Registered Link Incident Report.
+ * @lport: Fibre Channel local port recieving the RLIR
+ * @sp: current sequence in the RLIR exchange
+ * @fp: RLIR request frame
+ *
+ * Locking Note: The lport lock is exected to be held before calling
+ * this function.
  */
-static void fc_lport_rlir_req(struct fc_seq *sp, struct fc_frame *fp,
-			      struct fc_lport *lport)
+static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp,
+				   struct fc_lport *lport)
 {
+	if (fc_lport_debug)
+		FC_DBG("Received RLIR request while in state %s\n",
+		       fc_lport_state(lport));
+
 	lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
 	fc_frame_free(fp);
 }
 
-/*
- * Handle received ECHO.
+/**
+ * fc_lport_recv_echo_req - Handle received ECHO request
+ * @lport: Fibre Channel local port recieving the ECHO
+ * @sp: current sequence in the ECHO exchange
+ * @fp: ECHO request frame
+ *
+ * Locking Note: The lport lock is exected to be held before calling
+ * this function.
  */
-static void fc_lport_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
-			      struct fc_lport *lport)
+static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
+				   struct fc_lport *lport)
 {
 	struct fc_frame *fp;
 	unsigned int len;
@@ -232,11 +228,16 @@ static void fc_lport_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
 	void *dp;
 	u32 f_ctl;
 
+	if (fc_lport_debug)
+		FC_DBG("Received RLIR request while in state %s\n",
+		       fc_lport_state(lport));
+
 	len = fr_len(in_fp) - sizeof(struct fc_frame_header);
 	pp = fc_frame_payload_get(in_fp, len);
 
 	if (len < sizeof(__be32))
 		len = sizeof(__be32);
+
 	fp = fc_frame_alloc(lport, len);
 	if (fp) {
 		dp = fc_frame_payload_get(fp, len);
@@ -250,11 +251,17 @@ static void fc_lport_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
 	fc_frame_free(in_fp);
 }
 
-/*
- * Handle received RNID.
+/**
+ * fc_lport_recv_echo_req - Handle received Request Node ID data request
+ * @lport: Fibre Channel local port recieving the RNID
+ * @sp: current sequence in the RNID exchange
+ * @fp: RNID request frame
+ *
+ * Locking Note: The lport lock is exected to be held before calling
+ * this function.
  */
-static void fc_lport_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
-			      struct fc_lport *lport)
+static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
+				   struct fc_lport *lport)
 {
 	struct fc_frame *fp;
 	struct fc_els_rnid *req;
@@ -268,6 +275,10 @@ static void fc_lport_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
 	size_t len;
 	u32 f_ctl;
 
+	if (fc_lport_debug)
+		FC_DBG("Received RNID 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;
@@ -305,31 +316,34 @@ static void fc_lport_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
 	fc_frame_free(in_fp);
 }
 
-/*
- * Handle received fabric logout request.
+/**
+ * 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
+ * @fp: LOGO request frame
+ *
+ * Locking Note: The lport lock is exected to be held before calling
+ * this function.
  */
 static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp,
-				   struct fc_lport *lp)
+				   struct fc_lport *lport)
 {
-	lp->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
-	fc_lport_enter_reset(lp);
+	lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
+	fc_lport_enter_reset(lport);
 	fc_frame_free(fp);
 }
 
-/*
- * Receive request frame
- */
-
 int fc_fabric_login(struct fc_lport *lport)
 {
 	int rc = -1;
 
+	mutex_lock(&lport->lp_mutex);
 	if (lport->state == LPORT_ST_NONE) {
-		fc_lport_lock(lport);
 		fc_lport_enter_reset(lport);
-		fc_lport_unlock(lport);
 		rc = 0;
 	}
+	mutex_unlock(&lport->lp_mutex);
+
 	return rc;
 }
 EXPORT_SYMBOL(fc_fabric_login);
@@ -340,55 +354,79 @@ EXPORT_SYMBOL(fc_fabric_login);
  **/
 void fc_linkup(struct fc_lport *lport)
 {
+	mutex_lock(&lport->lp_mutex);
 	if ((lport->link_status & FC_LINK_UP) != FC_LINK_UP) {
 		lport->link_status |= FC_LINK_UP;
-		fc_lport_lock(lport);
+		
 		if (lport->state == LPORT_ST_RESET)
 			fc_lport_enter_flogi(lport);
-		fc_lport_unlock(lport);
 	}
+	mutex_unlock(&lport->lp_mutex);
 }
 EXPORT_SYMBOL(fc_linkup);
 
 /**
  * fc_linkdown -  link down notification
- * @dev:      Pointer to fc_lport .
+ * @lport:        Pointer to fc_lport
  **/
 void fc_linkdown(struct fc_lport *lport)
 {
+	mutex_lock(&lport->lp_mutex);
+
 	if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) {
 		lport->link_status &= ~(FC_LINK_UP);
 		fc_lport_enter_reset(lport);
 		lport->tt.scsi_cleanup(lport);
 	}
+
+	mutex_unlock(&lport->lp_mutex);
 }
 EXPORT_SYMBOL(fc_linkdown);
 
+/**
+ * fc_pause -     Pause the flow of frames
+ * @lport:        Pointer to fc_lport
+ **/
 void fc_pause(struct fc_lport *lport)
 {
+	mutex_lock(&lport->lp_mutex);
 	lport->link_status |= FC_PAUSE;
+	mutex_unlock(&lport->lp_mutex);
 }
 EXPORT_SYMBOL(fc_pause);
 
+/**
+ * fc_unpause -   Unpause the flow of frames
+ * @lport:        Pointer to fc_lport
+ **/
 void fc_unpause(struct fc_lport *lport)
 {
+	mutex_lock(&lport->lp_mutex);
 	lport->link_status &= ~(FC_PAUSE);
+	mutex_unlock(&lport->lp_mutex);
 }
 EXPORT_SYMBOL(fc_unpause);
 
+/**
+ * fc_fabric_logoff - Logout of the fabric
+ * @lport:	      fc_lport pointer to logoff the fabric
+ *
+ * Return value:
+ *	0 for success, -1 for failure
+ **/
 int fc_fabric_logoff(struct fc_lport *lport)
 {
-	fc_lport_lock(lport);
+	mutex_lock(&lport->lp_mutex);
 	fc_lport_enter_logo(lport);
-	fc_lport_unlock(lport);
 	lport->tt.scsi_cleanup(lport);
+	mutex_unlock(&lport->lp_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(fc_fabric_logoff);
 
 /**
  * fc_lport_destroy - unregister a fc_lport
- * @lport:	   fc_lport pointer to unregister
+ * @lport:	      fc_lport pointer to unregister
  *
  * Return value:
  *	None
@@ -400,18 +438,12 @@ EXPORT_SYMBOL(fc_fabric_logoff);
  **/
 int fc_lport_destroy(struct fc_lport *lport)
 {
-	fc_lport_lock(lport);
-	fc_lport_state_enter(lport, LPORT_ST_LOGO);
-	fc_lport_unlock(lport);
-
+	mutex_lock(&lport->lp_mutex);
 	cancel_delayed_work_sync(&lport->ns_disc_work);
-
 	lport->tt.scsi_abort_io(lport);
-
 	lport->tt.frame_send = fc_frame_drop;
-
 	lport->tt.exch_mgr_reset(lport->emp, 0, 0);
-
+	mutex_unlock(&lport->lp_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(fc_lport_destroy);
@@ -421,6 +453,8 @@ int fc_set_mfs(struct fc_lport *lport, u32 mfs)
 	unsigned int old_mfs;
 	int rc = -1;
 
+	mutex_lock(&lport->lp_mutex);
+
 	old_mfs = lport->mfs;
 
 	if (mfs >= FC_MIN_MAX_FRAME) {
@@ -437,17 +471,29 @@ int fc_set_mfs(struct fc_lport *lport, u32 mfs)
 		lport->ns_disc_done = 0;
 		fc_lport_enter_reset(lport);
 	}
+
+	mutex_unlock(&lport->lp_mutex);
+
 	return rc;
 }
 EXPORT_SYMBOL(fc_set_mfs);
 
+/**
+ * fc_rport_enter_ready - Enter the ready state and start discovery
+ * @lport: Fibre Channel local port that is ready
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
+ */
 static void fc_lport_enter_ready(struct fc_lport *lport)
 {
 	if (fc_lport_debug)
 		FC_DBG("Port (%6x) entered Ready from state %s\n",
 		       lport->fid, fc_lport_state(lport));
-
+	
 	fc_lport_state_enter(lport, LPORT_ST_READY);
+
+	lport->tt.disc_start(lport);
 }
 
 /*
@@ -460,8 +506,8 @@ static void fc_lport_reject(struct fc_lport *lport)
 	case LPORT_ST_NONE:
 	case LPORT_ST_READY:
 	case LPORT_ST_RESET:
-	case LPORT_ST_REG_PN:
-	case LPORT_ST_REG_FT:
+	case LPORT_ST_RPN_ID:
+	case LPORT_ST_RFT_ID:
 	case LPORT_ST_SCR:
 	case LPORT_ST_DNS:
 	case LPORT_ST_FLOGI:
@@ -471,10 +517,18 @@ static void fc_lport_reject(struct fc_lport *lport)
 	}
 }
 
-/*
+/**
+ * fc_lport_recv_flogi_req - Handle received FLOGI request
+ * @lport: Fibre Channel local port recieving the FLOGI
+ * @sp: current sequence in the FLOGI exchange
+ * @fp: FLOGI request frame
+ *
  * A received FLOGI request indicates a point-to-point connection.
  * Accept it with the common service parameters indicating our N port.
  * Set up to do a PLOGI if we have the higher-number WWPN.
+ *
+ * Locking Note: The lport lock is exected to be held before calling
+ * this function.
  */
 static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
 				    struct fc_frame *rx_fp,
@@ -489,6 +543,10 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
 	u32 remote_fid;
 	u32 local_fid;
 	u32 f_ctl;
+	
+	if (fc_lport_debug)
+		FC_DBG("Received FLOGI request while in state %s\n",
+		       fc_lport_state(lport));
 
 	fh = fc_frame_header_get(rx_fp);
 	remote_fid = ntoh24(fh->fh_s_id);
@@ -502,7 +560,6 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
 		goto out;
 	}
 	FC_DBG("FLOGI from port WWPN %llx\n", remote_wwpn);
-	fc_lport_lock(lport);
 
 	/*
 	 * XXX what is the right thing to do for FIDs?
@@ -540,7 +597,7 @@ 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));
-	fc_lport_unlock(lport);
+
 	if (lport->tt.disc_start(lport))
 		FC_DBG("target discovery start error\n");
 out:
@@ -548,8 +605,8 @@ out:
 	fc_frame_free(rx_fp);
 }
 
-static void fc_lport_recv(struct fc_lport *lport, struct fc_seq *sp,
-			  struct fc_frame *fp)
+static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
+			      struct fc_frame *fp)
 {
 	struct fc_frame_header *fh = fc_frame_header_get(fp);
 	void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *);
@@ -558,6 +615,8 @@ static void fc_lport_recv(struct fc_lport *lport, struct fc_seq *sp,
 	u32 d_id;
 	struct fc_seq_els_data rjt_data;
 
+	mutex_lock(&lport->lp_mutex);
+
 	/*
 	 * Handle special ELS cases like FLOGI, LOGO, and
 	 * RSCN here.  These don't require a session.
@@ -581,13 +640,13 @@ static void fc_lport_recv(struct fc_lport *lport, struct fc_seq *sp,
 			recv = lport->tt.disc_recv_req;
 			break;
 		case ELS_ECHO:
-			recv = fc_lport_echo_req;
+			recv = fc_lport_recv_echo_req;
 			break;
 		case ELS_RLIR:
-			recv = fc_lport_rlir_req;
+			recv = fc_lport_recv_rlir_req;
 			break;
 		case ELS_RNID:
-			recv = fc_lport_rnid_req;
+			recv = fc_lport_recv_rnid_req;
 			break;
 		}
 
@@ -618,23 +677,32 @@ static void fc_lport_recv(struct fc_lport *lport, struct fc_seq *sp,
 		FC_DBG("dropping invalid frame (eof %x)\n", fr_eof(fp));
 		fc_frame_free(fp);
 	}
+	mutex_unlock(&lport->lp_mutex);
+}
 
-	/*
-	 *  The common exch_done for all request may not be good
-	 *  if any request requires longer hold on exhange. XXX
-	 */
-	lport->tt.exch_done(sp);
+int fc_lport_reset(struct fc_lport *lport)
+{
+	mutex_lock(&lport->lp_mutex);
+	fc_lport_enter_reset(lport);
+	mutex_unlock(&lport->lp_mutex);
+	return 0;
 }
+EXPORT_SYMBOL(fc_lport_reset);
 
-/*
- * Put the local port back into the initial state.  Reset all sessions.
- * This is called after a SCSI reset or the driver is unloading
- * or the program is exiting.
+/**
+ * fc_rport_enter_reset - Reset the local port
+ * @lport: Fibre Channel local port to be reset
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
  */
-int fc_lport_enter_reset(struct fc_lport *lport)
+static void fc_lport_enter_reset(struct fc_lport *lport)
 {
 	if (fc_lport_debug)
-		FC_DBG("Processing RESET state\n");
+		FC_DBG("Port (%6x) entered RESET state from %s state\n",
+		       lport->fid, fc_lport_state(lport));
+
+	fc_lport_state_enter(lport, LPORT_ST_RESET);
 
 	if (lport->dns_rp) {
 		fc_remote_port_delete(lport->dns_rp);
@@ -643,23 +711,13 @@ int fc_lport_enter_reset(struct fc_lport *lport)
 	fc_lport_ptp_clear(lport);
 
 	lport->tt.rport_reset_list(lport);
-
-	/*
-	 * Setting state RESET keeps fc_lport_error() callbacks
-	 * by exch_mgr_reset() from recursing on the lock.
-	 * It also causes fc_lport_sess_event() to ignore events.
-	 * The lock is held for the duration of the time in RESET state.
-	 */
-	fc_lport_state_enter(lport, LPORT_ST_RESET);
 	lport->tt.exch_mgr_reset(lport->emp, 0, 0);
 
 	lport->fid = 0;
 
 	if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP)
 		fc_lport_enter_flogi(lport);
-	return 0;
 }
-EXPORT_SYMBOL(fc_lport_enter_reset);
 
 /**
  * fc_lport_error - Handler for any errors
@@ -691,60 +749,141 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
 		fc_lport_reject(lport);
 }
 
-/*
- * Handle response from name server.
+/**
+ * fc_lport_rft_id_resp - Handle response to Register Fibre
+ *                        Channel Types by ID (RPN_ID) request
+ * @sp: current sequence in RPN_ID exchange
+ * @fp: response frame
+ * @lp_arg: Fibre Channel host port instance
  */
-static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp,
-			     void *lp_arg)
+static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
+				 void *lp_arg)
 {
 	struct fc_lport *lport = lp_arg;
+	struct fc_frame_header *fh;
+	struct fc_ct_hdr *ct;
 
-	if (!IS_ERR(fp)) {
-		fc_lport_lock(lport);
-		cancel_delayed_work_sync(&lport->retry_work);
-		if (fc_lport_dns_acc(fp)) {
-			if (lport->state == LPORT_ST_REG_PN)
-				fc_lport_enter_reg_ft(lport);
-			else
-				fc_lport_enter_scr(lport);
+	mutex_lock(&lport->lp_mutex);
+	
+	if (fc_lport_debug)
+		FC_DBG("Received a RFT_ID response\n");
+	
+	if (lport->state != LPORT_ST_RFT_ID) {
+		FC_DBG("Received a RFT_ID response, but in state %s\n",
+		       fc_lport_state(lport));
+		goto out;
+	}
 
-		} else {
-			fc_lport_error(lport, fp);
-		}
-		fc_lport_unlock(lport);
-		fc_frame_free(fp);
-	} else
+	if (IS_ERR(fp)) {
+		fc_lport_error(lport, fp);
+		goto out;
+	}
+
+	fh = fc_frame_header_get(fp);
+	ct = fc_frame_payload_get(fp, sizeof(*ct));
+
+	if (fh && ct && fh->fh_type == FC_TYPE_CT &&
+	    ct->ct_fs_type == FC_FST_DIR &&
+	    ct->ct_fs_subtype == FC_NS_SUBTYPE &&
+	    ntohs(ct->ct_cmd) == FC_FS_ACC)
+		fc_lport_enter_scr(lport);
+	else
+		fc_lport_error(lport, fp);
+out:
+	mutex_unlock(&lport->lp_mutex);
+	fc_frame_free(fp);
+}
+
+/**
+ * fc_lport_rpn_id_resp - Handle response to Register Port
+ *                        Name by ID (RPN_ID) request
+ * @sp: current sequence in RPN_ID exchange
+ * @fp: response frame
+ * @lp_arg: Fibre Channel host port instance
+ */
+static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
+				 void *lp_arg)
+{
+	struct fc_lport *lport = lp_arg;
+	struct fc_frame_header *fh;
+	struct fc_ct_hdr *ct;
+
+	mutex_lock(&lport->lp_mutex);	
+	
+	if (fc_lport_debug)
+		FC_DBG("Received a RPN_ID response\n");
+	
+	if (lport->state != LPORT_ST_RPN_ID) {
+		FC_DBG("Received a RPN_ID response, but in state %s\n",
+		       fc_lport_state(lport));
+		goto out;
+	}
+
+	if (IS_ERR(fp)) {
+		fc_lport_error(lport, fp);
+		goto out;
+	}
+
+	fh = fc_frame_header_get(fp);
+	ct = fc_frame_payload_get(fp, sizeof(*ct));
+	if (fh && ct && fh->fh_type == FC_TYPE_CT &&
+	    ct->ct_fs_type == FC_FST_DIR &&
+	    ct->ct_fs_subtype == FC_NS_SUBTYPE &&
+	    ntohs(ct->ct_cmd) == FC_FS_ACC)
+		fc_lport_enter_rft_id(lport);
+	else
 		fc_lport_error(lport, fp);
+	
+out:
+	mutex_unlock(&lport->lp_mutex);
+	fc_frame_free(fp);
 }
 
 /**
  * fc_lport_scr_resp - Handle response to State Change Register (SCR) request
  * @sp: current sequence in SCR exchange
  * @fp: response frame
- * @lp_arg: Fibre Channel host port instance
+ * @lp_arg: Fibre Channel lport port instance that sent the registration request
  */
 static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
 			      void *lp_arg)
 {
 	struct fc_lport *lport = lp_arg;
-	int err;
+	u8 op;
 
-	if (IS_ERR(fp))
+	mutex_lock(&lport->lp_mutex);
+	
+	if (fc_lport_debug)
+		FC_DBG("Received a SCR response\n");
+	
+	if (lport->state != LPORT_ST_SCR) {
+		FC_DBG("Received a SCR response, but in state %s\n",
+		       fc_lport_state(lport));
+		goto out;
+	}
+
+	if (IS_ERR(fp)) {
 		fc_lport_error(lport, fp);
-	else {
-		fc_lport_lock(lport);
-		fc_lport_enter_ready(lport);
-		fc_lport_unlock(lport);
-		err = lport->tt.disc_start(lport);
-		if (err)
-			FC_DBG("target discovery start error\n");
-		fc_frame_free(fp);
+		goto out;
 	}
+
+	op = fc_frame_payload_op(fp);
+	if (op == ELS_LS_ACC)
+		fc_lport_enter_ready(lport);
+	else
+		fc_lport_error(lport, fp);
+	
+out:
+	mutex_unlock(&lport->lp_mutex);
+	fc_frame_free(fp);
 }
 
 /**
- * fc_lport_enter scr - Send a State Change Register (SCR) request
- * @lp: Fibre Channel host port instance
+ * fc_lport_enter_scr - Send a State Change Register (SCR) request
+ * @lport: Fibre Channel local port to register for state changes
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
  */
 static void fc_lport_enter_scr(struct fc_lport *lport)
 {
@@ -752,32 +891,40 @@ static void fc_lport_enter_scr(struct fc_lport *lport)
 	struct fc_els_scr *scr;
 
 	if (fc_lport_debug)
-		FC_DBG("Processing SCR state\n");
+		FC_DBG("Port (%6x) entered SCR state from %s state\n",
+		       lport->fid, fc_lport_state(lport));
 
 	fc_lport_state_enter(lport, LPORT_ST_SCR);
 
 	fp = fc_frame_alloc(lport, sizeof(*scr));
-	if (fp) {
-		scr = fc_frame_payload_get(fp, sizeof(*scr));
-		memset(scr, 0, sizeof(*scr));
-		scr->scr_cmd = ELS_SCR;
-		scr->scr_reg_func = ELS_SCRF_FULL;
+	if (!fp) {
+		fc_lport_error(lport, fp);
+		return;
 	}
+
+	scr = fc_frame_payload_get(fp, sizeof(*scr));
+	memset(scr, 0, sizeof(*scr));
+	scr->scr_cmd = ELS_SCR;
+	scr->scr_reg_func = ELS_SCRF_FULL;
 	fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
 	fc_frame_set_offset(fp, 0);
 
-	lport->tt.exch_seq_send(lport, fp,
-				fc_lport_scr_resp,
-				lport, lport->e_d_tov,
-				lport->fid, FC_FID_FCTRL,
-				FC_FC_SEQ_INIT | FC_FC_END_SEQ);
+	if (!lport->tt.exch_seq_send(lport, fp,
+				     fc_lport_scr_resp,
+				     lport, lport->e_d_tov,
+				     lport->fid, FC_FID_FCTRL,
+				     FC_FC_SEQ_INIT | FC_FC_END_SEQ))
+		fc_lport_error(lport, fp);
 }
 
 /**
- * fc_lport_enter_reg_ft - Register FC4-types with the name server
- * @lp: Fibre Channel host port instance
+ * fc_lport_enter_rft_id - Register FC4-types with the name server
+ * @lport: Fibre Channel local port to register
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
  */
-static void fc_lport_enter_reg_ft(struct fc_lport *lport)
+static void fc_lport_enter_rft_id(struct fc_lport *lport)
 {
 	struct fc_frame *fp;
 	struct req {
@@ -789,47 +936,54 @@ static void fc_lport_enter_reg_ft(struct fc_lport *lport)
 	int i;
 
 	if (fc_lport_debug)
-		FC_DBG("Processing REG_FT state\n");
+		FC_DBG("Port (%6x) entered RFT_ID state from %s state\n",
+		       lport->fid, fc_lport_state(lport));
 
-	fc_lport_state_enter(lport, LPORT_ST_REG_FT);
+	fc_lport_state_enter(lport, LPORT_ST_RFT_ID);
 
 	lps = &lport->fcts;
 	i = sizeof(lps->ff_type_map) / sizeof(lps->ff_type_map[0]);
 	while (--i >= 0)
 		if (ntohl(lps->ff_type_map[i]) != 0)
 			break;
-	if (i >= 0) {
+	if (i < 0) {
+		/* nothing to register, move on to SCR */
+		fc_lport_enter_scr(lport);
+	} else {
 		fp = fc_frame_alloc(lport, sizeof(*req));
-		if (fp) {
-			req = fc_frame_payload_get(fp, sizeof(*req));
-			fc_fill_dns_hdr(lport, &req->ct,
-					FC_NS_RFT_ID,
-					sizeof(*req) -
-					sizeof(struct fc_ct_hdr));
-			hton24(req->fid.fp_fid, lport->fid);
-			req->fts = *lps;
-			fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
-
-			if (!lport->tt.exch_seq_send(lport, fp,
-						     fc_lport_ns_resp, lport,
-						     lport->e_d_tov,
-						     lport->fid,
-						     FC_FID_DIR_SERV,
-						     FC_FC_SEQ_INIT |
-						     FC_FC_END_SEQ))
-				fc_lport_error(lport, fp);
-		} else {
+		if (!fp) {
 			fc_lport_error(lport, fp);
+			return;
 		}
-	} else {
-		fc_lport_enter_scr(lport);
+
+		req = fc_frame_payload_get(fp, sizeof(*req));
+		fc_fill_dns_hdr(lport, &req->ct,
+				FC_NS_RFT_ID,
+				sizeof(*req) -
+				sizeof(struct fc_ct_hdr));
+		hton24(req->fid.fp_fid, lport->fid);
+		req->fts = *lps;
+		fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
+		
+		if (!lport->tt.exch_seq_send(lport, fp,
+					     fc_lport_rft_id_resp,
+					     lport, lport->e_d_tov,
+					     lport->fid,
+					     FC_FID_DIR_SERV,
+					     FC_FC_SEQ_INIT |
+					     FC_FC_END_SEQ))
+			fc_lport_error(lport, fp);
 	}
 }
 
-/*
- * Register port name with name server.
+/**
+ * fc_rport_enter_rft_id - Register port name with the name server
+ * @lport: Fibre Channel local port to register
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
  */
-static void fc_lport_enter_reg_pn(struct fc_lport *lport)
+static void fc_lport_enter_rpn_id(struct fc_lport *lport)
 {
 	struct fc_frame *fp;
 	struct req {
@@ -838,22 +992,26 @@ static void fc_lport_enter_reg_pn(struct fc_lport *lport)
 	} *req;
 
 	if (fc_lport_debug)
-		FC_DBG("Processing REG_PN state\n");
+		FC_DBG("Port (%6x) entered RPN_ID state from %s state\n",
+		       lport->fid, fc_lport_state(lport));
+
+	fc_lport_state_enter(lport, LPORT_ST_RPN_ID);
 
-	fc_lport_state_enter(lport, LPORT_ST_REG_PN);
 	fp = fc_frame_alloc(lport, sizeof(*req));
 	if (!fp) {
 		fc_lport_error(lport, fp);
 		return;
 	}
+
 	req = fc_frame_payload_get(fp, sizeof(*req));
 	memset(req, 0, sizeof(*req));
 	fc_fill_dns_hdr(lport, &req->ct, FC_NS_RPN_ID, sizeof(req->rn));
 	hton24(req->rn.fr_fid.fp_fid, lport->fid);
 	put_unaligned_be64(lport->wwpn, &req->rn.fr_wwn);
 	fc_frame_setup(fp, FC_RCTL_DD_UNSOL_CTL, FC_TYPE_CT);
+
 	if (!lport->tt.exch_seq_send(lport, fp,
-				     fc_lport_ns_resp, lport,
+				     fc_lport_rpn_id_resp, lport,
 				     lport->e_d_tov,
 				     lport->fid,
 				     FC_FID_DIR_SERV,
@@ -861,8 +1019,12 @@ static void fc_lport_enter_reg_pn(struct fc_lport *lport)
 		fc_lport_error(lport, fp);
 }
 
-/*
- * Setup session to dNS if not already set up.
+/**
+ * fc_rport_enter_dns - Create a rport to the name server
+ * @lport: Fibre Channel local port requesting a rport for the name server
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
  */
 static void fc_lport_enter_dns(struct fc_lport *lport)
 {
@@ -876,15 +1038,15 @@ static void fc_lport_enter_dns(struct fc_lport *lport)
 	dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
 
 	if (fc_lport_debug)
-		FC_DBG("Processing DNS state\n");
+		FC_DBG("Port (%6x) entered DNS state from %s state\n",
+		       lport->fid, fc_lport_state(lport));
 
 	fc_lport_state_enter(lport, LPORT_ST_DNS);
 
 	if (!lport->dns_rp) {
 		/* Set up a dummy rport to directory server */
-		fc_lport_unlock(lport);
 		rport = fc_rport_dummy_create(&dp);
-		fc_lport_lock(lport);
+
 		if (!rport)
 			goto err;
 		lport->dns_rp = rport;
@@ -894,16 +1056,8 @@ static void fc_lport_enter_dns(struct fc_lport *lport)
 	rdata = rport->dd_data;
 	rdata->local_port = lport;
 
-	/*
-	 * If dNS session isn't ready, start its logon.
-	 */
-	if (rdata->rp_state != RPORT_ST_READY) {
-		rdata->event_callback = fc_lport_rport_event;
-		lport->tt.rport_login(rport);
-	} else {
-		cancel_delayed_work_sync(&lport->retry_work);
-		fc_lport_enter_reg_pn(lport);
-	}
+	rdata->event_callback = fc_lport_rport_event;
+	lport->tt.rport_login(rport);
 	return;
 
 err:
@@ -920,7 +1074,7 @@ static void fc_lport_timeout(struct work_struct *work)
 		container_of(work, struct fc_lport,
 			     retry_work.work);
 	
-	fc_lport_lock(lport);
+	mutex_lock(&lport->lp_mutex);
 
 	switch (lport->state) {
 	case LPORT_ST_NONE:
@@ -934,11 +1088,11 @@ static void fc_lport_timeout(struct work_struct *work)
 	case LPORT_ST_DNS:
 		fc_lport_enter_dns(lport);
 		break;
-	case LPORT_ST_REG_PN:
-		fc_lport_enter_reg_pn(lport);
+	case LPORT_ST_RPN_ID:
+		fc_lport_enter_rpn_id(lport);
 		break;
-	case LPORT_ST_REG_FT:
-		fc_lport_enter_reg_ft(lport);
+	case LPORT_ST_RFT_ID:
+		fc_lport_enter_rft_id(lport);
 		break;
 	case LPORT_ST_SCR:
 		fc_lport_enter_scr(lport);
@@ -947,33 +1101,63 @@ static void fc_lport_timeout(struct work_struct *work)
 		fc_lport_enter_logo(lport);
 		break;
 	}
-	
-	fc_lport_unlock(lport);
+	mutex_unlock(&lport->lp_mutex);
 }
 
+/**
+ * fc_lport_logo_resp - Handle response to LOGO request
+ * @sp: current sequence in LOGO exchange
+ * @fp: response frame
+ * @lp_arg: Fibre Channel lport port instance that sent the LOGO request
+ */
 static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
 			       void *lp_arg)
 {
 	struct fc_lport *lport = lp_arg;
+	u8 op;
+
+	mutex_lock(&lport->lp_mutex);
+	
+	if (fc_lport_debug)
+		FC_DBG("Received a LOGO response\n");
+	
+	if (lport->state != LPORT_ST_LOGO) {
+		FC_DBG("Received a LOGO response, but in state %s\n",
+		       fc_lport_state(lport));
+		goto out;
+	}
 
-	if (IS_ERR(fp))
+	if (IS_ERR(fp)) {
 		fc_lport_error(lport, fp);
-	else {
-		fc_frame_free(fp);
-		fc_lport_lock(lport);
-		fc_lport_enter_reset(lport);
-		fc_lport_unlock(lport);
+		goto out;
 	}
+
+	op = fc_frame_payload_op(fp);
+	if (op == ELS_LS_ACC)
+		fc_lport_enter_reset(lport);
+	else
+		fc_lport_error(lport, fp);
+	
+out:
+	mutex_unlock(&lport->lp_mutex);
+	fc_frame_free(fp);
 }
 
-/* Logout of the FC fabric */
+/**
+ * fc_rport_enter_logo - Logout of the fabric
+ * @lport: Fibre Channel local port to be logged out
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
+ */
 static void fc_lport_enter_logo(struct fc_lport *lport)
 {
 	struct fc_frame *fp;
 	struct fc_els_logo *logo;
-
+	
 	if (fc_lport_debug)
-		FC_DBG("Processing LOGO state\n");
+		FC_DBG("Port (%6x) entered LOGO state from %s state\n",
+		       lport->fid, fc_lport_state(lport));
 
 	fc_lport_state_enter(lport, LPORT_ST_LOGO);
 
@@ -985,7 +1169,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport)
 
 	fp = fc_frame_alloc(lport, sizeof(*logo));
 	if (!fp) {
-		FC_DBG("failed to allocate frame\n");
+		fc_lport_error(lport, fp);
 		return;
 	}
 
@@ -994,20 +1178,22 @@ static void fc_lport_enter_logo(struct fc_lport *lport)
 	logo->fl_cmd = ELS_LOGO;
 	hton24(logo->fl_n_port_id, lport->fid);
 	logo->fl_n_port_wwn = htonll(lport->wwpn);
-
 	fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
 	fc_frame_set_offset(fp, 0);
 
-	lport->tt.exch_seq_send(lport, fp,
-				fc_lport_logo_resp,
-				lport, lport->e_d_tov,
-				lport->fid, FC_FID_FLOGI,
-				FC_FC_SEQ_INIT | FC_FC_END_SEQ);
+	if (!lport->tt.exch_seq_send(lport, fp,
+				     fc_lport_logo_resp,
+				     lport, lport->e_d_tov,
+				     lport->fid, FC_FID_FLOGI,
+				     FC_FC_SEQ_INIT | FC_FC_END_SEQ))
+		fc_lport_error(lport, fp);
 }
 
-/*
- * Handle incoming ELS FLOGI response.
- * Save parameters of remote switch.  Finish exchange.
+/**
+ * fc_lport_flogi_resp - Handle response to FLOGI request
+ * @sp: current sequence in FLOGI exchange
+ * @fp: response frame
+ * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request
  */
 static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg)
 {
@@ -1020,17 +1206,28 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp
 	unsigned int e_d_tov;
 	u16 mfs;
 
+	mutex_lock(&lport->lp_mutex);
+	
+	if (fc_lport_debug)
+		FC_DBG("Received a FLOGI response\n");
+	
+	if (lport->state != LPORT_ST_FLOGI) {
+		FC_DBG("Received a FLOGI response, but in state %s\n",
+		       fc_lport_state(lport));
+		goto out;
+	}
+	
 	if (IS_ERR(fp)) {
 		fc_lport_error(lport, fp);
-		return;
+		goto out;
 	}
-
+	
 	fh = fc_frame_header_get(fp);
 	did = ntoh24(fh->fh_d_id);
 	if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
 		if (fc_lport_debug)
-			FC_DBG("assigned fid %x\n", did);
-		fc_lport_lock(lport);
+			FC_DBG("Assigned fid %x\n", did);
+
 		lport->fid = did;
 		flp = fc_frame_payload_get(fp, sizeof(*flp));
 		if (flp) {
@@ -1048,7 +1245,7 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp
 				if (e_d_tov > lport->e_d_tov)
 					lport->e_d_tov = e_d_tov;
 				lport->r_a_tov = 2 * e_d_tov;
-				FC_DBG("point-to-point mode\n");
+				FC_DBG("Point-to-Point mode\n");
 				fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id),
 						   get_unaligned_be64(
 							   &flp->fl_wwpn),
@@ -1060,22 +1257,29 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp
 				fc_lport_enter_dns(lport);
 			}
 		}
-		fc_lport_unlock(lport);
+
 		if (flp) {
 			csp_flags = ntohs(flp->fl_csp.sp_features);
 			if ((csp_flags & FC_SP_FT_FPORT) == 0) {
 				if (lport->tt.disc_start(lport))
-					FC_DBG("target disc start error\n");
+					FC_DBG("Target disc start error\n");
 			}
 		}
 	} else {
 		FC_DBG("bad FLOGI response\n");
 	}
+
+out:
+	mutex_unlock(&lport->lp_mutex);
 	fc_frame_free(fp);
 }
 
-/*
- * Send ELS (extended link service) FLOGI request to peer.
+/**
+ * fc_rport_enter_flogi - Send a FLOGI request to the fabric manager
+ * @lport: Fibre Channel local port to be logged in to the fabric
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
  */
 void fc_lport_enter_flogi(struct fc_lport *lport)
 {
@@ -1083,17 +1287,19 @@ void fc_lport_enter_flogi(struct fc_lport *lport)
 	struct fc_els_flogi *flp;
 
 	if (fc_lport_debug)
-		FC_DBG("Processing FLOGI state\n");
+		FC_DBG("Port (%6x) entered FLOGI state from %s state\n",
+		       lport->fid, fc_lport_state(lport));
 
 	fc_lport_state_enter(lport, LPORT_ST_FLOGI);
 
 	fp = fc_frame_alloc(lport, sizeof(*flp));
-	if (!fp)
-		return fc_lport_error(lport, fp);
+	if (!fp) {
+		fc_lport_error(lport, fp);
+		return;
+	}
 
 	flp = fc_frame_payload_get(fp, sizeof(*flp));
 	fc_lport_flogi_fill(lport, flp, ELS_FLOGI);
-
 	fc_frame_setup(fp, FC_RCTL_ELS_REQ, FC_TYPE_ELS);
 	fc_frame_set_offset(fp, 0);
 
@@ -1109,11 +1315,9 @@ void fc_lport_enter_flogi(struct fc_lport *lport)
 int fc_lport_config(struct fc_lport *lport)
 {
 	INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
-	spin_lock_init(&lport->state_lock);
+	mutex_init(&lport->lp_mutex);
 
-	fc_lport_lock(lport);
 	fc_lport_state_enter(lport, LPORT_ST_NONE);
-	fc_lport_unlock(lport);
 
 	lport->ns_disc_delay = DNS_DELAY;
 
@@ -1127,10 +1331,10 @@ EXPORT_SYMBOL(fc_lport_config);
 int fc_lport_init(struct fc_lport *lport)
 {
 	if (!lport->tt.lport_recv)
-		lport->tt.lport_recv = fc_lport_recv;
+		lport->tt.lport_recv = fc_lport_recv_req;
 
 	if (!lport->tt.lport_reset)
-		lport->tt.lport_reset = fc_lport_enter_reset;
+		lport->tt.lport_reset = fc_lport_reset;
 
 	if (!lport->tt.event_callback)
 		lport->tt.event_callback = fc_lport_rport_event;
diff --git a/drivers/scsi/libfc/fc_ns.c b/drivers/scsi/libfc/fc_ns.c
index 844c2f2..dec0e69 100644
--- a/drivers/scsi/libfc/fc_ns.c
+++ b/drivers/scsi/libfc/fc_ns.c
@@ -154,13 +154,11 @@ static void fc_ns_recv_req(struct fc_seq *sp, struct fc_frame *fp,
  */
 static int fc_ns_restart(struct fc_lport *lp)
 {
-	fc_lport_lock(lp);
 	if (!lp->ns_disc_requested && !lp->ns_disc_pending) {
 		schedule_delayed_work(&lp->ns_disc_work,
 				msecs_to_jiffies(lp->ns_disc_delay * 1000));
 	}
 	lp->ns_disc_requested = 1;
-	fc_lport_unlock(lp);
 	return 0;
 }
 
@@ -225,14 +223,12 @@ int fc_ns_disc_start(struct fc_lport *lp)
 	int error;
 	struct fc_rport_identifiers ids;
 
-	fc_lport_lock(lp);
-
 	/*
 	 * If not ready, or already running discovery, just set request flag.
 	 */
 	if (!fc_lport_test_ready(lp) || lp->ns_disc_pending) {
 		lp->ns_disc_requested = 1;
-		fc_lport_unlock(lp);
+
 		return 0;
 	}
 	lp->ns_disc_pending = 1;
@@ -250,13 +246,13 @@ int fc_ns_disc_start(struct fc_lport *lp)
 		ids.node_name = rport->node_name;
 		ids.roles = FC_RPORT_ROLE_UNKNOWN;
 		get_device(&rport->dev);
-		fc_lport_unlock(lp);
+
 		error = fc_ns_new_target(lp, rport, &ids);
 		put_device(&rport->dev);
 		if (!error)
 			fc_ns_disc_done(lp);
 	} else {
-		fc_lport_unlock(lp);
+
 		fc_block_rports(lp);
 		fc_ns_gpn_ft_req(lp);	/* get ports by FC-4 type */
 		error = 0;
diff --git a/include/scsi/libfc/libfc.h b/include/scsi/libfc/libfc.h
index e287144..07a1220 100644
--- a/include/scsi/libfc/libfc.h
+++ b/include/scsi/libfc/libfc.h
@@ -92,8 +92,8 @@ enum fc_lport_state {
 	LPORT_ST_NONE = 0,
 	LPORT_ST_FLOGI,
 	LPORT_ST_DNS,
-	LPORT_ST_REG_PN,
-	LPORT_ST_REG_FT,
+	LPORT_ST_RPN_ID,
+	LPORT_ST_RFT_ID,
 	LPORT_ST_SCR,
 	LPORT_ST_READY,
 	LPORT_ST_LOGO,
@@ -451,8 +451,8 @@ struct fc_lport {
 	struct fc_ns_fts	fcts;	        /* FC-4 type masks */
 	struct fc_els_rnid_gen	rnid_gen;	/* RNID information */
 
-	/* Locks */
-	spinlock_t		state_lock;	/* serializes state changes */
+	/* Semaphores */
+	struct mutex lp_mutex;
 
 	/* Miscellaneous */
 	struct fc_gpn_ft_resp	ns_disc_buf;	/* partial name buffer */
@@ -486,15 +486,6 @@ static inline void fc_set_wwpn(struct fc_lport *lp, u64 wwnn)
 	lp->wwpn = wwnn;
 }
 
-static inline int fc_lport_locked(struct fc_lport *lp)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-	return spin_is_locked(&lp->state_lock);
-#else
-	return 1;
-#endif /* CONFIG_SMP || CONFIG_DEBUG_SPINLOCK */
-}
-
 /**
  * fc_fill_dns_hdr - Fill in a name service request header
  * @lp: Fibre Channel host port instance
@@ -512,23 +503,9 @@ static inline void fc_fill_dns_hdr(struct fc_lport *lp, struct fc_ct_hdr *ct,
 	ct->ct_cmd = htons((u16) op);
 }
 
-/*
- * Locking code.
- */
-static inline void fc_lport_lock(struct fc_lport *lp)
-{
-	spin_lock_bh(&lp->state_lock);
-}
-
-static inline void fc_lport_unlock(struct fc_lport *lp)
-{
-	spin_unlock_bh(&lp->state_lock);
-}
-
 static inline void fc_lport_state_enter(struct fc_lport *lp,
 					enum fc_lport_state state)
 {
-	WARN_ON(!fc_lport_locked(lp));
 	if (state != lp->state)
 		lp->retry_count = 0;
 	lp->state = state;
@@ -583,7 +560,7 @@ int fc_lport_config(struct fc_lport *);
 /*
  * Reset the local port.
  */
-int fc_lport_enter_reset(struct fc_lport *);
+int fc_lport_reset(struct fc_lport *);
 
 /*
  * Set the mfs or reset




More information about the devel mailing list