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