All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] [FCoE] Removal of state machine transition abstraction layer.
@ 2008-01-12  0:17 Robert Love
  0 siblings, 0 replies; only message in thread
From: Robert Love @ 2008-01-12  0:17 UTC (permalink / raw)
  To: linux-scsi

Part of effort to remove libsa.

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

 drivers/scsi/ofc/include/sa_state.h    |  164 -------------
 drivers/scsi/ofc/libfc/fc_local_port.c |  402 ++++++++++++++------------------
 drivers/scsi/ofc/libfc/fc_sess.c       |  398 ++++++++++----------------------
 drivers/scsi/ofc/libfc/fc_sess_impl.h  |    1 
 drivers/scsi/ofc/libfc/fcs_state.c     |    4 
 drivers/scsi/ofc/libsa/Makefile        |    1 
 drivers/scsi/ofc/libsa/sa_state.c      |  371 ------------------------------
 7 files changed, 308 insertions(+), 1033 deletions(-)
 delete mode 100644 drivers/scsi/ofc/include/sa_state.h
 delete mode 100644 drivers/scsi/ofc/libsa/sa_state.c


diff --git a/drivers/scsi/ofc/include/sa_state.h b/drivers/scsi/ofc/include/sa_state.h
deleted file mode 100644
index 8a7ee8d..0000000
--- a/drivers/scsi/ofc/include/sa_state.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright(c) 2007 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,
- * version 2, as published by the Free Software Foundation.
- * 
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- * 
- * Maintained at www.Open-FCoE.org
- */
-
-#ifndef _LIBSA_SA_STATE_H_
-#define _LIBSA_SA_STATE_H_
-
-/*
- * State transition table handling.
- */
-struct sa_state_table;
-
-/*
- * State transition description.
- * There are the following entry types:
- * - END simply indicates the end of the table.
- * - STATE gives the number and name of a state.
- * - EVENT gives the number and name of an event
- * - HANDLER gives the number and function pointer to a handler.
- * - FROM sets the current state.
- * - NEXT gives a state transition from the current state on.
- * a given event; the next state and/or a handler to call are given.
- *
- * A handler can also be associated with a particular state, in which
- * case the handler will be called on every entry to the state.
- */
-struct sa_state_desc {
-	enum {
-		SST_END,	/* end of table */
-		SST_STATE,	/* state definition */
-		SST_EVENT,	/* event definition */
-		SST_HANDLER,	/* handler */
-		SST_FROM,	/* old state definition */
-		SST_NEXT,	/* state transition definition */
-	} sd_type;
-	u_char	sd_in;		/* event or state number */
-	u_char	sd_next;	/* next state number */
-	const char *sd_ptr;	/* name of state or event or function or NULL */
-};
-
-typedef void (sa_state_handler_t)(void *arg, u_int next_state, u_int event);
-
-/*
- * Convenience macros for filling in descriptors.
- */
-
-/**
- * SA_STATE_LABEL(state, name) - declare a state name and number.
- *
- * @param state symbol with value of state.
- * @param name human-readable name for state.
- *
- * This sets the current state for the following state event initializations.
- */
-#define SA_STATE_LABEL(state, name) { \
-        .sd_type = SST_STATE, .sd_ptr = name, .sd_in = state }
-
-/**
- * SA_STATE_NAME(state) - declare a state name and number.
- *
- * @param state symbol with value of state, also used for state name
- *
- * This sets the current state for the following state event initializations.
- */
-#define SA_STATE_NAME(state) SA_STATE_LABEL(state, #state)
-
-/**
- * SA_STATE_HANDLER(state, handler) - declare function to handle entry to state.
- *
- * @param state the state number.
- * @param handler the handler function pointer.
- */
-#define SA_STATE_HANDLER(state, handler) { \
-        .sd_type = SST_HANDLER, .sd_ptr = (void *) handler, .sd_in = state }
-
-/*
- * SA_STATE_EVENT(event)
- *
- * @param event symbol with value of event, also used for the event name.
- *
- * This declares an event which can be used in the state transition table.
- */
-#define SA_STATE_EVENT(event) { \
-        .sd_type = SST_EVENT, .sd_ptr = #event, .sd_in = event }
-
-/**
- * SA_STATE_FROM(val) - set the state number for subsequent SA_STATE_NEXT*()s.
- */
-#define SA_STATE_FROM(val) {            /* not really needed */ \
-        .sd_type = SST_STATE, .sd_in = val }
-
-/**
- * SA_STATE_NEXT_FUNC(event, next, handler) - declare transition entry.
- *
- * @param event the event number.
- * @param next the state to which to transition.
- * @param handler a pointer to a function to call before the transition.
- */
-#define SA_STATE_NEXT_FUNC(event, next, handler) { \
-        .sd_type = SST_NEXT, .sd_in = event, .sd_next = next, \
-        .sd_ptr = (void *) handler }
-
-/**
- * SA_STATE_NEXT(event, next) - declare transition entry.
- *
- * @param event the event number.
- * @param next the state to which to transition.
- */
-#define SA_STATE_NEXT(event, next)  SA_STATE_NEXT_FUNC(event, next, NULL)
-
-/**
- * SA_STATE_END - declare end of state table description.
- */
-#define SA_STATE_END    { .sd_type = SST_END }
-
-/*
- * State transition table initialization.
- */
-struct sa_state_table *sa_state_table_alloc(const char *name,
-					    const struct sa_state_desc
-					    *state_desc);
-
-/*
- * Free state table.
- */
-void sa_state_table_free(struct sa_state_table *);
-
-/*
- * Handle event for a state transition table.
- */
-void sa_state_table_step(struct sa_state_table *tp, void *statep,
-			 u_int event, void *arg);
-
-/*
- * Transition to the specified state.  Run the handler if any.
- */
-void sa_state_table_enter(struct sa_state_table *, void *statep,
-			  u_int new_state, u_int event, void *arg);
-
-/**
- * sa_state_table_log() - set function to log state table transitions.
- */
-void sa_state_table_log(struct sa_state_table *tp,
-			void (*log_func) (void *arg, const char *msg));
-
-const char *sa_state_event_name(struct sa_state_table *, u_int);
-const char *sa_state_name(struct sa_state_table *, u_int);
-
-#endif /* _LIBSA_SA_STATE_H_ */
diff --git a/drivers/scsi/ofc/libfc/fc_local_port.c b/drivers/scsi/ofc/libfc/fc_local_port.c
index 1911405..7430da4 100644
--- a/drivers/scsi/ofc/libfc/fc_local_port.c
+++ b/drivers/scsi/ofc/libfc/fc_local_port.c
@@ -29,7 +29,6 @@
 #include "sa_timer.h"
 #include "sa_event.h"
 #include "sa_hash.h"
-#include "sa_state.h"
 
 #include "fc_fs.h"
 #include "fc_gs.h"
@@ -49,7 +48,6 @@
 #include "fc_port.h"
 #include "fc_frame.h"
 #include "fc_exch.h"
-#include "fc_event.h"
 
 #include "fc_sess_impl.h"
 #include "fc_local_port_impl.h"
@@ -94,123 +92,83 @@ static void fc_local_port_port_event(int, void *);
 static void fc_local_port_set_fid_int(struct fc_local_port *, fc_fid_t);
 static void fc_local_port_gid_pn_error(enum fc_event, void *arg);
 
+static inline void fc_local_port_enter_state(struct fc_local_port *lp,
+				      enum fc_local_port_state state)
+{
+	WARN_ON(!fc_local_port_locked(lp));
+	sa_timer_cancel(&lp->fl_timer);
+	if (state != lp->fl_state)
+		lp->fl_retry_count = 0;
+	lp->fl_state = state;
+}
+
 /*
- * Session state transition table.
+ * re-enter state for retrying a request after a timeout or alloc failure.
  */
-static const struct sa_state_desc fc_local_port_state_desc[] = {
-	/*
-	 * Declare events.
-	 * The event meanings are slightly different than the generic ones.
-	 */
-	SA_STATE_EVENT(FC_EV_ACC),	/* exchange accepted */
-	SA_STATE_EVENT(FC_EV_RJT),	/* exchange rejected */
-	SA_STATE_EVENT(FC_EV_TIMEOUT),	/* exchange timed out */
-	SA_STATE_EVENT(FC_EV_START),	/* upper layer requested FLOGI */
-	SA_STATE_EVENT(FC_EV_STOP),	/* upper layer requested LOGO */
-	SA_STATE_EVENT(FC_EV_READY),	/* dNS session ready */
-	SA_STATE_EVENT(FC_EV_CLOSED),	/* dNS session closed */
-	SA_STATE_EVENT(FC_EV_DOWN),	/* event shouldn't be seen */
-
-	/*
-	 * Associate handlers for entering specific states.
-	 */
-	SA_STATE_HANDLER(LOCAL_PORT_ST_INIT, fc_local_port_enter_init),
-	SA_STATE_HANDLER(LOCAL_PORT_ST_FLOGI, fc_local_port_enter_flogi),
-	SA_STATE_HANDLER(LOCAL_PORT_ST_DNS, fc_local_port_enter_dns),
-	SA_STATE_HANDLER(LOCAL_PORT_ST_REG_PN, fc_local_port_enter_reg_pn),
-	SA_STATE_HANDLER(LOCAL_PORT_ST_REG_FT, fc_local_port_enter_reg_ft),
-	SA_STATE_HANDLER(LOCAL_PORT_ST_SCR, fc_local_port_enter_scr),
-	SA_STATE_HANDLER(LOCAL_PORT_ST_READY, fc_local_port_enter_ready),
-	SA_STATE_HANDLER(LOCAL_PORT_ST_DNS_STOP, fc_local_port_enter_dns_stop),
-	SA_STATE_HANDLER(LOCAL_PORT_ST_LOGO, fc_local_port_enter_logo),
-
-	/*
-	 * Declare states and transitions.
-	 */
-	SA_STATE_LABEL(LOCAL_PORT_ST_INIT, "idle"),	/* idle state */
-	SA_STATE_NEXT(FC_EV_START, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_STOP, LOCAL_PORT_ST_INIT),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, LOCAL_PORT_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, LOCAL_PORT_ST_INIT),
-
-	SA_STATE_LABEL(LOCAL_PORT_ST_FLOGI, "FLOGI"),	/* login to fabric */
-	SA_STATE_NEXT(FC_EV_ACC, LOCAL_PORT_ST_DNS),
-	SA_STATE_NEXT(FC_EV_RJT, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_CLOSED, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_STOP, LOCAL_PORT_ST_INIT),
-
-	SA_STATE_LABEL(LOCAL_PORT_ST_DNS, "dNS"),	/* wait for dNS sess */
-	SA_STATE_NEXT(FC_EV_READY, LOCAL_PORT_ST_REG_PN),
-	SA_STATE_NEXT(FC_EV_CLOSED, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_STOP, LOCAL_PORT_ST_LOGO),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, LOCAL_PORT_ST_DNS),
-	SA_STATE_NEXT(FC_EV_RJT, LOCAL_PORT_ST_INIT),
-
-	SA_STATE_LABEL(LOCAL_PORT_ST_REG_PN, "REG_PN"), /* reg. ID with dNS */
-	SA_STATE_NEXT(FC_EV_ACC, LOCAL_PORT_ST_REG_FT),
-	SA_STATE_NEXT(FC_EV_RJT, LOCAL_PORT_ST_REG_FT),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_CLOSED, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_STOP, LOCAL_PORT_ST_DNS_STOP),
-
-	SA_STATE_LABEL(LOCAL_PORT_ST_REG_FT, "REG_FT"),	/* register FC-4 type */
-	SA_STATE_NEXT(FC_EV_ACC, LOCAL_PORT_ST_SCR),
-	SA_STATE_NEXT(FC_EV_RJT, LOCAL_PORT_ST_SCR),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_CLOSED, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_STOP, LOCAL_PORT_ST_DNS_STOP),
-
-	SA_STATE_LABEL(LOCAL_PORT_ST_SCR, "SCR"),	/* state change reg. */
-	SA_STATE_NEXT(FC_EV_ACC, LOCAL_PORT_ST_READY),
-	SA_STATE_NEXT(FC_EV_RJT, LOCAL_PORT_ST_SCR),	/* XXX wrong */
-	SA_STATE_NEXT(FC_EV_TIMEOUT, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_CLOSED, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_STOP, LOCAL_PORT_ST_DNS_STOP),
-
-	SA_STATE_LABEL(LOCAL_PORT_ST_READY, "ready"),	/* ready */
-	SA_STATE_NEXT(FC_EV_STOP, LOCAL_PORT_ST_DNS_STOP),
-	SA_STATE_NEXT(FC_EV_CLOSED, LOCAL_PORT_ST_FLOGI),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, LOCAL_PORT_ST_READY),
-	SA_STATE_NEXT(FC_EV_RJT, LOCAL_PORT_ST_READY),	/* late response */
-
-	SA_STATE_LABEL(LOCAL_PORT_ST_DNS_STOP, "stop"),	/* dNS session logout */
-	SA_STATE_NEXT(FC_EV_CLOSED, LOCAL_PORT_ST_LOGO),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, LOCAL_PORT_ST_DNS_STOP),
-	SA_STATE_NEXT(FC_EV_RJT, LOCAL_PORT_ST_DNS_STOP),
-
-	SA_STATE_LABEL(LOCAL_PORT_ST_LOGO, "LOGO"),	/* logout */
-	SA_STATE_NEXT(FC_EV_ACC, LOCAL_PORT_ST_INIT),
-	SA_STATE_NEXT(FC_EV_RJT, LOCAL_PORT_ST_INIT),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, LOCAL_PORT_ST_LOGO),
-	SA_STATE_NEXT(FC_EV_STOP, LOCAL_PORT_ST_LOGO),
-	SA_STATE_NEXT(FC_EV_CLOSED, LOCAL_PORT_ST_INIT),
-
-	SA_STATE_LABEL(LOCAL_PORT_ST_RESET, "reset"),
-
-	SA_STATE_END
-};
-
-static struct sa_state_table *fc_local_port_state_table;
-static int fc_local_port_state_table_refcnt;
+static void fc_local_port_enter_retry(struct fc_local_port *lp)
+{
+	switch (lp->fl_state) {
+	case LOCAL_PORT_ST_NONE:
+	case LOCAL_PORT_ST_INIT:
+	case LOCAL_PORT_ST_READY:
+	case LOCAL_PORT_ST_RESET:
+		WARN_ON(1);
+		break;
+	case LOCAL_PORT_ST_FLOGI:
+		fc_local_port_enter_flogi(lp);
+		break;
+	case LOCAL_PORT_ST_DNS:
+		fc_local_port_enter_dns(lp);
+		break;
+	case LOCAL_PORT_ST_DNS_STOP:
+		fc_local_port_enter_dns_stop(lp);
+		break;
+	case LOCAL_PORT_ST_REG_PN:
+		fc_local_port_enter_reg_pn(lp);
+		break;
+	case LOCAL_PORT_ST_REG_FT:
+		fc_local_port_enter_reg_ft(lp);
+		break;
+	case LOCAL_PORT_ST_SCR:
+		fc_local_port_enter_scr(lp);
+		break;
+	case LOCAL_PORT_ST_LOGO:
+		fc_local_port_enter_logo(lp);
+		break;
+	}
+}
 
 /*
- * Transition a local port state due to an event.
+ * enter next state for handling an exchange reject or retry exhaustion
+ * in the current state.
  */
-static void fc_local_port_state_event(struct fc_local_port *lp,
-				      enum fc_event event)
-{
-	enum fc_local_port_state old_state;
-
-	ASSERT(fc_local_port_locked(lp));
-	old_state = lp->fl_state;
-	ASSERT(old_state != LOCAL_PORT_ST_RESET);
-	sa_timer_cancel(&lp->fl_timer);
-	sa_state_table_step(fc_local_port_state_table, &lp->fl_state,
-			    event, lp);
-	ASSERT(fc_local_port_locked(lp));
-	if (lp->fl_state != old_state)
-		lp->fl_retry_count = 0;
+static void fc_local_port_enter_reject(struct fc_local_port *lp)
+{
+	switch (lp->fl_state) {
+	case LOCAL_PORT_ST_NONE:
+	case LOCAL_PORT_ST_INIT:
+	case LOCAL_PORT_ST_READY:
+	case LOCAL_PORT_ST_RESET:
+		WARN_ON(1);
+		break;
+	case LOCAL_PORT_ST_FLOGI:
+		fc_local_port_enter_flogi(lp);
+		break;
+	case LOCAL_PORT_ST_REG_PN:
+		fc_local_port_enter_reg_ft(lp);
+		break;
+	case LOCAL_PORT_ST_REG_FT:
+		fc_local_port_enter_scr(lp);
+		break;
+	case LOCAL_PORT_ST_SCR:
+	case LOCAL_PORT_ST_DNS_STOP:
+		fc_local_port_enter_dns_stop(lp);
+		break;
+	case LOCAL_PORT_ST_DNS:
+	case LOCAL_PORT_ST_LOGO:
+		fc_local_port_enter_init(lp);
+		break;
+	}
 }
 
 static void fc_local_port_timeout(void *lp_arg)
@@ -218,32 +176,51 @@ static void fc_local_port_timeout(void *lp_arg)
 	struct fc_local_port *lp = lp_arg;
 
 	fc_local_port_lock(lp);
-	fc_local_port_state_event(lp, FC_EV_TIMEOUT);
+	fc_local_port_enter_retry(lp);
 	fc_local_port_unlock_send(lp);
 }
 
+static const char *fc_local_port_state_names[] = {
+ 	[LOCAL_PORT_ST_NONE] =	"none",
+ 	[LOCAL_PORT_ST_INIT] =	"idle",
+ 	[LOCAL_PORT_ST_FLOGI] =	"FLOGI",
+ 	[LOCAL_PORT_ST_DNS] =	"dNS",
+ 	[LOCAL_PORT_ST_REG_PN] = "REG_PN",
+ 	[LOCAL_PORT_ST_REG_FT] = "REG_FT",
+ 	[LOCAL_PORT_ST_SCR] =	"SCR",
+ 	[LOCAL_PORT_ST_READY] =	"ready",
+ 	[LOCAL_PORT_ST_DNS_STOP] = "stop",
+ 	[LOCAL_PORT_ST_LOGO] =	"LOGO",
+ 	[LOCAL_PORT_ST_RESET] =	"reset",
+};
+
 const char *fc_local_port_state(struct fc_local_port *lp)
 {
-	return sa_state_name(fc_local_port_state_table, lp->fl_state);
+ 	const char *cp;
+
+ 	cp = fc_local_port_state_names[lp->fl_state];
+	if (!cp)
+		cp = "unknown";
+	return cp;
 }
 
+/*
+ * Handle resource allocation problem by retrying in a bit.
+ */
 static void fc_local_port_retry(struct fc_local_port *lp)
 {
-	const char *state;
-
 	ASSERT(fc_local_port_locked(lp));
-	state = fc_local_port_state(lp);
-	if (lp->fl_retry_count == 0) {
+	if (lp->fl_retry_count == 0)
 		OFC_DBG("local port %6x alloc failure in state %s "
-		       "- will retry", lp->fl_fid, state);
-	}
+			"- will retry", lp->fl_fid, fc_local_port_state(lp));
 	if (lp->fl_retry_count < lp->fl_retry_limit) {
 		lp->fl_retry_count++;
 		sa_timer_set(&lp->fl_timer, lp->fl_e_d_tov * 1000);
 	} else {
 		OFC_DBG("local port %6x alloc failure in state %s "
-		       "- retries exhausted", lp->fl_fid, state);
-		fc_local_port_state_event(lp, FC_EV_RJT);
+			"- retries exhausted", lp->fl_fid,
+			fc_local_port_state(lp));
+ 		fc_local_port_enter_reject(lp);
 	}
 }
 
@@ -281,9 +258,8 @@ static void fc_local_port_ptp_setup(struct fc_local_port *lp,
 		if (lp->fl_ptp_rp)
 			fc_remote_port_release(lp->fl_ptp_rp);
 		lp->fl_ptp_rp = rp;
+		fc_local_port_enter_ready(lp);
 	}
-	sa_state_table_enter(fc_local_port_state_table, &lp->fl_state,
-			     LOCAL_PORT_ST_READY, FC_EV_NONE, lp);
 }
 
 static void fc_local_port_ptp_clear(struct fc_local_port *lp)
@@ -404,10 +380,8 @@ fc_local_port_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg)
 			} else {
 				lp->fl_e_d_tov = e_d_tov;
 				lp->fl_r_a_tov = r_a_tov;
-				fc_local_port_state_event(lp, FC_EV_ACC);
+				fc_local_port_enter_dns(lp);
 			}
-		} else {
-			fc_local_port_state_event(lp, FC_EV_RJT);
 		}
 		fc_local_port_unlock_send(lp);
 	} else {
@@ -513,8 +487,7 @@ static void fc_local_port_recv_flogi_req(struct fc_seq *sp_in,
 	}
 	fc_local_port_set_fid_int(lp, local_fid);
 
-	sa_state_table_enter(fc_local_port_state_table, &lp->fl_state,
-			     LOCAL_PORT_ST_READY, FC_EV_NONE, lp);
+	fc_local_port_enter_ready(lp);
 
 	fp = fc_frame_alloc(lp->fl_port, sizeof(*flp));
 	if (fp) {
@@ -545,7 +518,7 @@ out:
 
 static void fc_local_port_enter_flogi(struct fc_local_port *lp)
 {
-	ASSERT(fc_local_port_locked(lp));
+	fc_local_port_enter_state(lp, LOCAL_PORT_ST_FLOGI);
 	fc_local_port_ptp_clear(lp);
 	fc_local_port_flogi_send(lp);
 }
@@ -563,19 +536,25 @@ static void fc_local_port_sess_event(int event, void *lp_arg)
 
 	fc_local_port_hold(lp);
 	fc_local_port_lock(lp);
+	sa_timer_cancel(&lp->fl_timer);
+
 	if (fc_local_port_debug) {
 		OFC_DBG("local fid %6x dNS session event %d\n", lp->fl_fid,
 		       event);
 	}
 	switch (event) {
 	case FC_EV_READY:
-		fc_local_port_state_event(lp, event);
+		if (lp->fl_state == LOCAL_PORT_ST_DNS)
+ 			fc_local_port_enter_reg_pn(lp);
 		break;
 	case FC_EV_CLOSED:
 		sess = lp->fl_dns_sess;
 		ASSERT(sess);
 		lp->fl_dns_sess = NULL;
-		fc_local_port_state_event(lp, event);
+ 		if (lp->fl_state == LOCAL_PORT_ST_DNS_STOP)
+ 			fc_local_port_enter_logo(lp);
+ 		else
+ 			fc_local_port_enter_flogi(lp);
 		break;
 	default:
 		OFC_DBG("unexpected event %d from dNS session", event);
@@ -597,7 +576,7 @@ static void fc_local_port_enter_dns(struct fc_local_port *lp)
 	struct fc_sess *sess;
 	struct fc_remote_port *rp;
 
-	ASSERT(fc_local_port_locked(lp));
+	fc_local_port_enter_state(lp, LOCAL_PORT_ST_DNS);
 	sess = lp->fl_dns_sess;
 	if (!sess) {
 		/*
@@ -625,7 +604,8 @@ static void fc_local_port_enter_dns(struct fc_local_port *lp)
 	if (sess->fs_state != SESS_ST_READY) {
 		fc_sess_start(sess);	/* start the PLOGI ASAP */
 	} else {
-		fc_local_port_state_event(lp, FC_EV_READY);
+		sa_timer_cancel(&lp->fl_timer);
+		fc_local_port_enter_reg_pn(lp);
 	}
 	return;
 
@@ -681,6 +661,7 @@ static void fc_local_port_enter_reg_pn(struct fc_local_port *lp)
 		struct fc_ns_rn_id rn;
 	} *rp;
 
+	fc_local_port_enter_state(lp, LOCAL_PORT_ST_REG_PN);
 	fp = fc_frame_alloc(lp->fl_port, sizeof(*rp));
 	if (!fp) {
 		fc_local_port_retry(lp);
@@ -707,10 +688,15 @@ fc_local_port_ns_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg)
 	struct fc_local_port *lp = lp_arg;
 
 	fc_local_port_lock(lp);
+	sa_timer_cancel(&lp->fl_timer);
 	if (fc_local_port_dns_acc(fp)) {
-		fc_local_port_state_event(lp, FC_EV_ACC);
+		if (lp->fl_state == LOCAL_PORT_ST_REG_PN)
+			fc_local_port_enter_reg_ft(lp);
+		else
+			fc_local_port_enter_scr(lp);
+
 	} else {
-		fc_local_port_state_event(lp, FC_EV_RJT);
+		fc_local_port_retry(lp);
 	}
 	fc_local_port_unlock_send(lp);
 	fc_frame_free(fp);
@@ -730,7 +716,7 @@ static void fc_local_port_enter_reg_ft(struct fc_local_port *lp)
 	struct fc_ns_fts *lps;
 	int i;
 
-	ASSERT(fc_local_port_locked(lp));
+	fc_local_port_enter_state(lp, LOCAL_PORT_ST_REG_FT);
 	lps = &lp->fl_ns_fts;
 	i = sizeof(lps->ff_type_map) / sizeof(lps->ff_type_map[0]);
 	while (--i >= 0)
@@ -756,7 +742,7 @@ static void fc_local_port_enter_reg_ft(struct fc_local_port *lp)
 			fc_local_port_retry(lp);
 		}
 	} else {
-		fc_local_port_state_event(lp, FC_EV_ACC);
+		fc_local_port_enter_scr(lp);
 	}
 }
 
@@ -766,6 +752,7 @@ static void fc_local_port_enter_scr(struct fc_local_port *lp)
 	struct fc_els_scr *scr;
 	struct fc_seq *sp;
 
+	fc_local_port_enter_state(lp, LOCAL_PORT_ST_SCR);
 	sp = fc_seq_start_exch(lp->fl_vf->vf_exch_mgr,
 			       fc_local_port_scr_resp, fc_local_port_error,
 			       lp, lp->fl_fid, FC_FID_FCTRL);
@@ -784,26 +771,16 @@ static void
 fc_local_port_scr_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg)
 {
 	struct fc_local_port *lp = lp_arg;
-	struct fc_frame_header *fh;
 
 	fc_local_port_lock(lp);
-	fh = fc_frame_header_get(fp);
-	ASSERT(fh);
-	switch (fc_frame_payload_op(fp)) {
-	case ELS_LS_ACC:
-		fc_local_port_state_event(lp, FC_EV_ACC);
-		break;
-	default:
-		fc_local_port_state_event(lp, FC_EV_RJT);
-		break;
-	}
+	fc_local_port_enter_ready(lp);
 	fc_local_port_unlock_send(lp);
 	fc_frame_free(fp);
 }
 
 static void fc_local_port_enter_ready(struct fc_local_port *lp)
 {
-	ASSERT(fc_local_port_locked(lp));
+	fc_local_port_enter_state(lp, LOCAL_PORT_ST_READY);
 	sa_event_call_cancel(lp->fl_events, FC_EV_CLOSED);
 	sa_event_call_defer(lp->fl_events, FC_EV_READY);
 }
@@ -816,12 +793,12 @@ static void fc_local_port_enter_dns_stop(struct fc_local_port *lp)
 {
 	struct fc_sess *sess;
 
-	ASSERT(fc_local_port_locked(lp));
+	fc_local_port_enter_state(lp, LOCAL_PORT_ST_DNS_STOP);
 	sess = lp->fl_dns_sess;
 	if (sess) {
 		fc_sess_stop(sess);
 	} else {
-		fc_local_port_state_event(lp, FC_EV_CLOSED);
+		fc_local_port_enter_logo(lp);
 	}
 }
 
@@ -830,15 +807,10 @@ static void fc_local_port_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
 {
 	struct fc_local_port *lp = lp_arg;
 
-	ASSERT(lp);
+	fc_frame_free(fp);
 	fc_local_port_lock(lp);
-	if (fc_frame_payload_op(fp) == ELS_LS_ACC) {
-		fc_local_port_state_event(lp, FC_EV_ACC);
-	} else {
-		fc_local_port_state_event(lp, FC_EV_RJT);
-	}
+	fc_local_port_enter_init(lp);
 	fc_local_port_unlock_send(lp);
-	fc_frame_free(fp);
 }
 
 /*
@@ -854,6 +826,7 @@ static void fc_local_port_enter_logo(struct fc_local_port *lp)
 	/*
 	 * DNS session should be closed so we can release it here.
 	 */
+	fc_local_port_enter_state(lp, LOCAL_PORT_ST_LOGO);
 	sess = lp->fl_dns_sess;
 	if (sess) {
 		fc_sess_release(sess);
@@ -876,20 +849,9 @@ static void fc_local_port_enter_logo(struct fc_local_port *lp)
 	fc_local_port_els_send(lp, sp, fp);
 }
 
-/*
- * Log state transition messages.
- */
-static void fc_local_port_log(void *lp_arg, const char *msg)
-{
-	struct fc_local_port *lp = lp_arg;
-
-	OFC_DBG("local_port %6x %s", lp->fl_fid, msg);
-}
-
 int fc_local_port_table_create(struct fc_virt_fab *vp)
 {
 	struct sa_hash *hp;
-	struct sa_state_table *tp;
 
 	ASSERT(vp);
 	ASSERT(!vp->vf_lport_by_fid);
@@ -901,21 +863,7 @@ int fc_local_port_table_create(struct fc_virt_fab *vp)
 		return -1;
 	vp->vf_lport_by_fid = hp;
 	INIT_LIST_HEAD(&vp->vf_local_ports);
-	if (!fc_local_port_state_table) {
-
-		tp = sa_state_table_alloc("local_port",
-					  fc_local_port_state_desc);
 
-		if (!tp) {
-			sa_hash_destroy(hp);
-			vp->vf_lport_by_fid = NULL;
-			return -1;
-		}
-		fc_local_port_state_table = tp;
-		if (fc_local_port_debug)
-			sa_state_table_log(tp, fc_local_port_log);
-	}
-	fc_local_port_state_table_refcnt++;
 	return 0;
 }
 
@@ -923,12 +871,6 @@ void fc_local_port_table_destroy(struct fc_virt_fab *vp)
 {
 	ASSERT(list_empty(&vp->vf_local_ports));
 	sa_hash_destroy(vp->vf_lport_by_fid);
-	ASSERT(fc_local_port_state_table_refcnt > 0);
-	fc_local_port_state_table_refcnt--;
-	if (!fc_local_port_state_table_refcnt) {
-		sa_state_table_free(fc_local_port_state_table);
-		fc_local_port_state_table = NULL;
-	}
 }
 
 /*
@@ -1010,7 +952,6 @@ static void fc_local_port_set_fid_int(struct fc_local_port *lp, fc_fid_t fid)
 	struct fc_virt_fab *vf;
 
 	ASSERT(fc_local_port_locked(lp));
-
 	vf = lp->fl_vf;
 	if (lp->fl_fid != fid) {
 		if (fc_local_port_debug) {
@@ -1043,15 +984,9 @@ void fc_local_port_set_fid(struct fc_local_port *lp, fc_fid_t fid)
 		fc_local_port_set_fid_int(lp, fid);
 
 		if (fid != 0 && lp->fl_state == LOCAL_PORT_ST_INIT)
-			sa_state_table_enter(fc_local_port_state_table,
-					     &lp->fl_state,
-					     LOCAL_PORT_ST_READY,
-					     FC_EV_NONE, lp);
+			fc_local_port_enter_ready(lp);
 		else
-			sa_state_table_enter(fc_local_port_state_table,
-					     &lp->fl_state,
-					     LOCAL_PORT_ST_INIT,
-					     FC_EV_NONE, lp);
+			fc_local_port_enter_init(lp);
 	}
 	fc_local_port_unlock_send(lp);
 }
@@ -1170,7 +1105,7 @@ void fc_local_port_logon(struct fc_local_port *lp, sa_event_handler_t *cb,
 	fc_local_port_lock(lp);
 	lp->fl_logon_req = 1;
 	if (lp->fl_state == LOCAL_PORT_ST_INIT) {
-		fc_local_port_state_event(lp, FC_EV_START);
+		fc_local_port_enter_flogi(lp);
 	} else if (lp->fl_state == LOCAL_PORT_ST_READY) {
 		event = FC_EV_READY;
 	}
@@ -1186,7 +1121,26 @@ void fc_local_port_logoff(struct fc_local_port *lp)
 {
 	fc_local_port_lock(lp);
 	lp->fl_logon_req = 0;
-	fc_local_port_state_event(lp, FC_EV_STOP);
+	switch (lp->fl_state) {
+	case LOCAL_PORT_ST_NONE:
+	case LOCAL_PORT_ST_INIT:
+		break;
+	case LOCAL_PORT_ST_FLOGI:
+	case LOCAL_PORT_ST_LOGO:
+	case LOCAL_PORT_ST_RESET:
+		fc_local_port_enter_init(lp);
+		break;
+	case LOCAL_PORT_ST_DNS:
+	case LOCAL_PORT_ST_DNS_STOP:
+		fc_local_port_enter_logo(lp);
+		break;
+	case LOCAL_PORT_ST_REG_PN:
+	case LOCAL_PORT_ST_REG_FT:
+	case LOCAL_PORT_ST_SCR:
+	case LOCAL_PORT_ST_READY:
+		fc_local_port_enter_dns_stop(lp);
+		break;
+	}
 	fc_local_port_unlock_send(lp);
 }
 
@@ -1227,18 +1181,18 @@ static void fc_local_port_enter_init(struct fc_local_port *lp)
 	/*
 	 * Setting state RESET keeps fc_local_port_error() callbacks
 	 * by fc_exch_mgr_reset() from recursing on the lock.
-	 * It also prevents fc_sess_reset_list() from generating events.
+	 * It also causes fc_local_port_sess_event() to ignore events.
 	 * The lock is held for the duration of the time in RESET state.
 	 */
 	lp->fl_state = LOCAL_PORT_ST_RESET;
 	fc_exch_mgr_reset(lp->fl_vf->vf_exch_mgr, 0, 0);
 	fc_sess_reset_list(lp->fl_vf, &lp->fl_sess_list);
 	fc_local_port_set_fid_int(lp, 0);
-	lp->fl_state = LOCAL_PORT_ST_INIT;
+	fc_local_port_enter_state(lp, LOCAL_PORT_ST_INIT);
 	sa_event_call_cancel(lp->fl_events, FC_EV_READY);
 	sa_event_call_defer(lp->fl_events, FC_EV_CLOSED);
 	if (lp->fl_logon_req && fc_port_ready(lp->fl_port))
-		fc_local_port_state_event(lp, FC_EV_START);
+		fc_local_port_enter_flogi(lp);
 }
 
 /*
@@ -1250,8 +1204,7 @@ static void fc_local_port_enter_init(struct fc_local_port *lp)
 void fc_local_port_reset(struct fc_local_port *lp)
 {
 	fc_local_port_lock(lp);
-	sa_state_table_enter(fc_local_port_state_table, &lp->fl_state,
-			     LOCAL_PORT_ST_INIT, FC_EV_NONE, lp);
+	fc_local_port_enter_init(lp);
 	fc_local_port_unlock_send(lp);
 }
 
@@ -1658,28 +1611,29 @@ void fc_local_port_recv(struct fc_local_port *lp, struct fc_frame *fp)
  * Handle errors on local port requests.
  * Just put event into the state machine.
  * Don't get locks if in RESET state.
+ * The only events possible here so far are exchange TIMEOUT and CLOSED (reset).
  */
 static void fc_local_port_error(enum fc_event event, void *lp_arg)
 {
 	struct fc_local_port *lp = lp_arg;
 
-	if (lp->fl_state != LOCAL_PORT_ST_RESET) {
-		fc_local_port_lock(lp);
-		if (event == FC_EV_TIMEOUT) {
-			if (lp->fl_retry_count < lp->fl_retry_limit)
-				lp->fl_retry_count++;
-			else
-				event = FC_EV_RJT;
+ 	if (lp->fl_state == LOCAL_PORT_ST_RESET)
+ 		return;
+
+ 	fc_local_port_lock(lp);
+ 	if (event == FC_EV_TIMEOUT) {
+ 		if (lp->fl_retry_count < lp->fl_retry_limit) {
+ 			lp->fl_retry_count++;
+ 			fc_local_port_enter_retry(lp);
+ 		} else {
+ 			fc_local_port_enter_reject(lp);
+			
 		}
-		if (fc_local_port_debug)
-			OFC_DBG("event %x %s retries %d limit %d",
-			       event,
-			       sa_state_event_name(fc_local_port_state_table,
-						   event),
-			       lp->fl_retry_count, lp->fl_retry_limit);
-		fc_local_port_state_event(lp, event);
-		fc_local_port_unlock_send(lp);
 	}
+ 	if (fc_local_port_debug)
+ 		OFC_DBG("event %x retries %d limit %d",
+ 		       event, lp->fl_retry_count, lp->fl_retry_limit);
+ 	fc_local_port_unlock_send(lp);
 }
 
 static int fc_local_port_fid_match(const sa_hash_key_t key, void *lp_arg)
@@ -1709,7 +1663,7 @@ static void fc_local_port_port_event(int event, void *lp_arg)
 	case FC_EV_READY:
 		fc_local_port_lock(lp);
 		if (lp->fl_logon_req && lp->fl_state == LOCAL_PORT_ST_INIT)
-			fc_local_port_state_event(lp, FC_EV_START);
+			fc_local_port_enter_flogi(lp);
 		fc_local_port_unlock_send(lp);
 		break;
 
diff --git a/drivers/scsi/ofc/libfc/fc_sess.c b/drivers/scsi/ofc/libfc/fc_sess.c
index 8ac6811..11cd05e 100644
--- a/drivers/scsi/ofc/libfc/fc_sess.c
+++ b/drivers/scsi/ofc/libfc/fc_sess.c
@@ -33,7 +33,6 @@
 #include "sa_timer.h"
 #include "sa_event.h"
 #include "sa_hash.h"
-#include "sa_state.h"
 
 #include "fc_fs.h"
 #include "fc_els.h"
@@ -100,111 +99,6 @@ static void fc_sess_recv_logo_req(struct fc_sess *,
 				  struct fc_seq *, struct fc_frame *);
 static void fc_sess_delete(struct fc_sess *, void *);
 static void fc_sess_timeout(void *);
-static void fc_sess_state_event(struct fc_sess *, enum fc_event);
-
-/*
- * Session state transition table.
- */
-static const struct sa_state_desc fc_sess_state_desc[] = {
-	/*
-	 * Declare events.
-	 */
-	SA_STATE_EVENT(FC_EV_ACC),
-	SA_STATE_EVENT(FC_EV_RJT),
-	SA_STATE_EVENT(FC_EV_TIMEOUT),
-	SA_STATE_EVENT(FC_EV_READY),
-	SA_STATE_EVENT(FC_EV_DOWN),
-	SA_STATE_EVENT(FC_EV_CLOSED),
-	SA_STATE_EVENT(FC_EV_START),
-	SA_STATE_EVENT(FC_EV_STOP),
-
-	/*
-	 * Associate handlers for entering specific states.
-	 */
-	SA_STATE_HANDLER(SESS_ST_INIT, fc_sess_enter_init),
-	SA_STATE_HANDLER(SESS_ST_STARTED, fc_sess_enter_started),
-	SA_STATE_HANDLER(SESS_ST_PLOGI, fc_sess_enter_plogi),
-	SA_STATE_HANDLER(SESS_ST_PRLI, fc_sess_enter_prli),
-	SA_STATE_HANDLER(SESS_ST_RTV, fc_sess_enter_rtv),
-	SA_STATE_HANDLER(SESS_ST_READY, fc_sess_enter_ready),
-	SA_STATE_HANDLER(SESS_ST_LOGO, fc_sess_enter_logo),
-	SA_STATE_HANDLER(SESS_ST_RESTART, fc_sess_enter_logo),
-	SA_STATE_HANDLER(SESS_ST_ERROR, fc_sess_enter_error),
-
-	/*
-	 * Declare states and transitions.
-	 */
-	SA_STATE_NAME(SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_START, SESS_ST_STARTED),
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),	/* link down */
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),	/* received LOGO */
-	SA_STATE_NEXT(FC_EV_STOP, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_RJT, SESS_ST_INIT),
-
-	SA_STATE_NAME(SESS_ST_STARTED),	/* wait for local_port ready */
-	SA_STATE_NEXT(FC_EV_ACC, SESS_ST_PLOGI),
-	SA_STATE_NEXT(FC_EV_READY, SESS_ST_PLOGI),
-	SA_STATE_NEXT(FC_EV_STOP, SESS_ST_INIT),	/* TBD need handler */
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-
-	SA_STATE_NAME(SESS_ST_PLOGI),
-	SA_STATE_NEXT(FC_EV_ACC, SESS_ST_PRLI),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, SESS_ST_PLOGI),
-	SA_STATE_NEXT(FC_EV_RJT, SESS_ST_ERROR),
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-
-	SA_STATE_NAME(SESS_ST_PLOGI_RECV),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-
-	SA_STATE_NAME(SESS_ST_PRLI),
-	SA_STATE_NEXT(FC_EV_ACC, SESS_ST_RTV),
-	SA_STATE_NEXT(FC_EV_STOP, SESS_ST_LOGO),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, SESS_ST_PRLI),
-	SA_STATE_NEXT(FC_EV_RJT, SESS_ST_ERROR),
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-
-	SA_STATE_NAME(SESS_ST_RTV),
-	SA_STATE_NEXT(FC_EV_ACC, SESS_ST_READY),
-	SA_STATE_NEXT(FC_EV_STOP, SESS_ST_LOGO),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, SESS_ST_RTV),
-	SA_STATE_NEXT(FC_EV_RJT, SESS_ST_READY),
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-
-	SA_STATE_NAME(SESS_ST_READY),
-	SA_STATE_NEXT(FC_EV_STOP, SESS_ST_LOGO),
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-
-	SA_STATE_NAME(SESS_ST_LOGO),
-	SA_STATE_NEXT(FC_EV_ACC, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_STOP, SESS_ST_LOGO),
-
-	SA_STATE_NAME(SESS_ST_RESTART),
-	SA_STATE_NEXT(FC_EV_ACC, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_TIMEOUT, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_STOP, SESS_ST_INIT),
-
-	SA_STATE_NAME(SESS_ST_ERROR),
-	SA_STATE_NEXT(FC_EV_START, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_STOP, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_DOWN, SESS_ST_INIT),
-	SA_STATE_NEXT(FC_EV_CLOSED, SESS_ST_INIT),
-	SA_STATE_END
-};
-
-static struct sa_state_table *fc_sess_state_table;
-static u_int fc_sess_table_refcnt;
 
 /*
  * Lock session.
@@ -264,7 +158,7 @@ static inline void fc_sess_unlock_send(struct fc_sess *sess)
 			return;
 		}
 		if (state == SESS_ST_READY)
-			fc_sess_state_event(sess, FC_EV_STOP);
+			fc_sess_enter_logo(sess);
 	}
 
 	/*
@@ -284,33 +178,12 @@ static inline void fc_sess_unlock_send(struct fc_sess *sess)
 	fc_sess_release(sess);
 }
 
-/*
- * Handle next session state after a successful completion.
- */
-static void fc_sess_state_event(struct fc_sess *sess, enum fc_event event)
+static void fc_sess_state_enter(struct fc_sess *sess, enum fc_sess_state new)
 {
 	ASSERT(fc_sess_locked(sess));
-	if (event != FC_EV_TIMEOUT)
+ 	if (sess->fs_state != new)
 		sess->fs_retries = 0;
-	sa_state_table_step(fc_sess_state_table, &sess->fs_state, event, sess);
-}
-
-static void fc_sess_state_enter(struct fc_sess *sess,
-				enum fc_sess_state next_state)
-{
-	ASSERT(fc_sess_locked(sess));
-	sa_state_table_enter(fc_sess_state_table, &sess->fs_state,
-			     next_state, FC_EV_ACC, sess);
-}
-
-/*
- * Log state transition messages.
- */
-static void fc_sess_log(void *sess_arg, const char *msg)
-{
-	struct fc_sess *sess = sess_arg;
-
-	OFC_DBG("sess to %6x %s", sess->fs_remote_fid, msg);
+ 	sess->fs_state = new;
 }
 
 /*
@@ -321,21 +194,8 @@ int fc_sess_table_create(struct fc_virt_fab *vf)
 	struct sa_hash *tp;
 
 	tp = sa_hash_create(&fc_sess_hash_type, FC_SESS_HASH_SIZE);
-
 	if (!tp)
 		return -1;
-	if (!fc_sess_state_table) {
-		fc_sess_state_table =
-		    sa_state_table_alloc("session", fc_sess_state_desc);
-
-		if (!fc_sess_state_table) {
-			sa_hash_destroy(tp);
-			return -1;
-		}
-		if (fc_sess_debug)
-			sa_state_table_log(fc_sess_state_table, fc_sess_log);
-	}
-	fc_sess_table_refcnt++;
 	vf->vf_sess_by_fids = tp;
 	return 0;
 }
@@ -410,14 +270,7 @@ void fc_sess_table_destroy(struct fc_virt_fab *vf)
 	sa_hash_destroy(vf->vf_sess_by_fids);
 	vf->vf_sess_by_fids = NULL;
 	fc_virt_fab_unlock(vf);
-	ASSERT(fc_sess_state_table);
-	ASSERT(fc_sess_table_refcnt != 0);
-	fc_sess_table_refcnt--;
-	if (fc_sess_state_table && fc_sess_table_refcnt == 0) {
-		sa_state_table_free(fc_sess_state_table);
-		fc_sess_state_table = NULL;
-		synchronize_rcu();
-	}
+	synchronize_rcu();
 }
 
 /*
@@ -566,8 +419,10 @@ void fc_sess_start(struct fc_sess *sess)
 		sess->fs_started = 1;
 		fc_sess_hold(sess);	/* internal hold while active */
 	}
-	if (sess->fs_state == SESS_ST_INIT || sess->fs_state == SESS_ST_ERROR)
-		fc_sess_state_event(sess, FC_EV_START);
+	if (sess->fs_state == SESS_ST_INIT)
+		fc_sess_enter_started(sess);
+	else if (sess->fs_state == SESS_ST_ERROR)
+		fc_sess_enter_init(sess);
 	fc_sess_unlock_send(sess);
 }
 
@@ -577,7 +432,16 @@ void fc_sess_start(struct fc_sess *sess)
 void fc_sess_stop(struct fc_sess *sess)
 {
 	fc_sess_lock(sess);
-	fc_sess_state_event(sess, FC_EV_STOP);
+	switch (sess->fs_state) {
+	case SESS_ST_PRLI:
+	case SESS_ST_RTV:
+	case SESS_ST_READY:
+		fc_sess_enter_logo(sess);
+		break;
+	default:
+		fc_sess_enter_init(sess);
+		break;
+	}
 	fc_sess_unlock_send(sess);
 }
 
@@ -614,7 +478,7 @@ void fc_sess_reset(struct fc_sess *sess)
 		key = fc_sess_key(sess->fs_local_fid, sess->fs_remote_fid);
 		sa_hash_insert(vp->vf_sess_by_fids, &key, sess);
 	}
-	fc_sess_state_enter(sess, SESS_ST_INIT);
+	fc_sess_enter_init(sess);
 	fc_sess_unlock_send(sess);
 	if (started)
 		fc_sess_release(sess);
@@ -711,12 +575,18 @@ int fc_sess_send_req(struct fc_sess *sess, struct fc_frame *fp,
 	return rc;
 }
 
+/*
+ * Handle events from the local port.  These can be READY or CLOSED.
+ */
 static void fc_sess_local_port_event(int event, void *sess_arg)
 {
 	struct fc_sess *sess = sess_arg;
 
 	fc_sess_lock(sess);
-	fc_sess_state_event(sess, event);
+	if (event == FC_EV_READY && sess->fs_state == SESS_ST_STARTED)
+		fc_sess_enter_plogi(sess);
+	else if (event == FC_EV_CLOSED)
+		fc_sess_enter_init(sess);
 	fc_sess_unlock_send(sess);
 }
 
@@ -728,19 +598,68 @@ static void fc_sess_enter_started(struct fc_sess *sess)
 	 * If the local port is already logged on, advance to next state.
 	 * Otherwise the local port will be logged on by fc_sess_unlock().
 	 */
-	ASSERT(fc_sess_locked(sess));
-	ASSERT(sess->fs_state == SESS_ST_STARTED);
+	fc_sess_state_enter(sess, SESS_ST_STARTED);
 	lp = sess->fs_local_port;
 	if (sess == lp->fl_dns_sess || fc_local_port_test_ready(lp))
-		fc_sess_state_event(sess, FC_EV_ACC);
+		fc_sess_enter_plogi(sess);
 }
 
 /*
- * Timeout handler for retrying after allocation failures.
+ * Handle exchange reject or retry exhaustion in various states.
+ */
+static void fc_sess_reject(struct fc_sess *sess)
+{
+	switch (sess->fs_state) {
+	case SESS_ST_PLOGI:
+	case SESS_ST_PRLI:
+		fc_sess_enter_error(sess);
+		break;
+	case SESS_ST_RTV:
+		fc_sess_enter_ready(sess);
+		break;
+	case SESS_ST_LOGO:
+		fc_sess_enter_init(sess);
+		break;
+	case SESS_ST_NONE:
+	case SESS_ST_READY:
+	case SESS_ST_ERROR:
+	case SESS_ST_PLOGI_RECV:
+	case SESS_ST_STARTED:
+	case SESS_ST_INIT:
+		BUG();
+		break;
+	}
+}
+
+/*
+ * Timeout handler for retrying after allocation failures or exchange timeout.
  */
 static void fc_sess_timeout(void *sess_arg)
 {
-	fc_sess_state_event((struct fc_sess *)sess_arg, FC_EV_TIMEOUT);
+	struct fc_sess *sess = sess_arg;
+
+	switch (sess->fs_state) {
+	case SESS_ST_PLOGI:
+		fc_sess_enter_plogi(sess);
+		break;
+	case SESS_ST_PRLI:
+		fc_sess_enter_prli(sess);
+		break;
+	case SESS_ST_RTV:
+		fc_sess_enter_rtv(sess);
+		break;
+	case SESS_ST_LOGO:
+		fc_sess_enter_logo(sess);
+		break;
+	case SESS_ST_NONE:
+	case SESS_ST_READY:
+	case SESS_ST_ERROR:
+	case SESS_ST_PLOGI_RECV:
+	case SESS_ST_STARTED:
+	case SESS_ST_INIT:
+		BUG();
+		break;
+	}
 }
 
 /*
@@ -748,22 +667,19 @@ static void fc_sess_timeout(void *sess_arg)
  */
 static void fc_sess_retry(struct fc_sess *sess)
 {
-	const char *state;
 	struct fc_local_port *lp;
 
 	ASSERT(fc_sess_locked(sess));
-	state = sa_state_name(fc_sess_state_table, sess->fs_state);
+
 	lp = sess->fs_local_port;
-	if (sess->fs_retries == 0)
-		OFC_DBG("sess %6x alloc failure in state %s - will retry",
-		       sess->fs_remote_fid, state);
+
 	if (sess->fs_retries < lp->fl_retry_limit) {
 		sess->fs_retries++;
 		sa_timer_set(&sess->fs_timer, sess->fs_e_d_tov * 1000);
 	} else {
-		OFC_DBG("sess %6x alloc failure in state %s retries exhausted",
-						sess->fs_remote_fid, state);
-		fc_sess_state_event(sess, FC_EV_RJT);
+ 		OFC_DBG("sess %6x alloc failure in state %d - retries exhausted",
+			sess->fs_remote_fid, sess->fs_state);
+ 		fc_sess_reject(sess);
 	}
 }
 
@@ -775,14 +691,16 @@ static void fc_sess_error(enum fc_event event, void *sess_arg)
 	struct fc_sess *sess = sess_arg;
 
 	fc_sess_lock(sess);
+ 	if (fc_sess_debug)
+ 		OFC_DBG("state %d event %d retries %d",
+ 		       sess->fs_state, event, sess->fs_retries);
+
 	if (event == FC_EV_TIMEOUT &&
 	    sess->fs_retries++ >= sess->fs_local_port->fl_retry_limit)
-		event = FC_EV_RJT;
-	if (fc_sess_debug)
-		OFC_DBG("event %s retries %d",
-		       sa_state_event_name(fc_sess_state_table, event),
-		       sess->fs_retries);
-	fc_sess_state_event(sess_arg, event);
+ 		fc_sess_timeout(sess);
+ 	else
+ 		fc_sess_reject(sess);
+	
 	fc_sess_unlock_send(sess);
 }
 
@@ -818,21 +736,20 @@ static void fc_sess_plogi_recv_resp(struct fc_seq *sp, struct fc_frame *fp,
 		if (cssp_seq < csp_seq)
 			csp_seq = cssp_seq;
 		sess->fs_max_seq = csp_seq;
-		fc_sess_state_event(sess, FC_EV_ACC);
+		if (sess->fs_state == SESS_ST_PLOGI)
+ 			fc_sess_enter_prli(sess);
 	} else {
 		if (fc_sess_debug) {
 			OFC_DBG("bad PLOGI response");
 			fc_print_frame_hdr((char *)__FUNCTION__, fp);
 		}
+		
 		rjp = fc_frame_payload_get(fp, sizeof(*rjp));
-#if 0				/* XXX */
 		if (op == ELS_LS_RJT && rjp != NULL &&
 		    rjp->er_reason == ELS_RJT_INPROG)
-			fc_sess_state_event(sess, FC_EV_TIMEOUT);
-/* XXX not right either.   Should have a wait state ... retry after a bit. */
+			fc_sess_retry(sess);    /* try again in a while */
 		else
-#endif
-			fc_sess_state_event(sess, FC_EV_RJT);
+			fc_sess_reject(sess);   /* error */
 	}
 	fc_sess_unlock_send(sess);
 	fc_frame_free(fp);
@@ -847,6 +764,7 @@ static void fc_sess_enter_plogi(struct fc_sess *sess)
 	struct fc_els_flogi *rp;
 
 	ASSERT(fc_sess_locked(sess));
+	fc_sess_state_enter(sess, SESS_ST_PLOGI);
 	sess->fs_max_payload = sess->fs_local_port->fl_max_payload;
 	fp = fc_frame_alloc(sess->fs_local_port->fl_port, sizeof(*rp));
 	if (!fp) {
@@ -872,31 +790,38 @@ static void fc_sess_els_recv_resp(struct fc_seq *sp, struct fc_frame *fp,
 {
 	struct fc_sess *sess = sess_arg;
 	u_char op;
+	struct {
+		struct fc_els_prli prli;
+		struct fc_els_spp spp;
+	} *pp;
 
 	fc_sess_lock(sess);
 	op = fc_frame_payload_op(fp);
 	if (op == ELS_LS_ACC) {
-
 		/*
 		 * For PRLI, get the remote port's service parameter flags.
 		 */
-		if (sess->fs_state == SESS_ST_PRLI) {
-			struct {
-				struct fc_els_prli prli;
-				struct fc_els_spp spp;
-			} *pp;
-
+		switch (sess->fs_state) {
+ 		case SESS_ST_PRLI:
 			pp = fc_frame_payload_get(fp, sizeof(*pp));
 			if (pp && pp->prli.prli_spp_len >= sizeof(pp->spp)) {
 				sess->fs_remote_port->rp_fcp_parm =
-				    net32_get(&pp->spp.spp_params);
+					net32_get(&pp->spp.spp_params);
 			}
+			fc_sess_enter_rtv(sess);
+			break;
+		case SESS_ST_LOGO:
+			fc_sess_enter_rtv(sess);
+			break;
+		default:
+			OFC_DBG("ELS ACC in state %d ignored", sess->fs_state);
+			break;
 		}
-		fc_sess_state_event(sess, FC_EV_ACC);
+		
 	} else {
 		OFC_DBG("bad ELS response\n");
 		fc_print_frame_hdr((char *)__FUNCTION__, fp);	/* XXX */
-		fc_sess_state_event(sess, FC_EV_RJT);
+		fc_sess_enter_error(sess);
 	}
 	fc_sess_unlock_send(sess);
 	fc_frame_free(fp);
@@ -914,6 +839,7 @@ static void fc_sess_enter_prli(struct fc_sess *sess)
 	struct fc_frame *fp;
 
 	ASSERT(fc_sess_locked(sess));
+	fc_sess_state_enter(sess, SESS_ST_PRLI);
 
 	/*
 	 * Special case if session is for name server or any other
@@ -921,7 +847,7 @@ static void fc_sess_enter_prli(struct fc_sess *sess)
 	 * This should be made more general, possibly moved to the FCP layer.
 	 */
 	if (sess->fs_remote_fid >= FC_FID_DOM_MGR) {
-		fc_sess_state_enter(sess, SESS_ST_READY);
+		fc_sess_enter_ready(sess);
 		return;
 	}
 	fp = fc_frame_alloc(sess->fs_local_port->fl_port, sizeof(*pp));
@@ -976,10 +902,8 @@ static void fc_sess_els_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
 				tov = 1;
 			sess->fs_e_d_tov = tov;
 		}
-		fc_sess_state_event(sess, FC_EV_ACC);
-	} else {
-		fc_sess_state_event(sess, FC_EV_RJT);
 	}
+	fc_sess_enter_ready(sess);
 	fc_sess_unlock_send(sess);
 	fc_frame_free(fp);
 }
@@ -993,6 +917,7 @@ static void fc_sess_enter_rtv(struct fc_sess *sess)
 	struct fc_frame *fp;
 
 	ASSERT(fc_sess_locked(sess));
+	fc_sess_state_enter(sess, SESS_ST_RTV);
 
 	fp = fc_frame_alloc(sess->fs_local_port->fl_port, sizeof(*rtv));
 	if (!fp) {
@@ -1033,6 +958,7 @@ void fc_sess_event_deq(struct fc_sess *sess, sa_event_handler_t handler,
 static void fc_sess_enter_ready(struct fc_sess *sess)
 {
 	ASSERT(fc_sess_locked(sess));
+	fc_sess_state_enter(sess, SESS_ST_READY);
 	sa_event_call_cancel(sess->fs_events, FC_EV_CLOSED);
 	sa_event_call_cancel(sess->fs_events, FC_EV_RJT);
 	sa_event_call_defer(sess->fs_events, FC_EV_READY);
@@ -1041,6 +967,7 @@ static void fc_sess_enter_ready(struct fc_sess *sess)
 static void fc_sess_enter_init(struct fc_sess *sess)
 {
 	ASSERT(fc_sess_locked(sess));
+	fc_sess_state_enter(sess, SESS_ST_INIT);
 	sa_event_call_cancel(sess->fs_events, FC_EV_READY);
 	sa_event_call_cancel(sess->fs_events, FC_EV_RJT);
 	sa_event_call_defer(sess->fs_events, FC_EV_CLOSED);
@@ -1049,6 +976,7 @@ static void fc_sess_enter_init(struct fc_sess *sess)
 static void fc_sess_enter_error(struct fc_sess *sess)
 {
 	ASSERT(fc_sess_locked(sess));
+	fc_sess_state_enter(sess, SESS_ST_ERROR);
 	sa_event_call_cancel(sess->fs_events, FC_EV_READY);
 	sa_event_call_cancel(sess->fs_events, FC_EV_CLOSED);
 	sa_event_call_defer(sess->fs_events, FC_EV_RJT);
@@ -1061,6 +989,7 @@ static void fc_sess_enter_logo(struct fc_sess *sess)
 	struct fc_local_port *lp;
 
 	ASSERT(fc_sess_locked(sess));
+	fc_sess_state_enter(sess, SESS_ST_LOGO);
 	lp = sess->fs_local_port;
 	fp = fc_frame_alloc(lp->fl_port, sizeof(*logo));
 	if (!fp) {
@@ -1310,7 +1239,7 @@ static void fc_sess_recv_plogi_req(struct fc_sess *sess,
 		 */
 		fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS);
 		if (sess->fs_state == SESS_ST_PLOGI)
-			fc_sess_state_enter(sess, SESS_ST_PRLI);
+			fc_sess_enter_prli(sess);
 		else
 			fc_sess_state_enter(sess, SESS_ST_PLOGI_RECV);
 		fc_sess_hold(sess);	/* represents login */
@@ -1436,7 +1365,7 @@ static void fc_sess_recv_prli_req(struct fc_sess *sess,
 		switch (sess->fs_state) {
 		case SESS_ST_PLOGI_RECV:
 		case SESS_ST_PRLI:
-			fc_sess_state_enter(sess, SESS_ST_READY);
+			fc_sess_enter_ready(sess);
 			break;
 		case SESS_ST_READY:
 			break;
@@ -1473,15 +1402,10 @@ static void fc_sess_recv_logo_req(struct fc_sess *sess, struct fc_seq *sp,
 	u_int held;
 
 	fh = fc_frame_header_get(fp);
-	if (fc_sess_debug)
-		OFC_DBG("incoming LOGO from %x state %s %s",
-			net24_get(&fh->fh_s_id),
-			sa_state_name(fc_sess_state_table, sess->fs_state),
-			sess->fs_started ? "started" : "not started");
 	fc_sess_lock(sess);
-	fc_sess_state_event(sess, FC_EV_CLOSED);
 	held = sess->fs_plogi_held;
 	sess->fs_plogi_held = 0;
+	fc_sess_enter_init(sess);
 	fc_sess_unlock_send(sess);
 	if (held)
 		fc_sess_release(sess);
@@ -1545,69 +1469,3 @@ struct fc_sess *fc_sess_lookup_create(struct fc_local_port *lp,
 	}
 	return sess;
 }
-
-struct fc_sess_disp_arg {
-	char *da_buf;
-	size_t da_len;
-	size_t da_off;
-};
-
-/*
- * Print session state for debugging.
- */
-static void fc_sess_disp_one(struct fc_sess *sess, void *arg)
-{
-	struct fc_sess_disp_arg *ap = arg;
-	struct fc_local_port *lp;
-	struct fc_remote_port *rp;
-
-	lp = sess->fs_local_port;
-	rp = sess->fs_remote_port;
-	ASSERT(lp);
-	ASSERT(rp);
-	if (ap->da_off < ap->da_len) {
-		ap->da_off += snprintf(ap->da_buf + ap->da_off,
-				       ap->da_len - ap->da_off,
-				       "sess %u ref %u state %d %s\n"
-				       "\tlocal  fid %6x "
-				       "wwpn %16.16llx wwnn %16.16llx\n"
-				       "\tremote fid %6x "
-				       "wwpn %16.16llx wwnn %16.16llx\n",
-				       sess->fs_sess_id,
-				       atomic_read(&sess->fs_refcnt),
-				       sess->fs_state,
-				       sa_state_name(fc_sess_state_table,
-						     sess->fs_state),
-				       sess->fs_local_fid, lp->fl_port_wwn,
-				       lp->fl_node_wwn, sess->fs_remote_fid,
-				       rp->rp_port_wwn, rp->rp_node_wwn);
-	}
-}
-
-/*
- * Print session state for debugging.
- */
-size_t fc_sess_disp(struct fc_sess *sess, char *buf, size_t len)
-{
-	struct fc_sess_disp_arg arg;
-
-	arg.da_buf = buf;
-	arg.da_len = len;
-	arg.da_off = 0;
-	fc_sess_disp_one(sess, &arg);
-	return arg.da_off;
-}
-
-/*
- * Supply session states for entire virtual fabric for debugging.
- */
-size_t fc_sess_disp_all(struct fc_virt_fab *vf, char *buf, size_t len)
-{
-	struct fc_sess_disp_arg arg;
-
-	arg.da_buf = buf;
-	arg.da_len = len;
-	arg.da_off = 0;
-	fc_sess_iterate(vf, fc_sess_disp_one, &arg);
-	return arg.da_off;
-}
diff --git a/drivers/scsi/ofc/libfc/fc_sess_impl.h b/drivers/scsi/ofc/libfc/fc_sess_impl.h
index 2660f1a..37166fb 100644
--- a/drivers/scsi/ofc/libfc/fc_sess_impl.h
+++ b/drivers/scsi/ofc/libfc/fc_sess_impl.h
@@ -37,7 +37,6 @@ enum fc_sess_state {
 	SESS_ST_ERROR,		/* error */
 	SESS_ST_READY,		/* ready for use */
 	SESS_ST_LOGO,		/* port logout sent */
-	SESS_ST_RESTART,	/* restarting */
 };
 
 /*
diff --git a/drivers/scsi/ofc/libfc/fcs_state.c b/drivers/scsi/ofc/libfc/fcs_state.c
index d970ac9..794f440 100644
--- a/drivers/scsi/ofc/libfc/fcs_state.c
+++ b/drivers/scsi/ofc/libfc/fcs_state.c
@@ -108,11 +108,11 @@ struct fcs_state *fcs_create(struct fcs_create_args *ap)
 	outer_port = ap->fca_port;
 	mfs = fc_port_get_max_frame_size(outer_port);
 	if (mfs < FC_MIN_MAX_PAYLOAD) {
-		OFC_DBG("port max frame size only %d (0x%x) bytes - "
+		OFC_DBG("port max frame size only %zx (0x%zx) bytes - "
 		       "setting to %d", mfs, mfs, FC_MIN_MAX_PAYLOAD);
 		mfs = 1024;
 	} else if (mfs > FC_MAX_PAYLOAD + sizeof(struct fc_frame_header)) {
-		OFC_DBG("port max frame size too large: %d (0x%x) bytes\n",
+		OFC_DBG("port max frame size too large: %zx (0x%zx) bytes\n",
 		       mfs, mfs);
 		mfs = FC_MAX_PAYLOAD + sizeof(struct fc_frame_header);
 	}
diff --git a/drivers/scsi/ofc/libsa/Makefile b/drivers/scsi/ofc/libsa/Makefile
index 7f13291..42b8733 100644
--- a/drivers/scsi/ofc/libsa/Makefile
+++ b/drivers/scsi/ofc/libsa/Makefile
@@ -8,5 +8,4 @@ libsa-y := \
 	sa_assert.o \
 	sa_event.o \
 	sa_hash_kern.o \
-	sa_state.o \
 	sa_timer.o
diff --git a/drivers/scsi/ofc/libsa/sa_state.c b/drivers/scsi/ofc/libsa/sa_state.c
deleted file mode 100644
index 732d26d..0000000
--- a/drivers/scsi/ofc/libsa/sa_state.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright(c) 2007 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,
- * version 2, as published by the Free Software Foundation.
- * 
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- * 
- * Maintained at www.Open-FCoE.org
- */
-
-#include "sa_kernel.h"
-#include "sa_assert.h"
-#include "ofc_dbg.h"
-#include "sa_state.h"
-
-/*
- * Transition descriptor table size limit of 256 will allow the transition
- * table to contain just bytes.  A larger limit will make it twice as big.
- * Don't make this more than 65536.
- */
-#ifdef SA_STATE_DESC_LARGE	/* not usually defined */
-#define SA_STATE_DESC_LIMIT (1 << 16)	/* max fc_sess_desc table size */
-typedef u_int16_t sa_state_t;
-#else
-#define SA_STATE_DESC_LIMIT 256	/* max fc_sess_desc table size */
-typedef u_int8_t sa_state_t;
-#endif /* SA_STATE_DESC_LARGE */
-
-/*
- * State descriptor structure.
- */
-struct sa_state {
-	const char *st_name;	/* state name */
-	sa_state_handler_t *st_handler;	/* handler function if any */
-};
-
-/*
- * State transition table handling.
- */
-struct sa_state_table {
-	const char *st_name;	/* name of state table */
-	const struct sa_state_desc *st_desc;	/* condensed description */
-	uint st_desc_limit;	/* size of condensed desc. table */
-	void (*st_log_func) (void *, const char *);	/* log func */
-	u_short st_state_limit;	/* limit on state number */
-	u_short st_event_limit;	/* limit on event index */
-	struct sa_state *st_states;	/* array of state structures */
-	const char **st_event_name;
-
-	/*
-	 * Variable sized state table, indexed by state and event.
-	 */
-	sa_state_t st_next_table[0];
-
-	/*
-	 * Followed by array of struct sa_state
-	 * and then by event names pointers.
-	 */
-};
-
-/*
- * Return the transition table entry for state, event
- */
-static inline sa_state_t *sa_state_table_entry(struct sa_state_table *tp,
-					       u_int state, u_int event)
-{
-	sa_state_t *ep;
-
-	ASSERT(state < tp->st_state_limit);
-	ASSERT(event < tp->st_event_limit);
-
-	ep = &tp->st_next_table[state * tp->st_event_limit + event];
-	ASSERT(*ep < tp->st_desc_limit);
-	return ep;
-}
-
-/*
- * State transition table initialization.
- */
-struct sa_state_table *sa_state_table_alloc(const char *name,
-					    const struct sa_state_desc
-					    *state_desc)
-{
-	u_int state_limit = 0;
-	u_int event_limit = 0;
-	u_int cur_state = 0;
-	u_int desc;
-	int error = 0;
-	size_t len;
-	size_t table_size;
-	u_int event;
-	u_int state;
-	const struct sa_state_desc *dp;
-	struct sa_state_table *tp;
-	struct sa_state *sp;
-	sa_state_t *ep;
-
-	/*
-	 * Find the dimensions of the table we need.
-	 * Validate the table while we're at it.
-	 */
-	for (dp = state_desc; dp->sd_type != SST_END; dp++) {
-		switch (dp->sd_type) {
-		case SST_STATE:
-			if (dp->sd_in == 0) {
-				OFC_DBG("state table %s has invalid state %d "
-				       "at STATE entry %d",
-				       name, dp->sd_in, dp - state_desc);
-				error++;
-			}
-			if (dp->sd_in >= state_limit)
-				state_limit = dp->sd_in + 1;
-			cur_state = dp->sd_in;
-			break;
-		case SST_FROM:
-			if (dp->sd_in == 0) {
-				OFC_DBG("state table %s has invalid state %d "
-				       "at FROM entry %d",
-				       name, dp->sd_in, dp - state_desc);
-				error++;
-			}
-			cur_state = dp->sd_in;
-			break;
-		case SST_EVENT:
-			if (dp->sd_in == 0) {
-				OFC_DBG("state table %s has invalid event %d "
-				       "at EVENT entry %d",
-				       name, dp->sd_in, dp - state_desc);
-				error++;
-			}
-			if (dp->sd_in >= event_limit)
-				event_limit = dp->sd_in + 1;
-			break;
-		case SST_HANDLER:
-			if (dp->sd_ptr == NULL) {
-				OFC_DBG("state table %s has invalid hander %d "
-				       "at HANDLER entry %d",
-				       name, dp->sd_in, dp - state_desc);
-				error++;
-			}
-			if (dp->sd_in >= state_limit)
-				state_limit = dp->sd_in + 1;
-			break;
-		case SST_NEXT:
-			if (cur_state == 0) {
-				OFC_DBG("state table %s has no current state "
-				       "for NEXT entry %d",
-				       name, dp - state_desc);
-				error++;
-			}
-			if (dp->sd_in >= event_limit) {
-				OFC_DBG("state table %s has event %d "
-				       "out of range at NEXT entry %d",
-				       name, dp->sd_in, dp - state_desc);
-				error++;
-			}
-			if (dp->sd_next == 0 || dp->sd_next >= state_limit) {
-				OFC_DBG("state table %s has state %d "
-				       "out of range at NEXT entry %d",
-				       name, dp->sd_next, dp - state_desc);
-				error++;
-			}
-			break;
-		case SST_END:
-			break;
-		}
-	}
-
-	/*
-	 * Allocate the state transition table.
-	 */
-	if (error) {
-		tp = NULL;
-		goto out;
-	}
-	ASSERT_NOTIMPL(state_limit * event_limit <= SA_STATE_DESC_LIMIT);
-	table_size = state_limit * event_limit * sizeof(sa_state_t);
-	table_size = (table_size + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
-	len = sizeof(*tp) + table_size +
-	    state_limit * sizeof(struct sa_state) +
-	    event_limit * sizeof(char *);
-	tp = sa_malloc(len);
-	if (!tp)
-		goto out;
-	memset(tp, 0, len);
-	tp->st_name = name;
-	tp->st_desc = state_desc;
-	tp->st_desc_limit = (uint) (dp - state_desc);
-	ASSERT_NOTIMPL(tp->st_desc_limit <= SA_STATE_DESC_LIMIT);
-	tp->st_state_limit = (u_short) state_limit;
-	tp->st_event_limit = (u_short) event_limit;
-	ep = (sa_state_t *) (tp + 1);
-	tp->st_event_name = (const char **)(ep + table_size / sizeof(*ep));
-	tp->st_states = (struct sa_state *)(tp->st_event_name + event_limit);
-	ASSERT(len == (char *)(tp->st_states + state_limit) - (char *)tp);
-	cur_state = 0;
-
-	/*
-	 * Set up the big table from the compact descriptor table.
-	 */
-	for (dp = state_desc, desc = 0; dp->sd_type != SST_END; dp++, desc++) {
-		switch (dp->sd_type) {
-		case SST_STATE:
-			cur_state = dp->sd_in;
-			ASSERT(cur_state < state_limit);
-			sp = &tp->st_states[cur_state];
-			sp->st_name = dp->sd_ptr;
-			break;
-		case SST_EVENT:
-			ASSERT(dp->sd_in < event_limit);
-			tp->st_event_name[dp->sd_in] = dp->sd_ptr;
-			break;
-		case SST_HANDLER:
-			cur_state = dp->sd_in;
-			ASSERT(cur_state < state_limit);
-			sp = &tp->st_states[cur_state];
-			sp->st_handler =
-			    (/*const */ sa_state_handler_t *) dp->sd_ptr;
-			break;
-		case SST_FROM:
-			ASSERT(dp->sd_in < state_limit);
-			cur_state = dp->sd_in;
-			break;
-		case SST_NEXT:
-			ASSERT(dp->sd_next < state_limit);
-			ASSERT(desc <= SA_STATE_DESC_LIMIT);
-			ep = sa_state_table_entry(tp, cur_state, dp->sd_in);
-			*ep = (sa_state_t) desc;
-			break;
-		case SST_END:
-			break;
-		}
-	}
-
-	/*
-	 * Go through the names entries and make sure none are NULL.
-	 */
-	tp->st_event_name[0] = "none";
-	for (event = 0; event < event_limit; event++)
-		ASSERT(tp->st_event_name[event] != NULL);
-	tp->st_states[0].st_name = "none";
-	for (state = 0; state < state_limit; state++)
-		ASSERT(tp->st_states[state].st_name != NULL);
-out:
-	return tp;
-}
-
-/*
- * Free state table.
- */
-void sa_state_table_free(struct sa_state_table *tp)
-{
-	sa_free(tp);
-}
-
-/*
- * Get an event name.
- */
-const char *sa_state_event_name(struct sa_state_table *tp, u_int event)
-{
-	ASSERT(event < tp->st_event_limit);
-	return tp->st_event_name[event];
-}
-
-/*
- * Get a state name.
- */
-const char *sa_state_name(struct sa_state_table *tp, u_int state)
-{
-	ASSERT(state < tp->st_state_limit);
-	return tp->st_states[state].st_name;
-}
-
-/*
- * Run a step of the state transition table.
- */
-void
-sa_state_table_step(struct sa_state_table *tp, void *statep_arg,
-		    u_int event, void *arg)
-{
-	u_int *statep = statep_arg;
-	u_int old_state;
-	u_int next;
-	sa_state_t entry;
-	const struct sa_state_desc *np;
-	sa_state_handler_t *handler;
-
-	old_state = *statep;
-	ASSERT(old_state < tp->st_state_limit);
-	ASSERT(event < tp->st_event_limit);
-
-	next = 0;
-	handler = NULL;
-	entry = *sa_state_table_entry(tp, old_state, event);
-	if (entry) {
-		np = &tp->st_desc[entry];
-		ASSERT(np->sd_type == SST_NEXT);
-		next = np->sd_next;
-		ASSERT(next < tp->st_state_limit);
-		handler = (sa_state_handler_t *) np->sd_ptr;
-	}
-	if (handler) {
-		(*handler) (arg, next, event);
-	} else if (next != 0) {
-		sa_state_table_enter(tp, statep, next, event, arg);
-	} else {
-		OFC_DBG("state_table %s state %s (%d) "
-		       "event %s (%d) has no handler",
-		       tp->st_name, tp->st_states[old_state].st_name,
-		       old_state, tp->st_event_name[event], event);
-		if (tp->st_log_func) {
-			char buf[128];
-
-			snprintf(buf, sizeof(buf),
-				 "state %s (%d) event %s (%d) has no handler",
-				 tp->st_states[old_state].st_name,
-				 old_state, tp->st_event_name[event], event);
-			(*tp->st_log_func) (arg, buf);
-		}
-	}
-}
-
-/*
- * Transition to the specified state.  Run the handler if any.
- */
-void
-sa_state_table_enter(struct sa_state_table *tp, void *statep_arg,
-		     u_int next, u_int event, void *arg)
-{
-	u_int *statep = statep_arg;
-	u_int old_state;
-	sa_state_handler_t *handler;
-	struct sa_state *sp;
-
-	old_state = *statep;
-	ASSERT(old_state < tp->st_state_limit);
-	ASSERT(next < tp->st_state_limit);
-
-	sp = &tp->st_states[next];
-	if (tp->st_log_func != NULL) {
-		char buf[128];
-
-		snprintf(buf, sizeof(buf), "event %s state %s -> %s",
-			 tp->st_event_name[event],
-			 tp->st_states[old_state].st_name, sp->st_name);
-		(*tp->st_log_func) (arg, buf);
-	}
-	*statep = next;
-	handler = sp->st_handler;
-	if (handler)
-		(*handler) (arg, next, event);
-}
-
-/*
- * sa_state_table_log() - set function to log state table transitions.
- */
-void
-sa_state_table_log(struct sa_state_table *tp,
-		   void (*log_func) (void *arg, const char *msg))
-{
-	tp->st_log_func = log_func;
-}


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2008-01-12  0:50 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-12  0:17 [PATCH] [FCoE] Removal of state machine transition abstraction layer 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.