1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at
9 * http://www.opensource.org/licenses/cddl1.txt.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 2004-2012 Emulex. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <emlxs.h>
28
29/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30EMLXS_MSG_DEF(EMLXS_FCF_C);
31
32/*
33 * STATE MACHINE RULES:
34 *
35 * - State change requests to an XXXX object when operating within
36 * an emlxs_XXXX state management function must be made
37 * using the emlxs_XXXX_state() call.
38 *
39 * - State change requests to an XXXX object when operating outside
40 * an emlxs_XXXX state management function must be made
41 * using the emlxs_XXXX_alloc(), emlxs_XXXX_free(), emlxs_XXXX_event()
42 * or emlxs_XXXX_..._notify() calls.
43 *
44 * - emlxs_XXXX_..._notify() calls are used by routines outside
45 * this fcf module to enter the state machine.
46 *
47 * - It is forbidden to make direct calls to emlxs_XXXX_...._action()
48 * functions.  Only emlxs_XXXX_action() routines may make calls to
49 * emlxs_XXXX_...._action() functions.
50 *
51 * - Its is forbidden to make direct calls to emlxs_XXXX_action().
52 * Only emlxs_XXXX_state() and emlxs_XXXX_event() routines may make
53 * calls to emlxs_XXXX_action().
54 *
55 * - The EMLXS_FCF_LOCK must be held before calling:
56 * emlxs_XXXX_state(), emlxs_XXXX_event() and emlxs_XXXX_action().
57 *
58 * - All other calls touching fcftab, fcfi, vfi, vpi, rpi objects
59 * must hold the EMLXS_FCF_LOCK to protect these objects.
60 */
61
62/*
63 * DEBUG MESSAGE TERMINATION RULES:
64 *
65 * - A message should end in ">" if a thread operating outside the
66 * XXXX state machine enters the XXXX state machine with a call to
67 * emlxs_XXXX_event() or emlxs_XXXX_state().  This includes calls made
68 * from emlxs_..._notify(), emlxs_..._mbcmpl() and emlxs_..._timer()
69 * routines since they represent the beginnning of new threads.
70 *
71 * - A message should end in "<" if the thread is about exit
72 * an emlxs_XXXX_..._action() without previously calling the
73 * next emlxs_XXXX_state().  This includes the emlxs_XXXX_action()
74 * and emlxs_XXXX_state() routines themselves since errors
75 * in these routines represent the termination of state change
76 * thread.
77 *
78 * - A message should end in "." if none of the previous
79 * conditions apply.
80 */
81
82/* ************************************************************************** */
83/* FCF Generic */
84/* ************************************************************************** */
85
86/*
87 * EVENT			ARG1
88 * --------------------------------------------
89 * FCF_EVENT_STATE_ENTER	None
90 *
91 * FCF_EVENT_LINKUP		None
92 * FCF_EVENT_LINKDOWN		None
93 * FCF_EVENT_CVL		vpi
94 * FCF_EVENT_FCFTAB_FULL	None
95 * FCF_EVENT_FCF_FOUND		fcf_index
96 * FCF_EVENT_FCF_LOST		fcf_index
97 * FCF_EVENT_FCF_CHANGED	fcf_index
98 *
99 * FCF_EVENT_FCFI_ONLINE	FCFIobj_t*
100 * FCF_EVENT_FCFI_OFFLINE	FCFIobj_t*
101 * FCF_EVENT_FCFI_PAUSE		FCFIobj_t*
102 *
103 * FCF_EVENT_VFI_ONLINE		VFIobj_t*
104 * FCF_EVENT_VFI_OFFLINE	VFIobj_t*
105 * FCF_EVENT_VFI_PAUSE		VFIobj_t*
106 *
107 * FCF_EVENT_VPI_ONLINE		VPIobj_t*
108 * FCF_EVENT_VPI_OFFLINE	VPIobj_t*
109 * FCF_EVENT_VPI_PAUSE		VPIobj_t*
110 *
111 * FCF_EVENT_RPI_ONLINE		RPIobj_t*
112 * FCF_EVENT_RPI_OFFLINE	RPIobj_t*
113 * FCF_EVENT_RPI_PAUSE		RPIobj_t*
114 * FCF_EVENT_RPI_RESUME		RPIobj_t*
115 * FCF_EVENT_RPI_TIMEOUT	RPIobj_t*
116 */
117
118/* Order does not matter */
119emlxs_table_t emlxs_fcf_event_table[] =
120{
121	{FCF_EVENT_STATE_ENTER, "E_ENTER"},
122
123	{FCF_EVENT_SHUTDOWN, "E_SHUTDOWN"},
124	{FCF_EVENT_LINKUP, "E_LINKUP"},
125	{FCF_EVENT_LINKDOWN, "E_LINKDOWN"},
126	{FCF_EVENT_CVL, "E_CVL"},
127	{FCF_EVENT_FCFTAB_FULL, "E_TABLE_FULL"},
128	{FCF_EVENT_FCF_FOUND, "E_FCF_FOUND"},
129	{FCF_EVENT_FCF_LOST, "E_FCF_LOST"},
130	{FCF_EVENT_FCF_CHANGED, "E_FCF_CHANGED"},
131
132	{FCF_EVENT_FCFI_ONLINE, "E_FCFI_ONLINE"},
133	{FCF_EVENT_FCFI_OFFLINE, "E_FCFI_OFFLINE"},
134	{FCF_EVENT_FCFI_PAUSE, "E_FCFI_PAUSE"},
135
136	{FCF_EVENT_VFI_ONLINE, "E_VFI_ONLINE"},
137	{FCF_EVENT_VFI_OFFLINE, "E_VFI_OFFLINE"},
138	{FCF_EVENT_VFI_PAUSE, "E_VFI_PAUSE"},
139
140	{FCF_EVENT_VPI_ONLINE, "E_VPI_ONLINE"},
141	{FCF_EVENT_VPI_OFFLINE, "E_VPI_OFFLINE"},
142	{FCF_EVENT_VPI_PAUSE, "E_VPI_PAUSE"},
143
144	{FCF_EVENT_RPI_ONLINE, "E_RPI_ONLINE"},
145	{FCF_EVENT_RPI_OFFLINE, "E_RPI_OFFLINE"},
146	{FCF_EVENT_RPI_PAUSE, "E_RPI_PAUSE"},
147	{FCF_EVENT_RPI_RESUME, "E_RPI_RESUME"},
148
149}; /* emlxs_fcf_event_table */
150
151
152/* Order does not matter */
153emlxs_table_t emlxs_fcf_reason_table[] =
154{
155	{FCF_REASON_NONE, "R_NONE"},
156	{FCF_REASON_REENTER, "R_REENTER"},
157	{FCF_REASON_EVENT, "R_EVENT"},
158	{FCF_REASON_REQUESTED, "R_REQUESTED"},
159	{FCF_REASON_NO_MBOX, "R_NO_MBOX"},
160	{FCF_REASON_NO_BUFFER, "R_NO_BUFFER"},
161	{FCF_REASON_SEND_FAILED, "R_SEND_FAILED"},
162	{FCF_REASON_MBOX_FAILED, "R_MBOX_FAILED"},
163	{FCF_REASON_MBOX_BUSY, "R_MBOX_BUSY"},
164	{FCF_REASON_NO_FCFI, "R_NO_FCFI"},
165	{FCF_REASON_NO_VFI, "R_NO_VFI"},
166	{FCF_REASON_ONLINE_FAILED, "R_ONLINE_FAILED"},
167	{FCF_REASON_OFFLINE_FAILED, "R_OFFLINE_FAILED"},
168	{FCF_REASON_OP_FAILED, "R_OP_FAILED"},
169	{FCF_REASON_NO_PKT, "R_NO_PKT"},
170	{FCF_REASON_NO_NODE, "R_NO_NODE"},
171	{FCF_REASON_NOT_ALLOWED, "R_NOT_ALLOWED"},
172	{FCF_REASON_UNUSED, "R_UNUSED"},
173	{FCF_REASON_INVALID, "R_INVALID"},
174
175}; /* emlxs_fcf_reason_table */
176
177
178/* ********************************************************************** */
179/* FCFTAB Generic */
180/* ********************************************************************** */
181static char 		*emlxs_fcftab_state_xlate(emlxs_port_t *port,
182				uint32_t state);
183static uint32_t		emlxs_fcftab_event(emlxs_port_t *port, uint32_t evt,
184				void *arg1);
185static uint32_t		emlxs_fcftab_shutdown_action(emlxs_port_t *port,
186				uint32_t evt, void *arg1);
187
188/* ********************************************************************** */
189/* FC FCFTAB */
190/* ********************************************************************** */
191
192/* Order does not matter */
193emlxs_table_t emlxs_fc_fcftab_state_table[] =
194{
195	{FC_FCFTAB_STATE_SHUTDOWN, "FCFTAB_SHUTDOWN"},
196	{FC_FCFTAB_STATE_OFFLINE, "FCFTAB_OFFLINE"},
197
198	{FC_FCFTAB_STATE_TOPO, "FCFTAB_TOPO"},
199	{FC_FCFTAB_STATE_TOPO_FAILED, "FCFTAB_TOPO_FAILED"},
200	{FC_FCFTAB_STATE_TOPO_CMPL, "FCFTAB_TOPO_CMPL"},
201
202	{FC_FCFTAB_STATE_CFGLINK, "FCFTAB_CFGLINK"},
203	{FC_FCFTAB_STATE_CFGLINK_FAILED, "FCFTAB_CFGLINK_FAILED"},
204	{FC_FCFTAB_STATE_CFGLINK_CMPL, "FCFTAB_CFGLINK_CMPL"},
205
206	{FC_FCFTAB_STATE_SPARM, "FCFTAB_SPARM"},
207	{FC_FCFTAB_STATE_SPARM_FAILED, "FCFTAB_SPARM_FAILED"},
208	{FC_FCFTAB_STATE_SPARM_CMPL, "FCFTAB_SPARM_CMPL"},
209
210	{FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
211	    "FCFTAB_FCFI_OFFLINE_CMPL"},
212	{FC_FCFTAB_STATE_FCFI_OFFLINE, "FCFTAB_FCFI_OFFLINE"},
213
214	{FC_FCFTAB_STATE_FCFI_ONLINE, "FCFTAB_FCFI_ONLINE"},
215	{FC_FCFTAB_STATE_FCFI_ONLINE_CMPL, "FCFTAB_FCFI_ONLINE_CMPL"},
216
217	{FC_FCFTAB_STATE_ONLINE, "FCFTAB_ONLINE"},
218
219}; /* emlxs_fc_fcftab_state_table */
220
221static void emlxs_fc_fcftab_online_timer(emlxs_hba_t *hba);
222
223static uint32_t emlxs_fc_fcftab_offline_action(emlxs_port_t *port,
224			uint32_t evt, void *arg1);
225static uint32_t emlxs_fc_fcftab_online_action(emlxs_port_t *port,
226			uint32_t evt, void *arg1);
227
228static uint32_t emlxs_fc_fcftab_topo_cmpl_action(emlxs_port_t *port,
229			uint32_t evt, void *arg1);
230static uint32_t emlxs_fc_fcftab_topo_failed_action(emlxs_port_t *port,
231			uint32_t evt, void *arg1);
232static uint32_t emlxs_fc_fcftab_topo_action(emlxs_port_t *port,
233			uint32_t evt, void *arg1);
234
235static uint32_t emlxs_fc_fcftab_cfglink_cmpl_action(emlxs_port_t *port,
236			uint32_t evt, void *arg1);
237static uint32_t emlxs_fc_fcftab_cfglink_failed_action(emlxs_port_t *port,
238			uint32_t evt, void *arg1);
239static uint32_t emlxs_fc_fcftab_cfglink_action(emlxs_port_t *port,
240			uint32_t evt, void *arg1);
241
242static uint32_t emlxs_fc_fcftab_sparm_cmpl_action(emlxs_port_t *port,
243			uint32_t evt, void *arg1);
244static uint32_t emlxs_fc_fcftab_sparm_failed_action(emlxs_port_t *port,
245			uint32_t evt, void *arg1);
246static uint32_t emlxs_fc_fcftab_sparm_action(emlxs_port_t *port,
247			uint32_t evt, void *arg1);
248
249static uint32_t emlxs_fc_fcftab_linkup_evt_action(emlxs_port_t *port,
250			uint32_t evt, void *arg1);
251static uint32_t emlxs_fc_fcftab_linkdown_evt_action(emlxs_port_t *port,
252			uint32_t evt, void *arg1);
253
254static uint32_t emlxs_fc_fcftab_fcfi_online_evt_action(emlxs_port_t *port,
255			uint32_t evt, void *arg1);
256static uint32_t emlxs_fc_fcftab_fcfi_offline_evt_action(emlxs_port_t *port,
257			uint32_t evt, void *arg1);
258
259static uint32_t emlxs_fc_fcftab_shutdown_evt_action(emlxs_port_t *port,
260			uint32_t evt, void *arg1);
261static uint32_t emlxs_fc_fcftab_fcfi_offline_action(emlxs_port_t *port,
262			uint32_t evt, void *arg1);
263static uint32_t emlxs_fc_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port,
264			uint32_t evt, void *arg1);
265static uint32_t emlxs_fc_fcftab_fcfi_online_action(emlxs_port_t *port,
266			uint32_t evt, void *arg1);
267static uint32_t emlxs_fc_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port,
268			uint32_t evt, void *arg1);
269
270static char *emlxs_fc_fcftab_state_xlate(uint32_t state);
271static uint32_t emlxs_fc_fcftab_event(emlxs_port_t *port,
272			uint32_t evt, void *arg1);
273static uint32_t emlxs_fc_fcftab_req_handler(emlxs_port_t *port, void *arg1);
274
275/*
276 * - Online sequencing can start from FC_FCFTAB_STATE_OFFLINE state
277 *
278 * - Offline sequencing can interrupt the online sequencing at the
279 * entry of the next wait state.
280 *
281 * NORMAL ONLINE SEQ
282 * ---------------------------
283 * LINK_UP event <-- Adapter
284 * FC_FCFTAB_STATE_OFFLINE
285 * FC_FCFTAB_STATE_TOPO
286 *     FC_FCFTAB_STATE_TOPO_CMPL
287 * FC_FCFTAB_STATE_CFGLINK
288 *     FC_FCFTAB_STATE_CFGLINK_CMPL
289 * FC_FCFTAB_STATE_SPARM
290 *     FC_FCFTAB_STATE_SPARM_CMPL
291 * FC_FCFTAB_STATE_FCFI_ONLINE
292 *     FC_FCFTAB_STATE_FCFI_ONLINE_CMPL
293 * FC_FCFTAB_STATE_ONLINE
294 *
295 *
296 * NORMAL OFFLINE SEQ
297 * ---------------------------
298 * LINK_DOWN event <-- Adapter
299 * FC_FCFTAB_STATE_ONLINE
300 * FC_FCFTAB_STATE_FCFI_OFFLINE
301 *     FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL
302 * FC_FCFTAB_STATE_OFFLINE
303 *
304 */
305/* Order does matter */
306static void *emlxs_fc_fcftab_action_table[] =
307{
308	/* Action routine				Event */
309/* FC_FCFTAB_STATE_SHUTDOWN  0			(Requires adapter reset) */
310	(void *) emlxs_fcftab_shutdown_action,		/* STATE_ENTER */
311	(void *) NULL,					/* SHUTDOWN */
312	(void *) NULL,					/* LINK_UP */
313	(void *) NULL,					/* LINK_DOWN */
314	(void *) NULL,					/* FCFI_ONLINE */
315	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
316
317/* FC_FCFTAB_STATE_OFFLINE  1			(Wait for LINK_UP event) */
318	(void *) emlxs_fc_fcftab_offline_action,	/* STATE_ENTER */
319	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
320	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
321	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
322	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
323	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
324
325
326/* FC_FCFTAB_STATE_TOPO  2			(Wait for topo mbcmpl) */
327	(void *) emlxs_fc_fcftab_topo_action,		/* STATE_ENTER */
328	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
329	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
330	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
331	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
332	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
333
334/* FC_FCFTAB_STATE_TOPO_FAILED  3		(Transitional) */
335	(void *) emlxs_fc_fcftab_topo_failed_action,	/* STATE_ENTER */
336	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
337	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
338	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
339	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
340	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
341
342/* FC_FCFTAB_STATE_TOPO_CMPL  4			(Transitional) */
343	(void *) emlxs_fc_fcftab_topo_cmpl_action,	/* STATE_ENTER */
344	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
345	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
346	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
347	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
348	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
349
350
351/* FC_FCFTAB_STATE_CFGLINK  5			(Wait for cfglink mbcmpl) */
352	(void *) emlxs_fc_fcftab_cfglink_action,	/* STATE_ENTER */
353	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
354	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
355	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
356	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
357	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
358
359/* FC_FCFTAB_STATE_CFGLINK_FAILED  6		(Transitional) */
360	(void *) emlxs_fc_fcftab_cfglink_failed_action,	/* STATE_ENTER */
361	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
362	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
363	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
364	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
365	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
366
367/* FC_FCFTAB_STATE_CFGLINK_CMPL  7			(Transitional) */
368	(void *) emlxs_fc_fcftab_cfglink_cmpl_action,	/* STATE_ENTER */
369	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
370	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
371	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
372	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
373	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
374
375
376/* FC_FCFTAB_STATE_SPARM  8			(Wait for sparm mbcmpl) */
377	(void *) emlxs_fc_fcftab_sparm_action,		/* STATE_ENTER */
378	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
379	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
380	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
381	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
382	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
383
384/* FC_FCFTAB_STATE_SPARM_FAILED  9		(Transitional) */
385	(void *) emlxs_fc_fcftab_sparm_failed_action,	/* STATE_ENTER */
386	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
387	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
388	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
389	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
390	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
391
392/* FC_FCFTAB_STATE_SPARM_CMPL  10		(Transitional) */
393	(void *) emlxs_fc_fcftab_sparm_cmpl_action,	/* STATE_ENTER */
394	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
395	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
396	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
397	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
398	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
399
400
401/* FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL  11	(Transitional) */
402	(void *) emlxs_fc_fcftab_fcfi_offline_cmpl_action, /* STATE_ENTER */
403	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
404	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
405	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
406	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
407	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
408
409/* FC_FCFTAB_STATE_FCFI_OFFLINE  12		(Wait for FCFI_OFFLINE event) */
410	(void *) emlxs_fc_fcftab_fcfi_offline_action,	/* STATE_ENTER */
411	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
412	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
413	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
414	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
415	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
416
417
418/* FC_FCFTAB_STATE_FCFI_ONLINE  13		(Wait for FCFI_ONLINE event) */
419	(void *) emlxs_fc_fcftab_fcfi_online_action,	/* STATE_ENTER */
420	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
421	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
422	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
423	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
424	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
425
426/* FC_FCFTAB_STATE_FCFI_ONLINE_CMPL  14		(Transitional) */
427	(void *) emlxs_fc_fcftab_fcfi_online_cmpl_action, /* STATE_ENTER */
428	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
429	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
430	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
431	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
432	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
433
434
435/* FC_FCFTAB_STATE_ONLINE  15			(Wait for LINK_DOWN evt) */
436	(void *) emlxs_fc_fcftab_online_action,		/* STATE_ENTER */
437	(void *) emlxs_fc_fcftab_shutdown_evt_action,	/* SHUTDOWN */
438	(void *) emlxs_fc_fcftab_linkup_evt_action,	/* LINK_UP */
439	(void *) emlxs_fc_fcftab_linkdown_evt_action,	/* LINK_DOWN */
440	(void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
441	(void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
442
443}; /* emlxs_fc_fcftab_action_table[] */
444#define	FC_FCFTAB_ACTION_EVENTS			6
445#define	FC_FCFTAB_ACTION_STATES			\
446	(sizeof (emlxs_fc_fcftab_action_table)/ \
447	(FC_FCFTAB_ACTION_EVENTS * sizeof (void *)))
448
449
450/* ********************************************************************** */
451/* FCOE FCFTAB */
452/* ********************************************************************** */
453
454/* Order does not matter */
455emlxs_table_t emlxs_fcoe_fcftab_state_table[] =
456{
457	{FCOE_FCFTAB_STATE_SHUTDOWN, "FCFTAB_SHUTDOWN"},
458	{FCOE_FCFTAB_STATE_OFFLINE, "FCFTAB_OFFLINE"},
459
460	{FCOE_FCFTAB_STATE_SOLICIT, "FCFTAB_SOLICIT"},
461	{FCOE_FCFTAB_STATE_SOLICIT_FAILED, "FCFTAB_SOLICIT_FAILED"},
462	{FCOE_FCFTAB_STATE_SOLICIT_CMPL, "FCFTAB_SOLICIT_CMPL"},
463
464	{FCOE_FCFTAB_STATE_READ, "FCFTAB_READ"},
465	{FCOE_FCFTAB_STATE_READ_FAILED, "FCFTAB_READ_FAILED"},
466	{FCOE_FCFTAB_STATE_READ_CMPL, "FCFTAB_READ_CMPL"},
467
468	{FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
469	    "FCFTAB_FCFI_OFFLINE_CMPL"},
470	{FCOE_FCFTAB_STATE_FCFI_OFFLINE, "FCFTAB_FCFI_OFFLINE"},
471
472	{FCOE_FCFTAB_STATE_FCFI_ONLINE, "FCFTAB_FCFI_ONLINE"},
473	{FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL,
474	    "FCFTAB_FCFI_ONLINE_CMPL"},
475
476	{FCOE_FCFTAB_STATE_ONLINE, "FCFTAB_ONLINE"},
477
478}; /* emlxs_fcoe_fcftab_state_table */
479
480static uint32_t emlxs_fcoe_fcftab_sol_cmpl_action(emlxs_port_t *port,
481			uint32_t evt, void *arg1);
482static uint32_t emlxs_fcoe_fcftab_sol_failed_action(emlxs_port_t *port,
483			uint32_t evt, void *arg1);
484static uint32_t emlxs_fcoe_fcftab_sol_action(emlxs_port_t *port,
485			uint32_t evt, void *arg1);
486static uint32_t emlxs_fcoe_fcftab_shutdown_evt_action(emlxs_port_t *port,
487			uint32_t evt, void *arg1);
488static uint32_t emlxs_fcoe_fcftab_linkdown_evt_action(emlxs_port_t *port,
489			uint32_t evt, void *arg1);
490static uint32_t emlxs_fcoe_fcftab_read_action(emlxs_port_t *port,
491			uint32_t evt, void *arg1);
492static uint32_t emlxs_fcoe_fcftab_read_failed_action(emlxs_port_t *port,
493			uint32_t evt, void *arg1);
494static uint32_t emlxs_fcoe_fcftab_read_cmpl_action(emlxs_port_t *port,
495			uint32_t evt, void *arg1);
496static uint32_t emlxs_fcoe_fcftab_fcfi_online_action(emlxs_port_t *port,
497			uint32_t evt, void *arg1);
498static uint32_t emlxs_fcoe_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port,
499			uint32_t evt, void *arg1);
500static uint32_t emlxs_fcoe_fcftab_fcfi_offline_action(emlxs_port_t *port,
501			uint32_t evt, void *arg1);
502static uint32_t emlxs_fcoe_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port,
503			uint32_t evt, void *arg1);
504static uint32_t emlxs_fcoe_fcftab_found_evt_action(emlxs_port_t *port,
505			uint32_t evt, void *arg1);
506static uint32_t emlxs_fcoe_fcftab_lost_evt_action(emlxs_port_t *port,
507			uint32_t evt, void *arg1);
508static uint32_t emlxs_fcoe_fcftab_changed_evt_action(emlxs_port_t *port,
509			uint32_t evt, void *arg1);
510static uint32_t emlxs_fcoe_fcftab_full_evt_action(emlxs_port_t *port,
511			uint32_t evt, void *arg1);
512static uint32_t emlxs_fcoe_fcftab_linkup_evt_action(emlxs_port_t *port,
513			uint32_t evt, void *arg1);
514static uint32_t emlxs_fcoe_fcftab_cvl_evt_action(emlxs_port_t *port,
515			uint32_t evt, void *arg1);
516static uint32_t emlxs_fcoe_fcftab_online_action(emlxs_port_t *port,
517			uint32_t evt, void *arg1);
518static uint32_t emlxs_fcoe_fcftab_offline_action(emlxs_port_t *port,
519			uint32_t evt, void *arg1);
520static uint32_t emlxs_fcoe_fcftab_fcfi_offline_evt_action(emlxs_port_t *port,
521			uint32_t evt, void *arg1);
522static uint32_t emlxs_fcoe_fcftab_fcfi_online_evt_action(emlxs_port_t *port,
523			uint32_t evt, void *arg1);
524
525static void emlxs_fcoe_fcftab_read_timer(emlxs_hba_t *hba);
526static void emlxs_fcoe_fcftab_sol_timer(emlxs_hba_t *hba);
527static void emlxs_fcoe_fcftab_offline_timer(emlxs_hba_t *hba);
528static char *emlxs_fcoe_fcftab_state_xlate(uint32_t state);
529static uint32_t emlxs_fcoe_fcftab_event(emlxs_port_t *port,
530			uint32_t evt, void *arg1);
531static uint32_t emlxs_fcoe_fcftab_state(emlxs_port_t *port, uint16_t state,
532	uint16_t reason, uint32_t explain, void *arg1);
533
534/*
535 * - Online sequencing can start from FCOE_FCFTAB_STATE_OFFLINE state
536 *
537 * - Offline sequencing can interrupt the online sequencing at the
538 * entry of the next wait state.
539 *
540 * NORMAL ONLINE SEQ
541 * ---------------------------
542 * LINK_UP event <-- Adapter
543 * FCOE_FCFTAB_STATE_OFFLINE
544 * FCOE_FCFTAB_STATE_SOLICIT
545 *     FCOE_FCFTAB_STATE_SOLICIT_CMPL
546 * FCOE_FCFTAB_STATE_READ
547 *     FCOE_FCFTAB_STATE_READ_CMPL
548 * FCOE_FCFTAB_STATE_FCFI_OFFLINE
549 *     FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL
550 * FCOE_FCFTAB_STATE_FCFI_ONLINE
551 *     FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL
552 * FCOE_FCFTAB_STATE_ONLINE
553 *
554 *
555 * NORMAL OFFLINE SEQ
556 * ---------------------------
557 * LINK_DOWN event <-- Adapter
558 * FCOE_FCFTAB_STATE_ONLINE
559 * FCOE_FCFTAB_STATE_FCFI_OFFLINE
560 *     FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL
561 * FCOE_FCFTAB_STATE_OFFLINE
562 *
563 */
564/* Order does matter */
565static void *emlxs_fcoe_fcftab_action_table[] =
566{
567	/* Action routine				Event */
568/* FCOE_FCFTAB_STATE_SHUTDOWN  0		(Requires adapter reset) */
569	(void *) emlxs_fcftab_shutdown_action,		/* STATE_ENTER */
570	(void *) NULL,					/* SHUTDOWN */
571	(void *) NULL,					/* LINK_UP */
572	(void *) NULL,					/* LINK_DOWN */
573	(void *) NULL,					/* CVL_RECD */
574	(void *) NULL,					/* FCF_FOUND */
575	(void *) NULL,					/* FCF_LOST */
576	(void *) NULL,					/* FCF_CHANGED */
577	(void *) NULL,					/* TABLE_FULL */
578	(void *) NULL,					/* FCFI_ONLINE */
579	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
580
581/* FCOE_FCFTAB_STATE_OFFLINE  1			(Wait for LINK_UP event) */
582	(void *) emlxs_fcoe_fcftab_offline_action,	/* STATE_ENTER */
583	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
584	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
585	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
586	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
587	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
588	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
589	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
590	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
591	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
592	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
593
594
595/* FCOE_FCFTAB_STATE_SOLICIT  2			(Wait on fcf_solicit cmpl) */
596	(void *) emlxs_fcoe_fcftab_sol_action,		/* STATE_ENTER */
597	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
598	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
599	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
600	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
601	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
602	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
603	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
604	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
605	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
606	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
607
608/* FCOE_FCFTAB_STATE_SOLICIT_FAILED  3		(Transitional) */
609	(void *) emlxs_fcoe_fcftab_sol_failed_action,	/* STATE_ENTER */
610	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
611	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
612	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
613	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
614	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
615	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
616	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
617	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
618	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
619	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
620
621/* FCOE_FCFTAB_STATE_SOLICIT_CMPL  4		(Wait on fcf timer cmpl) */
622	(void *) emlxs_fcoe_fcftab_sol_cmpl_action,	/* STATE_ENTER */
623	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
624	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
625	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
626	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
627	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
628	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
629	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
630	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
631	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
632	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
633
634
635/* FCOE_FCFTAB_STATE_READ  5			(Wait on fcf_read cmpl) */
636	(void *) emlxs_fcoe_fcftab_read_action,		/* STATE_ENTER */
637	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
638	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
639	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
640	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
641	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
642	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
643	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
644	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
645	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
646	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
647
648/* FCOE_FCFTAB_STATE_READ_FAILED  6		(Transitional) */
649	(void *) emlxs_fcoe_fcftab_read_failed_action,	/* STATE_ENTER */
650	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
651	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
652	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
653	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
654	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
655	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
656	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
657	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
658	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
659	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
660
661/* FCOE_FCFTAB_STATE_READ_CMPL  7		(Transitional) */
662	(void *) emlxs_fcoe_fcftab_read_cmpl_action,	/* STATE_ENTER */
663	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
664	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
665	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
666	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
667	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
668	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
669	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
670	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
671	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
672	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
673
674
675/* FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL  8	(Transitional) */
676	(void *) emlxs_fcoe_fcftab_fcfi_offline_cmpl_action, /* STATE_ENTER */
677	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
678	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
679	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
680	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
681	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
682	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
683	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
684	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
685	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
686	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
687
688/* FCOE_FCFTAB_STATE_FCFI_OFFLINE  9		(Wait for FCFI_OFFLINE event) */
689	(void *) emlxs_fcoe_fcftab_fcfi_offline_action,	/* STATE_ENTER */
690	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
691	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
692	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
693	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
694	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
695	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
696	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
697	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
698	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
699	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
700
701
702/* FCOE_FCFTAB_STATE_FCFI_ONLINE  10		(Wait on FCFI_ONLINE event) */
703	(void *) emlxs_fcoe_fcftab_fcfi_online_action,	/* STATE_ENTER */
704	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
705	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
706	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
707	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
708	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
709	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
710	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
711	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
712	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
713	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
714
715/* FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL  11	(Transitional) */
716	(void *) emlxs_fcoe_fcftab_fcfi_online_cmpl_action, /* STATE_ENTER */
717	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
718	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
719	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
720	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
721	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
722	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
723	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
724	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
725	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
726	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
727
728
729/* FCOE_FCFTAB_STATE_ONLINE  12			(Wait for LINK_DOWN event) */
730	(void *) emlxs_fcoe_fcftab_online_action,	/* STATE_ENTER */
731	(void *) emlxs_fcoe_fcftab_shutdown_evt_action,	/* SHUTDOWN */
732	(void *) emlxs_fcoe_fcftab_linkup_evt_action,	/* LINK_UP */
733	(void *) emlxs_fcoe_fcftab_linkdown_evt_action,	/* LINK_DOWN */
734	(void *) emlxs_fcoe_fcftab_cvl_evt_action,	/* CVL_RECD */
735	(void *) emlxs_fcoe_fcftab_found_evt_action,	/* FCF_FOUND */
736	(void *) emlxs_fcoe_fcftab_lost_evt_action,	/* FCF_LOST */
737	(void *) emlxs_fcoe_fcftab_changed_evt_action,	/* FCF_CHANGED */
738	(void *) emlxs_fcoe_fcftab_full_evt_action,	/* TABLE_FULL */
739	(void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
740	(void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
741
742}; /* emlxs_fcoe_fcftab_action_table[] */
743#define	FCOE_FCFTAB_ACTION_EVENTS			11
744#define	FCOE_FCFTAB_ACTION_STATES			\
745	(sizeof (emlxs_fcoe_fcftab_action_table)/ \
746	(FCOE_FCFTAB_ACTION_EVENTS * sizeof (void *)))
747
748
749
750
751/* ********************************************************************** */
752/* FCFI */
753/* ********************************************************************** */
754
755/* Order does not matter */
756emlxs_table_t emlxs_fcfi_state_table[] =
757{
758	{FCFI_STATE_FREE, "FCFI_FREE"},
759
760	{FCFI_STATE_OFFLINE, "FCFI_OFFLINE"},
761
762	{FCFI_STATE_UNREG_CMPL, "FCFI_UNREG_CMPL"},
763	{FCFI_STATE_UNREG_FAILED, "FCFI_UNREG_FAILED"},
764	{FCFI_STATE_UNREG, "FCFI_UNREG"},
765
766	{FCFI_STATE_REG, "FCFI_REG"},
767	{FCFI_STATE_REG_FAILED, "FCFI_REG_FAILED"},
768	{FCFI_STATE_REG_CMPL, "FCFI_REG_CMPL"},
769
770	{FCFI_STATE_VFI_OFFLINE_CMPL, "FCFI_VFI_OFFLINE_CMPL"},
771	{FCFI_STATE_VFI_OFFLINE, "FCFI_VFI_OFFLINE"},
772
773	{FCFI_STATE_VFI_ONLINE, "FCFI_VFI_ONLINE"},
774	{FCFI_STATE_VFI_ONLINE_CMPL, "FCFI_VFI_ONLINE_CMPL"},
775
776	{FCFI_STATE_PAUSED, "FCFI_PAUSED"},
777	{FCFI_STATE_ONLINE, "FCFI_ONLINE"},
778
779}; /* emlxs_fcfi_state_table */
780
781
782static uint32_t emlxs_fcfi_free_action(emlxs_port_t *port,
783			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
784static uint32_t emlxs_fcfi_online_evt_action(emlxs_port_t *port,
785			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
786static uint32_t emlxs_fcfi_offline_evt_action(emlxs_port_t *port,
787			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
788static uint32_t emlxs_fcfi_pause_evt_action(emlxs_port_t *port,
789			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
790static uint32_t emlxs_fcfi_reg_action(emlxs_port_t *port,
791			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
792static uint32_t emlxs_fcfi_unreg_action(emlxs_port_t *port,
793			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
794static uint32_t emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port,
795			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
796static uint32_t emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port,
797			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
798static uint32_t emlxs_fcfi_vfi_online_action(emlxs_port_t *port,
799			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
800static uint32_t emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port,
801			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
802static uint32_t emlxs_fcfi_reg_failed_action(emlxs_port_t *port,
803			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
804static uint32_t emlxs_fcfi_unreg_failed_action(emlxs_port_t *port,
805			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
806static uint32_t emlxs_fcfi_vfi_offline_action(emlxs_port_t *port,
807			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
808static uint32_t emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port,
809			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
810static uint32_t emlxs_fcfi_online_action(emlxs_port_t *port,
811			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
812static uint32_t emlxs_fcfi_paused_action(emlxs_port_t *port,
813			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
814static uint32_t emlxs_fcfi_offline_action(emlxs_port_t *port,
815			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
816static uint32_t emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port,
817			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
818static uint32_t emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port,
819			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
820
821static uint32_t emlxs_fcfi_event(emlxs_port_t *port,
822			uint32_t evt, void *arg1);
823static FCFIobj_t *emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec,
824			uint32_t *fcf_index);
825static FCFIobj_t *emlxs_fcfi_alloc(emlxs_port_t *port);
826static uint32_t emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp);
827static void emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp,
828			FCF_RECORD_t *fcf_rec, uint32_t event_tag);
829static char *emlxs_fcfi_state_xlate(uint32_t state);
830
831/*
832 * - Online sequencing can start from FCFI_STATE_OFFLINE state or
833 * the FCFI_STATE_VFI_OFFLINE state.
834 *
835 * - Offline sequencing can interrupt the online sequencing at the
836 * entry of the next wait state.
837 *
838 * NORMAL ONLINE SEQ
839 * ---------------------------
840 * FCFI_ONLINE event <-- FCFTAB
841 * FCFI_STATE_OFFLINE
842 * FCFI_STATE_REG
843 *     FCFI_STATE_REG_CMPL
844 * FCFI_STATE_VFI_ONLINE
845 *     FCFI_STATE_VFI_ONLINE_CMPL
846 * FCFI_STATE_ONLINE
847 * FCFI_ONLINE event-->FCFTAB
848 *
849 *
850 * NORMAL OFFLINE SEQ
851 * ---------------------------
852 * FCFI_OFFLINE event <-- FCFTAB
853 * FCFI_STATE_ONLINE
854 * FCFI_STATE_VFI_OFFLINE
855 *     FCFI_STATE_VFI_OFFLINE_CMPL
856 * FCFI_STATE_UNREG
857 *     FCFI_STATE_UNREG_CMPL
858 * FCFI_STATE_OFFLINE
859 * FCFI_OFFLINE event-->FCFTAB
860 *
861 *
862 * NORMAL PAUSE SEQ
863 * ---------------------------
864 * FCFI_PAUSE event <-- FCFTAB
865 * FCFI_STATE_ONLINE
866 * FCFI_STATE_PAUSED
867 *
868 */
869/* Order does matter */
870static void *emlxs_fcfi_action_table[] =
871{
872	/* Action routine				Event */
873/* FCFI_STATE_FREE  0			(Wait for allocation) */
874	(void *) emlxs_fcfi_free_action,		/* STATE_ENTER */
875	(void *) NULL,					/* FCFI_ONLINE */
876	(void *) NULL,					/* FCFI_OFFLINE */
877	(void *) NULL,					/* FCFI_PAUSE */
878	(void *) NULL,					/* VFI_ONLINE */
879	(void *) NULL,					/* VFI_OFFLINE */
880
881/* FCFI_STATE_OFFLINE  1		(Wait for FCFI_ONLINE event) */
882	(void *) emlxs_fcfi_offline_action,		/* STATE_ENTER */
883	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
884	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
885	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
886	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
887	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
888
889/* FCFI_STATE_UNREG_CMPL  2		(Transitional)  */
890	(void *) emlxs_fcfi_unreg_cmpl_action,		/* STATE_ENTER */
891	(void *) emlxs_fcfi_online_evt_action,  	/* FCFI_ONLINE */
892	(void *) emlxs_fcfi_offline_evt_action, 	/* FCFI_OFFLINE */
893	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
894	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
895	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
896
897/* FCFI_STATE_UNREG_FAILED  3		(Transitional) */
898	(void *) emlxs_fcfi_unreg_failed_action, 	/* STATE_ENTER */
899	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
900	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
901	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
902	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
903	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
904
905/* FCFI_STATE_UNREG  4			(Wait for unreg_fcfi cmpl) */
906	(void *) emlxs_fcfi_unreg_action,		/* STATE_ENTER */
907	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
908	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
909	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
910	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
911	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
912
913/* FCFI_STATE_REG  5			(Wait for reg_fcfi cmpl) */
914	(void *) emlxs_fcfi_reg_action,			/* STATE_ENTER */
915	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
916	(void *) emlxs_fcfi_offline_evt_action, 	/* FCFI_OFFLINE */
917	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
918	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
919	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
920
921/* FCFI_STATE_REG_FAILED  6		(Transitional) */
922	(void *) emlxs_fcfi_reg_failed_action,		/*  STATE_ENTER */
923	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
924	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
925	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
926	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
927	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
928
929/* FCFI_STATE_REG_CMPL  7		(Transitional) */
930	(void *) emlxs_fcfi_reg_cmpl_action,		/* STATE_ENTER */
931	(void *) emlxs_fcfi_online_evt_action,  	/* FCFI_ONLINE */
932	(void *) emlxs_fcfi_offline_evt_action, 	/* FCFI_OFFLINE */
933	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
934	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
935	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
936
937/* FCFI_STATE_VFI_OFFLINE_CMPL  8 	(Transitional) */
938	(void *) emlxs_fcfi_vfi_offline_cmpl_action,	/* STATE_ENTER */
939	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
940	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
941	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
942	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
943	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
944
945/* FCFI_STATE_VFI_OFFLINE  9		(Wait for VFI_OFFLINE event) */
946	(void *) emlxs_fcfi_vfi_offline_action,		/* STATE_ENTER */
947	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
948	(void *) emlxs_fcfi_offline_evt_action, 	/* FCFI_OFFLINE */
949	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
950	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
951	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE * */
952
953/* FCFI_STATE_VFI_ONLINE  10		(Wait for VFI_ONLINE event) */
954	(void *) emlxs_fcfi_vfi_online_action,		/* STATE_ENTER */
955	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
956	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
957	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
958	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
959	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
960
961/* FCFI_STATE_VFI_ONLINE_CMPL  11	(Transitional) */
962	(void *) emlxs_fcfi_vfi_online_cmpl_action, 	/* STATE_ENTER */
963	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
964	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
965	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
966	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
967	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
968
969
970/* FCFI_STATE_PAUSED 12			(Wait for FCFI_ONLINE event) */
971	(void *) emlxs_fcfi_paused_action,		/* STATE_ENTER */
972	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
973	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
974	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
975	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
976	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
977
978/* FCFI_STATE_ONLINE 13			(Wait for FCFI_OFFLINE event) */
979	(void *) emlxs_fcfi_online_action,		/* STATE_ENTER */
980	(void *) emlxs_fcfi_online_evt_action,		/* FCFI_ONLINE */
981	(void *) emlxs_fcfi_offline_evt_action,		/* FCFI_OFFLINE */
982	(void *) emlxs_fcfi_pause_evt_action,		/* FCFI_PAUSE */
983	(void *) emlxs_fcfi_vfi_online_evt_action,	/* VFI_ONLINE */
984	(void *) emlxs_fcfi_vfi_offline_evt_action,	/* VFI_OFFLINE */
985
986}; /* emlxs_fcfi_action_table[] */
987#define	FCFI_ACTION_EVENTS			6
988#define	FCFI_ACTION_STATES			\
989	(sizeof (emlxs_fcfi_action_table)/ \
990	(FCFI_ACTION_EVENTS * sizeof (void *)))
991
992
993/* ********************************************************************** */
994/* VFI */
995/* ********************************************************************** */
996
997/* Order does not matter */
998emlxs_table_t emlxs_vfi_state_table[] =
999{
1000	{VFI_STATE_OFFLINE, "VFI_OFFLINE"},
1001
1002	{VFI_STATE_INIT, "VFI_INIT"},
1003	{VFI_STATE_INIT_FAILED, "VFI_INIT_FAILED"},
1004	{VFI_STATE_INIT_CMPL, "VFI_INIT_CMPL"},
1005
1006	{VFI_STATE_VPI_OFFLINE_CMPL, "VFI_VPI_OFFLINE_CMPL"},
1007	{VFI_STATE_VPI_OFFLINE, "VFI_VPI_OFFLINE"},
1008
1009	{VFI_STATE_VPI_ONLINE, "VFI_VPI_ONLINE"},
1010	{VFI_STATE_VPI_ONLINE_CMPL, "VFI_VPI_ONLINE_CMPL"},
1011
1012	{VFI_STATE_UNREG_CMPL, "VFI_UNREG_CMPL"},
1013	{VFI_STATE_UNREG_FAILED, "VFI_UNREG_FAILED"},
1014	{VFI_STATE_UNREG, "VFI_UNREG"},
1015
1016	{VFI_STATE_REG, "VFI_REG"},
1017	{VFI_STATE_REG_FAILED, "VFI_REG_FAILED"},
1018	{VFI_STATE_REG_CMPL, "VFI_REG_CMPL"},
1019
1020	{VFI_STATE_PAUSED, "VFI_PAUSED"},
1021	{VFI_STATE_ONLINE, "VFI_ONLINE"},
1022
1023}; /* emlxs_vfi_state_table */
1024
1025
1026static uint32_t emlxs_vfi_pause_evt_action(emlxs_port_t *port,
1027			VFIobj_t *vfip, uint32_t evt, void *arg1);
1028static uint32_t emlxs_vfi_online_evt_action(emlxs_port_t *port,
1029			VFIobj_t *vfip, uint32_t evt, void *arg1);
1030static uint32_t emlxs_vfi_offline_evt_action(emlxs_port_t *port,
1031			VFIobj_t *vfip, uint32_t evt, void *arg1);
1032static uint32_t emlxs_vfi_init_action(emlxs_port_t *port,
1033			VFIobj_t *vfip, uint32_t evt, void *arg1);
1034static uint32_t emlxs_vfi_init_failed_action(emlxs_port_t *port,
1035			VFIobj_t *vfip, uint32_t evt, void *arg1);
1036static uint32_t emlxs_vfi_init_cmpl_action(emlxs_port_t *port,
1037			VFIobj_t *vfip, uint32_t evt, void *arg1);
1038static uint32_t emlxs_vfi_offline_action(emlxs_port_t *port,
1039			VFIobj_t *vfip, uint32_t evt, void *arg1);
1040static uint32_t emlxs_vfi_online_action(emlxs_port_t *port,
1041			VFIobj_t *vfip, uint32_t evt, void *arg1);
1042static uint32_t emlxs_vfi_paused_action(emlxs_port_t *port,
1043			VFIobj_t *vfip, uint32_t evt, void *arg1);
1044static uint32_t emlxs_vfi_vpi_online_action(emlxs_port_t *port,
1045			VFIobj_t *vfip, uint32_t evt, void *arg1);
1046static uint32_t emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port,
1047			VFIobj_t *vfip, uint32_t evt, void *arg1);
1048static uint32_t emlxs_vfi_vpi_offline_action(emlxs_port_t *port,
1049			VFIobj_t *vfip, uint32_t evt, void *arg1);
1050static uint32_t emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port,
1051			VFIobj_t *vfip, uint32_t evt, void *arg1);
1052static uint32_t emlxs_vfi_reg_action(emlxs_port_t *port,
1053			VFIobj_t *vfip, uint32_t evt, void *arg1);
1054static uint32_t emlxs_vfi_reg_failed_action(emlxs_port_t *port,
1055			VFIobj_t *vfip, uint32_t evt, void *arg1);
1056static uint32_t emlxs_vfi_reg_cmpl_action(emlxs_port_t *port,
1057			VFIobj_t *vfip, uint32_t evt, void *arg1);
1058static uint32_t emlxs_vfi_unreg_action(emlxs_port_t *port,
1059			VFIobj_t *vfip, uint32_t evt, void *arg1);
1060static uint32_t emlxs_vfi_unreg_failed_action(emlxs_port_t *port,
1061			VFIobj_t *vfip, uint32_t evt, void *arg1);
1062static uint32_t emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port,
1063			VFIobj_t *vfip, uint32_t evt, void *arg1);
1064static uint32_t emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port,
1065			VFIobj_t *vfip, uint32_t evt, void *arg1);
1066static uint32_t emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port,
1067			VFIobj_t *vfip, uint32_t evt, void *arg1);
1068
1069static uint32_t emlxs_vfi_event(emlxs_port_t *port,
1070			uint32_t evt, void *arg1);
1071
1072
1073/*
1074 * - Online sequencing can start from VFI_STATE_OFFLINE state or
1075 * the VFI_STATE_VPI_OFFLINE state.
1076 *
1077 * - Offline sequencing can interrupt the online sequencing at the
1078 * entry of the next wait state.
1079 *
1080 * NORMAL ONLINE SEQ
1081 * ---------------------------
1082 * VFI_ONLINE event <-- FCFI
1083 * VFI_STATE_OFFLINE
1084 * VFI_STATE_INIT
1085 *     VFI_STATE_INIT_CMPL
1086 * VFI_STATE_VPI_ONLINE
1087 *     VFI_STATE_VPI_ONLINE_CMPL
1088 * VFI_STATE_REG
1089 *     VFI_STATE_REG_CMPL
1090 * VFI_STATE_ONLINE
1091 * VFI_ONLINE event-->FCFI
1092 *
1093 *
1094 * NORMAL OFFLINE SEQ
1095 * ---------------------------
1096 * VFI_OFFLINE event <-- FCFI
1097 * VFI_STATE_ONLINE
1098 * VFI_STATE_VPI_OFFLINE
1099 *     VFI_STATE_VPI_OFFLINE_CMPL
1100 * VFI_STATE_UNREG
1101 *     VFI_STATE_UNREG_CMPL
1102 * VFI_STATE_OFFLINE
1103 * VFI_OFFLINE event-->FCFI
1104 *
1105 *
1106 * NORMAL PAUSE SEQ
1107 * ---------------------------
1108 * VFI_PAUSE event <-- FCFI
1109 * VFI_STATE_ONLINE
1110 * VFI_STATE_PAUSED
1111 *
1112 */
1113/* Order does matter */
1114static void *emlxs_vfi_action_table[] =
1115{
1116	/* Action routine				Event */
1117/* VFI_STATE_OFFLINE  0			(Wait for VFI_ONLINE event) */
1118	(void *) emlxs_vfi_offline_action,		/* STATE_ENTER */
1119	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1120	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1121	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1122	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1123	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1124
1125
1126/* VFI_STATE_INIT  1			(Wait for init_vfi cmpl) */
1127	(void *) emlxs_vfi_init_action,			/* STATE_ENTER */
1128	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1129	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1130	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1131	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1132	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1133
1134/* VFI_STATE_INIT_FAILED  2		(Transitional) */
1135	(void *) emlxs_vfi_init_failed_action,		/* STATE_ENTER */
1136	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1137	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1138	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1139	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1140	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1141
1142/* VFI_STATE_INIT_CMPL  3		(Transitional) */
1143	(void *) emlxs_vfi_init_cmpl_action,		/* STATE_ENTER */
1144	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1145	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1146	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1147	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1148	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1149
1150
1151/* VFI_STATE_VPI_OFFLINE_CMPL  4	(Wait for VPI_OFFLINE event) */
1152	(void *) emlxs_vfi_vpi_offline_cmpl_action,	/* STATE_ENTER */
1153	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1154	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1155	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1156	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1157	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1158
1159/* VFI_STATE_VPI_OFFLINE  5		(Wait for VPI_OFFLINE event) */
1160	(void *) emlxs_vfi_vpi_offline_action,		/* STATE_ENTER */
1161	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1162	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1163	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1164	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1165	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1166
1167
1168/* VFI_STATE_VPI_ONLINE 6		(Wait for VPI_ONLINE event) */
1169	(void *) emlxs_vfi_vpi_online_action,		/* STATE_ENTER */
1170	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1171	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1172	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1173	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1174	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1175
1176/* VFI_STATE_VPI_ONLINE_CMPL  7		(Transitional) */
1177	(void *) emlxs_vfi_vpi_online_cmpl_action,	/* STATE_ENTER */
1178	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1179	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1180	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1181	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1182	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1183
1184
1185/* VFI_STATE_UNREG_CMPL  8		(Transitional) */
1186	(void *) emlxs_vfi_unreg_cmpl_action,		/* STATE_ENTER */
1187	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1188	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1189	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1190	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1191	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1192
1193/* VFI_STATE_UNREG_FAILED  9		(Transitional) */
1194	(void *) emlxs_vfi_unreg_failed_action,		/* STATE_ENTER */
1195	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1196	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1197	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1198	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1199	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1200
1201/* VFI_STATE_UNREG  10			(Wait for unreg_vfi cmpl) */
1202	(void *) emlxs_vfi_unreg_action,		/* STATE_ENTER */
1203	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1204	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1205	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1206	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1207	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1208
1209
1210/* VFI_STATE_REG  11			(Wait for reg_vfi cmpl) */
1211	(void *) emlxs_vfi_reg_action,			/* STATE_ENTER */
1212	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1213	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1214	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1215	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1216	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1217
1218/* VFI_STATE_REG_FAILED  12		(Transitional) */
1219	(void *) emlxs_vfi_reg_failed_action,		/* STATE_ENTER */
1220	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1221	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1222	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1223	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1224	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1225
1226/* VFI_STATE_REG_CMPL  13		(Transitional) */
1227	(void *) emlxs_vfi_reg_cmpl_action,		/* STATE_ENTER */
1228	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1229	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1230	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1231	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1232	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1233
1234
1235/* VFI_STATE_PAUSED  14			(Wait for VFI_OFFLINE event) */
1236	(void *) emlxs_vfi_paused_action,		/* STATE_ENTER */
1237	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1238	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1239	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1240	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1241	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1242
1243/* VFI_STATE_ONLINE  14			(Wait for VFI_OFFLINE event) */
1244	(void *) emlxs_vfi_online_action,		/* STATE_ENTER */
1245	(void *) emlxs_vfi_online_evt_action,		/* VFI_ONLINE */
1246	(void *) emlxs_vfi_offline_evt_action,		/* VFI_OFFLINE */
1247	(void *) emlxs_vfi_pause_evt_action,		/* VFI_PAUSE */
1248	(void *) emlxs_vfi_vpi_online_evt_action,	/* VPI_ONLINE */
1249	(void *) emlxs_vfi_vpi_offline_evt_action,	/* VPI_OFFLINE */
1250
1251}; /* emlxs_vfi_action_table[] */
1252#define	VFI_ACTION_EVENTS			6
1253#define	VFI_ACTION_STATES			\
1254	(sizeof (emlxs_vfi_action_table)/ \
1255	(VFI_ACTION_EVENTS * sizeof (void *)))
1256
1257
1258/* ********************************************************************** */
1259/* VPI */
1260/* ********************************************************************** */
1261
1262/* Order does not matter */
1263emlxs_table_t emlxs_vpi_state_table[] =
1264{
1265	{VPI_STATE_OFFLINE, "VPI_OFFLINE"},
1266
1267	{VPI_STATE_INIT, "VPI_INIT"},
1268	{VPI_STATE_INIT_FAILED, "VPI_INIT_FAILED"},
1269	{VPI_STATE_INIT_CMPL, "VPI_INIT_CMPL"},
1270
1271	{VPI_STATE_UNREG_CMPL, "VPI_UNREG_CMPL"},
1272	{VPI_STATE_UNREG_FAILED, "VPI_UNREG_FAILED"},
1273	{VPI_STATE_UNREG, "VPI_UNREG"},
1274
1275	{VPI_STATE_LOGO_CMPL, "VPI_LOGO_CMPL"},
1276	{VPI_STATE_LOGO_FAILED, "VPI_LOGO_FAILED"},
1277	{VPI_STATE_LOGO, "VPI_LOGO"},
1278
1279	{VPI_STATE_PORT_OFFLINE, "VPI_PORT_OFFLINE"},
1280	{VPI_STATE_PORT_ONLINE, "VPI_PORT_ONLINE"},
1281
1282	{VPI_STATE_LOGI, "VPI_LOGI"},
1283	{VPI_STATE_LOGI_FAILED, "VPI_LOGI_FAILED"},
1284	{VPI_STATE_LOGI_CMPL, "VPI_LOGI_CMPL"},
1285
1286	{VPI_STATE_REG, "VPI_REG"},
1287	{VPI_STATE_REG_FAILED, "VPI_REG_FAILED"},
1288	{VPI_STATE_REG_CMPL, "VPI_REG_CMPL"},
1289
1290	{VPI_STATE_PAUSED, "VPI_PAUSED"},
1291	{VPI_STATE_ONLINE, "VPI_ONLINE"},
1292
1293}; /* emlxs_vpi_state_table */
1294
1295
1296static uint32_t emlxs_vpi_online_evt_action(emlxs_port_t *port,
1297			VPIobj_t *vpip, uint32_t evt, void *arg1);
1298static uint32_t emlxs_vpi_offline_evt_action(emlxs_port_t *port,
1299			VPIobj_t *vpip, uint32_t evt, void *arg1);
1300static uint32_t emlxs_vpi_pause_evt_action(emlxs_port_t *port,
1301			VPIobj_t *vpip, uint32_t evt, void *arg1);
1302static uint32_t emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port,
1303			VPIobj_t *vpip, uint32_t evt, void *arg1);
1304static uint32_t emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port,
1305			VPIobj_t *vpip, uint32_t evt, void *arg1);
1306static uint32_t emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port,
1307			VPIobj_t *vpip, uint32_t evt, void *arg1);
1308
1309static uint32_t emlxs_vpi_init_action(emlxs_port_t *port,
1310			VPIobj_t *vpip, uint32_t evt, void *arg1);
1311static uint32_t emlxs_vpi_init_failed_action(emlxs_port_t *port,
1312			VPIobj_t *vpip, uint32_t evt, void *arg1);
1313static uint32_t emlxs_vpi_init_cmpl_action(emlxs_port_t *port,
1314			VPIobj_t *vpip, uint32_t evt, void *arg1);
1315
1316static uint32_t emlxs_vpi_offline_action(emlxs_port_t *port,
1317			VPIobj_t *vpip, uint32_t evt, void *arg1);
1318static uint32_t emlxs_vpi_online_action(emlxs_port_t *port,
1319			VPIobj_t *vpip, uint32_t evt, void *arg1);
1320static uint32_t emlxs_vpi_paused_action(emlxs_port_t *port,
1321			VPIobj_t *vpip, uint32_t evt, void *arg1);
1322
1323static uint32_t emlxs_vpi_port_online_action(emlxs_port_t *port,
1324			VPIobj_t *vpip, uint32_t evt, void *arg1);
1325static uint32_t emlxs_vpi_port_offline_action(emlxs_port_t *port,
1326			VPIobj_t *vpip, uint32_t evt, void *arg1);
1327
1328static uint32_t emlxs_vpi_logi_cmpl_action(emlxs_port_t *port,
1329			VPIobj_t *vpip, uint32_t evt, void *arg1);
1330static uint32_t emlxs_vpi_logi_failed_action(emlxs_port_t *port,
1331			VPIobj_t *vpip, uint32_t evt, void *arg1);
1332static uint32_t emlxs_vpi_logi_action(emlxs_port_t *port,
1333			VPIobj_t *vpip, uint32_t evt, void *arg1);
1334
1335static uint32_t emlxs_vpi_reg_action(emlxs_port_t *port,
1336			VPIobj_t *vpip, uint32_t evt, void *arg1);
1337static uint32_t emlxs_vpi_reg_failed_action(emlxs_port_t *port,
1338			VPIobj_t *vpip, uint32_t evt, void *arg1);
1339static uint32_t emlxs_vpi_reg_cmpl_action(emlxs_port_t *port,
1340			VPIobj_t *vpip, uint32_t evt, void *arg1);
1341
1342static uint32_t emlxs_vpi_unreg_action(emlxs_port_t *port,
1343			VPIobj_t *vpip, uint32_t evt, void *arg1);
1344static uint32_t emlxs_vpi_unreg_failed_action(emlxs_port_t *port,
1345			VPIobj_t *vpip, uint32_t evt, void *arg1);
1346static uint32_t emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port,
1347			VPIobj_t *vpip, uint32_t evt, void *arg1);
1348
1349static uint32_t emlxs_vpi_logo_action(emlxs_port_t *port,
1350			VPIobj_t *vpip, uint32_t evt, void *arg1);
1351static uint32_t emlxs_vpi_logo_failed_action(emlxs_port_t *port,
1352			VPIobj_t *vpip, uint32_t evt, void *arg1);
1353static uint32_t emlxs_vpi_logo_cmpl_action(emlxs_port_t *port,
1354			VPIobj_t *vpip, uint32_t evt, void *arg1);
1355
1356static uint32_t emlxs_vpi_event(emlxs_port_t *port,
1357			uint32_t evt, void *arg1);
1358static uint32_t emlxs_vpi_logi_cmpl_notify(emlxs_port_t *port,
1359			RPIobj_t *rpip);
1360static void emlxs_vpi_logo_handler(emlxs_port_t *port,
1361			VPIobj_t *vpip);
1362
1363/*
1364 * - Online sequencing can only start from VPI_STATE_OFFLINE or
1365 * VPI_STATE_PORT_OFFLINE state.
1366 *
1367 * - Offline sequencing can interrupt the online sequencing at the
1368 * entry of the next wait state.
1369 *
1370 * NORMAL ONLINE SEQ
1371 * ---------------------------
1372 * VPI_ONLINE event <-- VFI
1373 * VPI_STATE_OFFLINE
1374 * VPI_STATE_INIT
1375 *     VPI_STATE_INIT_CMPL
1376 * VPI_STATE_PORT_ONLINE
1377 * VPI_STATE_LOGI
1378 *     VPI_STATE_LOGI_CMPL
1379 * VPI_STATE_REG
1380 *     VPI_STATE_REG_CMPL
1381 * VPI_STATE_ONLINE
1382 * VPI_ONLINE event-->VFI
1383 *
1384 *
1385 * NORMAL OFFLINE SEQ
1386 * ---------------------------
1387 * VPI_OFFLINE event <-- VFI
1388 * VPI_STATE_ONLINE
1389 * VPI_STATE_PORT_OFFLINE
1390 * VPI_STATE_LOGO
1391 *     VPI_STATE_LOGO_CMPL
1392 * VPI_STATE_UNREG
1393 *     VPI_STATE_UNREG_CMPL
1394 * VPI_STATE_OFFLINE
1395 * VPI_OFFLINE event-->VFI
1396 *
1397 *
1398 * NORMAL PAUSE SEQ
1399 * ---------------------------
1400 * VPI_PAUSE event <-- VFI
1401 * VPI_STATE_ONLINE
1402 * VPI_STATE_PORT_OFFLINE
1403 * VPI_STATE_PAUSED
1404 *
1405 */
1406/* Order does matter */
1407static void *emlxs_vpi_action_table[] =
1408{
1409	/* Action routine				Event */
1410/* VPI_STATE_OFFLINE  0 		(Wait for VPI_ONLINE event) */
1411	(void *) emlxs_vpi_offline_action,		/* STATE_ENTER */
1412	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1413	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1414	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1415	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1416	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1417	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1418
1419
1420/* VPI_STATE_INIT  1 			(Wait for init_vpi cmpl) */
1421	(void *) emlxs_vpi_init_action,			/* STATE_ENTER */
1422	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1423	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1424	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1425	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1426	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1427	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1428
1429/* VPI_STATE_INIT_FAILED  2  		(Transitional) */
1430	(void *) emlxs_vpi_init_failed_action,		/* STATE_ENTER */
1431	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1432	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1433	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1434	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1435	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1436	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1437
1438/* VPI_STATE_INIT_CMPL  3 		(Transitional) */
1439	(void *) emlxs_vpi_init_cmpl_action,		/* STATE_ENTER */
1440	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1441	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1442	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1443	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1444	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1445	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1446
1447
1448/* VPI_STATE_UNREG_CMPL  4 		(Transitional) */
1449	(void *) emlxs_vpi_unreg_cmpl_action,		/* STATE_ENTER */
1450	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1451	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1452	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1453	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1454	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1455	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1456
1457/* VPI_STATE_UNREG_FAILED  5  		(Transitional) */
1458	(void *) emlxs_vpi_unreg_failed_action,		/* STATE_ENTER */
1459	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1460	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1461	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1462	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1463	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1464	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1465
1466/* VPI_STATE_UNREG  6 			(Wait for unreg_vpi cmpl) */
1467	(void *) emlxs_vpi_unreg_action,		/* STATE_ENTER */
1468	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1469	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1470	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1471	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1472	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1473	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1474
1475
1476/* VPI_STATE_LOGO_CMPL  7 		(Transitional) */
1477	(void *) emlxs_vpi_logo_cmpl_action,		/* STATE_ENTER */
1478	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1479	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1480	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1481	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1482	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1483	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1484
1485/* VPI_STATE_LOGO_FAILED  8  		(Transitional) */
1486	(void *) emlxs_vpi_logo_failed_action,		/* STATE_ENTER */
1487	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1488	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1489	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1490	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1491	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1492	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1493
1494/* VPI_STATE_LOGO  9 			(Transitional) */
1495	(void *) emlxs_vpi_logo_action,			/* STATE_ENTER */
1496	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1497	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1498	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1499	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1500	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1501	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1502
1503
1504/* VPI_STATE_PORT_OFFLINE  10	(Wait for RPI_OFFLINE or VPI_ONLINE) */
1505	(void *) emlxs_vpi_port_offline_action,		/* STATE_ENTER */
1506	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1507	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1508	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1509	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1510	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1511	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1512
1513/* VPI_STATE_PORT_ONLINE  11 	(Wait for emlxs_vpi_logi_notify() ) */
1514	(void *) emlxs_vpi_port_online_action,		/* STATE_ENTER */
1515	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1516	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1517	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1518	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1519	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1520	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1521
1522
1523/* VPI_STATE_LOGI  12 		(Wait for emlxs_vpi_logi_cmpl_notify() ) */
1524	(void *) emlxs_vpi_logi_action,			/* STATE_ENTER */
1525	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1526	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1527	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1528	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1529	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1530	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1531
1532/* VPI_STATE_LOGI_FAILED  13  		(Transitional) */
1533	(void *) emlxs_vpi_logi_failed_action,		/* STATE_ENTER */
1534	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1535	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1536	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1537	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1538	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1539	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1540
1541/* VPI_STATE_LOGI_CMPL  14 		(Transitional) */
1542	(void *) emlxs_vpi_logi_cmpl_action,		/* STATE_ENTER */
1543	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1544	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1545	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1546	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1547	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1548	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1549
1550
1551/* VPI_STATE_REG  15 			(Wait for reg_vpi cmpl) */
1552	(void *) emlxs_vpi_reg_action,			/* STATE_ENTER */
1553	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1554	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1555	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1556	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1557	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1558	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1559
1560/* VPI_STATE_REG_FAILED  16  		(Transitional) */
1561	(void *) emlxs_vpi_reg_failed_action,		/* STATE_ENTER */
1562	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1563	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1564	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1565	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1566	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1567	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1568
1569/* VPI_STATE_REG_CMPL  17 		(Transitional) */
1570	(void *) emlxs_vpi_reg_cmpl_action,		/* STATE_ENTER */
1571	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1572	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1573	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1574	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1575	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1576	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1577
1578
1579/* VPI_STATE_PAUSED 18			(Wait for VPI_ONLINE() ) */
1580	(void *) emlxs_vpi_paused_action,		/* STATE_ENTER */
1581	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1582	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1583	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1584	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1585	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1586	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1587
1588/* VPI_STATE_ONLINE  19 		(Wait for VPI_OFFLINE event) */
1589	(void *) emlxs_vpi_online_action,		/* STATE_ENTER */
1590	(void *) emlxs_vpi_online_evt_action,		/* VPI_ONLINE */
1591	(void *) emlxs_vpi_offline_evt_action,		/* VPI_OFFLINE */
1592	(void *) emlxs_vpi_pause_evt_action,		/* VPI_PAUSE */
1593	(void *) emlxs_vpi_rpi_online_evt_action,	/* RPI_ONLINE */
1594	(void *) emlxs_vpi_rpi_offline_evt_action,	/* RPI_OFFLINE */
1595	(void *) emlxs_vpi_rpi_pause_evt_action,	/* RPI_PAUSE */
1596
1597}; /* emlxs_vpi_action_table() */
1598#define	VPI_ACTION_EVENTS			7
1599#define	VPI_ACTION_STATES			\
1600	(sizeof (emlxs_vpi_action_table)/ \
1601	(VPI_ACTION_EVENTS * sizeof (void *)))
1602
1603
1604/* ********************************************************************** */
1605/* RPI */
1606/* ********************************************************************** */
1607
1608/* Order does not matter */
1609emlxs_table_t emlxs_rpi_state_table[] =
1610{
1611	{RPI_STATE_FREE, "RPI_FREE"},
1612
1613	{RPI_STATE_RESERVED, "RPI_RESERVED"},
1614	{RPI_STATE_OFFLINE, "RPI_OFFLINE"},
1615
1616	{RPI_STATE_UNREG_CMPL, "RPI_UNREG_CMPL"},
1617	{RPI_STATE_UNREG_FAILED, "RPI_UNREG_FAILED"},
1618	{RPI_STATE_UNREG, "RPI_UNREG"},
1619
1620	{RPI_STATE_REG, "RPI_REG"},
1621	{RPI_STATE_REG_FAILED, "RPI_REG_FAILED"},
1622	{RPI_STATE_REG_CMPL, "RPI_REG_CMPL"},
1623
1624	{RPI_STATE_PAUSED, "RPI_PAUSED"},
1625
1626	{RPI_STATE_RESUME, "RPI_RESUME"},
1627	{RPI_STATE_RESUME_FAILED, "RPI_RESUME_FAILED"},
1628	{RPI_STATE_RESUME_CMPL, "RPI_RESUME_CMPL"},
1629
1630	{RPI_STATE_ONLINE, "RPI_ONLINE"},
1631
1632}; /* emlxs_rpi_state_table */
1633
1634static uint32_t emlxs_rpi_free_action(emlxs_port_t *port,
1635			RPIobj_t *rpip, uint32_t evt, void *arg1);
1636
1637static uint32_t emlxs_rpi_online_evt_action(emlxs_port_t *port,
1638			RPIobj_t *rpip, uint32_t evt, void *arg1);
1639static uint32_t emlxs_rpi_offline_evt_action(emlxs_port_t *port,
1640			RPIobj_t *rpip, uint32_t evt, void *arg1);
1641static uint32_t emlxs_rpi_pause_evt_action(emlxs_port_t *port,
1642			RPIobj_t *rpip, uint32_t evt, void *arg1);
1643static uint32_t emlxs_rpi_resume_evt_action(emlxs_port_t *port,
1644			RPIobj_t *rpip, uint32_t evt, void *arg1);
1645
1646static uint32_t emlxs_rpi_reg_action(emlxs_port_t *port,
1647			RPIobj_t *rpip, uint32_t evt, void *arg1);
1648static uint32_t emlxs_rpi_reg_cmpl_action(emlxs_port_t *port,
1649			RPIobj_t *rpip, uint32_t evt, void *arg1);
1650static uint32_t emlxs_rpi_reg_failed_action(emlxs_port_t *port,
1651			RPIobj_t *rpip, uint32_t evt, void *arg1);
1652
1653static uint32_t emlxs_rpi_unreg_action(emlxs_port_t *port,
1654			RPIobj_t *rpip, uint32_t evt, void *arg1);
1655static uint32_t emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port,
1656			RPIobj_t *rpip, uint32_t evt, void *arg1);
1657static uint32_t emlxs_rpi_unreg_failed_action(emlxs_port_t *port,
1658			RPIobj_t *rpip, uint32_t evt, void *arg1);
1659
1660static uint32_t emlxs_rpi_online_action(emlxs_port_t *port,
1661			RPIobj_t *rpip, uint32_t evt, void *arg1);
1662static uint32_t emlxs_rpi_paused_action(emlxs_port_t *port,
1663			RPIobj_t *rpip, uint32_t evt, void *arg1);
1664static uint32_t emlxs_rpi_offline_action(emlxs_port_t *port,
1665			RPIobj_t *rpip, uint32_t evt, void *arg1);
1666static uint32_t emlxs_rpi_reserved_action(emlxs_port_t *port,
1667			RPIobj_t *rpip, uint32_t evt, void *arg1);
1668
1669static uint32_t emlxs_rpi_resume_failed_action(emlxs_port_t *port,
1670			RPIobj_t *rpip, uint32_t evt, void *arg1);
1671static uint32_t emlxs_rpi_resume_cmpl_action(emlxs_port_t *port,
1672			RPIobj_t *rpip, uint32_t evt, void *arg1);
1673static uint32_t emlxs_rpi_resume_action(emlxs_port_t *port,
1674			RPIobj_t *rpip, uint32_t evt, void *arg1);
1675
1676static uint32_t emlxs_rpi_event(emlxs_port_t *port,
1677			uint32_t evt, void *arg1);
1678static RPIobj_t *emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did);
1679static uint32_t emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip);
1680static RPIobj_t *emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did);
1681
1682static void emlxs_rpi_resume_handler(emlxs_port_t *port,
1683			RPIobj_t *rpip);
1684static void emlxs_rpi_unreg_handler(emlxs_port_t *port,
1685			RPIobj_t *rpip);
1686static uint32_t emlxs_rpi_reg_handler(emlxs_port_t *port,
1687			RPIobj_t *rpip);
1688
1689static void emlxs_rpi_idle_timer(emlxs_hba_t *hba);
1690
1691static uint32_t emlxs_rpi_state(emlxs_port_t *port, RPIobj_t *rpip,
1692			uint16_t state, uint16_t reason, uint32_t explain,
1693			void *arg1);
1694
1695static void emlxs_rpi_alloc_fabric_rpi(emlxs_port_t *port);
1696
1697static void emlxs_rpi_deferred_cmpl(emlxs_port_t *port, RPIobj_t *rpip,
1698			uint32_t status);
1699
1700/*
1701 * - Online sequencing can start from RPI_STATE_RESERVED state or
1702 * the RPI_STATE_PAUSED state.
1703 *
1704 * - Offline sequencing can interrupt the online sequencing at the
1705 * entry of the next wait state.
1706 *
1707 * NORMAL ONLINE SEQ
1708 * ---------------------------
1709 * RPI_ONLINE event <-- VPI
1710 * RPI_STATE_RESERVED
1711 * RPI_STATE_REG
1712 *     RPI_STATE_REG_CMPL
1713 * RPI_STATE_ONLINE
1714 * RPI_ONLINE event-->VPI
1715 *
1716 *
1717 * NORMAL OFFLINE SEQ
1718 * ---------------------------
1719 * RPI_OFFLINE event <-- VPI
1720 * RPI_STATE_ONLINE
1721 * RPI_STATE_UNREG
1722 *     RPI_STATE_UNREG_CMPL
1723 * RPI_STATE_OFFLINE
1724 * RPI_OFFLINE event-->VPI
1725 *
1726 *
1727 * NORMAL PAUSE SEQ
1728 * ---------------------------
1729 * RPI_PAUSE event <-- VPI
1730 * RPI_STATE_ONLINE
1731 * RPI_STATE_PAUSED
1732 *
1733 */
1734/* Order does matter */
1735static void *emlxs_rpi_action_table[] =
1736{
1737	/* Action routine				Event */
1738/* RPI_STATE_FREE  0			(Wait for allocation) */
1739	(void *) emlxs_rpi_free_action,			/* STATE_ENTER */
1740	(void *) NULL,					/* RPI_ONLINE */
1741	(void *) NULL,					/* RPI_OFFLINE */
1742	(void *) NULL,					/* RPI_PAUSE */
1743	(void *) NULL,					/* RPI_RESUME */
1744
1745/* RPI_STATE_RESERVED  1		(Wait for RPI_ONLINE event) */
1746	(void *) emlxs_rpi_reserved_action,		/* STATE_ENTER */
1747	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1748	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1749	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1750	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1751
1752/* RPI_STATE_OFFLINE  2			(Transitional) */
1753	(void *) emlxs_rpi_offline_action,		/* STATE_ENTER */
1754	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1755	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1756	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1757	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1758
1759/* RPI_STATE_UNREG_CMPL  3		(Transitional)  */
1760	(void *) emlxs_rpi_unreg_cmpl_action,		/* STATE_ENTER */
1761	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1762	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1763	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1764	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1765
1766/* RPI_STATE_UNREG_FAILED  4		(Transitional) */
1767	(void *) emlxs_rpi_unreg_failed_action, 	/* STATE_ENTER */
1768	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1769	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1770	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1771	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1772
1773/* RPI_STATE_UNREG  5			(Wait for unreg_rpi cmpl) */
1774	(void *) emlxs_rpi_unreg_action,		/* STATE_ENTER */
1775	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1776	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1777	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1778	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1779
1780
1781/* RPI_STATE_REG  6			(Wait for reg_rpi cmpl) */
1782	(void *) emlxs_rpi_reg_action,			/* STATE_ENTER */
1783	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1784	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1785	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1786	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1787
1788/* RPI_STATE_REG_FAILED  7		(Transitional) */
1789	(void *) emlxs_rpi_reg_failed_action,		/* STATE_ENTER */
1790	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1791	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1792	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1793	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1794
1795/* RPI_STATE_REG_CMPL  8		(Transitional) */
1796	(void *) emlxs_rpi_reg_cmpl_action,		/* STATE_ENTER */
1797	(void *) emlxs_rpi_online_evt_action,  		/* RPI_ONLINE */
1798	(void *) emlxs_rpi_offline_evt_action, 		/* RPI_OFFLINE */
1799	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1800	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1801
1802
1803/* RPI_STATE_PAUSED  9			(Wait for RPI_ONLINE) */
1804	(void *) emlxs_rpi_paused_action,		/* STATE_ENTER */
1805	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1806	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1807	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1808	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1809
1810
1811/* RPI_STATE_RESUME  10			(Wait for resume_rpi mbcmpl) */
1812	(void *) emlxs_rpi_resume_action,		/* STATE_ENTER */
1813	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1814	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1815	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1816	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1817
1818/* RPI_STATE_RESUME_FAILED  11		(Transitional) */
1819	(void *) emlxs_rpi_resume_failed_action,	/* STATE_ENTER */
1820	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1821	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1822	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1823	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1824
1825/* RPI_STATE_RESUME_CMPL  12		(Transitional) */
1826	(void *) emlxs_rpi_resume_cmpl_action, 		/* STATE_ENTER */
1827	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1828	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1829	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1830	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1831
1832
1833/* RPI_STATE_ONLINE 13			(Wait for RPI_OFFLINE event) */
1834	(void *) emlxs_rpi_online_action,		/* STATE_ENTER */
1835	(void *) emlxs_rpi_online_evt_action,		/* RPI_ONLINE */
1836	(void *) emlxs_rpi_offline_evt_action,		/* RPI_OFFLINE */
1837	(void *) emlxs_rpi_pause_evt_action,		/* RPI_PAUSE */
1838	(void *) emlxs_rpi_resume_evt_action,		/* RPI_RESUME */
1839
1840}; /* emlxs_rpi_action_table[] */
1841#define	RPI_ACTION_EVENTS			5
1842#define	RPI_ACTION_STATES			\
1843	(sizeof (emlxs_rpi_action_table)/ \
1844	(RPI_ACTION_EVENTS * sizeof (void *)))
1845
1846
1847/* ************************************************************************** */
1848/* FCF Generic */
1849/* ************************************************************************** */
1850static void
1851emlxs_fcf_linkdown(emlxs_port_t *port)
1852{
1853	emlxs_hba_t *hba = HBA;
1854
1855	if (hba->state <= FC_LINK_DOWN) {
1856		return;
1857	}
1858
1859	mutex_enter(&EMLXS_PORT_LOCK);
1860
1861	if (hba->state <= FC_LINK_DOWN) {
1862		mutex_exit(&EMLXS_PORT_LOCK);
1863		return;
1864	}
1865
1866	HBASTATS.LinkDown++;
1867	EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN);
1868
1869	hba->flag &= FC_LINKDOWN_MASK;
1870	hba->discovery_timer = 0;
1871	hba->linkup_timer = 0;
1872
1873	mutex_exit(&EMLXS_PORT_LOCK);
1874
1875	emlxs_log_link_event(port);
1876
1877	return;
1878
1879} /* emlxs_fcf_linkdown() */
1880
1881
1882static void
1883emlxs_fcf_linkup(emlxs_port_t *port)
1884{
1885	emlxs_hba_t *hba = HBA;
1886	emlxs_config_t *cfg = &CFG;
1887
1888	if (hba->state >= FC_LINK_UP) {
1889		return;
1890	}
1891
1892	mutex_enter(&EMLXS_PORT_LOCK);
1893
1894	if (hba->state >= FC_LINK_UP) {
1895		mutex_exit(&EMLXS_PORT_LOCK);
1896		return;
1897	}
1898
1899	/* Check for any mode changes */
1900	emlxs_mode_set(hba);
1901
1902	HBASTATS.LinkUp++;
1903	EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP);
1904
1905	hba->discovery_timer = hba->timer_tics +
1906	    cfg[CFG_LINKUP_TIMEOUT].current +
1907	    cfg[CFG_DISC_TIMEOUT].current;
1908
1909	mutex_exit(&EMLXS_PORT_LOCK);
1910
1911	emlxs_log_link_event(port);
1912
1913	return;
1914
1915} /* emlxs_fcf_linkup() */
1916
1917
1918extern void
1919emlxs_fcf_fini(emlxs_hba_t *hba)
1920{
1921	emlxs_port_t	*port = &PPORT;
1922	emlxs_port_t	*vport;
1923	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
1924	uint32_t	i;
1925	RPIobj_t	*rpip;
1926
1927	if (!(hba->sli.sli4.flag & EMLXS_SLI4_FCF_INIT)) {
1928		return;
1929	}
1930
1931	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
1932	    "fcf_fini: %s flag=%x fcfi_online=%d.",
1933	    emlxs_fcftab_state_xlate(port, fcftab->state),
1934	    fcftab->flag, fcftab->fcfi_online);
1935
1936	if (!(fcftab->flag & EMLXS_FCFTAB_SHUTDOWN)) {
1937		(void) emlxs_fcf_shutdown_notify(port, 1);
1938	}
1939
1940	mutex_enter(&EMLXS_FCF_LOCK);
1941	hba->sli.sli4.flag &= ~EMLXS_SLI4_FCF_INIT;
1942
1943	/* Free the FCF memory */
1944
1945	kmem_free(fcftab->table,
1946	    (sizeof (FCFIobj_t) * fcftab->table_count));
1947
1948	fcftab->table = NULL;
1949	fcftab->table_count = 0;
1950
1951	/* Free the VFI memory */
1952
1953	kmem_free(hba->sli.sli4.VFI_table,
1954	    (sizeof (VFIobj_t) * hba->sli.sli4.VFICount));
1955
1956	hba->sli.sli4.VFI_table = NULL;
1957	hba->sli.sli4.VFICount = 0;
1958
1959	/* Free the VPI Fabric RPI's */
1960
1961	for (i = 0; i < MAX_VPORTS; i++) {
1962		vport = &VPORT(i);
1963		rpip = vport->vpip->fabric_rpip;
1964
1965		if (rpip->state == RPI_STATE_FREE) {
1966			continue;
1967		}
1968
1969		(void) emlxs_rpi_free(port, rpip);
1970	}
1971
1972	/* Free the RPI memory */
1973
1974	rpip = hba->sli.sli4.RPIp;
1975	for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
1976		if (rpip->state == RPI_STATE_FREE) {
1977			continue;
1978		}
1979
1980		(void) emlxs_rpi_free(port, rpip);
1981	}
1982
1983	kmem_free(hba->sli.sli4.RPIp,
1984	    (sizeof (RPIobj_t) * hba->sli.sli4.RPICount));
1985
1986	hba->sli.sli4.RPIp = NULL;
1987	hba->sli.sli4.RPICount = 0;
1988
1989	/* Free the mutex */
1990	mutex_exit(&EMLXS_FCF_LOCK);
1991	mutex_destroy(&EMLXS_FCF_LOCK);
1992
1993	return;
1994
1995} /* emlxs_fcf_fini() */
1996
1997
1998extern void
1999emlxs_fcf_init(emlxs_hba_t *hba)
2000{
2001	emlxs_port_t	*port = &PPORT;
2002	emlxs_port_t	*vport;
2003	uint16_t	i;
2004	FCFIobj_t	*fcfp;
2005	VPIobj_t	*vpip;
2006	VFIobj_t	*vfip;
2007	RPIobj_t	*rpip;
2008	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
2009
2010	if (hba->sli.sli4.flag & EMLXS_SLI4_FCF_INIT) {
2011		return;
2012	}
2013
2014	mutex_init(&EMLXS_FCF_LOCK, NULL, MUTEX_DRIVER, NULL);
2015	mutex_enter(&EMLXS_FCF_LOCK);
2016
2017	/* FCFTAB */
2018
2019	bzero(fcftab, sizeof (FCFTable_t));
2020	fcftab->state = FCFTAB_STATE_OFFLINE;
2021
2022	/* FCFI */
2023
2024	fcftab->table_count = hba->sli.sli4.FCFICount;
2025	fcftab->table = (FCFIobj_t *)kmem_zalloc(
2026	    (sizeof (FCFIobj_t) * fcftab->table_count), KM_SLEEP);
2027
2028	fcfp = fcftab->table;
2029	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2030		fcfp->index = i;
2031		fcfp->FCFI  = 0xFFFF;
2032		fcfp->state = FCFI_STATE_FREE;
2033	}
2034
2035	/* VFI */
2036
2037	hba->sli.sli4.VFI_table = (VFIobj_t *)kmem_zalloc(
2038	    (sizeof (VFIobj_t) * hba->sli.sli4.VFICount), KM_SLEEP);
2039
2040	vfip = hba->sli.sli4.VFI_table;
2041	for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
2042		vfip->VFI = emlxs_sli4_index_to_vfi(hba, i);
2043		vfip->index = i;
2044		vfip->state = VFI_STATE_OFFLINE;
2045	}
2046
2047	/* VPI */
2048
2049	for (i = 0; i < MAX_VPORTS; i++) {
2050		vport = &VPORT(i);
2051		vpip = &vport->VPIobj;
2052
2053		bzero(vpip, sizeof (VPIobj_t));
2054		vpip->index = i;
2055		vpip->VPI = emlxs_sli4_index_to_vpi(hba, i);
2056		vpip->port = vport;
2057		vpip->state = VPI_STATE_OFFLINE;
2058		vport->vpip = vpip;
2059
2060		/* Init the Fabric RPI's */
2061		rpip = &vpip->fabric_rpi;
2062		rpip->state = RPI_STATE_FREE;
2063		rpip->index = 0xffff;
2064		rpip->RPI   = FABRIC_RPI;
2065		rpip->did   = FABRIC_DID;
2066		rpip->vpip  = vpip;
2067		vpip->fabric_rpip = rpip;
2068	}
2069
2070	/* RPI */
2071
2072	hba->sli.sli4.RPIp = (RPIobj_t *)kmem_zalloc(
2073	    (sizeof (RPIobj_t) * hba->sli.sli4.RPICount), KM_SLEEP);
2074
2075	rpip = hba->sli.sli4.RPIp;
2076	for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
2077		rpip->state = RPI_STATE_FREE;
2078		rpip->RPI = emlxs_sli4_index_to_rpi(hba, i);
2079		rpip->index = i;
2080	}
2081
2082	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2083	    "fcf_init: %s flag=%x fcfi=%d vfi=%d vpi=%d rpi=%d.",
2084	    emlxs_fcftab_state_xlate(port, fcftab->state),
2085	    fcftab->flag,
2086	    fcftab->table_count,
2087	    hba->sli.sli4.VFICount,
2088	    MAX_VPORTS,
2089	    hba->sli.sli4.RPICount);
2090
2091	hba->sli.sli4.flag |= EMLXS_SLI4_FCF_INIT;
2092	mutex_exit(&EMLXS_FCF_LOCK);
2093
2094	return;
2095
2096} /* emlxs_fcf_init() */
2097
2098
2099static char *
2100emlxs_fcf_event_xlate(uint32_t state)
2101{
2102	static char buffer[32];
2103	uint32_t i;
2104	uint32_t count;
2105
2106	count = sizeof (emlxs_fcf_event_table) / sizeof (emlxs_table_t);
2107	for (i = 0; i < count; i++) {
2108		if (state == emlxs_fcf_event_table[i].code) {
2109			return (emlxs_fcf_event_table[i].string);
2110		}
2111	}
2112
2113	(void) snprintf(buffer, sizeof (buffer), "event=0x%x", state);
2114	return (buffer);
2115
2116} /* emlxs_fcf_event_xlate() */
2117
2118
2119static char *
2120emlxs_fcf_reason_xlate(uint32_t reason)
2121{
2122	static char buffer[32];
2123	uint32_t i;
2124	uint32_t count;
2125
2126	count = sizeof (emlxs_fcf_reason_table) / sizeof (emlxs_table_t);
2127	for (i = 0; i < count; i++) {
2128		if (reason == emlxs_fcf_reason_table[i].code) {
2129			return (emlxs_fcf_reason_table[i].string);
2130		}
2131	}
2132
2133	(void) snprintf(buffer, sizeof (buffer), "reason=0x%x", reason);
2134	return (buffer);
2135
2136} /* emlxs_fcf_reason_xlate() */
2137
2138
2139extern void
2140emlxs_fcf_timer_notify(emlxs_hba_t *hba)
2141{
2142	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2143
2144	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2145		return;
2146	}
2147
2148	if (fcftab->table == 0) {
2149		return;
2150	}
2151
2152	mutex_enter(&EMLXS_FCF_LOCK);
2153
2154	if (SLI4_FCOE_MODE) {
2155		emlxs_fcoe_fcftab_sol_timer(hba);
2156
2157		emlxs_fcoe_fcftab_read_timer(hba);
2158
2159		emlxs_fcoe_fcftab_offline_timer(hba);
2160	} else {
2161		emlxs_fc_fcftab_online_timer(hba);
2162	}
2163
2164	emlxs_rpi_idle_timer(hba);
2165
2166	mutex_exit(&EMLXS_FCF_LOCK);
2167
2168	return;
2169
2170} /* emlxs_fcf_timer_notify() */
2171
2172
2173extern uint32_t
2174emlxs_fcf_shutdown_notify(emlxs_port_t *port, uint32_t wait)
2175{
2176	emlxs_hba_t *hba = HBA;
2177	emlxs_port_t *pport = &PPORT;
2178	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2179	uint32_t rval = 0;
2180	uint32_t i;
2181
2182	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2183		return (1);
2184	}
2185
2186	if (!(pport->flag & EMLXS_PORT_BOUND) ||
2187	    (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2188		return (1);
2189	}
2190
2191	if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) {
2192		return (0);
2193	}
2194
2195	mutex_enter(&EMLXS_FCF_LOCK);
2196
2197	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2198	    "fcf_shutdown_notify: %s flag=%x "
2199	    "fcfi_online=%d. Shutting down FCFTAB. >",
2200	    emlxs_fcftab_state_xlate(port, fcftab->state),
2201	    fcftab->flag, fcftab->fcfi_online);
2202
2203	rval = emlxs_fcftab_event(port, FCF_EVENT_SHUTDOWN, 0);
2204
2205	if (wait && (rval == 0)) {
2206		/* Wait for shutdown flag */
2207		i = 0;
2208		while (!(fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) && (i++ < 120)) {
2209			mutex_exit(&EMLXS_FCF_LOCK);
2210			BUSYWAIT_MS(1000);
2211			mutex_enter(&EMLXS_FCF_LOCK);
2212		}
2213
2214		if (!(fcftab->flag & EMLXS_FCFTAB_SHUTDOWN)) {
2215			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2216			    "fcf_shutdown_notify: %s flag=%x "
2217			    "fcfi_online=%d. Shutdown timeout.",
2218			    emlxs_fcftab_state_xlate(port, fcftab->state),
2219			    fcftab->flag, fcftab->fcfi_online);
2220			rval = 1;
2221		}
2222	}
2223
2224	mutex_exit(&EMLXS_FCF_LOCK);
2225
2226	return (rval);
2227
2228} /* emlxs_fcf_shutdown_notify() */
2229
2230
2231extern uint32_t
2232emlxs_fcf_linkup_notify(emlxs_port_t *port)
2233{
2234	emlxs_hba_t *hba = HBA;
2235	emlxs_port_t *pport = &PPORT;
2236	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2237	uint32_t rval = 0;
2238
2239	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2240		return (1);
2241	}
2242
2243	if (!(pport->flag & EMLXS_PORT_BOUND) ||
2244	    (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2245		return (1);
2246	}
2247
2248	mutex_enter(&EMLXS_FCF_LOCK);
2249
2250	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2251	    "fcf_linkup_notify: %s flag=%x "
2252	    "fcfi_online=%d. FCFTAB Link up. >",
2253	    emlxs_fcftab_state_xlate(port, fcftab->state),
2254	    fcftab->flag, fcftab->fcfi_online);
2255
2256	rval = emlxs_fcftab_event(port, FCF_EVENT_LINKUP, 0);
2257
2258	mutex_exit(&EMLXS_FCF_LOCK);
2259
2260	return (rval);
2261
2262} /* emlxs_fcf_linkup_notify() */
2263
2264
2265extern uint32_t
2266emlxs_fcf_linkdown_notify(emlxs_port_t *port)
2267{
2268	emlxs_hba_t *hba = HBA;
2269	emlxs_port_t *pport = &PPORT;
2270	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2271	uint32_t rval = 0;
2272
2273	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2274		return (1);
2275	}
2276
2277	if (!(pport->flag & EMLXS_PORT_BOUND) ||
2278	    (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2279		return (1);
2280	}
2281
2282	mutex_enter(&EMLXS_FCF_LOCK);
2283
2284	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2285	    "fcf_linkdown_notify: %s flag=%x "
2286	    "fcfi_online=%d. FCFTAB Link down. >",
2287	    emlxs_fcftab_state_xlate(port, fcftab->state),
2288	    fcftab->flag, fcftab->fcfi_online);
2289
2290	rval = emlxs_fcftab_event(port, FCF_EVENT_LINKDOWN, 0);
2291
2292	mutex_exit(&EMLXS_FCF_LOCK);
2293
2294	return (rval);
2295
2296} /* emlxs_fcf_linkdown_notify() */
2297
2298
2299extern uint32_t
2300emlxs_fcf_cvl_notify(emlxs_port_t *port, uint32_t vpi)
2301{
2302	emlxs_hba_t *hba = HBA;
2303	emlxs_port_t *pport = &PPORT;
2304	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2305	uint32_t rval = 0;
2306
2307	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2308		return (1);
2309	}
2310
2311	if (!(pport->flag & EMLXS_PORT_BOUND) ||
2312	    (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2313		return (1);
2314	}
2315
2316	mutex_enter(&EMLXS_FCF_LOCK);
2317
2318	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2319	    "fcf_cvl_notify: %s flag=%x "
2320	    "fcfi_online=%d. FCFTAB FCF CVL. >",
2321	    emlxs_fcftab_state_xlate(port, fcftab->state),
2322	    fcftab->flag, fcftab->fcfi_online);
2323
2324	rval = emlxs_fcftab_event(port, FCF_EVENT_CVL,
2325	    (void *)((unsigned long)vpi));
2326
2327	mutex_exit(&EMLXS_FCF_LOCK);
2328
2329	return (rval);
2330
2331} /* emlxs_fcf_cvl_notify() */
2332
2333
2334extern uint32_t
2335emlxs_fcf_full_notify(emlxs_port_t *port)
2336{
2337	emlxs_hba_t *hba = HBA;
2338	emlxs_port_t *pport = &PPORT;
2339	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2340	uint32_t rval = 0;
2341
2342	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2343		return (1);
2344	}
2345
2346	if (!(pport->flag & EMLXS_PORT_BOUND) ||
2347	    (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2348		return (1);
2349	}
2350
2351	mutex_enter(&EMLXS_FCF_LOCK);
2352
2353	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2354	    "fcf_full_notify: %s flag=%x "
2355	    "fcfi_online=%d. FCFTAB FCF full. >",
2356	    emlxs_fcftab_state_xlate(port, fcftab->state),
2357	    fcftab->flag, fcftab->fcfi_online);
2358
2359	rval = emlxs_fcftab_event(port, FCF_EVENT_FCFTAB_FULL, 0);
2360
2361	mutex_exit(&EMLXS_FCF_LOCK);
2362
2363	return (rval);
2364
2365} /* emlxs_fcf_full_notify() */
2366
2367
2368extern uint32_t
2369emlxs_fcf_found_notify(emlxs_port_t *port, uint32_t fcf_index)
2370{
2371	emlxs_hba_t *hba = HBA;
2372	emlxs_port_t *pport = &PPORT;
2373	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2374	uint32_t rval = 0;
2375
2376	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2377		return (1);
2378	}
2379
2380	if (!(pport->flag & EMLXS_PORT_BOUND) ||
2381	    (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2382		return (1);
2383	}
2384
2385	mutex_enter(&EMLXS_FCF_LOCK);
2386
2387	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2388	    "fcf_found_notify: %s flag=%x "
2389	    "fcfi_online=%d. FCFTAB FCF found. >",
2390	    emlxs_fcftab_state_xlate(port, fcftab->state),
2391	    fcftab->flag, fcftab->fcfi_online);
2392
2393	rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_FOUND,
2394	    (void *)((unsigned long)fcf_index));
2395
2396	mutex_exit(&EMLXS_FCF_LOCK);
2397
2398	return (rval);
2399
2400} /* emlxs_fcf_found_notify() */
2401
2402
2403extern uint32_t
2404emlxs_fcf_changed_notify(emlxs_port_t *port, uint32_t fcf_index)
2405{
2406	emlxs_hba_t *hba = HBA;
2407	emlxs_port_t *pport = &PPORT;
2408	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2409	uint32_t rval = 0;
2410
2411	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2412		return (1);
2413	}
2414
2415	if (!(pport->flag & EMLXS_PORT_BOUND) ||
2416	    (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2417		return (1);
2418	}
2419
2420	mutex_enter(&EMLXS_FCF_LOCK);
2421
2422	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2423	    "fcf_changes_notify: %s flag=%x "
2424	    "fcfi_online=%d. FCFTAB FCF changed. >",
2425	    emlxs_fcftab_state_xlate(port, fcftab->state),
2426	    fcftab->flag, fcftab->fcfi_online);
2427
2428	rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_CHANGED,
2429	    (void *)((unsigned long)fcf_index));
2430
2431	mutex_exit(&EMLXS_FCF_LOCK);
2432
2433	return (rval);
2434
2435} /* emlxs_fcf_changed_notify() */
2436
2437
2438extern uint32_t
2439emlxs_fcf_lost_notify(emlxs_port_t *port, uint32_t fcf_index)
2440{
2441	emlxs_hba_t *hba = HBA;
2442	emlxs_port_t *pport = &PPORT;
2443	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2444	uint32_t rval = 0;
2445
2446	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2447		return (1);
2448	}
2449
2450	if (!(pport->flag & EMLXS_PORT_BOUND) ||
2451	    (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2452		return (1);
2453	}
2454
2455	mutex_enter(&EMLXS_FCF_LOCK);
2456
2457	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2458	    "fcf_lost_notify: %s flag=%x "
2459	    "fcfi_online=%d. FCFTAB FCF lost. >",
2460	    emlxs_fcftab_state_xlate(port, fcftab->state),
2461	    fcftab->flag, fcftab->fcfi_online);
2462
2463	rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_LOST,
2464	    (void *)((unsigned long)fcf_index));
2465
2466	mutex_exit(&EMLXS_FCF_LOCK);
2467
2468	return (rval);
2469
2470} /* emlxs_fcf_lost_notify() */
2471
2472
2473/* ************************************************************************** */
2474/* FCFTAB Generic */
2475/* ************************************************************************** */
2476
2477static char *
2478emlxs_fcftab_state_xlate(emlxs_port_t *port, uint32_t state)
2479{
2480	emlxs_hba_t *hba = HBA;
2481
2482	if (SLI4_FCOE_MODE) {
2483		return (emlxs_fcoe_fcftab_state_xlate(state));
2484	} else {
2485		return (emlxs_fc_fcftab_state_xlate(state));
2486	}
2487
2488} /* emlxs_fcftab_state_xlate() */
2489
2490static uint32_t
2491emlxs_fcftab_event(emlxs_port_t *port, uint32_t evt, void *arg1)
2492{
2493	emlxs_hba_t *hba = HBA;
2494
2495	if (SLI4_FCOE_MODE) {
2496		return (emlxs_fcoe_fcftab_event(port, evt, arg1));
2497	} else {
2498		return (emlxs_fc_fcftab_event(port, evt, arg1));
2499	}
2500
2501} /* emlxs_fcftab_event() */
2502
2503
2504/*ARGSUSED*/
2505static uint32_t
2506emlxs_fcftab_shutdown_action(emlxs_port_t *port, uint32_t evt,
2507    void *arg1)
2508{
2509	emlxs_hba_t *hba = HBA;
2510	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2511	FCFIobj_t *fcfp;
2512	uint32_t i;
2513	uint32_t online;
2514
2515	if (fcftab->state != FCFTAB_STATE_SHUTDOWN) {
2516		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2517		    "fcftab_shutdown_action:%x %s:%s arg=%p. "
2518		    "Invalid state. <",
2519		    fcftab->TID,
2520		    emlxs_fcftab_state_xlate(port, fcftab->state),
2521		    emlxs_fcf_event_xlate(evt), arg1);
2522		return (1);
2523	}
2524
2525	fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
2526
2527	if (fcftab->prev_state != FCFTAB_STATE_SHUTDOWN) {
2528		/* Offline all FCF's */
2529		online = 0;
2530		fcfp = fcftab->table;
2531		for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2532
2533			if (fcfp->state <= FCFI_STATE_OFFLINE) {
2534				continue;
2535			}
2536
2537			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2538			    "fcftab_shutdown_action:%x fcfi_online=%d. "
2539			    "Offlining FCFI:%d. >",
2540			    fcftab->TID,
2541			    fcftab->fcfi_online,
2542			    fcfp->fcf_index);
2543
2544			(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE,
2545			    fcfp);
2546
2547			online++;
2548		}
2549
2550		if (!online) {
2551			goto done;
2552		}
2553
2554		return (0);
2555	}
2556
2557	/* Check FCF states */
2558	online = 0;
2559	fcfp = fcftab->table;
2560	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2561
2562		if (fcfp->state <= FCFI_STATE_OFFLINE) {
2563			continue;
2564		}
2565
2566		online++;
2567	}
2568
2569	if (online) {
2570		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2571		    "fcftab_shutdown_action:%x %s:%s arg=%p. "
2572		    "fcfi_online=%d,%d <",
2573		    fcftab->TID,
2574		    emlxs_fcftab_state_xlate(port, fcftab->state),
2575		    emlxs_fcf_event_xlate(evt), arg1,
2576		    online, fcftab->fcfi_online);
2577
2578		return (0);
2579	}
2580
2581done:
2582	/* Free FCF table */
2583	fcfp = fcftab->table;
2584	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2585
2586		if (fcfp->state == FCFI_STATE_FREE) {
2587			continue;
2588		}
2589
2590		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2591		    "fcftab_shutdown_action:%x. Freeing FCFI:%d. >",
2592		    fcftab->TID,
2593		    fcfp->fcf_index);
2594
2595		(void) emlxs_fcfi_free(port, fcfp);
2596	}
2597
2598	/* Clean the selection table */
2599	bzero(fcftab->fcfi, sizeof (fcftab->fcfi));
2600	fcftab->fcfi_count = 0;
2601
2602	fcftab->flag |= EMLXS_FCFTAB_SHUTDOWN;
2603
2604	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2605	    "fcftab_shutdown_action:%x %s:%s arg=%p flag=%x fcfi_online=%d. "
2606	    "Shutdown. <",
2607	    fcftab->TID,
2608	    emlxs_fcftab_state_xlate(port, fcftab->state),
2609	    emlxs_fcf_event_xlate(evt), arg1,
2610	    fcftab->flag, fcftab->fcfi_online);
2611
2612	return (0);
2613
2614} /* emlxs_fcftab_shutdown_action() */
2615
2616
2617/* ************************************************************************** */
2618/* FC FCFTAB */
2619/* ************************************************************************** */
2620
2621static char *
2622emlxs_fc_fcftab_state_xlate(uint32_t state)
2623{
2624	static char buffer[32];
2625	uint32_t i;
2626	uint32_t count;
2627
2628	count = sizeof (emlxs_fc_fcftab_state_table) / sizeof (emlxs_table_t);
2629	for (i = 0; i < count; i++) {
2630		if (state == emlxs_fc_fcftab_state_table[i].code) {
2631			return (emlxs_fc_fcftab_state_table[i].string);
2632		}
2633	}
2634
2635	(void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
2636	return (buffer);
2637
2638} /* emlxs_fc_fcftab_state_xlate() */
2639
2640
2641static uint32_t
2642emlxs_fc_fcftab_action(emlxs_port_t *port, uint32_t evt,
2643    void *arg1)
2644{
2645	emlxs_hba_t *hba = HBA;
2646	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2647	uint32_t rval = 0;
2648	uint32_t(*func) (emlxs_port_t *, uint32_t, void *);
2649	uint32_t index;
2650	uint32_t events;
2651	uint16_t state;
2652
2653	/* Convert event to action table index */
2654	switch (evt) {
2655	case FCF_EVENT_STATE_ENTER:
2656		index = 0;
2657		break;
2658	case FCF_EVENT_SHUTDOWN:
2659		index = 1;
2660		break;
2661	case FCF_EVENT_LINKUP:
2662		index = 2;
2663		break;
2664	case FCF_EVENT_LINKDOWN:
2665		index = 3;
2666		break;
2667	case FCF_EVENT_FCFI_ONLINE:
2668		index = 4;
2669		break;
2670	case FCF_EVENT_FCFI_OFFLINE:
2671		index = 5;
2672		break;
2673	default:
2674		return (1);
2675	}
2676
2677	events = FC_FCFTAB_ACTION_EVENTS;
2678	state  = fcftab->state;
2679
2680	index += (state * events);
2681	func   = (uint32_t(*) (emlxs_port_t *, uint32_t, void *))
2682	    emlxs_fc_fcftab_action_table[index];
2683
2684	if (!func) {
2685		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
2686		    "fc_fcftab_action:%x %s:%s arg=%p. No action. <",
2687		    fcftab->TID,
2688		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2689		    emlxs_fcf_event_xlate(evt), arg1);
2690
2691		return (1);
2692	}
2693
2694	rval = (func)(port, evt, arg1);
2695
2696	return (rval);
2697
2698} /* emlxs_fc_fcftab_action() */
2699
2700
2701static uint32_t
2702emlxs_fc_fcftab_event(emlxs_port_t *port, uint32_t evt,
2703    void *arg1)
2704{
2705	emlxs_hba_t *hba = HBA;
2706	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2707	uint32_t rval = 0;
2708
2709	/* Filter events */
2710	switch (evt) {
2711	case FCF_EVENT_SHUTDOWN:
2712	case FCF_EVENT_LINKUP:
2713	case FCF_EVENT_LINKDOWN:
2714	case FCF_EVENT_FCFI_ONLINE:
2715	case FCF_EVENT_FCFI_OFFLINE:
2716		break;
2717
2718	default:
2719		return (1);
2720	}
2721
2722	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
2723	    "fc_fcftab_event:%x %s:%s arg=%p.",
2724	    fcftab->TID,
2725	    emlxs_fc_fcftab_state_xlate(fcftab->state),
2726	    emlxs_fcf_event_xlate(evt), arg1);
2727
2728	rval = emlxs_fc_fcftab_action(port, evt, arg1);
2729
2730	return (rval);
2731
2732} /* emlxs_fc_fcftab_event() */
2733
2734
2735/* EMLXS_FCF_LOCK must be held to enter */
2736/*ARGSUSED*/
2737static uint32_t
2738emlxs_fc_fcftab_state(emlxs_port_t *port, uint16_t state, uint16_t reason,
2739    uint32_t explain, void *arg1)
2740{
2741	emlxs_hba_t *hba = HBA;
2742	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2743	uint32_t rval = 0;
2744
2745	if (state >= FC_FCFTAB_ACTION_STATES) {
2746		return (1);
2747	}
2748
2749	if ((fcftab->state == state) &&
2750	    (reason != FCF_REASON_REENTER)) {
2751		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2752		    "fcftab_state:%x %s:%s:0x%x arg=%p. "
2753		    "State not changed. <",
2754		    fcftab->TID,
2755		    emlxs_fc_fcftab_state_xlate(state),
2756		    emlxs_fcf_reason_xlate(reason),
2757		    explain, arg1);
2758		return (1);
2759	}
2760
2761	if (!reason) {
2762		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2763		    "fcftab_state:%x %s-->%s arg=%p",
2764		    fcftab->TID,
2765		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2766		    emlxs_fc_fcftab_state_xlate(state), arg1);
2767	} else if (reason == FCF_REASON_EVENT) {
2768		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2769		    "fcftab_state:%x %s-->%s:%s:%s arg=%p",
2770		    fcftab->TID,
2771		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2772		    emlxs_fc_fcftab_state_xlate(state),
2773		    emlxs_fcf_reason_xlate(reason),
2774		    emlxs_fcf_event_xlate(explain), arg1);
2775	} else if (explain) {
2776		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2777		    "fcftab_state:%x %s-->%s:%s:0x%x arg=%p",
2778		    fcftab->TID,
2779		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2780		    emlxs_fc_fcftab_state_xlate(state),
2781		    emlxs_fcf_reason_xlate(reason),
2782		    explain, arg1);
2783	} else {
2784		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2785		    "fcftab_state:%x %s-->%s:%s arg=%p",
2786		    fcftab->TID,
2787		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2788		    emlxs_fc_fcftab_state_xlate(state),
2789		    emlxs_fcf_reason_xlate(reason), arg1);
2790	}
2791
2792	fcftab->prev_state = fcftab->state;
2793	fcftab->prev_reason = fcftab->reason;
2794	fcftab->state = state;
2795	fcftab->reason = reason;
2796
2797	rval = emlxs_fc_fcftab_action(port, FCF_EVENT_STATE_ENTER, arg1);
2798
2799	return (rval);
2800
2801} /* emlxs_fc_fcftab_state() */
2802
2803
2804static void
2805emlxs_fc_fcftab_online_timer(emlxs_hba_t *hba)
2806{
2807	emlxs_port_t *port = &PPORT;
2808	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2809
2810	/* Check FCF timer */
2811	if (!fcftab->online_timer ||
2812	    (hba->timer_tics < fcftab->online_timer)) {
2813		return;
2814	}
2815	fcftab->online_timer = 0;
2816
2817	switch (fcftab->state) {
2818	case FC_FCFTAB_STATE_ONLINE:
2819		emlxs_fcf_linkup(port);
2820
2821		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
2822		fcftab->flag |= EMLXS_FC_FCFTAB_TOPO_REQ;
2823		fcftab->generation++;
2824
2825		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2826		    "fc_fcftab_online_timer:%x %s gen=%x. Read topology. >",
2827		    fcftab->TID,
2828		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2829		    fcftab->generation);
2830
2831		(void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
2832		    FCF_REASON_EVENT, 0, 0);
2833		break;
2834
2835	default:
2836		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2837		    "fc_fcftab_online_timer:%x %s",
2838		    fcftab->TID,
2839		    emlxs_fc_fcftab_state_xlate(fcftab->state));
2840		break;
2841	}
2842
2843	return;
2844
2845}  /* emlxs_fc_fcftab_online_timer() */
2846
2847
2848/*ARGSUSED*/
2849static uint32_t
2850emlxs_fc_fcftab_offline_action(emlxs_port_t *port, uint32_t evt,
2851    void *arg1)
2852{
2853	emlxs_hba_t *hba = HBA;
2854	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2855	uint32_t rval = 0;
2856
2857	if (fcftab->state != FC_FCFTAB_STATE_OFFLINE) {
2858		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2859		    "fc_fcftab_offline_action:%x %s:%s arg=%p. "
2860		    "Invalid state. <",
2861		    fcftab->TID,
2862		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2863		    emlxs_fcf_event_xlate(evt), arg1);
2864		return (1);
2865	}
2866
2867	fcftab->flag &= ~EMLXS_FC_FCFTAB_OFFLINE_REQ;
2868
2869	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
2870		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2871		    "fc_fcftab_offline_action:%x %s:%s arg=%p flag=%x. "
2872		    "Handling request.",
2873		    fcftab->TID,
2874		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2875		    emlxs_fcf_event_xlate(evt), arg1,
2876		    fcftab->flag);
2877
2878		rval = emlxs_fc_fcftab_req_handler(port, arg1);
2879		return (rval);
2880	}
2881
2882	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2883	    "fc_fcftab_offline_action:%x %s:%s arg=%p fcfi_online=%d. "
2884	    "Offline. <",
2885	    fcftab->TID,
2886	    emlxs_fc_fcftab_state_xlate(fcftab->state),
2887	    emlxs_fcf_event_xlate(evt), arg1,
2888	    fcftab->fcfi_online);
2889
2890	return (0);
2891
2892} /* emlxs_fc_fcftab_offline_action() */
2893
2894
2895/*ARGSUSED*/
2896static uint32_t
2897emlxs_fc_fcftab_online_action(emlxs_port_t *port, uint32_t evt,
2898    void *arg1)
2899{
2900	emlxs_hba_t *hba = HBA;
2901	emlxs_port_t *pport = &PPORT;
2902	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2903	uint32_t rval = 0;
2904
2905	if (fcftab->state != FC_FCFTAB_STATE_ONLINE) {
2906		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2907		    "fc_fcftab_online_action:%x %s:%s arg=%p. "
2908		    "Invalid state. <",
2909		    fcftab->TID,
2910		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2911		    emlxs_fcf_event_xlate(evt), arg1);
2912		return (1);
2913	}
2914
2915	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
2916		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2917		    "fc_fcftab_online_action:%x flag=%x. "
2918		    "Handling requested.",
2919		    fcftab->TID,
2920		    fcftab->flag);
2921
2922		rval = emlxs_fc_fcftab_req_handler(port, arg1);
2923		return (rval);
2924	}
2925
2926	if (fcftab->fcfi_online == 0) {
2927		if (!(pport->flag & EMLXS_PORT_BOUND) ||
2928		    (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2929			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2930			    "fc_fcftab_online_action:%x %s:%s "
2931			    "fcfi_online=0. Pport not bound. <",
2932			    fcftab->TID,
2933			    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
2934			    emlxs_fcf_event_xlate(evt));
2935		} else {
2936			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2937			    "fc_fcftab_online_action:%x %s:%s "
2938			    "fcfi_online=0. Starting online timer. <",
2939			    fcftab->TID,
2940			    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
2941			    emlxs_fcf_event_xlate(evt));
2942
2943			/* Start the online timer */
2944			fcftab->online_timer = hba->timer_tics + 1;
2945		}
2946
2947		emlxs_fcf_linkdown(port);
2948
2949		return (0);
2950	}
2951
2952	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2953	    "fc_fcftab_online_action:%x flag=%x fcfi_online=%d. "
2954	    "Online. <",
2955	    fcftab->TID,
2956	    fcftab->flag,
2957	    fcftab->fcfi_online);
2958
2959	emlxs_fcf_linkup(port);
2960
2961	return (0);
2962
2963} /* emlxs_fc_fcftab_online_action() */
2964
2965
2966/*ARGSUSED*/
2967static uint32_t
2968emlxs_fc_fcftab_topo_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
2969{
2970	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
2971	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2972	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
2973	MATCHMAP *mp;
2974	uint8_t *alpa_map;
2975	uint32_t j;
2976	uint16_t TID;
2977
2978	mutex_enter(&EMLXS_FCF_LOCK);
2979	TID = (uint16_t)((unsigned long)mbq->context);
2980
2981	if (fcftab->state != FC_FCFTAB_STATE_TOPO) {
2982		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2983		    "fc_fcftab_topo_mbcmpl:%x state=%s.",
2984		    TID,
2985		    emlxs_fc_fcftab_state_xlate(fcftab->state));
2986
2987		mutex_exit(&EMLXS_FCF_LOCK);
2988		return (0);
2989	}
2990
2991	if (TID != fcftab->generation) {
2992		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2993		    "fc_fcftab_topo_mbcmpl:%x %s. "
2994		    "Incorrect generation %x. Dropping.",
2995		    TID,
2996		    emlxs_fc_fcftab_state_xlate(fcftab->state),
2997		    fcftab->generation);
2998
2999		mutex_exit(&EMLXS_FCF_LOCK);
3000		return (0);
3001	}
3002
3003	if (mb4->mbxStatus) {
3004		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3005		    "fc_fcftab_topo_mbcmpl:%x failed. %s. >",
3006		    fcftab->TID,
3007		    emlxs_mb_xlate_status(mb4->mbxStatus));
3008
3009		if (mb4->mbxStatus == MBXERR_NO_RESOURCES) {
3010			(void) emlxs_fc_fcftab_state(port,
3011			    FC_FCFTAB_STATE_TOPO_FAILED,
3012			    FCF_REASON_MBOX_BUSY, mb4->mbxStatus, 0);
3013		} else {
3014			(void) emlxs_fc_fcftab_state(port,
3015			    FC_FCFTAB_STATE_TOPO_FAILED,
3016			    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
3017		}
3018
3019		mutex_exit(&EMLXS_FCF_LOCK);
3020		return (0);
3021	}
3022
3023	if (mb4->un.varReadLA.attType == AT_LINK_DOWN) {
3024		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3025		    "fc_fcftab_topo_mbcmpl:%x  Linkdown attention. "
3026		    "Offline requested.",
3027		    fcftab->TID);
3028
3029		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
3030		fcftab->flag |= EMLXS_FC_FCFTAB_OFFLINE_REQ;
3031		(void) emlxs_fc_fcftab_req_handler(port, 0);
3032
3033		mutex_exit(&EMLXS_FCF_LOCK);
3034		return (0);
3035	}
3036
3037	if (hba->link_event_tag != mb4->un.varReadLA.eventTag) {
3038		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3039		    "fc_fcftab_topo_mbcmpl:%x Event tag invalid. %x != %x",
3040		    fcftab->TID,
3041		    hba->link_event_tag, mb4->un.varReadLA.eventTag);
3042	}
3043
3044	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3045	    "fc_fcftab_topo_mbcmpl:%x state=%s type=%s iotag=%d "
3046	    "alpa=%x. >",
3047	    fcftab->TID,
3048	    emlxs_fc_fcftab_state_xlate(fcftab->state),
3049	    (mb4->un.varReadLA.attType == AT_LINK_UP)?"linkup":"linkdown",
3050	    hba->link_event_tag,
3051	    (uint32_t)mb4->un.varReadLA.granted_AL_PA);
3052
3053	/* Link is up */
3054
3055	/* Save the linkspeed & topology */
3056	hba->linkspeed = mb4->un.varReadLA.UlnkSpeed;
3057	hba->topology = mb4->un.varReadLA.topology;
3058
3059	if (hba->topology != TOPOLOGY_LOOP) {
3060		port->did = 0;
3061		port->lip_type = 0;
3062		hba->flag &= ~FC_BYPASSED_MODE;
3063		bzero((caddr_t)port->alpa_map, 128);
3064
3065		goto done;
3066	}
3067
3068	/* TOPOLOGY_LOOP */
3069
3070	port->lip_type = mb4->un.varReadLA.lipType;
3071
3072	if (mb4->un.varReadLA.pb) {
3073		hba->flag |= FC_BYPASSED_MODE;
3074	} else {
3075		hba->flag &= ~FC_BYPASSED_MODE;
3076	}
3077
3078	/* Save the granted_alpa and alpa_map */
3079
3080	port->granted_alpa = mb4->un.varReadLA.granted_AL_PA;
3081	mp = (MATCHMAP *)mbq->bp;
3082	alpa_map = (uint8_t *)port->alpa_map;
3083
3084	bcopy((caddr_t)mp->virt, (caddr_t)alpa_map, 128);
3085
3086	/* Check number of devices in map */
3087	if (alpa_map[0] > 127) {
3088		alpa_map[0] = 127;
3089	}
3090
3091	EMLXS_MSGF(EMLXS_CONTEXT,
3092	    &emlxs_link_atten_msg,
3093	    "alpa_map: %d device(s): "
3094	    "%02x %02x %02x %02x %02x %02x %02x %02x",
3095	    alpa_map[0], alpa_map[1],
3096	    alpa_map[2], alpa_map[3],
3097	    alpa_map[4], alpa_map[5],
3098	    alpa_map[6], alpa_map[7],
3099	    alpa_map[8]);
3100
3101	for (j = 9; j <= alpa_map[0]; j += 8) {
3102		EMLXS_MSGF(EMLXS_CONTEXT,
3103		    &emlxs_link_atten_msg,
3104		    "alpa_map:               "
3105		    "%02x %02x %02x %02x %02x %02x %02x %02x",
3106		    alpa_map[j],
3107		    alpa_map[j + 1],
3108		    alpa_map[j + 2],
3109		    alpa_map[j + 3],
3110		    alpa_map[j + 4],
3111		    alpa_map[j + 5],
3112		    alpa_map[j + 6],
3113		    alpa_map[j + 7]);
3114	}
3115
3116done:
3117
3118	(void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_CMPL,
3119	    0, 0, 0);
3120
3121	mutex_exit(&EMLXS_FCF_LOCK);
3122	return (0);
3123
3124} /* emlxs_fc_fcftab_topo_mbcmpl() */
3125
3126
3127/*ARGSUSED*/
3128static uint32_t
3129emlxs_fc_fcftab_topo_action(emlxs_port_t *port, uint32_t evt,
3130    void *arg1)
3131{
3132	emlxs_hba_t *hba = HBA;
3133	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3134	MAILBOXQ *mbq;
3135	MAILBOX4 *mb4;
3136	uint32_t rval = 0;
3137	MATCHMAP *mp;
3138
3139	if (fcftab->state != FC_FCFTAB_STATE_TOPO) {
3140		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3141		    "fc_fcftab_topo_action:%x %s:%s arg=%p. "
3142		    "Invalid state. <",
3143		    fcftab->TID,
3144		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3145		    emlxs_fcf_event_xlate(evt), arg1);
3146		return (1);
3147	}
3148
3149	if ((fcftab->prev_state != FC_FCFTAB_STATE_TOPO_FAILED) ||
3150	    (fcftab->flag & EMLXS_FC_FCFTAB_TOPO_REQ)) {
3151		fcftab->flag &= ~EMLXS_FC_FCFTAB_TOPO_REQ;
3152		fcftab->attempts = 0;
3153	}
3154
3155	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3156		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3157		    "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3158		    "Handling request.",
3159		    fcftab->TID,
3160		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3161		    emlxs_fcf_event_xlate(evt), arg1,
3162		    fcftab->generation,
3163		    fcftab->flag);
3164
3165		rval = emlxs_fc_fcftab_req_handler(port, arg1);
3166		return (rval);
3167	}
3168
3169	if (fcftab->attempts == 0) {
3170		fcftab->TID = fcftab->generation;
3171	}
3172
3173	if (hba->topology != TOPOLOGY_LOOP) {
3174		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3175		    "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3176		    "Fabric Topology. Skipping READ_TOPO.",
3177		    fcftab->TID,
3178		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3179		    emlxs_fcf_event_xlate(evt), arg1,
3180		    fcftab->generation,
3181		    fcftab->flag);
3182
3183		port->did = 0;
3184		port->lip_type = 0;
3185		hba->flag &= ~FC_BYPASSED_MODE;
3186		bzero((caddr_t)port->alpa_map, 128);
3187
3188		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
3189		    FCF_REASON_EVENT, evt, arg1);
3190		return (rval);
3191	}
3192
3193	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3194	    "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3195	    "Sending READ_TOPO. <",
3196	    fcftab->TID,
3197	    emlxs_fc_fcftab_state_xlate(fcftab->state),
3198	    emlxs_fcf_event_xlate(evt), arg1,
3199	    fcftab->generation,
3200	    fcftab->flag);
3201
3202	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
3203		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_FAILED,
3204		    FCF_REASON_NO_MBOX, 0, arg1);
3205		return (rval);
3206	}
3207	mb4 = (MAILBOX4*)mbq;
3208	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
3209
3210	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
3211		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3212
3213		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_FAILED,
3214		    FCF_REASON_NO_BUFFER, 0, arg1);
3215		return (rval);
3216	}
3217	bzero(mp->virt, mp->size);
3218
3219	mbq->nonembed = NULL;
3220	mbq->bp = (void *)mp;
3221	mbq->mbox_cmpl = emlxs_fc_fcftab_topo_mbcmpl;
3222	mbq->context = (void *)((unsigned long)fcftab->TID);
3223	mbq->port = (void *)port;
3224
3225	mb4->un.varSLIConfig.be.embedded = 0;
3226	mb4->mbxCommand = MBX_READ_TOPOLOGY;
3227	mb4->mbxOwner = OWN_HOST;
3228
3229	mb4->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
3230	mb4->un.varReadLA.un.lilpBde64.addrHigh = PADDR_HI(mp->phys);
3231	mb4->un.varReadLA.un.lilpBde64.addrLow = PADDR_LO(mp->phys);
3232
3233	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3234	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3235		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
3236		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3237
3238		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_FAILED,
3239		    FCF_REASON_SEND_FAILED, rval, arg1);
3240
3241		return (rval);
3242	}
3243
3244	return (0);
3245
3246} /* emlxs_fc_fcftab_topo_action() */
3247
3248
3249/*ARGSUSED*/
3250static uint32_t
3251emlxs_fc_fcftab_topo_failed_action(emlxs_port_t *port, uint32_t evt,
3252    void *arg1)
3253{
3254	emlxs_hba_t *hba = HBA;
3255	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3256	uint32_t rval = 0;
3257
3258	fcftab->attempts++;
3259
3260	if (fcftab->state != FC_FCFTAB_STATE_TOPO_FAILED) {
3261		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3262		    "fc_fcftab_topo_failed_action:%x %s:%s arg=%p "
3263		    "attempt=%d. Invalid state. <",
3264		    fcftab->TID,
3265		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3266		    emlxs_fcf_event_xlate(evt),
3267		    arg1, fcftab->attempts);
3268		return (1);
3269	}
3270
3271	if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
3272	    (fcftab->reason == FCF_REASON_SEND_FAILED) ||
3273	    (fcftab->attempts >= 3)) {
3274		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3275		    "fc_fcftab_topo_failed_action:%x %s:%s arg=%p "
3276		    "attempt=%d reason=%x. Giving up.",
3277		    fcftab->TID,
3278		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3279		    emlxs_fcf_event_xlate(evt), arg1,
3280		    fcftab->attempts,
3281		    fcftab->reason);
3282
3283		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_CMPL,
3284		    FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3285
3286	} else {
3287		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3288		    "fc_fcftab_topo_failed_action:%x %s:%s arg=%p "
3289		    "attempt=%d reason=%x. Retrying.",
3290		    fcftab->TID,
3291		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3292		    emlxs_fcf_event_xlate(evt), arg1,
3293		    fcftab->attempts,
3294		    fcftab->reason);
3295
3296		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
3297		    FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3298	}
3299
3300	return (rval);
3301
3302} /* emlxs_fc_fcftab_topo_failed_action() */
3303
3304
3305/*ARGSUSED*/
3306static uint32_t
3307emlxs_fc_fcftab_topo_cmpl_action(emlxs_port_t *port, uint32_t evt,
3308    void *arg1)
3309{
3310	emlxs_hba_t *hba = HBA;
3311	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3312	uint32_t rval = 0;
3313
3314	if (fcftab->state != FC_FCFTAB_STATE_TOPO_CMPL) {
3315		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3316		    "fc_fcftab_topo_cmpl_action:%x %s:%s arg=%p. "
3317		    "Invalid state. <",
3318		    fcftab->TID,
3319		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3320		    emlxs_fcf_event_xlate(evt), arg1);
3321		return (1);
3322	}
3323
3324	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3325	    "fc_fcftab_topo_cmpl_action:%x attempts=%d. "
3326	    "Config link.",
3327	    fcftab->TID,
3328	    fcftab->attempts);
3329
3330	rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
3331	    FCF_REASON_EVENT, evt, arg1);
3332
3333	return (rval);
3334
3335} /* emlxs_fc_fcftab_topo_cmpl_action() */
3336
3337
3338/*ARGSUSED*/
3339static uint32_t
3340emlxs_fc_fcftab_cfglink_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
3341{
3342	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
3343	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3344	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
3345	uint16_t TID;
3346
3347	mutex_enter(&EMLXS_FCF_LOCK);
3348	TID = (uint16_t)((unsigned long)mbq->context);
3349
3350	if (fcftab->state != FC_FCFTAB_STATE_CFGLINK) {
3351		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3352		    "fc_fcftab_cfglink_mbcmpl:%x state=%s.",
3353		    TID,
3354		    emlxs_fc_fcftab_state_xlate(fcftab->state));
3355
3356		mutex_exit(&EMLXS_FCF_LOCK);
3357		return (0);
3358	}
3359
3360	if (TID != fcftab->generation) {
3361		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3362		    "fc_fcftab_cfglink_mbcmpl:%x %s. "
3363		    "Incorrect generation %x. Dropping.",
3364		    TID,
3365		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3366		    fcftab->generation);
3367
3368		mutex_exit(&EMLXS_FCF_LOCK);
3369		return (0);
3370	}
3371
3372	if (mb4->mbxStatus) {
3373		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3374		    "fc_fcftab_cfglink_mbcmpl:%x failed. %s. >",
3375		    fcftab->TID,
3376		    emlxs_mb_xlate_status(mb4->mbxStatus));
3377
3378		if (mb4->mbxStatus == MBXERR_NO_RESOURCES) {
3379			(void) emlxs_fc_fcftab_state(port,
3380			    FC_FCFTAB_STATE_CFGLINK_FAILED,
3381			    FCF_REASON_MBOX_BUSY, mb4->mbxStatus, 0);
3382		} else {
3383			(void) emlxs_fc_fcftab_state(port,
3384			    FC_FCFTAB_STATE_CFGLINK_FAILED,
3385			    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
3386		}
3387
3388		mutex_exit(&EMLXS_FCF_LOCK);
3389		return (0);
3390	}
3391
3392	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3393	    "fc_fcftab_cfglink_mbcmpl:%x. >",
3394	    fcftab->TID);
3395
3396	(void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK_CMPL,
3397	    0, 0, 0);
3398
3399	mutex_exit(&EMLXS_FCF_LOCK);
3400	return (0);
3401
3402} /* emlxs_fc_fcftab_cfglink_mbcmpl() */
3403
3404
3405
3406/*ARGSUSED*/
3407static uint32_t
3408emlxs_fc_fcftab_cfglink_action(emlxs_port_t *port, uint32_t evt,
3409    void *arg1)
3410{
3411	emlxs_hba_t *hba = HBA;
3412	emlxs_config_t *cfg = &CFG;
3413	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3414	MAILBOXQ *mbq;
3415	MAILBOX4 *mb4;
3416	uint32_t rval = 0;
3417
3418	if (fcftab->state != FC_FCFTAB_STATE_CFGLINK) {
3419		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3420		    "fc_fcftab_cfglink_action:%x %s:%s arg=%p. "
3421		    "Invalid state. <",
3422		    fcftab->TID,
3423		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3424		    emlxs_fcf_event_xlate(evt), arg1);
3425		return (1);
3426	}
3427
3428	if ((fcftab->prev_state != FC_FCFTAB_STATE_CFGLINK_FAILED) ||
3429	    (fcftab->flag & EMLXS_FC_FCFTAB_CFGLINK_REQ)) {
3430		fcftab->flag &= ~EMLXS_FC_FCFTAB_CFGLINK_REQ;
3431		fcftab->attempts = 0;
3432	}
3433
3434	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3435		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3436		    "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3437		    "Handling request.",
3438		    fcftab->TID,
3439		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3440		    emlxs_fcf_event_xlate(evt), arg1,
3441		    fcftab->generation,
3442		    fcftab->flag);
3443
3444		rval = emlxs_fc_fcftab_req_handler(port, arg1);
3445		return (rval);
3446	}
3447
3448	if (fcftab->attempts == 0) {
3449		fcftab->TID = fcftab->generation;
3450	}
3451
3452	if (hba->topology != TOPOLOGY_LOOP) {
3453		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3454		    "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3455		    "Fabric Topology. Skipping CONFIG_LINK.",
3456		    fcftab->TID,
3457		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3458		    emlxs_fcf_event_xlate(evt), arg1,
3459		    fcftab->generation,
3460		    fcftab->flag);
3461
3462		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
3463		    FCF_REASON_EVENT, evt, arg1);
3464		return (rval);
3465	}
3466
3467	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3468	    "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3469	    "Sending CONFIG_LINK. <",
3470	    fcftab->TID,
3471	    emlxs_fc_fcftab_state_xlate(fcftab->state),
3472	    emlxs_fcf_event_xlate(evt), arg1,
3473	    fcftab->generation,
3474	    fcftab->flag);
3475
3476	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
3477		rval = emlxs_fc_fcftab_state(port,
3478		    FC_FCFTAB_STATE_CFGLINK_FAILED,
3479		    FCF_REASON_NO_MBOX, 0, arg1);
3480		return (rval);
3481	}
3482	mb4 = (MAILBOX4*)mbq;
3483	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
3484
3485	mbq->nonembed = NULL;
3486	mbq->mbox_cmpl = emlxs_fc_fcftab_cfglink_mbcmpl;
3487	mbq->context = (void *)((unsigned long)fcftab->TID);
3488	mbq->port = (void *)port;
3489
3490	mb4->un.varSLIConfig.be.embedded = 0;
3491	mb4->mbxCommand = MBX_CONFIG_LINK;
3492	mb4->mbxOwner = OWN_HOST;
3493
3494	if (cfg[CFG_CR_DELAY].current) {
3495		mb4->un.varCfgLnk.cr = 1;
3496		mb4->un.varCfgLnk.ci = 1;
3497		mb4->un.varCfgLnk.cr_delay = cfg[CFG_CR_DELAY].current;
3498		mb4->un.varCfgLnk.cr_count = cfg[CFG_CR_COUNT].current;
3499	}
3500
3501	if (cfg[CFG_ACK0].current) {
3502		mb4->un.varCfgLnk.ack0_enable = 1;
3503	}
3504
3505	mb4->un.varCfgLnk.myId = port->did;
3506	mb4->un.varCfgLnk.edtov = hba->fc_edtov;
3507	mb4->un.varCfgLnk.arbtov = hba->fc_arbtov;
3508	mb4->un.varCfgLnk.ratov = hba->fc_ratov;
3509	mb4->un.varCfgLnk.rttov = hba->fc_rttov;
3510	mb4->un.varCfgLnk.altov = hba->fc_altov;
3511	mb4->un.varCfgLnk.crtov = hba->fc_crtov;
3512	mb4->un.varCfgLnk.citov = hba->fc_citov;
3513
3514	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3515	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3516		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3517
3518		rval = emlxs_fc_fcftab_state(port,
3519		    FC_FCFTAB_STATE_CFGLINK_FAILED,
3520		    FCF_REASON_SEND_FAILED, rval, arg1);
3521
3522		return (rval);
3523	}
3524
3525	return (0);
3526
3527} /* emlxs_fc_fcftab_cfglink_action() */
3528
3529
3530/*ARGSUSED*/
3531static uint32_t
3532emlxs_fc_fcftab_cfglink_failed_action(emlxs_port_t *port, uint32_t evt,
3533    void *arg1)
3534{
3535	emlxs_hba_t *hba = HBA;
3536	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3537	uint32_t rval = 0;
3538
3539	fcftab->attempts++;
3540
3541	if (fcftab->state != FC_FCFTAB_STATE_CFGLINK_FAILED) {
3542		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3543		    "fc_fcftab_cfglink_failed_action:%x %s:%s arg=%p "
3544		    "attempt=%d. Invalid state. <",
3545		    fcftab->TID,
3546		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3547		    emlxs_fcf_event_xlate(evt),
3548		    arg1, fcftab->attempts);
3549		return (1);
3550	}
3551
3552	if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
3553	    (fcftab->reason == FCF_REASON_SEND_FAILED) ||
3554	    (fcftab->attempts >= 3)) {
3555		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3556		    "fc_fcftab_cfglink_failed_action:%x %s:%s arg=%p "
3557		    "attempt=%d reason=%x. Giving up.",
3558		    fcftab->TID,
3559		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3560		    emlxs_fcf_event_xlate(evt), arg1,
3561		    fcftab->attempts,
3562		    fcftab->reason);
3563
3564		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK_CMPL,
3565		    FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3566
3567	} else {
3568		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3569		    "fc_fcftab_cfglink_failed_action:%x %s:%s arg=%p "
3570		    "attempt=%d reason=%x. Retrying.",
3571		    fcftab->TID,
3572		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3573		    emlxs_fcf_event_xlate(evt), arg1,
3574		    fcftab->attempts,
3575		    fcftab->reason);
3576
3577		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
3578		    FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3579	}
3580
3581	return (rval);
3582
3583} /* emlxs_fc_fcftab_cfglink_failed_action() */
3584
3585
3586/*ARGSUSED*/
3587static uint32_t
3588emlxs_fc_fcftab_cfglink_cmpl_action(emlxs_port_t *port, uint32_t evt,
3589    void *arg1)
3590{
3591	emlxs_hba_t *hba = HBA;
3592	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3593	uint32_t rval = 0;
3594
3595	if (fcftab->state != FC_FCFTAB_STATE_CFGLINK_CMPL) {
3596		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3597		    "fc_fcftab_cfglink_cmpl_action:%x %s:%s arg=%p. "
3598		    "Invalid state. <",
3599		    fcftab->TID,
3600		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3601		    emlxs_fcf_event_xlate(evt), arg1);
3602		return (1);
3603	}
3604
3605	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3606	    "fc_fcftab_cfglink_cmpl_action:%x attempts=%d. "
3607	    "Read SPARM.",
3608	    fcftab->TID,
3609	    fcftab->attempts);
3610
3611	rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
3612	    FCF_REASON_EVENT, evt, arg1);
3613
3614	return (rval);
3615
3616} /* emlxs_fc_fcftab_cfglink_cmpl_action() */
3617
3618
3619/*ARGSUSED*/
3620static uint32_t
3621emlxs_fc_fcftab_sparm_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
3622{
3623	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
3624	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3625	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
3626	MATCHMAP *mp;
3627	emlxs_port_t *vport;
3628	VPIobj_t *vpip;
3629	int32_t i;
3630	uint8_t null_wwn[8];
3631	uint16_t TID;
3632
3633	mutex_enter(&EMLXS_FCF_LOCK);
3634	TID = (uint16_t)((unsigned long)mbq->context);
3635
3636	if (fcftab->state != FC_FCFTAB_STATE_SPARM) {
3637		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3638		    "fc_fcftab_sparm_mbcmpl:%x state=%s.",
3639		    TID,
3640		    emlxs_fc_fcftab_state_xlate(fcftab->state));
3641
3642		mutex_exit(&EMLXS_FCF_LOCK);
3643		return (0);
3644	}
3645
3646	if (TID != fcftab->generation) {
3647		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3648		    "fc_fcftab_sparm_mbcmpl:%x %s. "
3649		    "Incorrect generation %x. Dropping.",
3650		    TID,
3651		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3652		    fcftab->generation);
3653
3654		mutex_exit(&EMLXS_FCF_LOCK);
3655		return (0);
3656	}
3657
3658	if (mb4->mbxStatus) {
3659		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3660		    "fc_fcftab_sparm_mbcmpl:%x failed. %s. >",
3661		    fcftab->TID,
3662		    emlxs_mb_xlate_status(mb4->mbxStatus));
3663
3664		if (mb4->mbxStatus == MBXERR_NO_RESOURCES) {
3665			(void) emlxs_fc_fcftab_state(port,
3666			    FC_FCFTAB_STATE_SPARM_FAILED,
3667			    FCF_REASON_MBOX_BUSY, mb4->mbxStatus, 0);
3668		} else {
3669			(void) emlxs_fc_fcftab_state(port,
3670			    FC_FCFTAB_STATE_SPARM_FAILED,
3671			    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
3672		}
3673
3674		mutex_exit(&EMLXS_FCF_LOCK);
3675		return (0);
3676	}
3677
3678	/* Save the parameters */
3679	mp = (MATCHMAP *)mbq->bp;
3680	bcopy((caddr_t)mp->virt, (caddr_t)&hba->sparam, sizeof (SERV_PARM));
3681
3682	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3683	    "fc_fcftab_sparm_mbcmpl:%x edtov=%x,%x bbc=%x. >",
3684	    fcftab->TID,
3685	    hba->fc_edtov, hba->sparam.cmn.e_d_tov,
3686	    hba->sparam.cmn.bbCreditlsb);
3687
3688	/* Initialize the node name and port name only once */
3689	bzero(null_wwn, 8);
3690	if ((bcmp((caddr_t)&hba->wwnn, (caddr_t)null_wwn, 8) == 0) &&
3691	    (bcmp((caddr_t)&hba->wwpn, (caddr_t)null_wwn, 8) == 0)) {
3692		bcopy((caddr_t)&hba->sparam.nodeName,
3693		    (caddr_t)&hba->wwnn, sizeof (NAME_TYPE));
3694
3695		bcopy((caddr_t)&hba->sparam.portName,
3696		    (caddr_t)&hba->wwpn, sizeof (NAME_TYPE));
3697	} else {
3698		bcopy((caddr_t)&hba->wwnn,
3699		    (caddr_t)&hba->sparam.nodeName, sizeof (NAME_TYPE));
3700
3701		bcopy((caddr_t)&hba->wwpn,
3702		    (caddr_t)&hba->sparam.portName, sizeof (NAME_TYPE));
3703	}
3704
3705	/* Update all bound ports */
3706	for (i = 0; i < MAX_VPORTS; i++) {
3707		vport = &VPORT(i);
3708		vpip = vport->vpip;
3709
3710		if (!(vport->flag & EMLXS_PORT_BOUND) ||
3711		    (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
3712			continue;
3713		}
3714
3715		bcopy((caddr_t)&hba->sparam,
3716		    (caddr_t)&vport->sparam,
3717		    sizeof (SERV_PARM));
3718
3719		bcopy((caddr_t)&vport->wwnn,
3720		    (caddr_t)&vport->sparam.nodeName,
3721		    sizeof (NAME_TYPE));
3722
3723		bcopy((caddr_t)&vport->wwpn,
3724		    (caddr_t)&vport->sparam.portName,
3725		    sizeof (NAME_TYPE));
3726	}
3727
3728	(void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM_CMPL,
3729	    0, 0, 0);
3730
3731	mutex_exit(&EMLXS_FCF_LOCK);
3732	return (0);
3733
3734} /* emlxs_fc_fcftab_sparm_mbcmpl() */
3735
3736
3737/*ARGSUSED*/
3738static uint32_t
3739emlxs_fc_fcftab_sparm_action(emlxs_port_t *port, uint32_t evt,
3740    void *arg1)
3741{
3742	emlxs_hba_t *hba = HBA;
3743	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3744	MAILBOXQ *mbq;
3745	MAILBOX4 *mb4;
3746	uint32_t rval = 0;
3747	MATCHMAP *mp;
3748
3749	if (fcftab->state != FC_FCFTAB_STATE_SPARM) {
3750		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3751		    "fc_fcftab_sparm_action:%x %s:%s arg=%p. "
3752		    "Invalid state. <",
3753		    fcftab->TID,
3754		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3755		    emlxs_fcf_event_xlate(evt), arg1);
3756		return (1);
3757	}
3758
3759	if ((fcftab->prev_state != FC_FCFTAB_STATE_SPARM_FAILED) ||
3760	    (fcftab->flag & EMLXS_FC_FCFTAB_SPARM_REQ)) {
3761		fcftab->flag &= ~EMLXS_FC_FCFTAB_SPARM_REQ;
3762		fcftab->attempts = 0;
3763	}
3764
3765	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3766		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3767		    "fc_fcftab_read_action:%x %s:%s arg=%p flag=%x. "
3768		    "Handling request.",
3769		    fcftab->TID,
3770		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3771		    emlxs_fcf_event_xlate(evt), arg1,
3772		    fcftab->flag);
3773
3774		rval = emlxs_fc_fcftab_req_handler(port, arg1);
3775		return (rval);
3776	}
3777
3778	if (fcftab->attempts == 0) {
3779		fcftab->TID = fcftab->generation;
3780	}
3781
3782	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3783	    "fc_fcftab_read_action:%x %s:%s arg=%p attempts=%d. "
3784	    "Reading SPARM. <",
3785	    fcftab->TID,
3786	    emlxs_fc_fcftab_state_xlate(fcftab->state),
3787	    emlxs_fcf_event_xlate(evt), arg1,
3788	    fcftab->attempts);
3789
3790	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
3791		rval = emlxs_fc_fcftab_state(port,
3792		    FC_FCFTAB_STATE_SPARM_FAILED,
3793		    FCF_REASON_NO_MBOX, 0, arg1);
3794		return (rval);
3795	}
3796	mb4 = (MAILBOX4*)mbq;
3797	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
3798
3799	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
3800		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3801
3802		rval = emlxs_fc_fcftab_state(port,
3803		    FC_FCFTAB_STATE_SPARM_FAILED,
3804		    FCF_REASON_NO_BUFFER, 0, arg1);
3805		return (rval);
3806	}
3807	bzero(mp->virt, mp->size);
3808
3809	mbq->nonembed = NULL;
3810	mbq->bp = (void *)mp;
3811	mbq->mbox_cmpl = emlxs_fc_fcftab_sparm_mbcmpl;
3812	mbq->context = (void *)((unsigned long)fcftab->TID);
3813	mbq->port = (void *)port;
3814
3815	mb4->un.varSLIConfig.be.embedded = 0;
3816	mb4->mbxCommand = MBX_READ_SPARM64;
3817	mb4->mbxOwner = OWN_HOST;
3818
3819	mb4->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
3820	mb4->un.varRdSparm.un.sp64.addrHigh = PADDR_HI(mp->phys);
3821	mb4->un.varRdSparm.un.sp64.addrLow = PADDR_LO(mp->phys);
3822
3823	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3824	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3825		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
3826		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3827
3828		rval = emlxs_fc_fcftab_state(port,
3829		    FC_FCFTAB_STATE_SPARM_FAILED,
3830		    FCF_REASON_SEND_FAILED, rval, arg1);
3831
3832		return (rval);
3833	}
3834
3835	return (0);
3836
3837} /* emlxs_fc_fcftab_sparm_action() */
3838
3839
3840/*ARGSUSED*/
3841static uint32_t
3842emlxs_fc_fcftab_sparm_failed_action(emlxs_port_t *port, uint32_t evt,
3843    void *arg1)
3844{
3845	emlxs_hba_t *hba = HBA;
3846	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3847	uint32_t rval = 0;
3848
3849	fcftab->attempts++;
3850
3851	if (fcftab->state != FC_FCFTAB_STATE_SPARM_FAILED) {
3852		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3853		    "fc_fcftab_sparm_failed_action:%x %s:%s arg=%p "
3854		    "attempt=%d. Invalid state. <",
3855		    fcftab->TID,
3856		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3857		    emlxs_fcf_event_xlate(evt),
3858		    arg1, fcftab->attempts);
3859		return (1);
3860	}
3861
3862	if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
3863	    (fcftab->reason == FCF_REASON_SEND_FAILED) ||
3864	    (fcftab->attempts >= 3)) {
3865		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3866		    "fc_fcftab_read_failed_action:%x %s:%s arg=%p "
3867		    "attempt=%d reason=%x. Giving up.",
3868		    fcftab->TID,
3869		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3870		    emlxs_fcf_event_xlate(evt), arg1,
3871		    fcftab->attempts,
3872		    fcftab->reason);
3873
3874		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM_CMPL,
3875		    FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3876	} else {
3877		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3878		    "fc_fcftab_read_failed_action:%x %s:%s arg=%p "
3879		    "attempt=%d reason=%x. Retrying.",
3880		    fcftab->TID,
3881		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3882		    emlxs_fcf_event_xlate(evt), arg1,
3883		    fcftab->attempts,
3884		    fcftab->reason);
3885
3886		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
3887		    FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3888	}
3889
3890	return (rval);
3891
3892} /* emlxs_fc_fcftab_sparm_failed_action() */
3893
3894
3895/*ARGSUSED*/
3896static uint32_t
3897emlxs_fc_fcftab_sparm_cmpl_action(emlxs_port_t *port, uint32_t evt,
3898    void *arg1)
3899{
3900	emlxs_hba_t *hba = HBA;
3901	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3902	uint32_t rval = 0;
3903
3904	if (fcftab->state != FC_FCFTAB_STATE_SPARM_CMPL) {
3905		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3906		    "fc_fcftab_sparm_cmpl_action:%x %s:%s arg=%p. "
3907		    "Invalid state. <",
3908		    fcftab->TID,
3909		    emlxs_fc_fcftab_state_xlate(fcftab->state),
3910		    emlxs_fcf_event_xlate(evt), arg1);
3911		return (1);
3912	}
3913
3914	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3915	    "fc_fcftab_sparm_cmpl_action:%x attempts=%d. "
3916	    "Bring FCFTAB online.",
3917	    fcftab->TID,
3918	    fcftab->attempts);
3919
3920	rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE,
3921	    FCF_REASON_EVENT, evt, arg1);
3922
3923	return (rval);
3924
3925} /* emlxs_fc_fcftab_sparm_cmpl_action() */
3926
3927
3928/*ARGSUSED*/
3929static void
3930emlxs_fc_fcftab_process(emlxs_port_t *port)
3931{
3932	emlxs_hba_t *hba = HBA;
3933	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3934	FCFIobj_t *fcfp;
3935	FCF_RECORD_t fcf_record;
3936	FCF_RECORD_t *fcf_rec;
3937	uint8_t bitmap[512];
3938	uint16_t i;
3939
3940	/* Get the FCFI */
3941	fcfp = fcftab->fcfi[0];
3942
3943	if (!fcfp) {
3944		/* Allocate an fcfi */
3945		fcfp = emlxs_fcfi_alloc(port);
3946	}
3947
3948	if (!fcfp) {
3949		fcftab->fcfi_count = 0;
3950
3951		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3952		    "fc_fcftab_process:%x No FCF available.",
3953		    fcftab->TID);
3954		return;
3955	}
3956
3957	if (fcfp->flag & EMLXS_FCFI_SELECTED) {
3958		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3959		    "fc_fcftab_process:%x fcfi=%d %s. "
3960		    "FCF still selected.",
3961		    fcftab->TID,
3962		    fcfp->fcf_index,
3963		    emlxs_fcfi_state_xlate(fcfp->state));
3964	} else {
3965		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3966		    "fc_fcftab_process:%x fcfi=%d %s. "
3967		    "New FCF selected.",
3968		    fcftab->TID,
3969		    fcfp->fcf_index,
3970		    emlxs_fcfi_state_xlate(fcfp->state));
3971	}
3972
3973	/* Initalize an fcf_rec */
3974	fcf_rec = &fcf_record;
3975	bzero(fcf_rec, sizeof (FCF_RECORD_t));
3976
3977	fcf_rec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ;
3978	fcf_rec->fka_adv_period = 0;
3979	fcf_rec->fip_priority = 128;
3980
3981#ifdef EMLXS_BIG_ENDIAN
3982	fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3;
3983	fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2;
3984	fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1;
3985	fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0;
3986	fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC5;
3987	fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC4;
3988	fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2];
3989	fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
3990	fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0];
3991#endif /* EMLXS_BIG_ENDIAN */
3992#ifdef EMLXS_LITTLE_ENDIAN
3993	fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0;
3994	fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1;
3995	fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2;
3996	fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3;
3997	fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC4;
3998	fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC5;
3999	fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0];
4000	fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
4001	fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2];
4002#endif /* EMLXS_LITTLE_ENDIAN */
4003
4004	if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) {
4005		bzero((void *) bitmap, 512);
4006		i = hba->sli.sli4.cfgFCOE.VLanId;
4007		bitmap[i / 8] = (1 << (i % 8));
4008		BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
4009	} else {
4010		bzero((void *) bitmap, 512);
4011		bitmap[0] = 1; /* represents bit 0 */
4012		BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
4013	}
4014
4015	fcf_rec->fcf_valid = 1;
4016	fcf_rec->fcf_available = 1;
4017
4018	/* Update the FCFI */
4019	emlxs_fcfi_update(port, fcfp, fcf_rec, hba->link_event_tag);
4020
4021	/* Select the FCFI */
4022	fcfp->flag &= ~EMLXS_FCFI_FAILED;
4023	fcfp->flag |= EMLXS_FCFI_SELECTED;
4024	fcftab->fcfi[0] = fcfp;
4025	fcftab->fcfi_count = 1;
4026
4027	return;
4028
4029} /* emlxs_fc_fcftab_process() */
4030
4031
4032/*ARGSUSED*/
4033static uint32_t
4034emlxs_fc_fcftab_fcfi_online_action(emlxs_port_t *port, uint32_t evt,
4035    void *arg1)
4036{
4037	emlxs_hba_t *hba = HBA;
4038	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4039	uint32_t rval = 0;
4040	FCFIobj_t *fcfp;
4041
4042	if (fcftab->state != FC_FCFTAB_STATE_FCFI_ONLINE) {
4043		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4044		    "fc_fcftab_fcfi_online_action:%x %s:%s arg=%p. "
4045		    "Invalid state. <",
4046		    fcftab->TID,
4047		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4048		    emlxs_fcf_event_xlate(evt), arg1);
4049		return (1);
4050	}
4051
4052	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
4053		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4054		    "fc_fcftab_fcfi_online_action:%x flag=%x. "
4055		    "Handling request.",
4056		    fcftab->TID,
4057		    fcftab->flag);
4058
4059		rval = emlxs_fc_fcftab_req_handler(port, arg1);
4060		return (rval);
4061	}
4062
4063	emlxs_fc_fcftab_process(port);
4064
4065	fcfp = fcftab->fcfi[0];
4066	if (!fcfp) {
4067		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4068		    "fc_fcftab_fcfi_online_action:%x. "
4069		    "No FCF available. Offlining.",
4070		    fcftab->TID);
4071
4072		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4073		fcftab->flag |= EMLXS_FC_FCFTAB_OFFLINE_REQ;
4074		rval = emlxs_fc_fcftab_req_handler(port, arg1);
4075
4076		mutex_exit(&EMLXS_FCF_LOCK);
4077		return (rval);
4078	}
4079
4080	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4081	    "fc_fcftab_fcfi_online_action:%x fcfi_count=%d. "
4082	    "Onlining FCFI:%d. >",
4083	    fcftab->TID,
4084	    fcftab->fcfi_count,
4085	    fcfp->fcf_index);
4086
4087	(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_ONLINE, fcfp);
4088
4089	rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE_CMPL,
4090	    FCF_REASON_EVENT, evt, arg1);
4091
4092	return (rval);
4093
4094} /* emlxs_fc_fcftab_fcfi_online_action() */
4095
4096
4097/*ARGSUSED*/
4098static uint32_t
4099emlxs_fc_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, uint32_t evt,
4100    void *arg1)
4101{
4102	emlxs_hba_t *hba = HBA;
4103	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4104	uint32_t rval = 0;
4105
4106	if (fcftab->state != FC_FCFTAB_STATE_FCFI_ONLINE_CMPL) {
4107		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4108		    "fc_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p. "
4109		    "Invalid state. <",
4110		    fcftab->TID,
4111		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4112		    emlxs_fcf_event_xlate(evt), arg1);
4113		return (1);
4114	}
4115
4116	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
4117		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4118		    "fc_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p "
4119		    "flag=%x. Handling request.",
4120		    fcftab->TID,
4121		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4122		    emlxs_fcf_event_xlate(evt), arg1,
4123		    fcftab->flag);
4124
4125		rval = emlxs_fc_fcftab_req_handler(port, arg1);
4126		return (rval);
4127	}
4128
4129	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4130	    "fc_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p. "
4131	    "Going online.",
4132	    fcftab->TID,
4133	    emlxs_fc_fcftab_state_xlate(fcftab->state),
4134	    emlxs_fcf_event_xlate(evt), arg1);
4135
4136	rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_ONLINE,
4137	    FCF_REASON_EVENT, evt, arg1);
4138
4139	return (rval);
4140
4141} /* emlxs_fc_fcftab_fcfi_online_cmpl_action() */
4142
4143
4144/*ARGSUSED*/
4145static uint32_t
4146emlxs_fc_fcftab_fcfi_offline_action(emlxs_port_t *port, uint32_t evt,
4147    void *arg1)
4148{
4149	emlxs_hba_t *hba = HBA;
4150	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4151	uint32_t rval = 0;
4152	FCFIobj_t *fcfp;
4153
4154	if (fcftab->state != FC_FCFTAB_STATE_FCFI_OFFLINE) {
4155		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4156		    "fc_fcftab_fcftab_offline_action:%x %s:%s arg=%p. "
4157		    "Invalid state. <",
4158		    fcftab->TID,
4159		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4160		    emlxs_fcf_event_xlate(evt), arg1);
4161		return (1);
4162	}
4163
4164	if (fcftab->fcfi_online) {
4165		fcfp = fcftab->fcfi[0];
4166
4167		if (!(fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
4168			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4169			    "fc_fcftab_fcfi_offline_action:%d. "
4170			    "Offlining FCFI:%d. >",
4171			    fcftab->TID,
4172			    fcfp->fcf_index);
4173
4174			rval = emlxs_fcfi_event(port,
4175			    FCF_EVENT_FCFI_OFFLINE, fcfp);
4176
4177			return (rval);
4178		}
4179
4180		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4181		    "fc_fcftab_fcfi_offline_action:%x  fcfi_online=%d. "
4182		    "Waiting on FCF. <",
4183		    fcftab->TID,
4184		    fcftab->fcfi_online);
4185
4186		return (0);
4187	}
4188
4189	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4190	    "fc_fcftab_fcfi_offline_action:%x %s:%s arg=%p.",
4191	    fcftab->TID,
4192	    emlxs_fc_fcftab_state_xlate(fcftab->state),
4193	    emlxs_fcf_event_xlate(evt), arg1);
4194
4195	rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
4196	    FCF_REASON_EVENT, evt, arg1);
4197
4198	return (rval);
4199
4200} /* emlxs_fc_fcftab_fcfi_offline_action() */
4201
4202
4203/*ARGSUSED*/
4204static uint32_t
4205emlxs_fc_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, uint32_t evt,
4206    void *arg1)
4207{
4208	emlxs_hba_t *hba = HBA;
4209	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4210	uint32_t rval = 0;
4211
4212	if (fcftab->state != FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL) {
4213		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4214		    "fc_fcftab_fcftab_offline_cmpl_action:%x %s:%s arg=%p. "
4215		    "Invalid state. <",
4216		    fcftab->TID,
4217		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4218		    emlxs_fcf_event_xlate(evt), arg1);
4219		return (1);
4220	}
4221
4222	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
4223		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4224		    "fc_fcftab_fcfi_offline_cmpl_action:%x %s:%s arg=%p. "
4225		    "Handling request.",
4226		    fcftab->TID,
4227		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4228		    emlxs_fcf_event_xlate(evt), arg1);
4229
4230		rval = emlxs_fc_fcftab_req_handler(port, arg1);
4231		return (rval);
4232	}
4233
4234	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4235	    "fc_fcftab_fcftab_offline_cmpl_action:%x %s:%s arg=%p. "
4236	    "Returning FCF(s) online.",
4237	    fcftab->TID,
4238	    emlxs_fc_fcftab_state_xlate(fcftab->state),
4239	    emlxs_fcf_event_xlate(evt), arg1);
4240
4241	rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE,
4242	    FCF_REASON_EVENT, evt, arg1);
4243
4244	return (rval);
4245
4246} /* emlxs_fc_fcftab_fcfi_offline_cmpl_action() */
4247
4248
4249/*ARGSUSED*/
4250static uint32_t
4251emlxs_fc_fcftab_linkup_evt_action(emlxs_port_t *port, uint32_t evt,
4252    void *arg1)
4253{
4254	emlxs_hba_t *hba = HBA;
4255	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4256	uint32_t rval = 0;
4257
4258	if (evt != FCF_EVENT_LINKUP) {
4259		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4260		    "fc_fcftab_linkup_evt_action:%x %s:%s arg=%p flag=%x. "
4261		    "Invalid event type. <",
4262		    fcftab->TID,
4263		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4264		    emlxs_fcf_event_xlate(evt), arg1,
4265		    fcftab->flag);
4266		return (1);
4267	}
4268
4269	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4270	    "fc_fcftab_linkup_evt_action:%x %s:%s arg=%p gen=%x. Link up.",
4271	    fcftab->TID,
4272	    emlxs_fc_fcftab_state_xlate(fcftab->state),
4273	    emlxs_fcf_event_xlate(evt), arg1,
4274	    fcftab->generation);
4275
4276	emlxs_fcf_linkup(port);
4277
4278	fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4279	fcftab->flag |= EMLXS_FC_FCFTAB_TOPO_REQ;
4280	fcftab->generation++;
4281
4282	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4283	    "fc_fcftab_linkup_evt_action:%x %s gen=%x. "
4284	    "Read topology.",
4285	    fcftab->TID,
4286	    emlxs_fc_fcftab_state_xlate(fcftab->state),
4287	    fcftab->generation);
4288
4289	switch (fcftab->state) {
4290	case FC_FCFTAB_STATE_TOPO:
4291		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
4292		    FCF_REASON_REENTER, evt, arg1);
4293		break;
4294
4295	default:
4296		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
4297		    FCF_REASON_EVENT, evt, arg1);
4298		break;
4299	}
4300
4301	return (rval);
4302
4303} /* emlxs_fc_fcftab_linkup_evt_action() */
4304
4305
4306/*ARGSUSED*/
4307static uint32_t
4308emlxs_fc_fcftab_linkdown_evt_action(emlxs_port_t *port, uint32_t evt,
4309    void *arg1)
4310{
4311	emlxs_hba_t *hba = HBA;
4312	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4313	uint32_t rval = 0;
4314	uint32_t i;
4315	FCFIobj_t *fcfp;
4316
4317	if (evt != FCF_EVENT_LINKDOWN) {
4318		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4319		    "fc_fcftab_linkdown_evt_action:%x %s:%s arg=%p flag=%x. "
4320		    "Invalid event type. <",
4321		    fcftab->TID,
4322		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4323		    emlxs_fcf_event_xlate(evt), arg1,
4324		    fcftab->flag);
4325		return (1);
4326	}
4327
4328	fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4329	fcftab->flag |= EMLXS_FC_FCFTAB_OFFLINE_REQ;
4330
4331	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4332	    "fc_fcftab_linkdown_evt_action:%x %s:%s arg=%p flag=%x. Linkdown.",
4333	    fcftab->TID,
4334	    emlxs_fc_fcftab_state_xlate(fcftab->state),
4335	    emlxs_fcf_event_xlate(evt), arg1,
4336	    fcftab->flag);
4337
4338	emlxs_fcf_linkdown(port);
4339
4340	/* Pause all active FCFI's */
4341	for (i = 0; i < fcftab->fcfi_count; i++) {
4342		fcfp = fcftab->fcfi[i];
4343
4344		if ((fcfp->state == FCFI_STATE_OFFLINE) ||
4345		    (fcfp->state == FCFI_STATE_PAUSED)) {
4346			break;
4347		}
4348
4349		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4350		    "fc_fcftab_linkdown_evt_action:%x. "
4351		    "Pausing FCFI:%d. >",
4352		    fcftab->TID,
4353		    fcfp->fcf_index);
4354
4355		(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_PAUSE, fcfp);
4356	}
4357
4358	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4359	    "fc_fcftab_linkdown_evt_action:%x "
4360	    "Going offline.",
4361	    fcftab->TID);
4362
4363	switch (fcftab->state) {
4364	case FC_FCFTAB_STATE_OFFLINE:
4365		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_OFFLINE,
4366		    FCF_REASON_REENTER, evt, arg1);
4367		break;
4368
4369	default:
4370		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_OFFLINE,
4371		    FCF_REASON_EVENT, evt, arg1);
4372		break;
4373	}
4374
4375	return (rval);
4376
4377} /* emlxs_fc_fcftab_linkdown_evt_action() */
4378
4379
4380/*ARGSUSED*/
4381static uint32_t
4382emlxs_fc_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, uint32_t evt,
4383    void *arg1)
4384{
4385	emlxs_hba_t *hba = HBA;
4386	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4387	uint32_t rval = 0;
4388	FCFIobj_t *fcfp;
4389
4390	if (evt != FCF_EVENT_FCFI_OFFLINE) {
4391		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4392		    "fc_fcftab_fcftab_offline_evt_action:%x %s:%s arg=%p "
4393		    "flag=%x. Invalid event type. <",
4394		    fcftab->TID,
4395		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4396		    emlxs_fcf_event_xlate(evt), arg1,
4397		    fcftab->flag);
4398		return (1);
4399	}
4400
4401	fcfp = (FCFIobj_t *)arg1;
4402
4403	switch (fcftab->state) {
4404	case FC_FCFTAB_STATE_SHUTDOWN:
4405		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4406		    "fc_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4407		    "Shutting down.",
4408		    fcftab->TID,
4409		    fcfp->fcf_index);
4410
4411		/* This will trigger final shutdown */
4412		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SHUTDOWN,
4413		    FCF_REASON_REENTER, evt, arg1);
4414		break;
4415
4416	case FC_FCFTAB_STATE_FCFI_OFFLINE:
4417		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4418		    "fc_fcftab_fcfi_offline_evt_action:%x fcfi:%d. Offlining.",
4419		    fcftab->TID,
4420		    fcfp->fcf_index);
4421
4422		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_OFFLINE,
4423		    FCF_REASON_REENTER, evt, arg1);
4424		break;
4425
4426	case FC_FCFTAB_STATE_FCFI_ONLINE:
4427		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4428		    "fc_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4429		    "Retrying FCF.",
4430		    fcftab->TID,
4431		    fcfp->fcf_index);
4432
4433		fcfp->flag |= EMLXS_FCFI_FAILED;
4434
4435		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE,
4436		    FCF_REASON_REENTER, evt, arg1);
4437		break;
4438
4439	case FC_FCFTAB_STATE_ONLINE:
4440		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4441		    "fc_fcftab_fcfi_offline_evt_action:%x fcfi:%d.",
4442		    fcftab->TID,
4443		    fcfp->fcf_index);
4444
4445		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_ONLINE,
4446		    FCF_REASON_REENTER, evt, arg1);
4447		break;
4448
4449	default:
4450		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4451		    "fc_fcftab_fcfi_offline_evt_action:%x %s fcfi:%d.",
4452		    fcftab->TID,
4453		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4454		    fcfp->fcf_index);
4455		break;
4456	}
4457
4458	return (rval);
4459
4460} /* emlxs_fc_fcftab_fcfi_offline_evt_action() */
4461
4462
4463/*ARGSUSED*/
4464static uint32_t
4465emlxs_fc_fcftab_fcfi_online_evt_action(emlxs_port_t *port, uint32_t evt,
4466    void *arg1)
4467{
4468	emlxs_hba_t *hba = HBA;
4469	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4470	uint32_t rval = 0;
4471	FCFIobj_t *fcfp;
4472
4473	if (evt != FCF_EVENT_FCFI_ONLINE) {
4474		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4475		    "fc_fcftab_fcftab_online_evt_action:%x %s:%s arg=%p "
4476		    "flag=%x. Invalid event type. <",
4477		    fcftab->TID,
4478		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4479		    emlxs_fcf_event_xlate(evt), arg1,
4480		    fcftab->flag);
4481		return (1);
4482	}
4483
4484	fcfp = (FCFIobj_t *)arg1;
4485
4486	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4487	    "fc_fcftab_fcfi_online_evt_action:%d fcfi:%d. <",
4488	    fcftab->TID,
4489	    fcfp->fcf_index);
4490
4491	return (rval);
4492
4493} /* emlxs_fc_fcftab_fcfi_online_evt_action() */
4494
4495
4496/*ARGSUSED*/
4497static uint32_t
4498emlxs_fc_fcftab_shutdown_evt_action(emlxs_port_t *port, uint32_t evt,
4499    void *arg1)
4500{
4501	emlxs_hba_t *hba = HBA;
4502	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4503	uint32_t rval = 0;
4504
4505	if (evt != FCF_EVENT_SHUTDOWN) {
4506		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4507		    "fc_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
4508		    "Invalid event type. <",
4509		    fcftab->TID,
4510		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4511		    emlxs_fcf_event_xlate(evt), arg1,
4512		    fcftab->flag);
4513		return (1);
4514	}
4515
4516	if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) {
4517		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4518		    "fc_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
4519		    "Already shut down. <",
4520		    fcftab->TID,
4521		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4522		    emlxs_fcf_event_xlate(evt), arg1,
4523		    fcftab->flag);
4524		return (1);
4525	}
4526
4527	if (fcftab->state == FC_FCFTAB_STATE_SHUTDOWN) {
4528		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4529		    "fc_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
4530		    "Already shutting down. <",
4531		    fcftab->TID,
4532		    emlxs_fc_fcftab_state_xlate(fcftab->state),
4533		    emlxs_fcf_event_xlate(evt), arg1,
4534		    fcftab->flag);
4535		return (1);
4536	}
4537
4538	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4539	    "fc_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
4540	    "Shutting down.",
4541	    fcftab->TID,
4542	    emlxs_fc_fcftab_state_xlate(fcftab->state),
4543	    emlxs_fcf_event_xlate(evt), arg1,
4544	    fcftab->flag);
4545
4546	emlxs_fcf_linkdown(port);
4547
4548	rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SHUTDOWN,
4549	    FCF_REASON_EVENT, evt, arg1);
4550
4551	return (rval);
4552
4553} /* emlxs_fc_fcftab_shutdown_evt_action() */
4554
4555
4556static uint32_t
4557emlxs_fc_fcftab_req_handler(emlxs_port_t *port, void *arg1)
4558{
4559	emlxs_hba_t *hba = HBA;
4560	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4561	uint32_t rval = 0;
4562
4563	if (!(fcftab->flag & EMLXS_FCFTAB_REQ_MASK)) {
4564		return (1);
4565	}
4566
4567	if (fcftab->flag & EMLXS_FC_FCFTAB_OFFLINE_REQ) {
4568		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_OFFLINE,
4569		    FCF_REASON_REQUESTED, 0, arg1);
4570	}
4571
4572	else if (fcftab->flag & EMLXS_FC_FCFTAB_TOPO_REQ) {
4573		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
4574		    FCF_REASON_REQUESTED, 0, arg1);
4575	}
4576
4577	else if (fcftab->flag & EMLXS_FC_FCFTAB_CFGLINK_REQ) {
4578		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
4579		    FCF_REASON_REQUESTED, 0, arg1);
4580	}
4581
4582	else if (fcftab->flag & EMLXS_FC_FCFTAB_SPARM_REQ) {
4583		rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
4584		    FCF_REASON_REQUESTED, 0, arg1);
4585	}
4586
4587	return (rval);
4588
4589} /* emlxs_fc_fcftab_req_handler() */
4590
4591
4592
4593/* ************************************************************************** */
4594/* FCOE FCFTAB */
4595/* ************************************************************************** */
4596
4597static char *
4598emlxs_fcoe_fcftab_state_xlate(uint32_t state)
4599{
4600	static char buffer[32];
4601	uint32_t i;
4602	uint32_t count;
4603
4604	count = sizeof (emlxs_fcoe_fcftab_state_table) / sizeof (emlxs_table_t);
4605	for (i = 0; i < count; i++) {
4606		if (state == emlxs_fcoe_fcftab_state_table[i].code) {
4607			return (emlxs_fcoe_fcftab_state_table[i].string);
4608		}
4609	}
4610
4611	(void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
4612	return (buffer);
4613
4614} /* emlxs_fcoe_fcftab_state_xlate() */
4615
4616
4617static uint32_t
4618emlxs_fcoe_fcftab_action(emlxs_port_t *port, uint32_t evt,
4619    void *arg1)
4620{
4621	emlxs_hba_t *hba = HBA;
4622	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4623	uint32_t rval = 0;
4624	uint32_t(*func) (emlxs_port_t *, uint32_t, void *);
4625	uint32_t index;
4626	uint32_t events;
4627	uint16_t state;
4628
4629	/* Convert event to action table index */
4630	switch (evt) {
4631	case FCF_EVENT_STATE_ENTER:
4632		index = 0;
4633		break;
4634	case FCF_EVENT_SHUTDOWN:
4635		index = 1;
4636		break;
4637	case FCF_EVENT_LINKUP:
4638		index = 2;
4639		break;
4640	case FCF_EVENT_LINKDOWN:
4641		index = 3;
4642		break;
4643	case FCF_EVENT_CVL:
4644		index = 4;
4645		break;
4646	case FCF_EVENT_FCF_FOUND:
4647		index = 5;
4648		break;
4649	case FCF_EVENT_FCF_LOST:
4650		index = 6;
4651		break;
4652	case FCF_EVENT_FCF_CHANGED:
4653		index = 7;
4654		break;
4655	case FCF_EVENT_FCFTAB_FULL:
4656		index = 8;
4657		break;
4658	case FCF_EVENT_FCFI_ONLINE:
4659		index = 9;
4660		break;
4661	case FCF_EVENT_FCFI_OFFLINE:
4662		index = 10;
4663		break;
4664	default:
4665		return (1);
4666	}
4667
4668	events = FCOE_FCFTAB_ACTION_EVENTS;
4669	state  = fcftab->state;
4670
4671	index += (state * events);
4672	func   = (uint32_t(*) (emlxs_port_t *, uint32_t, void *))
4673	    emlxs_fcoe_fcftab_action_table[index];
4674
4675	if (!func) {
4676		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
4677		    "fcoe_fcftab_action:%x %s:%s arg=%p. No action. <",
4678		    fcftab->TID,
4679		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4680		    emlxs_fcf_event_xlate(evt), arg1);
4681
4682		return (1);
4683	}
4684
4685	rval = (func)(port, evt, arg1);
4686
4687	return (rval);
4688
4689} /* emlxs_fcoe_fcftab_action() */
4690
4691
4692static uint32_t
4693emlxs_fcoe_fcftab_event(emlxs_port_t *port, uint32_t evt,
4694    void *arg1)
4695{
4696	emlxs_hba_t *hba = HBA;
4697	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4698	uint32_t rval = 0;
4699
4700	/* Filter events */
4701	switch (evt) {
4702	case FCF_EVENT_SHUTDOWN:
4703	case FCF_EVENT_LINKUP:
4704	case FCF_EVENT_LINKDOWN:
4705	case FCF_EVENT_CVL:
4706	case FCF_EVENT_FCF_FOUND:
4707	case FCF_EVENT_FCF_LOST:
4708	case FCF_EVENT_FCF_CHANGED:
4709	case FCF_EVENT_FCFTAB_FULL:
4710	case FCF_EVENT_FCFI_OFFLINE:
4711	case FCF_EVENT_FCFI_ONLINE:
4712		break;
4713
4714	default:
4715		return (1);
4716	}
4717
4718	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
4719	    "fcoe_fcftab_event:%x %s:%s arg=%p.",
4720	    fcftab->TID,
4721	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4722	    emlxs_fcf_event_xlate(evt), arg1);
4723
4724	rval = emlxs_fcoe_fcftab_action(port, evt, arg1);
4725
4726	return (rval);
4727
4728} /* emlxs_fcoe_fcftab_event() */
4729
4730
4731/* EMLXS_FCF_LOCK must be held to enter */
4732/*ARGSUSED*/
4733static uint32_t
4734emlxs_fcoe_fcftab_state(emlxs_port_t *port, uint16_t state, uint16_t reason,
4735    uint32_t explain, void *arg1)
4736{
4737	emlxs_hba_t *hba = HBA;
4738	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4739	uint32_t rval = 0;
4740
4741	if (state >= FCOE_FCFTAB_ACTION_STATES) {
4742		return (1);
4743	}
4744
4745	if ((fcftab->state == state) &&
4746	    (reason != FCF_REASON_REENTER)) {
4747		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4748		    "fcftab_state:%x %s:%s:0x%x arg=%p. "
4749		    "State not changed. <",
4750		    fcftab->TID,
4751		    emlxs_fcoe_fcftab_state_xlate(state),
4752		    emlxs_fcf_reason_xlate(reason),
4753		    explain, arg1);
4754		return (1);
4755	}
4756
4757	if (!reason) {
4758		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4759		    "fcftab_state:%x %s-->%s arg=%p",
4760		    fcftab->TID,
4761		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4762		    emlxs_fcoe_fcftab_state_xlate(state), arg1);
4763	} else if (reason == FCF_REASON_EVENT) {
4764		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4765		    "fcftab_state:%x %s-->%s:%s:%s arg=%p",
4766		    fcftab->TID,
4767		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4768		    emlxs_fcoe_fcftab_state_xlate(state),
4769		    emlxs_fcf_reason_xlate(reason),
4770		    emlxs_fcf_event_xlate(explain), arg1);
4771	} else if (explain) {
4772		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4773		    "fcftab_state:%x %s-->%s:%s:0x%x arg=%p",
4774		    fcftab->TID,
4775		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4776		    emlxs_fcoe_fcftab_state_xlate(state),
4777		    emlxs_fcf_reason_xlate(reason),
4778		    explain, arg1);
4779	} else {
4780		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4781		    "fcftab_state:%x %s-->%s:%s arg=%p",
4782		    fcftab->TID,
4783		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4784		    emlxs_fcoe_fcftab_state_xlate(state),
4785		    emlxs_fcf_reason_xlate(reason), arg1);
4786	}
4787
4788	fcftab->prev_state = fcftab->state;
4789	fcftab->prev_reason = fcftab->reason;
4790	fcftab->state = state;
4791	fcftab->reason = reason;
4792
4793	rval = emlxs_fcoe_fcftab_action(port, FCF_EVENT_STATE_ENTER, arg1);
4794
4795	return (rval);
4796
4797} /* emlxs_fcoe_fcftab_state() */
4798
4799
4800/*ARGSUSED*/
4801static uint32_t
4802emlxs_fcoe_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, uint32_t evt,
4803    void *arg1)
4804{
4805	emlxs_hba_t *hba = HBA;
4806	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4807	uint32_t rval = 0;
4808	FCFIobj_t *fcfp;
4809
4810	if (evt != FCF_EVENT_FCFI_OFFLINE) {
4811		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4812		    "fcoe_fcftab_fcfi_offline_evt_action:%x %s:%s arg=%p "
4813		    "flag=%x. Invalid event type. <",
4814		    fcftab->TID,
4815		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4816		    emlxs_fcf_event_xlate(evt), arg1,
4817		    fcftab->flag);
4818		return (1);
4819	}
4820
4821	fcfp = (FCFIobj_t *)arg1;
4822
4823	switch (fcftab->state) {
4824	case FCOE_FCFTAB_STATE_SHUTDOWN:
4825		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4826		    "fcoe_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4827		    "Shutting down.",
4828		    fcftab->TID,
4829		    fcfp->fcf_index);
4830
4831		/* This will trigger final shutdown */
4832		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SHUTDOWN,
4833		    FCF_REASON_REENTER, evt, arg1);
4834		break;
4835
4836	case FCOE_FCFTAB_STATE_FCFI_OFFLINE:
4837		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4838		    "fcoe_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4839		    "Offlining.",
4840		    fcftab->TID,
4841		    fcfp->fcf_index);
4842
4843		rval = emlxs_fcoe_fcftab_state(port,
4844		    FCOE_FCFTAB_STATE_FCFI_OFFLINE,
4845		    FCF_REASON_REENTER, evt, arg1);
4846		break;
4847
4848	case FCOE_FCFTAB_STATE_FCFI_ONLINE:
4849		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4850		    "fcoe_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4851		    "Attempting failover.",
4852		    fcftab->TID,
4853		    fcfp->fcf_index);
4854
4855		fcfp->flag |= EMLXS_FCFI_FAILED;
4856
4857		rval = emlxs_fcoe_fcftab_state(port,
4858		    FCOE_FCFTAB_STATE_FCFI_ONLINE,
4859		    FCF_REASON_REENTER, evt, arg1);
4860		break;
4861
4862	case FCOE_FCFTAB_STATE_ONLINE:
4863		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4864		    "fcoe_fcftab_fcfi_offline_evt_action:%x fcfi:%d.",
4865		    fcftab->TID,
4866		    fcfp->fcf_index);
4867
4868		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_ONLINE,
4869		    FCF_REASON_REENTER, evt, arg1);
4870		break;
4871
4872	default:
4873		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4874		    "fcoe_fcftab_fcfi_offline_evt_action:%x %s fcfi:%d.",
4875		    fcftab->TID,
4876		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4877		    fcfp->fcf_index);
4878		break;
4879	}
4880
4881	return (rval);
4882
4883} /* emlxs_fcoe_fcftab_fcfi_offline_evt_action() */
4884
4885
4886/*ARGSUSED*/
4887static uint32_t
4888emlxs_fcoe_fcftab_fcfi_online_evt_action(emlxs_port_t *port, uint32_t evt,
4889    void *arg1)
4890{
4891	emlxs_hba_t *hba = HBA;
4892	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4893	uint32_t rval = 0;
4894	FCFIobj_t *fcfp;
4895
4896	if (evt != FCF_EVENT_FCFI_ONLINE) {
4897		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4898		    "fcoe_fcftab_fcfi_online_evt_action:%x %s:%s arg=%p "
4899		    "flag=%x. Invalid event type. <",
4900		    fcftab->TID,
4901		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4902		    emlxs_fcf_event_xlate(evt), arg1,
4903		    fcftab->flag);
4904		return (1);
4905	}
4906
4907	fcfp = (FCFIobj_t *)arg1;
4908
4909	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4910	    "fcoe_fcftab_fcfi_online_evt_action:%x fcfi:%d. <",
4911	    fcftab->TID,
4912	    fcfp->fcf_index);
4913
4914	return (rval);
4915
4916} /* emlxs_fcoe_fcftab_fcfi_online_evt_action() */
4917
4918
4919/*ARGSUSED*/
4920static uint32_t
4921emlxs_fcoe_fcftab_cvl_evt_action(emlxs_port_t *port, uint32_t evt,
4922    void *arg1)
4923{
4924	emlxs_hba_t *hba = HBA;
4925	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4926	uint32_t rval = 0;
4927	emlxs_port_t *vport;
4928	uint32_t vpi;
4929	VPIobj_t *vpip;
4930
4931	if (evt != FCF_EVENT_CVL) {
4932		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4933		    "fcoe_fcftab_cvl_evt_action:%x %s:%s arg=%p flag=%x. "
4934		    "Invalid event type. <",
4935		    fcftab->TID,
4936		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4937		    emlxs_fcf_event_xlate(evt), arg1,
4938		    fcftab->flag);
4939		return (1);
4940	}
4941
4942	/* Pause VPI */
4943	vpi = (uint32_t)((unsigned long)arg1);
4944	vport = &VPORT(vpi);
4945	vpip = vport->vpip;
4946
4947	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4948	    "fcoe_fcftab_cvl_evt_action:%x %s gen=%x. Pausing VPI:%d. >",
4949	    fcftab->TID,
4950	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4951	    fcftab->generation,
4952	    vpip->VPI);
4953
4954	rval = emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip);
4955
4956	switch (fcftab->state) {
4957	case FCOE_FCFTAB_STATE_SOLICIT:
4958		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4959		    "fcoe_fcftab_cvl_evt_action:%x %s gen=%x. "
4960		    "Already soliciting. <",
4961		    fcftab->TID,
4962		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4963		    fcftab->generation);
4964		break;
4965
4966	default:
4967		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4968		fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
4969		fcftab->generation++;
4970
4971		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4972		    "fcoe_fcftab_cvl_evt_action:%x %s gen=%x. Soliciting.",
4973		    fcftab->TID,
4974		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4975		    fcftab->generation);
4976
4977		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
4978		    FCF_REASON_EVENT, evt, arg1);
4979		break;
4980	}
4981
4982	return (rval);
4983
4984} /* emlxs_fcoe_fcftab_cvl_evt_action() */
4985
4986
4987/*ARGSUSED*/
4988static uint32_t
4989emlxs_fcoe_fcftab_linkup_evt_action(emlxs_port_t *port, uint32_t evt,
4990    void *arg1)
4991{
4992	emlxs_hba_t *hba = HBA;
4993	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4994	uint32_t rval = 0;
4995
4996	if (evt != FCF_EVENT_LINKUP) {
4997		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4998		    "fcoe_fcftab_linkup_evt_action:%x %s:%s arg=%p flag=%x. "
4999		    "Invalid event type. <",
5000		    fcftab->TID,
5001		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5002		    emlxs_fcf_event_xlate(evt), arg1,
5003		    fcftab->flag);
5004		return (1);
5005	}
5006
5007	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5008	    "fcoe_fcftab_linkup_evt_action:%x %s:%s arg=%p gen=%x. Link up.",
5009	    fcftab->TID,
5010	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5011	    emlxs_fcf_event_xlate(evt), arg1,
5012	    fcftab->generation);
5013
5014	emlxs_fcf_linkup(port);
5015
5016	switch (fcftab->state) {
5017	case FCOE_FCFTAB_STATE_SOLICIT:
5018		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5019		    "fcoe_fcftab_linkup_evt_action:%x %s gen=%x. "
5020		    "Already soliciting. <",
5021		    fcftab->TID,
5022		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5023		    fcftab->generation);
5024		break;
5025
5026	default:
5027		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
5028		fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
5029		fcftab->generation++;
5030
5031		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5032		    "fcoe_fcftab_linkup_evt_action:%x %s gen=%x. Soliciting.",
5033		    fcftab->TID,
5034		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5035		    fcftab->generation);
5036
5037		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
5038		    FCF_REASON_EVENT, evt, arg1);
5039		break;
5040	}
5041
5042	return (rval);
5043
5044} /* emlxs_fcoe_fcftab_linkup_evt_action() */
5045
5046
5047/*ARGSUSED*/
5048static uint32_t
5049emlxs_fcoe_fcftab_linkdown_evt_action(emlxs_port_t *port, uint32_t evt,
5050    void *arg1)
5051{
5052	emlxs_hba_t *hba = HBA;
5053	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5054	uint32_t rval = 0;
5055	int32_t i;
5056	FCFIobj_t *fcfp;
5057
5058	if (evt != FCF_EVENT_LINKDOWN) {
5059		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5060		    "fcoe_fcftab_linkdown_evt_action:%x %s:%s arg=%p "
5061		    "flag=%x. Invalid event type. <",
5062		    fcftab->TID,
5063		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5064		    emlxs_fcf_event_xlate(evt), arg1,
5065		    fcftab->flag);
5066		return (1);
5067	}
5068
5069	fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
5070	fcftab->flag |= EMLXS_FCOE_FCFTAB_OFFLINE_REQ;
5071
5072	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5073	    "fcoe_fcftab_linkdown_evt_action:%x %s:%s arg=%p flag=%x. "
5074	    "Linkdown.",
5075	    fcftab->TID,
5076	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5077	    emlxs_fcf_event_xlate(evt), arg1,
5078	    fcftab->flag);
5079
5080	emlxs_fcf_linkdown(port);
5081
5082	/* Pause all active FCFI's */
5083	for (i = 0; i < fcftab->fcfi_count; i++) {
5084		fcfp = fcftab->fcfi[i];
5085
5086		if ((fcfp->state == FCFI_STATE_OFFLINE) ||
5087		    (fcfp->state == FCFI_STATE_PAUSED)) {
5088			break;
5089		}
5090
5091		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5092		    "fcoe_fcftab_linkdown_evt_action:%x Pausing FCFI:%d. >",
5093		    fcftab->TID,
5094		    fcfp->fcf_index);
5095
5096		(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_PAUSE, fcfp);
5097	}
5098
5099	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5100	    "fcoe_fcftab_linkdown_evt_action:%x "
5101	    "Going offline.",
5102	    fcftab->TID);
5103
5104	switch (fcftab->state) {
5105	case FCOE_FCFTAB_STATE_OFFLINE:
5106		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_OFFLINE,
5107		    FCF_REASON_REENTER, evt, arg1);
5108		break;
5109
5110	default:
5111		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_OFFLINE,
5112		    FCF_REASON_EVENT, evt, arg1);
5113		break;
5114	}
5115
5116	return (rval);
5117
5118} /* emlxs_fcoe_fcftab_linkdown_evt_action() */
5119
5120
5121/*ARGSUSED*/
5122static uint32_t
5123emlxs_fcoe_fcftab_shutdown_evt_action(emlxs_port_t *port, uint32_t evt,
5124    void *arg1)
5125{
5126	emlxs_hba_t *hba = HBA;
5127	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5128	uint32_t rval = 0;
5129
5130	if (evt != FCF_EVENT_SHUTDOWN) {
5131		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5132		    "fcoe_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
5133		    "Invalid event type. <",
5134		    fcftab->TID,
5135		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5136		    emlxs_fcf_event_xlate(evt), arg1,
5137		    fcftab->flag);
5138		return (1);
5139	}
5140
5141	if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) {
5142		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5143		    "fcoe_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
5144		    "Already shut down. <",
5145		    fcftab->TID,
5146		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5147		    emlxs_fcf_event_xlate(evt), arg1,
5148		    fcftab->flag);
5149		return (1);
5150	}
5151
5152	if (fcftab->state == FCOE_FCFTAB_STATE_SHUTDOWN) {
5153		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5154		    "fcoe_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
5155		    "Already shutting down. <",
5156		    fcftab->TID,
5157		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5158		    emlxs_fcf_event_xlate(evt), arg1,
5159		    fcftab->flag);
5160		return (1);
5161	}
5162
5163	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5164	    "fcoe_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
5165	    "Shutting down.",
5166	    fcftab->TID,
5167	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5168	    emlxs_fcf_event_xlate(evt), arg1,
5169	    fcftab->flag);
5170
5171	emlxs_fcf_linkdown(port);
5172
5173	rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SHUTDOWN,
5174	    FCF_REASON_EVENT, evt, arg1);
5175
5176	return (rval);
5177
5178} /* emlxs_fcoe_fcftab_shutdown_evt_action() */
5179
5180
5181static uint32_t
5182emlxs_fcoe_fcftab_req_handler(emlxs_port_t *port, void *arg1)
5183{
5184	emlxs_hba_t *hba = HBA;
5185	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5186	uint32_t rval = 0;
5187
5188	if (!(fcftab->flag & EMLXS_FCFTAB_REQ_MASK)) {
5189		return (1);
5190	}
5191
5192	if (fcftab->flag & EMLXS_FCOE_FCFTAB_OFFLINE_REQ) {
5193		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_OFFLINE,
5194		    FCF_REASON_REQUESTED, 0, arg1);
5195	}
5196
5197	else if (fcftab->flag & EMLXS_FCOE_FCFTAB_SOL_REQ) {
5198		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
5199		    FCF_REASON_REQUESTED, 0, arg1);
5200	}
5201
5202	else if (fcftab->flag & EMLXS_FCOE_FCFTAB_READ_REQ) {
5203		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
5204		    FCF_REASON_REQUESTED, 0, FCFTAB_READ_ALL);
5205	}
5206
5207	return (rval);
5208
5209} /* emlxs_fcoe_fcftab_req_handler() */
5210
5211
5212static void
5213emlxs_fcoe_fcftab_read_timer(emlxs_hba_t *hba)
5214{
5215	emlxs_port_t *port = &PPORT;
5216	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5217
5218	/* Check FCF timer */
5219	if (!fcftab->read_timer ||
5220	    (hba->timer_tics < fcftab->read_timer)) {
5221		return;
5222	}
5223	fcftab->read_timer = 0;
5224	fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
5225
5226	switch (fcftab->state) {
5227	case FCOE_FCFTAB_STATE_SOLICIT_CMPL:
5228		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5229		    "fcoe_fcftab_timer:%x %s >",
5230		    fcftab->TID,
5231		    emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5232
5233		(void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
5234		    0, 0, FCFTAB_READ_ALL);
5235		break;
5236
5237	default:
5238		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5239		    "fcoe_fcftab_timer:%x %s",
5240		    fcftab->TID,
5241		    emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5242		break;
5243	}
5244
5245	return;
5246
5247}  /* emlxs_fcoe_fcftab_read_timer() */
5248
5249
5250static void
5251emlxs_fcoe_fcftab_sol_timer(emlxs_hba_t *hba)
5252{
5253	emlxs_port_t *port = &PPORT;
5254	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5255
5256	/* Check FCF timer */
5257	if (!fcftab->sol_timer ||
5258	    (hba->timer_tics < fcftab->sol_timer)) {
5259		return;
5260	}
5261	fcftab->sol_timer = 0;
5262
5263	switch (fcftab->state) {
5264	case FCOE_FCFTAB_STATE_ONLINE:
5265		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
5266		fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
5267		fcftab->generation++;
5268
5269		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5270		    "fcoe_fcftab_sol_timer:%x %s gen=%x. Soliciting. >",
5271		    fcftab->TID,
5272		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5273		    fcftab->generation);
5274
5275		(void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
5276		    FCF_REASON_EVENT, 0, 0);
5277		break;
5278
5279	default:
5280		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5281		    "fcoe_fcftab_sol_timer:%x %s",
5282		    fcftab->TID,
5283		    emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5284		break;
5285	}
5286
5287	return;
5288
5289}  /* emlxs_fcoe_fcftab_sol_timer() */
5290
5291
5292static void
5293emlxs_fcoe_fcftab_offline_timer(emlxs_hba_t *hba)
5294{
5295	emlxs_port_t *port = &PPORT;
5296	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5297	uint32_t i;
5298	FCFIobj_t *fcfp;
5299
5300	for (i = 0; i < fcftab->fcfi_count; i++) {
5301		fcfp = fcftab->fcfi[i];
5302
5303		/* Check offline timer */
5304		if (!fcfp->offline_timer ||
5305		    (hba->timer_tics < fcfp->offline_timer)) {
5306			continue;
5307		}
5308		fcfp->offline_timer = 0;
5309
5310		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5311		    "fcoe_fcftab_offline_timer:%x. Offlining FCFI:%d. >",
5312		    fcftab->TID,
5313		    fcfp->fcf_index);
5314
5315		(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp);
5316	}
5317
5318	return;
5319
5320}  /* emlxs_fcoe_fcftab_offline_timer() */
5321
5322
5323/*ARGSUSED*/
5324static uint32_t
5325emlxs_fcoe_fcftab_sol_failed_action(emlxs_port_t *port, uint32_t evt,
5326    void *arg1)
5327{
5328	emlxs_hba_t *hba = HBA;
5329	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5330	uint32_t rval = 0;
5331
5332	fcftab->attempts++;
5333
5334	if (fcftab->state != FCOE_FCFTAB_STATE_SOLICIT_FAILED) {
5335		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5336		    "fcoe_fcftab_sol_failed_action:%x %s:%s arg=%p "
5337		    "attempt=%d. Invalid state. <",
5338		    fcftab->TID,
5339		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5340		    emlxs_fcf_event_xlate(evt),
5341		    arg1, fcftab->attempts);
5342		return (1);
5343	}
5344
5345	if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
5346	    (fcftab->reason == FCF_REASON_SEND_FAILED) ||
5347	    (fcftab->attempts >= 3)) {
5348		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5349		    "fcoe_fcftab_sol_failed_action:%x %s:%s arg=%p "
5350		    "attempt=%d reason=%x. Giving up.",
5351		    fcftab->TID,
5352		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5353		    emlxs_fcf_event_xlate(evt), arg1,
5354		    fcftab->attempts,
5355		    fcftab->reason);
5356
5357		rval = emlxs_fcoe_fcftab_state(port,
5358		    FCOE_FCFTAB_STATE_SOLICIT_CMPL,
5359		    FCF_REASON_OP_FAILED, 0, arg1);
5360	} else {
5361		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5362		    "fcoe_fcftab_sol_failed_action:%x %s:%s arg=%p "
5363		    "attempt=%d reason=%x. Retrying.",
5364		    fcftab->TID,
5365		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5366		    emlxs_fcf_event_xlate(evt), arg1,
5367		    fcftab->attempts,
5368		    fcftab->reason);
5369
5370		rval = emlxs_fcoe_fcftab_state(port,
5371		    FCOE_FCFTAB_STATE_SOLICIT,
5372		    FCF_REASON_OP_FAILED, 0, arg1);
5373	}
5374
5375	return (rval);
5376
5377} /* emlxs_fcoe_fcftab_sol_failed_action() */
5378
5379
5380/*ARGSUSED*/
5381static uint32_t
5382emlxs_fcoe_fcftab_sol_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
5383{
5384	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
5385	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5386	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
5387	uint16_t TID;
5388	mbox_rsp_hdr_t *hdr_rsp;
5389	MATCHMAP *mp;
5390	uint32_t status = MGMT_STATUS_FCF_IN_USE;
5391	uint32_t xstatus = 0;
5392	uint32_t fip_mode = 1;
5393
5394	mutex_enter(&EMLXS_FCF_LOCK);
5395	TID = (uint16_t)((unsigned long)mbq->context);
5396
5397	if (mbq->nonembed) {
5398		fip_mode = 0;
5399
5400		mp = (MATCHMAP *)mbq->nonembed;
5401		mbq->nonembed = NULL;
5402
5403		hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
5404		status  = hdr_rsp->status;
5405		xstatus = hdr_rsp->extra_status;
5406
5407		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
5408	}
5409
5410	if (fcftab->state != FCOE_FCFTAB_STATE_SOLICIT) {
5411		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5412		    "fcoe_fcftab_sol_mbcmpl:%x %s.",
5413		    TID,
5414		    emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5415
5416		mutex_exit(&EMLXS_FCF_LOCK);
5417		return (0);
5418	}
5419
5420	if (TID != fcftab->generation) {
5421		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5422		    "fcoe_fcftab_sol_mbcmpl:%x %s. "
5423		    "Incorrect generation %x. Dropping.",
5424		    TID,
5425		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5426		    fcftab->generation);
5427
5428		mutex_exit(&EMLXS_FCF_LOCK);
5429		return (0);
5430	}
5431
5432	if (mb4->mbxStatus) {
5433		if (fip_mode) {
5434			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5435			    "fcoe_fcftab_sol_mbcmpl:%x failed. %s. >",
5436			    fcftab->TID,
5437			    emlxs_mb_xlate_status(mb4->mbxStatus));
5438
5439			(void) emlxs_fcoe_fcftab_state(port,
5440			    FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5441			    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
5442
5443			mutex_exit(&EMLXS_FCF_LOCK);
5444			return (0);
5445
5446		} else if ((status == 0)||(status != MGMT_STATUS_FCF_IN_USE)) {
5447			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5448			    "fcoe_fcftab_sol_mbcmpl:%x failed. %s %x,%x. >",
5449			    fcftab->TID,
5450			    emlxs_mb_xlate_status(mb4->mbxStatus),
5451			    status, xstatus);
5452
5453			(void) emlxs_fcoe_fcftab_state(port,
5454			    FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5455			    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
5456
5457			mutex_exit(&EMLXS_FCF_LOCK);
5458			return (0);
5459		}
5460	}
5461
5462	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5463	    "fcoe_fcftab_sol_mbcmpl:%x %s gen=%x. Solicit complete. >",
5464	    fcftab->TID,
5465	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5466	    fcftab->generation);
5467
5468	(void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT_CMPL,
5469	    0, 0, 0);
5470
5471	mutex_exit(&EMLXS_FCF_LOCK);
5472	return (0);
5473
5474} /* emlxs_fcoe_fcftab_sol_mbcmpl() */
5475
5476
5477/*ARGSUSED*/
5478static uint32_t
5479emlxs_fcoe_fcftab_sol_action(emlxs_port_t *port, uint32_t evt,
5480    void *arg1)
5481{
5482	emlxs_hba_t *hba = HBA;
5483	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5484	MAILBOXQ *mbq;
5485	MAILBOX4 *mb4;
5486	MATCHMAP *mp = NULL;
5487	uint32_t rval = 0;
5488
5489	if (fcftab->state != FCOE_FCFTAB_STATE_SOLICIT) {
5490		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5491		    "fcoe_fcftab_sol_action:%x %s:%s arg=%p. "
5492		    "Invalid state. <",
5493		    fcftab->TID,
5494		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5495		    emlxs_fcf_event_xlate(evt), arg1);
5496		return (1);
5497	}
5498
5499	if ((fcftab->prev_state != FCOE_FCFTAB_STATE_SOLICIT_FAILED) ||
5500	    (fcftab->flag & EMLXS_FCOE_FCFTAB_SOL_REQ)) {
5501		fcftab->flag &= ~EMLXS_FCOE_FCFTAB_SOL_REQ;
5502		fcftab->attempts = 0;
5503	}
5504
5505	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
5506		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5507		    "fcoe_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
5508		    "Handling request.",
5509		    fcftab->TID,
5510		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5511		    emlxs_fcf_event_xlate(evt), arg1,
5512		    fcftab->generation,
5513		    fcftab->flag);
5514
5515		rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
5516		return (rval);
5517	}
5518
5519	if (fcftab->attempts == 0) {
5520		fcftab->TID = fcftab->generation;
5521	}
5522
5523	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5524	    "fcoe_fcftab_sol_action:%x %s:%s arg=%p gen=%x fip=%x. "
5525	    "Requesting solicit. <",
5526	    fcftab->TID,
5527	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5528	    emlxs_fcf_event_xlate(evt), arg1,
5529	    fcftab->generation,
5530	    ((hba->flag & FC_FIP_SUPPORTED)? 1:0));
5531
5532	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
5533		rval = emlxs_fcoe_fcftab_state(port,
5534		    FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5535		    FCF_REASON_NO_MBOX, 0, 0);
5536		return (rval);
5537	}
5538
5539	mb4 = (MAILBOX4*)mbq;
5540	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
5541
5542	if (hba->flag & FC_FIP_SUPPORTED) {
5543		IOCTL_FCOE_REDISCOVER_FCF_TABLE *fcf;
5544
5545		mbq->nonembed = NULL;
5546		mbq->mbox_cmpl = emlxs_fcoe_fcftab_sol_mbcmpl;
5547		mbq->context = (void *)((unsigned long)fcftab->TID);
5548		mbq->port = (void *)port;
5549
5550		mb4->un.varSLIConfig.be.embedded = 1;
5551		mb4->mbxCommand = MBX_SLI_CONFIG;
5552		mb4->mbxOwner = OWN_HOST;
5553		mb4->un.varSLIConfig.be.payload_length =
5554		    sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE) +
5555		    IOCTL_HEADER_SZ;
5556		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
5557		    IOCTL_SUBSYSTEM_FCOE;
5558		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
5559		    FCOE_OPCODE_REDISCOVER_FCF_TABLE;
5560		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
5561		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
5562		    sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE);
5563
5564		fcf = (IOCTL_FCOE_REDISCOVER_FCF_TABLE *)
5565		    &mb4->un.varSLIConfig.payload;
5566		fcf->params.request.fcf_count = 0; /* invalidate FCF table */
5567
5568	} else { /* Non-FIP */
5569
5570		/* Non-FIP uses a persistent FCF entry that */
5571		/* we must add to the table */
5572
5573		IOCTL_FCOE_ADD_FCF_TABLE *fcf;
5574		mbox_req_hdr_t *hdr_req;
5575		FCF_RECORD_t *fcf_rec;
5576		uint8_t bitmap[512];
5577		uint16_t i;
5578
5579		if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
5580			emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5581
5582			rval = emlxs_fcoe_fcftab_state(port,
5583			    FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5584			    FCF_REASON_NO_BUFFER, 0, arg1);
5585			return (rval);
5586		}
5587		bzero(mp->virt, mp->size);
5588
5589		mbq->nonembed = (void *)mp;
5590		mbq->mbox_cmpl = emlxs_fcoe_fcftab_sol_mbcmpl;
5591		mbq->context = (void *)((unsigned long)fcftab->generation);
5592		mbq->port = (void *)port;
5593
5594		mb4->un.varSLIConfig.be.embedded = 0;
5595		mb4->mbxCommand = MBX_SLI_CONFIG;
5596		mb4->mbxOwner = OWN_HOST;
5597
5598		hdr_req = (mbox_req_hdr_t *)mp->virt;
5599		hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
5600		hdr_req->opcode = FCOE_OPCODE_ADD_FCF_TABLE;
5601		hdr_req->timeout = 0;
5602		hdr_req->req_length = sizeof (IOCTL_FCOE_ADD_FCF_TABLE);
5603
5604		fcf = (IOCTL_FCOE_ADD_FCF_TABLE *)(hdr_req + 1);
5605		fcf->params.request.fcf_index = 0;
5606
5607		fcf_rec = &fcf->params.request.fcf_entry;
5608		fcf_rec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ;
5609		fcf_rec->fka_adv_period = 0;
5610		fcf_rec->fip_priority = 128;
5611
5612#ifdef EMLXS_BIG_ENDIAN
5613		fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3;
5614		fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2;
5615		fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1;
5616		fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0;
5617		fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC5;
5618		fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC4;
5619		fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2];
5620		fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
5621		fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0];
5622#endif /* EMLXS_BIG_ENDIAN */
5623#ifdef EMLXS_LITTLE_ENDIAN
5624		fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0;
5625		fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1;
5626		fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2;
5627		fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3;
5628		fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC4;
5629		fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC5;
5630		fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0];
5631		fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
5632		fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2];
5633#endif /* EMLXS_LITTLE_ENDIAN */
5634
5635		if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) {
5636			bzero((void *) bitmap, 512);
5637			i = hba->sli.sli4.cfgFCOE.VLanId;
5638			bitmap[i / 8] = (1 << (i % 8));
5639			BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
5640		} else {
5641			bzero((void *) bitmap, 512);
5642			bitmap[0] = 1; /* represents bit 0 */
5643			BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
5644		}
5645
5646		fcf_rec->fcf_valid = 1;
5647		fcf_rec->fcf_available = 1;
5648	}
5649
5650	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
5651	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
5652		if (mp) {
5653			emlxs_mem_put(hba, MEM_BUF, (void *)mp);
5654		}
5655		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5656
5657		rval = emlxs_fcoe_fcftab_state(port,
5658		    FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5659		    FCF_REASON_SEND_FAILED, rval, 0);
5660
5661		return (rval);
5662	}
5663
5664	return (0);
5665
5666} /* emlxs_fcoe_fcftab_sol_action() */
5667
5668
5669/*ARGSUSED*/
5670static uint32_t
5671emlxs_fcoe_fcftab_sol_cmpl_action(emlxs_port_t *port, uint32_t evt,
5672    void *arg1)
5673{
5674	emlxs_hba_t *hba = HBA;
5675	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5676	uint32_t rval = 0;
5677	emlxs_config_t *cfg = &CFG;
5678
5679	if (fcftab->state != FCOE_FCFTAB_STATE_SOLICIT_CMPL) {
5680		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5681		    "fcoe_fcftab_sol_cmpl_action:%x %s:%s arg=%p "
5682		    "Invalid state. <",
5683		    fcftab->TID,
5684		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5685		    emlxs_fcf_event_xlate(evt), arg1);
5686		return (1);
5687	}
5688
5689	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
5690		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5691		    "fcoe_fcftab_sol_cmpl_action:%x %s:%s arg=%p gen=%d "
5692		    "flag=%x. Handling request.",
5693		    fcftab->TID,
5694		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5695		    emlxs_fcf_event_xlate(evt), arg1,
5696		    fcftab->generation,
5697		    fcftab->flag);
5698
5699		rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
5700		return (rval);
5701	}
5702
5703	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5704	    "fcoe_fcftab_sol_cmpl_action:%x %s:%s arg=%p gen=%d. "
5705	    "Starting timer (%d secs).",
5706	    fcftab->TID,
5707	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5708	    emlxs_fcf_event_xlate(evt), arg1,
5709	    fcftab->generation,
5710	    cfg[CFG_FCF_SOLICIT_DELAY].current);
5711
5712	/* Start the read timer */
5713	fcftab->read_timer = hba->timer_tics +
5714	    cfg[CFG_FCF_SOLICIT_DELAY].current;
5715
5716	return (0);
5717
5718} /* emlxs_fcoe_fcftab_sol_cmpl_action() */
5719
5720
5721/*ARGSUSED*/
5722static uint32_t
5723emlxs_fcoe_fcftab_read_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
5724{
5725	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
5726	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5727	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
5728	mbox_rsp_hdr_t	*hdr_rsp;
5729	IOCTL_FCOE_READ_FCF_TABLE *fcf;
5730	FCF_RECORD_t *fcfrec;
5731	FCFIobj_t *fcfp;
5732	MATCHMAP *mp;
5733	uint32_t context;
5734	uint16_t index;
5735	uint16_t TID;
5736	uint32_t event_tag;
5737
5738	mutex_enter(&EMLXS_FCF_LOCK);
5739	context = (uint32_t)((unsigned long)mbq->context);
5740	TID =	(uint16_t)(context >> 16);
5741	index =	(uint16_t)(context & 0xFFFF);
5742
5743	if (fcftab->state != FCOE_FCFTAB_STATE_READ) {
5744		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5745		    "fcoe_fcftab_read_mbcmpl:%x index=%d %s.",
5746		    TID, index,
5747		    emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5748
5749		mutex_exit(&EMLXS_FCF_LOCK);
5750		return (0);
5751	}
5752
5753	if (TID != fcftab->generation) {
5754		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5755		    "fcoe_fcftab_read_mbcmpl:%x index=%d %s. "
5756		    "Incorrect generation %x. Dropping.",
5757		    TID, index,
5758		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5759		    fcftab->generation);
5760
5761		mutex_exit(&EMLXS_FCF_LOCK);
5762		return (0);
5763	}
5764
5765	mp = (MATCHMAP *)mbq->nonembed;
5766	hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
5767
5768	if (mb4->mbxStatus || hdr_rsp->status) {
5769		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5770		    "fcoe_fcftab_read_mbcmpl:%x index=%d failed. %s %x,%x. >",
5771		    fcftab->TID, index,
5772		    emlxs_mb_xlate_status(mb4->mbxStatus),
5773		    hdr_rsp->status, hdr_rsp->extra_status);
5774
5775		(void) emlxs_fcoe_fcftab_state(port,
5776		    FCOE_FCFTAB_STATE_READ_FAILED,
5777		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus,
5778		    (void*)((unsigned long)index));
5779
5780		mutex_exit(&EMLXS_FCF_LOCK);
5781		return (0);
5782	}
5783
5784	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5785	    "fcoe_fcftab_read_mbcmpl:%x index=%d %s",
5786	    fcftab->TID, index,
5787	    emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5788
5789	fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_rsp + 1);
5790	fcfrec = &fcf->params.response.fcf_entry[0];
5791
5792#ifdef EMLXS_BIG_ENDIAN
5793{
5794	uint32_t *iptr;
5795	uint32_t i;
5796	uint8_t  j;
5797	uint16_t s;
5798	uint16_t *sptr;
5799
5800	/* Fix up data in FCF record */
5801	SWAP32_BUFFER(&fcfrec->fabric_name_identifier[0], 8);
5802	SWAP32_BUFFER(&fcfrec->switch_name_identifier[0], 8);
5803	SWAP32_BUFFER(&fcfrec->vlan_bitmap[0], 512);
5804
5805	iptr = (uint32_t *)&fcfrec->fcf_mac_address_hi[0];
5806	i = *iptr;
5807	*iptr = SWAP32(i);
5808
5809	sptr = (uint16_t *)&fcfrec->fcf_mac_address_low[0];
5810	s = *sptr;
5811	*sptr = SWAP16(s);
5812
5813	j = fcfrec->fc_map[0];
5814	fcfrec->fc_map[0] = fcfrec->fc_map[2];
5815	fcfrec->fc_map[2] = j;
5816}
5817#endif /* EMLXS_BIG_ENDIAN */
5818
5819	event_tag = fcf->params.response.event_tag;
5820
5821	/* Try to find existing fcfrec */
5822	fcfp = emlxs_fcfi_find(port, fcfrec, 0);
5823
5824	/* If not found, allocate a new one */
5825	if (!fcfp) {
5826		fcfp = emlxs_fcfi_alloc(port);
5827	}
5828
5829	if (!fcfp) {
5830		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5831		    "fcoe_fcftab_read_mbcmpl:%x index=%d failed. "
5832		    "Unable to allocate fcfi. >",
5833		    fcftab->TID, index);
5834
5835		(void) emlxs_fcoe_fcftab_state(port,
5836		    FCOE_FCFTAB_STATE_READ_FAILED,
5837		    FCF_REASON_NO_FCFI, 0,
5838		    (void*)((unsigned long)index));
5839
5840		mutex_exit(&EMLXS_FCF_LOCK);
5841		return (0);
5842	}
5843
5844	/* Update the FCFI */
5845	emlxs_fcfi_update(port, fcfp, fcfrec, event_tag);
5846
5847	/* Check if another record needs to be acquired */
5848	if (fcf->params.response.next_valid_fcf_index != 0xffff) {
5849		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5850		    "fcoe_fcftab_read_mbcmpl:%x. Read next. >",
5851		    fcftab->TID);
5852
5853		(void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
5854		    FCF_REASON_REENTER, 0,
5855		    (void *)((unsigned long)fcf->params.response.
5856		    next_valid_fcf_index));
5857	} else {
5858		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5859		    "fcoe_fcftab_read_mbcmpl:%x. Read complete. >",
5860		    fcftab->TID);
5861
5862		(void) emlxs_fcoe_fcftab_state(port,
5863		    FCOE_FCFTAB_STATE_READ_CMPL,
5864		    0, 0, (void*)((unsigned long)index));
5865	}
5866
5867	mutex_exit(&EMLXS_FCF_LOCK);
5868	return (0);
5869
5870} /* emlxs_fcoe_fcftab_read_mbcmpl() */
5871
5872
5873/*ARGSUSED*/
5874static uint32_t
5875emlxs_fcoe_fcftab_read_action(emlxs_port_t *port, uint32_t evt,
5876    void *arg1)
5877{
5878	emlxs_hba_t *hba = HBA;
5879	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5880	MAILBOXQ *mbq;
5881	MAILBOX4 *mb4;
5882	IOCTL_FCOE_READ_FCF_TABLE *fcf;
5883	uint32_t rval = 0;
5884	MATCHMAP *mp;
5885	mbox_req_hdr_t	*hdr_req;
5886	uint16_t inde