15391 Add support for Emulex LPe35000/LPe36000 32Gb/64Gb fibre channel chipsets
[illumos-gate.git] / usr / src / uts / common / io / fibre-channel / fca / emlxs / emlxs_fcf.c
blob0d6e9d2d6a2a04587336ed4db1e8bb95114d460d
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2004-2012 Emulex. All rights reserved.
24 * Use is subject to license terms.
27 #include <emlxs.h>
29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30 EMLXS_MSG_DEF(EMLXS_FCF_C);
33 * STATE MACHINE RULES:
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.
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.
44 * - emlxs_XXXX_..._notify() calls are used by routines outside
45 * this fcf module to enter the state machine.
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.
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().
55 * - The EMLXS_FCF_LOCK must be held before calling:
56 * emlxs_XXXX_state(), emlxs_XXXX_event() and emlxs_XXXX_action().
58 * - All other calls touching fcftab, fcfi, vfi, vpi, rpi objects
59 * must hold the EMLXS_FCF_LOCK to protect these objects.
63 * DEBUG MESSAGE TERMINATION RULES:
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.
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.
78 * - A message should end in "." if none of the previous
79 * conditions apply.
82 /* ************************************************************************** */
83 /* FCF Generic */
84 /* ************************************************************************** */
87 * EVENT ARG1
88 * --------------------------------------------
89 * FCF_EVENT_STATE_ENTER None
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
99 * FCF_EVENT_FCFI_ONLINE FCFIobj_t*
100 * FCF_EVENT_FCFI_OFFLINE FCFIobj_t*
101 * FCF_EVENT_FCFI_PAUSE FCFIobj_t*
103 * FCF_EVENT_VFI_ONLINE VFIobj_t*
104 * FCF_EVENT_VFI_OFFLINE VFIobj_t*
105 * FCF_EVENT_VFI_PAUSE VFIobj_t*
107 * FCF_EVENT_VPI_ONLINE VPIobj_t*
108 * FCF_EVENT_VPI_OFFLINE VPIobj_t*
109 * FCF_EVENT_VPI_PAUSE VPIobj_t*
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*
118 /* Order does not matter */
119 emlxs_table_t emlxs_fcf_event_table[] =
121 {FCF_EVENT_STATE_ENTER, "E_ENTER"},
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"},
132 {FCF_EVENT_FCFI_ONLINE, "E_FCFI_ONLINE"},
133 {FCF_EVENT_FCFI_OFFLINE, "E_FCFI_OFFLINE"},
134 {FCF_EVENT_FCFI_PAUSE, "E_FCFI_PAUSE"},
136 {FCF_EVENT_VFI_ONLINE, "E_VFI_ONLINE"},
137 {FCF_EVENT_VFI_OFFLINE, "E_VFI_OFFLINE"},
138 {FCF_EVENT_VFI_PAUSE, "E_VFI_PAUSE"},
140 {FCF_EVENT_VPI_ONLINE, "E_VPI_ONLINE"},
141 {FCF_EVENT_VPI_OFFLINE, "E_VPI_OFFLINE"},
142 {FCF_EVENT_VPI_PAUSE, "E_VPI_PAUSE"},
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"},
149 }; /* emlxs_fcf_event_table */
152 /* Order does not matter */
153 emlxs_table_t emlxs_fcf_reason_table[] =
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"},
175 }; /* emlxs_fcf_reason_table */
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);
188 /* ********************************************************************** */
189 /* FC FCFTAB */
190 /* ********************************************************************** */
192 /* Order does not matter */
193 emlxs_table_t emlxs_fc_fcftab_state_table[] =
195 {FC_FCFTAB_STATE_SHUTDOWN, "FCFTAB_SHUTDOWN"},
196 {FC_FCFTAB_STATE_OFFLINE, "FCFTAB_OFFLINE"},
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"},
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"},
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"},
210 {FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
211 "FCFTAB_FCFI_OFFLINE_CMPL"},
212 {FC_FCFTAB_STATE_FCFI_OFFLINE, "FCFTAB_FCFI_OFFLINE"},
214 {FC_FCFTAB_STATE_FCFI_ONLINE, "FCFTAB_FCFI_ONLINE"},
215 {FC_FCFTAB_STATE_FCFI_ONLINE_CMPL, "FCFTAB_FCFI_ONLINE_CMPL"},
217 {FC_FCFTAB_STATE_ONLINE, "FCFTAB_ONLINE"},
219 }; /* emlxs_fc_fcftab_state_table */
221 static void emlxs_fc_fcftab_online_timer(emlxs_hba_t *hba);
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);
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);
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);
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);
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);
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);
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);
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);
276 * - Online sequencing can start from FC_FCFTAB_STATE_OFFLINE state
278 * - Offline sequencing can interrupt the online sequencing at the
279 * entry of the next wait state.
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
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
305 /* Order does matter */
306 static void *emlxs_fc_fcftab_action_table[] =
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 *)))
450 /* ********************************************************************** */
451 /* FCOE FCFTAB */
452 /* ********************************************************************** */
454 /* Order does not matter */
455 emlxs_table_t emlxs_fcoe_fcftab_state_table[] =
457 {FCOE_FCFTAB_STATE_SHUTDOWN, "FCFTAB_SHUTDOWN"},
458 {FCOE_FCFTAB_STATE_OFFLINE, "FCFTAB_OFFLINE"},
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"},
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"},
468 {FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
469 "FCFTAB_FCFI_OFFLINE_CMPL"},
470 {FCOE_FCFTAB_STATE_FCFI_OFFLINE, "FCFTAB_FCFI_OFFLINE"},
472 {FCOE_FCFTAB_STATE_FCFI_ONLINE, "FCFTAB_FCFI_ONLINE"},
473 {FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL,
474 "FCFTAB_FCFI_ONLINE_CMPL"},
476 {FCOE_FCFTAB_STATE_ONLINE, "FCFTAB_ONLINE"},
478 }; /* emlxs_fcoe_fcftab_state_table */
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);
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);
535 * - Online sequencing can start from FCOE_FCFTAB_STATE_OFFLINE state
537 * - Offline sequencing can interrupt the online sequencing at the
538 * entry of the next wait state.
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
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
564 /* Order does matter */
565 static void *emlxs_fcoe_fcftab_action_table[] =
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 *)))
751 /* ********************************************************************** */
752 /* FCFI */
753 /* ********************************************************************** */
755 /* Order does not matter */
756 emlxs_table_t emlxs_fcfi_state_table[] =
758 {FCFI_STATE_FREE, "FCFI_FREE"},
760 {FCFI_STATE_OFFLINE, "FCFI_OFFLINE"},
762 {FCFI_STATE_UNREG_CMPL, "FCFI_UNREG_CMPL"},
763 {FCFI_STATE_UNREG_FAILED, "FCFI_UNREG_FAILED"},
764 {FCFI_STATE_UNREG, "FCFI_UNREG"},
766 {FCFI_STATE_REG, "FCFI_REG"},
767 {FCFI_STATE_REG_FAILED, "FCFI_REG_FAILED"},
768 {FCFI_STATE_REG_CMPL, "FCFI_REG_CMPL"},
770 {FCFI_STATE_VFI_OFFLINE_CMPL, "FCFI_VFI_OFFLINE_CMPL"},
771 {FCFI_STATE_VFI_OFFLINE, "FCFI_VFI_OFFLINE"},
773 {FCFI_STATE_VFI_ONLINE, "FCFI_VFI_ONLINE"},
774 {FCFI_STATE_VFI_ONLINE_CMPL, "FCFI_VFI_ONLINE_CMPL"},
776 {FCFI_STATE_PAUSED, "FCFI_PAUSED"},
777 {FCFI_STATE_ONLINE, "FCFI_ONLINE"},
779 }; /* emlxs_fcfi_state_table */
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);
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);
832 * - Online sequencing can start from FCFI_STATE_OFFLINE state or
833 * the FCFI_STATE_VFI_OFFLINE state.
835 * - Offline sequencing can interrupt the online sequencing at the
836 * entry of the next wait state.
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
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
862 * NORMAL PAUSE SEQ
863 * ---------------------------
864 * FCFI_PAUSE event <-- FCFTAB
865 * FCFI_STATE_ONLINE
866 * FCFI_STATE_PAUSED
869 /* Order does matter */
870 static void *emlxs_fcfi_action_table[] =
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 * */
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 */
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 */
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 */
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 */
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 *)))
993 /* ********************************************************************** */
994 /* VFI */
995 /* ********************************************************************** */
997 /* Order does not matter */
998 emlxs_table_t emlxs_vfi_state_table[] =
1000 {VFI_STATE_OFFLINE, "VFI_OFFLINE"},
1002 {VFI_STATE_INIT, "VFI_INIT"},
1003 {VFI_STATE_INIT_FAILED, "VFI_INIT_FAILED"},
1004 {VFI_STATE_INIT_CMPL, "VFI_INIT_CMPL"},
1006 {VFI_STATE_VPI_OFFLINE_CMPL, "VFI_VPI_OFFLINE_CMPL"},
1007 {VFI_STATE_VPI_OFFLINE, "VFI_VPI_OFFLINE"},
1009 {VFI_STATE_VPI_ONLINE, "VFI_VPI_ONLINE"},
1010 {VFI_STATE_VPI_ONLINE_CMPL, "VFI_VPI_ONLINE_CMPL"},
1012 {VFI_STATE_UNREG_CMPL, "VFI_UNREG_CMPL"},
1013 {VFI_STATE_UNREG_FAILED, "VFI_UNREG_FAILED"},
1014 {VFI_STATE_UNREG, "VFI_UNREG"},
1016 {VFI_STATE_REG, "VFI_REG"},
1017 {VFI_STATE_REG_FAILED, "VFI_REG_FAILED"},
1018 {VFI_STATE_REG_CMPL, "VFI_REG_CMPL"},
1020 {VFI_STATE_PAUSED, "VFI_PAUSED"},
1021 {VFI_STATE_ONLINE, "VFI_ONLINE"},
1023 }; /* emlxs_vfi_state_table */
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);
1069 static uint32_t emlxs_vfi_event(emlxs_port_t *port,
1070 uint32_t evt, void *arg1);
1074 * - Online sequencing can start from VFI_STATE_OFFLINE state or
1075 * the VFI_STATE_VPI_OFFLINE state.
1077 * - Offline sequencing can interrupt the online sequencing at the
1078 * entry of the next wait state.
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
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
1106 * NORMAL PAUSE SEQ
1107 * ---------------------------
1108 * VFI_PAUSE event <-- FCFI
1109 * VFI_STATE_ONLINE
1110 * VFI_STATE_PAUSED
1113 /* Order does matter */
1114 static void *emlxs_vfi_action_table[] =
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 *)))
1258 /* ********************************************************************** */
1259 /* VPI */
1260 /* ********************************************************************** */
1262 /* Order does not matter */
1263 emlxs_table_t emlxs_vpi_state_table[] =
1265 {VPI_STATE_OFFLINE, "VPI_OFFLINE"},
1267 {VPI_STATE_INIT, "VPI_INIT"},
1268 {VPI_STATE_INIT_FAILED, "VPI_INIT_FAILED"},
1269 {VPI_STATE_INIT_CMPL, "VPI_INIT_CMPL"},
1271 {VPI_STATE_UNREG_CMPL, "VPI_UNREG_CMPL"},
1272 {VPI_STATE_UNREG_FAILED, "VPI_UNREG_FAILED"},
1273 {VPI_STATE_UNREG, "VPI_UNREG"},
1275 {VPI_STATE_LOGO_CMPL, "VPI_LOGO_CMPL"},
1276 {VPI_STATE_LOGO_FAILED, "VPI_LOGO_FAILED"},
1277 {VPI_STATE_LOGO, "VPI_LOGO"},
1279 {VPI_STATE_PORT_OFFLINE, "VPI_PORT_OFFLINE"},
1280 {VPI_STATE_PORT_ONLINE, "VPI_PORT_ONLINE"},
1282 {VPI_STATE_LOGI, "VPI_LOGI"},
1283 {VPI_STATE_LOGI_FAILED, "VPI_LOGI_FAILED"},
1284 {VPI_STATE_LOGI_CMPL, "VPI_LOGI_CMPL"},
1286 {VPI_STATE_REG, "VPI_REG"},
1287 {VPI_STATE_REG_FAILED, "VPI_REG_FAILED"},
1288 {VPI_STATE_REG_CMPL, "VPI_REG_CMPL"},
1290 {VPI_STATE_PAUSED, "VPI_PAUSED"},
1291 {VPI_STATE_ONLINE, "VPI_ONLINE"},
1293 }; /* emlxs_vpi_state_table */
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);
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);
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);
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);
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);
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);
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);
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);
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);
1364 * - Online sequencing can only start from VPI_STATE_OFFLINE or
1365 * VPI_STATE_PORT_OFFLINE state.
1367 * - Offline sequencing can interrupt the online sequencing at the
1368 * entry of the next wait state.
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
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
1398 * NORMAL PAUSE SEQ
1399 * ---------------------------
1400 * VPI_PAUSE event <-- VFI
1401 * VPI_STATE_ONLINE
1402 * VPI_STATE_PORT_OFFLINE
1403 * VPI_STATE_PAUSED
1406 /* Order does matter */
1407 static void *emlxs_vpi_action_table[] =
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 *)))
1604 /* ********************************************************************** */
1605 /* RPI */
1606 /* ********************************************************************** */
1608 /* Order does not matter */
1609 emlxs_table_t emlxs_rpi_state_table[] =
1611 {RPI_STATE_FREE, "RPI_FREE"},
1613 {RPI_STATE_RESERVED, "RPI_RESERVED"},
1614 {RPI_STATE_OFFLINE, "RPI_OFFLINE"},
1616 {RPI_STATE_UNREG_CMPL, "RPI_UNREG_CMPL"},
1617 {RPI_STATE_UNREG_FAILED, "RPI_UNREG_FAILED"},
1618 {RPI_STATE_UNREG, "RPI_UNREG"},
1620 {RPI_STATE_REG, "RPI_REG"},
1621 {RPI_STATE_REG_FAILED, "RPI_REG_FAILED"},
1622 {RPI_STATE_REG_CMPL, "RPI_REG_CMPL"},
1624 {RPI_STATE_PAUSED, "RPI_PAUSED"},
1626 {RPI_STATE_RESUME, "RPI_RESUME"},
1627 {RPI_STATE_RESUME_FAILED, "RPI_RESUME_FAILED"},
1628 {RPI_STATE_RESUME_CMPL, "RPI_RESUME_CMPL"},
1630 {RPI_STATE_ONLINE, "RPI_ONLINE"},
1632 }; /* emlxs_rpi_state_table */
1634 static uint32_t emlxs_rpi_free_action(emlxs_port_t *port,
1635 RPIobj_t *rpip, uint32_t evt, void *arg1);
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);
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);
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);
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);
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);
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);
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);
1689 static void emlxs_rpi_idle_timer(emlxs_hba_t *hba);
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);
1695 static void emlxs_rpi_alloc_fabric_rpi(emlxs_port_t *port);
1697 static void emlxs_rpi_deferred_cmpl(emlxs_port_t *port, RPIobj_t *rpip,
1698 uint32_t status);
1701 * - Online sequencing can start from RPI_STATE_RESERVED state or
1702 * the RPI_STATE_PAUSED state.
1704 * - Offline sequencing can interrupt the online sequencing at the
1705 * entry of the next wait state.
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
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
1727 * NORMAL PAUSE SEQ
1728 * ---------------------------
1729 * RPI_PAUSE event <-- VPI
1730 * RPI_STATE_ONLINE
1731 * RPI_STATE_PAUSED
1734 /* Order does matter */
1735 static void *emlxs_rpi_action_table[] =
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 *)))
1847 /* ************************************************************************** */
1848 /* FCF Generic */
1849 /* ************************************************************************** */
1850 static void
1851 emlxs_fcf_linkdown(emlxs_port_t *port)
1853 emlxs_hba_t *hba = HBA;
1855 if (hba->state <= FC_LINK_DOWN) {
1856 return;
1859 mutex_enter(&EMLXS_PORT_LOCK);
1861 if (hba->state <= FC_LINK_DOWN) {
1862 mutex_exit(&EMLXS_PORT_LOCK);
1863 return;
1866 HBASTATS.LinkDown++;
1867 EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN);
1869 hba->flag &= FC_LINKDOWN_MASK;
1870 hba->discovery_timer = 0;
1871 hba->linkup_timer = 0;
1873 mutex_exit(&EMLXS_PORT_LOCK);
1875 emlxs_log_link_event(port);
1877 return;
1879 } /* emlxs_fcf_linkdown() */
1882 static void
1883 emlxs_fcf_linkup(emlxs_port_t *port)
1885 emlxs_hba_t *hba = HBA;
1886 emlxs_config_t *cfg = &CFG;
1888 if (hba->state >= FC_LINK_UP) {
1889 return;
1892 mutex_enter(&EMLXS_PORT_LOCK);
1894 if (hba->state >= FC_LINK_UP) {
1895 mutex_exit(&EMLXS_PORT_LOCK);
1896 return;
1899 /* Check for any mode changes */
1900 emlxs_mode_set(hba);
1902 HBASTATS.LinkUp++;
1903 EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP);
1905 hba->discovery_timer = hba->timer_tics +
1906 cfg[CFG_LINKUP_TIMEOUT].current +
1907 cfg[CFG_DISC_TIMEOUT].current;
1909 mutex_exit(&EMLXS_PORT_LOCK);
1911 emlxs_log_link_event(port);
1913 return;
1915 } /* emlxs_fcf_linkup() */
1918 extern void
1919 emlxs_fcf_fini(emlxs_hba_t *hba)
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;
1927 if (!(hba->sli.sli4.flag & EMLXS_SLI4_FCF_INIT)) {
1928 return;
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);
1936 if (!(fcftab->flag & EMLXS_FCFTAB_SHUTDOWN)) {
1937 (void) emlxs_fcf_shutdown_notify(port, 1);
1940 mutex_enter(&EMLXS_FCF_LOCK);
1941 hba->sli.sli4.flag &= ~EMLXS_SLI4_FCF_INIT;
1943 /* Free the FCF memory */
1945 kmem_free(fcftab->table,
1946 (sizeof (FCFIobj_t) * fcftab->table_count));
1948 fcftab->table = NULL;
1949 fcftab->table_count = 0;
1951 /* Free the VFI memory */
1953 kmem_free(hba->sli.sli4.VFI_table,
1954 (sizeof (VFIobj_t) * hba->sli.sli4.VFICount));
1956 hba->sli.sli4.VFI_table = NULL;
1957 hba->sli.sli4.VFICount = 0;
1959 /* Free the VPI Fabric RPI's */
1961 for (i = 0; i < MAX_VPORTS; i++) {
1962 vport = &VPORT(i);
1963 rpip = vport->vpip->fabric_rpip;
1965 if (rpip->state == RPI_STATE_FREE) {
1966 continue;
1969 (void) emlxs_rpi_free(port, rpip);
1972 /* Free the RPI memory */
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;
1980 (void) emlxs_rpi_free(port, rpip);
1983 kmem_free(hba->sli.sli4.RPIp,
1984 (sizeof (RPIobj_t) * hba->sli.sli4.RPICount));
1986 hba->sli.sli4.RPIp = NULL;
1987 hba->sli.sli4.RPICount = 0;
1989 /* Free the mutex */
1990 mutex_exit(&EMLXS_FCF_LOCK);
1991 mutex_destroy(&EMLXS_FCF_LOCK);
1993 return;
1995 } /* emlxs_fcf_fini() */
1998 extern void
1999 emlxs_fcf_init(emlxs_hba_t *hba)
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;
2010 if (hba->sli.sli4.flag & EMLXS_SLI4_FCF_INIT) {
2011 return;
2014 mutex_init(&EMLXS_FCF_LOCK, NULL, MUTEX_DRIVER, NULL);
2015 mutex_enter(&EMLXS_FCF_LOCK);
2017 /* FCFTAB */
2019 bzero(fcftab, sizeof (FCFTable_t));
2020 fcftab->state = FCFTAB_STATE_OFFLINE;
2022 /* FCFI */
2024 fcftab->table_count = hba->sli.sli4.FCFICount;
2025 fcftab->table = (FCFIobj_t *)kmem_zalloc(
2026 (sizeof (FCFIobj_t) * fcftab->table_count), KM_SLEEP);
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;
2035 /* VFI */
2037 hba->sli.sli4.VFI_table = (VFIobj_t *)kmem_zalloc(
2038 (sizeof (VFIobj_t) * hba->sli.sli4.VFICount), KM_SLEEP);
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;
2047 /* VPI */
2049 for (i = 0; i < MAX_VPORTS; i++) {
2050 vport = &VPORT(i);
2051 vpip = &vport->VPIobj;
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;
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;
2070 /* RPI */
2072 hba->sli.sli4.RPIp = (RPIobj_t *)kmem_zalloc(
2073 (sizeof (RPIobj_t) * hba->sli.sli4.RPICount), KM_SLEEP);
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;
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);
2091 hba->sli.sli4.flag |= EMLXS_SLI4_FCF_INIT;
2092 mutex_exit(&EMLXS_FCF_LOCK);
2094 return;
2096 } /* emlxs_fcf_init() */
2099 static char *
2100 emlxs_fcf_event_xlate(uint32_t state)
2102 static char buffer[32];
2103 uint32_t i;
2104 uint32_t count;
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);
2113 (void) snprintf(buffer, sizeof (buffer), "event=0x%x", state);
2114 return (buffer);
2116 } /* emlxs_fcf_event_xlate() */
2119 static char *
2120 emlxs_fcf_reason_xlate(uint32_t reason)
2122 static char buffer[32];
2123 uint32_t i;
2124 uint32_t count;
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);
2133 (void) snprintf(buffer, sizeof (buffer), "reason=0x%x", reason);
2134 return (buffer);
2136 } /* emlxs_fcf_reason_xlate() */
2139 extern void
2140 emlxs_fcf_timer_notify(emlxs_hba_t *hba)
2142 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2144 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2145 return;
2148 if (fcftab->table == 0) {
2149 return;
2152 mutex_enter(&EMLXS_FCF_LOCK);
2154 if (SLI4_FCOE_MODE) {
2155 emlxs_fcoe_fcftab_sol_timer(hba);
2157 emlxs_fcoe_fcftab_read_timer(hba);
2159 emlxs_fcoe_fcftab_offline_timer(hba);
2160 } else {
2161 emlxs_fc_fcftab_online_timer(hba);
2164 emlxs_rpi_idle_timer(hba);
2166 mutex_exit(&EMLXS_FCF_LOCK);
2168 return;
2170 } /* emlxs_fcf_timer_notify() */
2173 extern uint32_t
2174 emlxs_fcf_shutdown_notify(emlxs_port_t *port, uint32_t wait)
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;
2182 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2183 return (1);
2186 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2187 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2188 return (1);
2191 if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) {
2192 return (0);
2195 mutex_enter(&EMLXS_FCF_LOCK);
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);
2203 rval = emlxs_fcftab_event(port, FCF_EVENT_SHUTDOWN, 0);
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);
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;
2224 mutex_exit(&EMLXS_FCF_LOCK);
2226 return (rval);
2228 } /* emlxs_fcf_shutdown_notify() */
2231 extern uint32_t
2232 emlxs_fcf_linkup_notify(emlxs_port_t *port)
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;
2239 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2240 return (1);
2243 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2244 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2245 return (1);
2248 mutex_enter(&EMLXS_FCF_LOCK);
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);
2256 rval = emlxs_fcftab_event(port, FCF_EVENT_LINKUP, 0);
2258 mutex_exit(&EMLXS_FCF_LOCK);
2260 return (rval);
2262 } /* emlxs_fcf_linkup_notify() */
2265 extern uint32_t
2266 emlxs_fcf_linkdown_notify(emlxs_port_t *port)
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;
2273 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2274 return (1);
2277 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2278 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2279 return (1);
2282 mutex_enter(&EMLXS_FCF_LOCK);
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);
2290 rval = emlxs_fcftab_event(port, FCF_EVENT_LINKDOWN, 0);
2292 mutex_exit(&EMLXS_FCF_LOCK);
2294 return (rval);
2296 } /* emlxs_fcf_linkdown_notify() */
2299 extern uint32_t
2300 emlxs_fcf_cvl_notify(emlxs_port_t *port, uint32_t vpi)
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;
2307 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2308 return (1);
2311 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2312 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2313 return (1);
2316 mutex_enter(&EMLXS_FCF_LOCK);
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);
2324 rval = emlxs_fcftab_event(port, FCF_EVENT_CVL,
2325 (void *)((unsigned long)vpi));
2327 mutex_exit(&EMLXS_FCF_LOCK);
2329 return (rval);
2331 } /* emlxs_fcf_cvl_notify() */
2334 extern uint32_t
2335 emlxs_fcf_full_notify(emlxs_port_t *port)
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;
2342 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2343 return (1);
2346 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2347 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2348 return (1);
2351 mutex_enter(&EMLXS_FCF_LOCK);
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);
2359 rval = emlxs_fcftab_event(port, FCF_EVENT_FCFTAB_FULL, 0);
2361 mutex_exit(&EMLXS_FCF_LOCK);
2363 return (rval);
2365 } /* emlxs_fcf_full_notify() */
2368 extern uint32_t
2369 emlxs_fcf_found_notify(emlxs_port_t *port, uint32_t fcf_index)
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;
2376 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2377 return (1);
2380 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2381 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2382 return (1);
2385 mutex_enter(&EMLXS_FCF_LOCK);
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);
2393 rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_FOUND,
2394 (void *)((unsigned long)fcf_index));
2396 mutex_exit(&EMLXS_FCF_LOCK);
2398 return (rval);
2400 } /* emlxs_fcf_found_notify() */
2403 extern uint32_t
2404 emlxs_fcf_changed_notify(emlxs_port_t *port, uint32_t fcf_index)
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;
2411 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2412 return (1);
2415 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2416 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2417 return (1);
2420 mutex_enter(&EMLXS_FCF_LOCK);
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);
2428 rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_CHANGED,
2429 (void *)((unsigned long)fcf_index));
2431 mutex_exit(&EMLXS_FCF_LOCK);
2433 return (rval);
2435 } /* emlxs_fcf_changed_notify() */
2438 extern uint32_t
2439 emlxs_fcf_lost_notify(emlxs_port_t *port, uint32_t fcf_index)
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;
2446 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2447 return (1);
2450 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2451 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2452 return (1);
2455 mutex_enter(&EMLXS_FCF_LOCK);
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);
2463 rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_LOST,
2464 (void *)((unsigned long)fcf_index));
2466 mutex_exit(&EMLXS_FCF_LOCK);
2468 return (rval);
2470 } /* emlxs_fcf_lost_notify() */
2473 /* ************************************************************************** */
2474 /* FCFTAB Generic */
2475 /* ************************************************************************** */
2477 static char *
2478 emlxs_fcftab_state_xlate(emlxs_port_t *port, uint32_t state)
2480 emlxs_hba_t *hba = HBA;
2482 if (SLI4_FCOE_MODE) {
2483 return (emlxs_fcoe_fcftab_state_xlate(state));
2484 } else {
2485 return (emlxs_fc_fcftab_state_xlate(state));
2488 } /* emlxs_fcftab_state_xlate() */
2490 static uint32_t
2491 emlxs_fcftab_event(emlxs_port_t *port, uint32_t evt, void *arg1)
2493 emlxs_hba_t *hba = HBA;
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));
2501 } /* emlxs_fcftab_event() */
2504 /*ARGSUSED*/
2505 static uint32_t
2506 emlxs_fcftab_shutdown_action(emlxs_port_t *port, uint32_t evt,
2507 void *arg1)
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;
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);
2525 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
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++) {
2533 if (fcfp->state <= FCFI_STATE_OFFLINE) {
2534 continue;
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);
2544 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE,
2545 fcfp);
2547 online++;
2550 if (!online) {
2551 goto done;
2554 return (0);
2557 /* Check FCF states */
2558 online = 0;
2559 fcfp = fcftab->table;
2560 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2562 if (fcfp->state <= FCFI_STATE_OFFLINE) {
2563 continue;
2566 online++;
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);
2578 return (0);
2581 done:
2582 /* Free FCF table */
2583 fcfp = fcftab->table;
2584 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2586 if (fcfp->state == FCFI_STATE_FREE) {
2587 continue;
2590 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2591 "fcftab_shutdown_action:%x. Freeing FCFI:%d. >",
2592 fcftab->TID,
2593 fcfp->fcf_index);
2595 (void) emlxs_fcfi_free(port, fcfp);
2598 /* Clean the selection table */
2599 bzero(fcftab->fcfi, sizeof (fcftab->fcfi));
2600 fcftab->fcfi_count = 0;
2602 fcftab->flag |= EMLXS_FCFTAB_SHUTDOWN;
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);
2612 return (0);
2614 } /* emlxs_fcftab_shutdown_action() */
2617 /* ************************************************************************** */
2618 /* FC FCFTAB */
2619 /* ************************************************************************** */
2621 static char *
2622 emlxs_fc_fcftab_state_xlate(uint32_t state)
2624 static char buffer[32];
2625 uint32_t i;
2626 uint32_t count;
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);
2635 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
2636 return (buffer);
2638 } /* emlxs_fc_fcftab_state_xlate() */
2641 static uint32_t
2642 emlxs_fc_fcftab_action(emlxs_port_t *port, uint32_t evt,
2643 void *arg1)
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;
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);
2677 events = FC_FCFTAB_ACTION_EVENTS;
2678 state = fcftab->state;
2680 index += (state * events);
2681 func = (uint32_t(*) (emlxs_port_t *, uint32_t, void *))
2682 emlxs_fc_fcftab_action_table[index];
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);
2691 return (1);
2694 rval = (func)(port, evt, arg1);
2696 return (rval);
2698 } /* emlxs_fc_fcftab_action() */
2701 static uint32_t
2702 emlxs_fc_fcftab_event(emlxs_port_t *port, uint32_t evt,
2703 void *arg1)
2705 emlxs_hba_t *hba = HBA;
2706 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2707 uint32_t rval = 0;
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;
2718 default:
2719 return (1);
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);
2728 rval = emlxs_fc_fcftab_action(port, evt, arg1);
2730 return (rval);
2732 } /* emlxs_fc_fcftab_event() */
2735 /* EMLXS_FCF_LOCK must be held to enter */
2736 /*ARGSUSED*/
2737 static uint32_t
2738 emlxs_fc_fcftab_state(emlxs_port_t *port, uint16_t state, uint16_t reason,
2739 uint32_t explain, void *arg1)
2741 emlxs_hba_t *hba = HBA;
2742 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2743 uint32_t rval = 0;
2745 if (state >= FC_FCFTAB_ACTION_STATES) {
2746 return (1);
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);
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);
2792 fcftab->prev_state = fcftab->state;
2793 fcftab->prev_reason = fcftab->reason;
2794 fcftab->state = state;
2795 fcftab->reason = reason;
2797 rval = emlxs_fc_fcftab_action(port, FCF_EVENT_STATE_ENTER, arg1);
2799 return (rval);
2801 } /* emlxs_fc_fcftab_state() */
2804 static void
2805 emlxs_fc_fcftab_online_timer(emlxs_hba_t *hba)
2807 emlxs_port_t *port = &PPORT;
2808 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2810 /* Check FCF timer */
2811 if (!fcftab->online_timer ||
2812 (hba->timer_tics < fcftab->online_timer)) {
2813 return;
2815 fcftab->online_timer = 0;
2817 switch (fcftab->state) {
2818 case FC_FCFTAB_STATE_ONLINE:
2819 emlxs_fcf_linkup(port);
2821 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
2822 fcftab->flag |= EMLXS_FC_FCFTAB_TOPO_REQ;
2823 fcftab->generation++;
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);
2831 (void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
2832 FCF_REASON_EVENT, 0, 0);
2833 break;
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;
2843 return;
2845 } /* emlxs_fc_fcftab_online_timer() */
2848 /*ARGSUSED*/
2849 static uint32_t
2850 emlxs_fc_fcftab_offline_action(emlxs_port_t *port, uint32_t evt,
2851 void *arg1)
2853 emlxs_hba_t *hba = HBA;
2854 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2855 uint32_t rval = 0;
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);
2867 fcftab->flag &= ~EMLXS_FC_FCFTAB_OFFLINE_REQ;
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);
2878 rval = emlxs_fc_fcftab_req_handler(port, arg1);
2879 return (rval);
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);
2890 return (0);
2892 } /* emlxs_fc_fcftab_offline_action() */
2895 /*ARGSUSED*/
2896 static uint32_t
2897 emlxs_fc_fcftab_online_action(emlxs_port_t *port, uint32_t evt,
2898 void *arg1)
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;
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);
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);
2922 rval = emlxs_fc_fcftab_req_handler(port, arg1);
2923 return (rval);
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));
2943 /* Start the online timer */
2944 fcftab->online_timer = hba->timer_tics + 1;
2947 emlxs_fcf_linkdown(port);
2949 return (0);
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);
2959 emlxs_fcf_linkup(port);
2961 return (0);
2963 } /* emlxs_fc_fcftab_online_action() */
2966 /*ARGSUSED*/
2967 static uint32_t
2968 emlxs_fc_fcftab_topo_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
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;
2978 mutex_enter(&EMLXS_FCF_LOCK);
2979 TID = (uint16_t)((unsigned long)mbq->context);
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));
2987 mutex_exit(&EMLXS_FCF_LOCK);
2988 return (0);
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);
2999 mutex_exit(&EMLXS_FCF_LOCK);
3000 return (0);
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));
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);
3019 mutex_exit(&EMLXS_FCF_LOCK);
3020 return (0);
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);
3029 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
3030 fcftab->flag |= EMLXS_FC_FCFTAB_OFFLINE_REQ;
3031 (void) emlxs_fc_fcftab_req_handler(port, 0);
3033 mutex_exit(&EMLXS_FCF_LOCK);
3034 return (0);
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);
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);
3053 /* Link is up */
3055 /* Save the linkspeed & topology */
3056 hba->linkspeed = mb4->un.varReadLA.UlnkSpeed;
3057 hba->topology = mb4->un.varReadLA.topology;
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);
3065 goto done;
3068 /* TOPOLOGY_LOOP */
3070 port->lip_type = mb4->un.varReadLA.lipType;
3072 if (mb4->un.varReadLA.pb) {
3073 hba->flag |= FC_BYPASSED_MODE;
3074 } else {
3075 hba->flag &= ~FC_BYPASSED_MODE;
3078 /* Save the granted_alpa and alpa_map */
3080 port->granted_alpa = mb4->un.varReadLA.granted_AL_PA;
3081 mp = (MATCHMAP *)mbq->bp;
3082 alpa_map = (uint8_t *)port->alpa_map;
3084 bcopy((caddr_t)mp->virt, (caddr_t)alpa_map, 128);
3086 /* Check number of devices in map */
3087 if (alpa_map[0] > 127) {
3088 alpa_map[0] = 127;
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]);
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]);
3116 done:
3118 (void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_CMPL,
3119 0, 0, 0);
3121 mutex_exit(&EMLXS_FCF_LOCK);
3122 return (0);
3124 } /* emlxs_fc_fcftab_topo_mbcmpl() */
3127 /*ARGSUSED*/
3128 static uint32_t
3129 emlxs_fc_fcftab_topo_action(emlxs_port_t *port, uint32_t evt,
3130 void *arg1)
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;
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);
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;
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);
3165 rval = emlxs_fc_fcftab_req_handler(port, arg1);
3166 return (rval);
3169 if (fcftab->attempts == 0) {
3170 fcftab->TID = fcftab->generation;
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);
3183 port->did = 0;
3184 port->lip_type = 0;
3185 hba->flag &= ~FC_BYPASSED_MODE;
3186 bzero((caddr_t)port->alpa_map, 128);
3188 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
3189 FCF_REASON_EVENT, evt, arg1);
3190 return (rval);
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);
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);
3207 mb4 = (MAILBOX4*)mbq;
3208 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
3210 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
3211 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3213 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_FAILED,
3214 FCF_REASON_NO_BUFFER, 0, arg1);
3215 return (rval);
3217 bzero(mp->virt, mp->size);
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;
3225 mb4->un.varSLIConfig.be.embedded = 0;
3226 mb4->mbxCommand = MBX_READ_TOPOLOGY;
3227 mb4->mbxOwner = OWN_HOST;
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);
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);
3238 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_FAILED,
3239 FCF_REASON_SEND_FAILED, rval, arg1);
3241 return (rval);
3244 return (0);
3246 } /* emlxs_fc_fcftab_topo_action() */
3249 /*ARGSUSED*/
3250 static uint32_t
3251 emlxs_fc_fcftab_topo_failed_action(emlxs_port_t *port, uint32_t evt,
3252 void *arg1)
3254 emlxs_hba_t *hba = HBA;
3255 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3256 uint32_t rval = 0;
3258 fcftab->attempts++;
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);
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);
3283 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_CMPL,
3284 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
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);
3296 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
3297 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3300 return (rval);
3302 } /* emlxs_fc_fcftab_topo_failed_action() */
3305 /*ARGSUSED*/
3306 static uint32_t
3307 emlxs_fc_fcftab_topo_cmpl_action(emlxs_port_t *port, uint32_t evt,
3308 void *arg1)
3310 emlxs_hba_t *hba = HBA;
3311 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3312 uint32_t rval = 0;
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);
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);
3330 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
3331 FCF_REASON_EVENT, evt, arg1);
3333 return (rval);
3335 } /* emlxs_fc_fcftab_topo_cmpl_action() */
3338 /*ARGSUSED*/
3339 static uint32_t
3340 emlxs_fc_fcftab_cfglink_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
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;
3347 mutex_enter(&EMLXS_FCF_LOCK);
3348 TID = (uint16_t)((unsigned long)mbq->context);
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));
3356 mutex_exit(&EMLXS_FCF_LOCK);
3357 return (0);
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);
3368 mutex_exit(&EMLXS_FCF_LOCK);
3369 return (0);
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));
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);
3388 mutex_exit(&EMLXS_FCF_LOCK);
3389 return (0);
3392 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3393 "fc_fcftab_cfglink_mbcmpl:%x. >",
3394 fcftab->TID);
3396 (void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK_CMPL,
3397 0, 0, 0);
3399 mutex_exit(&EMLXS_FCF_LOCK);
3400 return (0);
3402 } /* emlxs_fc_fcftab_cfglink_mbcmpl() */
3406 /*ARGSUSED*/
3407 static uint32_t
3408 emlxs_fc_fcftab_cfglink_action(emlxs_port_t *port, uint32_t evt,
3409 void *arg1)
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;
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);
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;
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);
3444 rval = emlxs_fc_fcftab_req_handler(port, arg1);
3445 return (rval);
3448 if (fcftab->attempts == 0) {
3449 fcftab->TID = fcftab->generation;
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);
3462 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
3463 FCF_REASON_EVENT, evt, arg1);
3464 return (rval);
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);
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);
3482 mb4 = (MAILBOX4*)mbq;
3483 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
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;
3490 mb4->un.varSLIConfig.be.embedded = 0;
3491 mb4->mbxCommand = MBX_CONFIG_LINK;
3492 mb4->mbxOwner = OWN_HOST;
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;
3501 if (cfg[CFG_ACK0].current) {
3502 mb4->un.varCfgLnk.ack0_enable = 1;
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;
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);
3518 rval = emlxs_fc_fcftab_state(port,
3519 FC_FCFTAB_STATE_CFGLINK_FAILED,
3520 FCF_REASON_SEND_FAILED, rval, arg1);
3522 return (rval);
3525 return (0);
3527 } /* emlxs_fc_fcftab_cfglink_action() */
3530 /*ARGSUSED*/
3531 static uint32_t
3532 emlxs_fc_fcftab_cfglink_failed_action(emlxs_port_t *port, uint32_t evt,
3533 void *arg1)
3535 emlxs_hba_t *hba = HBA;
3536 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3537 uint32_t rval = 0;
3539 fcftab->attempts++;
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);
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);
3564 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK_CMPL,
3565 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
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);
3577 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
3578 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3581 return (rval);
3583 } /* emlxs_fc_fcftab_cfglink_failed_action() */
3586 /*ARGSUSED*/
3587 static uint32_t
3588 emlxs_fc_fcftab_cfglink_cmpl_action(emlxs_port_t *port, uint32_t evt,
3589 void *arg1)
3591 emlxs_hba_t *hba = HBA;
3592 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3593 uint32_t rval = 0;
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);
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);
3611 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
3612 FCF_REASON_EVENT, evt, arg1);
3614 return (rval);
3616 } /* emlxs_fc_fcftab_cfglink_cmpl_action() */
3619 /*ARGSUSED*/
3620 static uint32_t
3621 emlxs_fc_fcftab_sparm_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
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;
3633 mutex_enter(&EMLXS_FCF_LOCK);
3634 TID = (uint16_t)((unsigned long)mbq->context);
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));
3642 mutex_exit(&EMLXS_FCF_LOCK);
3643 return (0);
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);
3654 mutex_exit(&EMLXS_FCF_LOCK);
3655 return (0);
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));
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);
3674 mutex_exit(&EMLXS_FCF_LOCK);
3675 return (0);
3678 /* Save the parameters */
3679 mp = (MATCHMAP *)mbq->bp;
3680 bcopy((caddr_t)mp->virt, (caddr_t)&hba->sparam, sizeof (SERV_PARM));
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);
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));
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));
3701 bcopy((caddr_t)&hba->wwpn,
3702 (caddr_t)&hba->sparam.portName, sizeof (NAME_TYPE));
3705 /* Update all bound ports */
3706 for (i = 0; i < MAX_VPORTS; i++) {
3707 vport = &VPORT(i);
3708 vpip = vport->vpip;
3710 if (!(vport->flag & EMLXS_PORT_BOUND) ||
3711 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
3712 continue;
3715 bcopy((caddr_t)&hba->sparam,
3716 (caddr_t)&vport->sparam,
3717 sizeof (SERV_PARM));
3719 bcopy((caddr_t)&vport->wwnn,
3720 (caddr_t)&vport->sparam.nodeName,
3721 sizeof (NAME_TYPE));
3723 bcopy((caddr_t)&vport->wwpn,
3724 (caddr_t)&vport->sparam.portName,
3725 sizeof (NAME_TYPE));
3728 (void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM_CMPL,
3729 0, 0, 0);
3731 mutex_exit(&EMLXS_FCF_LOCK);
3732 return (0);
3734 } /* emlxs_fc_fcftab_sparm_mbcmpl() */
3737 /*ARGSUSED*/
3738 static uint32_t
3739 emlxs_fc_fcftab_sparm_action(emlxs_port_t *port, uint32_t evt,
3740 void *arg1)
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;
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);
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;
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);
3774 rval = emlxs_fc_fcftab_req_handler(port, arg1);
3775 return (rval);
3778 if (fcftab->attempts == 0) {
3779 fcftab->TID = fcftab->generation;
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);
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);
3796 mb4 = (MAILBOX4*)mbq;
3797 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
3799 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
3800 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3802 rval = emlxs_fc_fcftab_state(port,
3803 FC_FCFTAB_STATE_SPARM_FAILED,
3804 FCF_REASON_NO_BUFFER, 0, arg1);
3805 return (rval);
3807 bzero(mp->virt, mp->size);
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;
3815 mb4->un.varSLIConfig.be.embedded = 0;
3816 mb4->mbxCommand = MBX_READ_SPARM64;
3817 mb4->mbxOwner = OWN_HOST;
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);
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);
3828 rval = emlxs_fc_fcftab_state(port,
3829 FC_FCFTAB_STATE_SPARM_FAILED,
3830 FCF_REASON_SEND_FAILED, rval, arg1);
3832 return (rval);
3835 return (0);
3837 } /* emlxs_fc_fcftab_sparm_action() */
3840 /*ARGSUSED*/
3841 static uint32_t
3842 emlxs_fc_fcftab_sparm_failed_action(emlxs_port_t *port, uint32_t evt,
3843 void *arg1)
3845 emlxs_hba_t *hba = HBA;
3846 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3847 uint32_t rval = 0;
3849 fcftab->attempts++;
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);
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);
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);
3886 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
3887 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3890 return (rval);
3892 } /* emlxs_fc_fcftab_sparm_failed_action() */
3895 /*ARGSUSED*/
3896 static uint32_t
3897 emlxs_fc_fcftab_sparm_cmpl_action(emlxs_port_t *port, uint32_t evt,
3898 void *arg1)
3900 emlxs_hba_t *hba = HBA;
3901 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3902 uint32_t rval = 0;
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);
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);
3920 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE,
3921 FCF_REASON_EVENT, evt, arg1);
3923 return (rval);
3925 } /* emlxs_fc_fcftab_sparm_cmpl_action() */
3928 /*ARGSUSED*/
3929 static void
3930 emlxs_fc_fcftab_process(emlxs_port_t *port)
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;
3940 /* Get the FCFI */
3941 fcfp = fcftab->fcfi[0];
3943 if (!fcfp) {
3944 /* Allocate an fcfi */
3945 fcfp = emlxs_fcfi_alloc(port);
3948 if (!fcfp) {
3949 fcftab->fcfi_count = 0;
3951 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3952 "fc_fcftab_process:%x No FCF available.",
3953 fcftab->TID);
3954 return;
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));
3973 /* Initalize an fcf_rec */
3974 fcf_rec = &fcf_record;
3975 bzero(fcf_rec, sizeof (FCF_RECORD_t));
3977 fcf_rec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ;
3978 fcf_rec->fka_adv_period = 0;
3979 fcf_rec->fip_priority = 128;
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 */
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);
4015 fcf_rec->fcf_valid = 1;
4016 fcf_rec->fcf_available = 1;
4018 /* Update the FCFI */
4019 emlxs_fcfi_update(port, fcfp, fcf_rec, hba->link_event_tag);
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;
4027 return;
4029 } /* emlxs_fc_fcftab_process() */
4032 /*ARGSUSED*/
4033 static uint32_t
4034 emlxs_fc_fcftab_fcfi_online_action(emlxs_port_t *port, uint32_t evt,
4035 void *arg1)
4037 emlxs_hba_t *hba = HBA;
4038 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4039 uint32_t rval = 0;
4040 FCFIobj_t *fcfp;
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);
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);
4059 rval = emlxs_fc_fcftab_req_handler(port, arg1);
4060 return (rval);
4063 emlxs_fc_fcftab_process(port);
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);
4072 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4073 fcftab->flag |= EMLXS_FC_FCFTAB_OFFLINE_REQ;
4074 rval = emlxs_fc_fcftab_req_handler(port, arg1);
4076 mutex_exit(&EMLXS_FCF_LOCK);
4077 return (rval);
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);
4087 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_ONLINE, fcfp);
4089 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE_CMPL,
4090 FCF_REASON_EVENT, evt, arg1);
4092 return (rval);
4094 } /* emlxs_fc_fcftab_fcfi_online_action() */
4097 /*ARGSUSED*/
4098 static uint32_t
4099 emlxs_fc_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, uint32_t evt,
4100 void *arg1)
4102 emlxs_hba_t *hba = HBA;
4103 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4104 uint32_t rval = 0;
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);
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);
4125 rval = emlxs_fc_fcftab_req_handler(port, arg1);
4126 return (rval);
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);
4136 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_ONLINE,
4137 FCF_REASON_EVENT, evt, arg1);
4139 return (rval);
4141 } /* emlxs_fc_fcftab_fcfi_online_cmpl_action() */
4144 /*ARGSUSED*/
4145 static uint32_t
4146 emlxs_fc_fcftab_fcfi_offline_action(emlxs_port_t *port, uint32_t evt,
4147 void *arg1)
4149 emlxs_hba_t *hba = HBA;
4150 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4151 uint32_t rval = 0;
4152 FCFIobj_t *fcfp;
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);
4164 if (fcftab->fcfi_online) {
4165 fcfp = fcftab->fcfi[0];
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);
4174 rval = emlxs_fcfi_event(port,
4175 FCF_EVENT_FCFI_OFFLINE, fcfp);
4177 return (rval);
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);
4186 return (0);
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);
4195 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
4196 FCF_REASON_EVENT, evt, arg1);
4198 return (rval);
4200 } /* emlxs_fc_fcftab_fcfi_offline_action() */
4203 /*ARGSUSED*/
4204 static uint32_t
4205 emlxs_fc_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, uint32_t evt,
4206 void *arg1)
4208 emlxs_hba_t *hba = HBA;
4209 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4210 uint32_t rval = 0;
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);
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);
4230 rval = emlxs_fc_fcftab_req_handler(port, arg1);
4231 return (rval);
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);
4241 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE,
4242 FCF_REASON_EVENT, evt, arg1);
4244 return (rval);
4246 } /* emlxs_fc_fcftab_fcfi_offline_cmpl_action() */
4249 /*ARGSUSED*/
4250 static uint32_t
4251 emlxs_fc_fcftab_linkup_evt_action(emlxs_port_t *port, uint32_t evt,
4252 void *arg1)
4254 emlxs_hba_t *hba = HBA;
4255 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4256 uint32_t rval = 0;
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);
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);
4276 emlxs_fcf_linkup(port);
4278 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4279 fcftab->flag |= EMLXS_FC_FCFTAB_TOPO_REQ;
4280 fcftab->generation++;
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);
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;
4295 default:
4296 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
4297 FCF_REASON_EVENT, evt, arg1);
4298 break;
4301 return (rval);
4303 } /* emlxs_fc_fcftab_linkup_evt_action() */
4306 /*ARGSUSED*/
4307 static uint32_t
4308 emlxs_fc_fcftab_linkdown_evt_action(emlxs_port_t *port, uint32_t evt,
4309 void *arg1)
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;
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);
4328 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4329 fcftab->flag |= EMLXS_FC_FCFTAB_OFFLINE_REQ;
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);
4338 emlxs_fcf_linkdown(port);
4340 /* Pause all active FCFI's */
4341 for (i = 0; i < fcftab->fcfi_count; i++) {
4342 fcfp = fcftab->fcfi[i];
4344 if ((fcfp->state == FCFI_STATE_OFFLINE) ||
4345 (fcfp->state == FCFI_STATE_PAUSED)) {
4346 break;
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);
4355 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_PAUSE, fcfp);
4358 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4359 "fc_fcftab_linkdown_evt_action:%x "
4360 "Going offline.",
4361 fcftab->TID);
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;
4369 default:
4370 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_OFFLINE,
4371 FCF_REASON_EVENT, evt, arg1);
4372 break;
4375 return (rval);
4377 } /* emlxs_fc_fcftab_linkdown_evt_action() */
4380 /*ARGSUSED*/
4381 static uint32_t
4382 emlxs_fc_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, uint32_t evt,
4383 void *arg1)
4385 emlxs_hba_t *hba = HBA;
4386 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4387 uint32_t rval = 0;
4388 FCFIobj_t *fcfp;
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);
4401 fcfp = (FCFIobj_t *)arg1;
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);
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;
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);
4422 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_OFFLINE,
4423 FCF_REASON_REENTER, evt, arg1);
4424 break;
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);
4433 fcfp->flag |= EMLXS_FCFI_FAILED;
4435 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE,
4436 FCF_REASON_REENTER, evt, arg1);
4437 break;
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);
4445 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_ONLINE,
4446 FCF_REASON_REENTER, evt, arg1);
4447 break;
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;
4458 return (rval);
4460 } /* emlxs_fc_fcftab_fcfi_offline_evt_action() */
4463 /*ARGSUSED*/
4464 static uint32_t
4465 emlxs_fc_fcftab_fcfi_online_evt_action(emlxs_port_t *port, uint32_t evt,
4466 void *arg1)
4468 emlxs_hba_t *hba = HBA;
4469 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4470 uint32_t rval = 0;
4471 FCFIobj_t *fcfp;
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);
4484 fcfp = (FCFIobj_t *)arg1;
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);
4491 return (rval);
4493 } /* emlxs_fc_fcftab_fcfi_online_evt_action() */
4496 /*ARGSUSED*/
4497 static uint32_t
4498 emlxs_fc_fcftab_shutdown_evt_action(emlxs_port_t *port, uint32_t evt,
4499 void *arg1)
4501 emlxs_hba_t *hba = HBA;
4502 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4503 uint32_t rval = 0;
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);
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);
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);
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);
4546 emlxs_fcf_linkdown(port);
4548 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SHUTDOWN,
4549 FCF_REASON_EVENT, evt, arg1);
4551 return (rval);
4553 } /* emlxs_fc_fcftab_shutdown_evt_action() */
4556 static uint32_t
4557 emlxs_fc_fcftab_req_handler(emlxs_port_t *port, void *arg1)
4559 emlxs_hba_t *hba = HBA;
4560 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4561 uint32_t rval = 0;
4563 if (!(fcftab->flag & EMLXS_FCFTAB_REQ_MASK)) {
4564 return (1);
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);
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);
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);
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);
4587 return (rval);
4589 } /* emlxs_fc_fcftab_req_handler() */
4593 /* ************************************************************************** */
4594 /* FCOE FCFTAB */
4595 /* ************************************************************************** */
4597 static char *
4598 emlxs_fcoe_fcftab_state_xlate(uint32_t state)
4600 static char buffer[32];
4601 uint32_t i;
4602 uint32_t count;
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);
4611 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
4612 return (buffer);
4614 } /* emlxs_fcoe_fcftab_state_xlate() */
4617 static uint32_t
4618 emlxs_fcoe_fcftab_action(emlxs_port_t *port, uint32_t evt,
4619 void *arg1)
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;
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);
4668 events = FCOE_FCFTAB_ACTION_EVENTS;
4669 state = fcftab->state;
4671 index += (state * events);
4672 func = (uint32_t(*) (emlxs_port_t *, uint32_t, void *))
4673 emlxs_fcoe_fcftab_action_table[index];
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);
4682 return (1);
4685 rval = (func)(port, evt, arg1);
4687 return (rval);
4689 } /* emlxs_fcoe_fcftab_action() */
4692 static uint32_t
4693 emlxs_fcoe_fcftab_event(emlxs_port_t *port, uint32_t evt,
4694 void *arg1)
4696 emlxs_hba_t *hba = HBA;
4697 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4698 uint32_t rval = 0;
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;
4714 default:
4715 return (1);
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);
4724 rval = emlxs_fcoe_fcftab_action(port, evt, arg1);
4726 return (rval);
4728 } /* emlxs_fcoe_fcftab_event() */
4731 /* EMLXS_FCF_LOCK must be held to enter */
4732 /*ARGSUSED*/
4733 static uint32_t
4734 emlxs_fcoe_fcftab_state(emlxs_port_t *port, uint16_t state, uint16_t reason,
4735 uint32_t explain, void *arg1)
4737 emlxs_hba_t *hba = HBA;
4738 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4739 uint32_t rval = 0;
4741 if (state >= FCOE_FCFTAB_ACTION_STATES) {
4742 return (1);
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);
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);
4788 fcftab->prev_state = fcftab->state;
4789 fcftab->prev_reason = fcftab->reason;
4790 fcftab->state = state;
4791 fcftab->reason = reason;
4793 rval = emlxs_fcoe_fcftab_action(port, FCF_EVENT_STATE_ENTER, arg1);
4795 return (rval);
4797 } /* emlxs_fcoe_fcftab_state() */
4800 /*ARGSUSED*/
4801 static uint32_t
4802 emlxs_fcoe_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, uint32_t evt,
4803 void *arg1)
4805 emlxs_hba_t *hba = HBA;
4806 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4807 uint32_t rval = 0;
4808 FCFIobj_t *fcfp;
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);
4821 fcfp = (FCFIobj_t *)arg1;
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);
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;
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);
4843 rval = emlxs_fcoe_fcftab_state(port,
4844 FCOE_FCFTAB_STATE_FCFI_OFFLINE,
4845 FCF_REASON_REENTER, evt, arg1);
4846 break;
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);
4855 fcfp->flag |= EMLXS_FCFI_FAILED;
4857 rval = emlxs_fcoe_fcftab_state(port,
4858 FCOE_FCFTAB_STATE_FCFI_ONLINE,
4859 FCF_REASON_REENTER, evt, arg1);
4860 break;
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);
4868 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_ONLINE,
4869 FCF_REASON_REENTER, evt, arg1);
4870 break;
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;
4881 return (rval);
4883 } /* emlxs_fcoe_fcftab_fcfi_offline_evt_action() */
4886 /*ARGSUSED*/
4887 static uint32_t
4888 emlxs_fcoe_fcftab_fcfi_online_evt_action(emlxs_port_t *port, uint32_t evt,
4889 void *arg1)
4891 emlxs_hba_t *hba = HBA;
4892 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4893 uint32_t rval = 0;
4894 FCFIobj_t *fcfp;
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);
4907 fcfp = (FCFIobj_t *)arg1;
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);
4914 return (rval);
4916 } /* emlxs_fcoe_fcftab_fcfi_online_evt_action() */
4919 /*ARGSUSED*/
4920 static uint32_t
4921 emlxs_fcoe_fcftab_cvl_evt_action(emlxs_port_t *port, uint32_t evt,
4922 void *arg1)
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;
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);
4942 /* Pause VPI */
4943 vpi = (uint32_t)((unsigned long)arg1);
4944 vport = &VPORT(vpi);
4945 vpip = vport->vpip;
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);
4954 rval = emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip);
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;
4966 default:
4967 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4968 fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
4969 fcftab->generation++;
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);
4977 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
4978 FCF_REASON_EVENT, evt, arg1);
4979 break;
4982 return (rval);
4984 } /* emlxs_fcoe_fcftab_cvl_evt_action() */
4987 /*ARGSUSED*/
4988 static uint32_t
4989 emlxs_fcoe_fcftab_linkup_evt_action(emlxs_port_t *port, uint32_t evt,
4990 void *arg1)
4992 emlxs_hba_t *hba = HBA;
4993 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4994 uint32_t rval = 0;
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);
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);
5014 emlxs_fcf_linkup(port);
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;
5026 default:
5027 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
5028 fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
5029 fcftab->generation++;
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);
5037 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
5038 FCF_REASON_EVENT, evt, arg1);
5039 break;
5042 return (rval);
5044 } /* emlxs_fcoe_fcftab_linkup_evt_action() */
5047 /*ARGSUSED*/
5048 static uint32_t
5049 emlxs_fcoe_fcftab_linkdown_evt_action(emlxs_port_t *port, uint32_t evt,
5050 void *arg1)
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;
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);
5069 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
5070 fcftab->flag |= EMLXS_FCOE_FCFTAB_OFFLINE_REQ;
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);
5080 emlxs_fcf_linkdown(port);
5082 /* Pause all active FCFI's */
5083 for (i = 0; i < fcftab->fcfi_count; i++) {
5084 fcfp = fcftab->fcfi[i];
5086 if ((fcfp->state == FCFI_STATE_OFFLINE) ||
5087 (fcfp->state == FCFI_STATE_PAUSED)) {
5088 break;
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);
5096 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_PAUSE, fcfp);
5099 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5100 "fcoe_fcftab_linkdown_evt_action:%x "
5101 "Going offline.",
5102 fcftab->TID);
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;
5110 default:
5111 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_OFFLINE,
5112 FCF_REASON_EVENT, evt, arg1);
5113 break;
5116 return (rval);
5118 } /* emlxs_fcoe_fcftab_linkdown_evt_action() */
5121 /*ARGSUSED*/
5122 static uint32_t
5123 emlxs_fcoe_fcftab_shutdown_evt_action(emlxs_port_t *port, uint32_t evt,
5124 void *arg1)
5126 emlxs_hba_t *hba = HBA;
5127 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5128 uint32_t rval = 0;
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);
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);
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);
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);
5171 emlxs_fcf_linkdown(port);
5173 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SHUTDOWN,
5174 FCF_REASON_EVENT, evt, arg1);
5176 return (rval);
5178 } /* emlxs_fcoe_fcftab_shutdown_evt_action() */
5181 static uint32_t
5182 emlxs_fcoe_fcftab_req_handler(emlxs_port_t *port, void *arg1)
5184 emlxs_hba_t *hba = HBA;
5185 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5186 uint32_t rval = 0;
5188 if (!(fcftab->flag & EMLXS_FCFTAB_REQ_MASK)) {
5189 return (1);
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);
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);
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);
5207 return (rval);
5209 } /* emlxs_fcoe_fcftab_req_handler() */
5212 static void
5213 emlxs_fcoe_fcftab_read_timer(emlxs_hba_t *hba)
5215 emlxs_port_t *port = &PPORT;
5216 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5218 /* Check FCF timer */
5219 if (!fcftab->read_timer ||
5220 (hba->timer_tics < fcftab->read_timer)) {
5221 return;
5223 fcftab->read_timer = 0;
5224 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
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));
5233 (void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
5234 0, 0, FCFTAB_READ_ALL);
5235 break;
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;
5245 return;
5247 } /* emlxs_fcoe_fcftab_read_timer() */
5250 static void
5251 emlxs_fcoe_fcftab_sol_timer(emlxs_hba_t *hba)
5253 emlxs_port_t *port = &PPORT;
5254 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5256 /* Check FCF timer */
5257 if (!fcftab->sol_timer ||
5258 (hba->timer_tics < fcftab->sol_timer)) {
5259 return;
5261 fcftab->sol_timer = 0;
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++;
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);
5275 (void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
5276 FCF_REASON_EVENT, 0, 0);
5277 break;
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;
5287 return;
5289 } /* emlxs_fcoe_fcftab_sol_timer() */
5292 static void
5293 emlxs_fcoe_fcftab_offline_timer(emlxs_hba_t *hba)
5295 emlxs_port_t *port = &PPORT;
5296 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5297 uint32_t i;
5298 FCFIobj_t *fcfp;
5300 for (i = 0; i < fcftab->fcfi_count; i++) {
5301 fcfp = fcftab->fcfi[i];
5303 /* Check offline timer */
5304 if (!fcfp->offline_timer ||
5305 (hba->timer_tics < fcfp->offline_timer)) {
5306 continue;
5308 fcfp->offline_timer = 0;
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);
5315 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp);
5318 return;
5320 } /* emlxs_fcoe_fcftab_offline_timer() */
5323 /*ARGSUSED*/
5324 static uint32_t
5325 emlxs_fcoe_fcftab_sol_failed_action(emlxs_port_t *port, uint32_t evt,
5326 void *arg1)
5328 emlxs_hba_t *hba = HBA;
5329 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5330 uint32_t rval = 0;
5332 fcftab->attempts++;
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);
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);
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);
5370 rval = emlxs_fcoe_fcftab_state(port,
5371 FCOE_FCFTAB_STATE_SOLICIT,
5372 FCF_REASON_OP_FAILED, 0, arg1);
5375 return (rval);
5377 } /* emlxs_fcoe_fcftab_sol_failed_action() */
5380 /*ARGSUSED*/
5381 static uint32_t
5382 emlxs_fcoe_fcftab_sol_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
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;
5394 mutex_enter(&EMLXS_FCF_LOCK);
5395 TID = (uint16_t)((unsigned long)mbq->context);
5397 if (mbq->nonembed) {
5398 fip_mode = 0;
5400 mp = (MATCHMAP *)mbq->nonembed;
5401 mbq->nonembed = NULL;
5403 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
5404 status = hdr_rsp->status;
5405 xstatus = hdr_rsp->extra_status;
5407 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
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));
5416 mutex_exit(&EMLXS_FCF_LOCK);
5417 return (0);
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);
5428 mutex_exit(&EMLXS_FCF_LOCK);
5429 return (0);
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));
5439 (void) emlxs_fcoe_fcftab_state(port,
5440 FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5441 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
5443 mutex_exit(&EMLXS_FCF_LOCK);
5444 return (0);
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);
5453 (void) emlxs_fcoe_fcftab_state(port,
5454 FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5455 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
5457 mutex_exit(&EMLXS_FCF_LOCK);
5458 return (0);
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);
5468 (void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT_CMPL,
5469 0, 0, 0);
5471 mutex_exit(&EMLXS_FCF_LOCK);
5472 return (0);
5474 } /* emlxs_fcoe_fcftab_sol_mbcmpl() */
5477 /*ARGSUSED*/
5478 static uint32_t
5479 emlxs_fcoe_fcftab_sol_action(emlxs_port_t *port, uint32_t evt,
5480 void *arg1)
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;
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);
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;
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);
5515 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
5516 return (rval);
5519 if (fcftab->attempts == 0) {
5520 fcftab->TID = fcftab->generation;
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));
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);
5539 mb4 = (MAILBOX4*)mbq;
5540 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
5542 if (hba->flag & FC_FIP_SUPPORTED) {
5543 IOCTL_FCOE_REDISCOVER_FCF_TABLE *fcf;
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;
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);
5564 fcf = (IOCTL_FCOE_REDISCOVER_FCF_TABLE *)
5565 &mb4->un.varSLIConfig.payload;
5566 fcf->params.request.fcf_count = 0; /* invalidate FCF table */
5568 } else { /* Non-FIP */
5570 /* Non-FIP uses a persistent FCF entry that */
5571 /* we must add to the table */
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;
5579 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
5580 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5582 rval = emlxs_fcoe_fcftab_state(port,
5583 FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5584 FCF_REASON_NO_BUFFER, 0, arg1);
5585 return (rval);
5587 bzero(mp->virt, mp->size);
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;
5594 mb4->un.varSLIConfig.be.embedded = 0;
5595 mb4->mbxCommand = MBX_SLI_CONFIG;
5596 mb4->mbxOwner = OWN_HOST;
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);
5604 fcf = (IOCTL_FCOE_ADD_FCF_TABLE *)(hdr_req + 1);
5605 fcf->params.request.fcf_index = 0;
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;
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 */
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);
5646 fcf_rec->fcf_valid = 1;
5647 fcf_rec->fcf_available = 1;
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);
5655 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5657 rval = emlxs_fcoe_fcftab_state(port,
5658 FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5659 FCF_REASON_SEND_FAILED, rval, 0);
5661 return (rval);
5664 return (0);
5666 } /* emlxs_fcoe_fcftab_sol_action() */
5669 /*ARGSUSED*/
5670 static uint32_t
5671 emlxs_fcoe_fcftab_sol_cmpl_action(emlxs_port_t *port, uint32_t evt,
5672 void *arg1)
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;
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);
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);
5699 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
5700 return (rval);
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);
5712 /* Start the read timer */
5713 fcftab->read_timer = hba->timer_tics +
5714 cfg[CFG_FCF_SOLICIT_DELAY].current;
5716 return (0);
5718 } /* emlxs_fcoe_fcftab_sol_cmpl_action() */
5721 /*ARGSUSED*/
5722 static uint32_t
5723 emlxs_fcoe_fcftab_read_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
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;
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);
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));
5749 mutex_exit(&EMLXS_FCF_LOCK);
5750 return (0);
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);
5761 mutex_exit(&EMLXS_FCF_LOCK);
5762 return (0);
5765 mp = (MATCHMAP *)mbq->nonembed;
5766 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
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);
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));
5780 mutex_exit(&EMLXS_FCF_LOCK);
5781 return (0);
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));
5789 fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_rsp + 1);
5790 fcfrec = &fcf->params.response.fcf_entry[0];
5792 #ifdef EMLXS_BIG_ENDIAN
5794 uint32_t *iptr;
5795 uint32_t i;
5796 uint8_t j;
5797 uint16_t s;
5798 uint16_t *sptr;
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);
5805 iptr = (uint32_t *)&fcfrec->fcf_mac_address_hi[0];
5806 i = *iptr;
5807 *iptr = SWAP32(i);
5809 sptr = (uint16_t *)&fcfrec->fcf_mac_address_low[0];
5810 s = *sptr;
5811 *sptr = SWAP16(s);
5813 j = fcfrec->fc_map[0];
5814 fcfrec->fc_map[0] = fcfrec->fc_map[2];
5815 fcfrec->fc_map[2] = j;
5817 #endif /* EMLXS_BIG_ENDIAN */
5819 event_tag = fcf->params.response.event_tag;
5821 /* Try to find existing fcfrec */
5822 fcfp = emlxs_fcfi_find(port, fcfrec, 0);
5824 /* If not found, allocate a new one */
5825 if (!fcfp) {
5826 fcfp = emlxs_fcfi_alloc(port);
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);
5835 (void) emlxs_fcoe_fcftab_state(port,
5836 FCOE_FCFTAB_STATE_READ_FAILED,
5837 FCF_REASON_NO_FCFI, 0,
5838 (void*)((unsigned long)index));
5840 mutex_exit(&EMLXS_FCF_LOCK);
5841 return (0);
5844 /* Update the FCFI */
5845 emlxs_fcfi_update(port, fcfp, fcfrec, event_tag);
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);
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);
5862 (void) emlxs_fcoe_fcftab_state(port,
5863 FCOE_FCFTAB_STATE_READ_CMPL,
5864 0, 0, (void*)((unsigned long)index));
5867 mutex_exit(&EMLXS_FCF_LOCK);
5868 return (0);
5870 } /* emlxs_fcoe_fcftab_read_mbcmpl() */
5873 /*ARGSUSED*/
5874 static uint32_t
5875 emlxs_fcoe_fcftab_read_action(emlxs_port_t *port, uint32_t evt,
5876 void *arg1)
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;
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);
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;
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);
5914 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
5915 return (rval);
5918 if (fcftab->attempts == 0) {
5919 fcftab->TID = fcftab->generation;
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);
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);
5936 mb4 = (MAILBOX4*)mbq;
5937 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
5939 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
5940 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5942 rval = emlxs_fcoe_fcftab_state(port,
5943 FCOE_FCFTAB_STATE_READ_FAILED,
5944 FCF_REASON_NO_BUFFER, 0, arg1);
5945 return (rval);
5947 bzero(mp->virt, mp->size);
5949 mbq->nonembed = (void *)mp;
5950 mbq->mbox_cmpl = emlxs_fcoe_fcftab_read_mbcmpl;
5952 context = ((uint32_t)fcftab->TID << 16) | (uint32_t)index;
5953 mbq->context = (void *)((unsigned long)context);
5954 mbq->port = (void *)port;
5956 mb4->un.varSLIConfig.be.embedded = 0;
5957 mb4->mbxCommand = MBX_SLI_CONFIG;
5958 mb4->mbxOwner = OWN_HOST;
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);
5966 fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1);
5967 fcf->params.request.fcf_index = index;
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);
5974 rval = emlxs_fcoe_fcftab_state(port,
5975 FCOE_FCFTAB_STATE_READ_FAILED,
5976 FCF_REASON_SEND_FAILED, rval, arg1);
5978 return (rval);
5981 return (0);
5983 } /* emlxs_fcoe_fcftab_read_action() */
5986 /*ARGSUSED*/
5987 static uint32_t
5988 emlxs_fcoe_fcftab_read_failed_action(emlxs_port_t *port, uint32_t evt,
5989 void *arg1)
5991 emlxs_hba_t *hba = HBA;
5992 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5993 uint32_t rval = 0;
5995 fcftab->attempts++;
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);
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);
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);
6033 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
6034 FCF_REASON_OP_FAILED, fcftab->attempts, FCFTAB_READ_ALL);
6037 return (rval);
6039 } /* emlxs_fcoe_fcftab_read_failed_action() */
6042 /*ARGSUSED*/
6043 static uint32_t
6044 emlxs_fcoe_fcftab_read_cmpl_action(emlxs_port_t *port, uint32_t evt,
6045 void *arg1)
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;
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);
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);
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;
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;
6085 /* Clear the failed bit */
6086 fcfp->flag &= ~EMLXS_FCFI_FAILED;
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);
6097 (void) emlxs_fcfi_free(port, fcfp);
6098 continue;
6102 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_FCFI_ONLINE,
6103 FCF_REASON_EVENT, evt, arg1);
6105 return (rval);
6107 } /* emlxs_fcoe_fcftab_read_cmpl_action() */
6110 static FCFIobj_t *
6111 emlxs_fcoe_fcftab_fcfi_select(emlxs_port_t *port, char *fabric_wwn)
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;
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);
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;
6142 if ((fcfp1->flag & mask) != viable) {
6143 fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
6144 continue;
6147 if (fabric_wwn &&
6148 bcmp(fabric_wwn,
6149 fcfp1->fcf_rec.fabric_name_identifier, 8)) {
6150 fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
6151 continue;
6154 fcfp1->flag |= EMLXS_FCFI_TAGGED;
6155 fcfp = fcfp1;
6156 fcf_table_count++;
6159 if (fcf_table_count == 0) {
6160 return (NULL);
6163 if (fcf_table_count == 1) {
6164 return (fcfp);
6167 /* We found more than one viable entry */
6169 fcf_table = (FCFIobj_t **)kmem_zalloc(
6170 (sizeof (uintptr_t) * fcf_table_count), KM_SLEEP);
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;
6181 if (!fcfp ||
6182 (fcfp1->priority > fcfp->priority)) {
6183 fcfp = fcfp1;
6187 if (fcf_table[0] &&
6188 (fcf_table[0]->priority > fcfp->priority)) {
6189 break;
6192 fcfp->flag &= ~EMLXS_FCFI_TAGGED;
6193 fcf_table[i] = fcfp;
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);
6206 fcfp = fcf_table[(rnum%i)];
6207 } else {
6208 fcfp = fcf_table[0];
6211 /* Free the priority table */
6212 kmem_free(fcf_table, (sizeof (uintptr_t) * fcf_table_count));
6214 return (fcfp);
6216 } /* emlxs_fcoe_fcftab_fcfi_select() */
6219 /*ARGSUSED*/
6220 static void
6221 emlxs_fcoe_fcftab_process(emlxs_port_t *port)
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;
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);
6240 /* Deselection process */
6241 for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
6242 fcfp = fcftab->fcfi[i];
6244 if (!fcfp) {
6245 continue;
6248 /* Check if entry is viable */
6249 if ((fcfp->flag & mask) == viable) {
6250 if (fcfp->offline_timer) {
6251 fcfp->offline_timer = 0;
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);
6261 continue;
6264 /* Previous entry is no longer viable */
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;
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);
6282 continue;
6285 /* Deselect it */
6286 fcfp->flag &= ~EMLXS_FCFI_SELECTED;
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);
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));
6306 /* Reselection process */
6307 for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
6308 prev_fcfp = fcftab->fcfi[i];
6309 fcftab->fcfi[i] = NULL;
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);
6316 if (fcfp) {
6317 fcfp->flag |= EMLXS_FCFI_SELECTED;
6318 fcftab->fcfi[i] = fcfp;
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,
6333 continue;
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;
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;
6350 /* Previous entry is no longer selected */
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);
6356 if (fcfp) {
6357 fcfp->flag |= EMLXS_FCFI_SELECTED;
6358 fcftab->fcfi[i] = fcfp;
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;
6369 /* Select fcf from any fabric */
6370 fcfp = emlxs_fcoe_fcftab_fcfi_select(port, 0);
6372 if (fcfp) {
6373 fcfp->flag |= EMLXS_FCFI_SELECTED;
6374 fcftab->fcfi[i] = fcfp;
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;
6385 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6386 "fcoe_fcftab_process:%x %d. No FCF available.",
6387 fcftab->TID,
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;
6399 for (j = i+1; j < FCFTAB_MAX_FCFI_COUNT; j++) {
6400 if (fcftab->fcfi[j] == NULL) {
6401 continue;
6404 fcftab->fcfi[i] = fcftab->fcfi[j];
6405 fcftab->fcfi[j] = NULL;
6406 count++;
6407 break;
6410 if (j == FCFTAB_MAX_FCFI_COUNT) {
6411 break;
6414 fcftab->fcfi_count = count;
6416 return;
6418 } /* emlxs_fcoe_fcftab_process() */
6421 /*ARGSUSED*/
6422 static uint32_t
6423 emlxs_fcoe_fcftab_fcfi_online_action(emlxs_port_t *port, uint32_t evt,
6424 void *arg1)
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;
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);
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);
6451 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
6452 return (rval);
6455 emlxs_fcoe_fcftab_process(port);
6457 for (i = 0; i < fcftab->fcfi_count; i++) {
6458 fcfp = fcftab->fcfi[i];
6460 if (fcfp->offline_timer == 0) {
6461 online_count++;
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);
6470 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_ONLINE,
6471 fcfp);
6472 } else {
6473 offline_count++;
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);
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);
6490 /* Service timer now */
6491 emlxs_fcoe_fcftab_offline_timer(hba);
6493 return (rval);
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);
6503 rval = emlxs_fcoe_fcftab_state(port,
6504 FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL,
6505 FCF_REASON_EVENT, evt, arg1);
6507 return (rval);
6509 } /* emlxs_fcoe_fcftab_fcfi_online_action() */
6512 /*ARGSUSED*/
6513 static uint32_t
6514 emlxs_fcoe_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, uint32_t evt,
6515 void *arg1)
6517 emlxs_hba_t *hba = HBA;
6518 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6519 uint32_t rval = 0;
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);
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);
6540 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
6541 return (rval);
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);
6551 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_ONLINE,
6552 FCF_REASON_EVENT, evt, arg1);
6554 return (rval);
6556 } /* emlxs_fcoe_fcftab_fcfi_online_cmpl_action() */
6559 /*ARGSUSED*/
6560 static uint32_t
6561 emlxs_fcoe_fcftab_fcfi_offline_action(emlxs_port_t *port, uint32_t evt,
6562 void *arg1)
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;
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);
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];
6586 if (fcfp->state <= FCFI_STATE_OFFLINE) {
6587 continue;
6590 if (fcfp->offline_timer ||
6591 (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
6592 fcfi_offline++;
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);
6605 return (0);
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);
6614 rval = emlxs_fcoe_fcftab_state(port,
6615 FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
6616 FCF_REASON_EVENT, evt, arg1);
6618 return (rval);
6620 } /* emlxs_fcoe_fcftab_fcfi_offline_action() */
6623 /*ARGSUSED*/
6624 static uint32_t
6625 emlxs_fcoe_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, uint32_t evt,
6626 void *arg1)
6628 emlxs_hba_t *hba = HBA;
6629 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6630 uint32_t rval = 0;
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);
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);
6650 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
6651 return (rval);
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);
6661 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_FCFI_ONLINE,
6662 FCF_REASON_EVENT, evt, arg1);
6664 return (rval);
6666 } /* emlxs_fcoe_fcftab_fcfi_offline_cmpl_action() */
6669 /*ARGSUSED*/
6670 static uint32_t
6671 emlxs_fcoe_fcftab_found_evt_action(emlxs_port_t *port, uint32_t evt,
6672 void *arg1)
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;
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);
6689 return (1);
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;
6705 /* case FCOE_FCFTAB_STATE_FCFI_OFFLINE: */
6706 default:
6708 /* Scan for matching fcf index in table */
6709 fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
6711 if (fcfp && (fcfp->flag & EMLXS_FCFI_SELECTED)) {
6713 /* Trigger table read */
6714 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6715 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6716 fcftab->generation++;
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);
6726 rval = emlxs_fcoe_fcftab_state(port,
6727 FCOE_FCFTAB_STATE_READ,
6728 FCF_REASON_EVENT, evt, arg1);
6730 break;
6733 /* Check if we need more FCF's */
6734 if (fcftab->fcfi_online < FCFTAB_MAX_FCFI_COUNT) {
6736 /* Trigger table read */
6737 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6738 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6739 fcftab->generation++;
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);
6751 rval = emlxs_fcoe_fcftab_state(port,
6752 FCOE_FCFTAB_STATE_READ,
6753 FCF_REASON_EVENT, evt, arg1);
6755 break;
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);
6766 break;
6769 return (rval);
6771 } /* emlxs_fcoe_fcftab_found_evt_action() */
6774 /*ARGSUSED*/
6775 static uint32_t
6776 emlxs_fcoe_fcftab_lost_evt_action(emlxs_port_t *port, uint32_t evt,
6777 void *arg1)
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;
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);
6797 return (1);
6800 /* Scan for matching fcf index in table */
6801 fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
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);
6812 return (0);
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);
6824 return (0);
6827 /* Offline VPI's of this FCFI */
6828 for (i = 0; i <= hba->vpi_max; i++) {
6829 vport = &VPORT(i);
6830 vpip = vport->vpip;
6832 if ((vpip->state == VPI_STATE_OFFLINE) ||
6833 (vpip->vfip->fcfp != fcfp)) {
6834 continue;
6837 /* Fabric logo is implied */
6838 emlxs_vpi_logo_handler(port, vpip);
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);
6849 (void) emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
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;
6862 default:
6863 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6864 fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
6865 fcftab->generation++;
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);
6873 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
6874 FCF_REASON_EVENT, evt, arg1);
6875 break;
6878 return (rval);
6880 } /* emlxs_fcoe_fcftab_lost_evt_action() */
6883 /*ARGSUSED*/
6884 static uint32_t
6885 emlxs_fcoe_fcftab_changed_evt_action(emlxs_port_t *port, uint32_t evt,
6886 void *arg1)
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;
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);
6903 return (1);
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;
6919 /* case FCOE_FCFTAB_STATE_FCFI_OFFLINE: */
6920 default:
6922 /* Scan for matching fcf index in table */
6923 fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
6925 if (fcfp && (fcfp->flag & EMLXS_FCFI_SELECTED)) {
6927 /* Trigger table read */
6928 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6929 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6930 fcftab->generation++;
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);
6940 rval = emlxs_fcoe_fcftab_state(port,
6941 FCOE_FCFTAB_STATE_READ,
6942 FCF_REASON_EVENT, evt, arg1);
6944 break;
6947 /* Check if we need more FCF's */
6948 if (fcftab->fcfi_online < FCFTAB_MAX_FCFI_COUNT) {
6950 /* Trigger table read */
6951 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6952 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6953 fcftab->generation++;
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);
6965 rval = emlxs_fcoe_fcftab_state(port,
6966 FCOE_FCFTAB_STATE_READ,
6967 FCF_REASON_EVENT, evt, arg1);
6969 break;
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);
6980 break;
6983 return (rval);
6985 } /* emlxs_fcoe_fcftab_changed_evt_action() */
6988 /*ARGSUSED*/
6989 static uint32_t
6990 emlxs_fcoe_fcftab_fcf_delete(emlxs_port_t *port, uint32_t fcf_index)
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;
6999 IOCTL_FCOE_DELETE_FCF_TABLE *fcf;
7000 mbox_req_hdr_t *hdr_req;
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);
7009 return (1);
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);
7019 return (1);
7022 mb4 = (MAILBOX4*)mbq;
7023 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
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);
7032 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7033 return (1);
7035 bzero(mp->virt, mp->size);
7037 mbq->nonembed = (void *)mp;
7038 mbq->mbox_cmpl = NULL;
7039 mbq->context = (void *)((unsigned long)fcf_index);
7040 mbq->port = (void *)port;
7042 mb4->un.varSLIConfig.be.embedded = 0;
7043 mb4->mbxCommand = MBX_SLI_CONFIG;
7044 mb4->mbxOwner = OWN_HOST;
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);
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;
7056 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7057 "fcoe_fcftab_fcf_delete:%x fcfi:%d. <",
7058 fcftab->TID,
7059 fcf_index);
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);
7069 if (mp) {
7070 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
7072 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7074 return (1);
7077 return (0);
7080 } /* emlxs_fcoe_fcftab_fcf_delete() */
7083 /*ARGSUSED*/
7084 static uint32_t
7085 emlxs_fcoe_fcftab_full_evt_action(emlxs_port_t *port, uint32_t evt,
7086 void *arg1)
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;
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);
7105 return (1);
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);
7117 return (0);
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);
7128 mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7129 EMLXS_FCFI_CONFIGURED);
7130 viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7131 EMLXS_FCFI_CONFIGURED);
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;
7140 if (fcfp->flag & EMLXS_FCFI_SELECTED) {
7141 continue;
7144 if ((fcfp->flag & mask) == viable) {
7145 continue;
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);
7155 (void) emlxs_fcfi_free(port, fcfp);
7157 (void) emlxs_fcoe_fcftab_fcf_delete(port, fcfp->fcf_index);
7159 count++;
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);
7170 return (0);
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;
7183 default:
7184 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
7185 fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
7186 fcftab->generation++;
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);
7194 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
7195 FCF_REASON_EVENT, evt, arg1);
7196 break;
7199 return (rval);
7201 } /* emlxs_fcoe_fcftab_full_evt_action() */
7204 /*ARGSUSED*/
7205 static uint32_t
7206 emlxs_fcoe_fcftab_online_action(emlxs_port_t *port, uint32_t evt,
7207 void *arg1)
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;
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);
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);
7236 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
7237 return (rval);
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);
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;
7254 if ((fcfp->flag & mask) == viable) {
7255 count++;
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);
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);
7281 emlxs_fcf_linkdown(port);
7283 return (0);
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);
7293 emlxs_fcf_linkup(port);
7295 return (rval);
7297 } /* emlxs_fcoe_fcftab_online_action() */
7300 /*ARGSUSED*/
7301 static uint32_t
7302 emlxs_fcoe_fcftab_offline_action(emlxs_port_t *port, uint32_t evt,
7303 void *arg1)
7305 emlxs_hba_t *hba = HBA;
7306 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7307 uint32_t rval = 0;
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);
7320 fcftab->flag &= ~EMLXS_FCOE_FCFTAB_OFFLINE_REQ;
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);
7331 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
7332 return (rval);
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);
7343 return (rval);
7345 } /* emlxs_fcoe_fcftab_offline_action() */
7348 /* ************************************************************************** */
7349 /* FCFI */
7350 /* ************************************************************************** */
7352 static char *
7353 emlxs_fcfi_state_xlate(uint32_t state)
7355 static char buffer[32];
7356 uint32_t i;
7357 uint32_t count;
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);
7366 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
7367 return (buffer);
7369 } /* emlxs_fcfi_state_xlate() */
7372 static uint32_t
7373 emlxs_fcfi_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
7374 void *arg1)
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;
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);
7406 events = FCFI_ACTION_EVENTS;
7407 state = fcfp->state;
7409 index += (state * events);
7410 func = (uint32_t(*) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *))
7411 emlxs_fcfi_action_table[index];
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);
7420 return (1);
7423 rval = (func)(port, fcfp, evt, arg1);
7425 return (rval);
7427 } /* emlxs_fcfi_action() */
7430 static uint32_t
7431 emlxs_fcfi_event(emlxs_port_t *port, uint32_t evt,
7432 void *arg1)
7434 FCFIobj_t *fcfp = NULL;
7435 VFIobj_t *vfip = NULL;
7436 uint32_t rval = 0;
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;
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);
7449 return (1);
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);
7458 return (1);
7460 break;
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);
7471 return (1);
7473 break;
7475 default:
7476 return (1);
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);
7485 rval = emlxs_fcfi_action(port, fcfp, evt, arg1);
7487 return (rval);
7489 } /* emlxs_fcfi_event() */
7492 /* EMLXS_FCF_LOCK must be held to enter */
7493 /*ARGSUSED*/
7494 static uint32_t
7495 emlxs_fcfi_state(emlxs_port_t *port, FCFIobj_t *fcfp, uint16_t state,
7496 uint16_t reason, uint32_t explain, void *arg1)
7498 uint32_t rval = 0;
7500 if (state >= FCFI_ACTION_STATES) {
7501 return (1);
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);
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);
7547 fcfp->prev_state = fcfp->state;
7548 fcfp->prev_reason = fcfp->reason;
7549 fcfp->state = state;
7550 fcfp->reason = reason;
7552 rval = emlxs_fcfi_action(port, fcfp, FCF_EVENT_STATE_ENTER, arg1);
7554 return (rval);
7556 } /* emlxs_fcfi_state() */
7559 static FCFIobj_t *
7560 emlxs_fcfi_alloc(emlxs_port_t *port)
7562 emlxs_hba_t *hba = HBA;
7563 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7564 uint16_t i;
7565 FCFIobj_t *fcfp;
7567 fcfp = fcftab->table;
7568 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7569 if (fcfp->state == FCFI_STATE_FREE) {
7571 bzero(fcfp, sizeof (FCFIobj_t));
7572 fcfp->index = i;
7573 fcfp->FCFI = 0xFFFF;
7575 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7576 "fcfi_alloc:%d. Allocating FCFI. >",
7577 fcfp->index);
7579 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
7580 0, 0, 0);
7581 return (fcfp);
7585 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7586 "fcfi_alloc: Out of FCFI objects.",
7587 fcfp->index);
7589 return (NULL);
7591 } /* emlxs_fcfi_alloc() */
7594 static uint32_t
7595 emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp)
7597 uint32_t rval = 0;
7599 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_FREE, 0, 0, 0);
7601 return (rval);
7603 } /* emlxs_fcfi_free() */
7606 static FCFIobj_t *
7607 emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec, uint32_t *fcf_index)
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;
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;
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);
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;
7644 if (fcfp->fcf_index == index) {
7645 return (fcfp);
7650 return (NULL);
7652 } /* emlxs_fcfi_find() */
7655 /*ARGSUSED*/
7656 static uint32_t
7657 emlxs_fcfi_free_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
7658 void *arg1)
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);
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);
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);
7684 fcfp->flag = 0;
7686 return (0);
7688 } /* emlxs_fcfi_free_action() */
7691 /*ARGSUSED*/
7692 static uint32_t
7693 emlxs_fcfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
7694 void *arg1)
7696 emlxs_hba_t *hba = HBA;
7697 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7698 uint32_t rval = 0;
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);
7710 fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
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);
7718 return (0);
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);
7728 if (fcfp->flag & EMLXS_FCFI_FCFTAB) {
7729 fcfp->flag &= ~EMLXS_FCFI_FCFTAB;
7731 if (fcftab->fcfi_online) {
7732 fcftab->fcfi_online--;
7736 /* Check if online was requested */
7737 if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) {
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);
7745 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
7746 FCF_REASON_REQUESTED, 0, arg1);
7747 return (rval);
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);
7756 /* Notify FCFTAB */
7757 rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp);
7759 return (rval);
7761 } /* emlxs_fcfi_offline_action() */
7764 /*ARGSUSED*/
7765 static uint32_t
7766 emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
7767 uint32_t evt, void *arg1)
7769 uint32_t rval = 0;
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);
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);
7791 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
7792 FCF_REASON_REENTER, evt, arg1);
7793 break;
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);
7803 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE_CMPL,
7804 FCF_REASON_EVENT, evt, arg1);
7805 break;
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);
7816 return (rval);
7818 } /* emlxs_fcfi_vfi_online_evt_action() */
7821 /*ARGSUSED*/
7822 static uint32_t
7823 emlxs_fcfi_offline_handler(emlxs_port_t *port, FCFIobj_t *fcfp, void *arg1)
7825 uint32_t rval = 0;
7827 if (!(fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
7828 return (0);
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);
7841 } else if (fcfp->flag & EMLXS_FCFI_REG) {
7842 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
7843 FCF_REASON_REQUESTED, 0, arg1);
7845 } else {
7846 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
7847 FCF_REASON_REQUESTED, 0, arg1);
7850 return (rval);
7852 } /* emlxs_fcfi_offline_handler() */
7855 /*ARGSUSED*/
7856 static uint32_t
7857 emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
7858 uint32_t evt, void *arg1)
7860 uint32_t rval = 0;
7861 VFIobj_t *vfip;
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);
7874 vfip = (VFIobj_t *)arg1;
7875 vfip->fcfp = NULL;
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);
7887 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
7888 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
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);
7898 break;
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;
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);
7913 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL,
7914 FCF_REASON_EVENT, evt, arg1);
7915 break;
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);
7923 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL,
7924 FCF_REASON_REENTER, evt, arg1);
7925 break;
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);
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);
7944 return (0);
7947 return (rval);
7949 } /* emlxs_fcfi_vfi_offline_evt_action() */
7952 /*ARGSUSED*/
7953 static uint32_t
7954 emlxs_fcfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
7955 uint32_t evt, void *arg1)
7957 uint32_t rval = 0;
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);
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);
7977 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
7978 fcfp->flag |= EMLXS_FCFI_ONLINE_REQ;
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);
7987 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
7988 FCF_REASON_EVENT, evt, arg1);
7989 break;
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);
7998 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
7999 FCF_REASON_EVENT, evt, arg1);
8000 break;
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);
8008 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
8009 FCF_REASON_REENTER, evt, arg1);
8010 break;
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;
8020 return (rval);
8022 } /* emlxs_fcfi_online_evt_action() */
8025 /*ARGSUSED*/
8026 static uint32_t
8027 emlxs_fcfi_vfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8028 uint32_t evt, void *arg1)
8030 emlxs_hba_t *hba = HBA;
8031 uint32_t i;
8032 uint32_t rval = 0;
8033 VFIobj_t *vfip;
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);
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);
8050 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8051 return (rval);
8054 if (fcfp->vfi_online > 0) {
8055 /* Waking up out after being paused */
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;
8065 } else {
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;
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);
8084 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8085 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8087 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8088 return (rval);
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);
8097 rval = emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
8099 /* Wait for FCF_EVENT_VFI_ONLINE in return */
8101 return (rval);
8103 } /* emlxs_fcfi_vfi_online_action() */
8106 /*ARGSUSED*/
8107 static uint32_t
8108 emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8109 uint32_t evt, void *arg1)
8111 uint32_t rval = 0;
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);
8123 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8124 "fcfi_vfi_online_cmpl_action:%d. Going online.",
8125 fcfp->fcf_index);
8127 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
8128 FCF_REASON_EVENT, evt, arg1);
8130 return (rval);
8132 } /* emlxs_fcfi_vfi_online_cmpl_action() */
8135 /*ARGSUSED*/
8136 static uint32_t
8137 emlxs_fcfi_vfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8138 void *arg1)
8140 emlxs_hba_t *hba = HBA;
8141 VFIobj_t *vfip;
8142 uint32_t rval = 0;
8143 int32_t i;
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);
8153 return (1);
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);
8162 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED,
8163 FCF_REASON_EVENT, evt, arg1);
8165 return (rval);
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);
8174 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
8175 FCF_REASON_EVENT, evt, arg1);
8177 return (rval);
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];
8184 if ((vfip->fcfp != fcfp) ||
8185 (vfip->state == VFI_STATE_OFFLINE) ||
8186 (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
8187 continue;
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);
8195 (void) emlxs_vfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip);
8198 /* Wait for FCF_EVENT_VFI_OFFLINE in return */
8200 return (0);
8202 } /* emlxs_fcfi_vfi_offline_action() */
8205 /*ARGSUSED*/
8206 static uint32_t
8207 emlxs_fcfi_paused_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8208 void *arg1)
8210 emlxs_hba_t *hba = HBA;
8211 VFIobj_t *vfip;
8212 int32_t i;
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);
8222 return (1);
8225 fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
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];
8231 if ((vfip->state == VFI_STATE_OFFLINE) ||
8232 (vfip->state == VFI_STATE_PAUSED) ||
8233 (vfip->fcfp != fcfp)) {
8234 continue;
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);
8243 (void) emlxs_vfi_event(port, FCF_EVENT_VFI_PAUSE, vfip);
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);
8251 return (0);
8253 } /* emlxs_fcfi_paused_action() */
8256 /*ARGSUSED*/
8257 static uint32_t
8258 emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8259 uint32_t evt, void *arg1)
8261 uint32_t rval = 0;
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);
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);
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);
8290 return (rval);
8292 } /* emlxs_fcfi_vfi_offline_cmpl_action() */
8295 /*ARGSUSED*/
8296 static uint32_t
8297 emlxs_fcfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8298 void *arg1)
8300 uint32_t rval = 0;
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);
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);
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;
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;
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);
8342 /* Handle offline now */
8343 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8344 break;
8346 /* Transitional states */
8347 default:
8348 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8349 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8351 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8352 "fcfi_offline_evt_action:%d. "
8353 "Invalid state. <",
8354 fcfp->fcf_index);
8355 break;
8358 return (rval);
8360 } /* emlxs_fcfi_offline_evt_action() */
8363 /*ARGSUSED*/
8364 static uint32_t
8365 emlxs_fcfi_pause_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8366 void *arg1)
8368 uint32_t rval = 0;
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);
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);
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);
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;
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;
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);
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);
8422 /* Handle offline now */
8423 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8424 break;
8426 /* Transitional states */
8427 default:
8428 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8429 fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
8431 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8432 "fcfi_pause_evt_action:%d. "
8433 "Invalid state. <",
8434 fcfp->fcf_index);
8435 break;
8438 return (rval);
8440 } /* emlxs_fcfi_pause_evt_action() */
8443 /*ARGSUSED*/
8444 static uint32_t
8445 emlxs_fcfi_unreg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8446 uint32_t evt, void *arg1)
8448 uint32_t rval = 0;
8450 fcfp->attempts++;
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);
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);
8472 fcfp->flag &= ~EMLXS_FCFI_REG;
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);
8482 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
8483 FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8486 return (rval);
8488 } /* emlxs_fcfi_unreg_failed_action() */
8491 /*ARGSUSED*/
8492 static uint32_t
8493 emlxs_fcfi_reg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8494 void *arg1)
8496 uint32_t rval = 0;
8498 fcfp->attempts++;
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);
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);
8519 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8520 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
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);
8530 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
8531 FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8534 return (rval);
8536 } /* emlxs_fcfi_reg_failed_action() */
8539 /*ARGSUSED*/
8540 static uint32_t
8541 emlxs_fcfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
8543 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
8544 MAILBOX4 *mb4;
8545 FCFIobj_t *fcfp;
8547 fcfp = (FCFIobj_t *)mbq->context;
8548 mb4 = (MAILBOX4 *)mbq;
8550 mutex_enter(&EMLXS_FCF_LOCK);
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));
8558 mutex_exit(&EMLXS_FCF_LOCK);
8559 return (0);
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));
8568 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
8569 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
8571 mutex_exit(&EMLXS_FCF_LOCK);
8572 return (0);
8575 fcfp->FCFI = mb4->un.varRegFCFI.FCFI;
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);
8582 fcfp->flag |= EMLXS_FCFI_REG;
8584 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL,
8585 0, 0, 0);
8586 mutex_exit(&EMLXS_FCF_LOCK);
8587 return (0);
8589 } /* emlxs_fcfi_reg_mbcmpl() */
8592 /*ARGSUSED*/
8593 static uint32_t
8594 emlxs_fcfi_reg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8595 void *arg1)
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;
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);
8613 if (!(fcfp->flag & EMLXS_FCFI_FCFTAB)) {
8614 fcfp->flag |= EMLXS_FCFI_FCFTAB;
8615 fcftab->fcfi_online++;
8618 if (fcfp->prev_state != FCFI_STATE_REG_FAILED) {
8619 fcfp->attempts = 0;
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);
8628 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8629 return (rval);
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);
8638 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
8639 FCF_REASON_EVENT, evt, arg1);
8640 return (rval);
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);
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);
8652 return (rval);
8654 mb4 = (MAILBOX4*)mbq;
8655 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
8657 mbq->mbox_cmpl = emlxs_fcfi_reg_mbcmpl;
8658 mbq->context = (void *)fcfp;
8659 mbq->port = (void *)port;
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;
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;
8672 mb4->un.varRegFCFI.RQId1 = 0xffff;
8673 mb4->un.varRegFCFI.RQId2 = 0xffff;
8674 mb4->un.varRegFCFI.RQId3 = 0xffff;
8676 if (fcfp->flag & EMLXS_FCFI_VLAN_ID) {
8677 mb4->un.varRegFCFI.vv = 1;
8678 mb4->un.varRegFCFI.vlanTag = fcfp->vlan_id;
8681 /* Ignore the fcf record and force FPMA */
8682 mb4->un.varRegFCFI.mam = EMLXS_REG_FCFI_MAM_FPMA;
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);
8688 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
8689 FCF_REASON_SEND_FAILED, rval, arg1);
8691 return (rval);
8694 return (0);
8696 } /* emlxs_fcfi_reg_action() */
8699 /*ARGSUSED*/
8700 static uint32_t
8701 emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8702 void *arg1)
8704 uint32_t rval = 0;
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);
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);
8721 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8722 return (rval);
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);
8730 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
8731 FCF_REASON_EVENT, evt, arg1);
8733 return (rval);
8735 } /* emlxs_fcfi_reg_cmpl_action() */
8738 /*ARGSUSED*/
8739 static uint32_t
8740 emlxs_fcfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
8742 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
8743 MAILBOX4 *mb4;
8744 FCFIobj_t *fcfp;
8746 fcfp = (FCFIobj_t *)mbq->context;
8747 mb4 = (MAILBOX4 *)mbq;
8749 mutex_enter(&EMLXS_FCF_LOCK);
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));
8757 mutex_exit(&EMLXS_FCF_LOCK);
8758 return (0);
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));
8767 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
8768 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
8770 mutex_exit(&EMLXS_FCF_LOCK);
8771 return (0);
8774 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8775 "fcfi_unreg_mbcmpl:%d. Unreg complete. >",
8776 fcfp->fcf_index);
8778 fcfp->flag &= ~EMLXS_FCFI_REG;
8779 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL,
8780 0, 0, 0);
8782 mutex_exit(&EMLXS_FCF_LOCK);
8783 return (0);
8785 } /* emlxs_fcfi_unreg_mbcmpl() */
8788 /*ARGSUSED*/
8789 static uint32_t
8790 emlxs_fcfi_unreg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8791 void *arg1)
8793 emlxs_hba_t *hba = HBA;
8794 MAILBOX4 *mb4;
8795 MAILBOXQ *mbq;
8796 uint32_t rval = 0;
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);
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);
8814 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
8815 FCF_REASON_EVENT, evt, arg1);
8816 return (rval);
8819 if (fcfp->prev_state != FCFI_STATE_UNREG_FAILED) {
8820 fcfp->attempts = 0;
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);
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);
8833 mb4 = (MAILBOX4*)mbq;
8834 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
8836 mbq->mbox_cmpl = emlxs_fcfi_unreg_mbcmpl;
8837 mbq->context = (void *)fcfp;
8838 mbq->port = (void *)port;
8840 mb4->mbxCommand = MBX_UNREG_FCFI;
8841 mb4->mbxOwner = OWN_HOST;
8842 mb4->un.varUnRegFCFI.FCFI = fcfp->FCFI;
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);
8848 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
8849 FCF_REASON_SEND_FAILED, rval, arg1);
8851 return (rval);
8854 return (0);
8856 } /* emlxs_fcfi_unreg_action() */
8859 /*ARGSUSED*/
8860 static uint32_t
8861 emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8862 void *arg1)
8864 uint32_t rval = 0;
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);
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);
8883 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
8884 FCF_REASON_EVENT, evt, arg1);
8886 return (rval);
8888 } /* emlxs_fcfi_unreg_cmpl_action() */
8891 /*ARGSUSED*/
8892 static uint32_t
8893 emlxs_fcfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8894 void *arg1)
8896 emlxs_hba_t *hba = HBA;
8897 uint32_t rval = 0;
8898 VFIobj_t *vfip;
8899 uint32_t i;
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);
8911 fcfp->flag &= ~EMLXS_FCFI_ONLINE_REQ;
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);
8919 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8920 return (rval);
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;
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);
8936 (void) emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
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) {
8943 /* Perform VSAN Discovery (TBD) */
8944 /* For now we only need 1 VFI */
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);
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);
8960 /* Notify FCFTAB */
8961 rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_ONLINE, fcfp);
8963 return (rval);
8965 } /* emlxs_fcfi_online_action() */
8968 /*ARGSUSED*/
8969 static int
8970 emlxs_fcf_configured(emlxs_port_t *port, FCFIobj_t *fcfp)
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;
8982 /* Init the primary flag, we may set it later */
8983 fcfp->flag &= ~(EMLXS_FCFI_PRIMARY|EMLXS_FCFI_BOOT);
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 */
8992 return (0);
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 */
9000 return (0);
9003 /* For FIP mode, the FCF record must match Config Region 23 */
9005 entry_count = (hba->sli.sli4.cfgFCF.length * sizeof (uint32_t)) /
9006 sizeof (tlv_fcfconnectentry_t);
9007 valid_entry = 0;
9008 match_found = 0;
9010 for (i = 0; i < entry_count; i++) {
9012 if (!hba->sli.sli4.cfgFCF.entry[i].Valid) {
9013 continue;
9016 if (hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) {
9017 valid_entry = 1;
9019 if (bcmp((char *)fcfrec->fabric_name_identifier,
9020 hba->sli.sli4.cfgFCF.entry[i].FabricName, 8)) {
9021 match_found = 0;
9022 continue;
9025 match_found = 1;
9028 if (hba->sli.sli4.cfgFCF.entry[i].SwitchNameValid) {
9029 valid_entry = 1;
9031 if (bcmp((char *)fcfrec->switch_name_identifier,
9032 hba->sli.sli4.cfgFCF.entry[i].SwitchName, 8)) {
9033 match_found = 0;
9034 continue;
9037 match_found = 1;
9040 if (hba->sli.sli4.cfgFCF.entry[i].VLanValid) {
9041 valid_entry = 1;
9043 if (!(fcfp->flag & EMLXS_FCFI_VLAN_ID)) {
9044 match_found = 0;
9045 continue;
9048 VLanId = hba->sli.sli4.cfgFCF.entry[i].VLanId;
9049 j = VLanId / 8;
9050 k = 1 << (VLanId % 8);
9052 if (!(fcfrec->vlan_bitmap[j] & k)) {
9053 match_found = 0;
9054 continue;
9057 /* Assign requested vlan_id to this FCF */
9058 fcfp->vlan_id = VLanId;
9060 match_found = 1;
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;
9068 if (hba->sli.sli4.cfgFCF.entry[i].Boot) {
9069 fcfp->flag |= EMLXS_FCFI_BOOT;
9071 return (1);
9075 /* If no valid entries found, then allow any fabric */
9076 if (!valid_entry) {
9077 return (1);
9080 return (0);
9082 } /* emlxs_fcf_configured() */
9085 static void
9086 emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp, FCF_RECORD_t *fcf_rec,
9087 uint32_t event_tag)
9089 emlxs_hba_t *hba = HBA;
9090 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
9091 uint16_t i;
9093 bcopy((char *)fcf_rec, &fcfp->fcf_rec, sizeof (FCF_RECORD_t));
9094 fcfp->fcf_index = fcf_rec->fcf_index;
9096 /* Clear VLAN info */
9097 fcfp->vlan_id = 0;
9098 fcfp->flag &= ~EMLXS_FCFI_VLAN_ID;
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;
9110 if (fcf_rec->fcf_available) {
9111 fcfp->flag |= EMLXS_FCFI_AVAILABLE;
9112 } else {
9113 fcfp->flag &= ~EMLXS_FCFI_AVAILABLE;
9116 if (fcf_rec->fcf_valid && !fcf_rec->fcf_sol) {
9117 fcfp->flag |= EMLXS_FCFI_VALID;
9118 } else {
9119 fcfp->flag &= ~EMLXS_FCFI_VALID;
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;
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);
9136 fcfp->event_tag = event_tag;
9137 fcfp->generation = fcftab->generation;
9138 fcfp->flag |= EMLXS_FCFI_FRESH;
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);
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],
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],
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]);
9185 return;
9187 } /* emlxs_fcfi_update() */
9190 /* ************************************************************************** */
9191 /* VFI */
9192 /* ************************************************************************** */
9194 static char *
9195 emlxs_vfi_state_xlate(uint32_t state)
9197 static char buffer[32];
9198 uint32_t i;
9199 uint32_t count;
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);
9208 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
9209 return (buffer);
9211 } /* emlxs_vfi_state_xlate() */
9214 static uint32_t
9215 emlxs_vfi_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9216 void *arg1)
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;
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);
9248 events = VFI_ACTION_EVENTS;
9249 state = vfip->state;
9251 index += (state * events);
9252 func = (uint32_t(*) (emlxs_port_t *, VFIobj_t *, uint32_t, void *))
9253 emlxs_vfi_action_table[index];
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);
9262 return (1);
9265 rval = (func)(port, vfip, evt, arg1);
9267 return (rval);
9269 } /* emlxs_vfi_action() */
9272 static uint32_t
9273 emlxs_vfi_event(emlxs_port_t *port, uint32_t evt,
9274 void *arg1)
9276 VPIobj_t *vpip = NULL;
9277 VFIobj_t *vfip = NULL;
9278 uint32_t rval = 0;
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;
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);
9291 return (1);
9294 vfip = vpip->vfip;
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);
9301 return (1);
9303 break;
9305 case FCF_EVENT_VFI_ONLINE:
9306 case FCF_EVENT_VFI_OFFLINE:
9307 case FCF_EVENT_VFI_PAUSE:
9308 vfip = (VFIobj_t *)arg1;
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);
9315 return (1);
9317 break;
9319 default:
9320 return (1);
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);
9329 rval = emlxs_vfi_action(port, vfip, evt, arg1);
9331 return (rval);
9333 } /* emlxs_vfi_event() */
9336 /*ARGSUSED*/
9337 static uint32_t
9338 emlxs_vfi_state(emlxs_port_t *port, VFIobj_t *vfip, uint16_t state,
9339 uint16_t reason, uint32_t explain, void *arg1)
9341 uint32_t rval = 0;
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);
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);
9362 return (1);
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);
9396 vfip->prev_state = vfip->state;
9397 vfip->prev_reason = vfip->reason;
9398 vfip->state = state;
9399 vfip->reason = reason;
9401 rval = emlxs_vfi_action(port, vfip, FCF_EVENT_STATE_ENTER, arg1);
9403 return (rval);
9405 } /* emlxs_vfi_state() */
9408 /*ARGSUSED*/
9409 static uint32_t
9410 emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip,
9411 uint32_t evt, void *arg1)
9413 uint32_t rval = 0;
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);
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);
9435 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
9436 FCF_REASON_REENTER, evt, arg1);
9437 break;
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);
9447 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE_CMPL,
9448 FCF_REASON_EVENT, evt, arg1);
9449 break;
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);
9458 return (1);
9461 return (rval);
9463 } /* emlxs_vfi_vpi_online_evt_action() */
9466 /*ARGSUSED*/
9467 static uint32_t
9468 emlxs_vfi_offline_handler(emlxs_port_t *port, VFIobj_t *vfip, void *arg1)
9470 uint32_t rval = 0;
9472 if (!(vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
9473 return (0);
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);
9486 } else if (vfip->flag & EMLXS_VFI_REG) {
9487 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
9488 FCF_REASON_REQUESTED, 0, arg1);
9490 } else if (vfip->flag & EMLXS_VFI_INIT) {
9491 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
9492 FCF_REASON_REQUESTED, 0, arg1);
9494 } else {
9495 rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
9496 FCF_REASON_REQUESTED, 0, arg1);
9499 return (rval);
9501 } /* emlxs_vfi_offline_handler() */
9504 /*ARGSUSED*/
9505 static uint32_t
9506 emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip,
9507 uint32_t evt, void *arg1)
9509 uint32_t rval = 0;
9510 VPIobj_t *vpip;
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);
9523 /* Disconnect VPI object from VFI */
9524 vpip = (VPIobj_t *)arg1;
9525 vpip->vfip = NULL;
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);
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);
9547 break;
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;
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);
9562 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL,
9563 FCF_REASON_EVENT, evt, arg1);
9564 break;
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);
9572 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL,
9573 FCF_REASON_REENTER, evt, arg1);
9574 break;
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);
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);
9593 return (1);
9596 return (rval);
9598 } /* emlxs_vfi_vpi_offline_evt_action() */
9601 /*ARGSUSED*/
9602 static uint32_t
9603 emlxs_vfi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9604 void *arg1)
9606 emlxs_hba_t *hba = HBA;
9607 emlxs_port_t *vport;
9608 VPIobj_t *vpip;
9609 uint32_t rval = 0;
9610 uint32_t i;
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);
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);
9632 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
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);
9642 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
9643 FCF_REASON_EVENT, evt, arg1);
9644 break;
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);
9654 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
9655 FCF_REASON_EVENT, evt, arg1);
9656 break;
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;
9664 if (!(vport->flag & EMLXS_PORT_BOUND) ||
9665 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
9666 continue;
9669 if (vpip->vfip != vfip) {
9670 continue;
9673 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9674 "vfi_online_evt_action:%d. Onlining VPI:%d >",
9675 vfip->VFI,
9676 vpip->VPI);
9678 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE,
9679 vpip);
9681 break;
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);
9692 return (rval);
9694 } /* emlxs_vfi_online_evt_action() */
9697 /*ARGSUSED*/
9698 static uint32_t
9699 emlxs_vfi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9700 void *arg1)
9702 uint32_t rval = 0;
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);
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);
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;
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;
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);
9750 /* Handle offline now */
9751 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
9752 break;
9754 default:
9755 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9756 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
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;
9765 return (rval);
9767 } /* emlxs_vfi_offline_evt_action() */
9770 /*ARGSUSED*/
9771 static uint32_t
9772 emlxs_vfi_pause_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9773 void *arg1)
9775 uint32_t rval = 0;
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);
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);
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);
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;
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;
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);
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);
9837 /* Handle offline now */
9838 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
9839 break;
9841 default:
9842 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9843 vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
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;
9852 return (rval);
9854 } /* emlxs_vfi_pause_evt_action() */
9857 /*ARGSUSED*/
9858 static uint32_t
9859 emlxs_vfi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9860 void *arg1)
9862 uint32_t rval = 0;
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);
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);
9885 vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
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);
9893 return (0);
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);
9903 if (vfip->flag & EMLXS_VFI_FCFI) {
9904 vfip->flag &= ~EMLXS_VFI_FCFI;
9906 if (vfip->fcfp->vfi_online) {
9907 vfip->fcfp->vfi_online--;
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);
9918 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
9919 FCF_REASON_REQUESTED, 0, arg1);
9920 return (rval);
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);
9930 /* Notify FCFI */
9931 rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip);
9933 return (rval);
9935 } /* emlxs_vfi_offline_action() */
9938 /*ARGSUSED*/
9939 static uint32_t
9940 emlxs_vfi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
9942 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
9943 VFIobj_t *vfip;
9944 MAILBOX4 *mb4;
9946 vfip = (VFIobj_t *)mbq->context;
9947 mb4 = (MAILBOX4 *)mbq;
9949 mutex_enter(&EMLXS_FCF_LOCK);
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));
9957 mutex_exit(&EMLXS_FCF_LOCK);
9958 return (0);
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));
9967 (void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED,
9968 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
9970 mutex_exit(&EMLXS_FCF_LOCK);
9971 return (0);
9974 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9975 "vfi_init_mbcmpl:%d. Init complete. >",
9976 vfip->VFI,
9977 mb4->mbxStatus);
9979 vfip->flag |= EMLXS_VFI_INIT;
9980 (void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL, 0, 0, 0);
9982 mutex_exit(&EMLXS_FCF_LOCK);
9983 return (0);
9985 } /* emlxs_vfi_init_mbcmpl() */
9988 /*ARGSUSED*/
9989 static uint32_t
9990 emlxs_vfi_init_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9991 void *arg1)
9993 emlxs_hba_t *hba = HBA;
9994 MAILBOXQ *mbq;
9995 MAILBOX4 *mb4;
9996 uint32_t rval = 0;
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);
10008 if (!(vfip->flag & EMLXS_VFI_FCFI)) {
10009 vfip->flag |= EMLXS_VFI_FCFI;
10010 vfip->fcfp->vfi_online++;
10013 if (vfip->prev_state != VFI_STATE_INIT_FAILED) {
10014 vfip->attempts = 0;
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);
10023 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10024 return (rval);
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);
10033 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
10034 FCF_REASON_EVENT, evt, arg1);
10035 return (rval);
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);
10044 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
10045 FCF_REASON_EVENT, evt, arg1);
10046 return (rval);
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);
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);
10060 mb4 = (MAILBOX4*)mbq;
10061 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10063 mbq->nonembed = NULL;
10064 mbq->mbox_cmpl = emlxs_vfi_init_mbcmpl;
10065 mbq->context = (void *)vfip;
10066 mbq->port = (void *)port;
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;
10073 /* ??? This function is untested and incomplete */
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);
10079 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED,
10080 FCF_REASON_SEND_FAILED, rval, arg1);
10082 return (rval);
10085 return (0);
10087 } /* emlxs_vfi_init_action() */
10090 /*ARGSUSED*/
10091 static uint32_t
10092 emlxs_vfi_init_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10093 void *arg1)
10095 uint32_t rval = 0;
10097 vfip->attempts++;
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);
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);
10118 vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT);
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);
10130 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
10131 FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10134 return (rval);
10136 } /* emlxs_vfi_init_failed_action() */
10139 /*ARGSUSED*/
10140 static uint32_t
10141 emlxs_vfi_init_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10142 void *arg1)
10144 uint32_t rval = 0;
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);
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);
10161 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
10162 FCF_REASON_EVENT, evt, arg1);
10164 return (rval);
10166 } /* emlxs_vfi_init_cmpl_action() */
10169 /*ARGSUSED*/
10170 static uint32_t
10171 emlxs_vfi_vpi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10172 void *arg1)
10174 emlxs_hba_t *hba = HBA;
10175 uint32_t rval = 0;
10176 uint32_t i;
10177 emlxs_port_t *vport;
10178 VPIobj_t *vpip;
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);
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);
10195 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10196 return (rval);
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);
10208 if (vfip->vpi_online) {
10209 /* Waking up after being paused */
10211 /* Find first VPI of this VFI */
10212 for (i = 0; i <= hba->vpi_max; i++) {
10213 vport = &VPORT(i);
10214 vpip = vport->vpip;
10216 if (!(vport->flag & EMLXS_PORT_BOUND) ||
10217 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
10218 continue;
10221 if (vpip->vfip == vfip) {
10222 break;
10226 } else {
10228 /* Find first available VPI */
10229 for (i = 0; i <= hba->vpi_max; i++) {
10230 vport = &VPORT(i);
10231 vpip = vport->vpip;
10233 if (!(vport->flag & EMLXS_PORT_BOUND) ||
10234 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
10235 continue;
10238 if (vpip->vfip == NULL) {
10239 vpip->vfip = vfip;
10240 break;
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);
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);
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);
10267 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
10269 /* Wait for FCF_EVENT_VPI_ONLINE in return */
10271 return (rval);
10273 } /* emlxs_vfi_vpi_online_action() */
10276 /*ARGSUSED*/
10277 static uint32_t
10278 emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip,
10279 uint32_t evt, void *arg1)
10281 uint32_t rval = 0;
10282 VPIobj_t *vpip = (VPIobj_t *)arg1;
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);
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);
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);
10315 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
10316 FCF_REASON_EVENT, evt, arg1);
10319 return (rval);
10321 } /* emlxs_vfi_vpi_online_cmpl_action() */
10324 /*ARGSUSED*/
10325 static uint32_t
10326 emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip,
10327 uint32_t evt, void *arg1)
10329 uint32_t rval = 0;
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);
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);
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);
10358 return (rval);
10360 } /* emlxs_vfi_vpi_offline_cmpl_action() */
10363 /*ARGSUSED*/
10364 static uint32_t
10365 emlxs_vfi_vpi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10366 void *arg1)
10368 emlxs_hba_t *hba = HBA;
10369 emlxs_port_t *vport;
10370 uint32_t rval = 0;
10371 int32_t i;
10372 VPIobj_t *vpip;
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);
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);
10390 rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED,
10391 FCF_REASON_EVENT, evt, arg1);
10393 return (rval);
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);
10403 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
10404 FCF_REASON_EVENT, evt, arg1);
10406 return (rval);
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;
10414 if ((vpip->state == VPI_STATE_OFFLINE) ||
10415 (vpip->vfip != vfip)) {
10416 continue;
10419 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10420 "vfi_vpi_offline_action:%d. Offlining VPI:%d. >",
10421 vfip->VFI,
10422 vpip->VPI);
10424 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_OFFLINE, vpip);
10427 /* Wait for FCF_EVENT_VPI_OFFLINE in return */
10429 return (0);
10431 } /* emlxs_vfi_vpi_offline_action() */
10434 /*ARGSUSED*/
10435 static uint32_t
10436 emlxs_vfi_paused_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10437 void *arg1)
10439 emlxs_hba_t *hba = HBA;
10440 emlxs_port_t *vport;
10441 int32_t i;
10442 VPIobj_t *vpip;
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);
10454 vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
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;
10461 if ((vpip->state == VPI_STATE_PAUSED) ||
10462 (vpip->vfip != vfip)) {
10463 continue;
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);
10472 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip);
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);
10480 return (0);
10482 } /* emlxs_vfi_paused_action() */
10485 /*ARGSUSED*/
10486 static uint32_t
10487 emlxs_vfi_unreg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10488 void *arg1)
10490 uint32_t rval = 0;
10492 vfip->attempts++;
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);
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);
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);
10521 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
10522 FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10525 return (rval);
10527 } /* emlxs_vfi_unreg_failed_action() */
10530 /*ARGSUSED*/
10531 static uint32_t
10532 emlxs_vfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
10534 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
10535 MAILBOX4 *mb4;
10536 VFIobj_t *vfip;
10538 vfip = (VFIobj_t *)mbq->context;
10539 mb4 = (MAILBOX4 *)mbq;
10541 mutex_enter(&EMLXS_FCF_LOCK);
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));
10549 mutex_exit(&EMLXS_FCF_LOCK);
10550 return (0);
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));
10559 (void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
10560 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
10562 mutex_exit(&EMLXS_FCF_LOCK);
10563 return (0);
10566 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10567 "vfi_unreg_mbcmpl:%d. Unreg complete. >",
10568 vfip->VFI);
10570 vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT);
10571 (void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL,
10572 0, 0, 0);
10574 mutex_exit(&EMLXS_FCF_LOCK);
10575 return (0);
10577 } /* emlxs_vfi_unreg_mbcmpl() */
10580 /*ARGSUSED*/
10581 static uint32_t
10582 emlxs_vfi_unreg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10583 void *arg1)
10585 emlxs_hba_t *hba = HBA;
10586 MAILBOX4 *mb4;
10587 MAILBOXQ *mbq;
10588 uint32_t rval = 0;
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);
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);
10605 rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
10606 FCF_REASON_EVENT, evt, arg1);
10607 return (rval);
10610 if (vfip->prev_state != VFI_STATE_UNREG_FAILED) {
10611 vfip->attempts = 0;
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);
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);
10623 return (rval);
10625 mb4 = (MAILBOX4*)mbq;
10626 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10628 mbq->nonembed = NULL;
10629 mbq->mbox_cmpl = emlxs_vfi_unreg_mbcmpl;
10630 mbq->context = (void *)vfip;
10631 mbq->port = (void *)port;
10633 mb4->un.varUnRegVFI4.vfi = vfip->VFI;
10634 mb4->mbxCommand = MBX_UNREG_VFI;
10635 mb4->mbxOwner = OWN_HOST;
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);
10641 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
10642 FCF_REASON_SEND_FAILED, rval, arg1);
10644 return (rval);
10647 return (0);
10649 } /* emlxs_vfi_unreg_action() */
10652 /*ARGSUSED*/
10653 static uint32_t
10654 emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10655 void *arg1)
10657 uint32_t rval = 0;
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);
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);
10674 rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
10675 FCF_REASON_EVENT, evt, arg1);
10677 return (rval);
10679 } /* emlxs_vfi_unreg_cmpl_action() */
10682 /*ARGSUSED*/
10683 static uint32_t
10684 emlxs_vfi_reg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10685 void *arg1)
10687 uint32_t rval = 0;
10689 vfip->attempts++;
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);
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);
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);
10720 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG,
10721 FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10724 return (rval);
10726 } /* emlxs_vfi_reg_failed_action() */
10729 /*ARGSUSED*/
10730 static uint32_t
10731 emlxs_vfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
10733 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
10734 MAILBOX4 *mb4;
10735 VFIobj_t *vfip;
10736 MATCHMAP *mp;
10738 vfip = (VFIobj_t *)mbq->context;
10739 mb4 = (MAILBOX4 *)mbq;
10741 mutex_enter(&EMLXS_FCF_LOCK);
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));
10749 mutex_exit(&EMLXS_FCF_LOCK);
10750 return (0);
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));
10759 (void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10760 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
10762 mutex_exit(&EMLXS_FCF_LOCK);
10763 return (0);
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));
10771 if (vfip->flogi_vpip) {
10772 if (mb4->un.varRegVFI4.vp == 1) {
10773 vfip->flogi_vpip->flag |= EMLXS_VPI_REG;
10775 vfip->flogi_vpip = NULL;
10778 vfip->flag |= EMLXS_VFI_REG;
10780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10781 "vfi_reg_mbcmpl:%d. Reg complete. >",
10782 vfip->VFI);
10784 (void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL, 0, 0, 0);
10786 mutex_exit(&EMLXS_FCF_LOCK);
10787 return (0);
10789 } /* emlxs_vfi_reg_mbcmpl() */
10792 /*ARGSUSED*/
10793 static uint32_t
10794 emlxs_vfi_reg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10795 void *arg1)
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;
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);
10817 if (vfip->prev_state != VFI_STATE_REG_FAILED) {
10818 vfip->attempts = 0;
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);
10827 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10828 return (rval);
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);
10837 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10838 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10840 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10841 return (rval);
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);
10851 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
10852 FCF_REASON_EVENT, evt, arg1);
10853 return (rval);
10856 /* Get the flogi_vpip's fabric_rpip's service parameters */
10857 flogi_sparam = &vfip->flogi_vpip->fabric_rpip->sparam;
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);
10866 ratov = (LE_SWAP32(flogi_sparam->cmn.w2.r_a_tov) + 999) / 1000;
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);
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);
10888 return (rval);
10890 mb4 = (MAILBOX4*)mbq;
10891 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10893 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
10894 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10896 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10897 FCF_REASON_NO_BUFFER, 0, arg1);
10899 return (1);
10902 mbq->bp = (void *)mp;
10903 mbq->nonembed = NULL;
10905 mbq->mbox_cmpl = emlxs_vfi_reg_mbcmpl;
10906 mbq->context = (void *)vfip;
10907 mbq->port = (void *)port;
10909 mb4->mbxCommand = MBX_REG_VFI;
10910 mb4->mbxOwner = OWN_HOST;
10912 mb4->un.varRegVFI4.vfi = vfip->VFI;
10913 mb4->un.varRegVFI4.upd = (vfip->flag & EMLXS_VFI_REG)? 1:0;
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;
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));
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);
10941 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10942 FCF_REASON_SEND_FAILED, rval, arg1);
10944 return (rval);
10947 return (0);
10949 } /* emlxs_vfi_reg_action() */
10952 /*ARGSUSED*/
10953 static uint32_t
10954 emlxs_vfi_reg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10955 void *arg1)
10957 uint32_t rval = 0;
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);
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);
10975 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10976 return (rval);
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);
10984 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
10985 FCF_REASON_EVENT, evt, arg1);
10987 return (rval);
10989 } /* emlxs_vfi_reg_cmpl_action() */
10992 /*ARGSUSED*/
10993 static uint32_t
10994 emlxs_vfi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10995 void *arg1)
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;
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);
11013 vfip->flag &= ~EMLXS_VFI_ONLINE_REQ;
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);
11021 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
11022 return (rval);
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);
11030 /* This will complete the FLOGI/FDISC back to Leadville */
11031 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE,
11032 vpip->fabric_rpip);
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;
11038 /* Online remaining VPI's */
11039 for (i = 0; i <= hba->vpi_max; i++) {
11040 vport = &VPORT(i);
11041 vpip = vport->vpip;
11043 if (!(vport->flag & EMLXS_PORT_BOUND) ||
11044 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
11045 continue;
11048 if ((vpip->state == VPI_STATE_ONLINE) ||
11049 (vpip->flag & EMLXS_VPI_ONLINE_REQ)) {
11050 continue;
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);
11061 vpip->vfip = vfip;
11062 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE, vpip);
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);
11073 /* Notify FCFI */
11074 rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
11076 return (rval);
11078 } /* emlxs_vfi_online_action() */
11081 /* ************************************************************************** */
11082 /* VPI */
11083 /* ************************************************************************** */
11085 static char *
11086 emlxs_vpi_state_xlate(uint32_t state)
11088 static char buffer[32];
11089 uint32_t i;
11090 uint32_t count;
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);
11099 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
11100 return (buffer);
11102 } /* emlxs_vpi_state_xlate() */
11105 static uint32_t
11106 emlxs_vpi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11107 void *arg1)
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;
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);
11142 events = VPI_ACTION_EVENTS;
11143 state = vpip->state;
11145 index += (state * events);
11146 func = (uint32_t(*) (emlxs_port_t *, VPIobj_t *, uint32_t, void *))
11147 emlxs_vpi_action_table[index];
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);
11156 return (1);
11159 rval = (func)(port, vpip, evt, arg1);
11161 return (rval);
11163 } /* emlxs_vpi_action() */
11166 static uint32_t
11167 emlxs_vpi_event(emlxs_port_t *port, uint32_t evt,
11168 void *arg1)
11170 VPIobj_t *vpip = NULL;
11171 RPIobj_t *rpip;
11172 uint32_t rval = 0;
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;
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);
11186 return (1);
11189 vpip = rpip->vpip;
11190 break;
11192 case FCF_EVENT_VPI_ONLINE:
11193 case FCF_EVENT_VPI_PAUSE:
11194 case FCF_EVENT_VPI_OFFLINE:
11195 vpip = (VPIobj_t *)arg1;
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);
11202 return (1);
11205 break;
11207 default:
11208 return (1);
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);
11217 rval = emlxs_vpi_action(port, vpip, evt, arg1);
11219 return (rval);
11221 } /* emlxs_vpi_event() */
11224 /*ARGSUSED*/
11225 static uint32_t
11226 emlxs_vpi_state(emlxs_port_t *port, VPIobj_t *vpip, uint16_t state,
11227 uint16_t reason, uint32_t explain, void *arg1)
11229 uint32_t rval = 0;
11231 if (state >= VPI_ACTION_STATES) {
11232 return (1);
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);
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);
11278 vpip->prev_state = vpip->state;
11279 vpip->prev_reason = vpip->reason;
11280 vpip->state = state;
11281 vpip->reason = reason;
11283 rval = emlxs_vpi_action(port, vpip, FCF_EVENT_STATE_ENTER, arg1);
11285 return (rval);
11287 } /* emlxs_vpi_state() */
11290 extern uint32_t
11291 emlxs_vpi_port_bind_notify(emlxs_port_t *port)
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;
11303 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
11304 return (1);
11307 if (hba->state < FC_LINK_UP) {
11308 if (port->vpi == 0) {
11309 (void) emlxs_reset_link(hba, 1, 0);
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;
11320 return (0);
11323 mutex_enter(&EMLXS_FCF_LOCK);
11325 if (vpip->vfip) {
11326 vfip = vpip->vfip;
11327 fcfp = vfip->fcfp;
11328 goto done;
11331 /* We need to select a VFI for this VPI */
11333 /* First find a selected Fabric */
11334 fcfp = NULL;
11335 for (i = 0; i < fcftab->fcfi_count; i++) {
11336 fcfp1 = fcftab->fcfi[i];
11338 if (fcfp1->flag & EMLXS_FCFI_SELECTED) {
11339 fcfp = fcfp1;
11340 break;
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));
11351 mutex_exit(&EMLXS_FCF_LOCK);
11352 return (0);
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;
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);
11373 mutex_exit(&EMLXS_FCF_LOCK);
11374 return (0);
11377 vpip->vfip = vfip;
11378 done:
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);
11388 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
11390 mutex_exit(&EMLXS_FCF_LOCK);
11392 return (rval);
11394 } /* emlxs_vpi_port_bind_notify() */
11397 extern uint32_t
11398 emlxs_vpi_port_unbind_notify(emlxs_port_t *port, uint32_t wait)
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;
11407 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
11408 return (1);
11411 if (!(hba->sli.sli4.flag & EMLXS_SLI4_FCF_INIT)) {
11412 return (0);
11415 mutex_enter(&EMLXS_FCF_LOCK);
11417 if (vpip->state == VPI_STATE_OFFLINE) {
11418 mutex_exit(&EMLXS_FCF_LOCK);
11419 return (0);
11423 * Set flag to indicate that emlxs_vpi_port_unbind_notify
11424 * has been called
11426 vpip->flag |= EMLXS_VPI_PORT_UNBIND;
11428 vfip = vpip->vfip;
11429 fcfp = vfip->fcfp;
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);
11440 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
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;
11450 mutex_exit(&EMLXS_FCF_LOCK);
11451 BUSYWAIT_MS(1000);
11452 mutex_enter(&EMLXS_FCF_LOCK);
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);
11467 vpip->flag &= ~EMLXS_VPI_PORT_UNBIND;
11469 mutex_exit(&EMLXS_FCF_LOCK);
11471 return (rval);
11473 } /* emlxs_vpi_port_unbind_notify() */
11476 /*ARGSUSED*/
11477 static uint32_t
11478 emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
11479 uint32_t evt, void *arg1)
11481 uint32_t rval = 0;
11482 RPIobj_t *rpip = (RPIobj_t *)arg1;
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);
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);
11505 rval = 0;
11506 break;
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);
11516 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
11517 FCF_REASON_REENTER, evt, arg1);
11518 break;
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);
11528 rval = 0;
11529 break;
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);
11539 rval = 0;
11540 break;
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);
11551 rval = 1;
11552 break;
11555 return (rval);
11557 } /* emlxs_vpi_rpi_offline_evt_action() */
11560 /*ARGSUSED*/
11561 static uint32_t
11562 emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
11563 uint32_t evt, void *arg1)
11565 uint32_t rval = 0;
11566 RPIobj_t *rpip = (RPIobj_t *)arg1;
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);
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);
11589 rval = 0;
11590 break;
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);
11600 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
11601 FCF_REASON_REENTER, 0, 0);
11602 break;
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);
11612 rval = 0;
11613 break;
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);
11624 rval = 1;
11625 break;
11628 return (rval);
11630 } /* emlxs_vpi_rpi_pause_evt_action() */
11633 /*ARGSUSED*/
11634 static uint32_t
11635 emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
11636 uint32_t evt, void *arg1)
11638 RPIobj_t *rpip = (RPIobj_t *)arg1;
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);
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);
11657 return (0);
11659 } /* emlxs_vpi_rpi_online_evt_action() */
11662 /*ARGSUSED*/
11663 static uint32_t
11664 emlxs_vpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11665 void *arg1)
11667 uint32_t rval = 0;
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);
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);
11689 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11690 vpip->flag |= EMLXS_VPI_ONLINE_REQ;
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);
11699 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
11700 FCF_REASON_EVENT, evt, arg1);
11701 break;
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);
11710 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
11711 FCF_REASON_EVENT, evt, arg1);
11712 break;
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);
11722 return (rval);
11724 } /* emlxs_vpi_online_evt_action() */
11727 /*ARGSUSED*/
11728 static uint32_t
11729 emlxs_vpi_offline_handler(emlxs_port_t *port, VPIobj_t *vpip, void *arg1)
11731 uint32_t rval = 0;
11733 if (!(vpip->flag & EMLXS_VPI_OFFLINE_REQ)) {
11734 return (0);
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);
11741 } else if (vpip->flag & EMLXS_VPI_LOGI) {
11742 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
11743 FCF_REASON_REQUESTED, 0, arg1);
11745 } else if (vpip->flag & EMLXS_VPI_REG) {
11746 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
11747 FCF_REASON_REQUESTED, 0, arg1);
11749 } else if (vpip->flag & EMLXS_VPI_INIT) {
11750 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
11751 FCF_REASON_REQUESTED, 0, arg1);
11753 } else {
11754 rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
11755 FCF_REASON_REQUESTED, 0, arg1);
11758 return (rval);
11760 } /* emlxs_vpi_offline_handler() */
11763 /*ARGSUSED*/
11764 static uint32_t
11765 emlxs_vpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11766 void *arg1)
11768 uint32_t rval = 0;
11769 uint32_t pause_req;
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);
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);
11792 pause_req = vpip->flag & EMLXS_VPI_PAUSE_REQ;
11794 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11795 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
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);
11805 vpip->flag |= EMLXS_VPI_PORT_ONLINE;
11807 rval = emlxs_vpi_state(port, vpip,
11808 VPI_STATE_PORT_OFFLINE, FCF_REASON_REENTER, evt,
11809 arg1);
11811 break;
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);
11819 /* Handle offline now */
11820 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11821 break;
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);
11830 vpip->flag |= EMLXS_VPI_PORT_ONLINE;
11832 rval = emlxs_vpi_state(port, vpip,
11833 VPI_STATE_PORT_OFFLINE, FCF_REASON_EVENT, evt,
11834 arg1);
11836 break;
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);
11844 /* Handle offline now */
11845 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11846 break;
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);
11860 /* Handle offline now */
11861 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11862 break;
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;
11873 return (rval);
11875 } /* emlxs_vpi_offline_evt_action() */
11878 /*ARGSUSED*/
11879 static uint32_t
11880 emlxs_vpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11881 void *arg1)
11883 emlxs_hba_t *hba = HBA;
11884 uint32_t rval = 0;
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);
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);
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);
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);
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;
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;
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);
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);
11952 /* Handle offline now */
11953 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11954 break;
11956 /* Transitional states */
11957 default:
11958 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11959 vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
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;
11968 return (rval);
11970 } /* emlxs_vpi_pause_evt_action() */
11973 /* ARGSUSED */
11974 static void
11975 emlxs_deferred_cmpl_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
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;
11985 mbxStatus = (status)? MBX_FAILURE:MBX_SUCCESS;
11987 port = cmpl->port;
11988 sbp = (emlxs_buf_t *)cmpl->arg1;
11989 ubp = (fc_unsol_buf_t *)cmpl->arg2;
11990 iocbq = (IOCBQ *)cmpl->arg3;
11992 kmem_free(cmpl, sizeof (emlxs_deferred_cmpl_t));
11994 emlxs_mb_deferred_cmpl(port, mbxStatus, sbp, ubp, iocbq);
11996 return;
11998 } /* emlxs_deferred_cmpl_thread() */
12003 /* ARGSUSED */
12004 static void
12005 emlxs_port_offline_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
12007 emlxs_port_t *port = (emlxs_port_t *)arg1;
12008 uint32_t scope = (uint32_t)((unsigned long)arg2);
12010 (void) emlxs_port_offline(port, scope);
12011 return;
12013 } /* emlxs_port_offline_thread() */
12016 /* ARGSUSED */
12017 static void
12018 emlxs_port_online_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
12020 emlxs_port_t *port = (emlxs_port_t *)arg1;
12022 (void) emlxs_port_online(port);
12023 return;
12025 } /* emlxs_port_online_thread() */
12028 /*ARGSUSED*/
12029 static void
12030 emlxs_vpi_logo_handler(emlxs_port_t *port, VPIobj_t *vpip)
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;
12041 if (vpip->vfip->logi_count) {
12042 vpip->vfip->logi_count--;
12044 if (vpip == vpip->vfip->flogi_vpip) {
12045 vpip->vfip->flogi_vpip = NULL;
12048 } /* emlxs_vpi_logo_handler() */
12051 /*ARGSUSED*/
12052 static uint32_t
12053 emlxs_vpi_port_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12054 void *arg1)
12056 emlxs_hba_t *hba = HBA;
12057 uint32_t rval = 0;
12058 uint32_t scope;
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);
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);
12076 vpip->flag &= ~(EMLXS_VPI_PORT_ONLINE|EMLXS_VPI_PORT_ENABLED);
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 */
12085 emlxs_thread_spawn(hba, emlxs_port_offline_thread,
12086 (void *)vpip->port, (void *)((unsigned long)scope));
12088 if (vpip->flag & EMLXS_VPI_LOGI) {
12089 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
12090 FCF_REASON_EVENT, evt, arg1);
12092 return (rval);
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);
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);
12113 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
12114 vpip->fabric_rpip);
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);
12122 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED,
12123 FCF_REASON_EVENT, evt, arg1);
12125 return (rval);
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);
12135 return (0);
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);
12144 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
12145 vpip->fabric_rpip);
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);
12154 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
12155 FCF_REASON_EVENT, evt, arg1);
12157 return (rval);
12159 } /* emlxs_vpi_port_offline_action() */
12162 /*ARGSUSED*/
12163 static uint32_t
12164 emlxs_vpi_paused_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12165 void *arg1)
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);
12177 vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
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);
12184 return (0);
12186 } /* emlxs_vpi_paused_action() */
12189 /*ARGSUSED*/
12190 static uint32_t
12191 emlxs_vpi_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12192 void *arg1)
12194 uint32_t rval = 0;
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);
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);
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);
12223 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
12224 vpip->fabric_rpip);
12227 vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
12229 if (vpip->flag & EMLXS_VPI_VFI) {
12230 vpip->flag &= ~EMLXS_VPI_VFI;
12232 if (vpip->vfip->vpi_online) {
12233 vpip->vfip->vpi_online--;
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);
12244 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
12245 FCF_REASON_REQUESTED, 0, arg1);
12246 return (rval);
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);
12256 /* Notify VFI */
12257 rval = emlxs_vfi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
12259 return (rval);
12261 } /* emlxs_vpi_offline_action() */
12264 /*ARGSUSED*/
12265 static uint32_t
12266 emlxs_vpi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
12268 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
12269 VPIobj_t *vpip;
12270 MAILBOX4 *mb4;
12272 vpip = (VPIobj_t *)mbq->context;
12273 mb4 = (MAILBOX4 *)mbq;
12275 mutex_enter(&EMLXS_FCF_LOCK);
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));
12283 mutex_exit(&EMLXS_FCF_LOCK);
12284 return (0);
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));
12293 (void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED,
12294 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
12296 mutex_exit(&EMLXS_FCF_LOCK);
12297 return (0);
12300 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12301 "vpi_init_mbcmpl:%d. Init complete. >",
12302 vpip->VPI,
12303 mb4->mbxStatus);
12305 vpip->flag |= EMLXS_VPI_INIT;
12306 (void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL,
12307 0, 0, 0);
12309 mutex_exit(&EMLXS_FCF_LOCK);
12310 return (0);
12312 } /* emlxs_vpi_init_mbcmpl() */
12315 /*ARGSUSED*/
12316 static uint32_t
12317 emlxs_vpi_init_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12318 void *arg1)
12320 emlxs_hba_t *hba = HBA;
12321 MAILBOXQ *mbq;
12322 MAILBOX4 *mb4;
12323 uint32_t rval = 0;
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);
12335 if (vpip->prev_state != VPI_STATE_INIT_FAILED) {
12336 vpip->attempts = 0;
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);
12345 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12346 return (rval);
12349 if (!(vpip->flag & EMLXS_VPI_VFI)) {
12350 vpip->flag |= EMLXS_VPI_VFI;
12351 vpip->vfip->vpi_online++;
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);
12360 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
12361 FCF_REASON_EVENT, evt, arg1);
12362 return (rval);
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);
12371 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
12372 FCF_REASON_EVENT, evt, arg1);
12373 return (rval);
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);
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);
12387 mb4 = (MAILBOX4*)mbq;
12388 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
12390 mbq->nonembed = NULL;
12391 mbq->mbox_cmpl = emlxs_vpi_init_mbcmpl;
12392 mbq->context = (void *)vpip;
12393 mbq->port = (void *)port;
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;
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);
12404 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED,
12405 FCF_REASON_SEND_FAILED, rval, arg1);
12407 return (rval);
12410 return (0);
12412 } /* emlxs_vpi_init_action() */
12415 /*ARGSUSED*/
12416 static uint32_t
12417 emlxs_vpi_init_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12418 void *arg1)
12420 uint32_t rval = 0;
12422 vpip->attempts++;
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);
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);
12443 vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
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);
12455 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
12456 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
12459 return (rval);
12461 } /* emlxs_vpi_init_failed_action() */
12464 /*ARGSUSED*/
12465 static uint32_t
12466 emlxs_vpi_init_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12467 void *arg1)
12469 uint32_t rval = 0;
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);
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);
12486 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
12487 FCF_REASON_EVENT, evt, arg1);
12488 return (rval);
12490 } /* emlxs_vpi_init_cmpl_action() */
12493 /*ARGSUSED*/
12494 static uint32_t
12495 emlxs_vpi_port_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12496 void *arg1)
12498 emlxs_hba_t *hba = HBA;
12499 emlxs_config_t *cfg = &CFG;
12500 uint32_t rval = 0;
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);
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);
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);
12523 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12524 return (rval);
12527 /* Initialize the Fabric RPI */
12528 if (vpip->fabric_rpip->state == RPI_STATE_FREE) {
12529 emlxs_rpi_alloc_fabric_rpi(vpip->port);
12532 /* Notify ULP */
12533 vpip->flag |= EMLXS_VPI_PORT_ONLINE;
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);
12541 if (hba->topology != TOPOLOGY_LOOP) {
12542 port->did = 1;
12545 vpip->vfip->flogi_vpip = vpip;
12547 bcopy((void *)&vpip->port->sparam,
12548 (void *)&vpip->fabric_rpip->sparam,
12549 sizeof (SERV_PARM));
12551 /* Update the VPI Fabric RPI */
12552 vpip->fabric_rpip->sparam.cmn.w2.r_a_tov =
12553 LE_SWAP32((FF_DEF_RATOV * 1000));
12555 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
12556 FCF_REASON_EVENT, evt, arg1);
12558 return (rval);
12561 if ((hba->topology == TOPOLOGY_LOOP) && ! (port->did)) {
12562 port->did = port->granted_alpa;
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);
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);
12580 /* Wait for emlxs_vpi_logi_notify() */
12582 return (0);
12584 } /* emlxs_vpi_port_online_action() */
12587 extern uint32_t
12588 emlxs_vpi_logi_notify(emlxs_port_t *port, emlxs_buf_t *sbp)
12590 VPIobj_t *vpip = port->vpip;
12591 emlxs_hba_t *hba = HBA;
12592 uint32_t rval = 0;
12594 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
12595 return (1);
12598 mutex_enter(&EMLXS_FCF_LOCK);
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));
12606 mutex_exit(&EMLXS_FCF_LOCK);
12608 return (1);
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));
12618 mutex_exit(&EMLXS_FCF_LOCK);
12620 return (1);
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));
12629 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI,
12630 0, 0, sbp);
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);
12640 mutex_exit(&EMLXS_FCF_LOCK);
12642 return (rval);
12644 } /* emlxs_vpi_logi_notify() */
12647 static uint32_t
12648 emlxs_vpi_logi_cmpl_notify(emlxs_port_t *port, RPIobj_t *rpip)
12650 emlxs_hba_t *hba = HBA;
12651 VPIobj_t *vpip = port->vpip;
12652 uint32_t rval = 0;
12654 /* EMLXS_FCF_LOCK must be held when calling this routine */
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);
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));
12673 /* Complete the FLOGI/FDISC now */
12674 if (rpip->cmpl) {
12675 emlxs_rpi_deferred_cmpl(port, rpip, 0);
12678 /* Wait for P2P PLOGI completion to continue */
12679 return (0);
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);
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));
12695 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_CMPL,
12696 0, 0, 0);
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);
12706 return (rval);
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));
12717 if (rpip->cmpl) {
12718 emlxs_rpi_deferred_cmpl(port, rpip, 0);
12721 /* Wait for P2P PLOGI completion to continue */
12722 return (0);
12725 vpip->p2p_rpip = rpip;
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));
12733 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_CMPL,
12734 0, 0, 0);
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);
12744 return (rval);
12747 return (1);
12749 } /* emlxs_vpi_logi_cmpl_notify() */
12752 extern uint32_t
12753 emlxs_vpi_logi_failed_notify(emlxs_port_t *port, emlxs_buf_t *sbp)
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;
12761 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
12762 return (1);
12765 mutex_enter(&EMLXS_FCF_LOCK);
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));
12774 /* Fabric logo is implied */
12775 emlxs_vpi_logo_handler(port, vpip);
12777 mutex_exit(&EMLXS_FCF_LOCK);
12779 return (1);
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));
12788 /* For safety */
12789 if (rpip->cmpl) {
12790 emlxs_rpi_deferred_cmpl(port, rpip, 1);
12793 if (sbp) {
12794 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
12795 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
12797 cmpl->port = port;
12798 cmpl->arg1 = (void *)sbp;
12799 cmpl->arg2 = 0;
12800 cmpl->arg3 = 0;
12802 rpip->cmpl = cmpl;
12805 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_FAILED,
12806 FCF_REASON_OP_FAILED, 1, 0);
12808 if (rval && rpip->cmpl) {
12809 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
12810 rpip->cmpl = 0;
12813 mutex_exit(&EMLXS_FCF_LOCK);
12814 return (rval);
12816 } /* emlxs_vpi_logi_failed_notify() */
12819 extern uint32_t
12820 emlxs_vpi_logo_cmpl_notify(emlxs_port_t *port)
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;
12828 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
12829 return (1);
12832 mutex_enter(&EMLXS_FCF_LOCK);
12834 /* Fabric logo is complete */
12835 emlxs_vpi_logo_handler(port, vpip);
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);
12844 vfip = vpip->vfip;
12845 fcfp = vfip->fcfp;
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);
12856 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
12858 mutex_exit(&EMLXS_FCF_LOCK);
12860 return (rval);
12862 } /* emlxs_vpi_logo_cmpl_notify() */
12865 /*ARGSUSED*/
12866 static uint32_t
12867 emlxs_vpi_logi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12868 void *arg1)
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;
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);
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);
12890 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12891 return (rval);
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);
12899 /* Fabric logo is implied */
12900 emlxs_vpi_logo_handler(port, vpip);
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);
12910 *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FLOGI;
12912 vpip->vfip->flogi_vpip = vpip;
12914 if (vpip->vfip->logi_count == 0) {
12915 vpip->vfip->logi_count++;
12916 vpip->flag |= EMLXS_VPI_VFI_LOGI;
12919 return (0);
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);
12929 *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FLOGI;
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);
12938 *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FDISC;
12941 vpip->vfip->logi_count++;
12942 vpip->flag |= EMLXS_VPI_VFI_LOGI;
12944 return (0);
12946 } /* emlxs_vpi_logi_action() */
12949 /*ARGSUSED*/
12950 static uint32_t
12951 emlxs_vpi_logi_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12952 void *arg1)
12954 emlxs_hba_t *hba = HBA;
12955 uint32_t rval = 0;
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);
12967 /* Fabric logo is implied */
12968 emlxs_vpi_logo_handler(port, vpip);
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);
12976 /* Update the VPI flogi_vpip pointer for loop */
12977 /* because the vpi_logo_handler cleared it */
12978 vpip->vfip->flogi_vpip = vpip;
12980 bcopy((void *)&vpip->port->sparam,
12981 (void *)&vpip->fabric_rpip->sparam,
12982 sizeof (SERV_PARM));
12984 /* Update the VPI Fabric RPI */
12985 vpip->fabric_rpip->sparam.cmn.w2.r_a_tov =
12986 LE_SWAP32((FF_DEF_RATOV * 1000));
12988 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
12989 FCF_REASON_EVENT, evt, arg1);
12990 return (rval);
12993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12994 "vpi_logi_failed_action:%d. Requesting offline.",
12995 vpip->VPI);
12997 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
12998 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
12999 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13001 return (rval);
13003 } /* emlxs_vpi_logi_failed_action() */
13006 /*ARGSUSED*/
13007 static uint32_t
13008 emlxs_vpi_logi_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13009 void *arg1)
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;
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);
13027 vpip->flag |= EMLXS_VPI_LOGI;
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;
13039 } else {
13040 uint32_t old_topo;
13041 uint32_t new_topo;
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;
13047 if (old_topo != new_topo) {
13048 new_config = 1;
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;
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);
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);
13074 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
13075 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13076 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13078 return (rval);
13081 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13082 "vpi_logi_cmpl_action:%d. Registering.",
13083 vpip->VPI);
13085 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
13086 FCF_REASON_EVENT, evt, arg1);
13088 return (rval);
13090 } /* emlxs_vpi_logi_cmpl_action() */
13093 /*ARGSUSED*/
13094 static uint32_t
13095 emlxs_vpi_logo_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13096 void *arg1)
13098 emlxs_hba_t *hba = HBA;
13099 uint32_t rval = 0;
13101 vpip->attempts++;
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);
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);
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);
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);
13136 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
13137 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13140 return (rval);
13142 } /* emlxs_vpi_logo_failed_action() */
13145 /*ARGSUSED*/
13146 static uint32_t
13147 emlxs_vpi_logo_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13148 void *arg1)
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;
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);
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);
13173 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13174 FCF_REASON_EVENT, evt, arg1);
13175 return (rval);
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);
13184 /* Fabric logo is implied */
13185 emlxs_vpi_logo_handler(port, vpip);
13187 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13188 FCF_REASON_EVENT, evt, arg1);
13189 return (rval);
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);
13197 /* Fabric logo is implied */
13198 emlxs_vpi_logo_handler(port, vpip);
13200 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13201 FCF_REASON_EVENT, evt, arg1);
13202 return (rval);
13205 if (vpip->prev_state != VPI_STATE_LOGO_FAILED) {
13206 vpip->attempts = 0;
13209 did = FABRIC_DID;
13210 sid = (vport->did)? vport->did:vport->prev_did;
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);
13218 pkt = emlxs_pkt_alloc(vport,
13219 (sizeof (uint32_t) + sizeof (LOGO)),
13220 (sizeof (uint32_t) + sizeof (LOGO)), 0, KM_NOSLEEP);
13222 if (!pkt) {
13223 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED,
13224 FCF_REASON_NO_PKT, 0, arg1);
13226 return (rval);
13229 pkt->pkt_tran_type = FC_PKT_EXCHANGE;
13230 pkt->pkt_timeout = (2 * hba->fc_ratov);
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;
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);
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);
13260 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED,
13261 FCF_REASON_SEND_FAILED, rval, arg1);
13263 return (rval);
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);
13270 return (rval);
13272 } /* emlxs_vpi_logo_action() */
13275 /*ARGSUSED*/
13276 static uint32_t
13277 emlxs_vpi_logo_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13278 void *arg1)
13280 uint32_t rval = 0;
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);
13292 /* Fabric logo is complete */
13293 emlxs_vpi_logo_handler(port, vpip);
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);
13300 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13301 FCF_REASON_EVENT, evt, arg1);
13303 return (rval);
13305 } /* emlxs_vpi_logo_cmpl_action() */
13308 /*ARGSUSED*/
13309 static uint32_t
13310 emlxs_vpi_unreg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13311 void *arg1)
13313 uint32_t rval = 0;
13315 vpip->attempts++;
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);
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);
13335 vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
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);
13347 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
13348 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13351 return (rval);
13353 } /* emlxs_vpi_unreg_failed_action() */
13356 /*ARGSUSED*/
13357 static uint32_t
13358 emlxs_vpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
13360 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
13361 MAILBOX4 *mb4;
13362 VPIobj_t *vpip;
13364 vpip = (VPIobj_t *)mbq->context;
13365 mb4 = (MAILBOX4 *)mbq;
13367 mutex_enter(&EMLXS_FCF_LOCK);
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));
13375 mutex_exit(&EMLXS_FCF_LOCK);
13376 return (0);
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));
13385 (void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
13386 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
13388 mutex_exit(&EMLXS_FCF_LOCK);
13389 return (0);
13392 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13393 "vpi_unreg_mbcmpl:%d. Unreg complete. >",
13394 vpip->VPI);
13396 vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
13397 (void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL, 0, 0, 0);
13399 mutex_exit(&EMLXS_FCF_LOCK);
13400 return (0);
13402 } /* emlxs_vpi_unreg_mbcmpl() */
13405 /*ARGSUSED*/
13406 static uint32_t
13407 emlxs_vpi_unreg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13408 void *arg1)
13410 emlxs_hba_t *hba = HBA;
13411 MAILBOX4 *mb4;
13412 MAILBOXQ *mbq;
13413 uint32_t rval = 0;
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);
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);
13432 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13433 FCF_REASON_EVENT, evt, arg1);
13434 return (rval);
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);
13442 rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
13443 FCF_REASON_EVENT, evt, arg1);
13444 return (rval);
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);
13453 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED,
13454 FCF_REASON_EVENT, evt, arg1);
13455 return (rval);
13458 if (vpip->prev_state != VPI_STATE_UNREG_FAILED) {
13459 vpip->attempts = 0;
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);
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);
13471 return (rval);
13473 mb4 = (MAILBOX4*)mbq;
13474 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
13476 mbq->nonembed = NULL;
13477 mbq->mbox_cmpl = emlxs_vpi_unreg_mbcmpl;
13478 mbq->context = (void *)vpip;
13479 mbq->port = (void *)vpip->port;
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;
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);
13490 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
13491 FCF_REASON_SEND_FAILED, rval, arg1);
13493 return (rval);
13496 return (0);
13498 } /* emlxs_vpi_unreg_action() */
13501 /*ARGSUSED*/
13502 static uint32_t
13503 emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13504 void *arg1)
13506 uint32_t rval = 0;
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);
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);
13523 rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
13524 FCF_REASON_EVENT, evt, arg1);
13526 return (rval);
13528 } /* emlxs_vpi_unreg_cmpl_action() */
13531 /*ARGSUSED*/
13532 static uint32_t
13533 emlxs_vpi_reg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13534 void *arg1)
13536 uint32_t rval = 0;
13538 vpip->attempts++;
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);
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);
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);
13569 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
13570 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13573 return (rval);
13575 } /* emlxs_vpi_reg_failed_action() */
13578 /*ARGSUSED*/
13579 static uint32_t
13580 emlxs_vpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
13582 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
13583 MAILBOX4 *mb4;
13584 VPIobj_t *vpip;
13586 vpip = (VPIobj_t *)mbq->context;
13587 mb4 = (MAILBOX4 *)mbq;
13589 mutex_enter(&EMLXS_FCF_LOCK);
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));
13597 mutex_exit(&EMLXS_FCF_LOCK);
13598 return (0);
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));
13607 if (mb4->mbxStatus == MBXERR_DID_INCONSISTENT) {
13608 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13611 (void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
13612 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
13614 mutex_exit(&EMLXS_FCF_LOCK);
13615 return (0);
13618 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13619 "vpi_reg_mbcmpl:%d. Reg complete. >",
13620 vpip->VPI);
13622 vpip->flag |= EMLXS_VPI_REG;
13623 (void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL,
13624 0, 0, 0);
13626 mutex_exit(&EMLXS_FCF_LOCK);
13627 return (0);
13629 } /* emlxs_vpi_reg_mbcmpl() */
13632 /*ARGSUSED*/
13633 static uint32_t
13634 emlxs_vpi_reg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13635 void *arg1)
13637 emlxs_hba_t *hba = HBA;
13638 uint32_t *wwpn;
13639 MAILBOX *mb;
13640 MAILBOXQ *mbq;
13641 uint32_t rval = 0;
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);
13653 if (vpip->prev_state != VPI_STATE_REG_FAILED) {
13654 vpip->attempts = 0;
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);
13663 rval = emlxs_vpi_offline_handler(port, vpip, 0);
13664 return (rval);
13667 if (!(vpip->vfip->flag & EMLXS_VFI_REG)) {
13668 /* We can't register the VPI until our VFI is registered */
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);
13677 rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE,
13678 FCF_REASON_EVENT, evt, arg1);
13680 return (rval);
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);
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);
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);
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);
13711 return (rval);
13713 mb = (MAILBOX*)mbq;
13714 bzero((void *) mb, MAILBOX_CMD_BSIZE);
13716 mbq->nonembed = NULL;
13717 mbq->mbox_cmpl = emlxs_vpi_reg_mbcmpl;
13718 mbq->context = (void *)vpip;
13719 mbq->port = (void *)vpip->port;
13721 mb->un.varRegVpi.vfi = vpip->vfip->VFI;
13722 mb->un.varRegVpi.upd = (vpip->flag & EMLXS_VPI_REG)? 1:0;
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);
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;
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);
13738 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
13739 FCF_REASON_SEND_FAILED, rval, arg1);
13741 return (rval);
13744 return (0);
13746 } /* emlxs_vpi_reg_action() */
13749 /*ARGSUSED*/
13750 static uint32_t
13751 emlxs_vpi_reg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13752 void *arg1)
13754 uint32_t rval = 0;
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);
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);
13772 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13773 return (rval);
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);
13781 rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE,
13782 FCF_REASON_EVENT, evt, arg1);
13784 return (rval);
13786 } /* emlxs_vpi_reg_cmpl_action() */
13789 /*ARGSUSED*/
13790 static uint32_t
13791 emlxs_vpi_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13792 void *arg1)
13794 uint32_t rval = 0;
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);
13806 vpip->flag &= ~EMLXS_VPI_ONLINE_REQ;
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);
13814 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13815 return (rval);
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);
13823 /* Notify VFI */
13824 rval = emlxs_vfi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
13826 return (rval);
13828 } /* emlxs_vpi_online_action() */
13831 /* ************************************************************************** */
13832 /* RPI */
13833 /* ************************************************************************** */
13835 static char *
13836 emlxs_rpi_state_xlate(uint32_t state)
13838 static char buffer[32];
13839 uint32_t i;
13840 uint32_t count;
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);
13849 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
13850 return (buffer);
13852 } /* emlxs_rpi_state_xlate() */
13855 static uint32_t
13856 emlxs_rpi_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
13857 void *arg1)
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;
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);
13886 events = RPI_ACTION_EVENTS;
13887 state = rpip->state;
13889 index += (state * events);
13890 func = (uint32_t(*) (emlxs_port_t *, RPIobj_t *, uint32_t, void *))
13891 emlxs_rpi_action_table[index];
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);
13900 return (1);
13903 rval = (func)(port, rpip, evt, arg1);
13905 return (rval);
13907 } /* emlxs_rpi_action() */
13910 static uint32_t
13911 emlxs_rpi_event(emlxs_port_t *port, uint32_t evt,
13912 void *arg1)
13914 RPIobj_t *rpip = NULL;
13915 uint32_t rval = 0;
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;
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);
13930 return (1);
13933 break;
13935 default:
13936 return (1);
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);
13945 rval = emlxs_rpi_action(port, rpip, evt, arg1);
13947 return (rval);
13949 } /* emlxs_rpi_event() */
13952 /*ARGSUSED*/
13953 static uint32_t
13954 emlxs_rpi_state(emlxs_port_t *port, RPIobj_t *rpip, uint16_t state,
13955 uint16_t reason, uint32_t explain, void *arg1)
13957 uint32_t rval = 0;
13959 if (state >= RPI_ACTION_STATES) {
13960 return (1);
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);
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);
14005 rpip->prev_state = rpip->state;
14006 rpip->prev_reason = rpip->reason;
14007 rpip->state = state;
14008 rpip->reason = reason;
14010 rval = emlxs_rpi_action(port, rpip, FCF_EVENT_STATE_ENTER, arg1);
14012 return (rval);
14014 } /* emlxs_rpi_state() */
14017 static void
14018 emlxs_rpi_deferred_cmpl(emlxs_port_t *port, RPIobj_t *rpip, uint32_t status)
14020 emlxs_hba_t *hba = HBA;
14021 emlxs_deferred_cmpl_t *cmpl;
14023 if (!rpip->cmpl) {
14024 return;
14027 cmpl = rpip->cmpl;
14028 rpip->cmpl = 0;
14030 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14031 "rpi_deferred_cmpl:%d. status=%x ...",
14032 port->vpip->VPI,
14033 status);
14035 emlxs_thread_spawn(hba, emlxs_deferred_cmpl_thread, (void *)cmpl,
14036 (void*)(uintptr_t)status);
14038 return;
14040 } /* emlxs_rpi_deferred_cmpl() */
14043 static void
14044 emlxs_rpi_idle_timer(emlxs_hba_t *hba)
14046 emlxs_config_t *cfg = &CFG;
14047 RPIobj_t *rpip;
14048 uint32_t i;
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;
14060 /* If RPI is active, then clear timer. */
14061 if (rpip->xri_count) {
14062 rpip->idle_timer = 0;
14063 continue;
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;
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;
14080 /* Check for idle timeout */
14081 if (hba->timer_tics < rpip->idle_timer) {
14082 continue;
14084 rpip->idle_timer = 0;
14086 free_it:
14087 (void) emlxs_rpi_state(rpip->vpip->port, rpip, RPI_STATE_FREE,
14088 FCF_REASON_UNUSED, 0, 0);
14091 return;
14093 } /* emlxs_rpi_idle_timer() */
14096 static RPIobj_t *
14097 emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did)
14099 emlxs_hba_t *hba = HBA;
14100 uint16_t i;
14101 RPIobj_t *rpip;
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)) {
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;
14117 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14118 "rpi_alloc:%d. RPI allocated. >",
14119 rpip->RPI);
14121 (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESERVED,
14122 0, 0, 0);
14124 return (rpip);
14128 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14129 "rpi_alloc: Out of RPI objects.");
14131 return (NULL);
14133 } /* emlxs_rpi_alloc() */
14136 /* Special routine for VPI object */
14137 static void
14138 emlxs_rpi_alloc_fabric_rpi(emlxs_port_t *port)
14140 RPIobj_t *fabric_rpip;
14142 fabric_rpip = port->vpip->fabric_rpip;
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;
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;
14157 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14158 "rpi_alloc_fabric_rpi: Allocating Fabric RPI. >");
14160 (void) emlxs_rpi_state(port, fabric_rpip, RPI_STATE_RESERVED,
14161 0, 0, 0);
14163 return;
14165 } /* emlxs_rpi_alloc_fabric_rpi() */
14168 static uint32_t
14169 emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip)
14171 uint32_t rval = 0;
14173 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14174 "rpi_free:%d did=%x. Freeing RPI. >",
14175 rpip->RPI, rpip->did);
14177 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
14179 return (rval);
14181 } /* emlxs_rpi_free() */
14184 extern RPIobj_t *
14185 emlxs_rpi_find(emlxs_port_t *port, uint16_t rpi)
14187 emlxs_hba_t *hba = HBA;
14188 RPIobj_t *rpip;
14189 uint32_t index;
14191 /* Special handling for Fabric RPI */
14192 if (rpi == FABRIC_RPI) {
14193 return (port->vpip->fabric_rpip);
14196 index = emlxs_sli4_rpi_to_index(hba, rpi);
14198 if (index >= hba->sli.sli4.RPICount) {
14199 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14200 "rpi_find:%d. RPI Invalid.",
14201 rpi);
14203 return (NULL);
14206 rpip = &hba->sli.sli4.RPIp[index];
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);
14213 return (NULL);
14216 return (rpip);
14218 } /* emlxs_rpi_find() */
14221 static RPIobj_t *
14222 emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did)
14224 emlxs_hba_t *hba = HBA;
14225 RPIobj_t *rpip;
14226 RPIobj_t *rpip1;
14227 uint32_t i;
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;
14236 if ((rpip->did == did) && (rpip->vpip == port->vpip)) {
14237 rpip1 = rpip;
14238 break;
14242 return (rpip1);
14244 } /* emlxs_rpi_find_did() */
14247 extern RPIobj_t *
14248 emlxs_rpi_reserve_notify(emlxs_port_t *port, uint32_t did, XRIobj_t *xrip)
14250 emlxs_hba_t *hba = HBA;
14251 RPIobj_t *rpip;
14253 /* xrip will be NULL for unsolicited BLS requests */
14255 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14256 return (NULL);
14259 mutex_enter(&EMLXS_FCF_LOCK);
14261 rpip = emlxs_rpi_find_did(port, did);
14263 if (!rpip) {
14264 rpip = emlxs_rpi_alloc(port, did);
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));
14273 mutex_exit(&EMLXS_FCF_LOCK);
14274 return (NULL);
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);
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));
14289 mutex_exit(&EMLXS_FCF_LOCK);
14291 return (rpip);
14293 } /* emlxs_rpi_reserve_notify() */
14296 extern RPIobj_t *
14297 emlxs_rpi_alloc_notify(emlxs_port_t *port, uint32_t did)
14299 emlxs_hba_t *hba = HBA;
14300 RPIobj_t *rpip;
14302 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14303 return (NULL);
14306 mutex_enter(&EMLXS_FCF_LOCK);
14308 rpip = emlxs_rpi_alloc(port, did);
14310 mutex_exit(&EMLXS_FCF_LOCK);
14312 return (rpip);
14314 } /* emlxs_rpi_alloc_notify() */
14317 extern uint32_t
14318 emlxs_rpi_free_notify(emlxs_port_t *port, RPIobj_t *rpip)
14320 emlxs_hba_t *hba = HBA;
14321 uint32_t rval = 0;
14323 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14324 return (1);
14327 if (!rpip) {
14328 return (1);
14331 /* Fabric RPI will be handled automatically */
14332 if (rpip->RPI == FABRIC_RPI) {
14333 return (1);
14336 mutex_enter(&EMLXS_FCF_LOCK);
14338 rval = emlxs_rpi_free(port, rpip);
14340 mutex_exit(&EMLXS_FCF_LOCK);
14342 return (rval);
14344 } /* emlxs_rpi_free_notify() */
14347 extern uint32_t
14348 emlxs_rpi_pause_notify(emlxs_port_t *port, RPIobj_t *rpip)
14350 emlxs_hba_t *hba = HBA;
14352 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14353 return (1);
14356 if (!rpip) {
14357 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14358 "rpi_pause_notify: No RPI provided.");
14359 return (1);
14362 /* Fabric RPI will be handled automatically */
14363 if (rpip->RPI == FABRIC_RPI) {
14364 return (1);
14367 mutex_enter(&EMLXS_FCF_LOCK);
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));
14374 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_PAUSE, rpip);
14376 mutex_exit(&EMLXS_FCF_LOCK);
14378 return (0);
14380 } /* emlxs_rpi_pause_notify() */
14383 extern uint32_t
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)
14387 emlxs_hba_t *hba = HBA;
14388 emlxs_deferred_cmpl_t *cmpl;
14389 uint32_t allocated = 0;
14390 uint32_t rval = 0;
14392 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14393 return (1);
14396 if ((did == port->did) && (!(hba->flag & FC_LOOPBACK_MODE))) {
14397 /* We never register our local port */
14398 return (1);
14401 mutex_enter(&EMLXS_FCF_LOCK);
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;
14409 if (!rpip) {
14410 rpip = emlxs_rpi_find_did(port, did);
14413 if (!rpip) {
14414 rpip = emlxs_rpi_alloc(port, did);
14415 allocated = 1;
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);
14423 mutex_exit(&EMLXS_FCF_LOCK);
14424 return (1);
14427 /* Initialize RPI node info */
14428 bcopy((void *)sparam, (void *)&rpip->sparam, sizeof (SERV_PARM));
14430 if (arg1 || arg2 || arg3) {
14431 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
14432 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
14434 cmpl->port = port;
14435 cmpl->arg1 = arg1;
14436 cmpl->arg2 = arg2;
14437 cmpl->arg3 = arg3;
14439 /* For safety */
14440 if (rpip->cmpl) {
14441 emlxs_rpi_deferred_cmpl(port, rpip, 1);
14444 rpip->cmpl = cmpl;
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"));
14455 rval = emlxs_vpi_logi_cmpl_notify(port, rpip);
14457 if (rval && rpip->cmpl) {
14458 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14459 rpip->cmpl = 0;
14462 mutex_exit(&EMLXS_FCF_LOCK);
14463 return (rval);
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"));
14472 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE, rpip);
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));
14480 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14481 rpip->cmpl = 0;
14483 mutex_exit(&EMLXS_FCF_LOCK);
14484 return (1);
14487 mutex_exit(&EMLXS_FCF_LOCK);
14488 return (0);
14490 } /* emlxs_rpi_online_notify() */
14493 extern uint32_t
14494 emlxs_rpi_offline_notify(emlxs_port_t *port, RPIobj_t *rpip,
14495 void *arg1, void *arg2, void *arg3)
14497 emlxs_hba_t *hba = HBA;
14498 emlxs_deferred_cmpl_t *cmpl;
14500 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14501 return (1);
14504 if (!rpip) {
14505 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14506 "rpi_offline_notify: No RPI provided.");
14507 return (1);
14510 /* Fabric RPI will be handled automatically */
14511 if (rpip->RPI == FABRIC_RPI) {
14512 return (1);
14515 mutex_enter(&EMLXS_FCF_LOCK);
14517 if (arg1 || arg2 || arg3) {
14518 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
14519 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
14521 cmpl->port = port;
14522 cmpl->arg1 = arg1;
14523 cmpl->arg2 = arg2;
14524 cmpl->arg3 = arg3;
14526 rpip->cmpl = cmpl;
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));
14534 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip);
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));
14542 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14543 rpip->cmpl = 0;
14545 mutex_exit(&EMLXS_FCF_LOCK);
14546 return (1);
14549 mutex_exit(&EMLXS_FCF_LOCK);
14551 return (0);
14553 } /* emlxs_rpi_offline_notify() */
14556 extern uint32_t
14557 emlxs_rpi_resume_notify(emlxs_port_t *port, RPIobj_t *rpip, emlxs_buf_t *sbp)
14559 emlxs_hba_t *hba = HBA;
14560 emlxs_deferred_cmpl_t *cmpl;
14562 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14563 return (1);
14566 if (!rpip) {
14567 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14568 "rpi_resume_notify: No RPI provided.");
14569 return (1);
14572 /* Fabric RPI will be handled automatically */
14573 if (rpip->RPI == FABRIC_RPI) {
14574 return (1);
14577 mutex_enter(&EMLXS_FCF_LOCK);
14579 if (rpip->state != RPI_STATE_PAUSED) {
14580 mutex_exit(&EMLXS_FCF_LOCK);
14581 return (1);
14584 if (sbp) {
14585 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
14586 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
14588 cmpl->port = port;
14589 cmpl->arg1 = (void *)sbp;
14590 cmpl->arg2 = 0;
14591 cmpl->arg3 = 0;
14593 rpip->cmpl = cmpl;
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));
14601 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_RESUME, rpip);
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));
14609 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14610 rpip->cmpl = 0;
14612 mutex_exit(&EMLXS_FCF_LOCK);
14613 return (1);
14616 mutex_exit(&EMLXS_FCF_LOCK);
14618 return (0);
14620 } /* emlxs_rpi_resume_notify() */
14623 /*ARGSUSED*/
14624 static uint32_t
14625 emlxs_rpi_free_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14626 void *arg1)
14628 emlxs_hba_t *hba = HBA;
14629 XRIobj_t *xrip;
14630 XRIobj_t *next_xrip;
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);
14642 if (rpip->cmpl) {
14643 emlxs_rpi_deferred_cmpl(port, rpip, 1);
14646 if (rpip->vpip->p2p_rpip == rpip) {
14647 rpip->vpip->p2p_rpip = NULL;
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;
14656 rw_exit(&port->node_rwlock);
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);
14671 rpip->xri_count--;
14672 xrip->rpip = NULL;
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);
14683 rpip->xri_count--;
14684 xrip->reserved_rpip = NULL;
14687 xrip = next_xrip;
14689 mutex_exit(&EMLXS_FCTAB_LOCK);
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);
14698 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14699 "rpi_free_action:%d flag=%x. RPI freed. <",
14700 rpip->RPI,
14701 rpip->flag);
14703 rpip->flag = 0;
14705 return (0);
14707 } /* emlxs_rpi_free_action() */
14710 /*ARGSUSED*/
14711 static uint32_t
14712 emlxs_rpi_online_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14713 void *arg1)
14715 uint32_t rval = 1;
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);
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);
14734 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG,
14735 FCF_REASON_REENTER, evt, arg1);
14736 break;
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);
14744 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG,
14745 FCF_REASON_EVENT, evt, arg1);
14746 break;
14749 return (rval);
14751 } /* emlxs_rpi_online_evt_action() */
14754 /*ARGSUSED*/
14755 static uint32_t
14756 emlxs_rpi_offline_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14757 void *arg1)
14759 uint32_t rval = 1;
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);
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);
14778 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE,
14779 FCF_REASON_EVENT, evt, arg1);
14780 break;
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);
14789 break;
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);
14797 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
14798 FCF_REASON_EVENT, evt, arg1);
14799 break;
14803 return (rval);
14805 } /* emlxs_rpi_offline_evt_action() */
14808 /*ARGSUSED*/
14809 static uint32_t
14810 emlxs_rpi_pause_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14811 void *arg1)
14813 VPIobj_t *vpip;
14814 uint32_t rval = 1;
14816 vpip = rpip->vpip;
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);
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);
14836 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE,
14837 FCF_REASON_EVENT, evt, arg1);
14838 break;
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);
14846 break;
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);
14854 break;
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);
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);
14873 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
14874 FCF_REASON_EVENT, evt, arg1);
14875 break;
14878 rval = emlxs_rpi_state(port, rpip, RPI_STATE_PAUSED,
14879 FCF_REASON_EVENT, evt, arg1);
14880 break;
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;
14890 return (rval);
14892 } /* emlxs_rpi_pause_evt_action() */
14895 /*ARGSUSED*/
14896 static uint32_t
14897 emlxs_rpi_resume_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14898 void *arg1)
14900 uint32_t rval = 1;
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);
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);
14920 rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME,
14921 FCF_REASON_EVENT, evt, arg1);
14922 break;
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;
14932 return (rval);
14934 } /* emlxs_rpi_resume_evt_action() */
14937 /*ARGSUSED*/
14938 static uint32_t
14939 emlxs_rpi_reserved_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14940 void *arg1)
14942 VPIobj_t *vpip;
14944 vpip = rpip->vpip;
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);
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));
14965 return (1);
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);
14973 return (0);
14975 } /* emlxs_rpi_reserved_action() */
14978 /*ARGSUSED*/
14979 static uint32_t
14980 emlxs_rpi_offline_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14981 void *arg1)
14983 uint32_t rval = 0;
14984 VPIobj_t *vpip;
14986 vpip = rpip->vpip;
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);
14998 if (rpip->flag & EMLXS_RPI_PAUSED) {
14999 rpip->flag &= ~EMLXS_RPI_PAUSED;
15001 if (vpip->rpi_paused) {
15002 vpip->rpi_paused--;
15006 if (rpip->flag & EMLXS_RPI_VPI) {
15007 rpip->flag &= ~EMLXS_RPI_VPI;
15009 if (vpip->rpi_online) {
15010 vpip->rpi_online--;
15013 /* Added protection */
15014 if (vpip->rpi_online < vpip->rpi_paused) {
15015 vpip->rpi_paused = vpip->rpi_online;
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);
15027 /* Free RPI */
15028 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
15030 return (rval);
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);
15044 /* Notify VPI */
15045 (void) emlxs_vpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip);
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);
15056 /* Free RPI */
15057 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
15059 return (rval);
15061 } /* emlxs_rpi_offline_action() */
15064 /*ARGSUSED*/
15065 static uint32_t
15066 emlxs_rpi_paused_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15067 void *arg1)
15069 VPIobj_t *vpip;
15070 uint32_t rval = 0;
15072 vpip = rpip->vpip;
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);
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);
15093 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
15094 FCF_REASON_EVENT, evt, arg1);
15095 return (rval);
15098 if (!(rpip->flag & EMLXS_RPI_PAUSED)) {
15099 rpip->flag |= EMLXS_RPI_PAUSED;
15100 vpip->rpi_paused++;
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);
15114 /* Notify VPI */
15115 (void) emlxs_vpi_event(port, FCF_EVENT_RPI_PAUSE, rpip);
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);
15126 return (0);
15128 } /* emlxs_rpi_paused_action() */
15131 /*ARGSUSED*/
15132 static uint32_t
15133 emlxs_rpi_unreg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15134 void *arg1)
15136 uint32_t rval = 0;
15138 rpip->attempts++;
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);
15151 if ((rpip->reason == FCF_REASON_SEND_FAILED) ||
15152 !(rpip->flag & EMLXS_RPI_REG)) {
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);
15161 rpip->flag &= ~EMLXS_RPI_REG;
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);
15171 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15172 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15175 return (rval);
15177 } /* emlxs_rpi_unreg_failed_action() */
15180 static void
15181 emlxs_rpi_unreg_handler(emlxs_port_t *port, RPIobj_t *rpip)
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;
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);
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);
15213 (void) emlxs_sli4_unreserve_xri(port,
15214 xrip->XRI, 0);
15216 xrip = next_xrip;
15218 mutex_exit(&EMLXS_FCTAB_LOCK);
15221 rpip->flag &= ~EMLXS_RPI_REG;
15223 if (rpip->flag & EMLXS_RPI_PAUSED) {
15224 rpip->flag &= ~EMLXS_RPI_PAUSED;
15226 if (vpip->rpi_paused) {
15227 vpip->rpi_paused--;
15231 if (rpip->flag & EMLXS_RPI_VPI) {
15232 rpip->flag &= ~EMLXS_RPI_VPI;
15234 if (vpip->rpi_online) {
15235 vpip->rpi_online--;
15238 /* Added protection */
15239 if (vpip->rpi_online < vpip->rpi_paused) {
15240 vpip->rpi_paused = vpip->rpi_online;
15244 rw_enter(&port->node_rwlock, RW_WRITER);
15245 if (node) {
15246 rpip->node = NULL;
15247 node->rpip = NULL;
15249 rw_exit(&port->node_rwlock);
15251 if (node) {
15252 emlxs_node_rm(port, node);
15255 return;
15257 } /* emlxs_rpi_unreg_handler() */
15260 /*ARGSUSED*/
15261 static uint32_t
15262 emlxs_rpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
15264 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
15265 MAILBOX4 *mb4;
15266 RPIobj_t *rpip;
15268 mutex_enter(&EMLXS_FCF_LOCK);
15270 rpip = (RPIobj_t *)mbq->context;
15272 mb4 = (MAILBOX4 *)mbq;
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));
15281 mutex_exit(&EMLXS_FCF_LOCK);
15282 return (0);
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));
15291 (void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
15292 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
15294 mutex_exit(&EMLXS_FCF_LOCK);
15295 return (0);
15298 emlxs_rpi_unreg_handler(port, rpip);
15300 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15301 "rpi_unreg_mbcmpl:%d Unregistered. Unreg complete. >",
15302 rpip->RPI);
15304 (void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_CMPL,
15305 0, 0, 0);
15307 mutex_exit(&EMLXS_FCF_LOCK);
15308 return (0);
15310 } /* emlxs_rpi_unreg_mbcmpl() */
15313 /*ARGSUSED*/
15314 static uint32_t
15315 emlxs_rpi_unreg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15316 void *arg1)
15318 emlxs_hba_t *hba = HBA;
15319 MAILBOX4 *mb4;
15320 MAILBOXQ *mbq;
15321 uint32_t rval = 0;
15322 VPIobj_t *vpip = rpip->vpip;
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);
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);
15339 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15340 FCF_REASON_EVENT, evt, arg1);
15342 return (rval);
15345 if (rpip->prev_state != RPI_STATE_UNREG_FAILED) {
15346 rpip->attempts = 0;
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);
15357 /* Don't send UNREG_RPI, but process it as if we did */
15358 emlxs_rpi_unreg_handler(port, rpip);
15360 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15361 FCF_REASON_EVENT, evt, arg1);
15363 return (rval);
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);
15371 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
15373 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
15374 FCF_REASON_NO_MBOX, 0, arg1);
15376 return (rval);
15378 mb4 = (MAILBOX4*)mbq;
15379 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
15381 mbq->nonembed = NULL;
15382 mbq->mbox_cmpl = emlxs_rpi_unreg_mbcmpl;
15383 mbq->context = (void *)rpip;
15384 mbq->port = (void *)port;
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;
15391 if (rpip->cmpl) {
15392 mbq->sbp = rpip->cmpl->arg1;
15393 mbq->ubp = rpip->cmpl->arg2;
15394 mbq->iocbq = rpip->cmpl->arg3;
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);
15401 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
15402 FCF_REASON_SEND_FAILED, rval, arg1);
15404 return (rval);
15407 if (rpip->cmpl) {
15408 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
15409 rpip->cmpl = 0;
15412 return (0);
15414 } /* emlxs_rpi_unreg_action() */
15417 /*ARGSUSED*/
15418 static uint32_t
15419 emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15420 void *arg1)
15422 uint32_t rval = 0;
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);
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);
15439 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15440 FCF_REASON_EVENT, evt, arg1);
15442 return (rval);
15444 } /* emlxs_rpi_unreg_cmpl_action() */
15447 /*ARGSUSED*/
15448 static uint32_t
15449 emlxs_rpi_reg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15450 void *arg1)
15452 uint32_t rval = 0;
15454 rpip->attempts++;
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);
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);
15476 rpip->flag &= ~EMLXS_RPI_REG;
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);
15486 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
15487 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15490 return (rval);
15492 } /* emlxs_rpi_reg_failed_action() */
15495 static uint32_t
15496 emlxs_rpi_reg_handler(emlxs_port_t *port, RPIobj_t *rpip)
15498 emlxs_hba_t *hba = HBA;
15499 VPIobj_t *vpip;
15500 emlxs_node_t *node;
15502 vpip = rpip->vpip;
15504 rpip->flag |= EMLXS_RPI_REG;
15506 if (rpip->flag & EMLXS_RPI_PAUSED) {
15507 rpip->flag &= ~EMLXS_RPI_PAUSED;
15509 if (vpip->rpi_paused) {
15510 vpip->rpi_paused--;
15514 if (!(rpip->flag & EMLXS_RPI_VPI) && (rpip->RPI != FABRIC_RPI)) {
15515 rpip->flag |= EMLXS_RPI_VPI;
15516 vpip->rpi_online++;
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);
15524 /* Create or update the node */
15525 node = emlxs_node_create(port, rpip->did, rpip->RPI, &rpip->sparam);
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);
15532 return (FCF_REASON_NO_NODE);
15535 return (0);
15537 } /* emlxs_rpi_reg_handler() */
15540 /*ARGSUSED*/
15541 static uint32_t
15542 emlxs_rpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
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;
15550 mutex_enter(&EMLXS_FCF_LOCK);
15552 rpip = (RPIobj_t *)mbq->context;
15553 mb4 = (MAILBOX4 *)mbq;
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));
15561 mutex_exit(&EMLXS_FCF_LOCK);
15562 return (0);
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));
15571 (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15572 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
15574 mutex_exit(&EMLXS_FCF_LOCK);
15575 return (0);
15578 rval = emlxs_rpi_reg_handler(port, rpip);
15580 if (rval) {
15581 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15582 "rpi_reg_mbcmpl:%d. Reg failed. >",
15583 rpip->RPI);
15585 mb4->mbxStatus = MBX_FAILURE;
15587 (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15588 rval, 0, 0);
15590 mutex_exit(&EMLXS_FCF_LOCK);
15591 return (0);
15594 node = rpip->node;
15596 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15597 "rpi_reg_mbcmpl:%d Registered. Reg complete. >",
15598 rpip->RPI);
15600 (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_CMPL, 0, 0, 0);
15602 mutex_exit(&EMLXS_FCF_LOCK);
15604 /* Needed for FCT trigger in emlxs_mb_deferred_cmpl */
15605 if (mbq->sbp) {
15606 ((emlxs_buf_t *)mbq->sbp)->node = node;
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;
15619 #endif /* DHCHAP_SUPPORT */
15621 return (0);
15623 } /* emlxs_rpi_reg_mbcmpl() */
15626 /*ARGSUSED*/
15627 static uint32_t
15628 emlxs_rpi_reg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15629 void *arg1)
15631 emlxs_hba_t *hba = HBA;
15632 MAILBOX4 *mb4;
15633 MAILBOXQ *mbq;
15634 MATCHMAP *mp;
15635 uint32_t rval = 0;
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);
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);
15655 /* Don't send REG_RPI, but process it as if we did */
15656 rval = emlxs_rpi_reg_handler(port, rpip);
15658 if (rval) {
15659 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15660 rval, 0, 0);
15662 return (rval);
15665 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15666 FCF_REASON_EVENT, evt, arg1);
15668 return (rval);
15671 if (rpip->prev_state != RPI_STATE_REG_FAILED) {
15672 rpip->attempts = 0;
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);
15689 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
15691 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15692 FCF_REASON_NO_MBOX, 0, arg1);
15694 return (rval);
15697 mb4 = (MAILBOX4*)mbq;
15698 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
15700 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
15701 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
15703 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15704 FCF_REASON_NO_BUFFER, 0, arg1);
15706 return (rval);
15709 mbq->bp = (void *)mp;
15710 mbq->nonembed = NULL;
15712 mbq->mbox_cmpl = emlxs_rpi_reg_mbcmpl;
15713 mbq->context = (void *)rpip;
15714 mbq->port = (void *)port;
15716 mb4->mbxCommand = MBX_REG_RPI;
15717 mb4->mbxOwner = OWN_HOST;
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 */
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;
15729 bcopy((void *)&rpip->sparam, (void *)mp->virt, sizeof (SERV_PARM));
15731 if (rpip->cmpl) {
15732 mbq->sbp = rpip->cmpl->arg1;
15733 mbq->ubp = rpip->cmpl->arg2;
15734 mbq->iocbq = rpip->cmpl->arg3;
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);
15742 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15743 FCF_REASON_SEND_FAILED, rval, arg1);
15745 return (rval);
15748 if (rpip->cmpl) {
15749 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
15750 rpip->cmpl = 0;
15753 return (0);
15755 } /* emlxs_rpi_reg_action() */
15758 /*ARGSUSED*/
15759 static uint32_t
15760 emlxs_rpi_reg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15761 void *arg1)
15763 uint32_t rval = 0;
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);
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);
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);
15789 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15790 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15793 return (rval);
15795 } /* emlxs_rpi_reg_cmpl_action() */
15798 /*ARGSUSED*/
15799 static uint32_t
15800 emlxs_rpi_resume_failed_action(emlxs_port_t *port, RPIobj_t *rpip,
15801 uint32_t evt, void *arg1)
15803 uint32_t rval = 0;
15805 rpip->attempts++;
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);
15818 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15819 "rpi_resume_failed_action:%d attempt=%d. Unregistering.",
15820 rpip->RPI,
15821 rpip->attempts);
15823 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
15824 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15826 return (rval);
15828 } /* emlxs_rpi_resume_failed_action() */
15831 /*ARGSUSED*/
15832 static void
15833 emlxs_rpi_resume_handler(emlxs_port_t *port, RPIobj_t *rpip)
15835 if (rpip->flag & EMLXS_RPI_PAUSED) {
15836 rpip->flag &= ~EMLXS_RPI_PAUSED;
15838 if (rpip->vpip->rpi_paused) {
15839 rpip->vpip->rpi_paused--;
15843 return;
15845 } /* emlxs_rpi_resume_handler() */
15848 /*ARGSUSED*/
15849 static uint32_t
15850 emlxs_rpi_resume_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
15852 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
15853 MAILBOX4 *mb4;
15854 RPIobj_t *rpip;
15856 mutex_enter(&EMLXS_FCF_LOCK);
15858 rpip = (RPIobj_t *)mbq->context;
15859 mb4 = (MAILBOX4 *)mbq;
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));
15868 mutex_exit(&EMLXS_FCF_LOCK);
15869 return (0);
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));
15878 (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
15879 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
15881 mutex_exit(&EMLXS_FCF_LOCK);
15882 return (0);
15885 emlxs_rpi_resume_handler(port, rpip);
15887 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15888 "rpi_resume_mbcmpl:%d Resumed. Resume complete. >",
15889 rpip->RPI);
15891 (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_CMPL, 0, 0, 0);
15893 mutex_exit(&EMLXS_FCF_LOCK);
15895 return (0);
15897 } /* emlxs_rpi_resume_mbcmpl() */
15900 /*ARGSUSED*/
15901 static uint32_t
15902 emlxs_rpi_resume_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15903 void *arg1)
15905 emlxs_hba_t *hba = HBA;
15906 MAILBOX4 *mb4;
15907 MAILBOXQ *mbq;
15908 uint32_t rval = 0;
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);
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);
15925 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15926 FCF_REASON_EVENT, evt, arg1);
15928 return (rval);
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);
15937 /* Don't send RESUME_RPI, but process it as if we did */
15938 emlxs_rpi_resume_handler(port, rpip);
15940 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15941 FCF_REASON_EVENT, evt, arg1);
15943 return (rval);
15946 if (rpip->prev_state != RPI_STATE_RESUME_FAILED) {
15947 rpip->attempts = 0;
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);
15955 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
15957 rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
15958 FCF_REASON_NO_MBOX, 0, arg1);
15960 return (rval);
15962 mb4 = (MAILBOX4*)mbq;
15963 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
15965 mbq->nonembed = NULL;
15966 mbq->mbox_cmpl = emlxs_rpi_resume_mbcmpl;
15967 mbq->context = (void *)rpip;
15968 mbq->port = (void *)port;
15970 mb4->mbxCommand = MBX_RESUME_RPI;
15971 mb4->mbxOwner = OWN_HOST;
15973 mb4->un.varResumeRPI.EventTag = hba->link_event_tag;
15974 mb4->un.varResumeRPI.RPI = rpip->RPI;
15976 if (rpip->cmpl) {
15977 mbq->sbp = rpip->cmpl->arg1;
15978 mbq->ubp = rpip->cmpl->arg2;
15979 mbq->iocbq = rpip->cmpl->arg3;
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);
15986 rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
15987 FCF_REASON_SEND_FAILED, rval, arg1);
15989 return (rval);
15992 if (rpip->cmpl) {
15993 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
15994 rpip->cmpl = 0;
15997 return (0);
15999 } /* emlxs_rpi_resume_action() */
16002 static uint32_t
16003 emlxs_rpi_resume_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
16004 void *arg1)
16006 uint32_t rval = 0;
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);
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);
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);
16033 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
16034 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
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);
16042 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
16043 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
16046 return (rval);
16048 } /* emlxs_rpi_resume_cmpl_action() */
16051 /*ARGSUSED*/
16052 static uint32_t
16053 emlxs_rpi_online_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
16054 void *arg1)
16056 emlxs_hba_t *hba = HBA;
16057 uint32_t rval = 0;
16058 RPIobj_t *p2p_rpip;
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);
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);
16077 /* Now register the p2p_rpip */
16078 p2p_rpip = rpip->vpip->p2p_rpip;
16079 if (p2p_rpip) {
16080 rpip->vpip->p2p_rpip = NULL;
16082 rval = emlxs_rpi_state(port, p2p_rpip, RPI_STATE_REG,
16083 FCF_REASON_EVENT, evt, arg1);
16086 EMLXS_STATE_CHANGE(hba, FC_READY);
16088 if (rpip->cmpl) {
16089 emlxs_rpi_deferred_cmpl(port, rpip, 0);
16092 return (0);
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);
16101 /* Notify VPI */
16102 rval = emlxs_vpi_event(port, FCF_EVENT_RPI_ONLINE, rpip);
16104 return (rval);
16106 } /* emlxs_rpi_online_action() */