Part of effort to remove libsa.

Signed-off-by: Robert Love <[EMAIL PROTECTED]>
---

 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;
-}

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to