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 */
30 EMLXS_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 */
119 emlxs_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 */
153 emlxs_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 /* ********************************************************************** */
181 static char 		*emlxs_fcftab_state_xlate(emlxs_port_t *port,
182 				uint32_t state);
183 static uint32_t		emlxs_fcftab_event(emlxs_port_t *port, uint32_t evt,
184 				void *arg1);
185 static 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 */
193 emlxs_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 
221 static void emlxs_fc_fcftab_online_timer(emlxs_hba_t *hba);
222 
223 static uint32_t emlxs_fc_fcftab_offline_action(emlxs_port_t *port,
224 			uint32_t evt, void *arg1);
225 static uint32_t emlxs_fc_fcftab_online_action(emlxs_port_t *port,
226 			uint32_t evt, void *arg1);
227 
228 static uint32_t emlxs_fc_fcftab_topo_cmpl_action(emlxs_port_t *port,
229 			uint32_t evt, void *arg1);
230 static uint32_t emlxs_fc_fcftab_topo_failed_action(emlxs_port_t *port,
231 			uint32_t evt, void *arg1);
232 static uint32_t emlxs_fc_fcftab_topo_action(emlxs_port_t *port,
233 			uint32_t evt, void *arg1);
234 
235 static uint32_t emlxs_fc_fcftab_cfglink_cmpl_action(emlxs_port_t *port,
236 			uint32_t evt, void *arg1);
237 static uint32_t emlxs_fc_fcftab_cfglink_failed_action(emlxs_port_t *port,
238 			uint32_t evt, void *arg1);
239 static uint32_t emlxs_fc_fcftab_cfglink_action(emlxs_port_t *port,
240 			uint32_t evt, void *arg1);
241 
242 static uint32_t emlxs_fc_fcftab_sparm_cmpl_action(emlxs_port_t *port,
243 			uint32_t evt, void *arg1);
244 static uint32_t emlxs_fc_fcftab_sparm_failed_action(emlxs_port_t *port,
245 			uint32_t evt, void *arg1);
246 static uint32_t emlxs_fc_fcftab_sparm_action(emlxs_port_t *port,
247 			uint32_t evt, void *arg1);
248 
249 static uint32_t emlxs_fc_fcftab_linkup_evt_action(emlxs_port_t *port,
250 			uint32_t evt, void *arg1);
251 static uint32_t emlxs_fc_fcftab_linkdown_evt_action(emlxs_port_t *port,
252 			uint32_t evt, void *arg1);
253 
254 static uint32_t emlxs_fc_fcftab_fcfi_online_evt_action(emlxs_port_t *port,
255 			uint32_t evt, void *arg1);
256 static uint32_t emlxs_fc_fcftab_fcfi_offline_evt_action(emlxs_port_t *port,
257 			uint32_t evt, void *arg1);
258 
259 static uint32_t emlxs_fc_fcftab_shutdown_evt_action(emlxs_port_t *port,
260 			uint32_t evt, void *arg1);
261 static uint32_t emlxs_fc_fcftab_fcfi_offline_action(emlxs_port_t *port,
262 			uint32_t evt, void *arg1);
263 static uint32_t emlxs_fc_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port,
264 			uint32_t evt, void *arg1);
265 static uint32_t emlxs_fc_fcftab_fcfi_online_action(emlxs_port_t *port,
266 			uint32_t evt, void *arg1);
267 static uint32_t emlxs_fc_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port,
268 			uint32_t evt, void *arg1);
269 
270 static char *emlxs_fc_fcftab_state_xlate(uint32_t state);
271 static uint32_t emlxs_fc_fcftab_event(emlxs_port_t *port,
272 			uint32_t evt, void *arg1);
273 static 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 */
306 static 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 */
455 emlxs_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 
480 static uint32_t emlxs_fcoe_fcftab_sol_cmpl_action(emlxs_port_t *port,
481 			uint32_t evt, void *arg1);
482 static uint32_t emlxs_fcoe_fcftab_sol_failed_action(emlxs_port_t *port,
483 			uint32_t evt, void *arg1);
484 static uint32_t emlxs_fcoe_fcftab_sol_action(emlxs_port_t *port,
485 			uint32_t evt, void *arg1);
486 static uint32_t emlxs_fcoe_fcftab_shutdown_evt_action(emlxs_port_t *port,
487 			uint32_t evt, void *arg1);
488 static uint32_t emlxs_fcoe_fcftab_linkdown_evt_action(emlxs_port_t *port,
489 			uint32_t evt, void *arg1);
490 static uint32_t emlxs_fcoe_fcftab_read_action(emlxs_port_t *port,
491 			uint32_t evt, void *arg1);
492 static uint32_t emlxs_fcoe_fcftab_read_failed_action(emlxs_port_t *port,
493 			uint32_t evt, void *arg1);
494 static uint32_t emlxs_fcoe_fcftab_read_cmpl_action(emlxs_port_t *port,
495 			uint32_t evt, void *arg1);
496 static uint32_t emlxs_fcoe_fcftab_fcfi_online_action(emlxs_port_t *port,
497 			uint32_t evt, void *arg1);
498 static uint32_t emlxs_fcoe_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port,
499 			uint32_t evt, void *arg1);
500 static uint32_t emlxs_fcoe_fcftab_fcfi_offline_action(emlxs_port_t *port,
501 			uint32_t evt, void *arg1);
502 static uint32_t emlxs_fcoe_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port,
503 			uint32_t evt, void *arg1);
504 static uint32_t emlxs_fcoe_fcftab_found_evt_action(emlxs_port_t *port,
505 			uint32_t evt, void *arg1);
506 static uint32_t emlxs_fcoe_fcftab_lost_evt_action(emlxs_port_t *port,
507 			uint32_t evt, void *arg1);
508 static uint32_t emlxs_fcoe_fcftab_changed_evt_action(emlxs_port_t *port,
509 			uint32_t evt, void *arg1);
510 static uint32_t emlxs_fcoe_fcftab_full_evt_action(emlxs_port_t *port,
511 			uint32_t evt, void *arg1);
512 static uint32_t emlxs_fcoe_fcftab_linkup_evt_action(emlxs_port_t *port,
513 			uint32_t evt, void *arg1);
514 static uint32_t emlxs_fcoe_fcftab_cvl_evt_action(emlxs_port_t *port,
515 			uint32_t evt, void *arg1);
516 static uint32_t emlxs_fcoe_fcftab_online_action(emlxs_port_t *port,
517 			uint32_t evt, void *arg1);
518 static uint32_t emlxs_fcoe_fcftab_offline_action(emlxs_port_t *port,
519 			uint32_t evt, void *arg1);
520 static uint32_t emlxs_fcoe_fcftab_fcfi_offline_evt_action(emlxs_port_t *port,
521 			uint32_t evt, void *arg1);
522 static uint32_t emlxs_fcoe_fcftab_fcfi_online_evt_action(emlxs_port_t *port,
523 			uint32_t evt, void *arg1);
524 
525 static void emlxs_fcoe_fcftab_read_timer(emlxs_hba_t *hba);
526 static void emlxs_fcoe_fcftab_sol_timer(emlxs_hba_t *hba);
527 static void emlxs_fcoe_fcftab_offline_timer(emlxs_hba_t *hba);
528 static char *emlxs_fcoe_fcftab_state_xlate(uint32_t state);
529 static uint32_t emlxs_fcoe_fcftab_event(emlxs_port_t *port,
530 			uint32_t evt, void *arg1);
531 static 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 */
565 static 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 */
756 emlxs_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 
782 static uint32_t emlxs_fcfi_free_action(emlxs_port_t *port,
783 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
784 static uint32_t emlxs_fcfi_online_evt_action(emlxs_port_t *port,
785 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
786 static uint32_t emlxs_fcfi_offline_evt_action(emlxs_port_t *port,
787 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
788 static uint32_t emlxs_fcfi_pause_evt_action(emlxs_port_t *port,
789 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
790 static uint32_t emlxs_fcfi_reg_action(emlxs_port_t *port,
791 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
792 static uint32_t emlxs_fcfi_unreg_action(emlxs_port_t *port,
793 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
794 static uint32_t emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port,
795 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
796 static uint32_t emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port,
797 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
798 static uint32_t emlxs_fcfi_vfi_online_action(emlxs_port_t *port,
799 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
800 static uint32_t emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port,
801 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
802 static uint32_t emlxs_fcfi_reg_failed_action(emlxs_port_t *port,
803 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
804 static uint32_t emlxs_fcfi_unreg_failed_action(emlxs_port_t *port,
805 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
806 static uint32_t emlxs_fcfi_vfi_offline_action(emlxs_port_t *port,
807 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
808 static uint32_t emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port,
809 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
810 static uint32_t emlxs_fcfi_online_action(emlxs_port_t *port,
811 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
812 static uint32_t emlxs_fcfi_paused_action(emlxs_port_t *port,
813 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
814 static uint32_t emlxs_fcfi_offline_action(emlxs_port_t *port,
815 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
816 static uint32_t emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port,
817 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
818 static uint32_t emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port,
819 			FCFIobj_t *fcfp, uint32_t evt, void *arg1);
820 
821 static uint32_t emlxs_fcfi_event(emlxs_port_t *port,
822 			uint32_t evt, void *arg1);
823 static FCFIobj_t *emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec,
824 			uint32_t *fcf_index);
825 static FCFIobj_t *emlxs_fcfi_alloc(emlxs_port_t *port);
826 static uint32_t emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp);
827 static void emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp,
828 			FCF_RECORD_t *fcf_rec, uint32_t event_tag);
829 static 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 */
870 static 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 */
998 emlxs_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 
1026 static uint32_t emlxs_vfi_pause_evt_action(emlxs_port_t *port,
1027 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1028 static uint32_t emlxs_vfi_online_evt_action(emlxs_port_t *port,
1029 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1030 static uint32_t emlxs_vfi_offline_evt_action(emlxs_port_t *port,
1031 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1032 static uint32_t emlxs_vfi_init_action(emlxs_port_t *port,
1033 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1034 static uint32_t emlxs_vfi_init_failed_action(emlxs_port_t *port,
1035 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1036 static uint32_t emlxs_vfi_init_cmpl_action(emlxs_port_t *port,
1037 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1038 static uint32_t emlxs_vfi_offline_action(emlxs_port_t *port,
1039 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1040 static uint32_t emlxs_vfi_online_action(emlxs_port_t *port,
1041 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1042 static uint32_t emlxs_vfi_paused_action(emlxs_port_t *port,
1043 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1044 static uint32_t emlxs_vfi_vpi_online_action(emlxs_port_t *port,
1045 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1046 static uint32_t emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port,
1047 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1048 static uint32_t emlxs_vfi_vpi_offline_action(emlxs_port_t *port,
1049 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1050 static uint32_t emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port,
1051 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1052 static uint32_t emlxs_vfi_reg_action(emlxs_port_t *port,
1053 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1054 static uint32_t emlxs_vfi_reg_failed_action(emlxs_port_t *port,
1055 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1056 static uint32_t emlxs_vfi_reg_cmpl_action(emlxs_port_t *port,
1057 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1058 static uint32_t emlxs_vfi_unreg_action(emlxs_port_t *port,
1059 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1060 static uint32_t emlxs_vfi_unreg_failed_action(emlxs_port_t *port,
1061 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1062 static uint32_t emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port,
1063 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1064 static uint32_t emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port,
1065 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1066 static uint32_t emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port,
1067 			VFIobj_t *vfip, uint32_t evt, void *arg1);
1068 
1069 static 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 */
1114 static 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 */
1263 emlxs_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 
1296 static uint32_t emlxs_vpi_online_evt_action(emlxs_port_t *port,
1297 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1298 static uint32_t emlxs_vpi_offline_evt_action(emlxs_port_t *port,
1299 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1300 static uint32_t emlxs_vpi_pause_evt_action(emlxs_port_t *port,
1301 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1302 static uint32_t emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port,
1303 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1304 static uint32_t emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port,
1305 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1306 static uint32_t emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port,
1307 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1308 
1309 static uint32_t emlxs_vpi_init_action(emlxs_port_t *port,
1310 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1311 static uint32_t emlxs_vpi_init_failed_action(emlxs_port_t *port,
1312 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1313 static uint32_t emlxs_vpi_init_cmpl_action(emlxs_port_t *port,
1314 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1315 
1316 static uint32_t emlxs_vpi_offline_action(emlxs_port_t *port,
1317 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1318 static uint32_t emlxs_vpi_online_action(emlxs_port_t *port,
1319 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1320 static uint32_t emlxs_vpi_paused_action(emlxs_port_t *port,
1321 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1322 
1323 static uint32_t emlxs_vpi_port_online_action(emlxs_port_t *port,
1324 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1325 static uint32_t emlxs_vpi_port_offline_action(emlxs_port_t *port,
1326 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1327 
1328 static uint32_t emlxs_vpi_logi_cmpl_action(emlxs_port_t *port,
1329 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1330 static uint32_t emlxs_vpi_logi_failed_action(emlxs_port_t *port,
1331 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1332 static uint32_t emlxs_vpi_logi_action(emlxs_port_t *port,
1333 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1334 
1335 static uint32_t emlxs_vpi_reg_action(emlxs_port_t *port,
1336 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1337 static uint32_t emlxs_vpi_reg_failed_action(emlxs_port_t *port,
1338 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1339 static uint32_t emlxs_vpi_reg_cmpl_action(emlxs_port_t *port,
1340 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1341 
1342 static uint32_t emlxs_vpi_unreg_action(emlxs_port_t *port,
1343 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1344 static uint32_t emlxs_vpi_unreg_failed_action(emlxs_port_t *port,
1345 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1346 static uint32_t emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port,
1347 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1348 
1349 static uint32_t emlxs_vpi_logo_action(emlxs_port_t *port,
1350 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1351 static uint32_t emlxs_vpi_logo_failed_action(emlxs_port_t *port,
1352 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1353 static uint32_t emlxs_vpi_logo_cmpl_action(emlxs_port_t *port,
1354 			VPIobj_t *vpip, uint32_t evt, void *arg1);
1355 
1356 static uint32_t emlxs_vpi_event(emlxs_port_t *port,
1357 			uint32_t evt, void *arg1);
1358 static uint32_t emlxs_vpi_logi_cmpl_notify(emlxs_port_t *port,
1359 			RPIobj_t *rpip);
1360 static 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 */
1407 static 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 */
1609 emlxs_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 
1634 static uint32_t emlxs_rpi_free_action(emlxs_port_t *port,
1635 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1636 
1637 static uint32_t emlxs_rpi_online_evt_action(emlxs_port_t *port,
1638 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1639 static uint32_t emlxs_rpi_offline_evt_action(emlxs_port_t *port,
1640 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1641 static uint32_t emlxs_rpi_pause_evt_action(emlxs_port_t *port,
1642 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1643 static uint32_t emlxs_rpi_resume_evt_action(emlxs_port_t *port,
1644 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1645 
1646 static uint32_t emlxs_rpi_reg_action(emlxs_port_t *port,
1647 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1648 static uint32_t emlxs_rpi_reg_cmpl_action(emlxs_port_t *port,
1649 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1650 static uint32_t emlxs_rpi_reg_failed_action(emlxs_port_t *port,
1651 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1652 
1653 static uint32_t emlxs_rpi_unreg_action(emlxs_port_t *port,
1654 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1655 static uint32_t emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port,
1656 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1657 static uint32_t emlxs_rpi_unreg_failed_action(emlxs_port_t *port,
1658 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1659 
1660 static uint32_t emlxs_rpi_online_action(emlxs_port_t *port,
1661 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1662 static uint32_t emlxs_rpi_paused_action(emlxs_port_t *port,
1663 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1664 static uint32_t emlxs_rpi_offline_action(emlxs_port_t *port,
1665 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1666 static uint32_t emlxs_rpi_reserved_action(emlxs_port_t *port,
1667 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1668 
1669 static uint32_t emlxs_rpi_resume_failed_action(emlxs_port_t *port,
1670 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1671 static uint32_t emlxs_rpi_resume_cmpl_action(emlxs_port_t *port,
1672 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1673 static uint32_t emlxs_rpi_resume_action(emlxs_port_t *port,
1674 			RPIobj_t *rpip, uint32_t evt, void *arg1);
1675 
1676 static uint32_t emlxs_rpi_event(emlxs_port_t *port,
1677 			uint32_t evt, void *arg1);
1678 static RPIobj_t *emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did);
1679 static uint32_t emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip);
1680 static RPIobj_t *emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did);
1681 
1682 static void emlxs_rpi_resume_handler(emlxs_port_t *port,
1683 			RPIobj_t *rpip);
1684 static void emlxs_rpi_unreg_handler(emlxs_port_t *port,
1685 			RPIobj_t *rpip);
1686 static uint32_t emlxs_rpi_reg_handler(emlxs_port_t *port,
1687 			RPIobj_t *rpip);
1688 
1689 static void emlxs_rpi_idle_timer(emlxs_hba_t *hba);
1690 
1691 static 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 
1695 static void emlxs_rpi_alloc_fabric_rpi(emlxs_port_t *port);
1696 
1697 static 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 */
1735 static 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 /* ************************************************************************** */
1850 static void
emlxs_fcf_linkdown(emlxs_port_t * port)1851 emlxs_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 
1882 static void
emlxs_fcf_linkup(emlxs_port_t * port)1883 emlxs_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 
1918 extern void
emlxs_fcf_fini(emlxs_hba_t * hba)1919 emlxs_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 
1998 extern void
emlxs_fcf_init(emlxs_hba_t * hba)1999 emlxs_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 
2099 static char *
emlxs_fcf_event_xlate(uint32_t state)2100 emlxs_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 
2119 static char *
emlxs_fcf_reason_xlate(uint32_t reason)2120 emlxs_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 
2139 extern void
emlxs_fcf_timer_notify(emlxs_hba_t * hba)2140 emlxs_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 
2173 extern uint32_t
emlxs_fcf_shutdown_notify(emlxs_port_t * port,uint32_t wait)2174 emlxs_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 
2231 extern uint32_t
emlxs_fcf_linkup_notify(emlxs_port_t * port)2232 emlxs_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 
2265 extern uint32_t
emlxs_fcf_linkdown_notify(emlxs_port_t * port)2266 emlxs_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 
2299 extern uint32_t
emlxs_fcf_cvl_notify(emlxs_port_t * port,uint32_t vpi)2300 emlxs_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 
2334 extern uint32_t
emlxs_fcf_full_notify(emlxs_port_t * port)2335 emlxs_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 
2368 extern uint32_t
emlxs_fcf_found_notify(emlxs_port_t * port,uint32_t fcf_index)2369 emlxs_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 
2403 extern uint32_t
emlxs_fcf_changed_notify(emlxs_port_t * port,uint32_t fcf_index)2404 emlxs_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 
2438 extern uint32_t
emlxs_fcf_lost_notify(emlxs_port_t * port,uint32_t fcf_index)2439 emlxs_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 
2477 static char *
emlxs_fcftab_state_xlate(emlxs_port_t * port,uint32_t state)2478 emlxs_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 
2490 static uint32_t
emlxs_fcftab_event(emlxs_port_t * port,uint32_t evt,void * arg1)2491 emlxs_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*/
2505 static uint32_t
emlxs_fcftab_shutdown_action(emlxs_port_t * port,uint32_t evt,void * arg1)2506 emlxs_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 
2581 done:
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 
2621 static char *
emlxs_fc_fcftab_state_xlate(uint32_t state)2622 emlxs_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 
2641 static uint32_t
emlxs_fc_fcftab_action(emlxs_port_t * port,uint32_t evt,void * arg1)2642 emlxs_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 
2701 static uint32_t
emlxs_fc_fcftab_event(emlxs_port_t * port,uint32_t evt,void * arg1)2702 emlxs_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*/
2737 static uint32_t
emlxs_fc_fcftab_state(emlxs_port_t * port,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)2738 emlxs_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 
2804 static void
emlxs_fc_fcftab_online_timer(emlxs_hba_t * hba)2805 emlxs_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*/
2849 static uint32_t
emlxs_fc_fcftab_offline_action(emlxs_port_t * port,uint32_t evt,void * arg1)2850 emlxs_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*/
2896 static uint32_t
emlxs_fc_fcftab_online_action(emlxs_port_t * port,uint32_t evt,void * arg1)2897 emlxs_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*/
2967 static uint32_t
emlxs_fc_fcftab_topo_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)2968 emlxs_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 
3116 done:
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*/
3128 static uint32_t
emlxs_fc_fcftab_topo_action(emlxs_port_t * port,uint32_t evt,void * arg1)3129 emlxs_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*/
3250 static uint32_t
emlxs_fc_fcftab_topo_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)3251 emlxs_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*/
3306 static uint32_t
emlxs_fc_fcftab_topo_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)3307 emlxs_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*/
3339 static uint32_t
emlxs_fc_fcftab_cfglink_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)3340 emlxs_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*/
3407 static uint32_t
emlxs_fc_fcftab_cfglink_action(emlxs_port_t * port,uint32_t evt,void * arg1)3408 emlxs_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 
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*/
3531 static uint32_t
emlxs_fc_fcftab_cfglink_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)3532 emlxs_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*/
3587 static uint32_t
emlxs_fc_fcftab_cfglink_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)3588 emlxs_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*/
3620 static uint32_t
emlxs_fc_fcftab_sparm_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)3621 emlxs_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*/
3738 static uint32_t
emlxs_fc_fcftab_sparm_action(emlxs_port_t * port,uint32_t evt,void * arg1)3739 emlxs_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*/
3841 static uint32_t
emlxs_fc_fcftab_sparm_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)3842 emlxs_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*/
3896 static uint32_t
emlxs_fc_fcftab_sparm_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)3897 emlxs_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*/
3929 static void
emlxs_fc_fcftab_process(emlxs_port_t * port)3930 emlxs_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*/
4033 static uint32_t
emlxs_fc_fcftab_fcfi_online_action(emlxs_port_t * port,uint32_t evt,void * arg1)4034 emlxs_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*/
4098 static uint32_t
emlxs_fc_fcftab_fcfi_online_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)4099 emlxs_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*/
4145 static uint32_t
emlxs_fc_fcftab_fcfi_offline_action(emlxs_port_t * port,uint32_t evt,void * arg1)4146 emlxs_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*/
4204 static uint32_t
emlxs_fc_fcftab_fcfi_offline_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)4205 emlxs_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*/
4250 static uint32_t
emlxs_fc_fcftab_linkup_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4251 emlxs_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*/
4307 static uint32_t
emlxs_fc_fcftab_linkdown_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4308 emlxs_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*/
4381 static uint32_t
emlxs_fc_fcftab_fcfi_offline_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4382 emlxs_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*/
4464 static uint32_t
emlxs_fc_fcftab_fcfi_online_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4465 emlxs_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*/
4497 static uint32_t
emlxs_fc_fcftab_shutdown_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4498 emlxs_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 
4556 static uint32_t
emlxs_fc_fcftab_req_handler(emlxs_port_t * port,void * arg1)4557 emlxs_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 
4597 static char *
emlxs_fcoe_fcftab_state_xlate(uint32_t state)4598 emlxs_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 
4617 static uint32_t
emlxs_fcoe_fcftab_action(emlxs_port_t * port,uint32_t evt,void * arg1)4618 emlxs_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 
4692 static uint32_t
emlxs_fcoe_fcftab_event(emlxs_port_t * port,uint32_t evt,void * arg1)4693 emlxs_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*/
4733 static uint32_t
emlxs_fcoe_fcftab_state(emlxs_port_t * port,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)4734 emlxs_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*/
4801 static uint32_t
emlxs_fcoe_fcftab_fcfi_offline_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4802 emlxs_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*/
4887 static uint32_t
emlxs_fcoe_fcftab_fcfi_online_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4888 emlxs_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*/
4920 static uint32_t
emlxs_fcoe_fcftab_cvl_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4921 emlxs_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*/
4988 static uint32_t
emlxs_fcoe_fcftab_linkup_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4989 emlxs_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*/
5048 static uint32_t
emlxs_fcoe_fcftab_linkdown_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)5049 emlxs_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*/
5122 static uint32_t
emlxs_fcoe_fcftab_shutdown_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)5123 emlxs_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 
5181 static uint32_t
emlxs_fcoe_fcftab_req_handler(emlxs_port_t * port,void * arg1)5182 emlxs_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 
5212 static void
emlxs_fcoe_fcftab_read_timer(emlxs_hba_t * hba)5213 emlxs_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 
5250 static void
emlxs_fcoe_fcftab_sol_timer(emlxs_hba_t * hba)5251 emlxs_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 
5292 static void
emlxs_fcoe_fcftab_offline_timer(emlxs_hba_t * hba)5293 emlxs_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*/
5324 static uint32_t
emlxs_fcoe_fcftab_sol_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)5325 emlxs_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*/
5381 static uint32_t
emlxs_fcoe_fcftab_sol_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)5382 emlxs_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*/
5478 static uint32_t
emlxs_fcoe_fcftab_sol_action(emlxs_port_t * port,uint32_t evt,void * arg1)5479 emlxs_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*/
5670 static uint32_t
emlxs_fcoe_fcftab_sol_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)5671 emlxs_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*/
5722 static uint32_t
emlxs_fcoe_fcftab_read_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)5723 emlxs_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*/
5874 static uint32_t
emlxs_fcoe_fcftab_read_action(emlxs_port_t * port,uint32_t evt,void * arg1)5875 emlxs_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 index = (uint16_t)((unsigned long)arg1);
5887 	uint32_t context;
5888 
5889 	if (fcftab->state != FCOE_FCFTAB_STATE_READ) {
5890 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5891 		    "fcoe_fcftab_read_action:%x %s:%s arg=%p. "
5892 		    "Invalid state. <",
5893 		    fcftab->TID,
5894 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5895 		    emlxs_fcf_event_xlate(evt), arg1);
5896 		return (1);
5897 	}
5898 
5899 	if ((fcftab->prev_state != FCOE_FCFTAB_STATE_READ_FAILED) ||
5900 	    (fcftab->flag & EMLXS_FCOE_FCFTAB_READ_REQ)) {
5901 		fcftab->flag &= ~EMLXS_FCOE_FCFTAB_READ_REQ;
5902 		fcftab->attempts = 0;
5903 	}
5904 
5905 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
5906 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5907 		    "fcoe_fcftab_read_action:%x %s:%s arg=%p flag=%x. "
5908 		    "Handling request.",
5909 		    fcftab->TID,
5910 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5911 		    emlxs_fcf_event_xlate(evt), arg1,
5912 		    fcftab->flag);
5913 
5914 		rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
5915 		return (rval);
5916 	}
5917 
5918 	if (fcftab->attempts == 0) {
5919 		fcftab->TID = fcftab->generation;
5920 	}
5921 
5922 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5923 	    "fcoe_fcftab_read_action:%x %s:%s arg=%p attempts=%d. "
5924 	    "Reading FCF. <",
5925 	    fcftab->TID,
5926 	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5927 	    emlxs_fcf_event_xlate(evt), arg1,
5928 	    fcftab->attempts);
5929 
5930 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
5931 		rval = emlxs_fcoe_fcftab_state(port,
5932 		    FCOE_FCFTAB_STATE_READ_FAILED,
5933 		    FCF_REASON_NO_MBOX, 0, arg1);
5934 		return (rval);
5935 	}
5936 	mb4 = (MAILBOX4*)mbq;
5937 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
5938 
5939 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
5940 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5941 
5942 		rval = emlxs_fcoe_fcftab_state(port,
5943 		    FCOE_FCFTAB_STATE_READ_FAILED,
5944 		    FCF_REASON_NO_BUFFER, 0, arg1);
5945 		return (rval);
5946 	}
5947 	bzero(mp->virt, mp->size);
5948 
5949 	mbq->nonembed = (void *)mp;
5950 	mbq->mbox_cmpl = emlxs_fcoe_fcftab_read_mbcmpl;
5951 
5952 	context = ((uint32_t)fcftab->TID << 16) | (uint32_t)index;
5953 	mbq->context = (void *)((unsigned long)context);
5954 	mbq->port = (void *)port;
5955 
5956 	mb4->un.varSLIConfig.be.embedded = 0;
5957 	mb4->mbxCommand = MBX_SLI_CONFIG;
5958 	mb4->mbxOwner = OWN_HOST;
5959 
5960 	hdr_req = (mbox_req_hdr_t *)mp->virt;
5961 	hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
5962 	hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE;
5963 	hdr_req->timeout = 0;
5964 	hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE);
5965 
5966 	fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1);
5967 	fcf->params.request.fcf_index = index;
5968 
5969 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
5970 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
5971 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
5972 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5973 
5974 		rval = emlxs_fcoe_fcftab_state(port,
5975 		    FCOE_FCFTAB_STATE_READ_FAILED,
5976 		    FCF_REASON_SEND_FAILED, rval, arg1);
5977 
5978 		return (rval);
5979 	}
5980 
5981 	return (0);
5982 
5983 } /* emlxs_fcoe_fcftab_read_action() */
5984 
5985 
5986 /*ARGSUSED*/
5987 static uint32_t
emlxs_fcoe_fcftab_read_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)5988 emlxs_fcoe_fcftab_read_failed_action(emlxs_port_t *port, uint32_t evt,
5989     void *arg1)
5990 {
5991 	emlxs_hba_t *hba = HBA;
5992 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5993 	uint32_t rval = 0;
5994 
5995 	fcftab->attempts++;
5996 
5997 	if (fcftab->state != FCOE_FCFTAB_STATE_READ_FAILED) {
5998 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5999 		    "fcoe_fcftab_read_failed_action:%x %s:%s arg=%p "
6000 		    "attempt=%d. Invalid state. <",
6001 		    fcftab->TID,
6002 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6003 		    emlxs_fcf_event_xlate(evt),
6004 		    arg1, fcftab->attempts);
6005 		return (1);
6006 	}
6007 
6008 	if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
6009 	    (fcftab->reason == FCF_REASON_SEND_FAILED) ||
6010 	    (fcftab->attempts >= 3)) {
6011 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6012 		    "fcoe_fcftab_read_failed_action:%x %s:%s arg=%p "
6013 		    "attempt=%d reason=%x. Giving up.",
6014 		    fcftab->TID,
6015 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6016 		    emlxs_fcf_event_xlate(evt), arg1,
6017 		    fcftab->attempts,
6018 		    fcftab->reason);
6019 
6020 		rval = emlxs_fcoe_fcftab_state(port,
6021 		    FCOE_FCFTAB_STATE_READ_CMPL,
6022 		    FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
6023 	} else {
6024 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6025 		    "fcoe_fcftab_read_failed_action:%x %s:%s arg=%p "
6026 		    "attempt=%d reason=%x. Retrying.",
6027 		    fcftab->TID,
6028 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6029 		    emlxs_fcf_event_xlate(evt), arg1,
6030 		    fcftab->attempts,
6031 		    fcftab->reason);
6032 
6033 		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
6034 		    FCF_REASON_OP_FAILED, fcftab->attempts, FCFTAB_READ_ALL);
6035 	}
6036 
6037 	return (rval);
6038 
6039 } /* emlxs_fcoe_fcftab_read_failed_action() */
6040 
6041 
6042 /*ARGSUSED*/
6043 static uint32_t
emlxs_fcoe_fcftab_read_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)6044 emlxs_fcoe_fcftab_read_cmpl_action(emlxs_port_t *port, uint32_t evt,
6045     void *arg1)
6046 {
6047 	emlxs_hba_t *hba = HBA;
6048 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6049 	uint32_t rval = 0;
6050 	FCFIobj_t *fcfp;
6051 	uint32_t i;
6052 
6053 	if (fcftab->state != FCOE_FCFTAB_STATE_READ_CMPL) {
6054 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6055 		    "fcoe_fcftab_read_cmpl_action:%x %s:%s arg=%p. "
6056 		    "Invalid state. <",
6057 		    fcftab->TID,
6058 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6059 		    emlxs_fcf_event_xlate(evt), arg1);
6060 		return (1);
6061 	}
6062 
6063 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6064 	    "fcoe_fcftab_read_cmpl_action:%x %s:%s arg=%p attempts=%d. "
6065 	    "Cleaning table.",
6066 	    fcftab->TID,
6067 	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6068 	    emlxs_fcf_event_xlate(evt), arg1,
6069 	    fcftab->attempts);
6070 
6071 	/* Clean FCFI table */
6072 	fcfp = fcftab->table;
6073 	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
6074 		if (fcfp->state == FCFI_STATE_FREE) {
6075 			continue;
6076 		}
6077 
6078 		/* Adjust the freshness flag */
6079 		if (fcfp->generation == fcftab->generation) {
6080 			fcfp->flag |= EMLXS_FCFI_FRESH;
6081 		} else {
6082 			fcfp->flag &= ~EMLXS_FCFI_FRESH;
6083 		}
6084 
6085 		/* Clear the failed bit */
6086 		fcfp->flag &= ~EMLXS_FCFI_FAILED;
6087 
6088 		/* Free all stale unselected entries now */
6089 		if (!(fcfp->flag & EMLXS_FCFI_FRESH) &&
6090 		    !(fcfp->flag & EMLXS_FCFI_SELECTED)) {
6091 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6092 			    "fcoe_fcftab_read_cmpl_action:%x. FCF stale. "
6093 			    "Freeing FCFI:%d. >",
6094 			    fcftab->TID,
6095 			    fcfp->fcf_index);
6096 
6097 			(void) emlxs_fcfi_free(port, fcfp);
6098 			continue;
6099 		}
6100 	}
6101 
6102 	rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_FCFI_ONLINE,
6103 	    FCF_REASON_EVENT, evt, arg1);
6104 
6105 	return (rval);
6106 
6107 } /* emlxs_fcoe_fcftab_read_cmpl_action() */
6108 
6109 
6110 static FCFIobj_t *
emlxs_fcoe_fcftab_fcfi_select(emlxs_port_t * port,char * fabric_wwn)6111 emlxs_fcoe_fcftab_fcfi_select(emlxs_port_t *port, char *fabric_wwn)
6112 {
6113 	emlxs_hba_t *hba = HBA;
6114 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6115 	FCFIobj_t *fcfp;
6116 	FCFIobj_t *fcfp1;
6117 	uint32_t mask;
6118 	uint32_t viable;
6119 	uint32_t i;
6120 	uint32_t j;
6121 	uint32_t rnum;
6122 	timespec_t time;
6123 	FCFIobj_t **fcf_table;
6124 	uint32_t fcf_table_count;
6125 
6126 	mask =   (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
6127 	    EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH|
6128 	    EMLXS_FCFI_FAILED|EMLXS_FCFI_SELECTED);
6129 	viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
6130 	    EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH);
6131 
6132 	/* Tag & count viable entries */
6133 	fcf_table_count = 0;
6134 	fcfp = 0;
6135 	fcfp1 = fcftab->table;
6136 	for (i = 0; i < fcftab->table_count; i++, fcfp1++) {
6137 		if (fcfp1->state == FCFI_STATE_FREE) {
6138 			fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
6139 			continue;
6140 		}
6141 
6142 		if ((fcfp1->flag & mask) != viable) {
6143 			fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
6144 			continue;
6145 		}
6146 
6147 		if (fabric_wwn &&
6148 		    bcmp(fabric_wwn,
6149 		    fcfp1->fcf_rec.fabric_name_identifier, 8)) {
6150 			fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
6151 			continue;
6152 		}
6153 
6154 		fcfp1->flag |= EMLXS_FCFI_TAGGED;
6155 		fcfp = fcfp1;
6156 		fcf_table_count++;
6157 	}
6158 
6159 	if (fcf_table_count == 0) {
6160 		return (NULL);
6161 	}
6162 
6163 	if (fcf_table_count == 1) {
6164 		return (fcfp);
6165 	}
6166 
6167 	/* We found more than one viable entry */
6168 
6169 	fcf_table = (FCFIobj_t **)kmem_zalloc(
6170 	    (sizeof (uintptr_t) * fcf_table_count), KM_SLEEP);
6171 
6172 	/* Find the highest priority tagged entry(s) */
6173 	for (i = 0; i < fcf_table_count; i++) {
6174 		fcfp  = 0;
6175 		fcfp1 = fcftab->table;
6176 		for (j = 0; j < fcftab->table_count; j++, fcfp1++) {
6177 			if (!(fcfp1->flag & EMLXS_FCFI_TAGGED)) {
6178 				continue;
6179 			}
6180 
6181 			if (!fcfp ||
6182 			    (fcfp1->priority > fcfp->priority)) {
6183 				fcfp = fcfp1;
6184 			}
6185 		}
6186 
6187 		if (fcf_table[0] &&
6188 		    (fcf_table[0]->priority > fcfp->priority)) {
6189 			break;
6190 		}
6191 
6192 		fcfp->flag &= ~EMLXS_FCFI_TAGGED;
6193 		fcf_table[i] = fcfp;
6194 	}
6195 
6196 	/* If more than one entry has the highest priority, */
6197 	/* then randomly select one of the highest. */
6198 	if (i > 1) {
6199 		/* Pick a random number from 0 to (i-1) */
6200 		/* This algorithm uses the lower 16 bits of the nanosecond */
6201 		/* clock to determine the value */
6202 		bzero(&time, sizeof (timespec_t));
6203 		gethrestime(&time);
6204 		rnum = (uint32_t)(time.tv_nsec & 0xFFFF);
6205 
6206 		fcfp = fcf_table[(rnum%i)];
6207 	} else {
6208 		fcfp = fcf_table[0];
6209 	}
6210 
6211 	/* Free the priority table */
6212 	kmem_free(fcf_table, (sizeof (uintptr_t) * fcf_table_count));
6213 
6214 	return (fcfp);
6215 
6216 } /* emlxs_fcoe_fcftab_fcfi_select() */
6217 
6218 
6219 /*ARGSUSED*/
6220 static void
emlxs_fcoe_fcftab_process(emlxs_port_t * port)6221 emlxs_fcoe_fcftab_process(emlxs_port_t *port)
6222 {
6223 	emlxs_hba_t *hba = HBA;
6224 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6225 	FCFIobj_t *fcfp;
6226 	FCFIobj_t *prev_fcfp;
6227 	uint32_t i;
6228 	uint32_t j;
6229 	uint32_t count;
6230 	uint32_t mask;
6231 	uint32_t viable;
6232 	emlxs_config_t *cfg = &CFG;
6233 
6234 	mask =   (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
6235 	    EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH|
6236 	    EMLXS_FCFI_FAILED);
6237 	viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
6238 	    EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH);
6239 
6240 	/* Deselection process */
6241 	for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
6242 		fcfp = fcftab->fcfi[i];
6243 
6244 		if (!fcfp) {
6245 			continue;
6246 		}
6247 
6248 		/* Check if entry is viable */
6249 		if ((fcfp->flag & mask) == viable) {
6250 			if (fcfp->offline_timer) {
6251 				fcfp->offline_timer = 0;
6252 
6253 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6254 				    "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6255 				    "FCF viable. Offline timer disabled.",
6256 				    fcftab->TID,
6257 				    i, fcfp->fcf_index,
6258 				    emlxs_fcfi_state_xlate(fcfp->state),
6259 				    cfg[CFG_FCF_FAILOVER_DELAY].current);
6260 			}
6261 			continue;
6262 		}
6263 
6264 		/* Previous entry is no longer viable */
6265 
6266 		/* If FCF is still online */
6267 		if (fcfp->state > FCFI_STATE_OFFLINE) {
6268 			if (fcfp->offline_timer == 0) {
6269 				/* Set the offline timer */
6270 				fcfp->offline_timer = hba->timer_tics +
6271 				    cfg[CFG_FCF_FAILOVER_DELAY].current;
6272 
6273 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6274 				    "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6275 				    "No longer viable. "
6276 				    "Offlining FCF (%d secs).",
6277 				    fcftab->TID,
6278 				    i, fcfp->fcf_index,
6279 				    emlxs_fcfi_state_xlate(fcfp->state),
6280 				    cfg[CFG_FCF_FAILOVER_DELAY].current);
6281 			}
6282 			continue;
6283 		}
6284 
6285 		/* Deselect it */
6286 		fcfp->flag &= ~EMLXS_FCFI_SELECTED;
6287 
6288 		if (!(fcfp->flag & EMLXS_FCFI_FRESH)) {
6289 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6290 			    "fcoe_fcftab_process:%x %d. "
6291 			    "No longer viable. Freeing FCFI:%d. >",
6292 			    fcftab->TID,
6293 			    i, fcfp->fcf_index);
6294 
6295 			(void) emlxs_fcfi_free(port, fcfp);
6296 		} else {
6297 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6298 			    "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6299 			    "No longer viable. FCF deselected.",
6300 			    fcftab->TID,
6301 			    i, fcfp->fcf_index,
6302 			    emlxs_fcfi_state_xlate(fcfp->state));
6303 		}
6304 	}
6305 
6306 	/* Reselection process */
6307 	for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
6308 		prev_fcfp = fcftab->fcfi[i];
6309 		fcftab->fcfi[i] = NULL;
6310 
6311 		/* If no previous selection, then make new one */
6312 		if (!prev_fcfp) {
6313 			/* Select an fcf on any fabric */
6314 			fcfp = emlxs_fcoe_fcftab_fcfi_select(port, 0);
6315 
6316 			if (fcfp) {
6317 				fcfp->flag |= EMLXS_FCFI_SELECTED;
6318 				fcftab->fcfi[i] = fcfp;
6319 
6320 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6321 				    "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6322 				    "New FCF selected.",
6323 				    fcftab->TID,
6324 				    i, fcfp->fcf_index,
6325 				    emlxs_fcfi_state_xlate(fcfp->state));
6326 			} else {
6327 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6328 				    "fcoe_fcftab_process:%x %d. "
6329 				    "No FCF available.",
6330 				    fcftab->TID,
6331 				    i);
6332 			}
6333 			continue;
6334 		}
6335 
6336 		/* If previous entry is still selected, keep it */
6337 		if (prev_fcfp->flag & EMLXS_FCFI_SELECTED) {
6338 			fcfp = prev_fcfp;
6339 			fcftab->fcfi[i] = fcfp;
6340 
6341 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6342 			    "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6343 			    "FCF still selected.",
6344 			    fcftab->TID,
6345 			    i, fcfp->fcf_index,
6346 			    emlxs_fcfi_state_xlate(fcfp->state));
6347 			continue;
6348 		}
6349 
6350 		/* Previous entry is no longer selected */
6351 
6352 		/* Select a new fcf from same fabric */
6353 		fcfp = emlxs_fcoe_fcftab_fcfi_select(port,
6354 		    (char *)prev_fcfp->fcf_rec.fabric_name_identifier);
6355 
6356 		if (fcfp) {
6357 			fcfp->flag |= EMLXS_FCFI_SELECTED;
6358 			fcftab->fcfi[i] = fcfp;
6359 
6360 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6361 			    "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6362 			    "New FCF, same fabric selected.",
6363 			    fcftab->TID,
6364 			    i, fcfp->fcf_index,
6365 			    emlxs_fcfi_state_xlate(fcfp->state));
6366 			continue;
6367 		}
6368 
6369 		/* Select fcf from any fabric */
6370 		fcfp = emlxs_fcoe_fcftab_fcfi_select(port, 0);
6371 
6372 		if (fcfp) {
6373 			fcfp->flag |= EMLXS_FCFI_SELECTED;
6374 			fcftab->fcfi[i] = fcfp;
6375 
6376 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6377 			    "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6378 			    "New FCF, new fabric selected.",
6379 			    fcftab->TID,
6380 			    i, fcfp->fcf_index,
6381 			    emlxs_fcfi_state_xlate(fcfp->state));
6382 			continue;
6383 		}
6384 
6385 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6386 		    "fcoe_fcftab_process:%x %d. No FCF available.",
6387 		    fcftab->TID,
6388 		    i);
6389 	}
6390 
6391 	/* Pack entries */
6392 	count = 0;
6393 	for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
6394 		if (fcftab->fcfi[i]) {
6395 			count++;
6396 			continue;
6397 		}
6398 
6399 		for (j = i+1; j < FCFTAB_MAX_FCFI_COUNT; j++) {
6400 			if (fcftab->fcfi[j] == NULL) {
6401 				continue;
6402 			}
6403 
6404 			fcftab->fcfi[i] = fcftab->fcfi[j];
6405 			fcftab->fcfi[j] = NULL;
6406 			count++;
6407 			break;
6408 		}
6409 
6410 		if (j == FCFTAB_MAX_FCFI_COUNT) {
6411 			break;
6412 		}
6413 	}
6414 	fcftab->fcfi_count = count;
6415 
6416 	return;
6417 
6418 } /* emlxs_fcoe_fcftab_process() */
6419 
6420 
6421 /*ARGSUSED*/
6422 static uint32_t
emlxs_fcoe_fcftab_fcfi_online_action(emlxs_port_t * port,uint32_t evt,void * arg1)6423 emlxs_fcoe_fcftab_fcfi_online_action(emlxs_port_t *port, uint32_t evt,
6424     void *arg1)
6425 {
6426 	emlxs_hba_t *hba = HBA;
6427 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6428 	FCFIobj_t *fcfp;
6429 	uint32_t rval = 0;
6430 	uint32_t i;
6431 	uint32_t offline_count = 0;
6432 	uint32_t online_count = 0;
6433 
6434 	if (fcftab->state != FCOE_FCFTAB_STATE_FCFI_ONLINE) {
6435 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6436 		    "fcoe_fcftab_fcfi_online_action:%x %s:%s arg=%p. "
6437 		    "Invalid state. <",
6438 		    fcftab->TID,
6439 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6440 		    emlxs_fcf_event_xlate(evt), arg1);
6441 		return (1);
6442 	}
6443 
6444 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
6445 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6446 		    "fcoe_fcftab_fcfi_online_action:%x flag=%x. "
6447 		    "Handling request.",
6448 		    fcftab->TID,
6449 		    fcftab->flag);
6450 
6451 		rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
6452 		return (rval);
6453 	}
6454 
6455 	emlxs_fcoe_fcftab_process(port);
6456 
6457 	for (i = 0; i < fcftab->fcfi_count; i++) {
6458 		fcfp = fcftab->fcfi[i];
6459 
6460 		if (fcfp->offline_timer == 0) {
6461 			online_count++;
6462 
6463 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6464 			    "fcoe_fcftab_fcfi_online_action:%x fcfi_count=%d. "
6465 			    "Onlining FCFI:%d. >",
6466 			    fcftab->TID,
6467 			    fcftab->fcfi_count,
6468 			    fcfp->fcf_index);
6469 
6470 			(void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_ONLINE,
6471 			    fcfp);
6472 		} else {
6473 			offline_count++;
6474 
6475 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6476 			    "fcoe_fcftab_fcfi_online_action:%x fcfi_count=%d. "
6477 			    "Offlining fcfi:%d.",
6478 			    fcftab->TID,
6479 			    fcftab->fcfi_count,
6480 			    fcfp->fcf_index);
6481 		}
6482 	}
6483 
6484 	if (offline_count) {
6485 		/* Wait for FCF's to go offline */
6486 		rval = emlxs_fcoe_fcftab_state(port,
6487 		    FCOE_FCFTAB_STATE_FCFI_OFFLINE,
6488 		    FCF_REASON_EVENT, evt, arg1);
6489 
6490 		/* Service timer now */
6491 		emlxs_fcoe_fcftab_offline_timer(hba);
6492 
6493 		return (rval);
6494 	}
6495 
6496 	if (!online_count) {
6497 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6498 		    "fcoe_fcftab_fcfi_online_action:%x fcfi_count=%d.",
6499 		    fcftab->TID,
6500 		    fcftab->fcfi_count);
6501 	}
6502 
6503 	rval = emlxs_fcoe_fcftab_state(port,
6504 	    FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL,
6505 	    FCF_REASON_EVENT, evt, arg1);
6506 
6507 	return (rval);
6508 
6509 } /* emlxs_fcoe_fcftab_fcfi_online_action() */
6510 
6511 
6512 /*ARGSUSED*/
6513 static uint32_t
emlxs_fcoe_fcftab_fcfi_online_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)6514 emlxs_fcoe_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, uint32_t evt,
6515     void *arg1)
6516 {
6517 	emlxs_hba_t *hba = HBA;
6518 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6519 	uint32_t rval = 0;
6520 
6521 	if (fcftab->state != FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL) {
6522 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6523 		    "fcoe_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p. "
6524 		    "Invalid state. <",
6525 		    fcftab->TID,
6526 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6527 		    emlxs_fcf_event_xlate(evt), arg1);
6528 		return (1);
6529 	}
6530 
6531 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
6532 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6533 		    "fcoe_fcftab_fcfi_online_cmpl_action:%x %s:%s "
6534 		    "arg=%p flag=%x. Handling request.",
6535 		    fcftab->TID,
6536 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6537 		    emlxs_fcf_event_xlate(evt), arg1,
6538 		    fcftab->flag);
6539 
6540 		rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
6541 		return (rval);
6542 	}
6543 
6544 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6545 	    "fcoe_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p. "
6546 	    "Going online.",
6547 	    fcftab->TID,
6548 	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6549 	    emlxs_fcf_event_xlate(evt), arg1);
6550 
6551 	rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_ONLINE,
6552 	    FCF_REASON_EVENT, evt, arg1);
6553 
6554 	return (rval);
6555 
6556 } /* emlxs_fcoe_fcftab_fcfi_online_cmpl_action() */
6557 
6558 
6559 /*ARGSUSED*/
6560 static uint32_t
emlxs_fcoe_fcftab_fcfi_offline_action(emlxs_port_t * port,uint32_t evt,void * arg1)6561 emlxs_fcoe_fcftab_fcfi_offline_action(emlxs_port_t *port, uint32_t evt,
6562     void *arg1)
6563 {
6564 	emlxs_hba_t *hba = HBA;
6565 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6566 	FCFIobj_t *fcfp;
6567 	uint32_t rval = 0;
6568 	int32_t i;
6569 	uint32_t fcfi_offline;
6570 
6571 	if (fcftab->state != FCOE_FCFTAB_STATE_FCFI_OFFLINE) {
6572 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6573 		    "fcoe_fcftab_fcfi_offline_action:%x %s:%s arg=%p. "
6574 		    "Invalid state. <",
6575 		    fcftab->TID,
6576 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6577 		    emlxs_fcf_event_xlate(evt), arg1);
6578 		return (1);
6579 	}
6580 
6581 	/* Check for FCF's going offline */
6582 	fcfi_offline = 0;
6583 	for (i = 0; i < fcftab->fcfi_count; i++) {
6584 		fcfp = fcftab->fcfi[i];
6585 
6586 		if (fcfp->state <= FCFI_STATE_OFFLINE) {
6587 			continue;
6588 		}
6589 
6590 		if (fcfp->offline_timer ||
6591 		    (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
6592 			fcfi_offline++;
6593 		}
6594 	}
6595 
6596 	if (fcfi_offline) {
6597 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6598 		    "fcoe_fcftab_fcfi_offline_action:%x %s:%s arg=%p "
6599 		    "fcfi_offline=%d. <",
6600 		    fcftab->TID,
6601 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6602 		    emlxs_fcf_event_xlate(evt), arg1,
6603 		    fcfi_offline);
6604 
6605 		return (0);
6606 	}
6607 
6608 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6609 	    "fcoe_fcftab_fcfi_offline_action:%x %s:%s arg=%p.",
6610 	    fcftab->TID,
6611 	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6612 	    emlxs_fcf_event_xlate(evt), arg1);
6613 
6614 	rval = emlxs_fcoe_fcftab_state(port,
6615 	    FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
6616 	    FCF_REASON_EVENT, evt, arg1);
6617 
6618 	return (rval);
6619 
6620 } /* emlxs_fcoe_fcftab_fcfi_offline_action() */
6621 
6622 
6623 /*ARGSUSED*/
6624 static uint32_t
emlxs_fcoe_fcftab_fcfi_offline_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)6625 emlxs_fcoe_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, uint32_t evt,
6626     void *arg1)
6627 {
6628 	emlxs_hba_t *hba = HBA;
6629 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6630 	uint32_t rval = 0;
6631 
6632 	if (fcftab->state != FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL) {
6633 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6634 		    "fcoe_fcftab_fcfi_offline_cmpl_action:%x %s:%s arg=%p. "
6635 		    "Invalid state. <",
6636 		    fcftab->TID,
6637 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6638 		    emlxs_fcf_event_xlate(evt), arg1);
6639 		return (1);
6640 	}
6641 
6642 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
6643 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6644 		    "fcoe_fcftab_fcfi_offline_cmpl_action:%x %s:%s arg=%p. "
6645 		    "Handling request.",
6646 		    fcftab->TID,
6647 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6648 		    emlxs_fcf_event_xlate(evt), arg1);
6649 
6650 		rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
6651 		return (rval);
6652 	}
6653 
6654 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6655 	    "fcoe_fcftab_fcfi_offline_cmpl_action:%x %s:%s arg=%p. "
6656 	    "Returning FCF(s) online.",
6657 	    fcftab->TID,
6658 	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6659 	    emlxs_fcf_event_xlate(evt), arg1);
6660 
6661 	rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_FCFI_ONLINE,
6662 	    FCF_REASON_EVENT, evt, arg1);
6663 
6664 	return (rval);
6665 
6666 } /* emlxs_fcoe_fcftab_fcfi_offline_cmpl_action() */
6667 
6668 
6669 /*ARGSUSED*/
6670 static uint32_t
emlxs_fcoe_fcftab_found_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)6671 emlxs_fcoe_fcftab_found_evt_action(emlxs_port_t *port, uint32_t evt,
6672     void *arg1)
6673 {
6674 	emlxs_hba_t *hba = HBA;
6675 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6676 	uint32_t fcf_index = (uint32_t)((unsigned long)arg1);
6677 	FCFIobj_t *fcfp;
6678 	uint32_t rval = 0;
6679 
6680 	if (evt != FCF_EVENT_FCF_FOUND) {
6681 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6682 		    "fcoe_fcftab_found_evt_action:%x %s:%s fcf_index=%d. "
6683 		    "Invalid event type. <",
6684 		    fcftab->TID,
6685 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6686 		    emlxs_fcf_event_xlate(evt),
6687 		    fcf_index);
6688 
6689 		return (1);
6690 	}
6691 
6692 	switch (fcftab->state) {
6693 	case FCOE_FCFTAB_STATE_SOLICIT:
6694 	case FCOE_FCFTAB_STATE_SOLICIT_CMPL:
6695 	case FCOE_FCFTAB_STATE_READ:
6696 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6697 		    "fcoe_fcftab_found_evt_action:%x %s:%s "
6698 		    "fcf_index=%d gen=%x. <",
6699 		    fcftab->TID,
6700 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6701 		    emlxs_fcf_event_xlate(evt),
6702 		    fcf_index, fcftab->generation);
6703 		break;
6704 
6705 	/* case FCOE_FCFTAB_STATE_FCFI_OFFLINE: */
6706 	default:
6707 
6708 		/* Scan for matching fcf index in table */
6709 		fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
6710 
6711 		if (fcfp && (fcfp->flag & EMLXS_FCFI_SELECTED)) {
6712 
6713 			/* Trigger table read */
6714 			fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6715 			fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6716 			fcftab->generation++;
6717 
6718 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6719 			    "fcoe_fcftab_found_evt_action:%x %s:%s "
6720 			    "fcf_index=%d gen=%x. Read FCF table.",
6721 			    fcftab->TID,
6722 			    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6723 			    emlxs_fcf_event_xlate(evt),
6724 			    fcf_index, fcftab->generation);
6725 
6726 			rval = emlxs_fcoe_fcftab_state(port,
6727 			    FCOE_FCFTAB_STATE_READ,
6728 			    FCF_REASON_EVENT, evt, arg1);
6729 
6730 			break;
6731 		}
6732 
6733 		/* Check if we need more FCF's */
6734 		if (fcftab->fcfi_online < FCFTAB_MAX_FCFI_COUNT) {
6735 
6736 			/* Trigger table read */
6737 			fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6738 			fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6739 			fcftab->generation++;
6740 
6741 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6742 			    "fcoe_fcftab_found_evt_action:%x %s:%s "
6743 			    "fcf_index=%d gen=%x fcfi_online=%d. "
6744 			    "Read FCF table.",
6745 			    fcftab->TID,
6746 			    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6747 			    emlxs_fcf_event_xlate(evt),
6748 			    fcf_index, fcftab->generation,
6749 			    fcftab->fcfi_online);
6750 
6751 			rval = emlxs_fcoe_fcftab_state(port,
6752 			    FCOE_FCFTAB_STATE_READ,
6753 			    FCF_REASON_EVENT, evt, arg1);
6754 
6755 			break;
6756 		}
6757 
6758 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6759 		    "fcoe_fcftab_found_evt_action:%x %s:%s fcfi=%d. "
6760 		    "FCF not needed. <",
6761 		    fcftab->TID,
6762 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6763 		    emlxs_fcf_event_xlate(evt),
6764 		    fcf_index);
6765 
6766 		break;
6767 	}
6768 
6769 	return (rval);
6770 
6771 } /* emlxs_fcoe_fcftab_found_evt_action() */
6772 
6773 
6774 /*ARGSUSED*/
6775 static uint32_t
emlxs_fcoe_fcftab_lost_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)6776 emlxs_fcoe_fcftab_lost_evt_action(emlxs_port_t *port, uint32_t evt,
6777     void *arg1)
6778 {
6779 	emlxs_hba_t *hba = HBA;
6780 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6781 	FCFIobj_t *fcfp;
6782 	uint32_t fcf_index = (uint32_t)((unsigned long)arg1);
6783 	emlxs_port_t *vport;
6784 	VPIobj_t *vpip;
6785 	uint32_t i;
6786 	uint32_t rval = 0;
6787 
6788 	if (evt != FCF_EVENT_FCF_LOST) {
6789 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6790 		    "fcoe_fcftab_lost_evt_action:%x %s:%s fcf_index=%d. "
6791 		    "Invalid event type. <",
6792 		    fcftab->TID,
6793 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6794 		    emlxs_fcf_event_xlate(evt),
6795 		    fcf_index);
6796 
6797 		return (1);
6798 	}
6799 
6800 	/* Scan for matching fcf index in table */
6801 	fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
6802 
6803 	if (!fcfp) {
6804 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6805 		    "fcoe_fcftab_lost_evt_action:%x %s:%s fcf_index=%d. "
6806 		    "FCF not found. <",
6807 		    fcftab->TID,
6808 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6809 		    emlxs_fcf_event_xlate(evt),
6810 		    fcf_index);
6811 
6812 		return (0);
6813 	}
6814 
6815 	if (!(fcfp->flag & EMLXS_FCFI_SELECTED)) {
6816 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6817 		    "fcoe_fcftab_changed_evt_action:%x %s:%s fcf_index=%d. "
6818 		    "FCF not selected. <",
6819 		    fcftab->TID,
6820 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6821 		    emlxs_fcf_event_xlate(evt),
6822 		    fcf_index);
6823 
6824 		return (0);
6825 	}
6826 
6827 	/* Offline VPI's of this FCFI */
6828 	for (i = 0; i <= hba->vpi_max; i++) {
6829 		vport = &VPORT(i);
6830 		vpip = vport->vpip;
6831 
6832 		if ((vpip->state == VPI_STATE_OFFLINE) ||
6833 		    (vpip->vfip->fcfp != fcfp)) {
6834 			continue;
6835 		}
6836 
6837 		/* Fabric logo is implied */
6838 		emlxs_vpi_logo_handler(port, vpip);
6839 
6840 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6841 		    "fcoe_fcftab_lost_evt_action:%x %s:%s fcf_index=%d gen=%x. "
6842 		    "Offlining VPI:%d. >",
6843 		    fcftab->TID,
6844 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6845 		    emlxs_fcf_event_xlate(evt),
6846 		    fcf_index, fcftab->generation,
6847 		    vpip->VPI);
6848 
6849 		(void) emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
6850 	}
6851 
6852 	switch (fcftab->state) {
6853 	case FCOE_FCFTAB_STATE_SOLICIT:
6854 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6855 		    "fcoe_fcftab_lost_evt_action:%x %s gen=%x. "
6856 		    "Already soliciting. <",
6857 		    fcftab->TID,
6858 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6859 		    fcftab->generation);
6860 		break;
6861 
6862 	default:
6863 		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6864 		fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
6865 		fcftab->generation++;
6866 
6867 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6868 		    "fcoe_fcftab_lost_evt_action:%x %s gen=%x. Soliciting.",
6869 		    fcftab->TID,
6870 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6871 		    fcftab->generation);
6872 
6873 		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
6874 		    FCF_REASON_EVENT, evt, arg1);
6875 		break;
6876 	}
6877 
6878 	return (rval);
6879 
6880 } /* emlxs_fcoe_fcftab_lost_evt_action() */
6881 
6882 
6883 /*ARGSUSED*/
6884 static uint32_t
emlxs_fcoe_fcftab_changed_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)6885 emlxs_fcoe_fcftab_changed_evt_action(emlxs_port_t *port, uint32_t evt,
6886     void *arg1)
6887 {
6888 	emlxs_hba_t *hba = HBA;
6889 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6890 	FCFIobj_t *fcfp;
6891 	uint32_t fcf_index = (uint32_t)((unsigned long)arg1);
6892 	uint32_t rval = 0;
6893 
6894 	if (evt != FCF_EVENT_FCF_CHANGED) {
6895 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6896 		    "fcoe_fcftab_changed_evt_action:%x %s:%s fcf_index=%d. "
6897 		    "Invalid event type. <",
6898 		    fcftab->TID,
6899 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6900 		    emlxs_fcf_event_xlate(evt),
6901 		    fcf_index);
6902 
6903 		return (1);
6904 	}
6905 
6906 	switch (fcftab->state) {
6907 	case FCOE_FCFTAB_STATE_SOLICIT:
6908 	case FCOE_FCFTAB_STATE_SOLICIT_CMPL:
6909 	case FCOE_FCFTAB_STATE_READ:
6910 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6911 		    "fcoe_fcftab_changed_evt_action:%x %s:%s "
6912 		    "fcf_index=%d gen=%x. <",
6913 		    fcftab->TID,
6914 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6915 		    emlxs_fcf_event_xlate(evt),
6916 		    fcf_index, fcftab->generation);
6917 		break;
6918 
6919 	/* case FCOE_FCFTAB_STATE_FCFI_OFFLINE: */
6920 	default:
6921 
6922 		/* Scan for matching fcf index in table */
6923 		fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
6924 
6925 		if (fcfp && (fcfp->flag & EMLXS_FCFI_SELECTED)) {
6926 
6927 			/* Trigger table read */
6928 			fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6929 			fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6930 			fcftab->generation++;
6931 
6932 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6933 			    "fcoe_fcftab_changed_evt_action:%x %s:%s "
6934 			    "fcf_index=%d gen=%x. Read FCF table.",
6935 			    fcftab->TID,
6936 			    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6937 			    emlxs_fcf_event_xlate(evt),
6938 			    fcf_index, fcftab->generation);
6939 
6940 			rval = emlxs_fcoe_fcftab_state(port,
6941 			    FCOE_FCFTAB_STATE_READ,
6942 			    FCF_REASON_EVENT, evt, arg1);
6943 
6944 			break;
6945 		}
6946 
6947 		/* Check if we need more FCF's */
6948 		if (fcftab->fcfi_online < FCFTAB_MAX_FCFI_COUNT) {
6949 
6950 			/* Trigger table read */
6951 			fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6952 			fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6953 			fcftab->generation++;
6954 
6955 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6956 			    "fcoe_fcftab_changed_evt_action:%x %s:%s "
6957 			    "fcf_index=%d gen=%x fcfi_online=%d. "
6958 			    "Read FCF table.",
6959 			    fcftab->TID,
6960 			    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6961 			    emlxs_fcf_event_xlate(evt),
6962 			    fcf_index, fcftab->generation,
6963 			    fcftab->fcfi_online);
6964 
6965 			rval = emlxs_fcoe_fcftab_state(port,
6966 			    FCOE_FCFTAB_STATE_READ,
6967 			    FCF_REASON_EVENT, evt, arg1);
6968 
6969 			break;
6970 		}
6971 
6972 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6973 		    "fcoe_fcftab_changed_evt_action:%x %s:%s fcfi=%d. "
6974 		    "FCF not needed. <",
6975 		    fcftab->TID,
6976 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6977 		    emlxs_fcf_event_xlate(evt),
6978 		    fcf_index);
6979 
6980 		break;
6981 	}
6982 
6983 	return (rval);
6984 
6985 } /* emlxs_fcoe_fcftab_changed_evt_action() */
6986 
6987 
6988 /*ARGSUSED*/
6989 static uint32_t
emlxs_fcoe_fcftab_fcf_delete(emlxs_port_t * port,uint32_t fcf_index)6990 emlxs_fcoe_fcftab_fcf_delete(emlxs_port_t *port, uint32_t fcf_index)
6991 {
6992 	emlxs_hba_t *hba = HBA;
6993 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6994 	MAILBOXQ *mbq;
6995 	MAILBOX4 *mb4;
6996 	MATCHMAP *mp = NULL;
6997 	uint32_t rval = 0;
6998 
6999 	IOCTL_FCOE_DELETE_FCF_TABLE *fcf;
7000 	mbox_req_hdr_t *hdr_req;
7001 
7002 	if (fcf_index >= fcftab->fcfi_count) {
7003 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7004 		    "fcoe_fcftab_fcf_delete:%x fcfi:%d failed. "
7005 		    "Out of range.",
7006 		    fcftab->TID,
7007 		    fcf_index);
7008 
7009 		return (1);
7010 	}
7011 
7012 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
7013 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7014 		    "fcoe_fcftab_fcf_delete:%x fcfi:%d failed. "
7015 		    "Unable to allocate mailbox.",
7016 		    fcftab->TID,
7017 		    fcf_index);
7018 
7019 		return (1);
7020 	}
7021 
7022 	mb4 = (MAILBOX4*)mbq;
7023 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
7024 
7025 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
7026 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7027 		    "fcoe_fcftab_fcf_delete:%x fcfi:%d failed. "
7028 		    "Unable to allocate buffer.",
7029 		    fcftab->TID,
7030 		    fcf_index);
7031 
7032 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7033 		return (1);
7034 	}
7035 	bzero(mp->virt, mp->size);
7036 
7037 	mbq->nonembed = (void *)mp;
7038 	mbq->mbox_cmpl = NULL;
7039 	mbq->context = (void *)((unsigned long)fcf_index);
7040 	mbq->port = (void *)port;
7041 
7042 	mb4->un.varSLIConfig.be.embedded = 0;
7043 	mb4->mbxCommand = MBX_SLI_CONFIG;
7044 	mb4->mbxOwner = OWN_HOST;
7045 
7046 	hdr_req = (mbox_req_hdr_t *)mp->virt;
7047 	hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
7048 	hdr_req->opcode = FCOE_OPCODE_DELETE_FCF_TABLE;
7049 	hdr_req->timeout = 0;
7050 	hdr_req->req_length = sizeof (IOCTL_FCOE_DELETE_FCF_TABLE);
7051 
7052 	fcf = (IOCTL_FCOE_DELETE_FCF_TABLE *)(hdr_req + 1);
7053 	fcf->params.request.fcf_count = 1;
7054 	fcf->params.request.fcf_indexes[0] = (uint16_t)fcf_index;
7055 
7056 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7057 	    "fcoe_fcftab_fcf_delete:%x fcfi:%d. <",
7058 	    fcftab->TID,
7059 	    fcf_index);
7060 
7061 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
7062 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
7063 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7064 		    "fcoe_fcftab_fcf_delete:%x fcfi:%d failed. "
7065 		    "Unable to send request.",
7066 		    fcftab->TID,
7067 		    fcf_index);
7068 
7069 		if (mp) {
7070 			emlxs_mem_put(hba, MEM_BUF, (void *)mp);
7071 		}
7072 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7073 
7074 		return (1);
7075 	}
7076 
7077 	return (0);
7078 
7079 
7080 } /* emlxs_fcoe_fcftab_fcf_delete() */
7081 
7082 
7083 /*ARGSUSED*/
7084 static uint32_t
emlxs_fcoe_fcftab_full_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)7085 emlxs_fcoe_fcftab_full_evt_action(emlxs_port_t *port, uint32_t evt,
7086     void *arg1)
7087 {
7088 	emlxs_hba_t *hba = HBA;
7089 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7090 	FCFIobj_t *fcfp;
7091 	uint32_t rval = 0;
7092 	uint32_t mask;
7093 	uint32_t viable;
7094 	uint32_t i;
7095 	uint32_t count;
7096 
7097 	if (evt != FCF_EVENT_FCFTAB_FULL) {
7098 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7099 		    "fcoe_fcftab_full_evt_action:%x %s:%s arg=%p. "
7100 		    "Invalid event type. <",
7101 		    fcftab->TID,
7102 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7103 		    emlxs_fcf_event_xlate(evt), arg1);
7104 
7105 		return (1);
7106 	}
7107 
7108 	if (fcftab->fcfi_online == FCFTAB_MAX_FCFI_COUNT) {
7109 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7110 		    "fcoe_fcftab_full_evt_action:%x %s:%s arg=%p "
7111 		    "fcfi_online=%d. <",
7112 		    fcftab->TID,
7113 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7114 		    emlxs_fcf_event_xlate(evt), arg1,
7115 		    fcftab->fcfi_online);
7116 
7117 		return (0);
7118 	}
7119 
7120 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7121 	    "fcoe_fcftab_full_evt_action:%x %s:%s arg=%p fcfi_online=%d. "
7122 	    "Cleaning table...",
7123 	    fcftab->TID,
7124 	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7125 	    emlxs_fcf_event_xlate(evt), arg1,
7126 	    fcftab->fcfi_online);
7127 
7128 	mask =   (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7129 	    EMLXS_FCFI_CONFIGURED);
7130 	viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7131 	    EMLXS_FCFI_CONFIGURED);
7132 
7133 	count = 0;
7134 	fcfp = fcftab->table;
7135 	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7136 		if (fcfp->state == FCFI_STATE_FREE) {
7137 			continue;
7138 		}
7139 
7140 		if (fcfp->flag & EMLXS_FCFI_SELECTED) {
7141 			continue;
7142 		}
7143 
7144 		if ((fcfp->flag & mask) == viable) {
7145 			continue;
7146 		}
7147 
7148 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7149 		    "fcoe_fcftab_full_evt_action:%x. "
7150 		    "Deleting FCFI:%d %x. >",
7151 		    fcftab->TID,
7152 		    fcfp->fcf_index,
7153 		    fcfp->flag);
7154 
7155 		(void) emlxs_fcfi_free(port, fcfp);
7156 
7157 		(void) emlxs_fcoe_fcftab_fcf_delete(port, fcfp->fcf_index);
7158 
7159 		count++;
7160 	}
7161 
7162 	if (!count) {
7163 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7164 		    "fcoe_fcftab_full_evt_action:%x %s:%s arg=%p. "
7165 		    "All FCF's are viable. <",
7166 		    fcftab->TID,
7167 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7168 		    emlxs_fcf_event_xlate(evt), arg1);
7169 
7170 		return (0);
7171 	}
7172 
7173 	switch (fcftab->state) {
7174 	case FCOE_FCFTAB_STATE_SOLICIT:
7175 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7176 		    "fcoe_fcftab_full_evt_action:%x %s gen=%x. "
7177 		    "Already soliciting. <",
7178 		    fcftab->TID,
7179 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7180 		    fcftab->generation);
7181 		break;
7182 
7183 	default:
7184 		fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
7185 		fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
7186 		fcftab->generation++;
7187 
7188 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7189 		    "fcoe_fcftab_full_evt_action:%x %s gen=%x. Soliciting.",
7190 		    fcftab->TID,
7191 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7192 		    fcftab->generation);
7193 
7194 		rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
7195 		    FCF_REASON_EVENT, evt, arg1);
7196 		break;
7197 	}
7198 
7199 	return (rval);
7200 
7201 } /* emlxs_fcoe_fcftab_full_evt_action() */
7202 
7203 
7204 /*ARGSUSED*/
7205 static uint32_t
emlxs_fcoe_fcftab_online_action(emlxs_port_t * port,uint32_t evt,void * arg1)7206 emlxs_fcoe_fcftab_online_action(emlxs_port_t *port, uint32_t evt,
7207     void *arg1)
7208 {
7209 	emlxs_hba_t *hba = HBA;
7210 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7211 	emlxs_config_t *cfg = &CFG;
7212 	FCFIobj_t *fcfp;
7213 	uint32_t rval = 0;
7214 	uint32_t mask;
7215 	uint32_t viable;
7216 	uint32_t i;
7217 	uint32_t count = 0;
7218 
7219 	if (fcftab->state != FCOE_FCFTAB_STATE_ONLINE) {
7220 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7221 		    "fcoe_fcftab_online_action:%x %s:%s arg=%p. "
7222 		    "Invalid state. <",
7223 		    fcftab->TID,
7224 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7225 		    emlxs_fcf_event_xlate(evt), arg1);
7226 		return (1);
7227 	}
7228 
7229 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
7230 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7231 		    "fcoe_fcftab_online_action:%x flag=%x. "
7232 		    "Handling request.",
7233 		    fcftab->TID,
7234 		    fcftab->flag);
7235 
7236 		rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
7237 		return (rval);
7238 	}
7239 
7240 	if (fcftab->fcfi_online == 0) {
7241 		mask =   (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7242 		    EMLXS_FCFI_CONFIGURED);
7243 		viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7244 		    EMLXS_FCFI_CONFIGURED);
7245 
7246 		/* Count viable FCF's in table */
7247 		count = 0;
7248 		fcfp = fcftab->table;
7249 		for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7250 			if (fcfp->state == FCFI_STATE_FREE) {
7251 				continue;
7252 			}
7253 
7254 			if ((fcfp->flag & mask) == viable) {
7255 				count++;
7256 			}
7257 		}
7258 
7259 		if (count) {
7260 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7261 			    "fcoe_fcftab_online_action:%x %s:%s "
7262 			    "fcfi_online=0,%d,%d. Starting resolicit timer. <",
7263 			    fcftab->TID,
7264 			    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7265 			    emlxs_fcf_event_xlate(evt),
7266 			    fcftab->fcfi_count, count);
7267 
7268 			/* Start the solicit timer */
7269 			fcftab->sol_timer = hba->timer_tics +
7270 			    cfg[CFG_FCF_RESOLICIT_DELAY].current;
7271 		} else {
7272 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7273 			    "fcoe_fcftab_online_action:%x %s:%s "
7274 			    "fcfi_online=0,%d,0. Wait for FCF event. <",
7275 			    fcftab->TID,
7276 			    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7277 			    emlxs_fcf_event_xlate(evt),
7278 			    fcftab->fcfi_count);
7279 		}
7280 
7281 		emlxs_fcf_linkdown(port);
7282 
7283 		return (0);
7284 	}
7285 
7286 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7287 	    "fcoe_fcftab_online_action:%x flag=%x fcfi_online=%d. "
7288 	    "Online. <",
7289 	    fcftab->TID,
7290 	    fcftab->flag,
7291 	    fcftab->fcfi_online);
7292 
7293 	emlxs_fcf_linkup(port);
7294 
7295 	return (rval);
7296 
7297 } /* emlxs_fcoe_fcftab_online_action() */
7298 
7299 
7300 /*ARGSUSED*/
7301 static uint32_t
emlxs_fcoe_fcftab_offline_action(emlxs_port_t * port,uint32_t evt,void * arg1)7302 emlxs_fcoe_fcftab_offline_action(emlxs_port_t *port, uint32_t evt,
7303     void *arg1)
7304 {
7305 	emlxs_hba_t *hba = HBA;
7306 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7307 	uint32_t rval = 0;
7308 
7309 	if (fcftab->state != FCOE_FCFTAB_STATE_OFFLINE) {
7310 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7311 		    "fcoe_fcftab_offline_action:%x %s:%s arg=%p. "
7312 		    "Invalid state. <",
7313 		    fcftab->TID,
7314 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7315 		    emlxs_fcf_event_xlate(evt), arg1);
7316 		return (1);
7317 	}
7318 
7319 
7320 	fcftab->flag &= ~EMLXS_FCOE_FCFTAB_OFFLINE_REQ;
7321 
7322 	if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
7323 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7324 		    "fcoe_fcftab_offline_action:%x %s:%s arg=%p flag=%x. "
7325 		    "Handling request.",
7326 		    fcftab->TID,
7327 		    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7328 		    emlxs_fcf_event_xlate(evt), arg1,
7329 		    fcftab->flag);
7330 
7331 		rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
7332 		return (rval);
7333 	}
7334 
7335 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7336 	    "fcoe_fcftab_offline_action:%x %s:%s arg=%p fcfi_online=%d. "
7337 	    "Offline. <",
7338 	    fcftab->TID,
7339 	    emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7340 	    emlxs_fcf_event_xlate(evt), arg1,
7341 	    fcftab->fcfi_online);
7342 
7343 	return (rval);
7344 
7345 } /* emlxs_fcoe_fcftab_offline_action() */
7346 
7347 
7348 /* ************************************************************************** */
7349 /* FCFI */
7350 /* ************************************************************************** */
7351 
7352 static char *
emlxs_fcfi_state_xlate(uint32_t state)7353 emlxs_fcfi_state_xlate(uint32_t state)
7354 {
7355 	static char buffer[32];
7356 	uint32_t i;
7357 	uint32_t count;
7358 
7359 	count = sizeof (emlxs_fcfi_state_table) / sizeof (emlxs_table_t);
7360 	for (i = 0; i < count; i++) {
7361 		if (state == emlxs_fcfi_state_table[i].code) {
7362 			return (emlxs_fcfi_state_table[i].string);
7363 		}
7364 	}
7365 
7366 	(void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
7367 	return (buffer);
7368 
7369 } /* emlxs_fcfi_state_xlate() */
7370 
7371 
7372 static uint32_t
emlxs_fcfi_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7373 emlxs_fcfi_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
7374     void *arg1)
7375 {
7376 	uint32_t rval = 0;
7377 	uint32_t(*func) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *);
7378 	uint32_t index;
7379 	uint32_t events;
7380 	uint16_t state;
7381 
7382 	/* Convert event to action table index */
7383 	switch (evt) {
7384 	case FCF_EVENT_STATE_ENTER:
7385 		index = 0;
7386 		break;
7387 	case FCF_EVENT_FCFI_ONLINE:
7388 		index = 1;
7389 		break;
7390 	case FCF_EVENT_FCFI_OFFLINE:
7391 		index = 2;
7392 		break;
7393 	case FCF_EVENT_FCFI_PAUSE:
7394 		index = 3;
7395 		break;
7396 	case FCF_EVENT_VFI_ONLINE:
7397 		index = 4;
7398 		break;
7399 	case FCF_EVENT_VFI_OFFLINE:
7400 		index = 5;
7401 		break;
7402 	default:
7403 		return (1);
7404 	}
7405 
7406 	events = FCFI_ACTION_EVENTS;
7407 	state  = fcfp->state;
7408 
7409 	index += (state * events);
7410 	func   = (uint32_t(*) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *))
7411 	    emlxs_fcfi_action_table[index];
7412 
7413 	if (!func) {
7414 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7415 		    "fcfi_action:%d %s:%s arg=%p. No action. <",
7416 		    fcfp->fcf_index,
7417 		    emlxs_fcfi_state_xlate(fcfp->state),
7418 		    emlxs_fcf_event_xlate(evt), arg1);
7419 
7420 		return (1);
7421 	}
7422 
7423 	rval = (func)(port, fcfp, evt, arg1);
7424 
7425 	return (rval);
7426 
7427 } /* emlxs_fcfi_action() */
7428 
7429 
7430 static uint32_t
emlxs_fcfi_event(emlxs_port_t * port,uint32_t evt,void * arg1)7431 emlxs_fcfi_event(emlxs_port_t *port, uint32_t evt,
7432     void *arg1)
7433 {
7434 	FCFIobj_t *fcfp = NULL;
7435 	VFIobj_t *vfip = NULL;
7436 	uint32_t rval = 0;
7437 
7438 	/* Filter events and acquire fcfi context */
7439 	switch (evt) {
7440 	case FCF_EVENT_VFI_ONLINE:
7441 	case FCF_EVENT_VFI_OFFLINE:
7442 		vfip = (VFIobj_t *)arg1;
7443 
7444 		if (!vfip) {
7445 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7446 			    "fcfi_event: %s arg=%p. Null VFI found. <",
7447 			    emlxs_fcf_event_xlate(evt), arg1);
7448 
7449 			return (1);
7450 		}
7451 
7452 		fcfp = vfip->fcfp;
7453 		if (!fcfp) {
7454 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7455 			    "fcfi_event: %s arg=%p. FCF not found. <",
7456 			    emlxs_fcf_event_xlate(evt), arg1);
7457 
7458 			return (1);
7459 		}
7460 		break;
7461 
7462 	case FCF_EVENT_FCFI_ONLINE:
7463 	case FCF_EVENT_FCFI_OFFLINE:
7464 	case FCF_EVENT_FCFI_PAUSE:
7465 		fcfp = (FCFIobj_t *)arg1;
7466 		if (!fcfp) {
7467 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7468 			    "fcfi_event: %s arg=%p. Null FCFI found. <",
7469 			    emlxs_fcf_event_xlate(evt), arg1);
7470 
7471 			return (1);
7472 		}
7473 		break;
7474 
7475 	default:
7476 		return (1);
7477 	}
7478 
7479 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7480 	    "fcfi_event:%d %s:%s arg=%p",
7481 	    fcfp->fcf_index,
7482 	    emlxs_fcfi_state_xlate(fcfp->state),
7483 	    emlxs_fcf_event_xlate(evt), arg1);
7484 
7485 	rval = emlxs_fcfi_action(port, fcfp, evt, arg1);
7486 
7487 	return (rval);
7488 
7489 } /* emlxs_fcfi_event() */
7490 
7491 
7492 /* EMLXS_FCF_LOCK must be held to enter */
7493 /*ARGSUSED*/
7494 static uint32_t
emlxs_fcfi_state(emlxs_port_t * port,FCFIobj_t * fcfp,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)7495 emlxs_fcfi_state(emlxs_port_t *port, FCFIobj_t *fcfp, uint16_t state,
7496     uint16_t reason, uint32_t explain, void *arg1)
7497 {
7498 	uint32_t rval = 0;
7499 
7500 	if (state >= FCFI_ACTION_STATES) {
7501 		return (1);
7502 	}
7503 
7504 	if ((fcfp->state == state) &&
7505 	    (reason != FCF_REASON_REENTER)) {
7506 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7507 		    "fcfi_state:%d %s:%s:0x%x arg=%p. "
7508 		    "State not changed. <",
7509 		    fcfp->fcf_index,
7510 		    emlxs_fcfi_state_xlate(state),
7511 		    emlxs_fcf_reason_xlate(reason),
7512 		    explain, arg1);
7513 		return (1);
7514 	}
7515 
7516 	if (!reason) {
7517 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
7518 		    "fcfi_state:%d %s-->%s arg=%p",
7519 		    fcfp->fcf_index,
7520 		    emlxs_fcfi_state_xlate(fcfp->state),
7521 		    emlxs_fcfi_state_xlate(state), arg1);
7522 	} else if (reason == FCF_REASON_EVENT) {
7523 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
7524 		    "fcfi_state:%d %s-->%s:%s:%s arg=%p",
7525 		    fcfp->fcf_index,
7526 		    emlxs_fcfi_state_xlate(fcfp->state),
7527 		    emlxs_fcfi_state_xlate(state),
7528 		    emlxs_fcf_reason_xlate(reason),
7529 		    emlxs_fcf_event_xlate(explain), arg1);
7530 	} else if (explain) {
7531 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
7532 		    "fcfi_state:%d %s-->%s:%s:0x%x arg=%p",
7533 		    fcfp->fcf_index,
7534 		    emlxs_fcfi_state_xlate(fcfp->state),
7535 		    emlxs_fcfi_state_xlate(state),
7536 		    emlxs_fcf_reason_xlate(reason),
7537 		    explain, arg1);
7538 	} else {
7539 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
7540 		    "fcfi_state:%d %s-->%s:%s arg=%p",
7541 		    fcfp->fcf_index,
7542 		    emlxs_fcfi_state_xlate(fcfp->state),
7543 		    emlxs_fcfi_state_xlate(state),
7544 		    emlxs_fcf_reason_xlate(reason), arg1);
7545 	}
7546 
7547 	fcfp->prev_state = fcfp->state;
7548 	fcfp->prev_reason = fcfp->reason;
7549 	fcfp->state = state;
7550 	fcfp->reason = reason;
7551 
7552 	rval = emlxs_fcfi_action(port, fcfp, FCF_EVENT_STATE_ENTER, arg1);
7553 
7554 	return (rval);
7555 
7556 } /* emlxs_fcfi_state() */
7557 
7558 
7559 static FCFIobj_t *
emlxs_fcfi_alloc(emlxs_port_t * port)7560 emlxs_fcfi_alloc(emlxs_port_t *port)
7561 {
7562 	emlxs_hba_t	*hba = HBA;
7563 	FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7564 	uint16_t	i;
7565 	FCFIobj_t	*fcfp;
7566 
7567 	fcfp = fcftab->table;
7568 	for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7569 		if (fcfp->state == FCFI_STATE_FREE) {
7570 
7571 			bzero(fcfp, sizeof (FCFIobj_t));
7572 			fcfp->index = i;
7573 			fcfp->FCFI  = 0xFFFF;
7574 
7575 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7576 			    "fcfi_alloc:%d. Allocating FCFI. >",
7577 			    fcfp->index);
7578 
7579 			(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
7580 			    0, 0, 0);
7581 			return (fcfp);
7582 		}
7583 	}
7584 
7585 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7586 	    "fcfi_alloc: Out of FCFI objects.",
7587 	    fcfp->index);
7588 
7589 	return (NULL);
7590 
7591 } /* emlxs_fcfi_alloc() */
7592 
7593 
7594 static uint32_t
emlxs_fcfi_free(emlxs_port_t * port,FCFIobj_t * fcfp)7595 emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp)
7596 {
7597 	uint32_t rval = 0;
7598 
7599 	rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_FREE, 0, 0, 0);
7600 
7601 	return (rval);
7602 
7603 } /* emlxs_fcfi_free() */
7604 
7605 
7606 static FCFIobj_t *
emlxs_fcfi_find(emlxs_port_t * port,FCF_RECORD_t * fcfrec,uint32_t * fcf_index)7607 emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec, uint32_t *fcf_index)
7608 {
7609 	emlxs_hba_t	*hba = HBA;
7610 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
7611 	uint32_t	i;
7612 	uint32_t	index;
7613 	FCFIobj_t	*fcfp;
7614 
7615 	if (fcfrec) {
7616 		/* Check for a matching FCF index, fabric name, */
7617 		/* and mac address */
7618 		fcfp = fcftab->table;
7619 		for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7620 			if (fcfp->state == FCFI_STATE_FREE) {
7621 				continue;
7622 			}
7623 
7624 			if ((fcfp->fcf_index == fcfrec->fcf_index) &&
7625 			    (bcmp((char *)fcfrec->fabric_name_identifier,
7626 			    fcfp->fcf_rec.fabric_name_identifier, 8) == 0) &&
7627 			    (bcmp((char *)fcfrec->fcf_mac_address_hi,
7628 			    fcfp->fcf_rec.fcf_mac_address_hi, 4) == 0) &&
7629 			    (bcmp((char *)fcfrec->fcf_mac_address_low,
7630 			    fcfp->fcf_rec.fcf_mac_address_low, 2) == 0)) {
7631 				return (fcfp);
7632 			}
7633 		}
7634 
7635 	} else if (fcf_index) {
7636 		/* Check for a matching FCF index only */
7637 		index = *fcf_index;
7638 		fcfp = fcftab->table;
7639 		for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7640 			if (fcfp->state == FCFI_STATE_FREE) {
7641 				continue;
7642 			}
7643 
7644 			if (fcfp->fcf_index == index) {
7645 				return (fcfp);
7646 			}
7647 		}
7648 	}
7649 
7650 	return (NULL);
7651 
7652 } /* emlxs_fcfi_find() */
7653 
7654 
7655 /*ARGSUSED*/
7656 static uint32_t
emlxs_fcfi_free_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7657 emlxs_fcfi_free_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
7658     void *arg1)
7659 {
7660 
7661 	if (fcfp->state != FCFI_STATE_FREE) {
7662 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7663 		    "fcfi_free_action:%d %s:%s arg=%p. "
7664 		    "Invalid state. <",
7665 		    fcfp->fcf_index,
7666 		    emlxs_fcfi_state_xlate(fcfp->state),
7667 		    emlxs_fcf_event_xlate(evt), arg1);
7668 		return (1);
7669 	}
7670 
7671 	if (fcfp->vfi_online) {
7672 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7673 		    "fcfi_free_action:%d flag=%x vfi_online=%d",
7674 		    fcfp->fcf_index,
7675 		    fcfp->flag,
7676 		    fcfp->vfi_online);
7677 	}
7678 
7679 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7680 	    "fcfi_free_action:%d flag=%x. FCF freed. <",
7681 	    fcfp->fcf_index,
7682 	    fcfp->flag);
7683 
7684 	fcfp->flag = 0;
7685 
7686 	return (0);
7687 
7688 } /* emlxs_fcfi_free_action() */
7689 
7690 
7691 /*ARGSUSED*/
7692 static uint32_t
emlxs_fcfi_offline_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7693 emlxs_fcfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
7694     void *arg1)
7695 {
7696 	emlxs_hba_t *hba = HBA;
7697 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
7698 	uint32_t rval = 0;
7699 
7700 	if (fcfp->state != FCFI_STATE_OFFLINE) {
7701 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7702 		    "fcfi_offline_action:%d %s:%s arg=%p. "
7703 		    "Invalid state. <",
7704 		    fcfp->fcf_index,
7705 		    emlxs_fcfi_state_xlate(fcfp->state),
7706 		    emlxs_fcf_event_xlate(evt), arg1);
7707 		return (1);
7708 	}
7709 
7710 	fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
7711 
7712 	if (fcfp->prev_state == FCFI_STATE_FREE) {
7713 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7714 		    "fcfi_offline_action:%d fcfi_online=%d. <",
7715 		    fcfp->fcf_index,
7716 		    fcftab->fcfi_online);
7717 
7718 		return (0);
7719 	}
7720 
7721 	if (fcfp->vfi_online) {
7722 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7723 		    "fcfi_offline_action:%d vfi_online=%d.",
7724 		    fcfp->fcf_index,
7725 		    fcfp->vfi_online);
7726 	}
7727 
7728 	if (fcfp->flag & EMLXS_FCFI_FCFTAB) {
7729 		fcfp->flag &= ~EMLXS_FCFI_FCFTAB;
7730 
7731 		if (fcftab->fcfi_online) {
7732 			fcftab->fcfi_online--;
7733 		}
7734 	}
7735 
7736 	/* Check if online was requested */
7737 	if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) {
7738 
7739 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7740 		    "fcfi_offline_action:%d fcfi_online=%d. "
7741 		    "Online requested.",
7742 		    fcfp->fcf_index,
7743 		    fcftab->fcfi_online);
7744 
7745 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
7746 		    FCF_REASON_REQUESTED, 0, arg1);
7747 		return (rval);
7748 	}
7749 
7750 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7751 	    "fcfi_offline_action:%d fcfi_online=%d. "
7752 	    "FCFI offline. Notifying fcftab. >",
7753 	    fcfp->fcf_index,
7754 	    fcftab->fcfi_online);
7755 
7756 	/* Notify FCFTAB */
7757 	rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp);
7758 
7759 	return (rval);
7760 
7761 } /* emlxs_fcfi_offline_action() */
7762 
7763 
7764 /*ARGSUSED*/
7765 static uint32_t
emlxs_fcfi_vfi_online_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7766 emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
7767     uint32_t evt, void *arg1)
7768 {
7769 	uint32_t rval = 0;
7770 
7771 	if (evt != FCF_EVENT_VFI_ONLINE) {
7772 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7773 		    "fcfi_vfi_online_evt_action:%d %s:%s arg=%p flag=%x. "
7774 		    "Invalid event type. <",
7775 		    fcfp->fcf_index,
7776 		    emlxs_fcfi_state_xlate(fcfp->state),
7777 		    emlxs_fcf_event_xlate(evt), arg1,
7778 		    fcfp->flag);
7779 		return (1);
7780 	}
7781 
7782 	switch (fcfp->state) {
7783 	case FCFI_STATE_ONLINE:
7784 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7785 		    "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. "
7786 		    "Reentering online.",
7787 		    fcfp->fcf_index,
7788 		    fcfp->flag,
7789 		    fcfp->vfi_online);
7790 
7791 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
7792 		    FCF_REASON_REENTER, evt, arg1);
7793 		break;
7794 
7795 	case FCFI_STATE_VFI_ONLINE:
7796 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7797 		    "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. "
7798 		    "Online cmpl.",
7799 		    fcfp->fcf_index,
7800 		    fcfp->flag,
7801 		    fcfp->vfi_online);
7802 
7803 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE_CMPL,
7804 		    FCF_REASON_EVENT, evt, arg1);
7805 		break;
7806 
7807 	default:
7808 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7809 		    "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. <",
7810 		    fcfp->fcf_index,
7811 		    fcfp->flag,
7812 		    fcfp->vfi_online);
7813 		return (0);
7814 	}
7815 
7816 	return (rval);
7817 
7818 } /* emlxs_fcfi_vfi_online_evt_action() */
7819 
7820 
7821 /*ARGSUSED*/
7822 static uint32_t
emlxs_fcfi_offline_handler(emlxs_port_t * port,FCFIobj_t * fcfp,void * arg1)7823 emlxs_fcfi_offline_handler(emlxs_port_t *port, FCFIobj_t *fcfp, void *arg1)
7824 {
7825 	uint32_t rval = 0;
7826 
7827 	if (!(fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
7828 		return (0);
7829 	}
7830 
7831 	if (fcfp->vfi_online) {
7832 		if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) {
7833 			rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED,
7834 			    FCF_REASON_REQUESTED, 0, arg1);
7835 		} else {
7836 			rval = emlxs_fcfi_state(port, fcfp,
7837 			    FCFI_STATE_VFI_OFFLINE, FCF_REASON_REQUESTED,
7838 			    0, arg1);
7839 		}
7840 
7841 	} else if (fcfp->flag & EMLXS_FCFI_REG) {
7842 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
7843 		    FCF_REASON_REQUESTED, 0, arg1);
7844 
7845 	} else {
7846 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
7847 		    FCF_REASON_REQUESTED, 0, arg1);
7848 	}
7849 
7850 	return (rval);
7851 
7852 } /* emlxs_fcfi_offline_handler() */
7853 
7854 
7855 /*ARGSUSED*/
7856 static uint32_t
emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7857 emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
7858     uint32_t evt, void *arg1)
7859 {
7860 	uint32_t rval = 0;
7861 	VFIobj_t *vfip;
7862 
7863 	if (evt != FCF_EVENT_VFI_OFFLINE) {
7864 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7865 		    "fcfi_vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
7866 		    "Invalid event type. <",
7867 		    fcfp->fcf_index,
7868 		    emlxs_fcfi_state_xlate(fcfp->state),
7869 		    emlxs_fcf_event_xlate(evt), arg1,
7870 		    fcfp->flag);
7871 		return (1);
7872 	}
7873 
7874 	vfip = (VFIobj_t *)arg1;
7875 	vfip->fcfp = NULL;
7876 
7877 	switch (fcfp->state) {
7878 	case FCFI_STATE_VFI_ONLINE:
7879 	case FCFI_STATE_ONLINE:
7880 		if (fcfp->vfi_online == 0) {
7881 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7882 			    "fcfi_vfi_offline_evt_action:%d flag=%x "
7883 			    "vfi_online=%d. Offlining.",
7884 			    fcfp->fcf_index,
7885 			    fcfp->flag, fcfp->vfi_online);
7886 
7887 			fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
7888 			fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
7889 
7890 			rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
7891 		} else {
7892 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7893 			    "fcfi_vfi_offline_evt_action:%d flag=%x "
7894 			    "vfi_online=%d. <",
7895 			    fcfp->fcf_index,
7896 			    fcfp->flag, fcfp->vfi_online);
7897 		}
7898 		break;
7899 
7900 	case FCFI_STATE_PAUSED:
7901 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7902 		    "fcfi_vfi_offline_evt_action:%d flag=%x vfi_online=%d. <",
7903 		    fcfp->fcf_index,
7904 		    fcfp->flag, fcfp->vfi_online);
7905 		break;
7906 
7907 	case FCFI_STATE_VFI_OFFLINE:
7908 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7909 		    "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.",
7910 		    fcfp->fcf_index,
7911 		    fcfp->flag);
7912 
7913 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL,
7914 		    FCF_REASON_EVENT, evt, arg1);
7915 		break;
7916 
7917 	case FCFI_STATE_VFI_OFFLINE_CMPL:
7918 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7919 		    "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.",
7920 		    fcfp->fcf_index,
7921 		    fcfp->flag);
7922 
7923 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL,
7924 		    FCF_REASON_REENTER, evt, arg1);
7925 		break;
7926 
7927 	default:
7928 		if (fcfp->vfi_online == 0) {
7929 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7930 			    "fcfi_vfi_offline_evt_action:%d flag=%x "
7931 			    "vfi_online=%d. Offline requested. <",
7932 			    fcfp->fcf_index,
7933 			    fcfp->flag, fcfp->vfi_online);
7934 
7935 			fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
7936 			fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
7937 		} else {
7938 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7939 			    "fcfi_vfi_offline_evt_action:%d flag = %x "
7940 			    "vfi_online=%d. <",
7941 			    fcfp->fcf_index,
7942 			    fcfp->flag, fcfp->vfi_online);
7943 		}
7944 		return (0);
7945 	}
7946 
7947 	return (rval);
7948 
7949 } /* emlxs_fcfi_vfi_offline_evt_action() */
7950 
7951 
7952 /*ARGSUSED*/
7953 static uint32_t
emlxs_fcfi_online_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7954 emlxs_fcfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
7955     uint32_t evt, void *arg1)
7956 {
7957 	uint32_t rval = 0;
7958 
7959 	if (evt != FCF_EVENT_FCFI_ONLINE) {
7960 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7961 		    "fcfi_online_evt_action:%d %s:%s arg=%p. "
7962 		    "Invalid event type. <",
7963 		    fcfp->fcf_index,
7964 		    emlxs_fcfi_state_xlate(fcfp->state),
7965 		    emlxs_fcf_event_xlate(evt), arg1);
7966 		return (1);
7967 	}
7968 
7969 	if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) {
7970 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7971 		    "fcfi_online_evt_action:%d. "
7972 		    "Online already requested. <",
7973 		    fcfp->fcf_index);
7974 		return (1);
7975 	}
7976 
7977 	fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
7978 	fcfp->flag |= EMLXS_FCFI_ONLINE_REQ;
7979 
7980 	switch (fcfp->state) {
7981 	case FCFI_STATE_OFFLINE:
7982 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7983 		    "fcfi_online_evt_action:%d flag=%x. Initiating online.",
7984 		    fcfp->fcf_index,
7985 		    fcfp->flag);
7986 
7987 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
7988 		    FCF_REASON_EVENT, evt, arg1);
7989 		break;
7990 
7991 	case FCFI_STATE_VFI_OFFLINE:
7992 	case FCFI_STATE_PAUSED:
7993 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7994 		    "fcfi_online_evt_action:%d flag=%x. Initiating online.",
7995 		    fcfp->fcf_index,
7996 		    fcfp->flag);
7997 
7998 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
7999 		    FCF_REASON_EVENT, evt, arg1);
8000 		break;
8001 
8002 	case FCFI_STATE_ONLINE:
8003 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8004 		    "fcfi_online_evt_action:%d flag=%x. Reentering online.",
8005 		    fcfp->fcf_index,
8006 		    fcfp->flag);
8007 
8008 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
8009 		    FCF_REASON_REENTER, evt, arg1);
8010 		break;
8011 
8012 	default:
8013 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8014 		    "fcfi_online_evt_action:%d flag=%x. <",
8015 		    fcfp->fcf_index,
8016 		    fcfp->flag);
8017 		break;
8018 	}
8019 
8020 	return (rval);
8021 
8022 } /* emlxs_fcfi_online_evt_action() */
8023 
8024 
8025 /*ARGSUSED*/
8026 static uint32_t
emlxs_fcfi_vfi_online_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8027 emlxs_fcfi_vfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8028     uint32_t evt, void *arg1)
8029 {
8030 	emlxs_hba_t *hba = HBA;
8031 	uint32_t i;
8032 	uint32_t rval = 0;
8033 	VFIobj_t *vfip;
8034 
8035 	if (fcfp->state != FCFI_STATE_VFI_ONLINE) {
8036 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8037 		    "fcfi_vfi_online_action:%d %s:%s arg=%p. "
8038 		    "Invalid state. <",
8039 		    fcfp->fcf_index,
8040 		    emlxs_fcfi_state_xlate(fcfp->state),
8041 		    emlxs_fcf_event_xlate(evt), arg1);
8042 		return (1);
8043 	}
8044 
8045 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8046 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8047 		    "fcfi_vfi_online_action:%d. Offline requested.",
8048 		    fcfp->fcf_index);
8049 
8050 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8051 		return (rval);
8052 	}
8053 
8054 	if (fcfp->vfi_online > 0) {
8055 		/* Waking up out after being paused */
8056 
8057 		/* Find first VFI of this FCFI */
8058 		vfip = hba->sli.sli4.VFI_table;
8059 		for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
8060 			if (vfip->fcfp == fcfp) {
8061 				break;
8062 			}
8063 		}
8064 
8065 	} else {
8066 
8067 		/* Find first available VFI */
8068 		vfip = hba->sli.sli4.VFI_table;
8069 		for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
8070 			if (vfip->fcfp == NULL) {
8071 				vfip->fcfp = fcfp;
8072 				break;
8073 			}
8074 		}
8075 	}
8076 
8077 	if (i == hba->sli.sli4.VFICount) {
8078 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8079 		    "fcfi_vfi_online_action:%d vfi_online=%d. "
8080 		    "No VFI found. Offlining.",
8081 		    fcfp->fcf_index,
8082 		    fcfp->vfi_online);
8083 
8084 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8085 		fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8086 
8087 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8088 		return (rval);
8089 	}
8090 
8091 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8092 	    "fcfi_vfi_online_action:%d vfi_online=%d. Onlining VFI:%d. >",
8093 	    fcfp->fcf_index,
8094 	    fcfp->vfi_online,
8095 	    vfip->VFI);
8096 
8097 	rval = emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
8098 
8099 	/* Wait for FCF_EVENT_VFI_ONLINE in return */
8100 
8101 	return (rval);
8102 
8103 } /* emlxs_fcfi_vfi_online_action() */
8104 
8105 
8106 /*ARGSUSED*/
8107 static uint32_t
emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8108 emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8109     uint32_t evt, void *arg1)
8110 {
8111 	uint32_t rval = 0;
8112 
8113 	if (fcfp->state != FCFI_STATE_VFI_ONLINE_CMPL) {
8114 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8115 		    "fcfi_vfi_online_cmpl_action:%d %s:%s arg=%p. "
8116 		    "Invalid state. <",
8117 		    fcfp->fcf_index,
8118 		    emlxs_fcfi_state_xlate(fcfp->state),
8119 		    emlxs_fcf_event_xlate(evt), arg1);
8120 		return (1);
8121 	}
8122 
8123 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8124 	    "fcfi_vfi_online_cmpl_action:%d. Going online.",
8125 	    fcfp->fcf_index);
8126 
8127 	rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
8128 	    FCF_REASON_EVENT, evt, arg1);
8129 
8130 	return (rval);
8131 
8132 } /* emlxs_fcfi_vfi_online_cmpl_action() */
8133 
8134 
8135 /*ARGSUSED*/
8136 static uint32_t
emlxs_fcfi_vfi_offline_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8137 emlxs_fcfi_vfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8138     void *arg1)
8139 {
8140 	emlxs_hba_t *hba = HBA;
8141 	VFIobj_t *vfip;
8142 	uint32_t rval = 0;
8143 	int32_t i;
8144 
8145 	if (fcfp->state != FCFI_STATE_VFI_OFFLINE) {
8146 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8147 		    "fcfi_vfi_offline_action:%d %s:%s arg=%p. "
8148 		    "Invalid state. <",
8149 		    fcfp->fcf_index,
8150 		    emlxs_fcfi_state_xlate(fcfp->state),
8151 		    emlxs_fcf_event_xlate(evt), arg1);
8152 
8153 		return (1);
8154 	}
8155 
8156 	if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) {
8157 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8158 		    "fcfi_vfi_offline_action:%d vfi_online=%d. Pausing.",
8159 		    fcfp->fcf_index,
8160 		    fcfp->vfi_online);
8161 
8162 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED,
8163 		    FCF_REASON_EVENT, evt, arg1);
8164 
8165 		return (rval);
8166 	}
8167 
8168 	if (fcfp->vfi_online == 0) {
8169 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8170 		    "fcfi_vfi_offline_action:%d. "
8171 		    "VFI already offline. Skipping VFI offline.",
8172 		    fcfp->fcf_index);
8173 
8174 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
8175 		    FCF_REASON_EVENT, evt, arg1);
8176 
8177 		return (rval);
8178 	}
8179 
8180 	/* Offline VFI's of this FCFI */
8181 	for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) {
8182 		vfip = &hba->sli.sli4.VFI_table[i];
8183 
8184 		if ((vfip->fcfp != fcfp) ||
8185 		    (vfip->state == VFI_STATE_OFFLINE) ||
8186 		    (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
8187 			continue;
8188 		}
8189 
8190 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8191 		    "fcfi_vfi_offline_action:%d. Offlining VFI:%d >",
8192 		    fcfp->fcf_index,
8193 		    vfip->VFI);
8194 
8195 		(void) emlxs_vfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip);
8196 	}
8197 
8198 	/* Wait for FCF_EVENT_VFI_OFFLINE in return */
8199 
8200 	return (0);
8201 
8202 } /* emlxs_fcfi_vfi_offline_action() */
8203 
8204 
8205 /*ARGSUSED*/
8206 static uint32_t
emlxs_fcfi_paused_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8207 emlxs_fcfi_paused_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8208     void *arg1)
8209 {
8210 	emlxs_hba_t *hba = HBA;
8211 	VFIobj_t *vfip;
8212 	int32_t i;
8213 
8214 	if (fcfp->state != FCFI_STATE_PAUSED) {
8215 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8216 		    "fcfi_paused_action:%d %s:%s arg=%p. "
8217 		    "Invalid state. <",
8218 		    fcfp->fcf_index,
8219 		    emlxs_fcfi_state_xlate(fcfp->state),
8220 		    emlxs_fcf_event_xlate(evt), arg1);
8221 
8222 		return (1);
8223 	}
8224 
8225 	fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
8226 
8227 	/* Pause all VFI's of this FCFI */
8228 	for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) {
8229 		vfip = &hba->sli.sli4.VFI_table[i];
8230 
8231 		if ((vfip->state == VFI_STATE_OFFLINE) ||
8232 		    (vfip->state == VFI_STATE_PAUSED) ||
8233 		    (vfip->fcfp != fcfp)) {
8234 			continue;
8235 		}
8236 
8237 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8238 		    "fcfi_paused_action:%d vfi_online=%d. Pausing VFI:%d. >",
8239 		    fcfp->fcf_index,
8240 		    fcfp->vfi_online,
8241 		    vfip->VFI);
8242 
8243 		(void) emlxs_vfi_event(port, FCF_EVENT_VFI_PAUSE, vfip);
8244 	}
8245 
8246 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8247 	    "fcfi_paused_action:%d vfi_online=%d. FCFI paused. <",
8248 	    fcfp->fcf_index,
8249 	    fcfp->vfi_online);
8250 
8251 	return (0);
8252 
8253 } /* emlxs_fcfi_paused_action() */
8254 
8255 
8256 /*ARGSUSED*/
8257 static uint32_t
emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8258 emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8259     uint32_t evt, void *arg1)
8260 {
8261 	uint32_t rval = 0;
8262 
8263 	if (fcfp->state != FCFI_STATE_VFI_OFFLINE_CMPL) {
8264 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8265 		    "fcfi_vfi_offline_cmpl_action:%d %s:%s arg=%p. "
8266 		    "Invalid state. <",
8267 		    fcfp->fcf_index,
8268 		    emlxs_fcfi_state_xlate(fcfp->state),
8269 		    emlxs_fcf_event_xlate(evt), arg1);
8270 		return (1);
8271 	}
8272 
8273 	if ((fcfp->vfi_online == 0) &&
8274 	    (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
8275 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8276 		    "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. "
8277 		    "Unregistering.",
8278 		    fcfp->fcf_index,
8279 		    fcfp->vfi_online);
8280 
8281 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
8282 		    FCF_REASON_EVENT, evt, arg1);
8283 	} else {
8284 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8285 		    "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. <",
8286 		    fcfp->fcf_index,
8287 		    fcfp->vfi_online);
8288 	}
8289 
8290 	return (rval);
8291 
8292 } /* emlxs_fcfi_vfi_offline_cmpl_action() */
8293 
8294 
8295 /*ARGSUSED*/
8296 static uint32_t
emlxs_fcfi_offline_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8297 emlxs_fcfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8298     void *arg1)
8299 {
8300 	uint32_t rval = 0;
8301 
8302 	if (evt != FCF_EVENT_FCFI_OFFLINE) {
8303 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8304 		    "fcfi_offline_evt_action:%d %s:%s arg=%p. "
8305 		    "Invalid event type. <",
8306 		    fcfp->fcf_index,
8307 		    emlxs_fcfi_state_xlate(fcfp->state),
8308 		    emlxs_fcf_event_xlate(evt), arg1);
8309 		return (1);
8310 	}
8311 
8312 	if ((fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) &&
8313 	    !(fcfp->flag & EMLXS_FCFI_PAUSE_REQ)) {
8314 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8315 		    "fcfi_offline_evt_action:%d. Offline already requested. <",
8316 		    fcfp->fcf_index);
8317 		return (1);
8318 	}
8319 
8320 	switch (fcfp->state) {
8321 	case FCFI_STATE_OFFLINE:
8322 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8323 		    "fcfi_offline_evt_action:%d flag=%x. Already offline. <",
8324 		    fcfp->fcf_index,
8325 		    fcfp->flag);
8326 		break;
8327 
8328 	/* Wait states */
8329 	case FCFI_STATE_VFI_ONLINE:
8330 	case FCFI_STATE_VFI_OFFLINE:
8331 	case FCFI_STATE_REG:
8332 	case FCFI_STATE_ONLINE:
8333 	case FCFI_STATE_PAUSED:
8334 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8335 		fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8336 
8337 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8338 		    "fcfi_offline_evt_action:%d flag=%x.  Handling offline.",
8339 		    fcfp->fcf_index,
8340 		    fcfp->flag);
8341 
8342 		/* Handle offline now */
8343 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8344 		break;
8345 
8346 	/* Transitional states */
8347 	default:
8348 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8349 		fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8350 
8351 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8352 		    "fcfi_offline_evt_action:%d. "
8353 		    "Invalid state. <",
8354 		    fcfp->fcf_index);
8355 		break;
8356 	}
8357 
8358 	return (rval);
8359 
8360 } /* emlxs_fcfi_offline_evt_action() */
8361 
8362 
8363 /*ARGSUSED*/
8364 static uint32_t
emlxs_fcfi_pause_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8365 emlxs_fcfi_pause_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8366     void *arg1)
8367 {
8368 	uint32_t rval = 0;
8369 
8370 	if (evt != FCF_EVENT_FCFI_PAUSE) {
8371 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8372 		    "fcfi_pause_evt_action:%d %s:%s arg=%p. "
8373 		    "Invalid event type. <",
8374 		    fcfp->fcf_index,
8375 		    emlxs_fcfi_state_xlate(fcfp->state),
8376 		    emlxs_fcf_event_xlate(evt), arg1);
8377 		return (1);
8378 	}
8379 
8380 	if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) {
8381 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8382 		    "fcfi_pause_evt_action:%d. Pause already requested. <",
8383 		    fcfp->fcf_index);
8384 		return (1);
8385 	}
8386 
8387 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8388 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8389 		    "fcfi_pause_evt_action:%d. Offline already requested. <",
8390 		    fcfp->fcf_index);
8391 		return (1);
8392 	}
8393 
8394 	switch (fcfp->state) {
8395 	case FCFI_STATE_OFFLINE:
8396 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8397 		    "fcfi_pause_evt_action:%d flag=%x. Already offline. <",
8398 		    fcfp->fcf_index,
8399 		    fcfp->flag);
8400 		break;
8401 
8402 	case FCFI_STATE_PAUSED:
8403 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8404 		    "fcfi_pause_evt_action:%d flag=%x. Already paused. <",
8405 		    fcfp->fcf_index,
8406 		    fcfp->flag);
8407 		break;
8408 
8409 	/* Wait states */
8410 	case FCFI_STATE_VFI_ONLINE:
8411 	case FCFI_STATE_VFI_OFFLINE:
8412 	case FCFI_STATE_REG:
8413 	case FCFI_STATE_ONLINE:
8414 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8415 		fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
8416 
8417 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8418 		    "fcfi_pause_evt_action:%d flag=%x. Handle pause request.",
8419 		    fcfp->fcf_index,
8420 		    fcfp->flag);
8421 
8422 		/* Handle offline now */
8423 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8424 		break;
8425 
8426 	/* Transitional states */
8427 	default:
8428 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8429 		fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
8430 
8431 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8432 		    "fcfi_pause_evt_action:%d. "
8433 		    "Invalid state. <",
8434 		    fcfp->fcf_index);
8435 		break;
8436 	}
8437 
8438 	return (rval);
8439 
8440 } /* emlxs_fcfi_pause_evt_action() */
8441 
8442 
8443 /*ARGSUSED*/
8444 static uint32_t
emlxs_fcfi_unreg_failed_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8445 emlxs_fcfi_unreg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8446     uint32_t evt, void *arg1)
8447 {
8448 	uint32_t rval = 0;
8449 
8450 	fcfp->attempts++;
8451 
8452 	if (fcfp->state != FCFI_STATE_UNREG_FAILED) {
8453 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8454 		    "fcfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
8455 		    "Invalid state. <",
8456 		    fcfp->fcf_index,
8457 		    emlxs_fcfi_state_xlate(fcfp->state),
8458 		    emlxs_fcf_event_xlate(evt),
8459 		    arg1, fcfp->attempts);
8460 		return (1);
8461 	}
8462 
8463 	if ((fcfp->reason == FCF_REASON_SEND_FAILED) ||
8464 	    (fcfp->attempts >= 3)) {
8465 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8466 		    "fcfi_unreg_failed_action:%d attempt=%d reason=%x. "
8467 		    "Unreg cmpl.",
8468 		    fcfp->fcf_index,
8469 		    fcfp->attempts,
8470 		    fcfp->reason);
8471 
8472 		fcfp->flag &= ~EMLXS_FCFI_REG;
8473 
8474 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL,
8475 		    FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8476 	} else {
8477 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8478 		    "fcfi_unreg_failed_action:%d attempt=%d. Unregistering.",
8479 		    fcfp->fcf_index,
8480 		    arg1, fcfp->attempts);
8481 
8482 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
8483 		    FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8484 	}
8485 
8486 	return (rval);
8487 
8488 } /* emlxs_fcfi_unreg_failed_action() */
8489 
8490 
8491 /*ARGSUSED*/
8492 static uint32_t
emlxs_fcfi_reg_failed_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8493 emlxs_fcfi_reg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8494     void *arg1)
8495 {
8496 	uint32_t rval = 0;
8497 
8498 	fcfp->attempts++;
8499 
8500 	if (fcfp->state != FCFI_STATE_REG_FAILED) {
8501 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8502 		    "fcfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
8503 		    "Invalid state. <",
8504 		    fcfp->fcf_index,
8505 		    emlxs_fcfi_state_xlate(fcfp->state),
8506 		    emlxs_fcf_event_xlate(evt), arg1,
8507 		    fcfp->attempts);
8508 		return (1);
8509 	}
8510 
8511 	if ((fcfp->reason == FCF_REASON_SEND_FAILED) ||
8512 	    (fcfp->attempts >= 3)) {
8513 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8514 		    "fcfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.",
8515 		    fcfp->fcf_index,
8516 		    fcfp->attempts,
8517 		    fcfp->reason);
8518 
8519 		fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8520 		fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8521 
8522 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL,
8523 		    FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8524 	} else {
8525 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8526 		    "fcfi_reg_failed_action:%d attempt=%d. Registering.",
8527 		    fcfp->fcf_index,
8528 		    fcfp->attempts);
8529 
8530 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
8531 		    FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8532 	}
8533 
8534 	return (rval);
8535 
8536 } /* emlxs_fcfi_reg_failed_action() */
8537 
8538 
8539 /*ARGSUSED*/
8540 static uint32_t
emlxs_fcfi_reg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)8541 emlxs_fcfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
8542 {
8543 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
8544 	MAILBOX4 *mb4;
8545 	FCFIobj_t *fcfp;
8546 
8547 	fcfp = (FCFIobj_t *)mbq->context;
8548 	mb4 = (MAILBOX4 *)mbq;
8549 
8550 	mutex_enter(&EMLXS_FCF_LOCK);
8551 
8552 	if (fcfp->state != FCFI_STATE_REG) {
8553 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8554 		    "fcfi_reg_mbcmpl:%d state=%s.",
8555 		    fcfp->fcf_index,
8556 		    emlxs_fcfi_state_xlate(fcfp->state));
8557 
8558 		mutex_exit(&EMLXS_FCF_LOCK);
8559 		return (0);
8560 	}
8561 
8562 	if (mb4->mbxStatus) {
8563 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8564 		    "fcfi_reg_mbcmpl:%d failed. %s. >",
8565 		    fcfp->fcf_index,
8566 		    emlxs_mb_xlate_status(mb4->mbxStatus));
8567 
8568 		(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
8569 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
8570 
8571 		mutex_exit(&EMLXS_FCF_LOCK);
8572 		return (0);
8573 	}
8574 
8575 	fcfp->FCFI = mb4->un.varRegFCFI.FCFI;
8576 
8577 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8578 	    "fcfi_reg_mbcmpl:%d FCFI=%d. Reg complete. >",
8579 	    fcfp->fcf_index,
8580 	    fcfp->FCFI);
8581 
8582 	fcfp->flag |= EMLXS_FCFI_REG;
8583 
8584 	(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL,
8585 	    0, 0, 0);
8586 	mutex_exit(&EMLXS_FCF_LOCK);
8587 	return (0);
8588 
8589 } /* emlxs_fcfi_reg_mbcmpl() */
8590 
8591 
8592 /*ARGSUSED*/
8593 static uint32_t
emlxs_fcfi_reg_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8594 emlxs_fcfi_reg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8595     void *arg1)
8596 {
8597 	emlxs_hba_t *hba = HBA;
8598 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
8599 	MAILBOX4 *mb4;
8600 	MAILBOXQ *mbq;
8601 	uint32_t rval = 0;
8602 
8603 	if (fcfp->state != FCFI_STATE_REG) {
8604 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8605 		    "fcfi_reg_action:%d %s:%s arg=%p. "
8606 		    "Invalid state. <",
8607 		    fcfp->fcf_index,
8608 		    emlxs_fcfi_state_xlate(fcfp->state),
8609 		    emlxs_fcf_event_xlate(evt), arg1);
8610 		return (1);
8611 	}
8612 
8613 	if (!(fcfp->flag & EMLXS_FCFI_FCFTAB)) {
8614 		fcfp->flag |= EMLXS_FCFI_FCFTAB;
8615 		fcftab->fcfi_online++;
8616 	}
8617 
8618 	if (fcfp->prev_state != FCFI_STATE_REG_FAILED) {
8619 		fcfp->attempts = 0;
8620 	}
8621 
8622 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8623 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8624 		    "fcfi_reg_action:%d attempts=%d. Offline requested.",
8625 		    fcfp->fcf_index,
8626 		    fcfp->attempts);
8627 
8628 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8629 		return (rval);
8630 	}
8631 
8632 	if (fcfp->flag & EMLXS_FCFI_REG) {
8633 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8634 		    "fcfi_reg_action:%d. Already registered. "
8635 		    "Skipping REG_FCFI update.",
8636 		    fcfp->fcf_index);
8637 
8638 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
8639 		    FCF_REASON_EVENT, evt, arg1);
8640 		return (rval);
8641 	}
8642 
8643 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8644 	    "fcfi_reg_action:%d attempts=%d. Sending REG_FCFI. <",
8645 	    fcfp->fcf_index,
8646 	    fcfp->attempts);
8647 
8648 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
8649 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
8650 		    FCF_REASON_NO_MBOX, 0, arg1);
8651 
8652 		return (rval);
8653 	}
8654 	mb4 = (MAILBOX4*)mbq;
8655 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
8656 
8657 	mbq->mbox_cmpl = emlxs_fcfi_reg_mbcmpl;
8658 	mbq->context = (void *)fcfp;
8659 	mbq->port = (void *)port;
8660 
8661 	mb4->mbxCommand = MBX_REG_FCFI;
8662 	mb4->mbxOwner = OWN_HOST;
8663 	mb4->un.varRegFCFI.FCFI = 0; /* FCFI will be returned by firmware */
8664 	mb4->un.varRegFCFI.InfoIndex = fcfp->fcf_index;
8665 
8666 	mb4->un.varRegFCFI.RQId0 = hba->sli.sli4.rq[EMLXS_FCFI_RQ0_INDEX].qid;
8667 	mb4->un.varRegFCFI.Id0_rctl_mask = EMLXS_FCFI_RQ0_RMASK;
8668 	mb4->un.varRegFCFI.Id0_rctl = EMLXS_FCFI_RQ0_RCTL;
8669 	mb4->un.varRegFCFI.Id0_type_mask = EMLXS_FCFI_RQ0_TMASK;
8670 	mb4->un.varRegFCFI.Id0_type = EMLXS_FCFI_RQ0_TYPE;
8671 
8672 	mb4->un.varRegFCFI.RQId1 = 0xffff;
8673 	mb4->un.varRegFCFI.RQId2 = 0xffff;
8674 	mb4->un.varRegFCFI.RQId3 = 0xffff;
8675 
8676 	if (fcfp->flag & EMLXS_FCFI_VLAN_ID) {
8677 		mb4->un.varRegFCFI.vv = 1;
8678 		mb4->un.varRegFCFI.vlanTag = fcfp->vlan_id;
8679 	}
8680 
8681 	/* Ignore the fcf record and force FPMA */
8682 	mb4->un.varRegFCFI.mam = EMLXS_REG_FCFI_MAM_FPMA;
8683 
8684 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
8685 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
8686 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
8687 
8688 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
8689 		    FCF_REASON_SEND_FAILED, rval, arg1);
8690 
8691 		return (rval);
8692 	}
8693 
8694 	return (0);
8695 
8696 } /* emlxs_fcfi_reg_action() */
8697 
8698 
8699 /*ARGSUSED*/
8700 static uint32_t
emlxs_fcfi_reg_cmpl_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8701 emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8702     void *arg1)
8703 {
8704 	uint32_t rval = 0;
8705 
8706 	if (fcfp->state != FCFI_STATE_REG_CMPL) {
8707 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8708 		    "fcfi_reg_cmpl_action:%d %s:%s arg=%p. "
8709 		    "Invalid state. <",
8710 		    fcfp->fcf_index,
8711 		    emlxs_fcfi_state_xlate(fcfp->state),
8712 		    emlxs_fcf_event_xlate(evt), arg1);
8713 		return (1);
8714 	}
8715 
8716 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8717 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8718 		    "fcfi_reg_cmpl_action:%d. Offline requested.",
8719 		    fcfp->fcf_index);
8720 
8721 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8722 		return (rval);
8723 	}
8724 
8725 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8726 	    "fcfi_reg_cmpl_action:%d attempts=%d. Reg cmpl.",
8727 	    fcfp->fcf_index,
8728 	    fcfp->attempts);
8729 
8730 	rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
8731 	    FCF_REASON_EVENT, evt, arg1);
8732 
8733 	return (rval);
8734 
8735 } /* emlxs_fcfi_reg_cmpl_action() */
8736 
8737 
8738 /*ARGSUSED*/
8739 static uint32_t
emlxs_fcfi_unreg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)8740 emlxs_fcfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
8741 {
8742 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
8743 	MAILBOX4 *mb4;
8744 	FCFIobj_t *fcfp;
8745 
8746 	fcfp = (FCFIobj_t *)mbq->context;
8747 	mb4 = (MAILBOX4 *)mbq;
8748 
8749 	mutex_enter(&EMLXS_FCF_LOCK);
8750 
8751 	if (fcfp->state != FCFI_STATE_UNREG) {
8752 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8753 		    "fcfi_unreg_mbcmpl:%d state=%s.",
8754 		    fcfp->fcf_index,
8755 		    emlxs_fcfi_state_xlate(fcfp->state));
8756 
8757 		mutex_exit(&EMLXS_FCF_LOCK);
8758 		return (0);
8759 	}
8760 
8761 	if (mb4->mbxStatus) {
8762 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8763 		    "fcfi_unreg_mbcmpl:%d failed. %s. >",
8764 		    fcfp->fcf_index,
8765 		    emlxs_mb_xlate_status(mb4->mbxStatus));
8766 
8767 		(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
8768 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
8769 
8770 		mutex_exit(&EMLXS_FCF_LOCK);
8771 		return (0);
8772 	}
8773 
8774 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8775 	    "fcfi_unreg_mbcmpl:%d. Unreg complete. >",
8776 	    fcfp->fcf_index);
8777 
8778 	fcfp->flag &= ~EMLXS_FCFI_REG;
8779 	(void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL,
8780 	    0, 0, 0);
8781 
8782 	mutex_exit(&EMLXS_FCF_LOCK);
8783 	return (0);
8784 
8785 } /* emlxs_fcfi_unreg_mbcmpl() */
8786 
8787 
8788 /*ARGSUSED*/
8789 static uint32_t
emlxs_fcfi_unreg_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8790 emlxs_fcfi_unreg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8791     void *arg1)
8792 {
8793 	emlxs_hba_t *hba = HBA;
8794 	MAILBOX4 *mb4;
8795 	MAILBOXQ *mbq;
8796 	uint32_t rval = 0;
8797 
8798 	if (fcfp->state != FCFI_STATE_UNREG) {
8799 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8800 		    "fcfi_unreg_action:%d %s:%s arg=%p. "
8801 		    "Invalid state. <",
8802 		    fcfp->fcf_index,
8803 		    emlxs_fcfi_state_xlate(fcfp->state),
8804 		    emlxs_fcf_event_xlate(evt), arg1);
8805 		return (1);
8806 	}
8807 
8808 	if (!(fcfp->flag & EMLXS_FCFI_REG)) {
8809 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8810 		    "fcfi_unreg_action:%d. Not registered. "
8811 		    "Skipping UNREG_FCFI.",
8812 		    fcfp->fcf_index);
8813 
8814 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
8815 		    FCF_REASON_EVENT, evt, arg1);
8816 		return (rval);
8817 	}
8818 
8819 	if (fcfp->prev_state != FCFI_STATE_UNREG_FAILED) {
8820 		fcfp->attempts = 0;
8821 	}
8822 
8823 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8824 	    "fcfi_unreg_action:%d attempts=%d. Sending UNREG_FCFI. <",
8825 	    fcfp->fcf_index,
8826 	    fcfp->attempts);
8827 
8828 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
8829 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
8830 		    FCF_REASON_NO_MBOX, 0, arg1);
8831 		return (rval);
8832 	}
8833 	mb4 = (MAILBOX4*)mbq;
8834 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
8835 
8836 	mbq->mbox_cmpl = emlxs_fcfi_unreg_mbcmpl;
8837 	mbq->context = (void *)fcfp;
8838 	mbq->port = (void *)port;
8839 
8840 	mb4->mbxCommand = MBX_UNREG_FCFI;
8841 	mb4->mbxOwner = OWN_HOST;
8842 	mb4->un.varUnRegFCFI.FCFI = fcfp->FCFI;
8843 
8844 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
8845 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
8846 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
8847 
8848 		rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
8849 		    FCF_REASON_SEND_FAILED, rval, arg1);
8850 
8851 		return (rval);
8852 	}
8853 
8854 	return (0);
8855 
8856 } /* emlxs_fcfi_unreg_action() */
8857 
8858 
8859 /*ARGSUSED*/
8860 static uint32_t
emlxs_fcfi_unreg_cmpl_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8861 emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8862     void *arg1)
8863 {
8864 	uint32_t rval = 0;
8865 
8866 	if (fcfp->state != FCFI_STATE_UNREG_CMPL) {
8867 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8868 		    "fcfi_unreg_cmpl_action:%d %s:%s arg=%p. "
8869 		    "Invalid state. <",
8870 		    fcfp->fcf_index,
8871 		    emlxs_fcfi_state_xlate(fcfp->state),
8872 		    emlxs_fcf_event_xlate(evt), arg1);
8873 		return (1);
8874 	}
8875 
8876 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8877 	    "fcfi_unreg_cmpl_action:%d attempts=%d. Going offline.",
8878 	    fcfp->fcf_index,
8879 	    emlxs_fcfi_state_xlate(fcfp->state),
8880 	    emlxs_fcf_event_xlate(evt), arg1,
8881 	    fcfp->attempts);
8882 
8883 	rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
8884 	    FCF_REASON_EVENT, evt, arg1);
8885 
8886 	return (rval);
8887 
8888 } /* emlxs_fcfi_unreg_cmpl_action() */
8889 
8890 
8891 /*ARGSUSED*/
8892 static uint32_t
emlxs_fcfi_online_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8893 emlxs_fcfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8894     void *arg1)
8895 {
8896 	emlxs_hba_t *hba = HBA;
8897 	uint32_t rval = 0;
8898 	VFIobj_t *vfip;
8899 	uint32_t i;
8900 
8901 	if (fcfp->state != FCFI_STATE_ONLINE) {
8902 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8903 		    "fcfi_online_action:%d %s:%s arg=%p. "
8904 		    "Invalid state. <",
8905 		    fcfp->fcf_index,
8906 		    emlxs_fcfi_state_xlate(fcfp->state),
8907 		    emlxs_fcf_event_xlate(evt), arg1);
8908 		return (1);
8909 	}
8910 
8911 	fcfp->flag &= ~EMLXS_FCFI_ONLINE_REQ;
8912 
8913 	if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8914 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8915 		    "fcfi_online_action:%d attempts=%d. Offline requested.",
8916 		    fcfp->fcf_index,
8917 		    fcfp->attempts);
8918 
8919 		rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8920 		return (rval);
8921 	}
8922 
8923 	/* Online remaining VFI's for this FCFI */
8924 	vfip = hba->sli.sli4.VFI_table;
8925 	for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
8926 		if (vfip->fcfp != fcfp) {
8927 			continue;
8928 		}
8929 
8930 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8931 		    "fcfi_online_action:%d vfi_online=%d. Onlining VFI:%d. >",
8932 		    fcfp->fcf_index,
8933 		    fcfp->vfi_online,
8934 		    vfip->VFI);
8935 
8936 		(void) emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
8937 	}
8938 
8939 	if (fcfp->prev_state != FCFI_STATE_ONLINE) {
8940 		/* Perform VSAN discovery check when first VFI goes online */
8941 		if (fcfp->vfi_online < FCFI_MAX_VFI_COUNT) {
8942 
8943 			/* Perform VSAN Discovery (TBD) */
8944 			/* For now we only need 1 VFI */
8945 
8946 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8947 			    "fcfi_online_action:%d vfi_online=%d. "
8948 			    "VSAN discovery required.",
8949 			    fcfp->fcf_index,
8950 			    fcfp->vfi_online);
8951 		}
8952 	}
8953 
8954 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8955 	    "fcfi_online_action:%d vfi_online=%d. "
8956 	    "FCFI online. Notifying fcftab. >",
8957 	    fcfp->fcf_index,
8958 	    fcfp->vfi_online);
8959 
8960 	/* Notify FCFTAB */
8961 	rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_ONLINE, fcfp);
8962 
8963 	return (rval);
8964 
8965 } /* emlxs_fcfi_online_action() */
8966 
8967 
8968 /*ARGSUSED*/
8969 static int
emlxs_fcf_configured(emlxs_port_t * port,FCFIobj_t * fcfp)8970 emlxs_fcf_configured(emlxs_port_t *port,  FCFIobj_t *fcfp)
8971 {
8972 	emlxs_hba_t *hba = HBA;
8973 	int i;
8974 	uint32_t entry_count;
8975 	uint32_t valid_entry;
8976 	uint32_t match_found;
8977 	uint16_t VLanId;
8978 	FCF_RECORD_t *fcfrec = &fcfp->fcf_rec;
8979 	uint32_t j;
8980 	uint32_t k;
8981 
8982 	/* Init the primary flag, we may set it later */
8983 	fcfp->flag &= ~(EMLXS_FCFI_PRIMARY|EMLXS_FCFI_BOOT);
8984 
8985 	if (!(hba->flag & FC_FIP_SUPPORTED)) {
8986 		if (!hba->sli.sli4.cfgFCOE.length) {
8987 			/* Nothing specified, so everything matches */
8988 			/* For nonFIP only use index 0 */
8989 			if (fcfrec->fcf_index == 0) {
8990 				return (1);  /* success */
8991 			}
8992 			return (0);
8993 		}
8994 
8995 		/* Just check FCMap for now */
8996 		if (bcmp((char *)fcfrec->fc_map,
8997 		    hba->sli.sli4.cfgFCOE.FCMap, 3) == 0) {
8998 			return (1);  /* success */
8999 		}
9000 		return (0);
9001 	}
9002 
9003 	/* For FIP mode, the FCF record must match Config Region 23 */
9004 
9005 	entry_count = (hba->sli.sli4.cfgFCF.length * sizeof (uint32_t)) /
9006 	    sizeof (tlv_fcfconnectentry_t);
9007 	valid_entry = 0;
9008 	match_found = 0;
9009 
9010 	for (i = 0; i < entry_count; i++) {
9011 
9012 		if (!hba->sli.sli4.cfgFCF.entry[i].Valid) {
9013 			continue;
9014 		}
9015 
9016 		if (hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) {
9017 			valid_entry = 1;
9018 
9019 			if (bcmp((char *)fcfrec->fabric_name_identifier,
9020 			    hba->sli.sli4.cfgFCF.entry[i].FabricName, 8)) {
9021 				match_found = 0;
9022 				continue;
9023 			}
9024 
9025 			match_found = 1;
9026 		}
9027 
9028 		if (hba->sli.sli4.cfgFCF.entry[i].SwitchNameValid) {
9029 			valid_entry = 1;
9030 
9031 			if (bcmp((char *)fcfrec->switch_name_identifier,
9032 			    hba->sli.sli4.cfgFCF.entry[i].SwitchName, 8)) {
9033 				match_found = 0;
9034 				continue;
9035 			}
9036 
9037 			match_found = 1;
9038 		}
9039 
9040 		if (hba->sli.sli4.cfgFCF.entry[i].VLanValid) {
9041 			valid_entry = 1;
9042 
9043 			if (!(fcfp->flag & EMLXS_FCFI_VLAN_ID)) {
9044 				match_found = 0;
9045 				continue;
9046 			}
9047 
9048 			VLanId = hba->sli.sli4.cfgFCF.entry[i].VLanId;
9049 			j = VLanId / 8;
9050 			k = 1 << (VLanId % 8);
9051 
9052 			if (!(fcfrec->vlan_bitmap[j] & k)) {
9053 				match_found = 0;
9054 				continue;
9055 			}
9056 
9057 			/* Assign requested vlan_id to this FCF */
9058 			fcfp->vlan_id = VLanId;
9059 
9060 			match_found = 1;
9061 		}
9062 
9063 		/* If a match was found */
9064 		if (match_found) {
9065 			if (hba->sli.sli4.cfgFCF.entry[i].Primary) {
9066 				fcfp->flag |= EMLXS_FCFI_PRIMARY;
9067 			}
9068 			if (hba->sli.sli4.cfgFCF.entry[i].Boot) {
9069 				fcfp->flag |= EMLXS_FCFI_BOOT;
9070 			}
9071 			return (1);
9072 		}
9073 	}
9074 
9075 	/* If no valid entries found, then allow any fabric */
9076 	if (!valid_entry) {
9077 		return (1);
9078 	}
9079 
9080 	return (0);
9081 
9082 } /* emlxs_fcf_configured() */
9083 
9084 
9085 static void
emlxs_fcfi_update(emlxs_port_t * port,FCFIobj_t * fcfp,FCF_RECORD_t * fcf_rec,uint32_t event_tag)9086 emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp, FCF_RECORD_t *fcf_rec,
9087     uint32_t event_tag)
9088 {
9089 	emlxs_hba_t	*hba = HBA;
9090 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
9091 	uint16_t	i;
9092 
9093 	bcopy((char *)fcf_rec, &fcfp->fcf_rec, sizeof (FCF_RECORD_t));
9094 	fcfp->fcf_index = fcf_rec->fcf_index;
9095 
9096 	/* Clear VLAN info */
9097 	fcfp->vlan_id = 0;
9098 	fcfp->flag &= ~EMLXS_FCFI_VLAN_ID;
9099 
9100 	/* Check if fcf is a member of a VLAN */
9101 	for (i = 0; i < 4096; i++) {
9102 		if (fcf_rec->vlan_bitmap[i / 8] & (1 << (i % 8))) {
9103 			/* For now assign the VLAN id of the first VLAN found */
9104 			fcfp->vlan_id = i;
9105 			fcfp->flag |= EMLXS_FCFI_VLAN_ID;
9106 			break;
9107 		}
9108 	}
9109 
9110 	if (fcf_rec->fcf_available) {
9111 		fcfp->flag |= EMLXS_FCFI_AVAILABLE;
9112 	} else {
9113 		fcfp->flag &= ~EMLXS_FCFI_AVAILABLE;
9114 	}
9115 
9116 	if (fcf_rec->fcf_valid && !fcf_rec->fcf_sol) {
9117 		fcfp->flag |= EMLXS_FCFI_VALID;
9118 	} else {
9119 		fcfp->flag &= ~EMLXS_FCFI_VALID;
9120 	}
9121 
9122 	/* Check config region 23 */
9123 	/* Also sets BOOT and PRIMARY cfg bits as needed */
9124 	if (emlxs_fcf_configured(port, fcfp)) {
9125 		fcfp->flag |= EMLXS_FCFI_CONFIGURED;
9126 	} else {
9127 		fcfp->flag &= ~EMLXS_FCFI_CONFIGURED;
9128 	}
9129 
9130 	/* Set fcfp priority.  Used by selection alogithm */
9131 	/* Combination of BOOT:PRIMARY:~fip_priority */
9132 	fcfp->priority  = (fcfp->flag & EMLXS_FCFI_BOOT)? 0x200:0;
9133 	fcfp->priority |= (fcfp->flag & EMLXS_FCFI_PRIMARY)? 0x100:0;
9134 	fcfp->priority |= ~(fcf_rec->fip_priority & 0xff);
9135 
9136 	fcfp->event_tag  = event_tag;
9137 	fcfp->generation = fcftab->generation;
9138 	fcfp->flag |= EMLXS_FCFI_FRESH;
9139 
9140 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9141 	    "fcfi:%d gen=%x iotag=%d flag=%x sol=%x avl=%x val=%x state=%x "
9142 	    "map=%x pri=%x vid=%x",
9143 	    fcf_rec->fcf_index,
9144 	    fcfp->generation,
9145 	    fcfp->event_tag,
9146 	    fcfp->flag,
9147 	    fcf_rec->fcf_sol,
9148 	    fcf_rec->fcf_available,
9149 	    fcf_rec->fcf_valid,
9150 	    fcf_rec->fcf_state,
9151 	    fcf_rec->mac_address_provider,
9152 	    fcfp->priority,
9153 	    fcfp->vlan_id);
9154 
9155 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9156 	    "fcfi:%d mac=%02x:%02x:%02x:%02x:%02x:%02x "
9157 	    "fabric=%02x%02x%02x%02x%02x%02x%02x%02x "
9158 	    "switch=%02x%02x%02x%02x%02x%02x%02x%02x",
9159 	    fcfp->fcf_index,
9160 	    fcf_rec->fcf_mac_address_hi[0],
9161 	    fcf_rec->fcf_mac_address_hi[1],
9162 	    fcf_rec->fcf_mac_address_hi[2],
9163 	    fcf_rec->fcf_mac_address_hi[3],
9164 	    fcf_rec->fcf_mac_address_low[0],
9165 	    fcf_rec->fcf_mac_address_low[1],
9166 
9167 	    fcf_rec->fabric_name_identifier[0],
9168 	    fcf_rec->fabric_name_identifier[1],
9169 	    fcf_rec->fabric_name_identifier[2],
9170 	    fcf_rec->fabric_name_identifier[3],
9171 	    fcf_rec->fabric_name_identifier[4],
9172 	    fcf_rec->fabric_name_identifier[5],
9173 	    fcf_rec->fabric_name_identifier[6],
9174 	    fcf_rec->fabric_name_identifier[7],
9175 
9176 	    fcf_rec->switch_name_identifier[0],
9177 	    fcf_rec->switch_name_identifier[1],
9178 	    fcf_rec->switch_name_identifier[2],
9179 	    fcf_rec->switch_name_identifier[3],
9180 	    fcf_rec->switch_name_identifier[4],
9181 	    fcf_rec->switch_name_identifier[5],
9182 	    fcf_rec->switch_name_identifier[6],
9183 	    fcf_rec->switch_name_identifier[7]);
9184 
9185 	return;
9186 
9187 } /* emlxs_fcfi_update() */
9188 
9189 
9190 /* ************************************************************************** */
9191 /* VFI */
9192 /* ************************************************************************** */
9193 
9194 static char *
emlxs_vfi_state_xlate(uint32_t state)9195 emlxs_vfi_state_xlate(uint32_t state)
9196 {
9197 	static char buffer[32];
9198 	uint32_t i;
9199 	uint32_t count;
9200 
9201 	count = sizeof (emlxs_vfi_state_table) / sizeof (emlxs_table_t);
9202 	for (i = 0; i < count; i++) {
9203 		if (state == emlxs_vfi_state_table[i].code) {
9204 			return (emlxs_vfi_state_table[i].string);
9205 		}
9206 	}
9207 
9208 	(void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
9209 	return (buffer);
9210 
9211 } /* emlxs_vfi_state_xlate() */
9212 
9213 
9214 static uint32_t
emlxs_vfi_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9215 emlxs_vfi_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9216     void *arg1)
9217 {
9218 	uint32_t rval = 0;
9219 	uint32_t(*func) (emlxs_port_t *, VFIobj_t *, uint32_t, void *);
9220 	uint32_t index;
9221 	uint32_t events;
9222 	uint16_t state;
9223 
9224 	/* Convert event to action table index */
9225 	switch (evt) {
9226 	case FCF_EVENT_STATE_ENTER:
9227 		index = 0;
9228 		break;
9229 	case FCF_EVENT_VFI_ONLINE:
9230 		index = 1;
9231 		break;
9232 	case FCF_EVENT_VFI_OFFLINE:
9233 		index = 2;
9234 		break;
9235 	case FCF_EVENT_VFI_PAUSE:
9236 		index = 3;
9237 		break;
9238 	case FCF_EVENT_VPI_ONLINE:
9239 		index = 4;
9240 		break;
9241 	case FCF_EVENT_VPI_OFFLINE:
9242 		index = 5;
9243 		break;
9244 	default:
9245 		return (1);
9246 	}
9247 
9248 	events = VFI_ACTION_EVENTS;
9249 	state  = vfip->state;
9250 
9251 	index += (state * events);
9252 	func   = (uint32_t(*) (emlxs_port_t *, VFIobj_t *, uint32_t, void *))
9253 	    emlxs_vfi_action_table[index];
9254 
9255 	if (!func) {
9256 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9257 		    "vfi_action:%d %s:%s arg=%p. No action. <",
9258 		    vfip->VFI,
9259 		    emlxs_vfi_state_xlate(state),
9260 		    emlxs_fcf_event_xlate(evt), arg1);
9261 
9262 		return (1);
9263 	}
9264 
9265 	rval = (func)(port, vfip, evt, arg1);
9266 
9267 	return (rval);
9268 
9269 } /* emlxs_vfi_action() */
9270 
9271 
9272 static uint32_t
emlxs_vfi_event(emlxs_port_t * port,uint32_t evt,void * arg1)9273 emlxs_vfi_event(emlxs_port_t *port, uint32_t evt,
9274     void *arg1)
9275 {
9276 	VPIobj_t *vpip = NULL;
9277 	VFIobj_t *vfip = NULL;
9278 	uint32_t rval = 0;
9279 
9280 	/* Filter events and acquire fcfi context */
9281 	switch (evt) {
9282 	case FCF_EVENT_VPI_ONLINE:
9283 	case FCF_EVENT_VPI_OFFLINE:
9284 		vpip = (VPIobj_t *)arg1;
9285 
9286 		if (!vpip) {
9287 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9288 			    "vfi_event: %s arg=%p. Null VPI found. <",
9289 			    emlxs_fcf_event_xlate(evt), arg1);
9290 
9291 			return (1);
9292 		}
9293 
9294 		vfip = vpip->vfip;
9295 
9296 		if (!vfip) {
9297 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9298 			    "vfi_event: %s arg=%p. VFI not found. <",
9299 			    emlxs_fcf_event_xlate(evt), arg1);
9300 
9301 			return (1);
9302 		}
9303 		break;
9304 
9305 	case FCF_EVENT_VFI_ONLINE:
9306 	case FCF_EVENT_VFI_OFFLINE:
9307 	case FCF_EVENT_VFI_PAUSE:
9308 		vfip = (VFIobj_t *)arg1;
9309 
9310 		if (!vfip) {
9311 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9312 			    "vfi_event: %s arg=%p. VFI not found. <",
9313 			    emlxs_fcf_event_xlate(evt), arg1);
9314 
9315 			return (1);
9316 		}
9317 		break;
9318 
9319 	default:
9320 		return (1);
9321 	}
9322 
9323 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9324 	    "vfi_event:%d %s:%s arg=%p",
9325 	    vfip->VFI,
9326 	    emlxs_vfi_state_xlate(vfip->state),
9327 	    emlxs_fcf_event_xlate(evt), arg1);
9328 
9329 	rval = emlxs_vfi_action(port, vfip, evt, arg1);
9330 
9331 	return (rval);
9332 
9333 } /* emlxs_vfi_event() */
9334 
9335 
9336 /*ARGSUSED*/
9337 static uint32_t
emlxs_vfi_state(emlxs_port_t * port,VFIobj_t * vfip,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)9338 emlxs_vfi_state(emlxs_port_t *port, VFIobj_t *vfip, uint16_t state,
9339     uint16_t reason, uint32_t explain, void *arg1)
9340 {
9341 	uint32_t rval = 0;
9342 
9343 	if (state >= VFI_ACTION_STATES) {
9344 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9345 		    "vfi_state:%d %s. "
9346 		    "Invalid state. <",
9347 		    vfip->VFI,
9348 		    emlxs_vfi_state_xlate(vfip->state));
9349 		return (1);
9350 	}
9351 
9352 	if ((vfip->state == state) &&
9353 	    (reason != FCF_REASON_REENTER)) {
9354 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9355 		    "vfi_state:%d %s:%s:0x%x arg=%p. "
9356 		    "State not changed. <",
9357 		    vfip->VFI,
9358 		    emlxs_vfi_state_xlate(vfip->state),
9359 		    emlxs_fcf_reason_xlate(reason),
9360 		    explain, arg1);
9361 
9362 		return (1);
9363 	}
9364 
9365 	if (!reason) {
9366 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
9367 		    "vfi_state:%d %s-->%s arg=%p",
9368 		    vfip->VFI,
9369 		    emlxs_vfi_state_xlate(vfip->state),
9370 		    emlxs_vfi_state_xlate(state), arg1);
9371 	} else if (reason == FCF_REASON_EVENT) {
9372 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
9373 		    "vfi_state:%d %s-->%s:%s:%s arg=%p",
9374 		    vfip->VFI,
9375 		    emlxs_vfi_state_xlate(vfip->state),
9376 		    emlxs_vfi_state_xlate(state),
9377 		    emlxs_fcf_reason_xlate(reason),
9378 		    emlxs_fcf_event_xlate(explain), arg1);
9379 	} else if (explain) {
9380 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
9381 		    "vfi_state:%d %s-->%s:%s:0x%x arg=%p",
9382 		    vfip->VFI,
9383 		    emlxs_vfi_state_xlate(vfip->state),
9384 		    emlxs_vfi_state_xlate(state),
9385 		    emlxs_fcf_reason_xlate(reason),
9386 		    explain, arg1);
9387 	} else {
9388 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
9389 		    "vfi_state:%d %s-->%s:%s arg=%p",
9390 		    vfip->VFI,
9391 		    emlxs_vfi_state_xlate(vfip->state),
9392 		    emlxs_vfi_state_xlate(state),
9393 		    emlxs_fcf_reason_xlate(reason), arg1);
9394 	}
9395 
9396 	vfip->prev_state = vfip->state;
9397 	vfip->prev_reason = vfip->reason;
9398 	vfip->state = state;
9399 	vfip->reason = reason;
9400 
9401 	rval = emlxs_vfi_action(port, vfip, FCF_EVENT_STATE_ENTER, arg1);
9402 
9403 	return (rval);
9404 
9405 } /* emlxs_vfi_state() */
9406 
9407 
9408 /*ARGSUSED*/
9409 static uint32_t
emlxs_vfi_vpi_online_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9410 emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip,
9411     uint32_t evt, void *arg1)
9412 {
9413 	uint32_t rval = 0;
9414 
9415 	if (evt != FCF_EVENT_VPI_ONLINE) {
9416 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9417 		    "vfi_vpi_online_evt_action:%d %s:%s arg=%p flag=%x. "
9418 		    "Invalid event type. <",
9419 		    vfip->VFI,
9420 		    emlxs_vfi_state_xlate(vfip->state),
9421 		    emlxs_fcf_event_xlate(evt), arg1,
9422 		    vfip->flag);
9423 		return (1);
9424 	}
9425 
9426 	switch (vfip->state) {
9427 	case VFI_STATE_ONLINE:
9428 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9429 		    "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. "
9430 		    "Reentering online.",
9431 		    vfip->VFI,
9432 		    vfip->flag,
9433 		    vfip->vpi_online);
9434 
9435 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
9436 		    FCF_REASON_REENTER, evt, arg1);
9437 		break;
9438 
9439 	case VFI_STATE_VPI_ONLINE:
9440 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9441 		    "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. "
9442 		    "Online cmpl.",
9443 		    vfip->VFI,
9444 		    vfip->flag,
9445 		    vfip->vpi_online);
9446 
9447 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE_CMPL,
9448 		    FCF_REASON_EVENT, evt, arg1);
9449 		break;
9450 
9451 	default:
9452 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9453 		    "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. <",
9454 		    vfip->VFI,
9455 		    vfip->flag,
9456 		    vfip->vpi_online);
9457 
9458 		return (1);
9459 	}
9460 
9461 	return (rval);
9462 
9463 } /* emlxs_vfi_vpi_online_evt_action() */
9464 
9465 
9466 /*ARGSUSED*/
9467 static uint32_t
emlxs_vfi_offline_handler(emlxs_port_t * port,VFIobj_t * vfip,void * arg1)9468 emlxs_vfi_offline_handler(emlxs_port_t *port, VFIobj_t *vfip, void *arg1)
9469 {
9470 	uint32_t rval = 0;
9471 
9472 	if (!(vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
9473 		return (0);
9474 	}
9475 
9476 	if (vfip->vpi_online) {
9477 		if (vfip->flag & EMLXS_VFI_PAUSE_REQ) {
9478 			rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED,
9479 			    FCF_REASON_REQUESTED, 0, arg1);
9480 		} else {
9481 			rval = emlxs_vfi_state(port, vfip,
9482 			    VFI_STATE_VPI_OFFLINE, FCF_REASON_REQUESTED,
9483 			    0, arg1);
9484 		}
9485 
9486 	} else if (vfip->flag & EMLXS_VFI_REG) {
9487 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
9488 		    FCF_REASON_REQUESTED, 0, arg1);
9489 
9490 	} else if (vfip->flag & EMLXS_VFI_INIT) {
9491 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
9492 		    FCF_REASON_REQUESTED, 0, arg1);
9493 
9494 	} else {
9495 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
9496 		    FCF_REASON_REQUESTED, 0, arg1);
9497 	}
9498 
9499 	return (rval);
9500 
9501 } /* emlxs_vfi_offline_handler() */
9502 
9503 
9504 /*ARGSUSED*/
9505 static uint32_t
emlxs_vfi_vpi_offline_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9506 emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip,
9507     uint32_t evt, void *arg1)
9508 {
9509 	uint32_t rval = 0;
9510 	VPIobj_t *vpip;
9511 
9512 	if (evt != FCF_EVENT_VPI_OFFLINE) {
9513 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9514 		    "vfi_vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
9515 		    "Invalid event type. <",
9516 		    vfip->VFI,
9517 		    emlxs_vfi_state_xlate(vfip->state),
9518 		    emlxs_fcf_event_xlate(evt), arg1,
9519 		    vfip->flag);
9520 		return (1);
9521 	}
9522 
9523 	/* Disconnect VPI object from VFI */
9524 	vpip = (VPIobj_t *)arg1;
9525 	vpip->vfip = NULL;
9526 
9527 	switch (vfip->state) {
9528 	case VFI_STATE_ONLINE:
9529 	case VFI_STATE_VPI_ONLINE:
9530 		if (vfip->vpi_online == 0) {
9531 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9532 			    "vfi_vpi_offline_evt_action:%d flag=%x "
9533 			    "vpi_online=%d. Offlining.",
9534 			    vfip->VFI,
9535 			    vfip->flag, vfip->vpi_online);
9536 
9537 			vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9538 			vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
9539 			rval = emlxs_vfi_offline_handler(port, vfip, arg1);
9540 		} else {
9541 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9542 			    "vfi_vpi_offline_evt_action:%d flag=%x "
9543 			    "vpi_online=%d. <",
9544 			    vfip->VFI,
9545 			    vfip->flag, vfip->vpi_online);
9546 		}
9547 		break;
9548 
9549 	case VFI_STATE_PAUSED:
9550 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9551 		    "vfi_vpi_offline_evt_action:%d flag=%x vpi_online=%d. <",
9552 		    vfip->VFI,
9553 		    vfip->flag, vfip->vpi_online);
9554 		break;
9555 
9556 	case VFI_STATE_VPI_OFFLINE:
9557 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9558 		    "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.",
9559 		    vfip->VFI,
9560 		    vfip->flag);
9561 
9562 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL,
9563 		    FCF_REASON_EVENT, evt, arg1);
9564 		break;
9565 
9566 	case VFI_STATE_VPI_OFFLINE_CMPL:
9567 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9568 		    "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.",
9569 		    vfip->VFI,
9570 		    vfip->flag);
9571 
9572 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL,
9573 		    FCF_REASON_REENTER, evt, arg1);
9574 		break;
9575 
9576 	default:
9577 		if (vfip->vpi_online == 0) {
9578 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9579 			    "vfi_vpi_offline_evt_action:%d flag=%x "
9580 			    "vpi_online=%d. Requesting offline. <",
9581 			    vfip->VFI,
9582 			    vfip->flag, vfip->vpi_online);
9583 
9584 			vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9585 			vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
9586 		} else {
9587 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9588 			    "vfi_vpi_offline_evt_action:%d flag=%x "
9589 			    "vpi_online=%d. <",
9590 			    vfip->VFI,
9591 			    vfip->flag, vfip->vpi_online);
9592 		}
9593 		return (1);
9594 	}
9595 
9596 	return (rval);
9597 
9598 } /* emlxs_vfi_vpi_offline_evt_action() */
9599 
9600 
9601 /*ARGSUSED*/
9602 static uint32_t
emlxs_vfi_online_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9603 emlxs_vfi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9604     void *arg1)
9605 {
9606 	emlxs_hba_t *hba = HBA;
9607 	emlxs_port_t *vport;
9608 	VPIobj_t *vpip;
9609 	uint32_t rval = 0;
9610 	uint32_t i;
9611 
9612 	if (evt != FCF_EVENT_VFI_ONLINE) {
9613 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9614 		    "vfi_online_evt_action:%d %s:%s arg=%p flag=%x. "
9615 		    "Invalid event type. <",
9616 		    vfip->VFI,
9617 		    emlxs_vfi_state_xlate(vfip->state),
9618 		    emlxs_fcf_event_xlate(evt), arg1,
9619 		    vfip->flag);
9620 		return (1);
9621 	}
9622 
9623 	if (vfip->flag & EMLXS_VFI_ONLINE_REQ) {
9624 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9625 		    "vfi_online_evt_action:%d flag=%x. "
9626 		    "Online already requested. <",
9627 		    vfip->VFI,
9628 		    vfip->flag);
9629 		return (0);
9630 	}
9631 
9632 	vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9633 
9634 	switch (vfip->state) {
9635 	case VFI_STATE_OFFLINE:
9636 		vfip->flag |= EMLXS_VFI_ONLINE_REQ;
9637 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9638 		    "vfi_online_evt_action:%d flag=%x. Initiating online.",
9639 		    vfip->VFI,
9640 		    vfip->flag);
9641 
9642 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
9643 		    FCF_REASON_EVENT, evt, arg1);
9644 		break;
9645 
9646 	case VFI_STATE_VPI_OFFLINE:
9647 	case VFI_STATE_PAUSED:
9648 		vfip->flag |= EMLXS_VFI_ONLINE_REQ;
9649 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9650 		    "vfi_online_evt_action:%d flag=%x. Initiating online.",
9651 		    vfip->VFI,
9652 		    vfip->flag);
9653 
9654 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
9655 		    FCF_REASON_EVENT, evt, arg1);
9656 		break;
9657 
9658 	case VFI_STATE_ONLINE:
9659 		/* Online all VPI's belonging to this vfi */
9660 		for (i = 0; i <= hba->vpi_max; i++) {
9661 			vport = &VPORT(i);
9662 			vpip = vport->vpip;
9663 
9664 			if (!(vport->flag & EMLXS_PORT_BOUND) ||
9665 			    (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
9666 				continue;
9667 			}
9668 
9669 			if (vpip->vfip != vfip) {
9670 				continue;
9671 			}
9672 
9673 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9674 			    "vfi_online_evt_action:%d. Onlining VPI:%d >",
9675 			    vfip->VFI,
9676 			    vpip->VPI);
9677 
9678 			(void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE,
9679 			    vpip);
9680 		}
9681 		break;
9682 
9683 	default:
9684 		vfip->flag |= EMLXS_VFI_ONLINE_REQ;
9685 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9686 		    "vfi_online_evt_action:%d flag=%x. <",
9687 		    vfip->VFI,
9688 		    vfip->flag);
9689 		return (1);
9690 	}
9691 
9692 	return (rval);
9693 
9694 } /* emlxs_vfi_online_evt_action() */
9695 
9696 
9697 /*ARGSUSED*/
9698 static uint32_t
emlxs_vfi_offline_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9699 emlxs_vfi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9700     void *arg1)
9701 {
9702 	uint32_t rval = 0;
9703 
9704 	if (evt != FCF_EVENT_VFI_OFFLINE) {
9705 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9706 		    "vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
9707 		    "Invalid event type. <",
9708 		    vfip->VFI,
9709 		    emlxs_vfi_state_xlate(vfip->state),
9710 		    emlxs_fcf_event_xlate(evt), arg1,
9711 		    vfip->flag);
9712 		return (1);
9713 	}
9714 
9715 	if ((vfip->flag & EMLXS_VFI_OFFLINE_REQ) &&
9716 	    !(vfip->flag & EMLXS_VFI_PAUSE_REQ)) {
9717 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9718 		    "vfi_offline_evt_action:%d flag=%x. "
9719 		    "Offline already requested. <",
9720 		    vfip->VFI,
9721 		    vfip->flag);
9722 		return (0);
9723 	}
9724 
9725 	switch (vfip->state) {
9726 	case VFI_STATE_OFFLINE:
9727 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9728 		    "vfi_offline_evt_action:%d flag=%x. "
9729 		    "Already offline. <",
9730 		    vfip->VFI,
9731 		    vfip->flag);
9732 		break;
9733 
9734 	/* Wait states */
9735 	case VFI_STATE_VPI_ONLINE:
9736 	case VFI_STATE_VPI_OFFLINE:
9737 	case VFI_STATE_VPI_OFFLINE_CMPL:
9738 	case VFI_STATE_INIT:
9739 	case VFI_STATE_REG:
9740 	case VFI_STATE_ONLINE:
9741 	case VFI_STATE_PAUSED:
9742 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9743 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
9744 
9745 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9746 		    "vfi_offline_evt_action:%d flag=%x.  Handling offline.",
9747 		    vfip->VFI,
9748 		    vfip->flag);
9749 
9750 		/* Handle offline now */
9751 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
9752 		break;
9753 
9754 	default:
9755 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9756 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
9757 
9758 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9759 		    "vfi_offline_evt_action:%d flag=%x. <",
9760 		    vfip->VFI,
9761 		    vfip->flag);
9762 		break;
9763 	}
9764 
9765 	return (rval);
9766 
9767 } /* emlxs_vfi_offline_evt_action() */
9768 
9769 
9770 /*ARGSUSED*/
9771 static uint32_t
emlxs_vfi_pause_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9772 emlxs_vfi_pause_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9773     void *arg1)
9774 {
9775 	uint32_t rval = 0;
9776 
9777 	if (evt != FCF_EVENT_VFI_PAUSE) {
9778 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9779 		    "vfi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
9780 		    "Invalid event type. <",
9781 		    vfip->VFI,
9782 		    emlxs_vfi_state_xlate(vfip->state),
9783 		    emlxs_fcf_event_xlate(evt), arg1,
9784 		    vfip->flag);
9785 		return (1);
9786 	}
9787 
9788 	if (vfip->flag & EMLXS_VFI_PAUSE_REQ) {
9789 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9790 		    "vfi_pause_evt_action:%d flag=%x. "
9791 		    "Pause already requested. <",
9792 		    vfip->VFI,
9793 		    vfip->flag);
9794 		return (0);
9795 	}
9796 
9797 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
9798 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9799 		    "vfi_pause_evt_action:%d flag=%x. "
9800 		    "Offline already requested. <",
9801 		    vfip->VFI,
9802 		    vfip->flag);
9803 		return (0);
9804 	}
9805 
9806 	switch (vfip->state) {
9807 	case VFI_STATE_OFFLINE:
9808 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9809 		    "vfi_pause_evt_action:%d flag=%x. "
9810 		    "Already offline. <",
9811 		    vfip->VFI,
9812 		    vfip->flag);
9813 		break;
9814 
9815 	case VFI_STATE_PAUSED:
9816 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9817 		    "vfi_pause_evt_action:%d flag=%x. "
9818 		    "Already paused. <",
9819 		    vfip->VFI,
9820 		    vfip->flag);
9821 		break;
9822 
9823 	/* Wait states */
9824 	case VFI_STATE_VPI_ONLINE:
9825 	case VFI_STATE_VPI_OFFLINE_CMPL:
9826 	case VFI_STATE_INIT:
9827 	case VFI_STATE_REG:
9828 	case VFI_STATE_ONLINE:
9829 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9830 		vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
9831 
9832 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9833 		    "vfi_pause_evt_action:%d flag=%x. Handling offline.",
9834 		    vfip->VFI,
9835 		    vfip->flag);
9836 
9837 		/* Handle offline now */
9838 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
9839 		break;
9840 
9841 	default:
9842 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9843 		vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
9844 
9845 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9846 		    "vfi_pause_evt_action:%d flag=%x. <",
9847 		    vfip->VFI,
9848 		    vfip->flag);
9849 		break;
9850 	}
9851 
9852 	return (rval);
9853 
9854 } /* emlxs_vfi_pause_evt_action() */
9855 
9856 
9857 /*ARGSUSED*/
9858 static uint32_t
emlxs_vfi_offline_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9859 emlxs_vfi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9860     void *arg1)
9861 {
9862 	uint32_t rval = 0;
9863 
9864 	if (vfip->state != VFI_STATE_OFFLINE) {
9865 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9866 		    "vfi_offline_action:%d %s:%s arg=%p. "
9867 		    "Invalid state. <",
9868 		    vfip->VFI,
9869 		    emlxs_vfi_state_xlate(vfip->state),
9870 		    emlxs_fcf_event_xlate(evt), arg1);
9871 		return (1);
9872 	}
9873 
9874 	if (!vfip->fcfp) {
9875 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9876 		    "vfi_offline_action:%d %s:%s arg=%p flag=%x. "
9877 		    "Null fcfp found. <",
9878 		    vfip->VFI,
9879 		    emlxs_vfi_state_xlate(vfip->state),
9880 		    emlxs_fcf_event_xlate(evt), arg1,
9881 		    vfip->flag);
9882 		return (1);
9883 	}
9884 
9885 	vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
9886 
9887 	if (vfip->prev_state == VFI_STATE_OFFLINE) {
9888 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9889 		    "vfi_offline_action:%d vfi_online=%d. <",
9890 		    vfip->VFI,
9891 		    vfip->fcfp->vfi_online);
9892 
9893 		return (0);
9894 	}
9895 
9896 	if (vfip->vpi_online) {
9897 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9898 		    "vfi_offline_action:%d vpi_online=%d. VPI's still online.",
9899 		    vfip->VFI,
9900 		    vfip->vpi_online);
9901 	}
9902 
9903 	if (vfip->flag & EMLXS_VFI_FCFI) {
9904 		vfip->flag &= ~EMLXS_VFI_FCFI;
9905 
9906 		if (vfip->fcfp->vfi_online) {
9907 			vfip->fcfp->vfi_online--;
9908 		}
9909 	}
9910 
9911 	/* Check if online was requested */
9912 	if (vfip->flag & EMLXS_VFI_ONLINE_REQ) {
9913 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9914 		    "vfi_offline_action:%d vfi_online=%d. Online requested.",
9915 		    vfip->VFI,
9916 		    vfip->fcfp->vfi_online);
9917 
9918 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
9919 		    FCF_REASON_REQUESTED, 0, arg1);
9920 		return (rval);
9921 	}
9922 
9923 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9924 	    "vfi_offline_action:%d vfi_online=%d. "
9925 	    "VFI offline. Notifying FCFI:%d >",
9926 	    vfip->VFI,
9927 	    vfip->fcfp->vfi_online,
9928 	    vfip->fcfp->fcf_index);
9929 
9930 	/* Notify FCFI */
9931 	rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip);
9932 
9933 	return (rval);
9934 
9935 } /* emlxs_vfi_offline_action() */
9936 
9937 
9938 /*ARGSUSED*/
9939 static uint32_t
emlxs_vfi_init_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)9940 emlxs_vfi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
9941 {
9942 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
9943 	VFIobj_t *vfip;
9944 	MAILBOX4 *mb4;
9945 
9946 	vfip = (VFIobj_t *)mbq->context;
9947 	mb4 = (MAILBOX4 *)mbq;
9948 
9949 	mutex_enter(&EMLXS_FCF_LOCK);
9950 
9951 	if (vfip->state != VFI_STATE_INIT) {
9952 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9953 		    "vfi_init_mbcmpl:%d %s.",
9954 		    vfip->VFI,
9955 		    emlxs_vfi_state_xlate(vfip->state));
9956 
9957 		mutex_exit(&EMLXS_FCF_LOCK);
9958 		return (0);
9959 	}
9960 
9961 	if (mb4->mbxStatus) {
9962 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9963 		    "vfi_init_mbcmpl:%d failed. %s. >",
9964 		    vfip->VFI,
9965 		    emlxs_mb_xlate_status(mb4->mbxStatus));
9966 
9967 		(void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED,
9968 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
9969 
9970 		mutex_exit(&EMLXS_FCF_LOCK);
9971 		return (0);
9972 	}
9973 
9974 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9975 	    "vfi_init_mbcmpl:%d. Init complete. >",
9976 	    vfip->VFI,
9977 	    mb4->mbxStatus);
9978 
9979 	vfip->flag |= EMLXS_VFI_INIT;
9980 	(void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL, 0, 0, 0);
9981 
9982 	mutex_exit(&EMLXS_FCF_LOCK);
9983 	return (0);
9984 
9985 } /* emlxs_vfi_init_mbcmpl() */
9986 
9987 
9988 /*ARGSUSED*/
9989 static uint32_t
emlxs_vfi_init_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9990 emlxs_vfi_init_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9991     void *arg1)
9992 {
9993 	emlxs_hba_t *hba = HBA;
9994 	MAILBOXQ *mbq;
9995 	MAILBOX4 *mb4;
9996 	uint32_t rval = 0;
9997 
9998 	if (vfip->state != VFI_STATE_INIT) {
9999 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10000 		    "vfi_init_action:%d %s:%s arg=%p. "
10001 		    "Invalid state. <",
10002 		    vfip->VFI,
10003 		    emlxs_vfi_state_xlate(vfip->state),
10004 		    emlxs_fcf_event_xlate(evt), arg1);
10005 		return (1);
10006 	}
10007 
10008 	if (!(vfip->flag & EMLXS_VFI_FCFI)) {
10009 		vfip->flag |= EMLXS_VFI_FCFI;
10010 		vfip->fcfp->vfi_online++;
10011 	}
10012 
10013 	if (vfip->prev_state != VFI_STATE_INIT_FAILED) {
10014 		vfip->attempts = 0;
10015 	}
10016 
10017 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
10018 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10019 		    "vfi_init_action:%d attempts=%d. Offline requested.",
10020 		    vfip->VFI,
10021 		    vfip->attempts);
10022 
10023 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10024 		return (rval);
10025 	}
10026 
10027 	if (vfip->flag & EMLXS_VFI_INIT) {
10028 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10029 		    "vfi_init_action:%d flag=%x. "
10030 		    "Already init'd. Skipping INIT_VFI.",
10031 		    vfip->VFI);
10032 
10033 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
10034 		    FCF_REASON_EVENT, evt, arg1);
10035 		return (rval);
10036 	}
10037 
10038 	if (((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) ==
10039 	    SLI_INTF_IF_TYPE_0) && (vfip->fcfp->vfi_online == 1)) {
10040 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10041 		    "vfi_init_action:%d. First VFI. Skipping INIT_VFI.",
10042 		    vfip->VFI);
10043 
10044 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
10045 		    FCF_REASON_EVENT, evt, arg1);
10046 		return (rval);
10047 	}
10048 
10049 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10050 	    "vfi_init_action:%d vfi_online=%d attempts=%d. Sending INIT_VFI. <",
10051 	    vfip->VFI,
10052 	    vfip->fcfp->vfi_online,
10053 	    vfip->attempts);
10054 
10055 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
10056 		rval = emlxs_vfi_state(port, vfip, FCFI_STATE_REG_FAILED,
10057 		    FCF_REASON_NO_MBOX, 0, arg1);
10058 		return (rval);
10059 	}
10060 	mb4 = (MAILBOX4*)mbq;
10061 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10062 
10063 	mbq->nonembed = NULL;
10064 	mbq->mbox_cmpl = emlxs_vfi_init_mbcmpl;
10065 	mbq->context = (void *)vfip;
10066 	mbq->port = (void *)port;
10067 
10068 	mb4->mbxCommand = MBX_INIT_VFI;
10069 	mb4->mbxOwner = OWN_HOST;
10070 	mb4->un.varInitVFI4.fcfi = vfip->fcfp->FCFI;
10071 	mb4->un.varInitVFI4.vfi = vfip->VFI;
10072 
10073 	/* ??? This function is untested and incomplete */
10074 
10075 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
10076 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
10077 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10078 
10079 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED,
10080 		    FCF_REASON_SEND_FAILED, rval, arg1);
10081 
10082 		return (rval);
10083 	}
10084 
10085 	return (0);
10086 
10087 } /* emlxs_vfi_init_action() */
10088 
10089 
10090 /*ARGSUSED*/
10091 static uint32_t
emlxs_vfi_init_failed_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10092 emlxs_vfi_init_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10093     void *arg1)
10094 {
10095 	uint32_t rval = 0;
10096 
10097 	vfip->attempts++;
10098 
10099 	if (vfip->state != VFI_STATE_INIT_FAILED) {
10100 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10101 		    "vfi_init_action:%d %s:%s arg=%p attempt=%d. "
10102 		    "Invalid state. <",
10103 		    vfip->VFI,
10104 		    emlxs_vfi_state_xlate(vfip->state),
10105 		    emlxs_fcf_event_xlate(evt), arg1,
10106 		    vfip->attempts);
10107 		return (1);
10108 	}
10109 
10110 	if ((vfip->reason == FCF_REASON_SEND_FAILED) ||
10111 	    (vfip->attempts >= 3)) {
10112 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10113 		    "vfi_init_action:%d attempt=%d reason=%x. Init cmpl.",
10114 		    vfip->VFI,
10115 		    vfip->attempts,
10116 		    vfip->reason);
10117 
10118 		vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT);
10119 
10120 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10121 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10122 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL,
10123 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10124 	} else {
10125 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10126 		    "vfi_init_action:%d attempt=%d. Initializing.",
10127 		    vfip->VFI,
10128 		    vfip->attempts);
10129 
10130 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
10131 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10132 	}
10133 
10134 	return (rval);
10135 
10136 } /* emlxs_vfi_init_failed_action() */
10137 
10138 
10139 /*ARGSUSED*/
10140 static uint32_t
emlxs_vfi_init_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10141 emlxs_vfi_init_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10142     void *arg1)
10143 {
10144 	uint32_t rval = 0;
10145 
10146 	if (vfip->state != VFI_STATE_INIT_CMPL) {
10147 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10148 		    "vfi_init_cmpl_action:%d %s:%s arg=%p. "
10149 		    "Invalid state. <",
10150 		    vfip->VFI,
10151 		    emlxs_vfi_state_xlate(vfip->state),
10152 		    emlxs_fcf_event_xlate(evt), arg1);
10153 		return (1);
10154 	}
10155 
10156 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10157 	    "vfi_init_cmpl_action:%d attempts=%d. Init cmpl.",
10158 	    vfip->VFI,
10159 	    vfip->attempts);
10160 
10161 	rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
10162 	    FCF_REASON_EVENT, evt, arg1);
10163 
10164 	return (rval);
10165 
10166 } /* emlxs_vfi_init_cmpl_action() */
10167 
10168 
10169 /*ARGSUSED*/
10170 static uint32_t
emlxs_vfi_vpi_online_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10171 emlxs_vfi_vpi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10172     void *arg1)
10173 {
10174 	emlxs_hba_t *hba = HBA;
10175 	uint32_t rval = 0;
10176 	uint32_t i;
10177 	emlxs_port_t *vport;
10178 	VPIobj_t *vpip;
10179 
10180 	if (vfip->state != VFI_STATE_VPI_ONLINE) {
10181 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10182 		    "vfi_vpi_online_action:%d %s:%s arg=%p. "
10183 		    "Invalid state. <",
10184 		    vfip->VFI,
10185 		    emlxs_vfi_state_xlate(vfip->state),
10186 		    emlxs_fcf_event_xlate(evt), arg1);
10187 		return (1);
10188 	}
10189 
10190 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
10191 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10192 		    "vfi_vpi_online_action:%d. Offline requested.",
10193 		    vfip->VFI);
10194 
10195 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10196 		return (rval);
10197 	}
10198 
10199 	if (vfip->logi_count) {
10200 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10201 		    "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. "
10202 		    "VPI already logged in.",
10203 		    vfip->VFI,
10204 		    vfip->vpi_online,
10205 		    vfip->logi_count);
10206 	}
10207 
10208 	if (vfip->vpi_online) {
10209 		/* Waking up after being paused */
10210 
10211 		/* Find first VPI of this VFI */
10212 		for (i = 0; i <= hba->vpi_max; i++) {
10213 			vport = &VPORT(i);
10214 			vpip = vport->vpip;
10215 
10216 			if (!(vport->flag & EMLXS_PORT_BOUND) ||
10217 			    (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
10218 				continue;
10219 			}
10220 
10221 			if (vpip->vfip == vfip) {
10222 				break;
10223 			}
10224 		}
10225 
10226 	} else {
10227 
10228 		/* Find first available VPI */
10229 		for (i = 0; i <= hba->vpi_max; i++) {
10230 			vport = &VPORT(i);
10231 			vpip = vport->vpip;
10232 
10233 			if (!(vport->flag & EMLXS_PORT_BOUND) ||
10234 			    (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
10235 				continue;
10236 			}
10237 
10238 			if (vpip->vfip == NULL) {
10239 				vpip->vfip = vfip;
10240 				break;
10241 			}
10242 		}
10243 	}
10244 
10245 	if (i > hba->vpi_max) {
10246 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10247 		    "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. "
10248 		    "No VPI found. Offlining.",
10249 		    vfip->VFI,
10250 		    vfip->vpi_online,
10251 		    vfip->logi_count);
10252 
10253 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10254 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10255 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10256 		return (rval);
10257 	}
10258 
10259 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10260 	    "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. "
10261 	    "Onlining VPI:%d >",
10262 	    vfip->VFI,
10263 	    vfip->vpi_online,
10264 	    vfip->logi_count,
10265 	    vpip->VPI);
10266 
10267 	rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
10268 
10269 	/* Wait for FCF_EVENT_VPI_ONLINE in return */
10270 
10271 	return (rval);
10272 
10273 } /* emlxs_vfi_vpi_online_action() */
10274 
10275 
10276 /*ARGSUSED*/
10277 static uint32_t
emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10278 emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip,
10279     uint32_t evt, void *arg1)
10280 {
10281 	uint32_t rval = 0;
10282 	VPIobj_t *vpip = (VPIobj_t *)arg1;
10283 
10284 	if (vfip->state != VFI_STATE_VPI_ONLINE_CMPL) {
10285 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10286 		    "vfi_vpi_online_cmpl_action:%d %s:%s arg=%p. "
10287 		    "Invalid state. <",
10288 		    vfip->VFI,
10289 		    emlxs_vfi_state_xlate(vfip->state),
10290 		    emlxs_fcf_event_xlate(evt), arg1);
10291 		return (1);
10292 	}
10293 
10294 	if (vpip == vfip->flogi_vpip) {
10295 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10296 		    "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d "
10297 		    "logi_count=%d. flogi_vpi. Registering.",
10298 		    vfip->VFI,
10299 		    vfip->flag,
10300 		    vfip->vpi_online,
10301 		    vfip->logi_count);
10302 
10303 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG,
10304 		    FCF_REASON_EVENT, evt, arg1);
10305 	} else {
10306 		/* Waking up after pause */
10307 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10308 		    "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d "
10309 		    "logi_count=%d. Going online.",
10310 		    vfip->VFI,
10311 		    vfip->flag,
10312 		    vfip->vpi_online,
10313 		    vfip->logi_count);
10314 
10315 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
10316 		    FCF_REASON_EVENT, evt, arg1);
10317 	}
10318 
10319 	return (rval);
10320 
10321 } /* emlxs_vfi_vpi_online_cmpl_action() */
10322 
10323 
10324 /*ARGSUSED*/
10325 static uint32_t
emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10326 emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip,
10327     uint32_t evt, void *arg1)
10328 {
10329 	uint32_t rval = 0;
10330 
10331 	if (vfip->state != VFI_STATE_VPI_OFFLINE_CMPL) {
10332 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10333 		    "vfi_vpi_offline_cmpl_action:%d %s:%s arg=%p. "
10334 		    "Invalid state. <",
10335 		    vfip->VFI,
10336 		    emlxs_vfi_state_xlate(vfip->state),
10337 		    emlxs_fcf_event_xlate(evt), arg1);
10338 		return (1);
10339 	}
10340 
10341 	if ((vfip->vpi_online == 0) &&
10342 	    (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
10343 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10344 		    "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. "
10345 		    "Unregistering.",
10346 		    vfip->VFI,
10347 		    vfip->vpi_online);
10348 
10349 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
10350 		    FCF_REASON_EVENT, evt, arg1);
10351 	} else {
10352 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10353 		    "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. <",
10354 		    vfip->VFI,
10355 		    vfip->vpi_online);
10356 	}
10357 
10358 	return (rval);
10359 
10360 } /* emlxs_vfi_vpi_offline_cmpl_action() */
10361 
10362 
10363 /*ARGSUSED*/
10364 static uint32_t
emlxs_vfi_vpi_offline_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10365 emlxs_vfi_vpi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10366     void *arg1)
10367 {
10368 	emlxs_hba_t *hba = HBA;
10369 	emlxs_port_t *vport;
10370 	uint32_t rval = 0;
10371 	int32_t i;
10372 	VPIobj_t *vpip;
10373 
10374 	if (vfip->state != VFI_STATE_VPI_OFFLINE) {
10375 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10376 		    "vfi_vpi_offline_action:%d %s:%s arg=%p. "
10377 		    "Invalid state. <",
10378 		    vfip->VFI,
10379 		    emlxs_vfi_state_xlate(vfip->state),
10380 		    emlxs_fcf_event_xlate(evt), arg1);
10381 		return (1);
10382 	}
10383 
10384 	if (vfip->flag & EMLXS_VFI_PAUSE_REQ) {
10385 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10386 		    "vfi_vpi_offline_action:%d vpi_online=%d. Pausing.",
10387 		    vfip->VFI,
10388 		    vfip->vpi_online);
10389 
10390 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED,
10391 		    FCF_REASON_EVENT, evt, arg1);
10392 
10393 		return (rval);
10394 	}
10395 
10396 	if (vfip->vpi_online == 0) {
10397 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10398 		    "vfi_vpi_offline_action:%d vpi_online=%d. "
10399 		    "VPI already offline. Skipping VPI offline.",
10400 		    vfip->VFI,
10401 		    vfip->vpi_online);
10402 
10403 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
10404 		    FCF_REASON_EVENT, evt, arg1);
10405 
10406 		return (rval);
10407 	}
10408 
10409 	/* Offline all VPI's of this VFI */
10410 	for (i = hba->vpi_max; i >= 0; i--) {
10411 		vport = &VPORT(i);
10412 		vpip = vport->vpip;
10413 
10414 		if ((vpip->state == VPI_STATE_OFFLINE) ||
10415 		    (vpip->vfip != vfip)) {
10416 			continue;
10417 		}
10418 
10419 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10420 		    "vfi_vpi_offline_action:%d. Offlining VPI:%d. >",
10421 		    vfip->VFI,
10422 		    vpip->VPI);
10423 
10424 		(void) emlxs_vpi_event(vport, FCF_EVENT_VPI_OFFLINE, vpip);
10425 	}
10426 
10427 	/* Wait for FCF_EVENT_VPI_OFFLINE in return */
10428 
10429 	return (0);
10430 
10431 } /* emlxs_vfi_vpi_offline_action() */
10432 
10433 
10434 /*ARGSUSED*/
10435 static uint32_t
emlxs_vfi_paused_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10436 emlxs_vfi_paused_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10437     void *arg1)
10438 {
10439 	emlxs_hba_t *hba = HBA;
10440 	emlxs_port_t *vport;
10441 	int32_t i;
10442 	VPIobj_t *vpip;
10443 
10444 	if (vfip->state != VFI_STATE_PAUSED) {
10445 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10446 		    "vfi_paused_action:%d %s:%s arg=%p. "
10447 		    "Invalid state. <",
10448 		    vfip->VFI,
10449 		    emlxs_vfi_state_xlate(vfip->state),
10450 		    emlxs_fcf_event_xlate(evt), arg1);
10451 		return (1);
10452 	}
10453 
10454 	vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
10455 
10456 	/* Pause all VPI's of this VFI */
10457 	for (i = hba->vpi_max; i >= 0; i--) {
10458 		vport = &VPORT(i);
10459 		vpip = vport->vpip;
10460 
10461 		if ((vpip->state == VPI_STATE_PAUSED) ||
10462 		    (vpip->vfip != vfip)) {
10463 			continue;
10464 		}
10465 
10466 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10467 		    "vfi_paused_action:%d vpi_online=%d. Pausing VPI:%d. >",
10468 		    vfip->VFI,
10469 		    vfip->vpi_online,
10470 		    vpip->VPI);
10471 
10472 		(void) emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip);
10473 	}
10474 
10475 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10476 	    "vfi_paused_action:%d vpi_online=%d. VFI paused. <",
10477 	    vfip->VFI,
10478 	    vfip->vpi_online);
10479 
10480 	return (0);
10481 
10482 } /* emlxs_vfi_paused_action() */
10483 
10484 
10485 /*ARGSUSED*/
10486 static uint32_t
emlxs_vfi_unreg_failed_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10487 emlxs_vfi_unreg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10488     void *arg1)
10489 {
10490 	uint32_t rval = 0;
10491 
10492 	vfip->attempts++;
10493 
10494 	if (vfip->state != VFI_STATE_UNREG_FAILED) {
10495 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10496 		    "vfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
10497 		    "Invalid state. <",
10498 		    vfip->VFI,
10499 		    emlxs_vfi_state_xlate(vfip->state),
10500 		    emlxs_fcf_event_xlate(evt), arg1,
10501 		    vfip->attempts);
10502 		return (1);
10503 	}
10504 
10505 	if (vfip->attempts >= 3) {
10506 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10507 		    "vfi_unreg_failed_action:%d attempt=%d. Unreg cmpl.",
10508 		    vfip->VFI,
10509 		    vfip->attempts);
10510 
10511 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10512 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10513 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL,
10514 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10515 	} else {
10516 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10517 		    "vfi_unreg_failed_action:%d attempt=%d. Unregistering.",
10518 		    vfip->VFI,
10519 		    vfip->attempts);
10520 
10521 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
10522 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10523 	}
10524 
10525 	return (rval);
10526 
10527 } /* emlxs_vfi_unreg_failed_action() */
10528 
10529 
10530 /*ARGSUSED*/
10531 static uint32_t
emlxs_vfi_unreg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)10532 emlxs_vfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
10533 {
10534 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
10535 	MAILBOX4 *mb4;
10536 	VFIobj_t *vfip;
10537 
10538 	vfip = (VFIobj_t *)mbq->context;
10539 	mb4 = (MAILBOX4 *)mbq;
10540 
10541 	mutex_enter(&EMLXS_FCF_LOCK);
10542 
10543 	if (vfip->state != VFI_STATE_UNREG) {
10544 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10545 		    "vfi_unreg_mbcmpl:%d state=%s.",
10546 		    vfip->VFI,
10547 		    emlxs_vfi_state_xlate(vfip->state));
10548 
10549 		mutex_exit(&EMLXS_FCF_LOCK);
10550 		return (0);
10551 	}
10552 
10553 	if (mb4->mbxStatus) {
10554 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10555 		    "vfi_unreg_mbcmpl:%d failed. %s. >",
10556 		    vfip->VFI,
10557 		    emlxs_mb_xlate_status(mb4->mbxStatus));
10558 
10559 		(void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
10560 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
10561 
10562 		mutex_exit(&EMLXS_FCF_LOCK);
10563 		return (0);
10564 	}
10565 
10566 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10567 	    "vfi_unreg_mbcmpl:%d. Unreg complete. >",
10568 	    vfip->VFI);
10569 
10570 	vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT);
10571 	(void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL,
10572 	    0, 0, 0);
10573 
10574 	mutex_exit(&EMLXS_FCF_LOCK);
10575 	return (0);
10576 
10577 } /* emlxs_vfi_unreg_mbcmpl() */
10578 
10579 
10580 /*ARGSUSED*/
10581 static uint32_t
emlxs_vfi_unreg_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10582 emlxs_vfi_unreg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10583     void *arg1)
10584 {
10585 	emlxs_hba_t *hba = HBA;
10586 	MAILBOX4 *mb4;
10587 	MAILBOXQ *mbq;
10588 	uint32_t rval = 0;
10589 
10590 	if (vfip->state != VFI_STATE_UNREG) {
10591 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10592 		    "vfi_unreg_action:%d %s:%s arg=%p. "
10593 		    "Invalid state. <",
10594 		    vfip->VFI,
10595 		    emlxs_vfi_state_xlate(vfip->state),
10596 		    emlxs_fcf_event_xlate(evt), arg1);
10597 		return (1);
10598 	}
10599 
10600 	if (!(vfip->flag & EMLXS_VFI_REG)) {
10601 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10602 		    "vfi_unreg_action:%d. Not registered. Skipping UNREG_VFI.",
10603 		    vfip->VFI);
10604 
10605 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
10606 		    FCF_REASON_EVENT, evt, arg1);
10607 		return (rval);
10608 	}
10609 
10610 	if (vfip->prev_state != VFI_STATE_UNREG_FAILED) {
10611 		vfip->attempts = 0;
10612 	}
10613 
10614 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10615 	    "vfi_unreg_action:%d attempts=%d. Sending UNREG_VFI. <",
10616 	    vfip->VFI,
10617 	    vfip->attempts);
10618 
10619 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
10620 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
10621 		    FCF_REASON_NO_MBOX, 0, arg1);
10622 
10623 		return (rval);
10624 	}
10625 	mb4 = (MAILBOX4*)mbq;
10626 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10627 
10628 	mbq->nonembed = NULL;
10629 	mbq->mbox_cmpl = emlxs_vfi_unreg_mbcmpl;
10630 	mbq->context = (void *)vfip;
10631 	mbq->port = (void *)port;
10632 
10633 	mb4->un.varUnRegVFI4.vfi = vfip->VFI;
10634 	mb4->mbxCommand = MBX_UNREG_VFI;
10635 	mb4->mbxOwner = OWN_HOST;
10636 
10637 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
10638 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
10639 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10640 
10641 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
10642 		    FCF_REASON_SEND_FAILED, rval, arg1);
10643 
10644 		return (rval);
10645 	}
10646 
10647 	return (0);
10648 
10649 } /* emlxs_vfi_unreg_action() */
10650 
10651 
10652 /*ARGSUSED*/
10653 static uint32_t
emlxs_vfi_unreg_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10654 emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10655     void *arg1)
10656 {
10657 	uint32_t rval = 0;
10658 
10659 	if (vfip->state != VFI_STATE_UNREG_CMPL) {
10660 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10661 		    "vfi_unreg_cmpl_action:%d %s:%s arg=%p. "
10662 		    "Invalid state. <",
10663 		    vfip->VFI,
10664 		    emlxs_vfi_state_xlate(vfip->state),
10665 		    emlxs_fcf_event_xlate(evt), arg1);
10666 		return (1);
10667 	}
10668 
10669 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10670 	    "vfi_unreg_cmpl_action:%d attempts=%d. Going offline.",
10671 	    vfip->VFI,
10672 	    vfip->attempts);
10673 
10674 	rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
10675 	    FCF_REASON_EVENT, evt, arg1);
10676 
10677 	return (rval);
10678 
10679 } /* emlxs_vfi_unreg_cmpl_action() */
10680 
10681 
10682 /*ARGSUSED*/
10683 static uint32_t
emlxs_vfi_reg_failed_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10684 emlxs_vfi_reg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10685     void *arg1)
10686 {
10687 	uint32_t rval = 0;
10688 
10689 	vfip->attempts++;
10690 
10691 	if (vfip->state != VFI_STATE_REG_FAILED) {
10692 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10693 		    "vfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
10694 		    "Invalid state. <",
10695 		    vfip->VFI,
10696 		    emlxs_vfi_state_xlate(vfip->state),
10697 		    emlxs_fcf_event_xlate(evt), arg1,
10698 		    vfip->attempts);
10699 		return (1);
10700 	}
10701 
10702 	if ((vfip->reason == FCF_REASON_SEND_FAILED) ||
10703 	    (vfip->attempts >= 3)) {
10704 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10705 		    "vfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.",
10706 		    vfip->VFI,
10707 		    vfip->attempts,
10708 		    vfip->reason);
10709 
10710 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10711 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10712 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL,
10713 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10714 	} else {
10715 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10716 		    "vfi_reg_failed_action:%d attempt=%d. Registering.",
10717 		    vfip->VFI,
10718 		    vfip->attempts);
10719 
10720 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG,
10721 		    FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10722 	}
10723 
10724 	return (rval);
10725 
10726 } /* emlxs_vfi_reg_failed_action() */
10727 
10728 
10729 /*ARGSUSED*/
10730 static uint32_t
emlxs_vfi_reg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)10731 emlxs_vfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
10732 {
10733 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
10734 	MAILBOX4 *mb4;
10735 	VFIobj_t *vfip;
10736 	MATCHMAP *mp;
10737 
10738 	vfip = (VFIobj_t *)mbq->context;
10739 	mb4 = (MAILBOX4 *)mbq;
10740 
10741 	mutex_enter(&EMLXS_FCF_LOCK);
10742 
10743 	if (vfip->state != VFI_STATE_REG) {
10744 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10745 		    "vfi_reg_mbcmpl:%d state=%s.",
10746 		    vfip->VFI,
10747 		    emlxs_vfi_state_xlate(vfip->state));
10748 
10749 		mutex_exit(&EMLXS_FCF_LOCK);
10750 		return (0);
10751 	}
10752 
10753 	if (mb4->mbxStatus) {
10754 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10755 		    "vfi_reg_mbcmpl:%d failed. %s. >",
10756 		    vfip->VFI,
10757 		    emlxs_mb_xlate_status(mb4->mbxStatus));
10758 
10759 		(void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10760 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
10761 
10762 		mutex_exit(&EMLXS_FCF_LOCK);
10763 		return (0);
10764 	}
10765 
10766 	/* Archive a copy of the sparams in case we need them later */
10767 	mp = (MATCHMAP *)mbq->bp;
10768 	bcopy((uint32_t *)mp->virt, (uint32_t *)&vfip->sparam,
10769 	    sizeof (SERV_PARM));
10770 
10771 	if (vfip->flogi_vpip) {
10772 		if (mb4->un.varRegVFI4.vp == 1) {
10773 			vfip->flogi_vpip->flag |= EMLXS_VPI_REG;
10774 		}
10775 		vfip->flogi_vpip = NULL;
10776 	}
10777 
10778 	vfip->flag |= EMLXS_VFI_REG;
10779 
10780 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10781 	    "vfi_reg_mbcmpl:%d. Reg complete. >",
10782 	    vfip->VFI);
10783 
10784 	(void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL, 0, 0, 0);
10785 
10786 	mutex_exit(&EMLXS_FCF_LOCK);
10787 	return (0);
10788 
10789 } /* emlxs_vfi_reg_mbcmpl() */
10790 
10791 
10792 /*ARGSUSED*/
10793 static uint32_t
emlxs_vfi_reg_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10794 emlxs_vfi_reg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10795     void *arg1)
10796 {
10797 	emlxs_hba_t *hba = HBA;
10798 	MAILBOX4 *mb4;
10799 	MAILBOXQ *mbq;
10800 	MATCHMAP *mp;
10801 	uint32_t rval = 0;
10802 	uint32_t edtov;
10803 	uint32_t ratov;
10804 	SERV_PARM *flogi_sparam;
10805 	uint32_t *wwpn;
10806 
10807 	if (vfip->state != VFI_STATE_REG) {
10808 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10809 		    "vfi_reg_action:%d %s:%s arg=%p. "
10810 		    "Invalid state. <",
10811 		    vfip->VFI,
10812 		    emlxs_vfi_state_xlate(vfip->state),
10813 		    emlxs_fcf_event_xlate(evt), arg1);
10814 		return (1);
10815 	}
10816 
10817 	if (vfip->prev_state != VFI_STATE_REG_FAILED) {
10818 		vfip->attempts = 0;
10819 	}
10820 
10821 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
10822 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10823 		    "vfi_reg_action:%d %attempts=%d. Offline requested.",
10824 		    vfip->VFI,
10825 		    vfip->attempts);
10826 
10827 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10828 		return (rval);
10829 	}
10830 
10831 	if (!vfip->flogi_vpip) {
10832 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10833 		    "vfi_reg_action:%d %attempts=%d. No flogi_vpi found.",
10834 		    vfip->VFI,
10835 		    vfip->attempts);
10836 
10837 		vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10838 		vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10839 
10840 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10841 		return (rval);
10842 	}
10843 
10844 	if ((hba->model_info.chip & EMLXS_BE_CHIPS) &&
10845 	    (vfip->flag & EMLXS_VFI_REG)) {
10846 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10847 		    "vfi_reg_action:%d flag=%x. "
10848 		    "Already registered. Skipping REG_VFI update.",
10849 		    vfip->VFI);
10850 
10851 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
10852 		    FCF_REASON_EVENT, evt, arg1);
10853 		return (rval);
10854 	}
10855 
10856 	/* Get the flogi_vpip's fabric_rpip's service parameters */
10857 	flogi_sparam = &vfip->flogi_vpip->fabric_rpip->sparam;
10858 
10859 	if (flogi_sparam->cmn.edtovResolution) {
10860 		edtov = (LE_SWAP32(flogi_sparam->cmn.e_d_tov) + 999999) /
10861 		    1000000;
10862 	} else {
10863 		edtov = LE_SWAP32(flogi_sparam->cmn.e_d_tov);
10864 	}
10865 
10866 	ratov = (LE_SWAP32(flogi_sparam->cmn.w2.r_a_tov) + 999) / 1000;
10867 
10868 	if (vfip->flag & EMLXS_VFI_REG) {
10869 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10870 		    "vfi_reg_action:%d attempts=%d edtov=%d ratov=%d. "
10871 		    "Updating REG_VFI. <",
10872 		    vfip->VFI,
10873 		    vfip->attempts,
10874 		    edtov, ratov);
10875 	} else {
10876 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10877 		    "vfi_reg_action:%d attempts=%d edtov=%d ratov=%d. "
10878 		    "Sending REG_VFI. <",
10879 		    vfip->VFI,
10880 		    vfip->attempts,
10881 		    edtov, ratov);
10882 	}
10883 
10884 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
10885 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10886 		    FCF_REASON_NO_MBOX, 0, arg1);
10887 
10888 		return (rval);
10889 	}
10890 	mb4 = (MAILBOX4*)mbq;
10891 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10892 
10893 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
10894 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10895 
10896 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10897 		    FCF_REASON_NO_BUFFER, 0, arg1);
10898 
10899 		return (1);
10900 	}
10901 
10902 	mbq->bp = (void *)mp;
10903 	mbq->nonembed = NULL;
10904 
10905 	mbq->mbox_cmpl = emlxs_vfi_reg_mbcmpl;
10906 	mbq->context = (void *)vfip;
10907 	mbq->port = (void *)port;
10908 
10909 	mb4->mbxCommand = MBX_REG_VFI;
10910 	mb4->mbxOwner = OWN_HOST;
10911 
10912 	mb4->un.varRegVFI4.vfi = vfip->VFI;
10913 	mb4->un.varRegVFI4.upd = (vfip->flag & EMLXS_VFI_REG)? 1:0;
10914 
10915 	/* If the flogi_vpip was not previously registered, */
10916 	/* perform the REG_VPI now */
10917 	if (!(vfip->flogi_vpip->flag & EMLXS_VPI_REG)) {
10918 		mb4->un.varRegVFI4.vp = 1;
10919 		mb4->un.varRegVFI4.vpi = vfip->flogi_vpip->VPI;
10920 	}
10921 
10922 	mb4->un.varRegVFI4.fcfi = vfip->fcfp->FCFI;
10923 	wwpn = (uint32_t *)&port->wwpn;
10924 	mb4->un.varRegVFI4.portname[0] = BE_SWAP32(*wwpn);
10925 	wwpn++;
10926 	mb4->un.varRegVFI4.portname[1] = BE_SWAP32(*wwpn);
10927 	mb4->un.varRegVFI4.sid = port->did;
10928 	mb4->un.varRegVFI4.edtov = edtov;
10929 	mb4->un.varRegVFI4.ratov = ratov;
10930 	mb4->un.varRegVFI4.bde.tus.f.bdeSize = sizeof (SERV_PARM);
10931 	mb4->un.varRegVFI4.bde.addrHigh = PADDR_HI(mp->phys);
10932 	mb4->un.varRegVFI4.bde.addrLow = PADDR_LO(mp->phys);
10933 	bcopy((uint32_t *)flogi_sparam, (uint32_t *)mp->virt,
10934 	    sizeof (SERV_PARM));
10935 
10936 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
10937 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
10938 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
10939 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10940 
10941 		rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10942 		    FCF_REASON_SEND_FAILED, rval, arg1);
10943 
10944 		return (rval);
10945 	}
10946 
10947 	return (0);
10948 
10949 } /* emlxs_vfi_reg_action() */
10950 
10951 
10952 /*ARGSUSED*/
10953 static uint32_t
emlxs_vfi_reg_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10954 emlxs_vfi_reg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10955     void *arg1)
10956 {
10957 	uint32_t rval = 0;
10958 
10959 	if (vfip->state != VFI_STATE_REG_CMPL) {
10960 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10961 		    "vfi_reg_cmpl_action:%d %s:%s arg=%p. "
10962 		    "Invalid state. <",
10963 		    vfip->VFI,
10964 		    emlxs_vfi_state_xlate(vfip->state),
10965 		    emlxs_fcf_event_xlate(evt), arg1);
10966 		return (1);
10967 	}
10968 
10969 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
10970 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10971 		    "vfi_reg_cmpl_action:%d attempts=%d. Offline requested.",
10972 		    vfip->VFI,
10973 		    vfip->attempts);
10974 
10975 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10976 		return (rval);
10977 	}
10978 
10979 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10980 	    "vfi_reg_cmpl_action:%d attempts=%d. Going online.",
10981 	    vfip->VFI,
10982 	    vfip->attempts);
10983 
10984 	rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
10985 	    FCF_REASON_EVENT, evt, arg1);
10986 
10987 	return (rval);
10988 
10989 } /* emlxs_vfi_reg_cmpl_action() */
10990 
10991 
10992 /*ARGSUSED*/
10993 static uint32_t
emlxs_vfi_online_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10994 emlxs_vfi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10995     void *arg1)
10996 {
10997 	emlxs_hba_t *hba = HBA;
10998 	uint32_t i;
10999 	uint32_t rval = 0;
11000 	VPIobj_t *vpip = port->vpip;
11001 	emlxs_port_t *vport;
11002 
11003 	if (vfip->state != VFI_STATE_ONLINE) {
11004 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11005 		    "vfi_online_action:%d %s:%s arg=%p. "
11006 		    "Invalid state. <",
11007 		    vfip->VFI,
11008 		    emlxs_vfi_state_xlate(vfip->state),
11009 		    emlxs_fcf_event_xlate(evt), arg1);
11010 		return (1);
11011 	}
11012 
11013 	vfip->flag &= ~EMLXS_VFI_ONLINE_REQ;
11014 
11015 	if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
11016 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11017 		    "vfi_online_action:%d attempts=%d. Offline requested.",
11018 		    vfip->VFI,
11019 		    vfip->attempts);
11020 
11021 		rval = emlxs_vfi_offline_handler(port, vfip, arg1);
11022 		return (rval);
11023 	}
11024 
11025 	/* Take the port's Fabric RPI online now */
11026 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11027 	    "vfi_online_action:%d. Onlining Fabric RPI. >",
11028 	    vfip->VFI);
11029 
11030 	/* This will complete the FLOGI/FDISC back to Leadville */
11031 	(void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE,
11032 	    vpip->fabric_rpip);
11033 
11034 	/* FLOGI/FDISC has been completed back to Leadville */
11035 	/* It is now safe to accept unsolicited requests */
11036 	vpip->flag |= EMLXS_VPI_PORT_ENABLED;
11037 
11038 	/* Online remaining VPI's */
11039 	for (i = 0; i <= hba->vpi_max; i++) {
11040 		vport = &VPORT(i);
11041 		vpip = vport->vpip;
11042 
11043 		if (!(vport->flag & EMLXS_PORT_BOUND) ||
11044 		    (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
11045 			continue;
11046 		}
11047 
11048 		if ((vpip->state == VPI_STATE_ONLINE) ||
11049 		    (vpip->flag & EMLXS_VPI_ONLINE_REQ)) {
11050 			continue;
11051 		}
11052 
11053 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11054 		    "vfi_online_action:%d vpi_online=%d logi_count=%d. "
11055 		    "Onlining VPI:%d >",
11056 		    vfip->VFI,
11057 		    vfip->vpi_online,
11058 		    vfip->logi_count,
11059 		    vpip->VPI);
11060 
11061 		vpip->vfip = vfip;
11062 		(void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE, vpip);
11063 	}
11064 
11065 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11066 	    "vfi_online_action:%d vpi_online=%d logi_count=%d. "
11067 	    "VFI online. Notifying FCFI:%d. >",
11068 	    vfip->VFI,
11069 	    vfip->vpi_online,
11070 	    vfip->logi_count,
11071 	    vfip->fcfp->fcf_index);
11072 
11073 	/* Notify FCFI */
11074 	rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
11075 
11076 	return (rval);
11077 
11078 } /* emlxs_vfi_online_action() */
11079 
11080 
11081 /* ************************************************************************** */
11082 /* VPI */
11083 /* ************************************************************************** */
11084 
11085 static char *
emlxs_vpi_state_xlate(uint32_t state)11086 emlxs_vpi_state_xlate(uint32_t state)
11087 {
11088 	static char buffer[32];
11089 	uint32_t i;
11090 	uint32_t count;
11091 
11092 	count = sizeof (emlxs_vpi_state_table) / sizeof (emlxs_table_t);
11093 	for (i = 0; i < count; i++) {
11094 		if (state == emlxs_vpi_state_table[i].code) {
11095 			return (emlxs_vpi_state_table[i].string);
11096 		}
11097 	}
11098 
11099 	(void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
11100 	return (buffer);
11101 
11102 } /* emlxs_vpi_state_xlate() */
11103 
11104 
11105 static uint32_t
emlxs_vpi_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11106 emlxs_vpi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11107     void *arg1)
11108 {
11109 	uint32_t rval = 0;
11110 	uint32_t(*func) (emlxs_port_t *, VPIobj_t *, uint32_t, void *);
11111 	uint32_t index;
11112 	uint32_t events;
11113 	uint16_t state;
11114 
11115 	/* Convert event to action table index */
11116 	switch (evt) {
11117 	case FCF_EVENT_STATE_ENTER:
11118 		index = 0;
11119 		break;
11120 	case FCF_EVENT_VPI_ONLINE:
11121 		index = 1;
11122 		break;
11123 	case FCF_EVENT_VPI_OFFLINE:
11124 		index = 2;
11125 		break;
11126 	case FCF_EVENT_VPI_PAUSE:
11127 		index = 3;
11128 		break;
11129 	case FCF_EVENT_RPI_ONLINE:
11130 		index = 4;
11131 		break;
11132 	case FCF_EVENT_RPI_OFFLINE:
11133 		index = 5;
11134 		break;
11135 	case FCF_EVENT_RPI_PAUSE:
11136 		index = 6;
11137 		break;
11138 	default:
11139 		return (1);
11140 	}
11141 
11142 	events = VPI_ACTION_EVENTS;
11143 	state  = vpip->state;
11144 
11145 	index += (state * events);
11146 	func   = (uint32_t(*) (emlxs_port_t *, VPIobj_t *, uint32_t, void *))
11147 	    emlxs_vpi_action_table[index];
11148 
11149 	if (!func) {
11150 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11151 		    "vpi_action:%d %s:%s arg=%p. No action. <",
11152 		    vpip->VPI,
11153 		    emlxs_vpi_state_xlate(vpip->state),
11154 		    emlxs_fcf_event_xlate(evt), arg1);
11155 
11156 		return (1);
11157 	}
11158 
11159 	rval = (func)(port, vpip, evt, arg1);
11160 
11161 	return (rval);
11162 
11163 } /* emlxs_vpi_action() */
11164 
11165 
11166 static uint32_t
emlxs_vpi_event(emlxs_port_t * port,uint32_t evt,void * arg1)11167 emlxs_vpi_event(emlxs_port_t *port, uint32_t evt,
11168     void *arg1)
11169 {
11170 	VPIobj_t *vpip = NULL;
11171 	RPIobj_t *rpip;
11172 	uint32_t rval = 0;
11173 
11174 	/* Filter events and acquire fcfi context */
11175 	switch (evt) {
11176 	case FCF_EVENT_RPI_ONLINE:
11177 	case FCF_EVENT_RPI_OFFLINE:
11178 	case FCF_EVENT_RPI_PAUSE:
11179 		rpip = (RPIobj_t *)arg1;
11180 
11181 		if (!rpip) {
11182 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11183 			    "vpi_event: %s arg=%p. Null RPI found. <",
11184 			    emlxs_fcf_event_xlate(evt), arg1);
11185 
11186 			return (1);
11187 		}
11188 
11189 		vpip = rpip->vpip;
11190 		break;
11191 
11192 	case FCF_EVENT_VPI_ONLINE:
11193 	case FCF_EVENT_VPI_PAUSE:
11194 	case FCF_EVENT_VPI_OFFLINE:
11195 		vpip = (VPIobj_t *)arg1;
11196 
11197 		if (!vpip) {
11198 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11199 			    "vpi_event: %s arg=%p. Null VPI found. <",
11200 			    emlxs_fcf_event_xlate(evt), arg1);
11201 
11202 			return (1);
11203 		}
11204 
11205 		break;
11206 
11207 	default:
11208 		return (1);
11209 	}
11210 
11211 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11212 	    "vpi_event:%d %s:%s arg=%p",
11213 	    vpip->VPI,
11214 	    emlxs_vpi_state_xlate(vpip->state),
11215 	    emlxs_fcf_event_xlate(evt), arg1);
11216 
11217 	rval = emlxs_vpi_action(port, vpip, evt, arg1);
11218 
11219 	return (rval);
11220 
11221 } /* emlxs_vpi_event() */
11222 
11223 
11224 /*ARGSUSED*/
11225 static uint32_t
emlxs_vpi_state(emlxs_port_t * port,VPIobj_t * vpip,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)11226 emlxs_vpi_state(emlxs_port_t *port, VPIobj_t *vpip, uint16_t state,
11227     uint16_t reason, uint32_t explain, void *arg1)
11228 {
11229 	uint32_t rval = 0;
11230 
11231 	if (state >= VPI_ACTION_STATES) {
11232 		return (1);
11233 	}
11234 
11235 	if ((vpip->state == state) &&
11236 	    (reason != FCF_REASON_REENTER)) {
11237 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11238 		    "vpi_state:%d %s:%s:0x%x arg=%p. "
11239 		    "State not changed. <",
11240 		    vpip->VPI,
11241 		    emlxs_vpi_state_xlate(vpip->state),
11242 		    emlxs_fcf_reason_xlate(reason),
11243 		    explain, arg1);
11244 		return (1);
11245 	}
11246 
11247 	if (!reason) {
11248 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11249 		    "vpi_state:%d %s-->%s arg=%p",
11250 		    vpip->VPI,
11251 		    emlxs_vpi_state_xlate(vpip->state),
11252 		    emlxs_vpi_state_xlate(state), arg1);
11253 	} else if (reason == FCF_REASON_EVENT) {
11254 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11255 		    "vpi_state:%d %s-->%s:%s:%s arg=%p",
11256 		    vpip->VPI,
11257 		    emlxs_vpi_state_xlate(vpip->state),
11258 		    emlxs_vpi_state_xlate(state),
11259 		    emlxs_fcf_reason_xlate(reason),
11260 		    emlxs_fcf_event_xlate(explain), arg1);
11261 	} else if (explain) {
11262 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11263 		    "vpi_state:%d %s-->%s:%s:0x%x arg=%p",
11264 		    vpip->VPI,
11265 		    emlxs_vpi_state_xlate(vpip->state),
11266 		    emlxs_vpi_state_xlate(state),
11267 		    emlxs_fcf_reason_xlate(reason),
11268 		    explain, arg1);
11269 	} else {
11270 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11271 		    "vpi_state:%d %s-->%s:%s arg=%p",
11272 		    vpip->VPI,
11273 		    emlxs_vpi_state_xlate(vpip->state),
11274 		    emlxs_vpi_state_xlate(state),
11275 		    emlxs_fcf_reason_xlate(reason), arg1);
11276 	}
11277 
11278 	vpip->prev_state = vpip->state;
11279 	vpip->prev_reason = vpip->reason;
11280 	vpip->state = state;
11281 	vpip->reason = reason;
11282 
11283 	rval = emlxs_vpi_action(port, vpip, FCF_EVENT_STATE_ENTER, arg1);
11284 
11285 	return (rval);
11286 
11287 } /* emlxs_vpi_state() */
11288 
11289 
11290 extern uint32_t
emlxs_vpi_port_bind_notify(emlxs_port_t * port)11291 emlxs_vpi_port_bind_notify(emlxs_port_t *port)
11292 {
11293 	emlxs_hba_t *hba = HBA;
11294 	VPIobj_t 	*vpip = port->vpip;
11295 	FCFTable_t	*fcftab = &hba->sli.sli4.fcftab;
11296 	uint32_t rval = 0;
11297 	VFIobj_t *vfip;
11298 	VFIobj_t *vfip1;
11299 	uint32_t i = 0;
11300 	FCFIobj_t *fcfp;
11301 	FCFIobj_t *fcfp1;
11302 
11303 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
11304 		return (1);
11305 	}
11306 
11307 	if (hba->state < FC_LINK_UP) {
11308 		if (port->vpi == 0) {
11309 			(void) emlxs_reset_link(hba, 1, 0);
11310 
11311 			/* Wait for VPI to go online */
11312 			while ((vpip->state != VPI_STATE_PORT_ONLINE) &&
11313 			    (hba->state != FC_ERROR)) {
11314 				delay(drv_usectohz(500000));
11315 				if (i++ > 30) {
11316 					break;
11317 				}
11318 			}
11319 		}
11320 		return (0);
11321 	}
11322 
11323 	mutex_enter(&EMLXS_FCF_LOCK);
11324 
11325 	if (vpip->vfip) {
11326 		vfip = vpip->vfip;
11327 		fcfp = vfip->fcfp;
11328 		goto done;
11329 	}
11330 
11331 	/* We need to select a VFI for this VPI */
11332 
11333 	/* First find a selected Fabric */
11334 	fcfp = NULL;
11335 	for (i = 0; i < fcftab->fcfi_count; i++) {
11336 		fcfp1 = fcftab->fcfi[i];
11337 
11338 		if (fcfp1->flag & EMLXS_FCFI_SELECTED) {
11339 			fcfp = fcfp1;
11340 			break;
11341 		}
11342 	}
11343 
11344 	if (!fcfp) {
11345 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11346 		    "vpi_port_bind_notify:%d %s. "
11347 		    "No FCF available yet.",
11348 		    vpip->VPI,
11349 		    emlxs_vpi_state_xlate(vpip->state));
11350 
11351 		mutex_exit(&EMLXS_FCF_LOCK);
11352 		return (0);
11353 	}
11354 
11355 	/* Find first available VFI for this FCFI */
11356 	vfip = NULL;
11357 	vfip1 = hba->sli.sli4.VFI_table;
11358 	for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip1++) {
11359 		if (vfip1->fcfp == fcfp) {
11360 			vfip = vfip1;
11361 			break;
11362 		}
11363 	}
11364 
11365 	if (!vfip) {
11366 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11367 		    "vpi_port_bind_notify:%d %s fcfi:%d. "
11368 		    "No VFI available yet.",
11369 		    vpip->VPI,
11370 		    emlxs_vpi_state_xlate(vpip->state),
11371 		    fcfp->fcf_index);
11372 
11373 		mutex_exit(&EMLXS_FCF_LOCK);
11374 		return (0);
11375 	}
11376 
11377 	vpip->vfip = vfip;
11378 done:
11379 
11380 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11381 	    "vpi_port_bind_notify:%d %s fcfi:%d vfi:%d. Onlining VPI:%d >",
11382 	    vpip->VPI,
11383 	    emlxs_vpi_state_xlate(vpip->state),
11384 	    fcfp->fcf_index,
11385 	    vfip->VFI,
11386 	    vpip->VPI);
11387 
11388 	rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
11389 
11390 	mutex_exit(&EMLXS_FCF_LOCK);
11391 
11392 	return (rval);
11393 
11394 } /* emlxs_vpi_port_bind_notify() */
11395 
11396 
11397 extern uint32_t
emlxs_vpi_port_unbind_notify(emlxs_port_t * port,uint32_t wait)11398 emlxs_vpi_port_unbind_notify(emlxs_port_t *port, uint32_t wait)
11399 {
11400 	emlxs_hba_t *hba = HBA;
11401 	VPIobj_t 	*vpip = port->vpip;
11402 	uint32_t rval = 0;
11403 	VFIobj_t *vfip;
11404 	uint32_t i;
11405 	FCFIobj_t *fcfp;
11406 
11407 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
11408 		return (1);
11409 	}
11410 
11411 	if (!(hba->sli.sli4.flag & EMLXS_SLI4_FCF_INIT)) {
11412 		return (0);
11413 	}
11414 
11415 	mutex_enter(&EMLXS_FCF_LOCK);
11416 
11417 	if (vpip->state == VPI_STATE_OFFLINE) {
11418 		mutex_exit(&EMLXS_FCF_LOCK);
11419 		return (0);
11420 	}
11421 
11422 	/*
11423 	 * Set flag to indicate that emlxs_vpi_port_unbind_notify
11424 	 * has been called
11425 	 */
11426 	vpip->flag |= EMLXS_VPI_PORT_UNBIND;
11427 
11428 	vfip = vpip->vfip;
11429 	fcfp = vfip->fcfp;
11430 
11431 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11432 	    "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d. "
11433 	    "Offlining VPI:%d,%d >",
11434 	    vpip->VPI,
11435 	    emlxs_vpi_state_xlate(vpip->state),
11436 	    fcfp->fcf_index,
11437 	    vfip->VFI,
11438 	    vpip->index, vpip->VPI);
11439 
11440 	rval = emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
11441 
11442 	if (wait && (rval == 0)) {
11443 		/* Wait for VPI to go offline */
11444 		i = 0;
11445 		while (i++ < 120) {
11446 			if (vpip->state == VPI_STATE_OFFLINE) {
11447 				break;
11448 			}
11449 
11450 			mutex_exit(&EMLXS_FCF_LOCK);
11451 			BUSYWAIT_MS(1000);
11452 			mutex_enter(&EMLXS_FCF_LOCK);
11453 		}
11454 
11455 		if (i >= 120) {
11456 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11457 			    "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d "
11458 			    "rpi_online=%d,%d. Offline timeout.",
11459 			    vpip->VPI,
11460 			    emlxs_vpi_state_xlate(vpip->state),
11461 			    fcfp->fcf_index,
11462 			    vfip->VFI,
11463 			    vpip->rpi_online, vpip->rpi_paused);
11464 		}
11465 	}
11466 
11467 	vpip->flag &= ~EMLXS_VPI_PORT_UNBIND;
11468 
11469 	mutex_exit(&EMLXS_FCF_LOCK);
11470 
11471 	return (rval);
11472 
11473 } /* emlxs_vpi_port_unbind_notify() */
11474 
11475 
11476 /*ARGSUSED*/
11477 static uint32_t
emlxs_vpi_rpi_offline_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11478 emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
11479     uint32_t evt, void *arg1)
11480 {
11481 	uint32_t rval = 0;
11482 	RPIobj_t *rpip = (RPIobj_t *)arg1;
11483 
11484 	if (evt != FCF_EVENT_RPI_OFFLINE) {
11485 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11486 		    "vpi_rpi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
11487 		    "Invalid event type. <",
11488 		    vpip->VPI,
11489 		    emlxs_vpi_state_xlate(vpip->state),
11490 		    emlxs_fcf_event_xlate(evt), arg1,
11491 		    vpip->flag);
11492 		return (1);
11493 	}
11494 
11495 	switch (vpip->state) {
11496 	case VPI_STATE_LOGO:
11497 		/* rpi_online will be checked when LOGO is complete */
11498 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11499 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11500 		    "rpi=%d. Waiting for LOGO. <",
11501 		    vpip->VPI,
11502 		    vpip->rpi_online, vpip->rpi_paused,
11503 		    rpip->did, rpip->RPI);
11504 
11505 		rval = 0;
11506 		break;
11507 
11508 	case VPI_STATE_PORT_OFFLINE:
11509 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11510 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11511 		    "rpi=%d.",
11512 		    vpip->VPI,
11513 		    vpip->rpi_online, vpip->rpi_paused,
11514 		    rpip->did, rpip->RPI);
11515 
11516 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
11517 		    FCF_REASON_REENTER, evt, arg1);
11518 		break;
11519 
11520 	case VPI_STATE_PAUSED:
11521 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11522 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11523 		    "rpi=%d. VPI paused. <",
11524 		    vpip->VPI,
11525 		    vpip->rpi_online, vpip->rpi_paused,
11526 		    rpip->did, rpip->RPI);
11527 
11528 		rval = 0;
11529 		break;
11530 
11531 	case VPI_STATE_ONLINE:
11532 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11533 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11534 		    "rpi=%d. <",
11535 		    vpip->VPI,
11536 		    vpip->rpi_online, vpip->rpi_paused,
11537 		    rpip->did, rpip->RPI);
11538 
11539 		rval = 0;
11540 		break;
11541 
11542 	default:
11543 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11544 		    "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11545 		    "rpi=%d. "
11546 		    "Invalid state. <",
11547 		    vpip->VPI,
11548 		    vpip->rpi_online, vpip->rpi_paused,
11549 		    rpip->did, rpip->RPI);
11550 
11551 		rval = 1;
11552 		break;
11553 	}
11554 
11555 	return (rval);
11556 
11557 } /* emlxs_vpi_rpi_offline_evt_action() */
11558 
11559 
11560 /*ARGSUSED*/
11561 static uint32_t
emlxs_vpi_rpi_pause_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11562 emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
11563     uint32_t evt, void *arg1)
11564 {
11565 	uint32_t rval = 0;
11566 	RPIobj_t *rpip = (RPIobj_t *)arg1;
11567 
11568 	if (evt != FCF_EVENT_RPI_PAUSE) {
11569 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11570 		    "vpi_rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
11571 		    "Invalid event type. <",
11572 		    vpip->VPI,
11573 		    emlxs_vpi_state_xlate(vpip->state),
11574 		    emlxs_fcf_event_xlate(evt), arg1,
11575 		    vpip->flag);
11576 		return (1);
11577 	}
11578 
11579 	switch (vpip->state) {
11580 	case VPI_STATE_LOGO:
11581 		/* rpi_online will be checked when LOGO is complete */
11582 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11583 		    "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
11584 		    "rpi=%d. Waiting for LOGO. <",
11585 		    vpip->VPI,
11586 		    vpip->rpi_online, vpip->rpi_paused,
11587 		    rpip->did, rpip->RPI);
11588 
11589 		rval = 0;
11590 		break;
11591 
11592 	case VPI_STATE_PORT_OFFLINE:
11593 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11594 		    "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
11595 		    "rpi=%d.",
11596 		    vpip->VPI,
11597 		    vpip->rpi_online, vpip->rpi_paused,
11598 		    rpip->did, rpip->RPI);
11599 
11600 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
11601 		    FCF_REASON_REENTER, 0, 0);
11602 		break;
11603 
11604 	case VPI_STATE_PAUSED:
11605 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11606 		    "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
11607 		    "rpi=%d. VPI already paused. <",
11608 		    vpip->VPI,
11609 		    vpip->rpi_online, vpip->rpi_paused,
11610 		    rpip->did, rpip->RPI);
11611 
11612 		rval = 0;
11613 		break;
11614 
11615 	default:
11616 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11617 		    "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
11618 		    "rpi=%d. "
11619 		    "Invalid state. <",
11620 		    vpip->VPI,
11621 		    vpip->rpi_online, vpip->rpi_paused,
11622 		    rpip->did, rpip->RPI);
11623 
11624 		rval = 1;
11625 		break;
11626 	}
11627 
11628 	return (rval);
11629 
11630 } /* emlxs_vpi_rpi_pause_evt_action() */
11631 
11632 
11633 /*ARGSUSED*/
11634 static uint32_t
emlxs_vpi_rpi_online_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11635 emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
11636     uint32_t evt, void *arg1)
11637 {
11638 	RPIobj_t *rpip = (RPIobj_t *)arg1;
11639 
11640 	if (evt != FCF_EVENT_RPI_ONLINE) {
11641 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11642 		    "vpi_rpi_online_evt_action:%d %s:%s arg=%p flag=%x. "
11643 		    "Invalid event type. <",
11644 		    vpip->VPI,
11645 		    emlxs_vpi_state_xlate(vpip->state),
11646 		    emlxs_fcf_event_xlate(evt), arg1,
11647 		    vpip->flag);
11648 		return (1);
11649 	}
11650 
11651 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11652 	    "vpi_rpi_online_evt_action:%d rpi_online=%d,%d did=%x rpi=%d. <",
11653 	    vpip->VPI,
11654 	    vpip->rpi_online, vpip->rpi_paused,
11655 	    rpip->did, rpip->RPI);
11656 
11657 	return (0);
11658 
11659 } /* emlxs_vpi_rpi_online_evt_action() */
11660 
11661 
11662 /*ARGSUSED*/
11663 static uint32_t
emlxs_vpi_online_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11664 emlxs_vpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11665     void *arg1)
11666 {
11667 	uint32_t rval = 0;
11668 
11669 	if (evt != FCF_EVENT_VPI_ONLINE) {
11670 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11671 		    "vpi_online_evt_action:%d %s:%s arg=%p flag=%x. "
11672 		    "Invalid event type. <",
11673 		    vpip->VPI,
11674 		    emlxs_vpi_state_xlate(vpip->state),
11675 		    emlxs_fcf_event_xlate(evt), arg1,
11676 		    vpip->flag);
11677 		return (1);
11678 	}
11679 
11680 	if (vpip->flag & EMLXS_VPI_ONLINE_REQ) {
11681 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11682 		    "vpi_online_evt_action:%d flag=%x. "
11683 		    "Online already requested. <",
11684 		    vpip->VPI,
11685 		    vpip->flag);
11686 		return (1);
11687 	}
11688 
11689 	vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11690 	vpip->flag |= EMLXS_VPI_ONLINE_REQ;
11691 
11692 	switch (vpip->state) {
11693 	case VPI_STATE_OFFLINE:
11694 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11695 		    "vpi_online_evt_action:%d flag=%x. Initiating online.",
11696 		    vpip->VPI,
11697 		    vpip->flag);
11698 
11699 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
11700 		    FCF_REASON_EVENT, evt, arg1);
11701 		break;
11702 
11703 	case VPI_STATE_PORT_OFFLINE:
11704 	case VPI_STATE_PAUSED:
11705 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11706 		    "vpi_online_evt_action:%d flag=%x. Initiating online.",
11707 		    vpip->VPI,
11708 		    vpip->flag);
11709 
11710 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
11711 		    FCF_REASON_EVENT, evt, arg1);
11712 		break;
11713 
11714 	default:
11715 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11716 		    "vpi_online_evt_action:%d flag=%x. <",
11717 		    vpip->VPI,
11718 		    vpip->flag);
11719 		return (1);
11720 	}
11721 
11722 	return (rval);
11723 
11724 } /* emlxs_vpi_online_evt_action() */
11725 
11726 
11727 /*ARGSUSED*/
11728 static uint32_t
emlxs_vpi_offline_handler(emlxs_port_t * port,VPIobj_t * vpip,void * arg1)11729 emlxs_vpi_offline_handler(emlxs_port_t *port, VPIobj_t *vpip, void *arg1)
11730 {
11731 	uint32_t rval = 0;
11732 
11733 	if (!(vpip->flag & EMLXS_VPI_OFFLINE_REQ)) {
11734 		return (0);
11735 	}
11736 
11737 	if (vpip->flag & EMLXS_VPI_PORT_ONLINE) {
11738 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
11739 		    FCF_REASON_REQUESTED, 0, arg1);
11740 
11741 	} else if (vpip->flag & EMLXS_VPI_LOGI) {
11742 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
11743 		    FCF_REASON_REQUESTED, 0, arg1);
11744 
11745 	} else if (vpip->flag & EMLXS_VPI_REG) {
11746 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
11747 		    FCF_REASON_REQUESTED, 0, arg1);
11748 
11749 	} else if (vpip->flag & EMLXS_VPI_INIT) {
11750 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
11751 		    FCF_REASON_REQUESTED, 0, arg1);
11752 
11753 	} else {
11754 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
11755 		    FCF_REASON_REQUESTED, 0, arg1);
11756 	}
11757 
11758 	return (rval);
11759 
11760 } /* emlxs_vpi_offline_handler() */
11761 
11762 
11763 /*ARGSUSED*/
11764 static uint32_t
emlxs_vpi_offline_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11765 emlxs_vpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11766     void *arg1)
11767 {
11768 	uint32_t rval = 0;
11769 	uint32_t pause_req;
11770 
11771 	if (evt != FCF_EVENT_VPI_OFFLINE) {
11772 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11773 		    "vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
11774 		    "Invalid event type. <",
11775 		    vpip->VPI,
11776 		    emlxs_vpi_state_xlate(vpip->state),
11777 		    emlxs_fcf_event_xlate(evt), arg1,
11778 		    vpip->flag);
11779 		return (1);
11780 	}
11781 
11782 	if ((vpip->flag & EMLXS_VPI_OFFLINE_REQ) &&
11783 	    !(vpip->flag & EMLXS_VPI_PAUSE_REQ)) {
11784 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11785 		    "vpi_offline_evt_action:%d flag=%x. "
11786 		    "Offline already requested. <",
11787 		    vpip->VPI,
11788 		    vpip->flag);
11789 		return (1);
11790 	}
11791 
11792 	pause_req = vpip->flag & EMLXS_VPI_PAUSE_REQ;
11793 
11794 	vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11795 	vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
11796 
11797 	switch (vpip->state) {
11798 	case VPI_STATE_PORT_OFFLINE:
11799 		if (pause_req || vpip->rpi_paused) {
11800 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11801 			    "vpi_offline_evt_action:%d flag=%x. Clear nodes.",
11802 			    vpip->VPI,
11803 			    vpip->flag);
11804 
11805 			vpip->flag |= EMLXS_VPI_PORT_ONLINE;
11806 
11807 			rval = emlxs_vpi_state(port, vpip,
11808 			    VPI_STATE_PORT_OFFLINE, FCF_REASON_REENTER, evt,
11809 			    arg1);
11810 
11811 			break;
11812 		}
11813 
11814 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11815 		    "vpi_offline_evt_action:%d flag=%x. Handling offline.",
11816 		    vpip->VPI,
11817 		    vpip->flag);
11818 
11819 		/* Handle offline now */
11820 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11821 		break;
11822 
11823 	case VPI_STATE_PAUSED:
11824 		if (vpip->rpi_paused) {
11825 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11826 			    "vpi_offline_evt_action:%d flag=%x. Clear nodes.",
11827 			    vpip->VPI,
11828 			    vpip->flag);
11829 
11830 			vpip->flag |= EMLXS_VPI_PORT_ONLINE;
11831 
11832 			rval = emlxs_vpi_state(port, vpip,
11833 			    VPI_STATE_PORT_OFFLINE, FCF_REASON_EVENT, evt,
11834 			    arg1);
11835 
11836 			break;
11837 		}
11838 
11839 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11840 		    "vpi_offline_evt_action:%d flag=%x. Handling offline.",
11841 		    vpip->VPI,
11842 		    vpip->flag);
11843 
11844 		/* Handle offline now */
11845 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11846 		break;
11847 
11848 	/* wait states */
11849 	case VPI_STATE_UNREG:
11850 	case VPI_STATE_PORT_ONLINE:
11851 	case VPI_STATE_LOGI:
11852 	case VPI_STATE_INIT:
11853 	case VPI_STATE_REG:
11854 	case VPI_STATE_ONLINE:
11855 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11856 		    "vpi_offline_evt_action:%d flag=%x. Handling offline.",
11857 		    vpip->VPI,
11858 		    vpip->flag);
11859 
11860 		/* Handle offline now */
11861 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11862 		break;
11863 
11864 	/* Transitional states */
11865 	default:
11866 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11867 		    "vpi_offline_evt_action:%d flag=%x. <",
11868 		    vpip->VPI,
11869 		    vpip->flag);
11870 		break;
11871 	}
11872 
11873 	return (rval);
11874 
11875 } /* emlxs_vpi_offline_evt_action() */
11876 
11877 
11878 /*ARGSUSED*/
11879 static uint32_t
emlxs_vpi_pause_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11880 emlxs_vpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11881     void *arg1)
11882 {
11883 	emlxs_hba_t *hba = HBA;
11884 	uint32_t rval = 0;
11885 
11886 	if (evt != FCF_EVENT_VPI_PAUSE) {
11887 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11888 		    "vpi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
11889 		    "Invalid event type. <",
11890 		    vpip->VPI,
11891 		    emlxs_vpi_state_xlate(vpip->state),
11892 		    emlxs_fcf_event_xlate(evt), arg1,
11893 		    vpip->flag);
11894 		return (1);
11895 	}
11896 
11897 	if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
11898 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11899 		    "vpi_pause_evt_action:%d flag=%x. "
11900 		    "Pause already requested. <",
11901 		    vpip->VPI,
11902 		    vpip->flag);
11903 		return (1);
11904 	}
11905 
11906 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
11907 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11908 		    "vpi_pause_evt_action:%d flag=%x. "
11909 		    "Offline already requested. <",
11910 		    vpip->VPI,
11911 		    vpip->flag);
11912 		return (1);
11913 	}
11914 
11915 	if (SLI4_FC_MODE || !(hba->sli.sli4.flag & EMLXS_SLI4_DOWN_LINK)) {
11916 		/* Fabric logo is implied */
11917 		emlxs_vpi_logo_handler(port, vpip);
11918 	}
11919 
11920 	switch (vpip->state) {
11921 	case VPI_STATE_PORT_OFFLINE:
11922 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11923 		    "vpi_pause_evt_action:%d flag=%x. "
11924 		    "Already offline. <",
11925 		    vpip->VPI,
11926 		    vpip->flag);
11927 		break;
11928 
11929 	case VPI_STATE_PAUSED:
11930 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11931 		    "vpi_pause_evt_action:%d flag=%x. "
11932 		    "Already paused. <",
11933 		    vpip->VPI,
11934 		    vpip->flag);
11935 		break;
11936 
11937 	/* Wait states */
11938 	case VPI_STATE_UNREG:
11939 	case VPI_STATE_PORT_ONLINE:
11940 	case VPI_STATE_LOGI:
11941 	case VPI_STATE_INIT:
11942 	case VPI_STATE_REG:
11943 	case VPI_STATE_ONLINE:
11944 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11945 		vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
11946 
11947 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11948 		    "vpi_pause_evt_action:%d flag=%x. Handling offline.",
11949 		    vpip->VPI,
11950 		    vpip->flag);
11951 
11952 		/* Handle offline now */
11953 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11954 		break;
11955 
11956 	/* Transitional states */
11957 	default:
11958 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11959 		vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
11960 
11961 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11962 		    "vpi_pause_evt_action:%d flag=%x. <",
11963 		    vpip->VPI,
11964 		    vpip->flag);
11965 		break;
11966 	}
11967 
11968 	return (rval);
11969 
11970 } /* emlxs_vpi_pause_evt_action() */
11971 
11972 
11973 /* ARGSUSED */
11974 static void
emlxs_deferred_cmpl_thread(emlxs_hba_t * hba,void * arg1,void * arg2)11975 emlxs_deferred_cmpl_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
11976 {
11977 	emlxs_deferred_cmpl_t *cmpl = (emlxs_deferred_cmpl_t *)arg1;
11978 	uint32_t status = (uint32_t)((unsigned long)arg2);
11979 	emlxs_port_t *port;
11980 	uint32_t mbxStatus;
11981 	emlxs_buf_t *sbp;
11982 	fc_unsol_buf_t *ubp;
11983 	IOCBQ *iocbq;
11984 
11985 	mbxStatus = (status)? MBX_FAILURE:MBX_SUCCESS;
11986 
11987 	port = cmpl->port;
11988 	sbp = (emlxs_buf_t *)cmpl->arg1;
11989 	ubp = (fc_unsol_buf_t *)cmpl->arg2;
11990 	iocbq = (IOCBQ *)cmpl->arg3;
11991 
11992 	kmem_free(cmpl, sizeof (emlxs_deferred_cmpl_t));
11993 
11994 	emlxs_mb_deferred_cmpl(port, mbxStatus, sbp, ubp, iocbq);
11995 
11996 	return;
11997 
11998 } /* emlxs_deferred_cmpl_thread() */
11999 
12000 
12001 
12002 
12003 /* ARGSUSED */
12004 static void
emlxs_port_offline_thread(emlxs_hba_t * hba,void * arg1,void * arg2)12005 emlxs_port_offline_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
12006 {
12007 	emlxs_port_t *port = (emlxs_port_t *)arg1;
12008 	uint32_t scope = (uint32_t)((unsigned long)arg2);
12009 
12010 	(void) emlxs_port_offline(port, scope);
12011 	return;
12012 
12013 } /* emlxs_port_offline_thread() */
12014 
12015 
12016 /* ARGSUSED */
12017 static void
emlxs_port_online_thread(emlxs_hba_t * hba,void * arg1,void * arg2)12018 emlxs_port_online_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
12019 {
12020 	emlxs_port_t *port = (emlxs_port_t *)arg1;
12021 
12022 	(void) emlxs_port_online(port);
12023 	return;
12024 
12025 } /* emlxs_port_online_thread() */
12026 
12027 
12028 /*ARGSUSED*/
12029 static void
emlxs_vpi_logo_handler(emlxs_port_t * port,VPIobj_t * vpip)12030 emlxs_vpi_logo_handler(emlxs_port_t *port, VPIobj_t *vpip)
12031 {
12032 	vpip->flag &= ~EMLXS_VPI_LOGI;
12033 	if (vpip->flag & EMLXS_VPI_VFI_LOGI) {
12034 		vpip->flag &= ~EMLXS_VPI_VFI_LOGI;
12035 		if (vpip->vfip == NULL) {
12036 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12037 			    "emlxs_vpi_logo_handler: invalid state "
12038 			    "(vpip->vfip == NULL), vpip=%p", vpip);
12039 			return;
12040 		}
12041 		if (vpip->vfip->logi_count) {
12042 			vpip->vfip->logi_count--;
12043 		}
12044 		if (vpip == vpip->vfip->flogi_vpip) {
12045 			vpip->vfip->flogi_vpip = NULL;
12046 		}
12047 	}
12048 } /* emlxs_vpi_logo_handler() */
12049 
12050 
12051 /*ARGSUSED*/
12052 static uint32_t
emlxs_vpi_port_offline_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12053 emlxs_vpi_port_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12054     void *arg1)
12055 {
12056 	emlxs_hba_t *hba = HBA;
12057 	uint32_t rval = 0;
12058 	uint32_t scope;
12059 
12060 	if (vpip->state != VPI_STATE_PORT_OFFLINE) {
12061 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12062 		    "vpi_port_offline_action:%d %s:%s arg=%p. "
12063 		    "Invalid state. <",
12064 		    vpip->VPI,
12065 		    emlxs_vpi_state_xlate(vpip->state),
12066 		    emlxs_fcf_event_xlate(evt), arg1);
12067 		return (1);
12068 	}
12069 
12070 	if (vpip->flag & EMLXS_VPI_PORT_ONLINE) {
12071 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12072 		    "vpi_port_offline_action:%d flag=%x. Offlining port...",
12073 		    vpip->VPI,
12074 		    vpip->flag);
12075 
12076 		vpip->flag &= ~(EMLXS_VPI_PORT_ONLINE|EMLXS_VPI_PORT_ENABLED);
12077 
12078 		if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
12079 			scope = 0xFFFFFFFF; /* Clear all non-FCP2 nodes */
12080 					    /* Pause FCP2 nodes */
12081 		} else {
12082 			scope = 0xFDFFFFFF; /* Clear all nodes */
12083 		}
12084 
12085 		emlxs_thread_spawn(hba, emlxs_port_offline_thread,
12086 		    (void *)vpip->port, (void *)((unsigned long)scope));
12087 
12088 		if (vpip->flag & EMLXS_VPI_LOGI) {
12089 			rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
12090 			    FCF_REASON_EVENT, evt, arg1);
12091 
12092 			return (rval);
12093 		}
12094 	}
12095 
12096 	if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
12097 		if (vpip->rpi_online > vpip->rpi_paused) {
12098 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12099 			    "vpi_port_offline_action:%d rpi_online=%d,%d. "
12100 			    "Pausing. Waiting for RPI's. <",
12101 			    vpip->VPI,
12102 			    vpip->rpi_online, vpip->rpi_paused);
12103 			return (0);
12104 		}
12105 
12106 		/* Take the Fabric RPI offline now */
12107 		if (vpip->fabric_rpip->state != RPI_STATE_FREE) {
12108 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12109 			    "vpi_port_offline_action:%d. "
12110 			    "Offlining Fabric RPI. >",
12111 			    vpip->VPI);
12112 
12113 			(void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
12114 			    vpip->fabric_rpip);
12115 		}
12116 
12117 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12118 		    "vpi_port_offline_action:%d rpi_online=%d,%d. Pausing.",
12119 		    vpip->VPI,
12120 		    vpip->rpi_online, vpip->rpi_paused);
12121 
12122 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED,
12123 		    FCF_REASON_EVENT, evt, arg1);
12124 
12125 		return (rval);
12126 	}
12127 
12128 	if (vpip->rpi_online > 0) {
12129 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12130 		    "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. "
12131 		    "Waiting for RPI's. <",
12132 		    vpip->VPI,
12133 		    vpip->rpi_online, vpip->rpi_paused);
12134 
12135 		return (0);
12136 	}
12137 
12138 	/* Take the Fabric RPI offline now */
12139 	if (vpip->fabric_rpip->state != RPI_STATE_FREE) {
12140 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12141 		    "vpi_port_offline_action:%d. Offlining Fabric RPI. >",
12142 		    vpip->VPI);
12143 
12144 		(void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
12145 		    vpip->fabric_rpip);
12146 	}
12147 
12148 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12149 	    "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. "
12150 	    "Unreg VPI.",
12151 	    vpip->VPI,
12152 	    vpip->rpi_online, vpip->rpi_paused);
12153 
12154 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
12155 	    FCF_REASON_EVENT, evt, arg1);
12156 
12157 	return (rval);
12158 
12159 } /* emlxs_vpi_port_offline_action() */
12160 
12161 
12162 /*ARGSUSED*/
12163 static uint32_t
emlxs_vpi_paused_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12164 emlxs_vpi_paused_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12165     void *arg1)
12166 {
12167 	if (vpip->state != VPI_STATE_PAUSED) {
12168 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12169 		    "vpi_paused_action:%d %s:%s arg=%p. "
12170 		    "Invalid state. <",
12171 		    vpip->VPI,
12172 		    emlxs_vpi_state_xlate(vpip->state),
12173 		    emlxs_fcf_event_xlate(evt), arg1);
12174 		return (1);
12175 	}
12176 
12177 	vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
12178 
12179 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12180 	    "vpi_paused_action:%d rpi_online=%d,%d. VPI paused. <",
12181 	    vpip->VPI,
12182 	    vpip->rpi_online, vpip->rpi_paused);
12183 
12184 	return (0);
12185 
12186 } /* emlxs_vpi_paused_action() */
12187 
12188 
12189 /*ARGSUSED*/
12190 static uint32_t
emlxs_vpi_offline_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12191 emlxs_vpi_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12192     void *arg1)
12193 {
12194 	uint32_t rval = 0;
12195 
12196 	if (vpip->state != VPI_STATE_OFFLINE) {
12197 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12198 		    "vpi_offline_action:%d %s:%s arg=%p. "
12199 		    "Invalid state. <",
12200 		    vpip->VPI,
12201 		    emlxs_vpi_state_xlate(vpip->state),
12202 		    emlxs_fcf_event_xlate(evt), arg1);
12203 		return (1);
12204 	}
12205 
12206 	if (!vpip->vfip) {
12207 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12208 		    "vpi_offline_action:%d %s:%s arg=%p flag=%x. "
12209 		    "Null vfip found. <",
12210 		    vpip->VPI,
12211 		    emlxs_vpi_state_xlate(vpip->state),
12212 		    emlxs_fcf_event_xlate(evt), arg1,
12213 		    vpip->flag);
12214 		return (1);
12215 	}
12216 
12217 	/* Take the Fabric RPI offline, if still active */
12218 	if (vpip->fabric_rpip->state != RPI_STATE_FREE) {
12219 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12220 		    "vpi_offline_action:%d. Offlining Fabric RPI. >",
12221 		    vpip->VPI);
12222 
12223 		(void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
12224 		    vpip->fabric_rpip);
12225 	}
12226 
12227 	vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
12228 
12229 	if (vpip->flag & EMLXS_VPI_VFI) {
12230 		vpip->flag &= ~EMLXS_VPI_VFI;
12231 
12232 		if (vpip->vfip->vpi_online) {
12233 			vpip->vfip->vpi_online--;
12234 		}
12235 	}
12236 
12237 	/* Check if online was requested */
12238 	if (vpip->flag & EMLXS_VPI_ONLINE_REQ) {
12239 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12240 		    "vpi_offline_action:%d vpi_online=%d. Online requested.",
12241 		    vpip->VPI,
12242 		    vpip->vfip->vpi_online);
12243 
12244 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
12245 		    FCF_REASON_REQUESTED, 0, arg1);
12246 		return (rval);
12247 	}
12248 
12249 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12250 	    "vpi_offline_action:%d vpi_online=%d. "
12251 	    "VPI offline. Notifying VFI:%d. >",
12252 	    vpip->VPI,
12253 	    vpip->vfip->vpi_online,
12254 	    vpip->vfip->VFI);
12255 
12256 	/* Notify VFI */
12257 	rval = emlxs_vfi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
12258 
12259 	return (rval);
12260 
12261 } /* emlxs_vpi_offline_action() */
12262 
12263 
12264 /*ARGSUSED*/
12265 static uint32_t
emlxs_vpi_init_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)12266 emlxs_vpi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
12267 {
12268 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
12269 	VPIobj_t *vpip;
12270 	MAILBOX4 *mb4;
12271 
12272 	vpip = (VPIobj_t *)mbq->context;
12273 	mb4 = (MAILBOX4 *)mbq;
12274 
12275 	mutex_enter(&EMLXS_FCF_LOCK);
12276 
12277 	if (vpip->state != VPI_STATE_INIT) {
12278 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12279 		    "vpi_init_mbcmpl:%d %s.",
12280 		    vpip->VPI,
12281 		    emlxs_vpi_state_xlate(vpip->state));
12282 
12283 		mutex_exit(&EMLXS_FCF_LOCK);
12284 		return (0);
12285 	}
12286 
12287 	if (mb4->mbxStatus) {
12288 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12289 		    "vpi_init_mbcmpl:%d failed. %s. >",
12290 		    vpip->VPI,
12291 		    emlxs_mb_xlate_status(mb4->mbxStatus));
12292 
12293 		(void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED,
12294 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
12295 
12296 		mutex_exit(&EMLXS_FCF_LOCK);
12297 		return (0);
12298 	}
12299 
12300 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12301 	    "vpi_init_mbcmpl:%d. Init complete. >",
12302 	    vpip->VPI,
12303 	    mb4->mbxStatus);
12304 
12305 	vpip->flag |= EMLXS_VPI_INIT;
12306 	(void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL,
12307 	    0, 0, 0);
12308 
12309 	mutex_exit(&EMLXS_FCF_LOCK);
12310 	return (0);
12311 
12312 } /* emlxs_vpi_init_mbcmpl() */
12313 
12314 
12315 /*ARGSUSED*/
12316 static uint32_t
emlxs_vpi_init_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12317 emlxs_vpi_init_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12318     void *arg1)
12319 {
12320 	emlxs_hba_t *hba = HBA;
12321 	MAILBOXQ *mbq;
12322 	MAILBOX4 *mb4;
12323 	uint32_t rval = 0;
12324 
12325 	if (vpip->state != VPI_STATE_INIT) {
12326 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12327 		    "vpi_init_action:%d %s:%s arg=%p. "
12328 		    "Invalid state. <",
12329 		    vpip->VPI,
12330 		    emlxs_vpi_state_xlate(vpip->state),
12331 		    emlxs_fcf_event_xlate(evt), arg1);
12332 		return (1);
12333 	}
12334 
12335 	if (vpip->prev_state != VPI_STATE_INIT_FAILED) {
12336 		vpip->attempts = 0;
12337 	}
12338 
12339 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
12340 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12341 		    "vpi_init_action:%d attempts=%d. Offline requested.",
12342 		    vpip->VPI,
12343 		    vpip->attempts);
12344 
12345 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12346 		return (rval);
12347 	}
12348 
12349 	if (!(vpip->flag & EMLXS_VPI_VFI)) {
12350 		vpip->flag |= EMLXS_VPI_VFI;
12351 		vpip->vfip->vpi_online++;
12352 	}
12353 
12354 	if (((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) ==
12355 	    SLI_INTF_IF_TYPE_0) && (vpip->vfip->vpi_online == 1)) {
12356 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12357 		    "vpi_init_action:%d. First VPI. Skipping INIT_VPI.",
12358 		    vpip->VPI);
12359 
12360 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
12361 		    FCF_REASON_EVENT, evt, arg1);
12362 		return (rval);
12363 	}
12364 
12365 	if (vpip->flag & EMLXS_VPI_INIT) {
12366 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12367 		    "vpi_init_action:%d flag=%x. "
12368 		    "Already init'd. Skipping INIT_VPI.",
12369 		    vpip->VPI);
12370 
12371 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
12372 		    FCF_REASON_EVENT, evt, arg1);
12373 		return (rval);
12374 	}
12375 
12376 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12377 	    "vpi_init_action:%d vpi_online=%d attempts=%d. Sending INIT_VPI. <",
12378 	    vpip->VPI,
12379 	    vpip->vfip->vpi_online,
12380 	    vpip->attempts);
12381 
12382 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
12383 		rval = emlxs_vpi_state(port, vpip, FCFI_STATE_REG_FAILED,
12384 		    FCF_REASON_NO_MBOX, 0, arg1);
12385 		return (rval);
12386 	}
12387 	mb4 = (MAILBOX4*)mbq;
12388 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
12389 
12390 	mbq->nonembed = NULL;
12391 	mbq->mbox_cmpl = emlxs_vpi_init_mbcmpl;
12392 	mbq->context = (void *)vpip;
12393 	mbq->port = (void *)port;
12394 
12395 	mb4->mbxCommand = MBX_INIT_VPI;
12396 	mb4->mbxOwner = OWN_HOST;
12397 	mb4->un.varInitVPI4.vfi = vpip->vfip->VFI;
12398 	mb4->un.varInitVPI4.vpi = vpip->VPI;
12399 
12400 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
12401 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
12402 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
12403 
12404 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED,
12405 		    FCF_REASON_SEND_FAILED, rval, arg1);
12406 
12407 		return (rval);
12408 	}
12409 
12410 	return (0);
12411 
12412 } /* emlxs_vpi_init_action() */
12413 
12414 
12415 /*ARGSUSED*/
12416 static uint32_t
emlxs_vpi_init_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12417 emlxs_vpi_init_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12418     void *arg1)
12419 {
12420 	uint32_t rval = 0;
12421 
12422 	vpip->attempts++;
12423 
12424 	if (vpip->state != VPI_STATE_INIT_FAILED) {
12425 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12426 		    "vpi_init_action:%d %s:%s arg=%p attempt=%d. "
12427 		    "Invalid state. <",
12428 		    vpip->VPI,
12429 		    emlxs_vpi_state_xlate(vpip->state),
12430 		    emlxs_fcf_event_xlate(evt), arg1,
12431 		    vpip->attempts);
12432 		return (1);
12433 	}
12434 
12435 	if ((vpip->reason == FCF_REASON_SEND_FAILED) ||
12436 	    (vpip->attempts >= 3)) {
12437 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12438 		    "vpi_init_action:%d attempt=%d reason=%x. Init cmpl.",
12439 		    vpip->VPI,
12440 		    vpip->attempts,
12441 		    vpip->reason);
12442 
12443 		vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
12444 
12445 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
12446 		vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
12447 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL,
12448 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
12449 	} else {
12450 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12451 		    "vpi_init_action:%d attempt=%d. Initializing.",
12452 		    vpip->VPI,
12453 		    vpip->attempts);
12454 
12455 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
12456 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
12457 	}
12458 
12459 	return (rval);
12460 
12461 } /* emlxs_vpi_init_failed_action() */
12462 
12463 
12464 /*ARGSUSED*/
12465 static uint32_t
emlxs_vpi_init_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12466 emlxs_vpi_init_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12467     void *arg1)
12468 {
12469 	uint32_t rval = 0;
12470 
12471 	if (vpip->state != VPI_STATE_INIT_CMPL) {
12472 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12473 		    "vpi_init_cmpl_action:%d %s:%s arg=%p. "
12474 		    "Invalid state. <",
12475 		    vpip->VPI,
12476 		    emlxs_vpi_state_xlate(vpip->state),
12477 		    emlxs_fcf_event_xlate(evt), arg1);
12478 		return (1);
12479 	}
12480 
12481 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12482 	    "vpi_init_cmpl_action:%d attempts=%d. Onlining port.",
12483 	    vpip->VPI,
12484 	    vpip->attempts);
12485 
12486 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
12487 	    FCF_REASON_EVENT, evt, arg1);
12488 	return (rval);
12489 
12490 } /* emlxs_vpi_init_cmpl_action() */
12491 
12492 
12493 /*ARGSUSED*/
12494 static uint32_t
emlxs_vpi_port_online_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12495 emlxs_vpi_port_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12496     void *arg1)
12497 {
12498 	emlxs_hba_t *hba = HBA;
12499 	emlxs_config_t *cfg = &CFG;
12500 	uint32_t rval = 0;
12501 
12502 	if (vpip->state != VPI_STATE_PORT_ONLINE) {
12503 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12504 		    "vpi_port_online_action:%d %s:%s arg=%p. "
12505 		    "Invalid state. <",
12506 		    vpip->VPI,
12507 		    emlxs_vpi_state_xlate(vpip->state),
12508 		    emlxs_fcf_event_xlate(evt), arg1);
12509 		return (1);
12510 	}
12511 
12512 	if (vpip->flag & EMLXS_VPI_PORT_ONLINE) {
12513 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12514 		    "vpi_port_online_action:%d. Port already online.",
12515 		    vpip->VPI);
12516 	}
12517 
12518 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
12519 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12520 		    "vpi_port_online_action:%d. Offline requested.",
12521 		    vpip->VPI);
12522 
12523 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12524 		return (rval);
12525 	}
12526 
12527 	/* Initialize the Fabric RPI */
12528 	if (vpip->fabric_rpip->state == RPI_STATE_FREE) {
12529 		emlxs_rpi_alloc_fabric_rpi(vpip->port);
12530 	}
12531 
12532 	/* Notify ULP */
12533 	vpip->flag |= EMLXS_VPI_PORT_ONLINE;
12534 
12535 	if (hba->flag & FC_LOOPBACK_MODE) {
12536 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12537 		    "vpi_port_online_action:%d. Loopback mode. "
12538 		    "Registering VPI.",
12539 		    vpip->VPI);
12540 
12541 		if (hba->topology != TOPOLOGY_LOOP) {
12542 			port->did = 1;
12543 		}
12544 
12545 		vpip->vfip->flogi_vpip = vpip;
12546 
12547 		bcopy((void *)&vpip->port->sparam,
12548 		    (void *)&vpip->fabric_rpip->sparam,
12549 		    sizeof (SERV_PARM));
12550 
12551 		/* Update the VPI Fabric RPI */
12552 		vpip->fabric_rpip->sparam.cmn.w2.r_a_tov =
12553 		    LE_SWAP32((FF_DEF_RATOV * 1000));
12554 
12555 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
12556 		    FCF_REASON_EVENT, evt, arg1);
12557 
12558 		return (rval);
12559 	}
12560 
12561 	if ((hba->topology == TOPOLOGY_LOOP) && ! (port->did)) {
12562 		port->did = port->granted_alpa;
12563 	}
12564 
12565 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12566 	    "vpi_port_online_action:%d vpi_online=%d. Onlining port... <",
12567 	    vpip->VPI,
12568 	    vpip->vfip->vpi_online);
12569 
12570 	if (SLI4_FC_MODE && (port->vpi == 0)) {
12571 		mutex_enter(&EMLXS_PORT_LOCK);
12572 		hba->linkup_timer = hba->timer_tics +
12573 		    cfg[CFG_LINKUP_TIMEOUT].current;
12574 		mutex_exit(&EMLXS_PORT_LOCK);
12575 	} else {
12576 		emlxs_thread_spawn(hba, emlxs_port_online_thread,
12577 		    (void *)vpip->port, 0);
12578 	}
12579 
12580 	/* Wait for emlxs_vpi_logi_notify() */
12581 
12582 	return (0);
12583 
12584 } /* emlxs_vpi_port_online_action() */
12585 
12586 
12587 extern uint32_t
emlxs_vpi_logi_notify(emlxs_port_t * port,emlxs_buf_t * sbp)12588 emlxs_vpi_logi_notify(emlxs_port_t *port, emlxs_buf_t *sbp)
12589 {
12590 	VPIobj_t *vpip = port->vpip;
12591 	emlxs_hba_t *hba = HBA;
12592 	uint32_t rval = 0;
12593 
12594 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
12595 		return (1);
12596 	}
12597 
12598 	mutex_enter(&EMLXS_FCF_LOCK);
12599 
12600 	if (vpip->state == VPI_STATE_OFFLINE) {
12601 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12602 		    "vpi_logi_notify:%d %s.",
12603 		    vpip->VPI,
12604 		    emlxs_vpi_state_xlate(vpip->state));
12605 
12606 		mutex_exit(&EMLXS_FCF_LOCK);
12607 
12608 		return (1);
12609 	}
12610 
12611 	if (vpip->state != VPI_STATE_PORT_ONLINE) {
12612 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12613 		    "vpi_logi_notify:%d %s. "
12614 		    "Invalid state.",
12615 		    vpip->VPI,
12616 		    emlxs_vpi_state_xlate(vpip->state));
12617 
12618 		mutex_exit(&EMLXS_FCF_LOCK);
12619 
12620 		return (1);
12621 	}
12622 
12623 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12624 	    "vpi_logi_notify:%d %s. "
12625 	    "Logging in. >",
12626 	    vpip->VPI,
12627 	    emlxs_vpi_state_xlate(vpip->state));
12628 
12629 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI,
12630 	    0, 0, sbp);
12631 
12632 	if (rval) {
12633 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12634 		    "vpi_logi_notify:%d %s rval=%d.",
12635 		    vpip->VPI,
12636 		    emlxs_vpi_state_xlate(vpip->state),
12637 		    rval);
12638 	}
12639 
12640 	mutex_exit(&EMLXS_FCF_LOCK);
12641 
12642 	return (rval);
12643 
12644 } /* emlxs_vpi_logi_notify() */
12645 
12646 
12647 static uint32_t
emlxs_vpi_logi_cmpl_notify(emlxs_port_t * port,RPIobj_t * rpip)12648 emlxs_vpi_logi_cmpl_notify(emlxs_port_t *port, RPIobj_t *rpip)
12649 {
12650 	emlxs_hba_t *hba = HBA;
12651 	VPIobj_t *vpip = port->vpip;
12652 	uint32_t rval = 0;
12653 
12654 	/* EMLXS_FCF_LOCK must be held when calling this routine */
12655 
12656 	if (vpip->state != VPI_STATE_LOGI) {
12657 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12658 		    "vpi_logi_cmpl_notify:%d %s. "
12659 		    "Invalid state.",
12660 		    vpip->VPI,
12661 		    emlxs_vpi_state_xlate(vpip->state));
12662 		return (1);
12663 	}
12664 
12665 	if (rpip->RPI == FABRIC_RPI) {
12666 		if (hba->flag & FC_PT_TO_PT) {
12667 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12668 			    "vpi_logi_cmpl_notify:%d %s. P2P mode. "
12669 			    "Completing FLOGI.",
12670 			    vpip->VPI,
12671 			    emlxs_vpi_state_xlate(vpip->state));
12672 
12673 			/* Complete the FLOGI/FDISC now */
12674 			if (rpip->cmpl) {
12675 				emlxs_rpi_deferred_cmpl(port, rpip, 0);
12676 			}
12677 
12678 			/* Wait for P2P PLOGI completion to continue */
12679 			return (0);
12680 		}
12681 
12682 		if (!rpip->cmpl || !rpip->cmpl->arg1) {
12683 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12684 			    "vpi_logi_cmpl_notify:%d. Null sbp.",
12685 			    vpip->VPI);
12686 			return (1);
12687 		}
12688 
12689 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12690 		    "vpi_logi_cmpl_notify:%d %s. Fabric mode. "
12691 		    "Completing login. >",
12692 		    vpip->VPI,
12693 		    emlxs_vpi_state_xlate(vpip->state));
12694 
12695 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_CMPL,
12696 		    0, 0, 0);
12697 
12698 		if (rval) {
12699 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12700 			    "vpi_logi_cmpl_notify:%d %s rval=%d.",
12701 			    vpip->VPI,
12702 			    emlxs_vpi_state_xlate(vpip->state),
12703 			    rval);
12704 		}
12705 
12706 		return (rval);
12707 	}
12708 
12709 	if (hba->flag & FC_PT_TO_PT) {
12710 		if (port->did == 0) {
12711 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12712 			    "vpi_logi_cmpl_notify:%d %s did=0. P2P mode. "
12713 			    "Wait for PLOGI compl.",
12714 			    vpip->VPI,
12715 			    emlxs_vpi_state_xlate(vpip->state));
12716 
12717 			if (rpip->cmpl) {
12718 				emlxs_rpi_deferred_cmpl(port, rpip, 0);
12719 			}
12720 
12721 			/* Wait for P2P PLOGI completion to continue */
12722 			return (0);
12723 		}
12724 
12725 		vpip->p2p_rpip = rpip;
12726 
12727 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12728 		    "vpi_logi_cmpl_notify:%d %s. P2P mode. "
12729 		    "Completing login. >",
12730 		    vpip->VPI,
12731 		    emlxs_vpi_state_xlate(vpip->state));
12732 
12733 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_CMPL,
12734 		    0, 0, 0);
12735 
12736 		if (rval) {
12737 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12738 			    "vpi_logi_cmpl_notify:%d %s rval=%d.",
12739 			    vpip->VPI,
12740 			    emlxs_vpi_state_xlate(vpip->state),
12741 			    rval);
12742 		}
12743 
12744 		return (rval);
12745 	}
12746 
12747 	return (1);
12748 
12749 } /* emlxs_vpi_logi_cmpl_notify() */
12750 
12751 
12752 extern uint32_t
emlxs_vpi_logi_failed_notify(emlxs_port_t * port,emlxs_buf_t * sbp)12753 emlxs_vpi_logi_failed_notify(emlxs_port_t *port, emlxs_buf_t *sbp)
12754 {
12755 	emlxs_hba_t *hba = HBA;
12756 	VPIobj_t *vpip = port->vpip;
12757 	RPIobj_t *rpip = vpip->fabric_rpip;
12758 	uint32_t rval = 0;
12759 	emlxs_deferred_cmpl_t *cmpl;
12760 
12761 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
12762 		return (1);
12763 	}
12764 
12765 	mutex_enter(&EMLXS_FCF_LOCK);
12766 
12767 	if (vpip->state != VPI_STATE_LOGI) {
12768 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12769 		    "vpi_logi_failed_notify:%d %s. "
12770 		    "Invalid state.",
12771 		    vpip->VPI,
12772 		    emlxs_vpi_state_xlate(vpip->state));
12773 
12774 		/* Fabric logo is implied */
12775 		emlxs_vpi_logo_handler(port, vpip);
12776 
12777 		mutex_exit(&EMLXS_FCF_LOCK);
12778 
12779 		return (1);
12780 	}
12781 
12782 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12783 	    "vpi_logi_failed_notify:%d %s. "
12784 	    "Failing login. >",
12785 	    vpip->VPI,
12786 	    emlxs_vpi_state_xlate(vpip->state));
12787 
12788 	/* For safety */
12789 	if (rpip->cmpl) {
12790 		emlxs_rpi_deferred_cmpl(port, rpip, 1);
12791 	}
12792 
12793 	if (sbp) {
12794 		cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
12795 		    sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
12796 
12797 		cmpl->port = port;
12798 		cmpl->arg1 = (void *)sbp;
12799 		cmpl->arg2 = 0;
12800 		cmpl->arg3 = 0;
12801 
12802 		rpip->cmpl = cmpl;
12803 	}
12804 
12805 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_FAILED,
12806 	    FCF_REASON_OP_FAILED, 1, 0);
12807 
12808 	if (rval && rpip->cmpl) {
12809 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
12810 		rpip->cmpl = 0;
12811 	}
12812 
12813 	mutex_exit(&EMLXS_FCF_LOCK);
12814 	return (rval);
12815 
12816 } /* emlxs_vpi_logi_failed_notify() */
12817 
12818 
12819 extern uint32_t
emlxs_vpi_logo_cmpl_notify(emlxs_port_t * port)12820 emlxs_vpi_logo_cmpl_notify(emlxs_port_t *port)
12821 {
12822 	emlxs_hba_t *hba = HBA;
12823 	VPIobj_t *vpip = port->vpip;
12824 	uint32_t rval = 0;
12825 	VFIobj_t *vfip;
12826 	FCFIobj_t *fcfp;
12827 
12828 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
12829 		return (1);
12830 	}
12831 
12832 	mutex_enter(&EMLXS_FCF_LOCK);
12833 
12834 	/* Fabric logo is complete */
12835 	emlxs_vpi_logo_handler(port, vpip);
12836 
12837 	if ((vpip->state == VPI_STATE_OFFLINE) ||
12838 	    (vpip->flag & EMLXS_VPI_OFFLINE_REQ)) {
12839 		/* Already offline. Do nothing */
12840 		mutex_exit(&EMLXS_FCF_LOCK);
12841 		return (0);
12842 	}
12843 
12844 	vfip = vpip->vfip;
12845 	fcfp = vfip->fcfp;
12846 
12847 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12848 	    "vpi_logo_cmpl_notify:%d %s fcfi:%d vfi:%d. "
12849 	    "Offlining VPI:%d,%d >",
12850 	    vpip->VPI,
12851 	    emlxs_vpi_state_xlate(vpip->state),
12852 	    fcfp->fcf_index,
12853 	    vfip->VFI,
12854 	    vpip->index, vpip->VPI);
12855 
12856 	rval = emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
12857 
12858 	mutex_exit(&EMLXS_FCF_LOCK);
12859 
12860 	return (rval);
12861 
12862 } /* emlxs_vpi_logo_cmpl_notify() */
12863 
12864 
12865 /*ARGSUSED*/
12866 static uint32_t
emlxs_vpi_logi_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12867 emlxs_vpi_logi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12868     void *arg1)
12869 {
12870 	emlxs_hba_t *hba = HBA;
12871 	emlxs_buf_t *sbp = (emlxs_buf_t *)arg1;
12872 	fc_packet_t *pkt = PRIV2PKT(sbp);
12873 	uint32_t rval = 0;
12874 
12875 	if (vpip->state != VPI_STATE_LOGI) {
12876 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12877 		    "vpi_logi_action:%d %s:%s arg=%p. "
12878 		    "Invalid state. <",
12879 		    vpip->VPI,
12880 		    emlxs_vpi_state_xlate(vpip->state),
12881 		    emlxs_fcf_event_xlate(evt), arg1);
12882 		return (1);
12883 	}
12884 
12885 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
12886 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12887 		    "vpi_logi_action:%d. Offline requested.",
12888 		    vpip->VPI);
12889 
12890 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12891 		return (rval);
12892 	}
12893 
12894 	if (vpip->flag & EMLXS_VPI_LOGI) {
12895 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12896 		    "vpi_logi_action:%d flag=%x. LOGI already set.",
12897 		    vpip->VPI, vpip->flag);
12898 
12899 		/* Fabric logo is implied */
12900 		emlxs_vpi_logo_handler(port, vpip);
12901 	}
12902 
12903 	/* Check if FC_PT_TO_PT is set */
12904 	if (hba->flag & FC_PT_TO_PT) {
12905 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12906 		    "vpi_logi_action:%d logi_count=%d. FLOGI set. P2P. <",
12907 		    vpip->VPI,
12908 		    vpip->vfip->logi_count);
12909 
12910 		*((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FLOGI;
12911 
12912 		vpip->vfip->flogi_vpip = vpip;
12913 
12914 		if (vpip->vfip->logi_count == 0) {
12915 			vpip->vfip->logi_count++;
12916 			vpip->flag |= EMLXS_VPI_VFI_LOGI;
12917 		}
12918 
12919 		return (0);
12920 	}
12921 
12922 	/* Set login command based on vfi logi_count */
12923 	if (vpip->vfip->logi_count == 0) {
12924 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12925 		    "vpi_logi_action:%d logi_count=%d. FLOGI set. <",
12926 		    vpip->VPI,
12927 		    vpip->vfip->logi_count);
12928 
12929 		*((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FLOGI;
12930 
12931 		vpip->vfip->flogi_vpip = vpip;
12932 	} else {
12933 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12934 		    "vpi_logi_action:%d logi_count=%d. FDISC set. <",
12935 		    vpip->VPI,
12936 		    vpip->vfip->logi_count);
12937 
12938 		*((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FDISC;
12939 	}
12940 
12941 	vpip->vfip->logi_count++;
12942 	vpip->flag |= EMLXS_VPI_VFI_LOGI;
12943 
12944 	return (0);
12945 
12946 } /* emlxs_vpi_logi_action() */
12947 
12948 
12949 /*ARGSUSED*/
12950 static uint32_t
emlxs_vpi_logi_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12951 emlxs_vpi_logi_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12952     void *arg1)
12953 {
12954 	emlxs_hba_t *hba = HBA;
12955 	uint32_t rval = 0;
12956 
12957 	if (vpip->state != VPI_STATE_LOGI_FAILED) {
12958 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12959 		    "vpi_logi_failed_action:%d %s:%s arg=%p. "
12960 		    "Invalid state. <",
12961 		    vpip->VPI,
12962 		    emlxs_vpi_state_xlate(vpip->state),
12963 		    emlxs_fcf_event_xlate(evt), arg1);
12964 		return (1);
12965 	}
12966 
12967 	/* Fabric logo is implied */
12968 	emlxs_vpi_logo_handler(port, vpip);
12969 
12970 	if (hba->topology == TOPOLOGY_LOOP) {
12971 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12972 		    "vpi_logi_failed_action:%d. Private loop. "
12973 		    "Registering VPI.",
12974 		    vpip->VPI);
12975 
12976 		/* Update the VPI flogi_vpip pointer for loop */
12977 		/* because the vpi_logo_handler cleared it */
12978 		vpip->vfip->flogi_vpip = vpip;
12979 
12980 		bcopy((void *)&vpip->port->sparam,
12981 		    (void *)&vpip->fabric_rpip->sparam,
12982 		    sizeof (SERV_PARM));
12983 
12984 		/* Update the VPI Fabric RPI */
12985 		vpip->fabric_rpip->sparam.cmn.w2.r_a_tov =
12986 		    LE_SWAP32((FF_DEF_RATOV * 1000));
12987 
12988 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
12989 		    FCF_REASON_EVENT, evt, arg1);
12990 		return (rval);
12991 	}
12992 
12993 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12994 	    "vpi_logi_failed_action:%d. Requesting offline.",
12995 	    vpip->VPI);
12996 
12997 	vpip->flag &= ~EMLXS_VPI_REQ_MASK;
12998 	vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
12999 	rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13000 
13001 	return (rval);
13002 
13003 } /* emlxs_vpi_logi_failed_action() */
13004 
13005 
13006 /*ARGSUSED*/
13007 static uint32_t
emlxs_vpi_logi_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13008 emlxs_vpi_logi_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13009     void *arg1)
13010 {
13011 	emlxs_hba_t *hba = HBA;
13012 	uint32_t rval = 0;
13013 	char buffer1[64];
13014 	char buffer2[64];
13015 	uint32_t new_config = 0;
13016 
13017 	if (vpip->state != VPI_STATE_LOGI_CMPL) {
13018 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13019 		    "vpi_logi_cmpl_action:%d %s:%s arg=%p. "
13020 		    "Invalid state. <",
13021 		    vpip->VPI,
13022 		    emlxs_vpi_state_xlate(vpip->state),
13023 		    emlxs_fcf_event_xlate(evt), arg1);
13024 		return (1);
13025 	}
13026 
13027 	vpip->flag |= EMLXS_VPI_LOGI;
13028 
13029 	/* Check for new fabric */
13030 	if (port->prev_did) {
13031 		if (SLI4_FCOE_MODE) {
13032 			/* Check for FCF change */
13033 			if (((port->prev_did != port->did) ||
13034 			    bcmp(&port->prev_fabric_sparam.portName,
13035 			    &port->fabric_sparam.portName, 8)) &&
13036 			    emlxs_nport_count(port)) {
13037 				new_config = 1;
13038 			}
13039 		} else {
13040 			uint32_t old_topo;
13041 			uint32_t new_topo;
13042 
13043 			/* Check for topology change (0=loop 1=fabric) */
13044 			old_topo = ((port->prev_did && 0xFFFF00) == 0)? 0:1;
13045 			new_topo = ((port->did && 0xFFFF00) == 0)? 0:1;
13046 
13047 			if (old_topo != new_topo) {
13048 				new_config = 1;
13049 
13050 			/* Check for any switch change */
13051 			} else if ((port->prev_did != port->did) ||
13052 			    bcmp(&port->prev_fabric_sparam.portName,
13053 			    &port->fabric_sparam.portName, 8)) {
13054 				new_config = 1;
13055 			}
13056 		}
13057 	}
13058 
13059 	if (new_config) {
13060 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13061 		    "vpi_logi_cmpl_action:%d. "
13062 		    "New config. Offlining port.",
13063 		    vpip->VPI);
13064 
13065 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13066 		    "vpi_logi_cmpl_action: prev_wwpn=%s wwpn=%s prev_did=%x "
13067 		    "did=%x.",
13068 		    emlxs_wwn_xlate(buffer1, sizeof (buffer1),
13069 		    (uint8_t *)&port->prev_fabric_sparam.portName),
13070 		    emlxs_wwn_xlate(buffer2, sizeof (buffer2),
13071 		    (uint8_t *)&port->fabric_sparam.portName),
13072 		    port->prev_did, port->did);
13073 
13074 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
13075 		vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13076 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13077 
13078 		return (rval);
13079 	}
13080 
13081 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13082 	    "vpi_logi_cmpl_action:%d. Registering.",
13083 	    vpip->VPI);
13084 
13085 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
13086 	    FCF_REASON_EVENT, evt, arg1);
13087 
13088 	return (rval);
13089 
13090 } /* emlxs_vpi_logi_cmpl_action() */
13091 
13092 
13093 /*ARGSUSED*/
13094 static uint32_t
emlxs_vpi_logo_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13095 emlxs_vpi_logo_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13096     void *arg1)
13097 {
13098 	emlxs_hba_t *hba = HBA;
13099 	uint32_t rval = 0;
13100 
13101 	vpip->attempts++;
13102 
13103 	if (vpip->state != VPI_STATE_LOGO_FAILED) {
13104 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13105 		    "vpi_logo_failed_action:%d %s:%s arg=%p attempt=%d. "
13106 		    "Invalid state. <",
13107 		    vpip->VPI,
13108 		    emlxs_vpi_state_xlate(vpip->state),
13109 		    emlxs_fcf_event_xlate(evt), arg1,
13110 		    vpip->attempts);
13111 		return (1);
13112 	}
13113 
13114 	if (hba->state <= FC_LINK_DOWN) {
13115 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13116 		    "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.",
13117 		    vpip->VPI,
13118 		    vpip->attempts);
13119 
13120 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL,
13121 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13122 	} else if (vpip->attempts >= 3) {
13123 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13124 		    "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.",
13125 		    vpip->VPI,
13126 		    vpip->attempts);
13127 
13128 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL,
13129 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13130 	} else {
13131 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13132 		    "vpi_logo_failed_action:%d attempt=%d. Logging out.",
13133 		    vpip->VPI,
13134 		    vpip->attempts);
13135 
13136 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
13137 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13138 	}
13139 
13140 	return (rval);
13141 
13142 } /* emlxs_vpi_logo_failed_action() */
13143 
13144 
13145 /*ARGSUSED*/
13146 static uint32_t
emlxs_vpi_logo_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13147 emlxs_vpi_logo_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13148     void *arg1)
13149 {
13150 	emlxs_hba_t *hba = HBA;
13151 	emlxs_port_t *vport = vpip->port;
13152 	uint32_t rval = 0;
13153 	uint32_t did;
13154 	uint32_t sid;
13155 	fc_packet_t *pkt;
13156 	ELS_PKT *els;
13157 
13158 	if (vpip->state != VPI_STATE_LOGO) {
13159 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13160 		    "vpi_logo_action:%d %s:%s arg=%p. "
13161 		    "Invalid state. <",
13162 		    vpip->VPI,
13163 		    emlxs_vpi_state_xlate(vpip->state),
13164 		    emlxs_fcf_event_xlate(evt), arg1);
13165 		return (1);
13166 	}
13167 
13168 	if (!(vpip->flag & EMLXS_VPI_LOGI)) {
13169 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13170 		    "vpi_logo_action:%d. No login. Skipping LOGO.",
13171 		    vpip->VPI);
13172 
13173 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13174 		    FCF_REASON_EVENT, evt, arg1);
13175 		return (rval);
13176 	}
13177 
13178 	if (!(hba->flag & FC_ONLINE_MODE) &&
13179 	    !(hba->flag & FC_OFFLINING_MODE)) {
13180 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13181 		    "vpi_logo_action:%d. HBA offline. Skipping LOGO.",
13182 		    vpip->VPI);
13183 
13184 		/* Fabric logo is implied */
13185 		emlxs_vpi_logo_handler(port, vpip);
13186 
13187 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13188 		    FCF_REASON_EVENT, evt, arg1);
13189 		return (rval);
13190 	}
13191 
13192 	if (SLI4_FC_MODE) {
13193 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13194 		    "vpi_logo_action:%d. FC mode. Skipping LOGO.",
13195 		    vpip->VPI);
13196 
13197 		/* Fabric logo is implied */
13198 		emlxs_vpi_logo_handler(port, vpip);
13199 
13200 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13201 		    FCF_REASON_EVENT, evt, arg1);
13202 		return (rval);
13203 	}
13204 
13205 	if (vpip->prev_state != VPI_STATE_LOGO_FAILED) {
13206 		vpip->attempts = 0;
13207 	}
13208 
13209 	did = FABRIC_DID;
13210 	sid = (vport->did)? vport->did:vport->prev_did;
13211 
13212 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13213 	    "vpi_logo_action:%d attempts=%d sid=%x did=%x. Sending LOGO. <",
13214 	    vpip->VPI,
13215 	    vpip->attempts,
13216 	    sid, did);
13217 
13218 	pkt = emlxs_pkt_alloc(vport,
13219 	    (sizeof (uint32_t) + sizeof (LOGO)),
13220 	    (sizeof (uint32_t) + sizeof (LOGO)), 0, KM_NOSLEEP);
13221 
13222 	if (!pkt) {
13223 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED,
13224 		    FCF_REASON_NO_PKT, 0, arg1);
13225 
13226 		return (rval);
13227 	}
13228 
13229 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
13230 	pkt->pkt_timeout = (2 * hba->fc_ratov);
13231 
13232 	/* Build the fc header */
13233 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
13234 	pkt->pkt_cmd_fhdr.r_ctl =
13235 	    R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
13236 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid);
13237 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
13238 	pkt->pkt_cmd_fhdr.f_ctl =
13239 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
13240 	pkt->pkt_cmd_fhdr.seq_id = 0;
13241 	pkt->pkt_cmd_fhdr.df_ctl = 0;
13242 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
13243 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
13244 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
13245 	pkt->pkt_cmd_fhdr.ro = 0;
13246 
13247 	/* Build the command */
13248 	els = (ELS_PKT *)pkt->pkt_cmd;
13249 	els->elsCode = 0x05;
13250 	els->un.logo.un.nPortId32 = pkt->pkt_cmd_fhdr.s_id;
13251 	bcopy((uint8_t *)&vport->wwpn,
13252 	    (uint8_t *)&els->un.logo.portName, 8);
13253 
13254 	/* Send the pkt now */
13255 	rval = emlxs_pkt_send(pkt, 0);
13256 	if (rval != FC_SUCCESS) {
13257 		/* Free the pkt */
13258 		emlxs_pkt_free(pkt);
13259 
13260 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED,
13261 		    FCF_REASON_SEND_FAILED, rval, arg1);
13262 
13263 		return (rval);
13264 	}
13265 
13266 	/* For now we will send and forget */
13267 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL,
13268 	    FCF_REASON_EVENT, evt, arg1);
13269 
13270 	return (rval);
13271 
13272 } /* emlxs_vpi_logo_action() */
13273 
13274 
13275 /*ARGSUSED*/
13276 static uint32_t
emlxs_vpi_logo_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13277 emlxs_vpi_logo_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13278     void *arg1)
13279 {
13280 	uint32_t rval = 0;
13281 
13282 	if (vpip->state != VPI_STATE_LOGO_CMPL) {
13283 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13284 		    "vpi_logo_cmpl_action:%d %s:%s arg=%p. "
13285 		    "Invalid state. <",
13286 		    vpip->VPI,
13287 		    emlxs_vpi_state_xlate(vpip->state),
13288 		    emlxs_fcf_event_xlate(evt), arg1);
13289 		return (1);
13290 	}
13291 
13292 	/* Fabric logo is complete */
13293 	emlxs_vpi_logo_handler(port, vpip);
13294 
13295 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13296 	    "vpi_logo_cmpl_action:%d attempts=%d. Offline RPI's.",
13297 	    vpip->VPI,
13298 	    vpip->attempts);
13299 
13300 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13301 	    FCF_REASON_EVENT, evt, arg1);
13302 
13303 	return (rval);
13304 
13305 } /* emlxs_vpi_logo_cmpl_action() */
13306 
13307 
13308 /*ARGSUSED*/
13309 static uint32_t
emlxs_vpi_unreg_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13310 emlxs_vpi_unreg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13311     void *arg1)
13312 {
13313 	uint32_t rval = 0;
13314 
13315 	vpip->attempts++;
13316 
13317 	if (vpip->state != VPI_STATE_UNREG_FAILED) {
13318 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13319 		    "vpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
13320 		    "Invalid state. <",
13321 		    vpip->VPI,
13322 		    emlxs_vpi_state_xlate(vpip->state),
13323 		    emlxs_fcf_event_xlate(evt), arg1,
13324 		    vpip->attempts);
13325 		return (1);
13326 	}
13327 
13328 	if ((vpip->reason == FCF_REASON_SEND_FAILED) ||
13329 	    (vpip->attempts >= 3)) {
13330 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13331 		    "vpi_unreg_failed_action:%d attempt=%d. Unreg cmpl.",
13332 		    vpip->VPI,
13333 		    vpip->attempts);
13334 
13335 		vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
13336 
13337 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
13338 		vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13339 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL,
13340 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13341 	} else {
13342 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13343 		    "vpi_unreg_failed_action:%d attempt=%d. Unregistering.",
13344 		    vpip->VPI,
13345 		    vpip->attempts);
13346 
13347 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
13348 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13349 	}
13350 
13351 	return (rval);
13352 
13353 } /* emlxs_vpi_unreg_failed_action() */
13354 
13355 
13356 /*ARGSUSED*/
13357 static uint32_t
emlxs_vpi_unreg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)13358 emlxs_vpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
13359 {
13360 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
13361 	MAILBOX4 *mb4;
13362 	VPIobj_t *vpip;
13363 
13364 	vpip = (VPIobj_t *)mbq->context;
13365 	mb4 = (MAILBOX4 *)mbq;
13366 
13367 	mutex_enter(&EMLXS_FCF_LOCK);
13368 
13369 	if (vpip->state != VPI_STATE_UNREG) {
13370 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13371 		    "vpi_unreg_mbcmpl:%d state=%s.",
13372 		    vpip->VPI,
13373 		    emlxs_vpi_state_xlate(vpip->state));
13374 
13375 		mutex_exit(&EMLXS_FCF_LOCK);
13376 		return (0);
13377 	}
13378 
13379 	if (mb4->mbxStatus) {
13380 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13381 		    "vpi_unreg_mbcmpl:%d failed. %s. >",
13382 		    vpip->VPI,
13383 		    emlxs_mb_xlate_status(mb4->mbxStatus));
13384 
13385 		(void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
13386 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
13387 
13388 		mutex_exit(&EMLXS_FCF_LOCK);
13389 		return (0);
13390 	}
13391 
13392 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13393 	    "vpi_unreg_mbcmpl:%d. Unreg complete. >",
13394 	    vpip->VPI);
13395 
13396 	vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
13397 	(void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL, 0, 0, 0);
13398 
13399 	mutex_exit(&EMLXS_FCF_LOCK);
13400 	return (0);
13401 
13402 } /* emlxs_vpi_unreg_mbcmpl() */
13403 
13404 
13405 /*ARGSUSED*/
13406 static uint32_t
emlxs_vpi_unreg_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13407 emlxs_vpi_unreg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13408     void *arg1)
13409 {
13410 	emlxs_hba_t *hba = HBA;
13411 	MAILBOX4 *mb4;
13412 	MAILBOXQ *mbq;
13413 	uint32_t rval = 0;
13414 
13415 	if (vpip->state != VPI_STATE_UNREG) {
13416 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13417 		    "vpi_unreg_action:%d %s:%s arg=%p. "
13418 		    "Invalid state. <",
13419 		    vpip->VPI,
13420 		    emlxs_vpi_state_xlate(vpip->state),
13421 		    emlxs_fcf_event_xlate(evt), arg1);
13422 		return (1);
13423 	}
13424 
13425 	if ((vpip->rpi_online > vpip->rpi_paused) ||
13426 	    (vpip->fabric_rpip->state != RPI_STATE_FREE)) {
13427 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13428 		    "vpi_unreg_action:%d rpi_online=%d,%d fstate=%x. "
13429 		    "Waiting for RPI's.", vpip->VPI, vpip->rpi_online,
13430 		    vpip->rpi_paused, vpip->fabric_rpip->state);
13431 
13432 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13433 		    FCF_REASON_EVENT, evt, arg1);
13434 		return (rval);
13435 	}
13436 
13437 	if (!(vpip->flag & EMLXS_VPI_REG)) {
13438 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13439 		    "vpi_unreg_action:%d. Not registered. Skipping UNREG_VPI.",
13440 		    vpip->VPI);
13441 
13442 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
13443 		    FCF_REASON_EVENT, evt, arg1);
13444 		return (rval);
13445 	}
13446 
13447 	if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
13448 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13449 		    "vpi_unreg_action:%d rpi_online=%d,%d. Pausing.",
13450 		    vpip->VPI,
13451 		    vpip->rpi_online, vpip->rpi_paused);
13452 
13453 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED,
13454 		    FCF_REASON_EVENT, evt, arg1);
13455 		return (rval);
13456 	}
13457 
13458 	if (vpip->prev_state != VPI_STATE_UNREG_FAILED) {
13459 		vpip->attempts = 0;
13460 	}
13461 
13462 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13463 	    "vpi_unreg_action:%d attempts=%d. Sending UNREG_VPI. <",
13464 	    vpip->VPI,
13465 	    vpip->attempts);
13466 
13467 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
13468 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
13469 		    FCF_REASON_NO_MBOX, 0, arg1);
13470 
13471 		return (rval);
13472 	}
13473 	mb4 = (MAILBOX4*)mbq;
13474 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
13475 
13476 	mbq->nonembed = NULL;
13477 	mbq->mbox_cmpl = emlxs_vpi_unreg_mbcmpl;
13478 	mbq->context = (void *)vpip;
13479 	mbq->port = (void *)vpip->port;
13480 
13481 	mb4->un.varUnRegVPI4.ii = 0; /* index is a VPI */
13482 	mb4->un.varUnRegVPI4.index = vpip->VPI;
13483 	mb4->mbxCommand = MBX_UNREG_VPI;
13484 	mb4->mbxOwner = OWN_HOST;
13485 
13486 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
13487 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
13488 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
13489 
13490 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
13491 		    FCF_REASON_SEND_FAILED, rval, arg1);
13492 
13493 		return (rval);
13494 	}
13495 
13496 	return (0);
13497 
13498 } /* emlxs_vpi_unreg_action() */
13499 
13500 
13501 /*ARGSUSED*/
13502 static uint32_t
emlxs_vpi_unreg_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13503 emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13504     void *arg1)
13505 {
13506 	uint32_t rval = 0;
13507 
13508 	if (vpip->state != VPI_STATE_UNREG_CMPL) {
13509 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13510 		    "vpi_unreg_cmpl_action:%d %s:%s arg=%p. "
13511 		    "Invalid state. <",
13512 		    vpip->VPI,
13513 		    emlxs_vpi_state_xlate(vpip->state),
13514 		    emlxs_fcf_event_xlate(evt), arg1);
13515 		return (1);
13516 	}
13517 
13518 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13519 	    "vpi_unreg_cmpl_action:%d attempts=%d. Going offline.",
13520 	    vpip->VPI,
13521 	    vpip->attempts);
13522 
13523 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
13524 	    FCF_REASON_EVENT, evt, arg1);
13525 
13526 	return (rval);
13527 
13528 } /* emlxs_vpi_unreg_cmpl_action() */
13529 
13530 
13531 /*ARGSUSED*/
13532 static uint32_t
emlxs_vpi_reg_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13533 emlxs_vpi_reg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13534     void *arg1)
13535 {
13536 	uint32_t rval = 0;
13537 
13538 	vpip->attempts++;
13539 
13540 	if (vpip->state != VPI_STATE_REG_FAILED) {
13541 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13542 		    "vpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
13543 		    "Invalid state. <",
13544 		    vpip->VPI,
13545 		    emlxs_vpi_state_xlate(vpip->state),
13546 		    emlxs_fcf_event_xlate(evt), arg1,
13547 		    vpip->attempts);
13548 		return (1);
13549 	}
13550 
13551 	if ((vpip->reason == FCF_REASON_SEND_FAILED) ||
13552 	    (vpip->attempts >= 3)) {
13553 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13554 		    "vpi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.",
13555 		    vpip->VPI,
13556 		    vpip->attempts,
13557 		    vpip->reason);
13558 
13559 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
13560 		vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13561 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL,
13562 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13563 	} else {
13564 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13565 		    "vpi_reg_failed_action:%d attempt=%d. Registering.",
13566 		    vpip->VPI,
13567 		    vpip->attempts);
13568 
13569 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
13570 		    FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13571 	}
13572 
13573 	return (rval);
13574 
13575 } /* emlxs_vpi_reg_failed_action() */
13576 
13577 
13578 /*ARGSUSED*/
13579 static uint32_t
emlxs_vpi_reg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)13580 emlxs_vpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
13581 {
13582 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
13583 	MAILBOX4 *mb4;
13584 	VPIobj_t *vpip;
13585 
13586 	vpip = (VPIobj_t *)mbq->context;
13587 	mb4 = (MAILBOX4 *)mbq;
13588 
13589 	mutex_enter(&EMLXS_FCF_LOCK);
13590 
13591 	if (vpip->state != VPI_STATE_REG) {
13592 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13593 		    "vpi_reg_mbcmpl:%d state=%s.",
13594 		    vpip->VPI,
13595 		    emlxs_vpi_state_xlate(vpip->state));
13596 
13597 		mutex_exit(&EMLXS_FCF_LOCK);
13598 		return (0);
13599 	}
13600 
13601 	if (mb4->mbxStatus) {
13602 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13603 		    "vpi_reg_mbcmpl:%d failed. %s. >",
13604 		    vpip->VPI,
13605 		    emlxs_mb_xlate_status(mb4->mbxStatus));
13606 
13607 		if (mb4->mbxStatus == MBXERR_DID_INCONSISTENT) {
13608 			vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13609 		}
13610 
13611 		(void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
13612 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
13613 
13614 		mutex_exit(&EMLXS_FCF_LOCK);
13615 		return (0);
13616 	}
13617 
13618 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13619 	    "vpi_reg_mbcmpl:%d. Reg complete. >",
13620 	    vpip->VPI);
13621 
13622 	vpip->flag |= EMLXS_VPI_REG;
13623 	(void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL,
13624 	    0, 0, 0);
13625 
13626 	mutex_exit(&EMLXS_FCF_LOCK);
13627 	return (0);
13628 
13629 } /* emlxs_vpi_reg_mbcmpl() */
13630 
13631 
13632 /*ARGSUSED*/
13633 static uint32_t
emlxs_vpi_reg_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13634 emlxs_vpi_reg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13635     void *arg1)
13636 {
13637 	emlxs_hba_t *hba = HBA;
13638 	uint32_t *wwpn;
13639 	MAILBOX *mb;
13640 	MAILBOXQ *mbq;
13641 	uint32_t rval = 0;
13642 
13643 	if (vpip->state != VPI_STATE_REG) {
13644 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13645 		    "vpi_reg_action:%d %s:%s arg=%p. "
13646 		    "Invalid state. <",
13647 		    vpip->VPI,
13648 		    emlxs_vpi_state_xlate(vpip->state),
13649 		    emlxs_fcf_event_xlate(evt), arg1);
13650 		return (1);
13651 	}
13652 
13653 	if (vpip->prev_state != VPI_STATE_REG_FAILED) {
13654 		vpip->attempts = 0;
13655 	}
13656 
13657 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
13658 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13659 		    "vpi_reg_action:%d attempts=%d. Offline requested.",
13660 		    vpip->VPI,
13661 		    vpip->attempts);
13662 
13663 		rval = emlxs_vpi_offline_handler(port, vpip, 0);
13664 		return (rval);
13665 	}
13666 
13667 	if (!(vpip->vfip->flag & EMLXS_VFI_REG)) {
13668 		/* We can't register the VPI until our VFI is registered */
13669 
13670 		/* If this is the flogi_vpip, then we can skip the REG_VPI. */
13671 		/* REG_VPI will be performed later during REG_VFI */
13672 		if (vpip == vpip->vfip->flogi_vpip) {
13673 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13674 			    "vpi_reg_action:%d. flogi_vpi. Skipping REG_VPI.",
13675 			    vpip->VPI);
13676 
13677 			rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE,
13678 			    FCF_REASON_EVENT, evt, arg1);
13679 
13680 			return (rval);
13681 		}
13682 
13683 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13684 		    "vpi_reg_action:%d attempts=%d. VFI not registered. "
13685 		    "Offlining.",
13686 		    vpip->VPI,
13687 		    vpip->attempts);
13688 
13689 		vpip->flag &= ~EMLXS_VPI_REQ_MASK;
13690 		vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13691 		rval = emlxs_vpi_offline_handler(port, vpip, 0);
13692 		return (rval);
13693 	}
13694 
13695 	if (vpip->flag & EMLXS_VPI_REG) {
13696 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13697 		    "vpi_reg_action:%d attempts=%d. Updating REG_VPI. <",
13698 		    vpip->VPI,
13699 		    vpip->attempts);
13700 	} else {
13701 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13702 		    "vpi_reg_action:%d attempts=%d. Sending REG_VPI. <",
13703 		    vpip->VPI,
13704 		    vpip->attempts);
13705 	}
13706 
13707 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
13708 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
13709 		    FCF_REASON_NO_MBOX, 0, arg1);
13710 
13711 		return (rval);
13712 	}
13713 	mb = (MAILBOX*)mbq;
13714 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
13715 
13716 	mbq->nonembed = NULL;
13717 	mbq->mbox_cmpl = emlxs_vpi_reg_mbcmpl;
13718 	mbq->context = (void *)vpip;
13719 	mbq->port = (void *)vpip->port;
13720 
13721 	mb->un.varRegVpi.vfi = vpip->vfip->VFI;
13722 	mb->un.varRegVpi.upd = (vpip->flag & EMLXS_VPI_REG)? 1:0;
13723 
13724 	wwpn = (uint32_t *)&port->wwpn;
13725 	mb->un.varRegVpi.portname[0] = BE_SWAP32(*wwpn);
13726 	wwpn++;
13727 	mb->un.varRegVpi.portname[1] = BE_SWAP32(*wwpn);
13728 
13729 	mb->un.varRegVpi.vpi = vpip->VPI;
13730 	mb->un.varRegVpi.sid = vpip->port->did;
13731 	mb->mbxCommand = MBX_REG_VPI;
13732 	mb->mbxOwner = OWN_HOST;
13733 
13734 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
13735 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
13736 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
13737 
13738 		rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
13739 		    FCF_REASON_SEND_FAILED, rval, arg1);
13740 
13741 		return (rval);
13742 	}
13743 
13744 	return (0);
13745 
13746 } /* emlxs_vpi_reg_action() */
13747 
13748 
13749 /*ARGSUSED*/
13750 static uint32_t
emlxs_vpi_reg_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13751 emlxs_vpi_reg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13752     void *arg1)
13753 {
13754 	uint32_t rval = 0;
13755 
13756 	if (vpip->state != VPI_STATE_REG_CMPL) {
13757 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13758 		    "vpi_reg_cmpl_action:%d %s:%s arg=%p. "
13759 		    "Invalid state. <",
13760 		    vpip->VPI,
13761 		    emlxs_vpi_state_xlate(vpip->state),
13762 		    emlxs_fcf_event_xlate(evt), arg1);
13763 		return (1);
13764 	}
13765 
13766 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
13767 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13768 		    "vpi_reg_cmpl_action:%d attempts=%d. Offline requested.",
13769 		    vpip->VPI,
13770 		    vpip->attempts);
13771 
13772 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13773 		return (rval);
13774 	}
13775 
13776 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13777 	    "vpi_reg_cmpl_action:%d attempts=%d. Going online.",
13778 	    vpip->VPI,
13779 	    vpip->attempts);
13780 
13781 	rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE,
13782 	    FCF_REASON_EVENT, evt, arg1);
13783 
13784 	return (rval);
13785 
13786 } /* emlxs_vpi_reg_cmpl_action() */
13787 
13788 
13789 /*ARGSUSED*/
13790 static uint32_t
emlxs_vpi_online_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13791 emlxs_vpi_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13792     void *arg1)
13793 {
13794 	uint32_t rval = 0;
13795 
13796 	if (vpip->state != VPI_STATE_ONLINE) {
13797 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13798 		    "vpi_online_action:%d %s:%s arg=%p. "
13799 		    "Invalid state. <",
13800 		    vpip->VPI,
13801 		    emlxs_vpi_state_xlate(vpip->state),
13802 		    emlxs_fcf_event_xlate(evt), arg1);
13803 		return (1);
13804 	}
13805 
13806 	vpip->flag &= ~EMLXS_VPI_ONLINE_REQ;
13807 
13808 	if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
13809 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13810 		    "vpi_online_action:%d attempts=%d. Offline requested.",
13811 		    vpip->VPI,
13812 		    vpip->attempts);
13813 
13814 		rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13815 		return (rval);
13816 	}
13817 
13818 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13819 	    "vpi_online_action:%d. VPI online. Notifying VFI:%d >",
13820 	    vpip->VPI,
13821 	    vpip->vfip->VFI);
13822 
13823 	/* Notify VFI */
13824 	rval = emlxs_vfi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
13825 
13826 	return (rval);
13827 
13828 } /* emlxs_vpi_online_action() */
13829 
13830 
13831 /* ************************************************************************** */
13832 /* RPI */
13833 /* ************************************************************************** */
13834 
13835 static char *
emlxs_rpi_state_xlate(uint32_t state)13836 emlxs_rpi_state_xlate(uint32_t state)
13837 {
13838 	static char buffer[32];
13839 	uint32_t i;
13840 	uint32_t count;
13841 
13842 	count = sizeof (emlxs_rpi_state_table) / sizeof (emlxs_table_t);
13843 	for (i = 0; i < count; i++) {
13844 		if (state == emlxs_rpi_state_table[i].code) {
13845 			return (emlxs_rpi_state_table[i].string);
13846 		}
13847 	}
13848 
13849 	(void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
13850 	return (buffer);
13851 
13852 } /* emlxs_rpi_state_xlate() */
13853 
13854 
13855 static uint32_t
emlxs_rpi_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)13856 emlxs_rpi_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
13857     void *arg1)
13858 {
13859 	uint32_t rval = 0;
13860 	uint32_t(*func) (emlxs_port_t *, RPIobj_t *, uint32_t, void *);
13861 	uint32_t index;
13862 	uint32_t events;
13863 	uint16_t state;
13864 
13865 	/* Convert event to action table index */
13866 	switch (evt) {
13867 	case FCF_EVENT_STATE_ENTER:
13868 		index = 0;
13869 		break;
13870 	case FCF_EVENT_RPI_ONLINE:
13871 		index = 1;
13872 		break;
13873 	case FCF_EVENT_RPI_OFFLINE:
13874 		index = 2;
13875 		break;
13876 	case FCF_EVENT_RPI_PAUSE:
13877 		index = 3;
13878 		break;
13879 	case FCF_EVENT_RPI_RESUME:
13880 		index = 4;
13881 		break;
13882 	default:
13883 		return (1);
13884 	}
13885 
13886 	events = RPI_ACTION_EVENTS;
13887 	state  = rpip->state;
13888 
13889 	index += (state * events);
13890 	func   = (uint32_t(*) (emlxs_port_t *, RPIobj_t *, uint32_t, void *))
13891 	    emlxs_rpi_action_table[index];
13892 
13893 	if (!func) {
13894 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
13895 		    "rpi_action:%d %s:%s arg=%p. No action. <",
13896 		    rpip->RPI,
13897 		    emlxs_rpi_state_xlate(rpip->state),
13898 		    emlxs_fcf_event_xlate(evt), arg1);
13899 
13900 		return (1);
13901 	}
13902 
13903 	rval = (func)(port, rpip, evt, arg1);
13904 
13905 	return (rval);
13906 
13907 } /* emlxs_rpi_action() */
13908 
13909 
13910 static uint32_t
emlxs_rpi_event(emlxs_port_t * port,uint32_t evt,void * arg1)13911 emlxs_rpi_event(emlxs_port_t *port, uint32_t evt,
13912     void *arg1)
13913 {
13914 	RPIobj_t *rpip = NULL;
13915 	uint32_t rval = 0;
13916 
13917 	/* Filter events and acquire fcfi context */
13918 	switch (evt) {
13919 	case FCF_EVENT_RPI_ONLINE:
13920 	case FCF_EVENT_RPI_OFFLINE:
13921 	case FCF_EVENT_RPI_PAUSE:
13922 	case FCF_EVENT_RPI_RESUME:
13923 		rpip = (RPIobj_t *)arg1;
13924 
13925 		if (!rpip) {
13926 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
13927 			    "rpi_event: %s arg=%p. Null RPI found. <",
13928 			    emlxs_fcf_event_xlate(evt), arg1);
13929 
13930 			return (1);
13931 		}
13932 
13933 		break;
13934 
13935 	default:
13936 		return (1);
13937 	}
13938 
13939 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
13940 	    "rpi_event:%d %s:%s arg=%p",
13941 	    rpip->RPI,
13942 	    emlxs_rpi_state_xlate(rpip->state),
13943 	    emlxs_fcf_event_xlate(evt), arg1);
13944 
13945 	rval = emlxs_rpi_action(port, rpip, evt, arg1);
13946 
13947 	return (rval);
13948 
13949 } /* emlxs_rpi_event() */
13950 
13951 
13952 /*ARGSUSED*/
13953 static uint32_t
emlxs_rpi_state(emlxs_port_t * port,RPIobj_t * rpip,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)13954 emlxs_rpi_state(emlxs_port_t *port, RPIobj_t *rpip, uint16_t state,
13955     uint16_t reason, uint32_t explain, void *arg1)
13956 {
13957 	uint32_t rval = 0;
13958 
13959 	if (state >= RPI_ACTION_STATES) {
13960 		return (1);
13961 	}
13962 
13963 	if ((rpip->state == state) &&
13964 	    (reason != FCF_REASON_REENTER)) {
13965 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13966 		    "rpi_state:%d %s:%s:0x%x arg=%p. State not changed. <",
13967 		    rpip->RPI,
13968 		    emlxs_rpi_state_xlate(rpip->state),
13969 		    emlxs_fcf_reason_xlate(reason),
13970 		    explain, arg1);
13971 		return (1);
13972 	}
13973 
13974 	if (!reason) {
13975 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
13976 		    "rpi_state:%d %s-->%s arg=%p",
13977 		    rpip->RPI,
13978 		    emlxs_rpi_state_xlate(rpip->state),
13979 		    emlxs_rpi_state_xlate(state), arg1);
13980 	} else if (reason == FCF_REASON_EVENT) {
13981 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
13982 		    "rpi_state:%d %s-->%s:%s:%s arg=%p",
13983 		    rpip->RPI,
13984 		    emlxs_rpi_state_xlate(rpip->state),
13985 		    emlxs_rpi_state_xlate(state),
13986 		    emlxs_fcf_reason_xlate(reason),
13987 		    emlxs_fcf_event_xlate(explain), arg1);
13988 	} else if (explain) {
13989 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
13990 		    "rpi_state:%d %s-->%s:%s:0x%x arg=%p",
13991 		    rpip->RPI,
13992 		    emlxs_rpi_state_xlate(rpip->state),
13993 		    emlxs_rpi_state_xlate(state),
13994 		    emlxs_fcf_reason_xlate(reason),
13995 		    explain, arg1);
13996 	} else {
13997 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
13998 		    "rpi_state:%d %s-->%s:%s arg=%p",
13999 		    rpip->RPI,
14000 		    emlxs_rpi_state_xlate(rpip->state),
14001 		    emlxs_rpi_state_xlate(state),
14002 		    emlxs_fcf_reason_xlate(reason), arg1);
14003 	}
14004 
14005 	rpip->prev_state = rpip->state;
14006 	rpip->prev_reason = rpip->reason;
14007 	rpip->state = state;
14008 	rpip->reason = reason;
14009 
14010 	rval = emlxs_rpi_action(port, rpip, FCF_EVENT_STATE_ENTER, arg1);
14011 
14012 	return (rval);
14013 
14014 } /* emlxs_rpi_state() */
14015 
14016 
14017 static void
emlxs_rpi_deferred_cmpl(emlxs_port_t * port,RPIobj_t * rpip,uint32_t status)14018 emlxs_rpi_deferred_cmpl(emlxs_port_t *port, RPIobj_t *rpip, uint32_t status)
14019 {
14020 	emlxs_hba_t *hba = HBA;
14021 	emlxs_deferred_cmpl_t *cmpl;
14022 
14023 	if (!rpip->cmpl) {
14024 		return;
14025 	}
14026 
14027 	cmpl = rpip->cmpl;
14028 	rpip->cmpl = 0;
14029 
14030 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14031 	    "rpi_deferred_cmpl:%d. status=%x ...",
14032 	    port->vpip->VPI,
14033 	    status);
14034 
14035 	emlxs_thread_spawn(hba, emlxs_deferred_cmpl_thread, (void *)cmpl,
14036 	    (void*)(uintptr_t)status);
14037 
14038 	return;
14039 
14040 } /* emlxs_rpi_deferred_cmpl() */
14041 
14042 
14043 static void
emlxs_rpi_idle_timer(emlxs_hba_t * hba)14044 emlxs_rpi_idle_timer(emlxs_hba_t *hba)
14045 {
14046 	emlxs_config_t *cfg = &CFG;
14047 	RPIobj_t *rpip;
14048 	uint32_t i;
14049 
14050 	/* This timer monitors for idle timeout of an RPI in a */
14051 	/* RESERVED state. */
14052 	/* This means that the RPI was reserved, but never registered. */
14053 	/* If the RPI sits for too long (~2 secs) in this state we free it */
14054 	rpip = hba->sli.sli4.RPIp;
14055 	for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
14056 		if (rpip->state != RPI_STATE_RESERVED) {
14057 			continue;
14058 		}
14059 
14060 		/* If RPI is active, then clear timer. */
14061 		if (rpip->xri_count) {
14062 			rpip->idle_timer = 0;
14063 			continue;
14064 		}
14065 
14066 		/* If an F-port RPI is found idle, then free it. */
14067 		/* Since an F-port RPI is never registered after the login */
14068 		/* completes, it is safe to free it immediately. */
14069 		if ((rpip->did == FABRIC_DID) ||
14070 		    (rpip->did == SCR_DID)) {
14071 			goto free_it;
14072 		}
14073 
14074 		/* Start idle timer if not already active */
14075 		if (!rpip->idle_timer) {
14076 			rpip->idle_timer = hba->timer_tics +
14077 			    cfg[CFG_FCF_RPI_IDLE_TIMEOUT].current;
14078 		}
14079 
14080 		/* Check for idle timeout */
14081 		if (hba->timer_tics < rpip->idle_timer) {
14082 			continue;
14083 		}
14084 		rpip->idle_timer = 0;
14085 
14086 free_it:
14087 		(void) emlxs_rpi_state(rpip->vpip->port, rpip, RPI_STATE_FREE,
14088 		    FCF_REASON_UNUSED, 0, 0);
14089 	}
14090 
14091 	return;
14092 
14093 }  /* emlxs_rpi_idle_timer() */
14094 
14095 
14096 static RPIobj_t *
emlxs_rpi_alloc(emlxs_port_t * port,uint32_t did)14097 emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did)
14098 {
14099 	emlxs_hba_t *hba = HBA;
14100 	uint16_t	i;
14101 	RPIobj_t	*rpip;
14102 
14103 	rpip = hba->sli.sli4.RPIp;
14104 	for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
14105 		/* To be consistent with SLI3, the RPI assignment */
14106 		/* starts with 1. ONLY one SLI4 HBA in the entire */
14107 		/* system will be sacrificed by one RPI and that  */
14108 		/* is the one having RPI base equal 0. */
14109 		if ((rpip->state == RPI_STATE_FREE) && (rpip->RPI != 0)) {
14110 
14111 			bzero(rpip, sizeof (RPIobj_t));
14112 			rpip->index = i;
14113 			rpip->RPI = emlxs_sli4_index_to_rpi(hba, i);
14114 			rpip->vpip = port->vpip;
14115 			rpip->did = did;
14116 
14117 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14118 			    "rpi_alloc:%d. RPI allocated. >",
14119 			    rpip->RPI);
14120 
14121 			(void) emlxs_rpi_state(port, rpip, RPI_STATE_RESERVED,
14122 			    0, 0, 0);
14123 
14124 			return (rpip);
14125 		}
14126 	}
14127 
14128 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14129 	    "rpi_alloc: Out of RPI objects.");
14130 
14131 	return (NULL);
14132 
14133 } /* emlxs_rpi_alloc() */
14134 
14135 
14136 /* Special routine for VPI object */
14137 static void
emlxs_rpi_alloc_fabric_rpi(emlxs_port_t * port)14138 emlxs_rpi_alloc_fabric_rpi(emlxs_port_t *port)
14139 {
14140 	RPIobj_t	*fabric_rpip;
14141 
14142 	fabric_rpip = port->vpip->fabric_rpip;
14143 
14144 	if (fabric_rpip->state != RPI_STATE_FREE) {
14145 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14146 		    "rpi_alloc_fabric_rpi: Fabric RPI active:%s.",
14147 		    emlxs_rpi_state_xlate(fabric_rpip->state));
14148 		return;
14149 	}
14150 
14151 	bzero(fabric_rpip, sizeof (RPIobj_t));
14152 	fabric_rpip->index = 0xffff;
14153 	fabric_rpip->RPI = FABRIC_RPI;
14154 	fabric_rpip->did = FABRIC_DID;
14155 	fabric_rpip->vpip = port->vpip;
14156 
14157 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14158 	    "rpi_alloc_fabric_rpi: Allocating Fabric RPI. >");
14159 
14160 	(void) emlxs_rpi_state(port, fabric_rpip, RPI_STATE_RESERVED,
14161 	    0, 0, 0);
14162 
14163 	return;
14164 
14165 } /* emlxs_rpi_alloc_fabric_rpi() */
14166 
14167 
14168 static uint32_t
emlxs_rpi_free(emlxs_port_t * port,RPIobj_t * rpip)14169 emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip)
14170 {
14171 	uint32_t rval = 0;
14172 
14173 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14174 	    "rpi_free:%d did=%x. Freeing RPI. >",
14175 	    rpip->RPI, rpip->did);
14176 
14177 	rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
14178 
14179 	return (rval);
14180 
14181 } /* emlxs_rpi_free() */
14182 
14183 
14184 extern RPIobj_t *
emlxs_rpi_find(emlxs_port_t * port,uint16_t rpi)14185 emlxs_rpi_find(emlxs_port_t *port, uint16_t rpi)
14186 {
14187 	emlxs_hba_t *hba = HBA;
14188 	RPIobj_t *rpip;
14189 	uint32_t index;
14190 
14191 	/* Special handling for Fabric RPI */
14192 	if (rpi == FABRIC_RPI) {
14193 		return (port->vpip->fabric_rpip);
14194 	}
14195 
14196 	index = emlxs_sli4_rpi_to_index(hba, rpi);
14197 
14198 	if (index >= hba->sli.sli4.RPICount) {
14199 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14200 		    "rpi_find:%d. RPI Invalid.",
14201 		    rpi);
14202 
14203 		return (NULL);
14204 	}
14205 
14206 	rpip = &hba->sli.sli4.RPIp[index];
14207 
14208 	if (rpip->state == RPI_STATE_FREE) {
14209 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14210 		    "rpi_find:%d  RPI not active",
14211 		    rpi);
14212 
14213 		return (NULL);
14214 	}
14215 
14216 	return (rpip);
14217 
14218 } /* emlxs_rpi_find() */
14219 
14220 
14221 static RPIobj_t *
emlxs_rpi_find_did(emlxs_port_t * port,uint32_t did)14222 emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did)
14223 {
14224 	emlxs_hba_t *hba = HBA;
14225 	RPIobj_t	*rpip;
14226 	RPIobj_t	*rpip1;
14227 	uint32_t	i;
14228 
14229 	rpip1 = NULL;
14230 	rpip = hba->sli.sli4.RPIp;
14231 	for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
14232 		if (rpip->state == RPI_STATE_FREE) {
14233 			continue;
14234 		}
14235 
14236 		if ((rpip->did == did) && (rpip->vpip == port->vpip)) {
14237 			rpip1 = rpip;
14238 			break;
14239 		}
14240 	}
14241 
14242 	return (rpip1);
14243 
14244 } /* emlxs_rpi_find_did() */
14245 
14246 
14247 extern RPIobj_t *
emlxs_rpi_reserve_notify(emlxs_port_t * port,uint32_t did,XRIobj_t * xrip)14248 emlxs_rpi_reserve_notify(emlxs_port_t *port, uint32_t did, XRIobj_t *xrip)
14249 {
14250 	emlxs_hba_t 	*hba = HBA;
14251 	RPIobj_t	*rpip;
14252 
14253 	/* xrip will be NULL for unsolicited BLS requests */
14254 
14255 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14256 		return (NULL);
14257 	}
14258 
14259 	mutex_enter(&EMLXS_FCF_LOCK);
14260 
14261 	rpip = emlxs_rpi_find_did(port, did);
14262 
14263 	if (!rpip) {
14264 		rpip = emlxs_rpi_alloc(port, did);
14265 	}
14266 
14267 	if (!rpip) {
14268 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14269 		    "rpi_reserve_notify: Unable to reserve an rpi. "
14270 		    "did=%x xri=%d.",
14271 		    did, ((xrip)?xrip->XRI:0));
14272 
14273 		mutex_exit(&EMLXS_FCF_LOCK);
14274 		return (NULL);
14275 	}
14276 
14277 	/* Bind the XRI */
14278 	if (xrip) {
14279 		mutex_enter(&EMLXS_FCTAB_LOCK);
14280 		xrip->reserved_rpip = rpip;
14281 		rpip->xri_count++;
14282 		mutex_exit(&EMLXS_FCTAB_LOCK);
14283 	}
14284 
14285 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14286 	    "rpi_reserve_notify:%d  did=%x xri=%d.",
14287 	    rpip->RPI, rpip->did, ((xrip)?xrip->XRI:0));
14288 
14289 	mutex_exit(&EMLXS_FCF_LOCK);
14290 
14291 	return (rpip);
14292 
14293 } /* emlxs_rpi_reserve_notify() */
14294 
14295 
14296 extern RPIobj_t *
emlxs_rpi_alloc_notify(emlxs_port_t * port,uint32_t did)14297 emlxs_rpi_alloc_notify(emlxs_port_t *port, uint32_t did)
14298 {
14299 	emlxs_hba_t *hba = HBA;
14300 	RPIobj_t	*rpip;
14301 
14302 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14303 		return (NULL);
14304 	}
14305 
14306 	mutex_enter(&EMLXS_FCF_LOCK);
14307 
14308 	rpip = emlxs_rpi_alloc(port, did);
14309 
14310 	mutex_exit(&EMLXS_FCF_LOCK);
14311 
14312 	return (rpip);
14313 
14314 } /* emlxs_rpi_alloc_notify() */
14315 
14316 
14317 extern uint32_t
emlxs_rpi_free_notify(emlxs_port_t * port,RPIobj_t * rpip)14318 emlxs_rpi_free_notify(emlxs_port_t *port, RPIobj_t *rpip)
14319 {
14320 	emlxs_hba_t	*hba = HBA;
14321 	uint32_t	rval = 0;
14322 
14323 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14324 		return (1);
14325 	}
14326 
14327 	if (!rpip) {
14328 		return (1);
14329 	}
14330 
14331 	/* Fabric RPI will be handled automatically */
14332 	if (rpip->RPI == FABRIC_RPI) {
14333 		return (1);
14334 	}
14335 
14336 	mutex_enter(&EMLXS_FCF_LOCK);
14337 
14338 	rval =  emlxs_rpi_free(port, rpip);
14339 
14340 	mutex_exit(&EMLXS_FCF_LOCK);
14341 
14342 	return (rval);
14343 
14344 } /* emlxs_rpi_free_notify() */
14345 
14346 
14347 extern uint32_t
emlxs_rpi_pause_notify(emlxs_port_t * port,RPIobj_t * rpip)14348 emlxs_rpi_pause_notify(emlxs_port_t *port, RPIobj_t *rpip)
14349 {
14350 	emlxs_hba_t *hba = HBA;
14351 
14352 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14353 		return (1);
14354 	}
14355 
14356 	if (!rpip) {
14357 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14358 		    "rpi_pause_notify: No RPI provided.");
14359 		return (1);
14360 	}
14361 
14362 	/* Fabric RPI will be handled automatically */
14363 	if (rpip->RPI == FABRIC_RPI) {
14364 		return (1);
14365 	}
14366 
14367 	mutex_enter(&EMLXS_FCF_LOCK);
14368 
14369 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14370 	    "rpi_pause_notify:%d %s. Pausing RPI. >",
14371 	    rpip->RPI,
14372 	    emlxs_rpi_state_xlate(rpip->state));
14373 
14374 	(void) emlxs_rpi_event(port, FCF_EVENT_RPI_PAUSE, rpip);
14375 
14376 	mutex_exit(&EMLXS_FCF_LOCK);
14377 
14378 	return (0);
14379 
14380 } /* emlxs_rpi_pause_notify() */
14381 
14382 
14383 extern uint32_t
emlxs_rpi_online_notify(emlxs_port_t * port,RPIobj_t * rpip,uint32_t did,SERV_PARM * sparam,void * arg1,void * arg2,void * arg3)14384 emlxs_rpi_online_notify(emlxs_port_t *port, RPIobj_t *rpip, uint32_t did,
14385     SERV_PARM *sparam, void *arg1, void *arg2, void *arg3)
14386 {
14387 	emlxs_hba_t *hba = HBA;
14388 	emlxs_deferred_cmpl_t *cmpl;
14389 	uint32_t allocated = 0;
14390 	uint32_t rval = 0;
14391 
14392 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14393 		return (1);
14394 	}
14395 
14396 	if ((did == port->did) && (!(hba->flag & FC_LOOPBACK_MODE))) {
14397 		/* We never register our local port */
14398 		return (1);
14399 	}
14400 
14401 	mutex_enter(&EMLXS_FCF_LOCK);
14402 
14403 	if (!rpip && (did == FABRIC_DID)) {
14404 		/* We never online the Fabric DID other */
14405 		/* than the fabric_rpip */
14406 		rpip = port->vpip->fabric_rpip;
14407 	}
14408 
14409 	if (!rpip) {
14410 		rpip = emlxs_rpi_find_did(port, did);
14411 	}
14412 
14413 	if (!rpip) {
14414 		rpip = emlxs_rpi_alloc(port, did);
14415 		allocated = 1;
14416 	}
14417 
14418 	if (!rpip) {
14419 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14420 		    "rpi_online_notify: Unable to allocate an rpi. did=%x",
14421 		    did);
14422 
14423 		mutex_exit(&EMLXS_FCF_LOCK);
14424 		return (1);
14425 	}
14426 
14427 	/* Initialize RPI node info */
14428 	bcopy((void *)sparam, (void *)&rpip->sparam, sizeof (SERV_PARM));
14429 
14430 	if (arg1 || arg2 || arg3) {
14431 		cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
14432 		    sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
14433 
14434 		cmpl->port = port;
14435 		cmpl->arg1 = arg1;
14436 		cmpl->arg2 = arg2;
14437 		cmpl->arg3 = arg3;
14438 
14439 		/* For safety */
14440 		if (rpip->cmpl) {
14441 			emlxs_rpi_deferred_cmpl(port, rpip, 1);
14442 		}
14443 
14444 		rpip->cmpl = cmpl;
14445 	}
14446 
14447 	if ((rpip->RPI == FABRIC_RPI) ||
14448 	    (hba->flag & FC_PT_TO_PT)) {
14449 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14450 		    "rpi_online_notify:%d %s. %s. Login cmpl.",
14451 		    rpip->RPI,
14452 		    emlxs_rpi_state_xlate(rpip->state),
14453 		    ((allocated)? "Allocated":"Updated"));
14454 
14455 		rval = emlxs_vpi_logi_cmpl_notify(port, rpip);
14456 
14457 		if (rval && rpip->cmpl) {
14458 			kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14459 			rpip->cmpl = 0;
14460 		}
14461 
14462 		mutex_exit(&EMLXS_FCF_LOCK);
14463 		return (rval);
14464 	}
14465 
14466 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14467 	    "rpi_online_notify:%d %s. %s. Onlining RPI. >",
14468 	    rpip->RPI,
14469 	    emlxs_rpi_state_xlate(rpip->state),
14470 	    ((allocated)? "Allocated":"Updated"));
14471 
14472 	(void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE, rpip);
14473 
14474 	if (rpip->cmpl) {
14475 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14476 		    "rpi_online_notify:%d %s. Deferred args not completed.",
14477 		    rpip->RPI,
14478 		    emlxs_rpi_state_xlate(rpip->state));
14479 
14480 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14481 		rpip->cmpl = 0;
14482 
14483 		mutex_exit(&EMLXS_FCF_LOCK);
14484 		return (1);
14485 	}
14486 
14487 	mutex_exit(&EMLXS_FCF_LOCK);
14488 	return (0);
14489 
14490 } /* emlxs_rpi_online_notify() */
14491 
14492 
14493 extern uint32_t
emlxs_rpi_offline_notify(emlxs_port_t * port,RPIobj_t * rpip,void * arg1,void * arg2,void * arg3)14494 emlxs_rpi_offline_notify(emlxs_port_t *port, RPIobj_t *rpip,
14495     void *arg1, void *arg2, void *arg3)
14496 {
14497 	emlxs_hba_t *hba = HBA;
14498 	emlxs_deferred_cmpl_t *cmpl;
14499 
14500 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14501 		return (1);
14502 	}
14503 
14504 	if (!rpip) {
14505 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14506 		    "rpi_offline_notify: No RPI provided.");
14507 		return (1);
14508 	}
14509 
14510 	/* Fabric RPI will be handled automatically */
14511 	if (rpip->RPI == FABRIC_RPI) {
14512 		return (1);
14513 	}
14514 
14515 	mutex_enter(&EMLXS_FCF_LOCK);
14516 
14517 	if (arg1 || arg2 || arg3) {
14518 		cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
14519 		    sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
14520 
14521 		cmpl->port = port;
14522 		cmpl->arg1 = arg1;
14523 		cmpl->arg2 = arg2;
14524 		cmpl->arg3 = arg3;
14525 
14526 		rpip->cmpl = cmpl;
14527 	}
14528 
14529 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14530 	    "rpi_offline_notify:%d %s. Offlining RPI. >",
14531 	    rpip->RPI,
14532 	    emlxs_rpi_state_xlate(rpip->state));
14533 
14534 	(void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip);
14535 
14536 	if (rpip->cmpl) {
14537 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14538 		    "rpi_offline_notify:%d %s. Deferred args not completed.",
14539 		    rpip->RPI,
14540 		    emlxs_rpi_state_xlate(rpip->state));
14541 
14542 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14543 		rpip->cmpl = 0;
14544 
14545 		mutex_exit(&EMLXS_FCF_LOCK);
14546 		return (1);
14547 	}
14548 
14549 	mutex_exit(&EMLXS_FCF_LOCK);
14550 
14551 	return (0);
14552 
14553 } /* emlxs_rpi_offline_notify() */
14554 
14555 
14556 extern uint32_t
emlxs_rpi_resume_notify(emlxs_port_t * port,RPIobj_t * rpip,emlxs_buf_t * sbp)14557 emlxs_rpi_resume_notify(emlxs_port_t *port, RPIobj_t *rpip, emlxs_buf_t *sbp)
14558 {
14559 	emlxs_hba_t *hba = HBA;
14560 	emlxs_deferred_cmpl_t *cmpl;
14561 
14562 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14563 		return (1);
14564 	}
14565 
14566 	if (!rpip) {
14567 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14568 		    "rpi_resume_notify: No RPI provided.");
14569 		return (1);
14570 	}
14571 
14572 	/* Fabric RPI will be handled automatically */
14573 	if (rpip->RPI == FABRIC_RPI) {
14574 		return (1);
14575 	}
14576 
14577 	mutex_enter(&EMLXS_FCF_LOCK);
14578 
14579 	if (rpip->state != RPI_STATE_PAUSED) {
14580 		mutex_exit(&EMLXS_FCF_LOCK);
14581 		return (1);
14582 	}
14583 
14584 	if (sbp) {
14585 		cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
14586 		    sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
14587 
14588 		cmpl->port = port;
14589 		cmpl->arg1 = (void *)sbp;
14590 		cmpl->arg2 = 0;
14591 		cmpl->arg3 = 0;
14592 
14593 		rpip->cmpl = cmpl;
14594 	}
14595 
14596 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14597 	    "rpi_resume_notify:%d %s. Resuming RPI. >",
14598 	    rpip->RPI,
14599 	    emlxs_rpi_state_xlate(rpip->state));
14600 
14601 	(void) emlxs_rpi_event(port, FCF_EVENT_RPI_RESUME, rpip);
14602 
14603 	if (rpip->cmpl) {
14604 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14605 		    "rpi_resume_notify:%d %s. Deferred args not completed.",
14606 		    rpip->RPI,
14607 		    emlxs_rpi_state_xlate(rpip->state));
14608 
14609 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14610 		rpip->cmpl = 0;
14611 
14612 		mutex_exit(&EMLXS_FCF_LOCK);
14613 		return (1);
14614 	}
14615 
14616 	mutex_exit(&EMLXS_FCF_LOCK);
14617 
14618 	return (0);
14619 
14620 } /* emlxs_rpi_resume_notify() */
14621 
14622 
14623 /*ARGSUSED*/
14624 static uint32_t
emlxs_rpi_free_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14625 emlxs_rpi_free_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14626     void *arg1)
14627 {
14628 	emlxs_hba_t *hba = HBA;
14629 	XRIobj_t	*xrip;
14630 	XRIobj_t	*next_xrip;
14631 
14632 	if (rpip->state != RPI_STATE_FREE) {
14633 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14634 		    "rpi_free_action:%d %s:%s arg=%p. "
14635 		    "Invalid state. <",
14636 		    rpip->RPI,
14637 		    emlxs_rpi_state_xlate(rpip->state),
14638 		    emlxs_fcf_event_xlate(evt), arg1);
14639 		return (1);
14640 	}
14641 
14642 	if (rpip->cmpl) {
14643 		emlxs_rpi_deferred_cmpl(port, rpip, 1);
14644 	}
14645 
14646 	if (rpip->vpip->p2p_rpip == rpip) {
14647 		rpip->vpip->p2p_rpip = NULL;
14648 	}
14649 
14650 	/* Break node/RPI binding */
14651 	rw_enter(&port->node_rwlock, RW_WRITER);
14652 	if (rpip->node) {
14653 		rpip->node->rpip = NULL;
14654 		rpip->node = NULL;
14655 	}
14656 	rw_exit(&port->node_rwlock);
14657 
14658 	/* Remove all XRIs under this RPI */
14659 	mutex_enter(&EMLXS_FCTAB_LOCK);
14660 	xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
14661 	while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
14662 		next_xrip = xrip->_f;
14663 		if (xrip->rpip == rpip) {
14664 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14665 			    "rpi_free_action:%d xri_count=%d. "
14666 			    "Removing XRI:%d iotag:%d.",
14667 			    rpip->RPI,
14668 			    rpip->xri_count,
14669 			    xrip->XRI, xrip->iotag);
14670 
14671 			rpip->xri_count--;
14672 			xrip->rpip = NULL;
14673 		}
14674 
14675 		if (xrip->reserved_rpip == rpip) {
14676 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14677 			    "rpi_free_action:%d xri_count=%d. "
14678 			    "Removing XRI:%d iotag:%d.",
14679 			    rpip->RPI,
14680 			    rpip->xri_count,
14681 			    xrip->XRI, xrip->iotag);
14682 
14683 			rpip->xri_count--;
14684 			xrip->reserved_rpip = NULL;
14685 		}
14686 
14687 		xrip = next_xrip;
14688 	}
14689 	mutex_exit(&EMLXS_FCTAB_LOCK);
14690 
14691 	if (rpip->xri_count) {
14692 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14693 		    "rpi_free_action:%d. xri_count=%d",
14694 		    rpip->RPI,
14695 		    rpip->xri_count);
14696 	}
14697 
14698 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14699 	    "rpi_free_action:%d flag=%x. RPI freed. <",
14700 	    rpip->RPI,
14701 	    rpip->flag);
14702 
14703 	rpip->flag = 0;
14704 
14705 	return (0);
14706 
14707 } /* emlxs_rpi_free_action() */
14708 
14709 
14710 /*ARGSUSED*/
14711 static uint32_t
emlxs_rpi_online_evt_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14712 emlxs_rpi_online_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14713     void *arg1)
14714 {
14715 	uint32_t rval = 1;
14716 
14717 	if (evt != FCF_EVENT_RPI_ONLINE) {
14718 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14719 		    "rpi_online_evt_action:%d %s:%s arg=%p. "
14720 		    "Invalid event type. <",
14721 		    rpip->RPI,
14722 		    emlxs_rpi_state_xlate(rpip->state),
14723 		    emlxs_fcf_event_xlate(evt), arg1);
14724 		return (1);
14725 	}
14726 
14727 	switch (rpip->state) {
14728 	case RPI_STATE_REG:
14729 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14730 		    "rpi_online_evt_action:%d flag=%x. Registering.",
14731 		    rpip->RPI,
14732 		    rpip->flag);
14733 
14734 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG,
14735 		    FCF_REASON_REENTER, evt, arg1);
14736 		break;
14737 
14738 	default:
14739 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14740 		    "rpi_online_evt_action:%d flag=%x. Registering.",
14741 		    rpip->RPI,
14742 		    rpip->flag);
14743 
14744 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG,
14745 		    FCF_REASON_EVENT, evt, arg1);
14746 		break;
14747 	}
14748 
14749 	return (rval);
14750 
14751 } /* emlxs_rpi_online_evt_action() */
14752 
14753 
14754 /*ARGSUSED*/
14755 static uint32_t
emlxs_rpi_offline_evt_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14756 emlxs_rpi_offline_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14757     void *arg1)
14758 {
14759 	uint32_t rval = 1;
14760 
14761 	if (evt != FCF_EVENT_RPI_OFFLINE) {
14762 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14763 		    "rpi_offline_evt_action:%d %s:%s arg=%p. "
14764 		    "Invalid event type. <",
14765 		    rpip->RPI,
14766 		    emlxs_rpi_state_xlate(rpip->state),
14767 		    emlxs_fcf_event_xlate(evt), arg1);
14768 		return (1);
14769 	}
14770 
14771 	switch (rpip->state) {
14772 	case RPI_STATE_RESERVED:
14773 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14774 		    "rpi_offline_evt_action:%d flag=%x. Freeing RPI.",
14775 		    rpip->RPI,
14776 		    rpip->flag);
14777 
14778 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE,
14779 		    FCF_REASON_EVENT, evt, arg1);
14780 		break;
14781 
14782 	case RPI_STATE_UNREG:
14783 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14784 		    "rpi_offline_evt_action:%d flag=%x. "
14785 		    "Already unregistering. <",
14786 		    rpip->RPI,
14787 		    rpip->flag);
14788 
14789 		break;
14790 
14791 	default:
14792 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14793 		    "rpi_offline_evt_action:%d flag=%x. Unregistering.",
14794 		    rpip->RPI,
14795 		    rpip->flag);
14796 
14797 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
14798 		    FCF_REASON_EVENT, evt, arg1);
14799 		break;
14800 
14801 	}
14802 
14803 	return (rval);
14804 
14805 } /* emlxs_rpi_offline_evt_action() */
14806 
14807 
14808 /*ARGSUSED*/
14809 static uint32_t
emlxs_rpi_pause_evt_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14810 emlxs_rpi_pause_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14811     void *arg1)
14812 {
14813 	VPIobj_t *vpip;
14814 	uint32_t rval = 1;
14815 
14816 	vpip = rpip->vpip;
14817 
14818 	if (evt != FCF_EVENT_RPI_PAUSE) {
14819 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14820 		    "rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
14821 		    "Invalid event type. <",
14822 		    rpip->RPI,
14823 		    emlxs_rpi_state_xlate(rpip->state),
14824 		    emlxs_fcf_event_xlate(evt), arg1,
14825 		    rpip->flag);
14826 		return (1);
14827 	}
14828 
14829 	switch (rpip->state) {
14830 	case RPI_STATE_RESERVED:
14831 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14832 		    "rpi_pause_evt_action:%d flag=%x. Freeing RPI.",
14833 		    rpip->RPI,
14834 		    rpip->flag);
14835 
14836 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE,
14837 		    FCF_REASON_EVENT, evt, arg1);
14838 		break;
14839 
14840 	case RPI_STATE_UNREG:
14841 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14842 		    "rpi_pause_evt_action:%d flag=%x. Not online. <",
14843 		    rpip->RPI,
14844 		    rpip->flag);
14845 
14846 		break;
14847 
14848 	case RPI_STATE_PAUSED:
14849 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14850 		    "rpi_pause_evt_action:%d flag=%x. Already paused. <",
14851 		    rpip->RPI,
14852 		    rpip->flag);
14853 
14854 		break;
14855 
14856 	case RPI_STATE_REG:
14857 	case RPI_STATE_ONLINE:
14858 	case RPI_STATE_RESUME:
14859 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14860 		    "rpi_pause_evt_action:%d flag=%x. Pausing.",
14861 		    rpip->RPI,
14862 		    rpip->flag);
14863 
14864 		/* Don't pause an RPI, if the VPI is not pausing too */
14865 		if (!(vpip->flag & EMLXS_VPI_PAUSE_REQ)) {
14866 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14867 			    "rpi_pause_evt_action:%d rpi_online=%d,%d "
14868 			    "xri_count=%d. VPI:%d pause not requested.  "
14869 			    "Unregistering.", rpip->RPI,
14870 			    vpip->rpi_online, vpip->rpi_paused,
14871 			    rpip->xri_count, vpip->VPI);
14872 
14873 			rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
14874 			    FCF_REASON_EVENT, evt, arg1);
14875 			break;
14876 		}
14877 
14878 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_PAUSED,
14879 		    FCF_REASON_EVENT, evt, arg1);
14880 		break;
14881 
14882 	default:
14883 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14884 		    "rpi_pause_evt_action:%d flag=%x. <",
14885 		    rpip->RPI,
14886 		    rpip->flag);
14887 		break;
14888 	}
14889 
14890 	return (rval);
14891 
14892 } /* emlxs_rpi_pause_evt_action() */
14893 
14894 
14895 /*ARGSUSED*/
14896 static uint32_t
emlxs_rpi_resume_evt_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14897 emlxs_rpi_resume_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14898     void *arg1)
14899 {
14900 	uint32_t rval = 1;
14901 
14902 	if (evt != FCF_EVENT_RPI_RESUME) {
14903 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14904 		    "rpi_resume_evt_action:%d %s:%s arg=%p flag=%x. "
14905 		    "Invalid event type. <",
14906 		    rpip->RPI,
14907 		    emlxs_rpi_state_xlate(rpip->state),
14908 		    emlxs_fcf_event_xlate(evt), arg1,
14909 		    rpip->flag);
14910 		return (1);
14911 	}
14912 
14913 	switch (rpip->state) {
14914 	case RPI_STATE_PAUSED:
14915 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14916 		    "rpi_resume_evt_action:%d flag=%x. Resuming.",
14917 		    rpip->RPI,
14918 		    rpip->flag);
14919 
14920 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME,
14921 		    FCF_REASON_EVENT, evt, arg1);
14922 		break;
14923 
14924 	default:
14925 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14926 		    "rpi_resume_evt_action:%d flag=%x. Not paused. <",
14927 		    rpip->RPI,
14928 		    rpip->flag);
14929 		break;
14930 	}
14931 
14932 	return (rval);
14933 
14934 } /* emlxs_rpi_resume_evt_action() */
14935 
14936 
14937 /*ARGSUSED*/
14938 static uint32_t
emlxs_rpi_reserved_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14939 emlxs_rpi_reserved_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14940     void *arg1)
14941 {
14942 	VPIobj_t *vpip;
14943 
14944 	vpip = rpip->vpip;
14945 
14946 	if (rpip->state != RPI_STATE_RESERVED) {
14947 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14948 		    "rpi_reserved_action:%d %s:%s arg=%p. "
14949 		    "Invalid state. <",
14950 		    rpip->RPI,
14951 		    emlxs_rpi_state_xlate(rpip->state),
14952 		    emlxs_fcf_event_xlate(evt), arg1);
14953 		return (1);
14954 	}
14955 
14956 	if (rpip->prev_state != RPI_STATE_FREE) {
14957 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14958 		    "rpi_reserved_action:%d %s:%s arg=%p. "
14959 		    "Invalid previous state. %s  <",
14960 		    rpip->RPI,
14961 		    emlxs_rpi_state_xlate(rpip->state),
14962 		    emlxs_fcf_event_xlate(evt), arg1,
14963 		    emlxs_rpi_state_xlate(rpip->prev_state));
14964 
14965 		return (1);
14966 	}
14967 
14968 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14969 	    "rpi_reserved_action:%d rpi_online=%d,%d. <",
14970 	    rpip->RPI,
14971 	    vpip->rpi_online, vpip->rpi_paused);
14972 
14973 	return (0);
14974 
14975 } /* emlxs_rpi_reserved_action() */
14976 
14977 
14978 /*ARGSUSED*/
14979 static uint32_t
emlxs_rpi_offline_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14980 emlxs_rpi_offline_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14981     void *arg1)
14982 {
14983 	uint32_t rval = 0;
14984 	VPIobj_t *vpip;
14985 
14986 	vpip = rpip->vpip;
14987 
14988 	if (rpip->state != RPI_STATE_OFFLINE) {
14989 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14990 		    "rpi_offline_action:%d %s:%s arg=%p. "
14991 		    "Invalid state. <",
14992 		    rpip->RPI,
14993 		    emlxs_rpi_state_xlate(rpip->state),
14994 		    emlxs_fcf_event_xlate(evt), arg1);
14995 		return (1);
14996 	}
14997 
14998 	if (rpip->flag & EMLXS_RPI_PAUSED) {
14999 		rpip->flag &= ~EMLXS_RPI_PAUSED;
15000 
15001 		if (vpip->rpi_paused) {
15002 			vpip->rpi_paused--;
15003 		}
15004 	}
15005 
15006 	if (rpip->flag & EMLXS_RPI_VPI) {
15007 		rpip->flag &= ~EMLXS_RPI_VPI;
15008 
15009 		if (vpip->rpi_online) {
15010 			vpip->rpi_online--;
15011 		}
15012 
15013 		/* Added protection */
15014 		if (vpip->rpi_online < vpip->rpi_paused) {
15015 			vpip->rpi_paused = vpip->rpi_online;
15016 		}
15017 	}
15018 
15019 	if (rpip->RPI == FABRIC_RPI) {
15020 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15021 		    "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. "
15022 		    "Fabric RPI offline. Freeing.",
15023 		    rpip->RPI,
15024 		    vpip->rpi_online, vpip->rpi_paused,
15025 		    rpip->xri_count);
15026 
15027 		/* Free RPI */
15028 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
15029 
15030 		return (rval);
15031 	}
15032 
15033 	if ((vpip->rpi_online == 0) ||
15034 	    (vpip->rpi_online == vpip->rpi_paused)) {
15035 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15036 		    "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. "
15037 		    "RPI offline. "
15038 		    "Notifying VPI:%d >",
15039 		    rpip->RPI,
15040 		    vpip->rpi_online, vpip->rpi_paused,
15041 		    rpip->xri_count,
15042 		    vpip->VPI);
15043 
15044 		/* Notify VPI */
15045 		(void) emlxs_vpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip);
15046 
15047 	} else {
15048 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15049 		    "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. "
15050 		    "RPI offline. Freeing.",
15051 		    rpip->RPI,
15052 		    vpip->rpi_online, vpip->rpi_paused,
15053 		    rpip->xri_count);
15054 	}
15055 
15056 	/* Free RPI */
15057 	rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
15058 
15059 	return (rval);
15060 
15061 } /* emlxs_rpi_offline_action() */
15062 
15063 
15064 /*ARGSUSED*/
15065 static uint32_t
emlxs_rpi_paused_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15066 emlxs_rpi_paused_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15067     void *arg1)
15068 {
15069 	VPIobj_t *vpip;
15070 	uint32_t rval = 0;
15071 
15072 	vpip = rpip->vpip;
15073 
15074 	if (rpip->state != RPI_STATE_PAUSED) {
15075 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15076 		    "rpi_paused_action:%d %s:%s arg=%p. "
15077 		    "Invalid state. <",
15078 		    rpip->RPI,
15079 		    emlxs_rpi_state_xlate(rpip->state),
15080 		    emlxs_fcf_event_xlate(evt), arg1);
15081 		return (1);
15082 	}
15083 
15084 	if (!(vpip->flag & EMLXS_VPI_PAUSE_REQ)) {
15085 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15086 		    "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. "
15087 		    "VPI:%d pause not requested.  Unregistering.",
15088 		    rpip->RPI,
15089 		    vpip->rpi_online, vpip->rpi_paused,
15090 		    rpip->xri_count,
15091 		    vpip->VPI);
15092 
15093 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
15094 		    FCF_REASON_EVENT, evt, arg1);
15095 		return (rval);
15096 	}
15097 
15098 	if (!(rpip->flag & EMLXS_RPI_PAUSED)) {
15099 		rpip->flag |= EMLXS_RPI_PAUSED;
15100 		vpip->rpi_paused++;
15101 	}
15102 
15103 	/* Check if all RPI's have been paused for a VPI */
15104 	if (vpip->rpi_online == vpip->rpi_paused) {
15105 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15106 		    "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. "
15107 		    "RPI paused. "
15108 		    "Notifying VPI:%d >",
15109 		    rpip->RPI,
15110 		    vpip->rpi_online, vpip->rpi_paused,
15111 		    rpip->xri_count,
15112 		    vpip->VPI);
15113 
15114 		/* Notify VPI */
15115 		(void) emlxs_vpi_event(port, FCF_EVENT_RPI_PAUSE, rpip);
15116 
15117 	} else {
15118 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15119 		    "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. "
15120 		    "RPI paused. <",
15121 		    rpip->RPI,
15122 		    vpip->rpi_online, vpip->rpi_paused,
15123 		    rpip->xri_count);
15124 	}
15125 
15126 	return (0);
15127 
15128 } /* emlxs_rpi_paused_action() */
15129 
15130 
15131 /*ARGSUSED*/
15132 static uint32_t
emlxs_rpi_unreg_failed_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15133 emlxs_rpi_unreg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15134     void *arg1)
15135 {
15136 	uint32_t rval = 0;
15137 
15138 	rpip->attempts++;
15139 
15140 	if (rpip->state != RPI_STATE_UNREG_FAILED) {
15141 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15142 		    "rpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
15143 		    "Invalid state. <",
15144 		    rpip->RPI,
15145 		    emlxs_rpi_state_xlate(rpip->state),
15146 		    emlxs_fcf_event_xlate(evt), arg1,
15147 		    rpip->attempts);
15148 		return (1);
15149 	}
15150 
15151 	if ((rpip->reason == FCF_REASON_SEND_FAILED) ||
15152 	    !(rpip->flag & EMLXS_RPI_REG)) {
15153 
15154 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15155 		    "rpi_unreg_failed_action:%d reason=%x flag=%x. "
15156 		    "Going offline.",
15157 		    rpip->RPI,
15158 		    rpip->reason,
15159 		    rpip->flag);
15160 
15161 		rpip->flag &= ~EMLXS_RPI_REG;
15162 
15163 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15164 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15165 	} else {
15166 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15167 		    "rpi_unreg_failed_action:%d flag=%x. Going online.",
15168 		    rpip->RPI,
15169 		    rpip->flag);
15170 
15171 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15172 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15173 	}
15174 
15175 	return (rval);
15176 
15177 } /* emlxs_rpi_unreg_failed_action() */
15178 
15179 
15180 static void
emlxs_rpi_unreg_handler(emlxs_port_t * port,RPIobj_t * rpip)15181 emlxs_rpi_unreg_handler(emlxs_port_t *port, RPIobj_t *rpip)
15182 {
15183 	emlxs_hba_t *hba = HBA;
15184 	VPIobj_t *vpip = rpip->vpip;
15185 	emlxs_node_t *node = rpip->node;
15186 	XRIobj_t *xrip;
15187 	XRIobj_t *next_xrip;
15188 
15189 	/* Special handling for Fabric RPI */
15190 	if (rpip->RPI == FABRIC_RPI) {
15191 		if (node) {
15192 			(void) emlxs_tx_node_flush(port, node, 0, 0, 0);
15193 			(void) emlxs_chipq_node_flush(port, 0, node, 0);
15194 		}
15195 
15196 		/* Clear all reserved XRIs under this RPI */
15197 		mutex_enter(&EMLXS_FCTAB_LOCK);
15198 		xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
15199 		while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
15200 			next_xrip = xrip->_f;
15201 			/* We don't need to worry about xrip->reserved_rpip */
15202 			/* here because the Fabric RPI can never be reserved */
15203 			/* by an xri. */
15204 			if ((xrip->rpip == rpip) &&
15205 			    (xrip->flag & EMLXS_XRI_RESERVED)) {
15206 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15207 				    "rpi_unreg_handler:%d xri_count=%d. "
15208 				    "Unreserving XRI:%d iotag:%d.",
15209 				    rpip->RPI,
15210 				    rpip->xri_count,
15211 				    xrip->XRI, xrip->iotag);
15212 
15213 				(void) emlxs_sli4_unreserve_xri(port,
15214 				    xrip->XRI, 0);
15215 			}
15216 			xrip = next_xrip;
15217 		}
15218 		mutex_exit(&EMLXS_FCTAB_LOCK);
15219 	}
15220 
15221 	rpip->flag &= ~EMLXS_RPI_REG;
15222 
15223 	if (rpip->flag & EMLXS_RPI_PAUSED) {
15224 		rpip->flag &= ~EMLXS_RPI_PAUSED;
15225 
15226 		if (vpip->rpi_paused) {
15227 			vpip->rpi_paused--;
15228 		}
15229 	}
15230 
15231 	if (rpip->flag & EMLXS_RPI_VPI) {
15232 		rpip->flag &= ~EMLXS_RPI_VPI;
15233 
15234 		if (vpip->rpi_online) {
15235 			vpip->rpi_online--;
15236 		}
15237 
15238 		/* Added protection */
15239 		if (vpip->rpi_online < vpip->rpi_paused) {
15240 			vpip->rpi_paused = vpip->rpi_online;
15241 		}
15242 	}
15243 
15244 	rw_enter(&port->node_rwlock, RW_WRITER);
15245 	if (node) {
15246 		rpip->node = NULL;
15247 		node->rpip = NULL;
15248 	}
15249 	rw_exit(&port->node_rwlock);
15250 
15251 	if (node) {
15252 		emlxs_node_rm(port, node);
15253 	}
15254 
15255 	return;
15256 
15257 } /* emlxs_rpi_unreg_handler() */
15258 
15259 
15260 /*ARGSUSED*/
15261 static uint32_t
emlxs_rpi_unreg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)15262 emlxs_rpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
15263 {
15264 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
15265 	MAILBOX4 *mb4;
15266 	RPIobj_t *rpip;
15267 
15268 	mutex_enter(&EMLXS_FCF_LOCK);
15269 
15270 	rpip = (RPIobj_t *)mbq->context;
15271 
15272 	mb4 = (MAILBOX4 *)mbq;
15273 
15274 	if (rpip->state != RPI_STATE_UNREG) {
15275 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15276 		    "rpi_unreg_mbcmpl:%d state=%s. "
15277 		    "No longer in RPI_STATE_UNREG.",
15278 		    rpip->RPI,
15279 		    emlxs_rpi_state_xlate(rpip->state));
15280 
15281 		mutex_exit(&EMLXS_FCF_LOCK);
15282 		return (0);
15283 	}
15284 
15285 	if (mb4->mbxStatus) {
15286 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15287 		    "rpi_unreg_mbcmpl:%d failed. %s. >",
15288 		    rpip->RPI,
15289 		    emlxs_mb_xlate_status(mb4->mbxStatus));
15290 
15291 		(void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
15292 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
15293 
15294 		mutex_exit(&EMLXS_FCF_LOCK);
15295 		return (0);
15296 	}
15297 
15298 	emlxs_rpi_unreg_handler(port, rpip);
15299 
15300 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15301 	    "rpi_unreg_mbcmpl:%d Unregistered. Unreg complete. >",
15302 	    rpip->RPI);
15303 
15304 	(void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_CMPL,
15305 	    0, 0, 0);
15306 
15307 	mutex_exit(&EMLXS_FCF_LOCK);
15308 	return (0);
15309 
15310 } /* emlxs_rpi_unreg_mbcmpl() */
15311 
15312 
15313 /*ARGSUSED*/
15314 static uint32_t
emlxs_rpi_unreg_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15315 emlxs_rpi_unreg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15316     void *arg1)
15317 {
15318 	emlxs_hba_t *hba = HBA;
15319 	MAILBOX4 *mb4;
15320 	MAILBOXQ *mbq;
15321 	uint32_t rval = 0;
15322 	VPIobj_t *vpip = rpip->vpip;
15323 
15324 	if (rpip->state != RPI_STATE_UNREG) {
15325 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15326 		    "rpi_unreg_action:%d %s:%s arg=%p. "
15327 		    "Invalid state. <",
15328 		    rpip->RPI,
15329 		    emlxs_rpi_state_xlate(rpip->state),
15330 		    emlxs_fcf_event_xlate(evt), arg1);
15331 		return (1);
15332 	}
15333 
15334 	if (!(rpip->flag & EMLXS_RPI_REG)) {
15335 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15336 		    "rpi_unreg_action:%d. Not registered. Going offline.",
15337 		    rpip->RPI);
15338 
15339 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15340 		    FCF_REASON_EVENT, evt, arg1);
15341 
15342 		return (rval);
15343 	}
15344 
15345 	if (rpip->prev_state != RPI_STATE_UNREG_FAILED) {
15346 		rpip->attempts = 0;
15347 	}
15348 
15349 	if (rpip->RPI == FABRIC_RPI) {
15350 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15351 		    "rpi_unreg_action:%d did=%x vpi=%d. Fabric RPI. "
15352 		    "Going offline.",
15353 		    rpip->RPI,
15354 		    rpip->did,
15355 		    rpip->vpip->VPI);
15356 
15357 		/* Don't send UNREG_RPI, but process it as if we did */
15358 		emlxs_rpi_unreg_handler(port, rpip);
15359 
15360 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15361 		    FCF_REASON_EVENT, evt, arg1);
15362 
15363 		return (rval);
15364 	}
15365 
15366 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15367 	    "rpi_unreg_action:%d attempts=%d. Sending UNREG_RPI. <",
15368 	    rpip->RPI,
15369 	    rpip->attempts);
15370 
15371 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
15372 
15373 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
15374 		    FCF_REASON_NO_MBOX, 0, arg1);
15375 
15376 		return (rval);
15377 	}
15378 	mb4 = (MAILBOX4*)mbq;
15379 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
15380 
15381 	mbq->nonembed = NULL;
15382 	mbq->mbox_cmpl = emlxs_rpi_unreg_mbcmpl;
15383 	mbq->context = (void *)rpip;
15384 	mbq->port = (void *)port;
15385 
15386 	mb4->mbxCommand = MBX_UNREG_RPI;
15387 	mb4->mbxOwner = OWN_HOST;
15388 	mb4->un.varUnregLogin.rpi = rpip->RPI;
15389 	mb4->un.varUnregLogin.vpi = vpip->VPI;
15390 
15391 	if (rpip->cmpl) {
15392 		mbq->sbp = rpip->cmpl->arg1;
15393 		mbq->ubp = rpip->cmpl->arg2;
15394 		mbq->iocbq = rpip->cmpl->arg3;
15395 	}
15396 
15397 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
15398 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
15399 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
15400 
15401 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
15402 		    FCF_REASON_SEND_FAILED, rval, arg1);
15403 
15404 		return (rval);
15405 	}
15406 
15407 	if (rpip->cmpl) {
15408 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
15409 		rpip->cmpl = 0;
15410 	}
15411 
15412 	return (0);
15413 
15414 } /* emlxs_rpi_unreg_action() */
15415 
15416 
15417 /*ARGSUSED*/
15418 static uint32_t
emlxs_rpi_unreg_cmpl_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15419 emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15420     void *arg1)
15421 {
15422 	uint32_t rval = 0;
15423 
15424 	if (rpip->state != RPI_STATE_UNREG_CMPL) {
15425 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15426 		    "rpi_unreg_cmpl_action:%d %s:%s arg=%p. "
15427 		    "Invalid state. <",
15428 		    rpip->RPI,
15429 		    emlxs_rpi_state_xlate(rpip->state),
15430 		    emlxs_fcf_event_xlate(evt), arg1);
15431 		return (1);
15432 	}
15433 
15434 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15435 	    "rpi_unreg_cmpl_action:%d flag=%x. Going offline.",
15436 	    rpip->RPI,
15437 	    rpip->flag);
15438 
15439 	rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15440 	    FCF_REASON_EVENT, evt, arg1);
15441 
15442 	return (rval);
15443 
15444 } /* emlxs_rpi_unreg_cmpl_action() */
15445 
15446 
15447 /*ARGSUSED*/
15448 static uint32_t
emlxs_rpi_reg_failed_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15449 emlxs_rpi_reg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15450     void *arg1)
15451 {
15452 	uint32_t rval = 0;
15453 
15454 	rpip->attempts++;
15455 
15456 	if (rpip->state != RPI_STATE_REG_FAILED) {
15457 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15458 		    "rpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
15459 		    "Invalid state. <",
15460 		    rpip->RPI,
15461 		    emlxs_rpi_state_xlate(rpip->state),
15462 		    emlxs_fcf_event_xlate(evt), arg1,
15463 		    rpip->attempts);
15464 		return (1);
15465 	}
15466 
15467 	if ((rpip->reason == FCF_REASON_SEND_FAILED) ||
15468 	    !(rpip->flag & EMLXS_RPI_REG)) {
15469 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15470 		    "rpi_reg_failed_action:%d reason=%x flag=%x. "
15471 		    "Going offline.",
15472 		    rpip->RPI,
15473 		    rpip->reason,
15474 		    rpip->flag);
15475 
15476 		rpip->flag &= ~EMLXS_RPI_REG;
15477 
15478 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15479 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15480 	} else {
15481 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15482 		    "rpi_reg_failed_action:%d flag=%x. Unregistering",
15483 		    rpip->RPI,
15484 		    rpip->flag);
15485 
15486 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
15487 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15488 	}
15489 
15490 	return (rval);
15491 
15492 } /* emlxs_rpi_reg_failed_action() */
15493 
15494 
15495 static uint32_t
emlxs_rpi_reg_handler(emlxs_port_t * port,RPIobj_t * rpip)15496 emlxs_rpi_reg_handler(emlxs_port_t *port, RPIobj_t *rpip)
15497 {
15498 	emlxs_hba_t *hba = HBA;
15499 	VPIobj_t *vpip;
15500 	emlxs_node_t *node;
15501 
15502 	vpip = rpip->vpip;
15503 
15504 	rpip->flag |= EMLXS_RPI_REG;
15505 
15506 	if (rpip->flag & EMLXS_RPI_PAUSED) {
15507 		rpip->flag &= ~EMLXS_RPI_PAUSED;
15508 
15509 		if (vpip->rpi_paused) {
15510 			vpip->rpi_paused--;
15511 		}
15512 	}
15513 
15514 	if (!(rpip->flag & EMLXS_RPI_VPI) && (rpip->RPI != FABRIC_RPI)) {
15515 		rpip->flag |= EMLXS_RPI_VPI;
15516 		vpip->rpi_online++;
15517 	}
15518 
15519 	/* If private loop and this is fabric RPI, then exit now */
15520 	if (!(hba->flag & FC_FABRIC_ATTACHED) && (rpip->RPI == FABRIC_RPI)) {
15521 		return (0);
15522 	}
15523 
15524 	/* Create or update the node */
15525 	node = emlxs_node_create(port, rpip->did, rpip->RPI, &rpip->sparam);
15526 
15527 	if (!node) {
15528 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15529 		    "rpi_reg_handler:%d. Node create failed. Reg failed.",
15530 		    rpip->RPI);
15531 
15532 		return (FCF_REASON_NO_NODE);
15533 	}
15534 
15535 	return (0);
15536 
15537 } /* emlxs_rpi_reg_handler() */
15538 
15539 
15540 /*ARGSUSED*/
15541 static uint32_t
emlxs_rpi_reg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)15542 emlxs_rpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
15543 {
15544 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
15545 	MAILBOX4 *mb4;
15546 	RPIobj_t *rpip;
15547 	emlxs_node_t *node;
15548 	uint32_t rval = 0;
15549 
15550 	mutex_enter(&EMLXS_FCF_LOCK);
15551 
15552 	rpip = (RPIobj_t *)mbq->context;
15553 	mb4 = (MAILBOX4 *)mbq;
15554 
15555 	if (rpip->state != RPI_STATE_REG) {
15556 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15557 		    "rpi_reg_mbcmpl:%d state=%s. No longer in RPI_STATE_REG.",
15558 		    rpip->RPI,
15559 		    emlxs_rpi_state_xlate(rpip->state));
15560 
15561 		mutex_exit(&EMLXS_FCF_LOCK);
15562 		return (0);
15563 	}
15564 
15565 	if (mb4->mbxStatus) {
15566 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15567 		    "rpi_reg_mbcmpl:%d failed. %s. >",
15568 		    rpip->RPI,
15569 		    emlxs_mb_xlate_status(mb4->mbxStatus));
15570 
15571 		(void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15572 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
15573 
15574 		mutex_exit(&EMLXS_FCF_LOCK);
15575 		return (0);
15576 	}
15577 
15578 	rval = emlxs_rpi_reg_handler(port, rpip);
15579 
15580 	if (rval) {
15581 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15582 		    "rpi_reg_mbcmpl:%d. Reg failed. >",
15583 		    rpip->RPI);
15584 
15585 		mb4->mbxStatus = MBX_FAILURE;
15586 
15587 		(void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15588 		    rval, 0, 0);
15589 
15590 		mutex_exit(&EMLXS_FCF_LOCK);
15591 		return (0);
15592 	}
15593 
15594 	node = rpip->node;
15595 
15596 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15597 	    "rpi_reg_mbcmpl:%d Registered. Reg complete. >",
15598 	    rpip->RPI);
15599 
15600 	(void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_CMPL, 0, 0, 0);
15601 
15602 	mutex_exit(&EMLXS_FCF_LOCK);
15603 
15604 	/* Needed for FCT trigger in emlxs_mb_deferred_cmpl */
15605 	if (mbq->sbp) {
15606 		((emlxs_buf_t *)mbq->sbp)->node = node;
15607 	}
15608 
15609 #ifdef DHCHAP_SUPPORT
15610 	if (mbq->sbp || mbq->ubp) {
15611 		if (emlxs_dhc_auth_start(port, node, (uint8_t *)mbq->sbp,
15612 		    (uint8_t *)mbq->ubp) == 0) {
15613 			/* Auth started - auth completion will */
15614 			/* handle sbp and ubp now */
15615 			mbq->sbp = NULL;
15616 			mbq->ubp = NULL;
15617 		}
15618 	}
15619 #endif	/* DHCHAP_SUPPORT */
15620 
15621 	return (0);
15622 
15623 } /* emlxs_rpi_reg_mbcmpl() */
15624 
15625 
15626 /*ARGSUSED*/
15627 static uint32_t
emlxs_rpi_reg_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15628 emlxs_rpi_reg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15629     void *arg1)
15630 {
15631 	emlxs_hba_t *hba = HBA;
15632 	MAILBOX4 *mb4;
15633 	MAILBOXQ *mbq;
15634 	MATCHMAP *mp;
15635 	uint32_t rval = 0;
15636 
15637 	if (rpip->state != RPI_STATE_REG) {
15638 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15639 		    "rpi_reg_action:%d %s:%s arg=%p. "
15640 		    "Invalid state. <",
15641 		    rpip->RPI,
15642 		    emlxs_rpi_state_xlate(rpip->state),
15643 		    emlxs_fcf_event_xlate(evt), arg1);
15644 		return (1);
15645 	}
15646 
15647 	if (rpip->RPI == FABRIC_RPI) {
15648 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15649 		    "rpi_reg_action:%d did=%x vpi=%d. Fabric RPI. "
15650 		    "Going online.",
15651 		    rpip->RPI,
15652 		    rpip->did,
15653 		    rpip->vpip->VPI);
15654 
15655 		/* Don't send REG_RPI, but process it as if we did */
15656 		rval = emlxs_rpi_reg_handler(port, rpip);
15657 
15658 		if (rval) {
15659 			rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15660 			    rval, 0, 0);
15661 
15662 			return (rval);
15663 		}
15664 
15665 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15666 		    FCF_REASON_EVENT, evt, arg1);
15667 
15668 		return (rval);
15669 	}
15670 
15671 	if (rpip->prev_state != RPI_STATE_REG_FAILED) {
15672 		rpip->attempts = 0;
15673 	}
15674 
15675 	if (rpip->flag & EMLXS_RPI_REG) {
15676 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15677 		    "rpi_reg_action:%d attempts=%d. "
15678 		    "Updating REG_RPI. <",
15679 		    rpip->RPI,
15680 		    rpip->attempts);
15681 	} else {
15682 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15683 		    "rpi_reg_action:%d attempts=%d. "
15684 		    "Sending REG_RPI. <",
15685 		    rpip->RPI,
15686 		    rpip->attempts);
15687 	}
15688 
15689 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
15690 
15691 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15692 		    FCF_REASON_NO_MBOX, 0, arg1);
15693 
15694 		return (rval);
15695 	}
15696 
15697 	mb4 = (MAILBOX4*)mbq;
15698 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
15699 
15700 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
15701 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
15702 
15703 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15704 		    FCF_REASON_NO_BUFFER, 0, arg1);
15705 
15706 		return (rval);
15707 	}
15708 
15709 	mbq->bp = (void *)mp;
15710 	mbq->nonembed = NULL;
15711 
15712 	mbq->mbox_cmpl = emlxs_rpi_reg_mbcmpl;
15713 	mbq->context = (void *)rpip;
15714 	mbq->port = (void *)port;
15715 
15716 	mb4->mbxCommand = MBX_REG_RPI;
15717 	mb4->mbxOwner = OWN_HOST;
15718 
15719 	mb4->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
15720 	mb4->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys);
15721 	mb4->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys);
15722 	mb4->un.varRegLogin.did = rpip->did;
15723 	mb4->un.varWords[30] = 0;	/* flags */
15724 
15725 	mb4->un.varRegLogin.vpi = rpip->vpip->VPI;
15726 	mb4->un.varRegLogin.rpi = rpip->RPI;
15727 	mb4->un.varRegLogin.update = (rpip->flag & EMLXS_RPI_REG)? 1:0;
15728 
15729 	bcopy((void *)&rpip->sparam, (void *)mp->virt, sizeof (SERV_PARM));
15730 
15731 	if (rpip->cmpl) {
15732 		mbq->sbp = rpip->cmpl->arg1;
15733 		mbq->ubp = rpip->cmpl->arg2;
15734 		mbq->iocbq = rpip->cmpl->arg3;
15735 	}
15736 
15737 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
15738 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
15739 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
15740 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
15741 
15742 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15743 		    FCF_REASON_SEND_FAILED, rval, arg1);
15744 
15745 		return (rval);
15746 	}
15747 
15748 	if (rpip->cmpl) {
15749 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
15750 		rpip->cmpl = 0;
15751 	}
15752 
15753 	return (0);
15754 
15755 } /* emlxs_rpi_reg_action() */
15756 
15757 
15758 /*ARGSUSED*/
15759 static uint32_t
emlxs_rpi_reg_cmpl_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15760 emlxs_rpi_reg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15761     void *arg1)
15762 {
15763 	uint32_t rval = 0;
15764 
15765 	if (rpip->state != RPI_STATE_REG_CMPL) {
15766 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15767 		    "rpi_reg_cmpl_action:%d %s:%s arg=%p. "
15768 		    "Invalid state. <",
15769 		    rpip->RPI,
15770 		    emlxs_rpi_state_xlate(rpip->state),
15771 		    emlxs_fcf_event_xlate(evt), arg1);
15772 		return (1);
15773 	}
15774 
15775 	if (rpip->flag & EMLXS_RPI_REG) {
15776 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15777 		    "rpi_reg_cmpl_action:%d flag=%x. Going online.",
15778 		    rpip->RPI,
15779 		    rpip->flag);
15780 
15781 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15782 		    FCF_REASON_EVENT, evt, arg1);
15783 	} else {
15784 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15785 		    "rpi_reg_cmpl_action:%d flag=%x. Going offline.",
15786 		    rpip->RPI,
15787 		    rpip->flag);
15788 
15789 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15790 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15791 	}
15792 
15793 	return (rval);
15794 
15795 } /* emlxs_rpi_reg_cmpl_action() */
15796 
15797 
15798 /*ARGSUSED*/
15799 static uint32_t
emlxs_rpi_resume_failed_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15800 emlxs_rpi_resume_failed_action(emlxs_port_t *port, RPIobj_t *rpip,
15801     uint32_t evt, void *arg1)
15802 {
15803 	uint32_t rval = 0;
15804 
15805 	rpip->attempts++;
15806 
15807 	if (rpip->state != RPI_STATE_RESUME_FAILED) {
15808 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15809 		    "rpi_resume_failed_action:%d %s:%s arg=%p attempt=%d. "
15810 		    "Invalid state. <",
15811 		    rpip->RPI,
15812 		    emlxs_rpi_state_xlate(rpip->state),
15813 		    emlxs_fcf_event_xlate(evt), arg1,
15814 		    rpip->attempts);
15815 		return (1);
15816 	}
15817 
15818 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15819 	    "rpi_resume_failed_action:%d attempt=%d. Unregistering.",
15820 	    rpip->RPI,
15821 	    rpip->attempts);
15822 
15823 	rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
15824 	    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15825 
15826 	return (rval);
15827 
15828 } /* emlxs_rpi_resume_failed_action() */
15829 
15830 
15831 /*ARGSUSED*/
15832 static void
emlxs_rpi_resume_handler(emlxs_port_t * port,RPIobj_t * rpip)15833 emlxs_rpi_resume_handler(emlxs_port_t *port, RPIobj_t *rpip)
15834 {
15835 	if (rpip->flag & EMLXS_RPI_PAUSED) {
15836 		rpip->flag &= ~EMLXS_RPI_PAUSED;
15837 
15838 		if (rpip->vpip->rpi_paused) {
15839 			rpip->vpip->rpi_paused--;
15840 		}
15841 	}
15842 
15843 	return;
15844 
15845 } /* emlxs_rpi_resume_handler() */
15846 
15847 
15848 /*ARGSUSED*/
15849 static uint32_t
emlxs_rpi_resume_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)15850 emlxs_rpi_resume_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
15851 {
15852 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
15853 	MAILBOX4 *mb4;
15854 	RPIobj_t *rpip;
15855 
15856 	mutex_enter(&EMLXS_FCF_LOCK);
15857 
15858 	rpip = (RPIobj_t *)mbq->context;
15859 	mb4 = (MAILBOX4 *)mbq;
15860 
15861 	if (rpip->state != RPI_STATE_RESUME) {
15862 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15863 		    "rpi_resume_mbcmpl:%d state=%s. "
15864 		    "No longer in RPI_STATE_RESUME.",
15865 		    rpip->RPI,
15866 		    emlxs_rpi_state_xlate(rpip->state));
15867 
15868 		mutex_exit(&EMLXS_FCF_LOCK);
15869 		return (0);
15870 	}
15871 
15872 	if (mb4->mbxStatus) {
15873 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15874 		    "rpi_resume_mbcmpl:%d failed. %s. >",
15875 		    rpip->RPI,
15876 		    emlxs_mb_xlate_status(mb4->mbxStatus));
15877 
15878 		(void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
15879 		    FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
15880 
15881 		mutex_exit(&EMLXS_FCF_LOCK);
15882 		return (0);
15883 	}
15884 
15885 	emlxs_rpi_resume_handler(port, rpip);
15886 
15887 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15888 	    "rpi_resume_mbcmpl:%d Resumed. Resume complete. >",
15889 	    rpip->RPI);
15890 
15891 	(void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_CMPL, 0, 0, 0);
15892 
15893 	mutex_exit(&EMLXS_FCF_LOCK);
15894 
15895 	return (0);
15896 
15897 } /* emlxs_rpi_resume_mbcmpl() */
15898 
15899 
15900 /*ARGSUSED*/
15901 static uint32_t
emlxs_rpi_resume_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15902 emlxs_rpi_resume_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15903     void *arg1)
15904 {
15905 	emlxs_hba_t *hba = HBA;
15906 	MAILBOX4 *mb4;
15907 	MAILBOXQ *mbq;
15908 	uint32_t rval = 0;
15909 
15910 	if (rpip->state != RPI_STATE_RESUME) {
15911 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15912 		    "rpi_resume_action:%d %s:%s arg=%p. "
15913 		    "Invalid state. <",
15914 		    rpip->RPI,
15915 		    emlxs_rpi_state_xlate(rpip->state),
15916 		    emlxs_fcf_event_xlate(evt), arg1);
15917 		return (1);
15918 	}
15919 
15920 	if (!(rpip->flag & EMLXS_RPI_PAUSED)) {
15921 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15922 		    "rpi_resume_action:%d flag=%x. Not Paused. Going online.",
15923 		    rpip->RPI, rpip->flag);
15924 
15925 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15926 		    FCF_REASON_EVENT, evt, arg1);
15927 
15928 		return (rval);
15929 	}
15930 
15931 	if (rpip->RPI == FABRIC_RPI) {
15932 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15933 		    "rpi_resume_action:%d. Fabric RPI. "
15934 		    "Going online.",
15935 		    rpip->RPI);
15936 
15937 		/* Don't send RESUME_RPI, but process it as if we did */
15938 		emlxs_rpi_resume_handler(port, rpip);
15939 
15940 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15941 		    FCF_REASON_EVENT, evt, arg1);
15942 
15943 		return (rval);
15944 	}
15945 
15946 	if (rpip->prev_state != RPI_STATE_RESUME_FAILED) {
15947 		rpip->attempts = 0;
15948 	}
15949 
15950 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15951 	    "rpi_resume_action:%d attempts=%d. Sending RESUME_RPI. <",
15952 	    rpip->RPI,
15953 	    rpip->attempts);
15954 
15955 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
15956 
15957 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
15958 		    FCF_REASON_NO_MBOX, 0, arg1);
15959 
15960 		return (rval);
15961 	}
15962 	mb4 = (MAILBOX4*)mbq;
15963 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
15964 
15965 	mbq->nonembed = NULL;
15966 	mbq->mbox_cmpl = emlxs_rpi_resume_mbcmpl;
15967 	mbq->context = (void *)rpip;
15968 	mbq->port = (void *)port;
15969 
15970 	mb4->mbxCommand = MBX_RESUME_RPI;
15971 	mb4->mbxOwner = OWN_HOST;
15972 
15973 	mb4->un.varResumeRPI.EventTag = hba->link_event_tag;
15974 	mb4->un.varResumeRPI.RPI = rpip->RPI;
15975 
15976 	if (rpip->cmpl) {
15977 		mbq->sbp = rpip->cmpl->arg1;
15978 		mbq->ubp = rpip->cmpl->arg2;
15979 		mbq->iocbq = rpip->cmpl->arg3;
15980 	}
15981 
15982 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
15983 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
15984 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
15985 
15986 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
15987 		    FCF_REASON_SEND_FAILED, rval, arg1);
15988 
15989 		return (rval);
15990 	}
15991 
15992 	if (rpip->cmpl) {
15993 		kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
15994 		rpip->cmpl = 0;
15995 	}
15996 
15997 	return (0);
15998 
15999 } /* emlxs_rpi_resume_action() */
16000 
16001 
16002 static uint32_t
emlxs_rpi_resume_cmpl_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)16003 emlxs_rpi_resume_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
16004     void *arg1)
16005 {
16006 	uint32_t rval = 0;
16007 
16008 	if (rpip->state != RPI_STATE_RESUME_CMPL) {
16009 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
16010 		    "rpi_resume_cmpl_action:%d %s:%s arg=%p. "
16011 		    "Invalid state. <",
16012 		    rpip->RPI,
16013 		    emlxs_rpi_state_xlate(rpip->state),
16014 		    emlxs_fcf_event_xlate(evt), arg1);
16015 		return (1);
16016 	}
16017 
16018 	if (rpip->flag & EMLXS_RPI_PAUSED) {
16019 		if (rpip->flag & EMLXS_RPI_REG) {
16020 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16021 			    "rpi_reg_cmpl_action:%d flag=%x. Unregistering.",
16022 			    rpip->RPI,
16023 			    rpip->flag);
16024 
16025 			rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
16026 			    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
16027 		} else {
16028 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16029 			    "rpi_reg_cmpl_action:%d flag=%x. Going offline.",
16030 			    rpip->RPI,
16031 			    rpip->flag);
16032 
16033 			rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
16034 			    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
16035 		}
16036 	} else {
16037 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16038 		    "rpi_resume_cmpl_action:%d flag=%x. Going online.",
16039 		    rpip->RPI,
16040 		    rpip->flag);
16041 
16042 		rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
16043 		    FCF_REASON_OP_FAILED, rpip->attempts, arg1);
16044 	}
16045 
16046 	return (rval);
16047 
16048 } /* emlxs_rpi_resume_cmpl_action() */
16049 
16050 
16051 /*ARGSUSED*/
16052 static uint32_t
emlxs_rpi_online_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)16053 emlxs_rpi_online_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
16054     void *arg1)
16055 {
16056 	emlxs_hba_t *hba = HBA;
16057 	uint32_t rval = 0;
16058 	RPIobj_t *p2p_rpip;
16059 
16060 	if (rpip->state != RPI_STATE_ONLINE) {
16061 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16062 		    "rpi_online_action:%d %s:%s arg=%p. "
16063 		    "Invalid state. <",
16064 		    rpip->RPI,
16065 		    emlxs_rpi_state_xlate(rpip->state),
16066 		    emlxs_fcf_event_xlate(evt), arg1);
16067 		return (1);
16068 	}
16069 
16070 	if (rpip->RPI == FABRIC_RPI) {
16071 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16072 		    "rpi_online_action:%d did=%x. Fabric RPI online. <",
16073 		    rpip->RPI,
16074 		    rpip->did,
16075 		    rpip->vpip->VPI);
16076 
16077 		/* Now register the p2p_rpip */
16078 		p2p_rpip = rpip->vpip->p2p_rpip;
16079 		if (p2p_rpip) {
16080 			rpip->vpip->p2p_rpip = NULL;
16081 
16082 			rval = emlxs_rpi_state(port, p2p_rpip, RPI_STATE_REG,
16083 			    FCF_REASON_EVENT, evt, arg1);
16084 		}
16085 
16086 		EMLXS_STATE_CHANGE(hba, FC_READY);
16087 
16088 		if (rpip->cmpl) {
16089 			emlxs_rpi_deferred_cmpl(port, rpip, 0);
16090 		}
16091 
16092 		return (0);
16093 	}
16094 
16095 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16096 	    "rpi_online_action:%d did=%x. RPI online. Notifying VPI:%d. >",
16097 	    rpip->RPI,
16098 	    rpip->did,
16099 	    rpip->vpip->VPI);
16100 
16101 	/* Notify VPI */
16102 	rval = emlxs_vpi_event(port, FCF_EVENT_RPI_ONLINE, rpip);
16103 
16104 	return (rval);
16105 
16106 } /* emlxs_rpi_online_action() */
16107