1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at
9 * http://www.opensource.org/licenses/cddl1.txt.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2004-2012 Emulex. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <emlxs.h>
28
29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30 EMLXS_MSG_DEF(EMLXS_FCF_C);
31
32 /*
33 * STATE MACHINE RULES:
34 *
35 * - State change requests to an XXXX object when operating within
36 * an emlxs_XXXX state management function must be made
37 * using the emlxs_XXXX_state() call.
38 *
39 * - State change requests to an XXXX object when operating outside
40 * an emlxs_XXXX state management function must be made
41 * using the emlxs_XXXX_alloc(), emlxs_XXXX_free(), emlxs_XXXX_event()
42 * or emlxs_XXXX_..._notify() calls.
43 *
44 * - emlxs_XXXX_..._notify() calls are used by routines outside
45 * this fcf module to enter the state machine.
46 *
47 * - It is forbidden to make direct calls to emlxs_XXXX_...._action()
48 * functions. Only emlxs_XXXX_action() routines may make calls to
49 * emlxs_XXXX_...._action() functions.
50 *
51 * - Its is forbidden to make direct calls to emlxs_XXXX_action().
52 * Only emlxs_XXXX_state() and emlxs_XXXX_event() routines may make
53 * calls to emlxs_XXXX_action().
54 *
55 * - The EMLXS_FCF_LOCK must be held before calling:
56 * emlxs_XXXX_state(), emlxs_XXXX_event() and emlxs_XXXX_action().
57 *
58 * - All other calls touching fcftab, fcfi, vfi, vpi, rpi objects
59 * must hold the EMLXS_FCF_LOCK to protect these objects.
60 */
61
62 /*
63 * DEBUG MESSAGE TERMINATION RULES:
64 *
65 * - A message should end in ">" if a thread operating outside the
66 * XXXX state machine enters the XXXX state machine with a call to
67 * emlxs_XXXX_event() or emlxs_XXXX_state(). This includes calls made
68 * from emlxs_..._notify(), emlxs_..._mbcmpl() and emlxs_..._timer()
69 * routines since they represent the beginnning of new threads.
70 *
71 * - A message should end in "<" if the thread is about exit
72 * an emlxs_XXXX_..._action() without previously calling the
73 * next emlxs_XXXX_state(). This includes the emlxs_XXXX_action()
74 * and emlxs_XXXX_state() routines themselves since errors
75 * in these routines represent the termination of state change
76 * thread.
77 *
78 * - A message should end in "." if none of the previous
79 * conditions apply.
80 */
81
82 /* ************************************************************************** */
83 /* FCF Generic */
84 /* ************************************************************************** */
85
86 /*
87 * EVENT ARG1
88 * --------------------------------------------
89 * FCF_EVENT_STATE_ENTER None
90 *
91 * FCF_EVENT_LINKUP None
92 * FCF_EVENT_LINKDOWN None
93 * FCF_EVENT_CVL vpi
94 * FCF_EVENT_FCFTAB_FULL None
95 * FCF_EVENT_FCF_FOUND fcf_index
96 * FCF_EVENT_FCF_LOST fcf_index
97 * FCF_EVENT_FCF_CHANGED fcf_index
98 *
99 * FCF_EVENT_FCFI_ONLINE FCFIobj_t*
100 * FCF_EVENT_FCFI_OFFLINE FCFIobj_t*
101 * FCF_EVENT_FCFI_PAUSE FCFIobj_t*
102 *
103 * FCF_EVENT_VFI_ONLINE VFIobj_t*
104 * FCF_EVENT_VFI_OFFLINE VFIobj_t*
105 * FCF_EVENT_VFI_PAUSE VFIobj_t*
106 *
107 * FCF_EVENT_VPI_ONLINE VPIobj_t*
108 * FCF_EVENT_VPI_OFFLINE VPIobj_t*
109 * FCF_EVENT_VPI_PAUSE VPIobj_t*
110 *
111 * FCF_EVENT_RPI_ONLINE RPIobj_t*
112 * FCF_EVENT_RPI_OFFLINE RPIobj_t*
113 * FCF_EVENT_RPI_PAUSE RPIobj_t*
114 * FCF_EVENT_RPI_RESUME RPIobj_t*
115 * FCF_EVENT_RPI_TIMEOUT RPIobj_t*
116 */
117
118 /* Order does not matter */
119 emlxs_table_t emlxs_fcf_event_table[] =
120 {
121 {FCF_EVENT_STATE_ENTER, "E_ENTER"},
122
123 {FCF_EVENT_SHUTDOWN, "E_SHUTDOWN"},
124 {FCF_EVENT_LINKUP, "E_LINKUP"},
125 {FCF_EVENT_LINKDOWN, "E_LINKDOWN"},
126 {FCF_EVENT_CVL, "E_CVL"},
127 {FCF_EVENT_FCFTAB_FULL, "E_TABLE_FULL"},
128 {FCF_EVENT_FCF_FOUND, "E_FCF_FOUND"},
129 {FCF_EVENT_FCF_LOST, "E_FCF_LOST"},
130 {FCF_EVENT_FCF_CHANGED, "E_FCF_CHANGED"},
131
132 {FCF_EVENT_FCFI_ONLINE, "E_FCFI_ONLINE"},
133 {FCF_EVENT_FCFI_OFFLINE, "E_FCFI_OFFLINE"},
134 {FCF_EVENT_FCFI_PAUSE, "E_FCFI_PAUSE"},
135
136 {FCF_EVENT_VFI_ONLINE, "E_VFI_ONLINE"},
137 {FCF_EVENT_VFI_OFFLINE, "E_VFI_OFFLINE"},
138 {FCF_EVENT_VFI_PAUSE, "E_VFI_PAUSE"},
139
140 {FCF_EVENT_VPI_ONLINE, "E_VPI_ONLINE"},
141 {FCF_EVENT_VPI_OFFLINE, "E_VPI_OFFLINE"},
142 {FCF_EVENT_VPI_PAUSE, "E_VPI_PAUSE"},
143
144 {FCF_EVENT_RPI_ONLINE, "E_RPI_ONLINE"},
145 {FCF_EVENT_RPI_OFFLINE, "E_RPI_OFFLINE"},
146 {FCF_EVENT_RPI_PAUSE, "E_RPI_PAUSE"},
147 {FCF_EVENT_RPI_RESUME, "E_RPI_RESUME"},
148
149 }; /* emlxs_fcf_event_table */
150
151
152 /* Order does not matter */
153 emlxs_table_t emlxs_fcf_reason_table[] =
154 {
155 {FCF_REASON_NONE, "R_NONE"},
156 {FCF_REASON_REENTER, "R_REENTER"},
157 {FCF_REASON_EVENT, "R_EVENT"},
158 {FCF_REASON_REQUESTED, "R_REQUESTED"},
159 {FCF_REASON_NO_MBOX, "R_NO_MBOX"},
160 {FCF_REASON_NO_BUFFER, "R_NO_BUFFER"},
161 {FCF_REASON_SEND_FAILED, "R_SEND_FAILED"},
162 {FCF_REASON_MBOX_FAILED, "R_MBOX_FAILED"},
163 {FCF_REASON_MBOX_BUSY, "R_MBOX_BUSY"},
164 {FCF_REASON_NO_FCFI, "R_NO_FCFI"},
165 {FCF_REASON_NO_VFI, "R_NO_VFI"},
166 {FCF_REASON_ONLINE_FAILED, "R_ONLINE_FAILED"},
167 {FCF_REASON_OFFLINE_FAILED, "R_OFFLINE_FAILED"},
168 {FCF_REASON_OP_FAILED, "R_OP_FAILED"},
169 {FCF_REASON_NO_PKT, "R_NO_PKT"},
170 {FCF_REASON_NO_NODE, "R_NO_NODE"},
171 {FCF_REASON_NOT_ALLOWED, "R_NOT_ALLOWED"},
172 {FCF_REASON_UNUSED, "R_UNUSED"},
173 {FCF_REASON_INVALID, "R_INVALID"},
174
175 }; /* emlxs_fcf_reason_table */
176
177
178 /* ********************************************************************** */
179 /* FCFTAB Generic */
180 /* ********************************************************************** */
181 static char *emlxs_fcftab_state_xlate(emlxs_port_t *port,
182 uint32_t state);
183 static uint32_t emlxs_fcftab_event(emlxs_port_t *port, uint32_t evt,
184 void *arg1);
185 static uint32_t emlxs_fcftab_shutdown_action(emlxs_port_t *port,
186 uint32_t evt, void *arg1);
187
188 /* ********************************************************************** */
189 /* FC FCFTAB */
190 /* ********************************************************************** */
191
192 /* Order does not matter */
193 emlxs_table_t emlxs_fc_fcftab_state_table[] =
194 {
195 {FC_FCFTAB_STATE_SHUTDOWN, "FCFTAB_SHUTDOWN"},
196 {FC_FCFTAB_STATE_OFFLINE, "FCFTAB_OFFLINE"},
197
198 {FC_FCFTAB_STATE_TOPO, "FCFTAB_TOPO"},
199 {FC_FCFTAB_STATE_TOPO_FAILED, "FCFTAB_TOPO_FAILED"},
200 {FC_FCFTAB_STATE_TOPO_CMPL, "FCFTAB_TOPO_CMPL"},
201
202 {FC_FCFTAB_STATE_CFGLINK, "FCFTAB_CFGLINK"},
203 {FC_FCFTAB_STATE_CFGLINK_FAILED, "FCFTAB_CFGLINK_FAILED"},
204 {FC_FCFTAB_STATE_CFGLINK_CMPL, "FCFTAB_CFGLINK_CMPL"},
205
206 {FC_FCFTAB_STATE_SPARM, "FCFTAB_SPARM"},
207 {FC_FCFTAB_STATE_SPARM_FAILED, "FCFTAB_SPARM_FAILED"},
208 {FC_FCFTAB_STATE_SPARM_CMPL, "FCFTAB_SPARM_CMPL"},
209
210 {FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
211 "FCFTAB_FCFI_OFFLINE_CMPL"},
212 {FC_FCFTAB_STATE_FCFI_OFFLINE, "FCFTAB_FCFI_OFFLINE"},
213
214 {FC_FCFTAB_STATE_FCFI_ONLINE, "FCFTAB_FCFI_ONLINE"},
215 {FC_FCFTAB_STATE_FCFI_ONLINE_CMPL, "FCFTAB_FCFI_ONLINE_CMPL"},
216
217 {FC_FCFTAB_STATE_ONLINE, "FCFTAB_ONLINE"},
218
219 }; /* emlxs_fc_fcftab_state_table */
220
221 static void emlxs_fc_fcftab_online_timer(emlxs_hba_t *hba);
222
223 static uint32_t emlxs_fc_fcftab_offline_action(emlxs_port_t *port,
224 uint32_t evt, void *arg1);
225 static uint32_t emlxs_fc_fcftab_online_action(emlxs_port_t *port,
226 uint32_t evt, void *arg1);
227
228 static uint32_t emlxs_fc_fcftab_topo_cmpl_action(emlxs_port_t *port,
229 uint32_t evt, void *arg1);
230 static uint32_t emlxs_fc_fcftab_topo_failed_action(emlxs_port_t *port,
231 uint32_t evt, void *arg1);
232 static uint32_t emlxs_fc_fcftab_topo_action(emlxs_port_t *port,
233 uint32_t evt, void *arg1);
234
235 static uint32_t emlxs_fc_fcftab_cfglink_cmpl_action(emlxs_port_t *port,
236 uint32_t evt, void *arg1);
237 static uint32_t emlxs_fc_fcftab_cfglink_failed_action(emlxs_port_t *port,
238 uint32_t evt, void *arg1);
239 static uint32_t emlxs_fc_fcftab_cfglink_action(emlxs_port_t *port,
240 uint32_t evt, void *arg1);
241
242 static uint32_t emlxs_fc_fcftab_sparm_cmpl_action(emlxs_port_t *port,
243 uint32_t evt, void *arg1);
244 static uint32_t emlxs_fc_fcftab_sparm_failed_action(emlxs_port_t *port,
245 uint32_t evt, void *arg1);
246 static uint32_t emlxs_fc_fcftab_sparm_action(emlxs_port_t *port,
247 uint32_t evt, void *arg1);
248
249 static uint32_t emlxs_fc_fcftab_linkup_evt_action(emlxs_port_t *port,
250 uint32_t evt, void *arg1);
251 static uint32_t emlxs_fc_fcftab_linkdown_evt_action(emlxs_port_t *port,
252 uint32_t evt, void *arg1);
253
254 static uint32_t emlxs_fc_fcftab_fcfi_online_evt_action(emlxs_port_t *port,
255 uint32_t evt, void *arg1);
256 static uint32_t emlxs_fc_fcftab_fcfi_offline_evt_action(emlxs_port_t *port,
257 uint32_t evt, void *arg1);
258
259 static uint32_t emlxs_fc_fcftab_shutdown_evt_action(emlxs_port_t *port,
260 uint32_t evt, void *arg1);
261 static uint32_t emlxs_fc_fcftab_fcfi_offline_action(emlxs_port_t *port,
262 uint32_t evt, void *arg1);
263 static uint32_t emlxs_fc_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port,
264 uint32_t evt, void *arg1);
265 static uint32_t emlxs_fc_fcftab_fcfi_online_action(emlxs_port_t *port,
266 uint32_t evt, void *arg1);
267 static uint32_t emlxs_fc_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port,
268 uint32_t evt, void *arg1);
269
270 static char *emlxs_fc_fcftab_state_xlate(uint32_t state);
271 static uint32_t emlxs_fc_fcftab_event(emlxs_port_t *port,
272 uint32_t evt, void *arg1);
273 static uint32_t emlxs_fc_fcftab_req_handler(emlxs_port_t *port, void *arg1);
274
275 /*
276 * - Online sequencing can start from FC_FCFTAB_STATE_OFFLINE state
277 *
278 * - Offline sequencing can interrupt the online sequencing at the
279 * entry of the next wait state.
280 *
281 * NORMAL ONLINE SEQ
282 * ---------------------------
283 * LINK_UP event <-- Adapter
284 * FC_FCFTAB_STATE_OFFLINE
285 * FC_FCFTAB_STATE_TOPO
286 * FC_FCFTAB_STATE_TOPO_CMPL
287 * FC_FCFTAB_STATE_CFGLINK
288 * FC_FCFTAB_STATE_CFGLINK_CMPL
289 * FC_FCFTAB_STATE_SPARM
290 * FC_FCFTAB_STATE_SPARM_CMPL
291 * FC_FCFTAB_STATE_FCFI_ONLINE
292 * FC_FCFTAB_STATE_FCFI_ONLINE_CMPL
293 * FC_FCFTAB_STATE_ONLINE
294 *
295 *
296 * NORMAL OFFLINE SEQ
297 * ---------------------------
298 * LINK_DOWN event <-- Adapter
299 * FC_FCFTAB_STATE_ONLINE
300 * FC_FCFTAB_STATE_FCFI_OFFLINE
301 * FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL
302 * FC_FCFTAB_STATE_OFFLINE
303 *
304 */
305 /* Order does matter */
306 static void *emlxs_fc_fcftab_action_table[] =
307 {
308 /* Action routine Event */
309 /* FC_FCFTAB_STATE_SHUTDOWN 0 (Requires adapter reset) */
310 (void *) emlxs_fcftab_shutdown_action, /* STATE_ENTER */
311 (void *) NULL, /* SHUTDOWN */
312 (void *) NULL, /* LINK_UP */
313 (void *) NULL, /* LINK_DOWN */
314 (void *) NULL, /* FCFI_ONLINE */
315 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
316
317 /* FC_FCFTAB_STATE_OFFLINE 1 (Wait for LINK_UP event) */
318 (void *) emlxs_fc_fcftab_offline_action, /* STATE_ENTER */
319 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
320 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
321 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
322 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
323 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
324
325
326 /* FC_FCFTAB_STATE_TOPO 2 (Wait for topo mbcmpl) */
327 (void *) emlxs_fc_fcftab_topo_action, /* STATE_ENTER */
328 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
329 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
330 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
331 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
332 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
333
334 /* FC_FCFTAB_STATE_TOPO_FAILED 3 (Transitional) */
335 (void *) emlxs_fc_fcftab_topo_failed_action, /* STATE_ENTER */
336 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
337 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
338 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
339 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
340 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
341
342 /* FC_FCFTAB_STATE_TOPO_CMPL 4 (Transitional) */
343 (void *) emlxs_fc_fcftab_topo_cmpl_action, /* STATE_ENTER */
344 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
345 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
346 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
347 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
348 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
349
350
351 /* FC_FCFTAB_STATE_CFGLINK 5 (Wait for cfglink mbcmpl) */
352 (void *) emlxs_fc_fcftab_cfglink_action, /* STATE_ENTER */
353 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
354 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
355 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
356 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
357 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
358
359 /* FC_FCFTAB_STATE_CFGLINK_FAILED 6 (Transitional) */
360 (void *) emlxs_fc_fcftab_cfglink_failed_action, /* STATE_ENTER */
361 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
362 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
363 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
364 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
365 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
366
367 /* FC_FCFTAB_STATE_CFGLINK_CMPL 7 (Transitional) */
368 (void *) emlxs_fc_fcftab_cfglink_cmpl_action, /* STATE_ENTER */
369 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
370 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
371 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
372 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
373 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
374
375
376 /* FC_FCFTAB_STATE_SPARM 8 (Wait for sparm mbcmpl) */
377 (void *) emlxs_fc_fcftab_sparm_action, /* STATE_ENTER */
378 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
379 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
380 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
381 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
382 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
383
384 /* FC_FCFTAB_STATE_SPARM_FAILED 9 (Transitional) */
385 (void *) emlxs_fc_fcftab_sparm_failed_action, /* STATE_ENTER */
386 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
387 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
388 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
389 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
390 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
391
392 /* FC_FCFTAB_STATE_SPARM_CMPL 10 (Transitional) */
393 (void *) emlxs_fc_fcftab_sparm_cmpl_action, /* STATE_ENTER */
394 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
395 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
396 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
397 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
398 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
399
400
401 /* FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL 11 (Transitional) */
402 (void *) emlxs_fc_fcftab_fcfi_offline_cmpl_action, /* STATE_ENTER */
403 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
404 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
405 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
406 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
407 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
408
409 /* FC_FCFTAB_STATE_FCFI_OFFLINE 12 (Wait for FCFI_OFFLINE event) */
410 (void *) emlxs_fc_fcftab_fcfi_offline_action, /* STATE_ENTER */
411 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
412 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
413 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
414 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
415 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
416
417
418 /* FC_FCFTAB_STATE_FCFI_ONLINE 13 (Wait for FCFI_ONLINE event) */
419 (void *) emlxs_fc_fcftab_fcfi_online_action, /* STATE_ENTER */
420 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
421 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
422 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
423 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
424 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
425
426 /* FC_FCFTAB_STATE_FCFI_ONLINE_CMPL 14 (Transitional) */
427 (void *) emlxs_fc_fcftab_fcfi_online_cmpl_action, /* STATE_ENTER */
428 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
429 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
430 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
431 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
432 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
433
434
435 /* FC_FCFTAB_STATE_ONLINE 15 (Wait for LINK_DOWN evt) */
436 (void *) emlxs_fc_fcftab_online_action, /* STATE_ENTER */
437 (void *) emlxs_fc_fcftab_shutdown_evt_action, /* SHUTDOWN */
438 (void *) emlxs_fc_fcftab_linkup_evt_action, /* LINK_UP */
439 (void *) emlxs_fc_fcftab_linkdown_evt_action, /* LINK_DOWN */
440 (void *) emlxs_fc_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
441 (void *) emlxs_fc_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
442
443 }; /* emlxs_fc_fcftab_action_table[] */
444 #define FC_FCFTAB_ACTION_EVENTS 6
445 #define FC_FCFTAB_ACTION_STATES \
446 (sizeof (emlxs_fc_fcftab_action_table)/ \
447 (FC_FCFTAB_ACTION_EVENTS * sizeof (void *)))
448
449
450 /* ********************************************************************** */
451 /* FCOE FCFTAB */
452 /* ********************************************************************** */
453
454 /* Order does not matter */
455 emlxs_table_t emlxs_fcoe_fcftab_state_table[] =
456 {
457 {FCOE_FCFTAB_STATE_SHUTDOWN, "FCFTAB_SHUTDOWN"},
458 {FCOE_FCFTAB_STATE_OFFLINE, "FCFTAB_OFFLINE"},
459
460 {FCOE_FCFTAB_STATE_SOLICIT, "FCFTAB_SOLICIT"},
461 {FCOE_FCFTAB_STATE_SOLICIT_FAILED, "FCFTAB_SOLICIT_FAILED"},
462 {FCOE_FCFTAB_STATE_SOLICIT_CMPL, "FCFTAB_SOLICIT_CMPL"},
463
464 {FCOE_FCFTAB_STATE_READ, "FCFTAB_READ"},
465 {FCOE_FCFTAB_STATE_READ_FAILED, "FCFTAB_READ_FAILED"},
466 {FCOE_FCFTAB_STATE_READ_CMPL, "FCFTAB_READ_CMPL"},
467
468 {FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
469 "FCFTAB_FCFI_OFFLINE_CMPL"},
470 {FCOE_FCFTAB_STATE_FCFI_OFFLINE, "FCFTAB_FCFI_OFFLINE"},
471
472 {FCOE_FCFTAB_STATE_FCFI_ONLINE, "FCFTAB_FCFI_ONLINE"},
473 {FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL,
474 "FCFTAB_FCFI_ONLINE_CMPL"},
475
476 {FCOE_FCFTAB_STATE_ONLINE, "FCFTAB_ONLINE"},
477
478 }; /* emlxs_fcoe_fcftab_state_table */
479
480 static uint32_t emlxs_fcoe_fcftab_sol_cmpl_action(emlxs_port_t *port,
481 uint32_t evt, void *arg1);
482 static uint32_t emlxs_fcoe_fcftab_sol_failed_action(emlxs_port_t *port,
483 uint32_t evt, void *arg1);
484 static uint32_t emlxs_fcoe_fcftab_sol_action(emlxs_port_t *port,
485 uint32_t evt, void *arg1);
486 static uint32_t emlxs_fcoe_fcftab_shutdown_evt_action(emlxs_port_t *port,
487 uint32_t evt, void *arg1);
488 static uint32_t emlxs_fcoe_fcftab_linkdown_evt_action(emlxs_port_t *port,
489 uint32_t evt, void *arg1);
490 static uint32_t emlxs_fcoe_fcftab_read_action(emlxs_port_t *port,
491 uint32_t evt, void *arg1);
492 static uint32_t emlxs_fcoe_fcftab_read_failed_action(emlxs_port_t *port,
493 uint32_t evt, void *arg1);
494 static uint32_t emlxs_fcoe_fcftab_read_cmpl_action(emlxs_port_t *port,
495 uint32_t evt, void *arg1);
496 static uint32_t emlxs_fcoe_fcftab_fcfi_online_action(emlxs_port_t *port,
497 uint32_t evt, void *arg1);
498 static uint32_t emlxs_fcoe_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port,
499 uint32_t evt, void *arg1);
500 static uint32_t emlxs_fcoe_fcftab_fcfi_offline_action(emlxs_port_t *port,
501 uint32_t evt, void *arg1);
502 static uint32_t emlxs_fcoe_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port,
503 uint32_t evt, void *arg1);
504 static uint32_t emlxs_fcoe_fcftab_found_evt_action(emlxs_port_t *port,
505 uint32_t evt, void *arg1);
506 static uint32_t emlxs_fcoe_fcftab_lost_evt_action(emlxs_port_t *port,
507 uint32_t evt, void *arg1);
508 static uint32_t emlxs_fcoe_fcftab_changed_evt_action(emlxs_port_t *port,
509 uint32_t evt, void *arg1);
510 static uint32_t emlxs_fcoe_fcftab_full_evt_action(emlxs_port_t *port,
511 uint32_t evt, void *arg1);
512 static uint32_t emlxs_fcoe_fcftab_linkup_evt_action(emlxs_port_t *port,
513 uint32_t evt, void *arg1);
514 static uint32_t emlxs_fcoe_fcftab_cvl_evt_action(emlxs_port_t *port,
515 uint32_t evt, void *arg1);
516 static uint32_t emlxs_fcoe_fcftab_online_action(emlxs_port_t *port,
517 uint32_t evt, void *arg1);
518 static uint32_t emlxs_fcoe_fcftab_offline_action(emlxs_port_t *port,
519 uint32_t evt, void *arg1);
520 static uint32_t emlxs_fcoe_fcftab_fcfi_offline_evt_action(emlxs_port_t *port,
521 uint32_t evt, void *arg1);
522 static uint32_t emlxs_fcoe_fcftab_fcfi_online_evt_action(emlxs_port_t *port,
523 uint32_t evt, void *arg1);
524
525 static void emlxs_fcoe_fcftab_read_timer(emlxs_hba_t *hba);
526 static void emlxs_fcoe_fcftab_sol_timer(emlxs_hba_t *hba);
527 static void emlxs_fcoe_fcftab_offline_timer(emlxs_hba_t *hba);
528 static char *emlxs_fcoe_fcftab_state_xlate(uint32_t state);
529 static uint32_t emlxs_fcoe_fcftab_event(emlxs_port_t *port,
530 uint32_t evt, void *arg1);
531 static uint32_t emlxs_fcoe_fcftab_state(emlxs_port_t *port, uint16_t state,
532 uint16_t reason, uint32_t explain, void *arg1);
533
534 /*
535 * - Online sequencing can start from FCOE_FCFTAB_STATE_OFFLINE state
536 *
537 * - Offline sequencing can interrupt the online sequencing at the
538 * entry of the next wait state.
539 *
540 * NORMAL ONLINE SEQ
541 * ---------------------------
542 * LINK_UP event <-- Adapter
543 * FCOE_FCFTAB_STATE_OFFLINE
544 * FCOE_FCFTAB_STATE_SOLICIT
545 * FCOE_FCFTAB_STATE_SOLICIT_CMPL
546 * FCOE_FCFTAB_STATE_READ
547 * FCOE_FCFTAB_STATE_READ_CMPL
548 * FCOE_FCFTAB_STATE_FCFI_OFFLINE
549 * FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL
550 * FCOE_FCFTAB_STATE_FCFI_ONLINE
551 * FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL
552 * FCOE_FCFTAB_STATE_ONLINE
553 *
554 *
555 * NORMAL OFFLINE SEQ
556 * ---------------------------
557 * LINK_DOWN event <-- Adapter
558 * FCOE_FCFTAB_STATE_ONLINE
559 * FCOE_FCFTAB_STATE_FCFI_OFFLINE
560 * FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL
561 * FCOE_FCFTAB_STATE_OFFLINE
562 *
563 */
564 /* Order does matter */
565 static void *emlxs_fcoe_fcftab_action_table[] =
566 {
567 /* Action routine Event */
568 /* FCOE_FCFTAB_STATE_SHUTDOWN 0 (Requires adapter reset) */
569 (void *) emlxs_fcftab_shutdown_action, /* STATE_ENTER */
570 (void *) NULL, /* SHUTDOWN */
571 (void *) NULL, /* LINK_UP */
572 (void *) NULL, /* LINK_DOWN */
573 (void *) NULL, /* CVL_RECD */
574 (void *) NULL, /* FCF_FOUND */
575 (void *) NULL, /* FCF_LOST */
576 (void *) NULL, /* FCF_CHANGED */
577 (void *) NULL, /* TABLE_FULL */
578 (void *) NULL, /* FCFI_ONLINE */
579 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
580
581 /* FCOE_FCFTAB_STATE_OFFLINE 1 (Wait for LINK_UP event) */
582 (void *) emlxs_fcoe_fcftab_offline_action, /* STATE_ENTER */
583 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
584 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
585 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
586 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
587 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
588 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
589 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
590 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
591 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
592 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
593
594
595 /* FCOE_FCFTAB_STATE_SOLICIT 2 (Wait on fcf_solicit cmpl) */
596 (void *) emlxs_fcoe_fcftab_sol_action, /* STATE_ENTER */
597 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
598 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
599 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
600 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
601 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
602 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
603 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
604 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
605 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
606 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
607
608 /* FCOE_FCFTAB_STATE_SOLICIT_FAILED 3 (Transitional) */
609 (void *) emlxs_fcoe_fcftab_sol_failed_action, /* STATE_ENTER */
610 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
611 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
612 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
613 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
614 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
615 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
616 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
617 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
618 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
619 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
620
621 /* FCOE_FCFTAB_STATE_SOLICIT_CMPL 4 (Wait on fcf timer cmpl) */
622 (void *) emlxs_fcoe_fcftab_sol_cmpl_action, /* STATE_ENTER */
623 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
624 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
625 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
626 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
627 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
628 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
629 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
630 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
631 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
632 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
633
634
635 /* FCOE_FCFTAB_STATE_READ 5 (Wait on fcf_read cmpl) */
636 (void *) emlxs_fcoe_fcftab_read_action, /* STATE_ENTER */
637 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
638 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
639 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
640 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
641 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
642 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
643 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
644 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
645 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
646 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
647
648 /* FCOE_FCFTAB_STATE_READ_FAILED 6 (Transitional) */
649 (void *) emlxs_fcoe_fcftab_read_failed_action, /* STATE_ENTER */
650 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
651 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
652 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
653 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
654 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
655 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
656 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
657 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
658 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
659 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
660
661 /* FCOE_FCFTAB_STATE_READ_CMPL 7 (Transitional) */
662 (void *) emlxs_fcoe_fcftab_read_cmpl_action, /* STATE_ENTER */
663 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
664 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
665 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
666 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
667 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
668 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
669 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
670 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
671 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
672 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
673
674
675 /* FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL 8 (Transitional) */
676 (void *) emlxs_fcoe_fcftab_fcfi_offline_cmpl_action, /* STATE_ENTER */
677 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
678 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
679 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
680 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
681 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
682 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
683 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
684 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
685 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
686 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
687
688 /* FCOE_FCFTAB_STATE_FCFI_OFFLINE 9 (Wait for FCFI_OFFLINE event) */
689 (void *) emlxs_fcoe_fcftab_fcfi_offline_action, /* STATE_ENTER */
690 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
691 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
692 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
693 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
694 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
695 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
696 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
697 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
698 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
699 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
700
701
702 /* FCOE_FCFTAB_STATE_FCFI_ONLINE 10 (Wait on FCFI_ONLINE event) */
703 (void *) emlxs_fcoe_fcftab_fcfi_online_action, /* STATE_ENTER */
704 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
705 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
706 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
707 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
708 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
709 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
710 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
711 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
712 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
713 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
714
715 /* FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL 11 (Transitional) */
716 (void *) emlxs_fcoe_fcftab_fcfi_online_cmpl_action, /* STATE_ENTER */
717 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
718 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
719 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
720 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
721 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
722 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
723 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
724 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
725 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
726 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
727
728
729 /* FCOE_FCFTAB_STATE_ONLINE 12 (Wait for LINK_DOWN event) */
730 (void *) emlxs_fcoe_fcftab_online_action, /* STATE_ENTER */
731 (void *) emlxs_fcoe_fcftab_shutdown_evt_action, /* SHUTDOWN */
732 (void *) emlxs_fcoe_fcftab_linkup_evt_action, /* LINK_UP */
733 (void *) emlxs_fcoe_fcftab_linkdown_evt_action, /* LINK_DOWN */
734 (void *) emlxs_fcoe_fcftab_cvl_evt_action, /* CVL_RECD */
735 (void *) emlxs_fcoe_fcftab_found_evt_action, /* FCF_FOUND */
736 (void *) emlxs_fcoe_fcftab_lost_evt_action, /* FCF_LOST */
737 (void *) emlxs_fcoe_fcftab_changed_evt_action, /* FCF_CHANGED */
738 (void *) emlxs_fcoe_fcftab_full_evt_action, /* TABLE_FULL */
739 (void *) emlxs_fcoe_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */
740 (void *) emlxs_fcoe_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */
741
742 }; /* emlxs_fcoe_fcftab_action_table[] */
743 #define FCOE_FCFTAB_ACTION_EVENTS 11
744 #define FCOE_FCFTAB_ACTION_STATES \
745 (sizeof (emlxs_fcoe_fcftab_action_table)/ \
746 (FCOE_FCFTAB_ACTION_EVENTS * sizeof (void *)))
747
748
749
750
751 /* ********************************************************************** */
752 /* FCFI */
753 /* ********************************************************************** */
754
755 /* Order does not matter */
756 emlxs_table_t emlxs_fcfi_state_table[] =
757 {
758 {FCFI_STATE_FREE, "FCFI_FREE"},
759
760 {FCFI_STATE_OFFLINE, "FCFI_OFFLINE"},
761
762 {FCFI_STATE_UNREG_CMPL, "FCFI_UNREG_CMPL"},
763 {FCFI_STATE_UNREG_FAILED, "FCFI_UNREG_FAILED"},
764 {FCFI_STATE_UNREG, "FCFI_UNREG"},
765
766 {FCFI_STATE_REG, "FCFI_REG"},
767 {FCFI_STATE_REG_FAILED, "FCFI_REG_FAILED"},
768 {FCFI_STATE_REG_CMPL, "FCFI_REG_CMPL"},
769
770 {FCFI_STATE_VFI_OFFLINE_CMPL, "FCFI_VFI_OFFLINE_CMPL"},
771 {FCFI_STATE_VFI_OFFLINE, "FCFI_VFI_OFFLINE"},
772
773 {FCFI_STATE_VFI_ONLINE, "FCFI_VFI_ONLINE"},
774 {FCFI_STATE_VFI_ONLINE_CMPL, "FCFI_VFI_ONLINE_CMPL"},
775
776 {FCFI_STATE_PAUSED, "FCFI_PAUSED"},
777 {FCFI_STATE_ONLINE, "FCFI_ONLINE"},
778
779 }; /* emlxs_fcfi_state_table */
780
781
782 static uint32_t emlxs_fcfi_free_action(emlxs_port_t *port,
783 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
784 static uint32_t emlxs_fcfi_online_evt_action(emlxs_port_t *port,
785 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
786 static uint32_t emlxs_fcfi_offline_evt_action(emlxs_port_t *port,
787 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
788 static uint32_t emlxs_fcfi_pause_evt_action(emlxs_port_t *port,
789 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
790 static uint32_t emlxs_fcfi_reg_action(emlxs_port_t *port,
791 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
792 static uint32_t emlxs_fcfi_unreg_action(emlxs_port_t *port,
793 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
794 static uint32_t emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port,
795 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
796 static uint32_t emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port,
797 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
798 static uint32_t emlxs_fcfi_vfi_online_action(emlxs_port_t *port,
799 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
800 static uint32_t emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port,
801 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
802 static uint32_t emlxs_fcfi_reg_failed_action(emlxs_port_t *port,
803 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
804 static uint32_t emlxs_fcfi_unreg_failed_action(emlxs_port_t *port,
805 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
806 static uint32_t emlxs_fcfi_vfi_offline_action(emlxs_port_t *port,
807 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
808 static uint32_t emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port,
809 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
810 static uint32_t emlxs_fcfi_online_action(emlxs_port_t *port,
811 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
812 static uint32_t emlxs_fcfi_paused_action(emlxs_port_t *port,
813 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
814 static uint32_t emlxs_fcfi_offline_action(emlxs_port_t *port,
815 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
816 static uint32_t emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port,
817 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
818 static uint32_t emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port,
819 FCFIobj_t *fcfp, uint32_t evt, void *arg1);
820
821 static uint32_t emlxs_fcfi_event(emlxs_port_t *port,
822 uint32_t evt, void *arg1);
823 static FCFIobj_t *emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec,
824 uint32_t *fcf_index);
825 static FCFIobj_t *emlxs_fcfi_alloc(emlxs_port_t *port);
826 static uint32_t emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp);
827 static void emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp,
828 FCF_RECORD_t *fcf_rec, uint32_t event_tag);
829 static char *emlxs_fcfi_state_xlate(uint32_t state);
830
831 /*
832 * - Online sequencing can start from FCFI_STATE_OFFLINE state or
833 * the FCFI_STATE_VFI_OFFLINE state.
834 *
835 * - Offline sequencing can interrupt the online sequencing at the
836 * entry of the next wait state.
837 *
838 * NORMAL ONLINE SEQ
839 * ---------------------------
840 * FCFI_ONLINE event <-- FCFTAB
841 * FCFI_STATE_OFFLINE
842 * FCFI_STATE_REG
843 * FCFI_STATE_REG_CMPL
844 * FCFI_STATE_VFI_ONLINE
845 * FCFI_STATE_VFI_ONLINE_CMPL
846 * FCFI_STATE_ONLINE
847 * FCFI_ONLINE event-->FCFTAB
848 *
849 *
850 * NORMAL OFFLINE SEQ
851 * ---------------------------
852 * FCFI_OFFLINE event <-- FCFTAB
853 * FCFI_STATE_ONLINE
854 * FCFI_STATE_VFI_OFFLINE
855 * FCFI_STATE_VFI_OFFLINE_CMPL
856 * FCFI_STATE_UNREG
857 * FCFI_STATE_UNREG_CMPL
858 * FCFI_STATE_OFFLINE
859 * FCFI_OFFLINE event-->FCFTAB
860 *
861 *
862 * NORMAL PAUSE SEQ
863 * ---------------------------
864 * FCFI_PAUSE event <-- FCFTAB
865 * FCFI_STATE_ONLINE
866 * FCFI_STATE_PAUSED
867 *
868 */
869 /* Order does matter */
870 static void *emlxs_fcfi_action_table[] =
871 {
872 /* Action routine Event */
873 /* FCFI_STATE_FREE 0 (Wait for allocation) */
874 (void *) emlxs_fcfi_free_action, /* STATE_ENTER */
875 (void *) NULL, /* FCFI_ONLINE */
876 (void *) NULL, /* FCFI_OFFLINE */
877 (void *) NULL, /* FCFI_PAUSE */
878 (void *) NULL, /* VFI_ONLINE */
879 (void *) NULL, /* VFI_OFFLINE */
880
881 /* FCFI_STATE_OFFLINE 1 (Wait for FCFI_ONLINE event) */
882 (void *) emlxs_fcfi_offline_action, /* STATE_ENTER */
883 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
884 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
885 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
886 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
887 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
888
889 /* FCFI_STATE_UNREG_CMPL 2 (Transitional) */
890 (void *) emlxs_fcfi_unreg_cmpl_action, /* STATE_ENTER */
891 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
892 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
893 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
894 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
895 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
896
897 /* FCFI_STATE_UNREG_FAILED 3 (Transitional) */
898 (void *) emlxs_fcfi_unreg_failed_action, /* STATE_ENTER */
899 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
900 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
901 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
902 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
903 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
904
905 /* FCFI_STATE_UNREG 4 (Wait for unreg_fcfi cmpl) */
906 (void *) emlxs_fcfi_unreg_action, /* STATE_ENTER */
907 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
908 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
909 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
910 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
911 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
912
913 /* FCFI_STATE_REG 5 (Wait for reg_fcfi cmpl) */
914 (void *) emlxs_fcfi_reg_action, /* STATE_ENTER */
915 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
916 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
917 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
918 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
919 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
920
921 /* FCFI_STATE_REG_FAILED 6 (Transitional) */
922 (void *) emlxs_fcfi_reg_failed_action, /* STATE_ENTER */
923 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
924 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
925 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
926 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
927 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
928
929 /* FCFI_STATE_REG_CMPL 7 (Transitional) */
930 (void *) emlxs_fcfi_reg_cmpl_action, /* STATE_ENTER */
931 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
932 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
933 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
934 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
935 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
936
937 /* FCFI_STATE_VFI_OFFLINE_CMPL 8 (Transitional) */
938 (void *) emlxs_fcfi_vfi_offline_cmpl_action, /* STATE_ENTER */
939 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
940 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
941 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
942 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
943 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
944
945 /* FCFI_STATE_VFI_OFFLINE 9 (Wait for VFI_OFFLINE event) */
946 (void *) emlxs_fcfi_vfi_offline_action, /* STATE_ENTER */
947 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
948 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
949 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
950 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
951 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE * */
952
953 /* FCFI_STATE_VFI_ONLINE 10 (Wait for VFI_ONLINE event) */
954 (void *) emlxs_fcfi_vfi_online_action, /* STATE_ENTER */
955 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
956 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
957 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
958 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
959 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
960
961 /* FCFI_STATE_VFI_ONLINE_CMPL 11 (Transitional) */
962 (void *) emlxs_fcfi_vfi_online_cmpl_action, /* STATE_ENTER */
963 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
964 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
965 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
966 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
967 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
968
969
970 /* FCFI_STATE_PAUSED 12 (Wait for FCFI_ONLINE event) */
971 (void *) emlxs_fcfi_paused_action, /* STATE_ENTER */
972 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
973 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
974 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
975 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
976 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
977
978 /* FCFI_STATE_ONLINE 13 (Wait for FCFI_OFFLINE event) */
979 (void *) emlxs_fcfi_online_action, /* STATE_ENTER */
980 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */
981 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */
982 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */
983 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */
984 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */
985
986 }; /* emlxs_fcfi_action_table[] */
987 #define FCFI_ACTION_EVENTS 6
988 #define FCFI_ACTION_STATES \
989 (sizeof (emlxs_fcfi_action_table)/ \
990 (FCFI_ACTION_EVENTS * sizeof (void *)))
991
992
993 /* ********************************************************************** */
994 /* VFI */
995 /* ********************************************************************** */
996
997 /* Order does not matter */
998 emlxs_table_t emlxs_vfi_state_table[] =
999 {
1000 {VFI_STATE_OFFLINE, "VFI_OFFLINE"},
1001
1002 {VFI_STATE_INIT, "VFI_INIT"},
1003 {VFI_STATE_INIT_FAILED, "VFI_INIT_FAILED"},
1004 {VFI_STATE_INIT_CMPL, "VFI_INIT_CMPL"},
1005
1006 {VFI_STATE_VPI_OFFLINE_CMPL, "VFI_VPI_OFFLINE_CMPL"},
1007 {VFI_STATE_VPI_OFFLINE, "VFI_VPI_OFFLINE"},
1008
1009 {VFI_STATE_VPI_ONLINE, "VFI_VPI_ONLINE"},
1010 {VFI_STATE_VPI_ONLINE_CMPL, "VFI_VPI_ONLINE_CMPL"},
1011
1012 {VFI_STATE_UNREG_CMPL, "VFI_UNREG_CMPL"},
1013 {VFI_STATE_UNREG_FAILED, "VFI_UNREG_FAILED"},
1014 {VFI_STATE_UNREG, "VFI_UNREG"},
1015
1016 {VFI_STATE_REG, "VFI_REG"},
1017 {VFI_STATE_REG_FAILED, "VFI_REG_FAILED"},
1018 {VFI_STATE_REG_CMPL, "VFI_REG_CMPL"},
1019
1020 {VFI_STATE_PAUSED, "VFI_PAUSED"},
1021 {VFI_STATE_ONLINE, "VFI_ONLINE"},
1022
1023 }; /* emlxs_vfi_state_table */
1024
1025
1026 static uint32_t emlxs_vfi_pause_evt_action(emlxs_port_t *port,
1027 VFIobj_t *vfip, uint32_t evt, void *arg1);
1028 static uint32_t emlxs_vfi_online_evt_action(emlxs_port_t *port,
1029 VFIobj_t *vfip, uint32_t evt, void *arg1);
1030 static uint32_t emlxs_vfi_offline_evt_action(emlxs_port_t *port,
1031 VFIobj_t *vfip, uint32_t evt, void *arg1);
1032 static uint32_t emlxs_vfi_init_action(emlxs_port_t *port,
1033 VFIobj_t *vfip, uint32_t evt, void *arg1);
1034 static uint32_t emlxs_vfi_init_failed_action(emlxs_port_t *port,
1035 VFIobj_t *vfip, uint32_t evt, void *arg1);
1036 static uint32_t emlxs_vfi_init_cmpl_action(emlxs_port_t *port,
1037 VFIobj_t *vfip, uint32_t evt, void *arg1);
1038 static uint32_t emlxs_vfi_offline_action(emlxs_port_t *port,
1039 VFIobj_t *vfip, uint32_t evt, void *arg1);
1040 static uint32_t emlxs_vfi_online_action(emlxs_port_t *port,
1041 VFIobj_t *vfip, uint32_t evt, void *arg1);
1042 static uint32_t emlxs_vfi_paused_action(emlxs_port_t *port,
1043 VFIobj_t *vfip, uint32_t evt, void *arg1);
1044 static uint32_t emlxs_vfi_vpi_online_action(emlxs_port_t *port,
1045 VFIobj_t *vfip, uint32_t evt, void *arg1);
1046 static uint32_t emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port,
1047 VFIobj_t *vfip, uint32_t evt, void *arg1);
1048 static uint32_t emlxs_vfi_vpi_offline_action(emlxs_port_t *port,
1049 VFIobj_t *vfip, uint32_t evt, void *arg1);
1050 static uint32_t emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port,
1051 VFIobj_t *vfip, uint32_t evt, void *arg1);
1052 static uint32_t emlxs_vfi_reg_action(emlxs_port_t *port,
1053 VFIobj_t *vfip, uint32_t evt, void *arg1);
1054 static uint32_t emlxs_vfi_reg_failed_action(emlxs_port_t *port,
1055 VFIobj_t *vfip, uint32_t evt, void *arg1);
1056 static uint32_t emlxs_vfi_reg_cmpl_action(emlxs_port_t *port,
1057 VFIobj_t *vfip, uint32_t evt, void *arg1);
1058 static uint32_t emlxs_vfi_unreg_action(emlxs_port_t *port,
1059 VFIobj_t *vfip, uint32_t evt, void *arg1);
1060 static uint32_t emlxs_vfi_unreg_failed_action(emlxs_port_t *port,
1061 VFIobj_t *vfip, uint32_t evt, void *arg1);
1062 static uint32_t emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port,
1063 VFIobj_t *vfip, uint32_t evt, void *arg1);
1064 static uint32_t emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port,
1065 VFIobj_t *vfip, uint32_t evt, void *arg1);
1066 static uint32_t emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port,
1067 VFIobj_t *vfip, uint32_t evt, void *arg1);
1068
1069 static uint32_t emlxs_vfi_event(emlxs_port_t *port,
1070 uint32_t evt, void *arg1);
1071
1072
1073 /*
1074 * - Online sequencing can start from VFI_STATE_OFFLINE state or
1075 * the VFI_STATE_VPI_OFFLINE state.
1076 *
1077 * - Offline sequencing can interrupt the online sequencing at the
1078 * entry of the next wait state.
1079 *
1080 * NORMAL ONLINE SEQ
1081 * ---------------------------
1082 * VFI_ONLINE event <-- FCFI
1083 * VFI_STATE_OFFLINE
1084 * VFI_STATE_INIT
1085 * VFI_STATE_INIT_CMPL
1086 * VFI_STATE_VPI_ONLINE
1087 * VFI_STATE_VPI_ONLINE_CMPL
1088 * VFI_STATE_REG
1089 * VFI_STATE_REG_CMPL
1090 * VFI_STATE_ONLINE
1091 * VFI_ONLINE event-->FCFI
1092 *
1093 *
1094 * NORMAL OFFLINE SEQ
1095 * ---------------------------
1096 * VFI_OFFLINE event <-- FCFI
1097 * VFI_STATE_ONLINE
1098 * VFI_STATE_VPI_OFFLINE
1099 * VFI_STATE_VPI_OFFLINE_CMPL
1100 * VFI_STATE_UNREG
1101 * VFI_STATE_UNREG_CMPL
1102 * VFI_STATE_OFFLINE
1103 * VFI_OFFLINE event-->FCFI
1104 *
1105 *
1106 * NORMAL PAUSE SEQ
1107 * ---------------------------
1108 * VFI_PAUSE event <-- FCFI
1109 * VFI_STATE_ONLINE
1110 * VFI_STATE_PAUSED
1111 *
1112 */
1113 /* Order does matter */
1114 static void *emlxs_vfi_action_table[] =
1115 {
1116 /* Action routine Event */
1117 /* VFI_STATE_OFFLINE 0 (Wait for VFI_ONLINE event) */
1118 (void *) emlxs_vfi_offline_action, /* STATE_ENTER */
1119 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1120 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1121 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1122 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1123 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1124
1125
1126 /* VFI_STATE_INIT 1 (Wait for init_vfi cmpl) */
1127 (void *) emlxs_vfi_init_action, /* STATE_ENTER */
1128 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1129 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1130 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1131 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1132 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1133
1134 /* VFI_STATE_INIT_FAILED 2 (Transitional) */
1135 (void *) emlxs_vfi_init_failed_action, /* STATE_ENTER */
1136 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1137 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1138 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1139 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1140 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1141
1142 /* VFI_STATE_INIT_CMPL 3 (Transitional) */
1143 (void *) emlxs_vfi_init_cmpl_action, /* STATE_ENTER */
1144 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1145 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1146 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1147 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1148 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1149
1150
1151 /* VFI_STATE_VPI_OFFLINE_CMPL 4 (Wait for VPI_OFFLINE event) */
1152 (void *) emlxs_vfi_vpi_offline_cmpl_action, /* STATE_ENTER */
1153 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1154 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1155 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1156 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1157 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1158
1159 /* VFI_STATE_VPI_OFFLINE 5 (Wait for VPI_OFFLINE event) */
1160 (void *) emlxs_vfi_vpi_offline_action, /* STATE_ENTER */
1161 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1162 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1163 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1164 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1165 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1166
1167
1168 /* VFI_STATE_VPI_ONLINE 6 (Wait for VPI_ONLINE event) */
1169 (void *) emlxs_vfi_vpi_online_action, /* STATE_ENTER */
1170 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1171 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1172 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1173 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1174 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1175
1176 /* VFI_STATE_VPI_ONLINE_CMPL 7 (Transitional) */
1177 (void *) emlxs_vfi_vpi_online_cmpl_action, /* STATE_ENTER */
1178 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1179 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1180 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1181 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1182 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1183
1184
1185 /* VFI_STATE_UNREG_CMPL 8 (Transitional) */
1186 (void *) emlxs_vfi_unreg_cmpl_action, /* STATE_ENTER */
1187 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1188 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1189 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1190 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1191 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1192
1193 /* VFI_STATE_UNREG_FAILED 9 (Transitional) */
1194 (void *) emlxs_vfi_unreg_failed_action, /* STATE_ENTER */
1195 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1196 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1197 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1198 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1199 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1200
1201 /* VFI_STATE_UNREG 10 (Wait for unreg_vfi cmpl) */
1202 (void *) emlxs_vfi_unreg_action, /* STATE_ENTER */
1203 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1204 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1205 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1206 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1207 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1208
1209
1210 /* VFI_STATE_REG 11 (Wait for reg_vfi cmpl) */
1211 (void *) emlxs_vfi_reg_action, /* STATE_ENTER */
1212 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1213 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1214 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1215 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1216 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1217
1218 /* VFI_STATE_REG_FAILED 12 (Transitional) */
1219 (void *) emlxs_vfi_reg_failed_action, /* STATE_ENTER */
1220 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1221 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1222 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1223 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1224 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1225
1226 /* VFI_STATE_REG_CMPL 13 (Transitional) */
1227 (void *) emlxs_vfi_reg_cmpl_action, /* STATE_ENTER */
1228 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1229 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1230 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1231 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1232 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1233
1234
1235 /* VFI_STATE_PAUSED 14 (Wait for VFI_OFFLINE event) */
1236 (void *) emlxs_vfi_paused_action, /* STATE_ENTER */
1237 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1238 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1239 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1240 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1241 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1242
1243 /* VFI_STATE_ONLINE 14 (Wait for VFI_OFFLINE event) */
1244 (void *) emlxs_vfi_online_action, /* STATE_ENTER */
1245 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */
1246 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */
1247 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */
1248 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */
1249 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */
1250
1251 }; /* emlxs_vfi_action_table[] */
1252 #define VFI_ACTION_EVENTS 6
1253 #define VFI_ACTION_STATES \
1254 (sizeof (emlxs_vfi_action_table)/ \
1255 (VFI_ACTION_EVENTS * sizeof (void *)))
1256
1257
1258 /* ********************************************************************** */
1259 /* VPI */
1260 /* ********************************************************************** */
1261
1262 /* Order does not matter */
1263 emlxs_table_t emlxs_vpi_state_table[] =
1264 {
1265 {VPI_STATE_OFFLINE, "VPI_OFFLINE"},
1266
1267 {VPI_STATE_INIT, "VPI_INIT"},
1268 {VPI_STATE_INIT_FAILED, "VPI_INIT_FAILED"},
1269 {VPI_STATE_INIT_CMPL, "VPI_INIT_CMPL"},
1270
1271 {VPI_STATE_UNREG_CMPL, "VPI_UNREG_CMPL"},
1272 {VPI_STATE_UNREG_FAILED, "VPI_UNREG_FAILED"},
1273 {VPI_STATE_UNREG, "VPI_UNREG"},
1274
1275 {VPI_STATE_LOGO_CMPL, "VPI_LOGO_CMPL"},
1276 {VPI_STATE_LOGO_FAILED, "VPI_LOGO_FAILED"},
1277 {VPI_STATE_LOGO, "VPI_LOGO"},
1278
1279 {VPI_STATE_PORT_OFFLINE, "VPI_PORT_OFFLINE"},
1280 {VPI_STATE_PORT_ONLINE, "VPI_PORT_ONLINE"},
1281
1282 {VPI_STATE_LOGI, "VPI_LOGI"},
1283 {VPI_STATE_LOGI_FAILED, "VPI_LOGI_FAILED"},
1284 {VPI_STATE_LOGI_CMPL, "VPI_LOGI_CMPL"},
1285
1286 {VPI_STATE_REG, "VPI_REG"},
1287 {VPI_STATE_REG_FAILED, "VPI_REG_FAILED"},
1288 {VPI_STATE_REG_CMPL, "VPI_REG_CMPL"},
1289
1290 {VPI_STATE_PAUSED, "VPI_PAUSED"},
1291 {VPI_STATE_ONLINE, "VPI_ONLINE"},
1292
1293 }; /* emlxs_vpi_state_table */
1294
1295
1296 static uint32_t emlxs_vpi_online_evt_action(emlxs_port_t *port,
1297 VPIobj_t *vpip, uint32_t evt, void *arg1);
1298 static uint32_t emlxs_vpi_offline_evt_action(emlxs_port_t *port,
1299 VPIobj_t *vpip, uint32_t evt, void *arg1);
1300 static uint32_t emlxs_vpi_pause_evt_action(emlxs_port_t *port,
1301 VPIobj_t *vpip, uint32_t evt, void *arg1);
1302 static uint32_t emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port,
1303 VPIobj_t *vpip, uint32_t evt, void *arg1);
1304 static uint32_t emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port,
1305 VPIobj_t *vpip, uint32_t evt, void *arg1);
1306 static uint32_t emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port,
1307 VPIobj_t *vpip, uint32_t evt, void *arg1);
1308
1309 static uint32_t emlxs_vpi_init_action(emlxs_port_t *port,
1310 VPIobj_t *vpip, uint32_t evt, void *arg1);
1311 static uint32_t emlxs_vpi_init_failed_action(emlxs_port_t *port,
1312 VPIobj_t *vpip, uint32_t evt, void *arg1);
1313 static uint32_t emlxs_vpi_init_cmpl_action(emlxs_port_t *port,
1314 VPIobj_t *vpip, uint32_t evt, void *arg1);
1315
1316 static uint32_t emlxs_vpi_offline_action(emlxs_port_t *port,
1317 VPIobj_t *vpip, uint32_t evt, void *arg1);
1318 static uint32_t emlxs_vpi_online_action(emlxs_port_t *port,
1319 VPIobj_t *vpip, uint32_t evt, void *arg1);
1320 static uint32_t emlxs_vpi_paused_action(emlxs_port_t *port,
1321 VPIobj_t *vpip, uint32_t evt, void *arg1);
1322
1323 static uint32_t emlxs_vpi_port_online_action(emlxs_port_t *port,
1324 VPIobj_t *vpip, uint32_t evt, void *arg1);
1325 static uint32_t emlxs_vpi_port_offline_action(emlxs_port_t *port,
1326 VPIobj_t *vpip, uint32_t evt, void *arg1);
1327
1328 static uint32_t emlxs_vpi_logi_cmpl_action(emlxs_port_t *port,
1329 VPIobj_t *vpip, uint32_t evt, void *arg1);
1330 static uint32_t emlxs_vpi_logi_failed_action(emlxs_port_t *port,
1331 VPIobj_t *vpip, uint32_t evt, void *arg1);
1332 static uint32_t emlxs_vpi_logi_action(emlxs_port_t *port,
1333 VPIobj_t *vpip, uint32_t evt, void *arg1);
1334
1335 static uint32_t emlxs_vpi_reg_action(emlxs_port_t *port,
1336 VPIobj_t *vpip, uint32_t evt, void *arg1);
1337 static uint32_t emlxs_vpi_reg_failed_action(emlxs_port_t *port,
1338 VPIobj_t *vpip, uint32_t evt, void *arg1);
1339 static uint32_t emlxs_vpi_reg_cmpl_action(emlxs_port_t *port,
1340 VPIobj_t *vpip, uint32_t evt, void *arg1);
1341
1342 static uint32_t emlxs_vpi_unreg_action(emlxs_port_t *port,
1343 VPIobj_t *vpip, uint32_t evt, void *arg1);
1344 static uint32_t emlxs_vpi_unreg_failed_action(emlxs_port_t *port,
1345 VPIobj_t *vpip, uint32_t evt, void *arg1);
1346 static uint32_t emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port,
1347 VPIobj_t *vpip, uint32_t evt, void *arg1);
1348
1349 static uint32_t emlxs_vpi_logo_action(emlxs_port_t *port,
1350 VPIobj_t *vpip, uint32_t evt, void *arg1);
1351 static uint32_t emlxs_vpi_logo_failed_action(emlxs_port_t *port,
1352 VPIobj_t *vpip, uint32_t evt, void *arg1);
1353 static uint32_t emlxs_vpi_logo_cmpl_action(emlxs_port_t *port,
1354 VPIobj_t *vpip, uint32_t evt, void *arg1);
1355
1356 static uint32_t emlxs_vpi_event(emlxs_port_t *port,
1357 uint32_t evt, void *arg1);
1358 static uint32_t emlxs_vpi_logi_cmpl_notify(emlxs_port_t *port,
1359 RPIobj_t *rpip);
1360 static void emlxs_vpi_logo_handler(emlxs_port_t *port,
1361 VPIobj_t *vpip);
1362
1363 /*
1364 * - Online sequencing can only start from VPI_STATE_OFFLINE or
1365 * VPI_STATE_PORT_OFFLINE state.
1366 *
1367 * - Offline sequencing can interrupt the online sequencing at the
1368 * entry of the next wait state.
1369 *
1370 * NORMAL ONLINE SEQ
1371 * ---------------------------
1372 * VPI_ONLINE event <-- VFI
1373 * VPI_STATE_OFFLINE
1374 * VPI_STATE_INIT
1375 * VPI_STATE_INIT_CMPL
1376 * VPI_STATE_PORT_ONLINE
1377 * VPI_STATE_LOGI
1378 * VPI_STATE_LOGI_CMPL
1379 * VPI_STATE_REG
1380 * VPI_STATE_REG_CMPL
1381 * VPI_STATE_ONLINE
1382 * VPI_ONLINE event-->VFI
1383 *
1384 *
1385 * NORMAL OFFLINE SEQ
1386 * ---------------------------
1387 * VPI_OFFLINE event <-- VFI
1388 * VPI_STATE_ONLINE
1389 * VPI_STATE_PORT_OFFLINE
1390 * VPI_STATE_LOGO
1391 * VPI_STATE_LOGO_CMPL
1392 * VPI_STATE_UNREG
1393 * VPI_STATE_UNREG_CMPL
1394 * VPI_STATE_OFFLINE
1395 * VPI_OFFLINE event-->VFI
1396 *
1397 *
1398 * NORMAL PAUSE SEQ
1399 * ---------------------------
1400 * VPI_PAUSE event <-- VFI
1401 * VPI_STATE_ONLINE
1402 * VPI_STATE_PORT_OFFLINE
1403 * VPI_STATE_PAUSED
1404 *
1405 */
1406 /* Order does matter */
1407 static void *emlxs_vpi_action_table[] =
1408 {
1409 /* Action routine Event */
1410 /* VPI_STATE_OFFLINE 0 (Wait for VPI_ONLINE event) */
1411 (void *) emlxs_vpi_offline_action, /* STATE_ENTER */
1412 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1413 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1414 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1415 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1416 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1417 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1418
1419
1420 /* VPI_STATE_INIT 1 (Wait for init_vpi cmpl) */
1421 (void *) emlxs_vpi_init_action, /* STATE_ENTER */
1422 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1423 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1424 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1425 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1426 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1427 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1428
1429 /* VPI_STATE_INIT_FAILED 2 (Transitional) */
1430 (void *) emlxs_vpi_init_failed_action, /* STATE_ENTER */
1431 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1432 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1433 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1434 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1435 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1436 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1437
1438 /* VPI_STATE_INIT_CMPL 3 (Transitional) */
1439 (void *) emlxs_vpi_init_cmpl_action, /* STATE_ENTER */
1440 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1441 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1442 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1443 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1444 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1445 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1446
1447
1448 /* VPI_STATE_UNREG_CMPL 4 (Transitional) */
1449 (void *) emlxs_vpi_unreg_cmpl_action, /* STATE_ENTER */
1450 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1451 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1452 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1453 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1454 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1455 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1456
1457 /* VPI_STATE_UNREG_FAILED 5 (Transitional) */
1458 (void *) emlxs_vpi_unreg_failed_action, /* STATE_ENTER */
1459 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1460 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1461 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1462 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1463 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1464 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1465
1466 /* VPI_STATE_UNREG 6 (Wait for unreg_vpi cmpl) */
1467 (void *) emlxs_vpi_unreg_action, /* STATE_ENTER */
1468 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1469 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1470 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1471 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1472 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1473 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1474
1475
1476 /* VPI_STATE_LOGO_CMPL 7 (Transitional) */
1477 (void *) emlxs_vpi_logo_cmpl_action, /* STATE_ENTER */
1478 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1479 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1480 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1481 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1482 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1483 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1484
1485 /* VPI_STATE_LOGO_FAILED 8 (Transitional) */
1486 (void *) emlxs_vpi_logo_failed_action, /* STATE_ENTER */
1487 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1488 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1489 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1490 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1491 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1492 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1493
1494 /* VPI_STATE_LOGO 9 (Transitional) */
1495 (void *) emlxs_vpi_logo_action, /* STATE_ENTER */
1496 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1497 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1498 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1499 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1500 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1501 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1502
1503
1504 /* VPI_STATE_PORT_OFFLINE 10 (Wait for RPI_OFFLINE or VPI_ONLINE) */
1505 (void *) emlxs_vpi_port_offline_action, /* STATE_ENTER */
1506 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1507 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1508 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1509 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1510 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1511 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1512
1513 /* VPI_STATE_PORT_ONLINE 11 (Wait for emlxs_vpi_logi_notify() ) */
1514 (void *) emlxs_vpi_port_online_action, /* STATE_ENTER */
1515 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1516 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1517 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1518 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1519 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1520 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1521
1522
1523 /* VPI_STATE_LOGI 12 (Wait for emlxs_vpi_logi_cmpl_notify() ) */
1524 (void *) emlxs_vpi_logi_action, /* STATE_ENTER */
1525 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1526 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1527 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1528 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1529 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1530 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1531
1532 /* VPI_STATE_LOGI_FAILED 13 (Transitional) */
1533 (void *) emlxs_vpi_logi_failed_action, /* STATE_ENTER */
1534 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1535 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1536 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1537 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1538 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1539 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1540
1541 /* VPI_STATE_LOGI_CMPL 14 (Transitional) */
1542 (void *) emlxs_vpi_logi_cmpl_action, /* STATE_ENTER */
1543 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1544 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1545 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1546 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1547 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1548 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1549
1550
1551 /* VPI_STATE_REG 15 (Wait for reg_vpi cmpl) */
1552 (void *) emlxs_vpi_reg_action, /* STATE_ENTER */
1553 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1554 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1555 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1556 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1557 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1558 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1559
1560 /* VPI_STATE_REG_FAILED 16 (Transitional) */
1561 (void *) emlxs_vpi_reg_failed_action, /* STATE_ENTER */
1562 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1563 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1564 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1565 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1566 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1567 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1568
1569 /* VPI_STATE_REG_CMPL 17 (Transitional) */
1570 (void *) emlxs_vpi_reg_cmpl_action, /* STATE_ENTER */
1571 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1572 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1573 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1574 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1575 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1576 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1577
1578
1579 /* VPI_STATE_PAUSED 18 (Wait for VPI_ONLINE() ) */
1580 (void *) emlxs_vpi_paused_action, /* STATE_ENTER */
1581 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1582 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1583 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1584 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1585 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1586 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1587
1588 /* VPI_STATE_ONLINE 19 (Wait for VPI_OFFLINE event) */
1589 (void *) emlxs_vpi_online_action, /* STATE_ENTER */
1590 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */
1591 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */
1592 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */
1593 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */
1594 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */
1595 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */
1596
1597 }; /* emlxs_vpi_action_table() */
1598 #define VPI_ACTION_EVENTS 7
1599 #define VPI_ACTION_STATES \
1600 (sizeof (emlxs_vpi_action_table)/ \
1601 (VPI_ACTION_EVENTS * sizeof (void *)))
1602
1603
1604 /* ********************************************************************** */
1605 /* RPI */
1606 /* ********************************************************************** */
1607
1608 /* Order does not matter */
1609 emlxs_table_t emlxs_rpi_state_table[] =
1610 {
1611 {RPI_STATE_FREE, "RPI_FREE"},
1612
1613 {RPI_STATE_RESERVED, "RPI_RESERVED"},
1614 {RPI_STATE_OFFLINE, "RPI_OFFLINE"},
1615
1616 {RPI_STATE_UNREG_CMPL, "RPI_UNREG_CMPL"},
1617 {RPI_STATE_UNREG_FAILED, "RPI_UNREG_FAILED"},
1618 {RPI_STATE_UNREG, "RPI_UNREG"},
1619
1620 {RPI_STATE_REG, "RPI_REG"},
1621 {RPI_STATE_REG_FAILED, "RPI_REG_FAILED"},
1622 {RPI_STATE_REG_CMPL, "RPI_REG_CMPL"},
1623
1624 {RPI_STATE_PAUSED, "RPI_PAUSED"},
1625
1626 {RPI_STATE_RESUME, "RPI_RESUME"},
1627 {RPI_STATE_RESUME_FAILED, "RPI_RESUME_FAILED"},
1628 {RPI_STATE_RESUME_CMPL, "RPI_RESUME_CMPL"},
1629
1630 {RPI_STATE_ONLINE, "RPI_ONLINE"},
1631
1632 }; /* emlxs_rpi_state_table */
1633
1634 static uint32_t emlxs_rpi_free_action(emlxs_port_t *port,
1635 RPIobj_t *rpip, uint32_t evt, void *arg1);
1636
1637 static uint32_t emlxs_rpi_online_evt_action(emlxs_port_t *port,
1638 RPIobj_t *rpip, uint32_t evt, void *arg1);
1639 static uint32_t emlxs_rpi_offline_evt_action(emlxs_port_t *port,
1640 RPIobj_t *rpip, uint32_t evt, void *arg1);
1641 static uint32_t emlxs_rpi_pause_evt_action(emlxs_port_t *port,
1642 RPIobj_t *rpip, uint32_t evt, void *arg1);
1643 static uint32_t emlxs_rpi_resume_evt_action(emlxs_port_t *port,
1644 RPIobj_t *rpip, uint32_t evt, void *arg1);
1645
1646 static uint32_t emlxs_rpi_reg_action(emlxs_port_t *port,
1647 RPIobj_t *rpip, uint32_t evt, void *arg1);
1648 static uint32_t emlxs_rpi_reg_cmpl_action(emlxs_port_t *port,
1649 RPIobj_t *rpip, uint32_t evt, void *arg1);
1650 static uint32_t emlxs_rpi_reg_failed_action(emlxs_port_t *port,
1651 RPIobj_t *rpip, uint32_t evt, void *arg1);
1652
1653 static uint32_t emlxs_rpi_unreg_action(emlxs_port_t *port,
1654 RPIobj_t *rpip, uint32_t evt, void *arg1);
1655 static uint32_t emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port,
1656 RPIobj_t *rpip, uint32_t evt, void *arg1);
1657 static uint32_t emlxs_rpi_unreg_failed_action(emlxs_port_t *port,
1658 RPIobj_t *rpip, uint32_t evt, void *arg1);
1659
1660 static uint32_t emlxs_rpi_online_action(emlxs_port_t *port,
1661 RPIobj_t *rpip, uint32_t evt, void *arg1);
1662 static uint32_t emlxs_rpi_paused_action(emlxs_port_t *port,
1663 RPIobj_t *rpip, uint32_t evt, void *arg1);
1664 static uint32_t emlxs_rpi_offline_action(emlxs_port_t *port,
1665 RPIobj_t *rpip, uint32_t evt, void *arg1);
1666 static uint32_t emlxs_rpi_reserved_action(emlxs_port_t *port,
1667 RPIobj_t *rpip, uint32_t evt, void *arg1);
1668
1669 static uint32_t emlxs_rpi_resume_failed_action(emlxs_port_t *port,
1670 RPIobj_t *rpip, uint32_t evt, void *arg1);
1671 static uint32_t emlxs_rpi_resume_cmpl_action(emlxs_port_t *port,
1672 RPIobj_t *rpip, uint32_t evt, void *arg1);
1673 static uint32_t emlxs_rpi_resume_action(emlxs_port_t *port,
1674 RPIobj_t *rpip, uint32_t evt, void *arg1);
1675
1676 static uint32_t emlxs_rpi_event(emlxs_port_t *port,
1677 uint32_t evt, void *arg1);
1678 static RPIobj_t *emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did);
1679 static uint32_t emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip);
1680 static RPIobj_t *emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did);
1681
1682 static void emlxs_rpi_resume_handler(emlxs_port_t *port,
1683 RPIobj_t *rpip);
1684 static void emlxs_rpi_unreg_handler(emlxs_port_t *port,
1685 RPIobj_t *rpip);
1686 static uint32_t emlxs_rpi_reg_handler(emlxs_port_t *port,
1687 RPIobj_t *rpip);
1688
1689 static void emlxs_rpi_idle_timer(emlxs_hba_t *hba);
1690
1691 static uint32_t emlxs_rpi_state(emlxs_port_t *port, RPIobj_t *rpip,
1692 uint16_t state, uint16_t reason, uint32_t explain,
1693 void *arg1);
1694
1695 static void emlxs_rpi_alloc_fabric_rpi(emlxs_port_t *port);
1696
1697 static void emlxs_rpi_deferred_cmpl(emlxs_port_t *port, RPIobj_t *rpip,
1698 uint32_t status);
1699
1700 /*
1701 * - Online sequencing can start from RPI_STATE_RESERVED state or
1702 * the RPI_STATE_PAUSED state.
1703 *
1704 * - Offline sequencing can interrupt the online sequencing at the
1705 * entry of the next wait state.
1706 *
1707 * NORMAL ONLINE SEQ
1708 * ---------------------------
1709 * RPI_ONLINE event <-- VPI
1710 * RPI_STATE_RESERVED
1711 * RPI_STATE_REG
1712 * RPI_STATE_REG_CMPL
1713 * RPI_STATE_ONLINE
1714 * RPI_ONLINE event-->VPI
1715 *
1716 *
1717 * NORMAL OFFLINE SEQ
1718 * ---------------------------
1719 * RPI_OFFLINE event <-- VPI
1720 * RPI_STATE_ONLINE
1721 * RPI_STATE_UNREG
1722 * RPI_STATE_UNREG_CMPL
1723 * RPI_STATE_OFFLINE
1724 * RPI_OFFLINE event-->VPI
1725 *
1726 *
1727 * NORMAL PAUSE SEQ
1728 * ---------------------------
1729 * RPI_PAUSE event <-- VPI
1730 * RPI_STATE_ONLINE
1731 * RPI_STATE_PAUSED
1732 *
1733 */
1734 /* Order does matter */
1735 static void *emlxs_rpi_action_table[] =
1736 {
1737 /* Action routine Event */
1738 /* RPI_STATE_FREE 0 (Wait for allocation) */
1739 (void *) emlxs_rpi_free_action, /* STATE_ENTER */
1740 (void *) NULL, /* RPI_ONLINE */
1741 (void *) NULL, /* RPI_OFFLINE */
1742 (void *) NULL, /* RPI_PAUSE */
1743 (void *) NULL, /* RPI_RESUME */
1744
1745 /* RPI_STATE_RESERVED 1 (Wait for RPI_ONLINE event) */
1746 (void *) emlxs_rpi_reserved_action, /* STATE_ENTER */
1747 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1748 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1749 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1750 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1751
1752 /* RPI_STATE_OFFLINE 2 (Transitional) */
1753 (void *) emlxs_rpi_offline_action, /* STATE_ENTER */
1754 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1755 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1756 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1757 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1758
1759 /* RPI_STATE_UNREG_CMPL 3 (Transitional) */
1760 (void *) emlxs_rpi_unreg_cmpl_action, /* STATE_ENTER */
1761 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1762 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1763 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1764 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1765
1766 /* RPI_STATE_UNREG_FAILED 4 (Transitional) */
1767 (void *) emlxs_rpi_unreg_failed_action, /* STATE_ENTER */
1768 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1769 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1770 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1771 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1772
1773 /* RPI_STATE_UNREG 5 (Wait for unreg_rpi cmpl) */
1774 (void *) emlxs_rpi_unreg_action, /* STATE_ENTER */
1775 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1776 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1777 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1778 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1779
1780
1781 /* RPI_STATE_REG 6 (Wait for reg_rpi cmpl) */
1782 (void *) emlxs_rpi_reg_action, /* STATE_ENTER */
1783 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1784 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1785 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1786 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1787
1788 /* RPI_STATE_REG_FAILED 7 (Transitional) */
1789 (void *) emlxs_rpi_reg_failed_action, /* STATE_ENTER */
1790 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1791 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1792 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1793 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1794
1795 /* RPI_STATE_REG_CMPL 8 (Transitional) */
1796 (void *) emlxs_rpi_reg_cmpl_action, /* STATE_ENTER */
1797 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1798 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1799 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1800 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1801
1802
1803 /* RPI_STATE_PAUSED 9 (Wait for RPI_ONLINE) */
1804 (void *) emlxs_rpi_paused_action, /* STATE_ENTER */
1805 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1806 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1807 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1808 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1809
1810
1811 /* RPI_STATE_RESUME 10 (Wait for resume_rpi mbcmpl) */
1812 (void *) emlxs_rpi_resume_action, /* STATE_ENTER */
1813 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1814 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1815 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1816 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1817
1818 /* RPI_STATE_RESUME_FAILED 11 (Transitional) */
1819 (void *) emlxs_rpi_resume_failed_action, /* STATE_ENTER */
1820 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1821 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1822 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1823 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1824
1825 /* RPI_STATE_RESUME_CMPL 12 (Transitional) */
1826 (void *) emlxs_rpi_resume_cmpl_action, /* STATE_ENTER */
1827 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1828 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1829 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1830 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1831
1832
1833 /* RPI_STATE_ONLINE 13 (Wait for RPI_OFFLINE event) */
1834 (void *) emlxs_rpi_online_action, /* STATE_ENTER */
1835 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */
1836 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */
1837 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */
1838 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */
1839
1840 }; /* emlxs_rpi_action_table[] */
1841 #define RPI_ACTION_EVENTS 5
1842 #define RPI_ACTION_STATES \
1843 (sizeof (emlxs_rpi_action_table)/ \
1844 (RPI_ACTION_EVENTS * sizeof (void *)))
1845
1846
1847 /* ************************************************************************** */
1848 /* FCF Generic */
1849 /* ************************************************************************** */
1850 static void
emlxs_fcf_linkdown(emlxs_port_t * port)1851 emlxs_fcf_linkdown(emlxs_port_t *port)
1852 {
1853 emlxs_hba_t *hba = HBA;
1854
1855 if (hba->state <= FC_LINK_DOWN) {
1856 return;
1857 }
1858
1859 mutex_enter(&EMLXS_PORT_LOCK);
1860
1861 if (hba->state <= FC_LINK_DOWN) {
1862 mutex_exit(&EMLXS_PORT_LOCK);
1863 return;
1864 }
1865
1866 HBASTATS.LinkDown++;
1867 EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN);
1868
1869 hba->flag &= FC_LINKDOWN_MASK;
1870 hba->discovery_timer = 0;
1871 hba->linkup_timer = 0;
1872
1873 mutex_exit(&EMLXS_PORT_LOCK);
1874
1875 emlxs_log_link_event(port);
1876
1877 return;
1878
1879 } /* emlxs_fcf_linkdown() */
1880
1881
1882 static void
emlxs_fcf_linkup(emlxs_port_t * port)1883 emlxs_fcf_linkup(emlxs_port_t *port)
1884 {
1885 emlxs_hba_t *hba = HBA;
1886 emlxs_config_t *cfg = &CFG;
1887
1888 if (hba->state >= FC_LINK_UP) {
1889 return;
1890 }
1891
1892 mutex_enter(&EMLXS_PORT_LOCK);
1893
1894 if (hba->state >= FC_LINK_UP) {
1895 mutex_exit(&EMLXS_PORT_LOCK);
1896 return;
1897 }
1898
1899 /* Check for any mode changes */
1900 emlxs_mode_set(hba);
1901
1902 HBASTATS.LinkUp++;
1903 EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP);
1904
1905 hba->discovery_timer = hba->timer_tics +
1906 cfg[CFG_LINKUP_TIMEOUT].current +
1907 cfg[CFG_DISC_TIMEOUT].current;
1908
1909 mutex_exit(&EMLXS_PORT_LOCK);
1910
1911 emlxs_log_link_event(port);
1912
1913 return;
1914
1915 } /* emlxs_fcf_linkup() */
1916
1917
1918 extern void
emlxs_fcf_fini(emlxs_hba_t * hba)1919 emlxs_fcf_fini(emlxs_hba_t *hba)
1920 {
1921 emlxs_port_t *port = &PPORT;
1922 emlxs_port_t *vport;
1923 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
1924 uint32_t i;
1925 RPIobj_t *rpip;
1926
1927 if (!(hba->sli.sli4.flag & EMLXS_SLI4_FCF_INIT)) {
1928 return;
1929 }
1930
1931 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
1932 "fcf_fini: %s flag=%x fcfi_online=%d.",
1933 emlxs_fcftab_state_xlate(port, fcftab->state),
1934 fcftab->flag, fcftab->fcfi_online);
1935
1936 if (!(fcftab->flag & EMLXS_FCFTAB_SHUTDOWN)) {
1937 (void) emlxs_fcf_shutdown_notify(port, 1);
1938 }
1939
1940 mutex_enter(&EMLXS_FCF_LOCK);
1941 hba->sli.sli4.flag &= ~EMLXS_SLI4_FCF_INIT;
1942
1943 /* Free the FCF memory */
1944
1945 kmem_free(fcftab->table,
1946 (sizeof (FCFIobj_t) * fcftab->table_count));
1947
1948 fcftab->table = NULL;
1949 fcftab->table_count = 0;
1950
1951 /* Free the VFI memory */
1952
1953 kmem_free(hba->sli.sli4.VFI_table,
1954 (sizeof (VFIobj_t) * hba->sli.sli4.VFICount));
1955
1956 hba->sli.sli4.VFI_table = NULL;
1957 hba->sli.sli4.VFICount = 0;
1958
1959 /* Free the VPI Fabric RPI's */
1960
1961 for (i = 0; i < MAX_VPORTS; i++) {
1962 vport = &VPORT(i);
1963 rpip = vport->vpip->fabric_rpip;
1964
1965 if (rpip->state == RPI_STATE_FREE) {
1966 continue;
1967 }
1968
1969 (void) emlxs_rpi_free(port, rpip);
1970 }
1971
1972 /* Free the RPI memory */
1973
1974 rpip = hba->sli.sli4.RPIp;
1975 for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
1976 if (rpip->state == RPI_STATE_FREE) {
1977 continue;
1978 }
1979
1980 (void) emlxs_rpi_free(port, rpip);
1981 }
1982
1983 kmem_free(hba->sli.sli4.RPIp,
1984 (sizeof (RPIobj_t) * hba->sli.sli4.RPICount));
1985
1986 hba->sli.sli4.RPIp = NULL;
1987 hba->sli.sli4.RPICount = 0;
1988
1989 /* Free the mutex */
1990 mutex_exit(&EMLXS_FCF_LOCK);
1991 mutex_destroy(&EMLXS_FCF_LOCK);
1992
1993 return;
1994
1995 } /* emlxs_fcf_fini() */
1996
1997
1998 extern void
emlxs_fcf_init(emlxs_hba_t * hba)1999 emlxs_fcf_init(emlxs_hba_t *hba)
2000 {
2001 emlxs_port_t *port = &PPORT;
2002 emlxs_port_t *vport;
2003 uint16_t i;
2004 FCFIobj_t *fcfp;
2005 VPIobj_t *vpip;
2006 VFIobj_t *vfip;
2007 RPIobj_t *rpip;
2008 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2009
2010 if (hba->sli.sli4.flag & EMLXS_SLI4_FCF_INIT) {
2011 return;
2012 }
2013
2014 mutex_init(&EMLXS_FCF_LOCK, NULL, MUTEX_DRIVER, NULL);
2015 mutex_enter(&EMLXS_FCF_LOCK);
2016
2017 /* FCFTAB */
2018
2019 bzero(fcftab, sizeof (FCFTable_t));
2020 fcftab->state = FCFTAB_STATE_OFFLINE;
2021
2022 /* FCFI */
2023
2024 fcftab->table_count = hba->sli.sli4.FCFICount;
2025 fcftab->table = (FCFIobj_t *)kmem_zalloc(
2026 (sizeof (FCFIobj_t) * fcftab->table_count), KM_SLEEP);
2027
2028 fcfp = fcftab->table;
2029 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2030 fcfp->index = i;
2031 fcfp->FCFI = 0xFFFF;
2032 fcfp->state = FCFI_STATE_FREE;
2033 }
2034
2035 /* VFI */
2036
2037 hba->sli.sli4.VFI_table = (VFIobj_t *)kmem_zalloc(
2038 (sizeof (VFIobj_t) * hba->sli.sli4.VFICount), KM_SLEEP);
2039
2040 vfip = hba->sli.sli4.VFI_table;
2041 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
2042 vfip->VFI = emlxs_sli4_index_to_vfi(hba, i);
2043 vfip->index = i;
2044 vfip->state = VFI_STATE_OFFLINE;
2045 }
2046
2047 /* VPI */
2048
2049 for (i = 0; i < MAX_VPORTS; i++) {
2050 vport = &VPORT(i);
2051 vpip = &vport->VPIobj;
2052
2053 bzero(vpip, sizeof (VPIobj_t));
2054 vpip->index = i;
2055 vpip->VPI = emlxs_sli4_index_to_vpi(hba, i);
2056 vpip->port = vport;
2057 vpip->state = VPI_STATE_OFFLINE;
2058 vport->vpip = vpip;
2059
2060 /* Init the Fabric RPI's */
2061 rpip = &vpip->fabric_rpi;
2062 rpip->state = RPI_STATE_FREE;
2063 rpip->index = 0xffff;
2064 rpip->RPI = FABRIC_RPI;
2065 rpip->did = FABRIC_DID;
2066 rpip->vpip = vpip;
2067 vpip->fabric_rpip = rpip;
2068 }
2069
2070 /* RPI */
2071
2072 hba->sli.sli4.RPIp = (RPIobj_t *)kmem_zalloc(
2073 (sizeof (RPIobj_t) * hba->sli.sli4.RPICount), KM_SLEEP);
2074
2075 rpip = hba->sli.sli4.RPIp;
2076 for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
2077 rpip->state = RPI_STATE_FREE;
2078 rpip->RPI = emlxs_sli4_index_to_rpi(hba, i);
2079 rpip->index = i;
2080 }
2081
2082 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2083 "fcf_init: %s flag=%x fcfi=%d vfi=%d vpi=%d rpi=%d.",
2084 emlxs_fcftab_state_xlate(port, fcftab->state),
2085 fcftab->flag,
2086 fcftab->table_count,
2087 hba->sli.sli4.VFICount,
2088 MAX_VPORTS,
2089 hba->sli.sli4.RPICount);
2090
2091 hba->sli.sli4.flag |= EMLXS_SLI4_FCF_INIT;
2092 mutex_exit(&EMLXS_FCF_LOCK);
2093
2094 return;
2095
2096 } /* emlxs_fcf_init() */
2097
2098
2099 static char *
emlxs_fcf_event_xlate(uint32_t state)2100 emlxs_fcf_event_xlate(uint32_t state)
2101 {
2102 static char buffer[32];
2103 uint32_t i;
2104 uint32_t count;
2105
2106 count = sizeof (emlxs_fcf_event_table) / sizeof (emlxs_table_t);
2107 for (i = 0; i < count; i++) {
2108 if (state == emlxs_fcf_event_table[i].code) {
2109 return (emlxs_fcf_event_table[i].string);
2110 }
2111 }
2112
2113 (void) snprintf(buffer, sizeof (buffer), "event=0x%x", state);
2114 return (buffer);
2115
2116 } /* emlxs_fcf_event_xlate() */
2117
2118
2119 static char *
emlxs_fcf_reason_xlate(uint32_t reason)2120 emlxs_fcf_reason_xlate(uint32_t reason)
2121 {
2122 static char buffer[32];
2123 uint32_t i;
2124 uint32_t count;
2125
2126 count = sizeof (emlxs_fcf_reason_table) / sizeof (emlxs_table_t);
2127 for (i = 0; i < count; i++) {
2128 if (reason == emlxs_fcf_reason_table[i].code) {
2129 return (emlxs_fcf_reason_table[i].string);
2130 }
2131 }
2132
2133 (void) snprintf(buffer, sizeof (buffer), "reason=0x%x", reason);
2134 return (buffer);
2135
2136 } /* emlxs_fcf_reason_xlate() */
2137
2138
2139 extern void
emlxs_fcf_timer_notify(emlxs_hba_t * hba)2140 emlxs_fcf_timer_notify(emlxs_hba_t *hba)
2141 {
2142 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2143
2144 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2145 return;
2146 }
2147
2148 if (fcftab->table == 0) {
2149 return;
2150 }
2151
2152 mutex_enter(&EMLXS_FCF_LOCK);
2153
2154 if (SLI4_FCOE_MODE) {
2155 emlxs_fcoe_fcftab_sol_timer(hba);
2156
2157 emlxs_fcoe_fcftab_read_timer(hba);
2158
2159 emlxs_fcoe_fcftab_offline_timer(hba);
2160 } else {
2161 emlxs_fc_fcftab_online_timer(hba);
2162 }
2163
2164 emlxs_rpi_idle_timer(hba);
2165
2166 mutex_exit(&EMLXS_FCF_LOCK);
2167
2168 return;
2169
2170 } /* emlxs_fcf_timer_notify() */
2171
2172
2173 extern uint32_t
emlxs_fcf_shutdown_notify(emlxs_port_t * port,uint32_t wait)2174 emlxs_fcf_shutdown_notify(emlxs_port_t *port, uint32_t wait)
2175 {
2176 emlxs_hba_t *hba = HBA;
2177 emlxs_port_t *pport = &PPORT;
2178 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2179 uint32_t rval = 0;
2180 uint32_t i;
2181
2182 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2183 return (1);
2184 }
2185
2186 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2187 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2188 return (1);
2189 }
2190
2191 if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) {
2192 return (0);
2193 }
2194
2195 mutex_enter(&EMLXS_FCF_LOCK);
2196
2197 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2198 "fcf_shutdown_notify: %s flag=%x "
2199 "fcfi_online=%d. Shutting down FCFTAB. >",
2200 emlxs_fcftab_state_xlate(port, fcftab->state),
2201 fcftab->flag, fcftab->fcfi_online);
2202
2203 rval = emlxs_fcftab_event(port, FCF_EVENT_SHUTDOWN, 0);
2204
2205 if (wait && (rval == 0)) {
2206 /* Wait for shutdown flag */
2207 i = 0;
2208 while (!(fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) && (i++ < 120)) {
2209 mutex_exit(&EMLXS_FCF_LOCK);
2210 BUSYWAIT_MS(1000);
2211 mutex_enter(&EMLXS_FCF_LOCK);
2212 }
2213
2214 if (!(fcftab->flag & EMLXS_FCFTAB_SHUTDOWN)) {
2215 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2216 "fcf_shutdown_notify: %s flag=%x "
2217 "fcfi_online=%d. Shutdown timeout.",
2218 emlxs_fcftab_state_xlate(port, fcftab->state),
2219 fcftab->flag, fcftab->fcfi_online);
2220 rval = 1;
2221 }
2222 }
2223
2224 mutex_exit(&EMLXS_FCF_LOCK);
2225
2226 return (rval);
2227
2228 } /* emlxs_fcf_shutdown_notify() */
2229
2230
2231 extern uint32_t
emlxs_fcf_linkup_notify(emlxs_port_t * port)2232 emlxs_fcf_linkup_notify(emlxs_port_t *port)
2233 {
2234 emlxs_hba_t *hba = HBA;
2235 emlxs_port_t *pport = &PPORT;
2236 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2237 uint32_t rval = 0;
2238
2239 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2240 return (1);
2241 }
2242
2243 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2244 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2245 return (1);
2246 }
2247
2248 mutex_enter(&EMLXS_FCF_LOCK);
2249
2250 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2251 "fcf_linkup_notify: %s flag=%x "
2252 "fcfi_online=%d. FCFTAB Link up. >",
2253 emlxs_fcftab_state_xlate(port, fcftab->state),
2254 fcftab->flag, fcftab->fcfi_online);
2255
2256 rval = emlxs_fcftab_event(port, FCF_EVENT_LINKUP, 0);
2257
2258 mutex_exit(&EMLXS_FCF_LOCK);
2259
2260 return (rval);
2261
2262 } /* emlxs_fcf_linkup_notify() */
2263
2264
2265 extern uint32_t
emlxs_fcf_linkdown_notify(emlxs_port_t * port)2266 emlxs_fcf_linkdown_notify(emlxs_port_t *port)
2267 {
2268 emlxs_hba_t *hba = HBA;
2269 emlxs_port_t *pport = &PPORT;
2270 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2271 uint32_t rval = 0;
2272
2273 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2274 return (1);
2275 }
2276
2277 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2278 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2279 return (1);
2280 }
2281
2282 mutex_enter(&EMLXS_FCF_LOCK);
2283
2284 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2285 "fcf_linkdown_notify: %s flag=%x "
2286 "fcfi_online=%d. FCFTAB Link down. >",
2287 emlxs_fcftab_state_xlate(port, fcftab->state),
2288 fcftab->flag, fcftab->fcfi_online);
2289
2290 rval = emlxs_fcftab_event(port, FCF_EVENT_LINKDOWN, 0);
2291
2292 mutex_exit(&EMLXS_FCF_LOCK);
2293
2294 return (rval);
2295
2296 } /* emlxs_fcf_linkdown_notify() */
2297
2298
2299 extern uint32_t
emlxs_fcf_cvl_notify(emlxs_port_t * port,uint32_t vpi)2300 emlxs_fcf_cvl_notify(emlxs_port_t *port, uint32_t vpi)
2301 {
2302 emlxs_hba_t *hba = HBA;
2303 emlxs_port_t *pport = &PPORT;
2304 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2305 uint32_t rval = 0;
2306
2307 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2308 return (1);
2309 }
2310
2311 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2312 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2313 return (1);
2314 }
2315
2316 mutex_enter(&EMLXS_FCF_LOCK);
2317
2318 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2319 "fcf_cvl_notify: %s flag=%x "
2320 "fcfi_online=%d. FCFTAB FCF CVL. >",
2321 emlxs_fcftab_state_xlate(port, fcftab->state),
2322 fcftab->flag, fcftab->fcfi_online);
2323
2324 rval = emlxs_fcftab_event(port, FCF_EVENT_CVL,
2325 (void *)((unsigned long)vpi));
2326
2327 mutex_exit(&EMLXS_FCF_LOCK);
2328
2329 return (rval);
2330
2331 } /* emlxs_fcf_cvl_notify() */
2332
2333
2334 extern uint32_t
emlxs_fcf_full_notify(emlxs_port_t * port)2335 emlxs_fcf_full_notify(emlxs_port_t *port)
2336 {
2337 emlxs_hba_t *hba = HBA;
2338 emlxs_port_t *pport = &PPORT;
2339 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2340 uint32_t rval = 0;
2341
2342 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2343 return (1);
2344 }
2345
2346 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2347 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2348 return (1);
2349 }
2350
2351 mutex_enter(&EMLXS_FCF_LOCK);
2352
2353 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2354 "fcf_full_notify: %s flag=%x "
2355 "fcfi_online=%d. FCFTAB FCF full. >",
2356 emlxs_fcftab_state_xlate(port, fcftab->state),
2357 fcftab->flag, fcftab->fcfi_online);
2358
2359 rval = emlxs_fcftab_event(port, FCF_EVENT_FCFTAB_FULL, 0);
2360
2361 mutex_exit(&EMLXS_FCF_LOCK);
2362
2363 return (rval);
2364
2365 } /* emlxs_fcf_full_notify() */
2366
2367
2368 extern uint32_t
emlxs_fcf_found_notify(emlxs_port_t * port,uint32_t fcf_index)2369 emlxs_fcf_found_notify(emlxs_port_t *port, uint32_t fcf_index)
2370 {
2371 emlxs_hba_t *hba = HBA;
2372 emlxs_port_t *pport = &PPORT;
2373 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2374 uint32_t rval = 0;
2375
2376 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2377 return (1);
2378 }
2379
2380 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2381 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2382 return (1);
2383 }
2384
2385 mutex_enter(&EMLXS_FCF_LOCK);
2386
2387 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2388 "fcf_found_notify: %s flag=%x "
2389 "fcfi_online=%d. FCFTAB FCF found. >",
2390 emlxs_fcftab_state_xlate(port, fcftab->state),
2391 fcftab->flag, fcftab->fcfi_online);
2392
2393 rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_FOUND,
2394 (void *)((unsigned long)fcf_index));
2395
2396 mutex_exit(&EMLXS_FCF_LOCK);
2397
2398 return (rval);
2399
2400 } /* emlxs_fcf_found_notify() */
2401
2402
2403 extern uint32_t
emlxs_fcf_changed_notify(emlxs_port_t * port,uint32_t fcf_index)2404 emlxs_fcf_changed_notify(emlxs_port_t *port, uint32_t fcf_index)
2405 {
2406 emlxs_hba_t *hba = HBA;
2407 emlxs_port_t *pport = &PPORT;
2408 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2409 uint32_t rval = 0;
2410
2411 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2412 return (1);
2413 }
2414
2415 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2416 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2417 return (1);
2418 }
2419
2420 mutex_enter(&EMLXS_FCF_LOCK);
2421
2422 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2423 "fcf_changes_notify: %s flag=%x "
2424 "fcfi_online=%d. FCFTAB FCF changed. >",
2425 emlxs_fcftab_state_xlate(port, fcftab->state),
2426 fcftab->flag, fcftab->fcfi_online);
2427
2428 rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_CHANGED,
2429 (void *)((unsigned long)fcf_index));
2430
2431 mutex_exit(&EMLXS_FCF_LOCK);
2432
2433 return (rval);
2434
2435 } /* emlxs_fcf_changed_notify() */
2436
2437
2438 extern uint32_t
emlxs_fcf_lost_notify(emlxs_port_t * port,uint32_t fcf_index)2439 emlxs_fcf_lost_notify(emlxs_port_t *port, uint32_t fcf_index)
2440 {
2441 emlxs_hba_t *hba = HBA;
2442 emlxs_port_t *pport = &PPORT;
2443 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2444 uint32_t rval = 0;
2445
2446 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
2447 return (1);
2448 }
2449
2450 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2451 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2452 return (1);
2453 }
2454
2455 mutex_enter(&EMLXS_FCF_LOCK);
2456
2457 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2458 "fcf_lost_notify: %s flag=%x "
2459 "fcfi_online=%d. FCFTAB FCF lost. >",
2460 emlxs_fcftab_state_xlate(port, fcftab->state),
2461 fcftab->flag, fcftab->fcfi_online);
2462
2463 rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_LOST,
2464 (void *)((unsigned long)fcf_index));
2465
2466 mutex_exit(&EMLXS_FCF_LOCK);
2467
2468 return (rval);
2469
2470 } /* emlxs_fcf_lost_notify() */
2471
2472
2473 /* ************************************************************************** */
2474 /* FCFTAB Generic */
2475 /* ************************************************************************** */
2476
2477 static char *
emlxs_fcftab_state_xlate(emlxs_port_t * port,uint32_t state)2478 emlxs_fcftab_state_xlate(emlxs_port_t *port, uint32_t state)
2479 {
2480 emlxs_hba_t *hba = HBA;
2481
2482 if (SLI4_FCOE_MODE) {
2483 return (emlxs_fcoe_fcftab_state_xlate(state));
2484 } else {
2485 return (emlxs_fc_fcftab_state_xlate(state));
2486 }
2487
2488 } /* emlxs_fcftab_state_xlate() */
2489
2490 static uint32_t
emlxs_fcftab_event(emlxs_port_t * port,uint32_t evt,void * arg1)2491 emlxs_fcftab_event(emlxs_port_t *port, uint32_t evt, void *arg1)
2492 {
2493 emlxs_hba_t *hba = HBA;
2494
2495 if (SLI4_FCOE_MODE) {
2496 return (emlxs_fcoe_fcftab_event(port, evt, arg1));
2497 } else {
2498 return (emlxs_fc_fcftab_event(port, evt, arg1));
2499 }
2500
2501 } /* emlxs_fcftab_event() */
2502
2503
2504 /*ARGSUSED*/
2505 static uint32_t
emlxs_fcftab_shutdown_action(emlxs_port_t * port,uint32_t evt,void * arg1)2506 emlxs_fcftab_shutdown_action(emlxs_port_t *port, uint32_t evt,
2507 void *arg1)
2508 {
2509 emlxs_hba_t *hba = HBA;
2510 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2511 FCFIobj_t *fcfp;
2512 uint32_t i;
2513 uint32_t online;
2514
2515 if (fcftab->state != FCFTAB_STATE_SHUTDOWN) {
2516 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2517 "fcftab_shutdown_action:%x %s:%s arg=%p. "
2518 "Invalid state. <",
2519 fcftab->TID,
2520 emlxs_fcftab_state_xlate(port, fcftab->state),
2521 emlxs_fcf_event_xlate(evt), arg1);
2522 return (1);
2523 }
2524
2525 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
2526
2527 if (fcftab->prev_state != FCFTAB_STATE_SHUTDOWN) {
2528 /* Offline all FCF's */
2529 online = 0;
2530 fcfp = fcftab->table;
2531 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2532
2533 if (fcfp->state <= FCFI_STATE_OFFLINE) {
2534 continue;
2535 }
2536
2537 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2538 "fcftab_shutdown_action:%x fcfi_online=%d. "
2539 "Offlining FCFI:%d. >",
2540 fcftab->TID,
2541 fcftab->fcfi_online,
2542 fcfp->fcf_index);
2543
2544 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE,
2545 fcfp);
2546
2547 online++;
2548 }
2549
2550 if (!online) {
2551 goto done;
2552 }
2553
2554 return (0);
2555 }
2556
2557 /* Check FCF states */
2558 online = 0;
2559 fcfp = fcftab->table;
2560 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2561
2562 if (fcfp->state <= FCFI_STATE_OFFLINE) {
2563 continue;
2564 }
2565
2566 online++;
2567 }
2568
2569 if (online) {
2570 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2571 "fcftab_shutdown_action:%x %s:%s arg=%p. "
2572 "fcfi_online=%d,%d <",
2573 fcftab->TID,
2574 emlxs_fcftab_state_xlate(port, fcftab->state),
2575 emlxs_fcf_event_xlate(evt), arg1,
2576 online, fcftab->fcfi_online);
2577
2578 return (0);
2579 }
2580
2581 done:
2582 /* Free FCF table */
2583 fcfp = fcftab->table;
2584 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
2585
2586 if (fcfp->state == FCFI_STATE_FREE) {
2587 continue;
2588 }
2589
2590 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2591 "fcftab_shutdown_action:%x. Freeing FCFI:%d. >",
2592 fcftab->TID,
2593 fcfp->fcf_index);
2594
2595 (void) emlxs_fcfi_free(port, fcfp);
2596 }
2597
2598 /* Clean the selection table */
2599 bzero(fcftab->fcfi, sizeof (fcftab->fcfi));
2600 fcftab->fcfi_count = 0;
2601
2602 fcftab->flag |= EMLXS_FCFTAB_SHUTDOWN;
2603
2604 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2605 "fcftab_shutdown_action:%x %s:%s arg=%p flag=%x fcfi_online=%d. "
2606 "Shutdown. <",
2607 fcftab->TID,
2608 emlxs_fcftab_state_xlate(port, fcftab->state),
2609 emlxs_fcf_event_xlate(evt), arg1,
2610 fcftab->flag, fcftab->fcfi_online);
2611
2612 return (0);
2613
2614 } /* emlxs_fcftab_shutdown_action() */
2615
2616
2617 /* ************************************************************************** */
2618 /* FC FCFTAB */
2619 /* ************************************************************************** */
2620
2621 static char *
emlxs_fc_fcftab_state_xlate(uint32_t state)2622 emlxs_fc_fcftab_state_xlate(uint32_t state)
2623 {
2624 static char buffer[32];
2625 uint32_t i;
2626 uint32_t count;
2627
2628 count = sizeof (emlxs_fc_fcftab_state_table) / sizeof (emlxs_table_t);
2629 for (i = 0; i < count; i++) {
2630 if (state == emlxs_fc_fcftab_state_table[i].code) {
2631 return (emlxs_fc_fcftab_state_table[i].string);
2632 }
2633 }
2634
2635 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
2636 return (buffer);
2637
2638 } /* emlxs_fc_fcftab_state_xlate() */
2639
2640
2641 static uint32_t
emlxs_fc_fcftab_action(emlxs_port_t * port,uint32_t evt,void * arg1)2642 emlxs_fc_fcftab_action(emlxs_port_t *port, uint32_t evt,
2643 void *arg1)
2644 {
2645 emlxs_hba_t *hba = HBA;
2646 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2647 uint32_t rval = 0;
2648 uint32_t(*func) (emlxs_port_t *, uint32_t, void *);
2649 uint32_t index;
2650 uint32_t events;
2651 uint16_t state;
2652
2653 /* Convert event to action table index */
2654 switch (evt) {
2655 case FCF_EVENT_STATE_ENTER:
2656 index = 0;
2657 break;
2658 case FCF_EVENT_SHUTDOWN:
2659 index = 1;
2660 break;
2661 case FCF_EVENT_LINKUP:
2662 index = 2;
2663 break;
2664 case FCF_EVENT_LINKDOWN:
2665 index = 3;
2666 break;
2667 case FCF_EVENT_FCFI_ONLINE:
2668 index = 4;
2669 break;
2670 case FCF_EVENT_FCFI_OFFLINE:
2671 index = 5;
2672 break;
2673 default:
2674 return (1);
2675 }
2676
2677 events = FC_FCFTAB_ACTION_EVENTS;
2678 state = fcftab->state;
2679
2680 index += (state * events);
2681 func = (uint32_t(*) (emlxs_port_t *, uint32_t, void *))
2682 emlxs_fc_fcftab_action_table[index];
2683
2684 if (!func) {
2685 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
2686 "fc_fcftab_action:%x %s:%s arg=%p. No action. <",
2687 fcftab->TID,
2688 emlxs_fc_fcftab_state_xlate(fcftab->state),
2689 emlxs_fcf_event_xlate(evt), arg1);
2690
2691 return (1);
2692 }
2693
2694 rval = (func)(port, evt, arg1);
2695
2696 return (rval);
2697
2698 } /* emlxs_fc_fcftab_action() */
2699
2700
2701 static uint32_t
emlxs_fc_fcftab_event(emlxs_port_t * port,uint32_t evt,void * arg1)2702 emlxs_fc_fcftab_event(emlxs_port_t *port, uint32_t evt,
2703 void *arg1)
2704 {
2705 emlxs_hba_t *hba = HBA;
2706 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2707 uint32_t rval = 0;
2708
2709 /* Filter events */
2710 switch (evt) {
2711 case FCF_EVENT_SHUTDOWN:
2712 case FCF_EVENT_LINKUP:
2713 case FCF_EVENT_LINKDOWN:
2714 case FCF_EVENT_FCFI_ONLINE:
2715 case FCF_EVENT_FCFI_OFFLINE:
2716 break;
2717
2718 default:
2719 return (1);
2720 }
2721
2722 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
2723 "fc_fcftab_event:%x %s:%s arg=%p.",
2724 fcftab->TID,
2725 emlxs_fc_fcftab_state_xlate(fcftab->state),
2726 emlxs_fcf_event_xlate(evt), arg1);
2727
2728 rval = emlxs_fc_fcftab_action(port, evt, arg1);
2729
2730 return (rval);
2731
2732 } /* emlxs_fc_fcftab_event() */
2733
2734
2735 /* EMLXS_FCF_LOCK must be held to enter */
2736 /*ARGSUSED*/
2737 static uint32_t
emlxs_fc_fcftab_state(emlxs_port_t * port,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)2738 emlxs_fc_fcftab_state(emlxs_port_t *port, uint16_t state, uint16_t reason,
2739 uint32_t explain, void *arg1)
2740 {
2741 emlxs_hba_t *hba = HBA;
2742 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2743 uint32_t rval = 0;
2744
2745 if (state >= FC_FCFTAB_ACTION_STATES) {
2746 return (1);
2747 }
2748
2749 if ((fcftab->state == state) &&
2750 (reason != FCF_REASON_REENTER)) {
2751 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2752 "fcftab_state:%x %s:%s:0x%x arg=%p. "
2753 "State not changed. <",
2754 fcftab->TID,
2755 emlxs_fc_fcftab_state_xlate(state),
2756 emlxs_fcf_reason_xlate(reason),
2757 explain, arg1);
2758 return (1);
2759 }
2760
2761 if (!reason) {
2762 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2763 "fcftab_state:%x %s-->%s arg=%p",
2764 fcftab->TID,
2765 emlxs_fc_fcftab_state_xlate(fcftab->state),
2766 emlxs_fc_fcftab_state_xlate(state), arg1);
2767 } else if (reason == FCF_REASON_EVENT) {
2768 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2769 "fcftab_state:%x %s-->%s:%s:%s arg=%p",
2770 fcftab->TID,
2771 emlxs_fc_fcftab_state_xlate(fcftab->state),
2772 emlxs_fc_fcftab_state_xlate(state),
2773 emlxs_fcf_reason_xlate(reason),
2774 emlxs_fcf_event_xlate(explain), arg1);
2775 } else if (explain) {
2776 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2777 "fcftab_state:%x %s-->%s:%s:0x%x arg=%p",
2778 fcftab->TID,
2779 emlxs_fc_fcftab_state_xlate(fcftab->state),
2780 emlxs_fc_fcftab_state_xlate(state),
2781 emlxs_fcf_reason_xlate(reason),
2782 explain, arg1);
2783 } else {
2784 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
2785 "fcftab_state:%x %s-->%s:%s arg=%p",
2786 fcftab->TID,
2787 emlxs_fc_fcftab_state_xlate(fcftab->state),
2788 emlxs_fc_fcftab_state_xlate(state),
2789 emlxs_fcf_reason_xlate(reason), arg1);
2790 }
2791
2792 fcftab->prev_state = fcftab->state;
2793 fcftab->prev_reason = fcftab->reason;
2794 fcftab->state = state;
2795 fcftab->reason = reason;
2796
2797 rval = emlxs_fc_fcftab_action(port, FCF_EVENT_STATE_ENTER, arg1);
2798
2799 return (rval);
2800
2801 } /* emlxs_fc_fcftab_state() */
2802
2803
2804 static void
emlxs_fc_fcftab_online_timer(emlxs_hba_t * hba)2805 emlxs_fc_fcftab_online_timer(emlxs_hba_t *hba)
2806 {
2807 emlxs_port_t *port = &PPORT;
2808 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2809
2810 /* Check FCF timer */
2811 if (!fcftab->online_timer ||
2812 (hba->timer_tics < fcftab->online_timer)) {
2813 return;
2814 }
2815 fcftab->online_timer = 0;
2816
2817 switch (fcftab->state) {
2818 case FC_FCFTAB_STATE_ONLINE:
2819 emlxs_fcf_linkup(port);
2820
2821 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
2822 fcftab->flag |= EMLXS_FC_FCFTAB_TOPO_REQ;
2823 fcftab->generation++;
2824
2825 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2826 "fc_fcftab_online_timer:%x %s gen=%x. Read topology. >",
2827 fcftab->TID,
2828 emlxs_fc_fcftab_state_xlate(fcftab->state),
2829 fcftab->generation);
2830
2831 (void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
2832 FCF_REASON_EVENT, 0, 0);
2833 break;
2834
2835 default:
2836 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2837 "fc_fcftab_online_timer:%x %s",
2838 fcftab->TID,
2839 emlxs_fc_fcftab_state_xlate(fcftab->state));
2840 break;
2841 }
2842
2843 return;
2844
2845 } /* emlxs_fc_fcftab_online_timer() */
2846
2847
2848 /*ARGSUSED*/
2849 static uint32_t
emlxs_fc_fcftab_offline_action(emlxs_port_t * port,uint32_t evt,void * arg1)2850 emlxs_fc_fcftab_offline_action(emlxs_port_t *port, uint32_t evt,
2851 void *arg1)
2852 {
2853 emlxs_hba_t *hba = HBA;
2854 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2855 uint32_t rval = 0;
2856
2857 if (fcftab->state != FC_FCFTAB_STATE_OFFLINE) {
2858 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2859 "fc_fcftab_offline_action:%x %s:%s arg=%p. "
2860 "Invalid state. <",
2861 fcftab->TID,
2862 emlxs_fc_fcftab_state_xlate(fcftab->state),
2863 emlxs_fcf_event_xlate(evt), arg1);
2864 return (1);
2865 }
2866
2867 fcftab->flag &= ~EMLXS_FC_FCFTAB_OFFLINE_REQ;
2868
2869 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
2870 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2871 "fc_fcftab_offline_action:%x %s:%s arg=%p flag=%x. "
2872 "Handling request.",
2873 fcftab->TID,
2874 emlxs_fc_fcftab_state_xlate(fcftab->state),
2875 emlxs_fcf_event_xlate(evt), arg1,
2876 fcftab->flag);
2877
2878 rval = emlxs_fc_fcftab_req_handler(port, arg1);
2879 return (rval);
2880 }
2881
2882 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2883 "fc_fcftab_offline_action:%x %s:%s arg=%p fcfi_online=%d. "
2884 "Offline. <",
2885 fcftab->TID,
2886 emlxs_fc_fcftab_state_xlate(fcftab->state),
2887 emlxs_fcf_event_xlate(evt), arg1,
2888 fcftab->fcfi_online);
2889
2890 return (0);
2891
2892 } /* emlxs_fc_fcftab_offline_action() */
2893
2894
2895 /*ARGSUSED*/
2896 static uint32_t
emlxs_fc_fcftab_online_action(emlxs_port_t * port,uint32_t evt,void * arg1)2897 emlxs_fc_fcftab_online_action(emlxs_port_t *port, uint32_t evt,
2898 void *arg1)
2899 {
2900 emlxs_hba_t *hba = HBA;
2901 emlxs_port_t *pport = &PPORT;
2902 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2903 uint32_t rval = 0;
2904
2905 if (fcftab->state != FC_FCFTAB_STATE_ONLINE) {
2906 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
2907 "fc_fcftab_online_action:%x %s:%s arg=%p. "
2908 "Invalid state. <",
2909 fcftab->TID,
2910 emlxs_fc_fcftab_state_xlate(fcftab->state),
2911 emlxs_fcf_event_xlate(evt), arg1);
2912 return (1);
2913 }
2914
2915 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
2916 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2917 "fc_fcftab_online_action:%x flag=%x. "
2918 "Handling requested.",
2919 fcftab->TID,
2920 fcftab->flag);
2921
2922 rval = emlxs_fc_fcftab_req_handler(port, arg1);
2923 return (rval);
2924 }
2925
2926 if (fcftab->fcfi_online == 0) {
2927 if (!(pport->flag & EMLXS_PORT_BOUND) ||
2928 (pport->vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
2929 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2930 "fc_fcftab_online_action:%x %s:%s "
2931 "fcfi_online=0. Pport not bound. <",
2932 fcftab->TID,
2933 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
2934 emlxs_fcf_event_xlate(evt));
2935 } else {
2936 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2937 "fc_fcftab_online_action:%x %s:%s "
2938 "fcfi_online=0. Starting online timer. <",
2939 fcftab->TID,
2940 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
2941 emlxs_fcf_event_xlate(evt));
2942
2943 /* Start the online timer */
2944 fcftab->online_timer = hba->timer_tics + 1;
2945 }
2946
2947 emlxs_fcf_linkdown(port);
2948
2949 return (0);
2950 }
2951
2952 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2953 "fc_fcftab_online_action:%x flag=%x fcfi_online=%d. "
2954 "Online. <",
2955 fcftab->TID,
2956 fcftab->flag,
2957 fcftab->fcfi_online);
2958
2959 emlxs_fcf_linkup(port);
2960
2961 return (0);
2962
2963 } /* emlxs_fc_fcftab_online_action() */
2964
2965
2966 /*ARGSUSED*/
2967 static uint32_t
emlxs_fc_fcftab_topo_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)2968 emlxs_fc_fcftab_topo_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
2969 {
2970 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
2971 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
2972 MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
2973 MATCHMAP *mp;
2974 uint8_t *alpa_map;
2975 uint32_t j;
2976 uint16_t TID;
2977
2978 mutex_enter(&EMLXS_FCF_LOCK);
2979 TID = (uint16_t)((unsigned long)mbq->context);
2980
2981 if (fcftab->state != FC_FCFTAB_STATE_TOPO) {
2982 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2983 "fc_fcftab_topo_mbcmpl:%x state=%s.",
2984 TID,
2985 emlxs_fc_fcftab_state_xlate(fcftab->state));
2986
2987 mutex_exit(&EMLXS_FCF_LOCK);
2988 return (0);
2989 }
2990
2991 if (TID != fcftab->generation) {
2992 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
2993 "fc_fcftab_topo_mbcmpl:%x %s. "
2994 "Incorrect generation %x. Dropping.",
2995 TID,
2996 emlxs_fc_fcftab_state_xlate(fcftab->state),
2997 fcftab->generation);
2998
2999 mutex_exit(&EMLXS_FCF_LOCK);
3000 return (0);
3001 }
3002
3003 if (mb4->mbxStatus) {
3004 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3005 "fc_fcftab_topo_mbcmpl:%x failed. %s. >",
3006 fcftab->TID,
3007 emlxs_mb_xlate_status(mb4->mbxStatus));
3008
3009 if (mb4->mbxStatus == MBXERR_NO_RESOURCES) {
3010 (void) emlxs_fc_fcftab_state(port,
3011 FC_FCFTAB_STATE_TOPO_FAILED,
3012 FCF_REASON_MBOX_BUSY, mb4->mbxStatus, 0);
3013 } else {
3014 (void) emlxs_fc_fcftab_state(port,
3015 FC_FCFTAB_STATE_TOPO_FAILED,
3016 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
3017 }
3018
3019 mutex_exit(&EMLXS_FCF_LOCK);
3020 return (0);
3021 }
3022
3023 if (mb4->un.varReadLA.attType == AT_LINK_DOWN) {
3024 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3025 "fc_fcftab_topo_mbcmpl:%x Linkdown attention. "
3026 "Offline requested.",
3027 fcftab->TID);
3028
3029 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
3030 fcftab->flag |= EMLXS_FC_FCFTAB_OFFLINE_REQ;
3031 (void) emlxs_fc_fcftab_req_handler(port, 0);
3032
3033 mutex_exit(&EMLXS_FCF_LOCK);
3034 return (0);
3035 }
3036
3037 if (hba->link_event_tag != mb4->un.varReadLA.eventTag) {
3038 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3039 "fc_fcftab_topo_mbcmpl:%x Event tag invalid. %x != %x",
3040 fcftab->TID,
3041 hba->link_event_tag, mb4->un.varReadLA.eventTag);
3042 }
3043
3044 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3045 "fc_fcftab_topo_mbcmpl:%x state=%s type=%s iotag=%d "
3046 "alpa=%x. >",
3047 fcftab->TID,
3048 emlxs_fc_fcftab_state_xlate(fcftab->state),
3049 (mb4->un.varReadLA.attType == AT_LINK_UP)?"linkup":"linkdown",
3050 hba->link_event_tag,
3051 (uint32_t)mb4->un.varReadLA.granted_AL_PA);
3052
3053 /* Link is up */
3054
3055 /* Save the linkspeed & topology */
3056 hba->linkspeed = mb4->un.varReadLA.UlnkSpeed;
3057 hba->topology = mb4->un.varReadLA.topology;
3058
3059 if (hba->topology != TOPOLOGY_LOOP) {
3060 port->did = 0;
3061 port->lip_type = 0;
3062 hba->flag &= ~FC_BYPASSED_MODE;
3063 bzero((caddr_t)port->alpa_map, 128);
3064
3065 goto done;
3066 }
3067
3068 /* TOPOLOGY_LOOP */
3069
3070 port->lip_type = mb4->un.varReadLA.lipType;
3071
3072 if (mb4->un.varReadLA.pb) {
3073 hba->flag |= FC_BYPASSED_MODE;
3074 } else {
3075 hba->flag &= ~FC_BYPASSED_MODE;
3076 }
3077
3078 /* Save the granted_alpa and alpa_map */
3079
3080 port->granted_alpa = mb4->un.varReadLA.granted_AL_PA;
3081 mp = (MATCHMAP *)mbq->bp;
3082 alpa_map = (uint8_t *)port->alpa_map;
3083
3084 bcopy((caddr_t)mp->virt, (caddr_t)alpa_map, 128);
3085
3086 /* Check number of devices in map */
3087 if (alpa_map[0] > 127) {
3088 alpa_map[0] = 127;
3089 }
3090
3091 EMLXS_MSGF(EMLXS_CONTEXT,
3092 &emlxs_link_atten_msg,
3093 "alpa_map: %d device(s): "
3094 "%02x %02x %02x %02x %02x %02x %02x %02x",
3095 alpa_map[0], alpa_map[1],
3096 alpa_map[2], alpa_map[3],
3097 alpa_map[4], alpa_map[5],
3098 alpa_map[6], alpa_map[7],
3099 alpa_map[8]);
3100
3101 for (j = 9; j <= alpa_map[0]; j += 8) {
3102 EMLXS_MSGF(EMLXS_CONTEXT,
3103 &emlxs_link_atten_msg,
3104 "alpa_map: "
3105 "%02x %02x %02x %02x %02x %02x %02x %02x",
3106 alpa_map[j],
3107 alpa_map[j + 1],
3108 alpa_map[j + 2],
3109 alpa_map[j + 3],
3110 alpa_map[j + 4],
3111 alpa_map[j + 5],
3112 alpa_map[j + 6],
3113 alpa_map[j + 7]);
3114 }
3115
3116 done:
3117
3118 (void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_CMPL,
3119 0, 0, 0);
3120
3121 mutex_exit(&EMLXS_FCF_LOCK);
3122 return (0);
3123
3124 } /* emlxs_fc_fcftab_topo_mbcmpl() */
3125
3126
3127 /*ARGSUSED*/
3128 static uint32_t
emlxs_fc_fcftab_topo_action(emlxs_port_t * port,uint32_t evt,void * arg1)3129 emlxs_fc_fcftab_topo_action(emlxs_port_t *port, uint32_t evt,
3130 void *arg1)
3131 {
3132 emlxs_hba_t *hba = HBA;
3133 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3134 MAILBOXQ *mbq;
3135 MAILBOX4 *mb4;
3136 uint32_t rval = 0;
3137 MATCHMAP *mp;
3138
3139 if (fcftab->state != FC_FCFTAB_STATE_TOPO) {
3140 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3141 "fc_fcftab_topo_action:%x %s:%s arg=%p. "
3142 "Invalid state. <",
3143 fcftab->TID,
3144 emlxs_fc_fcftab_state_xlate(fcftab->state),
3145 emlxs_fcf_event_xlate(evt), arg1);
3146 return (1);
3147 }
3148
3149 if ((fcftab->prev_state != FC_FCFTAB_STATE_TOPO_FAILED) ||
3150 (fcftab->flag & EMLXS_FC_FCFTAB_TOPO_REQ)) {
3151 fcftab->flag &= ~EMLXS_FC_FCFTAB_TOPO_REQ;
3152 fcftab->attempts = 0;
3153 }
3154
3155 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3156 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3157 "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3158 "Handling request.",
3159 fcftab->TID,
3160 emlxs_fc_fcftab_state_xlate(fcftab->state),
3161 emlxs_fcf_event_xlate(evt), arg1,
3162 fcftab->generation,
3163 fcftab->flag);
3164
3165 rval = emlxs_fc_fcftab_req_handler(port, arg1);
3166 return (rval);
3167 }
3168
3169 if (fcftab->attempts == 0) {
3170 fcftab->TID = fcftab->generation;
3171 }
3172
3173 if (hba->topology != TOPOLOGY_LOOP) {
3174 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3175 "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3176 "Fabric Topology. Skipping READ_TOPO.",
3177 fcftab->TID,
3178 emlxs_fc_fcftab_state_xlate(fcftab->state),
3179 emlxs_fcf_event_xlate(evt), arg1,
3180 fcftab->generation,
3181 fcftab->flag);
3182
3183 port->did = 0;
3184 port->lip_type = 0;
3185 hba->flag &= ~FC_BYPASSED_MODE;
3186 bzero((caddr_t)port->alpa_map, 128);
3187
3188 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
3189 FCF_REASON_EVENT, evt, arg1);
3190 return (rval);
3191 }
3192
3193 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3194 "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3195 "Sending READ_TOPO. <",
3196 fcftab->TID,
3197 emlxs_fc_fcftab_state_xlate(fcftab->state),
3198 emlxs_fcf_event_xlate(evt), arg1,
3199 fcftab->generation,
3200 fcftab->flag);
3201
3202 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
3203 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_FAILED,
3204 FCF_REASON_NO_MBOX, 0, arg1);
3205 return (rval);
3206 }
3207 mb4 = (MAILBOX4*)mbq;
3208 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
3209
3210 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
3211 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3212
3213 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_FAILED,
3214 FCF_REASON_NO_BUFFER, 0, arg1);
3215 return (rval);
3216 }
3217 bzero(mp->virt, mp->size);
3218
3219 mbq->nonembed = NULL;
3220 mbq->bp = (void *)mp;
3221 mbq->mbox_cmpl = emlxs_fc_fcftab_topo_mbcmpl;
3222 mbq->context = (void *)((unsigned long)fcftab->TID);
3223 mbq->port = (void *)port;
3224
3225 mb4->un.varSLIConfig.be.embedded = 0;
3226 mb4->mbxCommand = MBX_READ_TOPOLOGY;
3227 mb4->mbxOwner = OWN_HOST;
3228
3229 mb4->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
3230 mb4->un.varReadLA.un.lilpBde64.addrHigh = PADDR_HI(mp->phys);
3231 mb4->un.varReadLA.un.lilpBde64.addrLow = PADDR_LO(mp->phys);
3232
3233 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3234 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3235 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
3236 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3237
3238 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_FAILED,
3239 FCF_REASON_SEND_FAILED, rval, arg1);
3240
3241 return (rval);
3242 }
3243
3244 return (0);
3245
3246 } /* emlxs_fc_fcftab_topo_action() */
3247
3248
3249 /*ARGSUSED*/
3250 static uint32_t
emlxs_fc_fcftab_topo_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)3251 emlxs_fc_fcftab_topo_failed_action(emlxs_port_t *port, uint32_t evt,
3252 void *arg1)
3253 {
3254 emlxs_hba_t *hba = HBA;
3255 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3256 uint32_t rval = 0;
3257
3258 fcftab->attempts++;
3259
3260 if (fcftab->state != FC_FCFTAB_STATE_TOPO_FAILED) {
3261 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3262 "fc_fcftab_topo_failed_action:%x %s:%s arg=%p "
3263 "attempt=%d. Invalid state. <",
3264 fcftab->TID,
3265 emlxs_fc_fcftab_state_xlate(fcftab->state),
3266 emlxs_fcf_event_xlate(evt),
3267 arg1, fcftab->attempts);
3268 return (1);
3269 }
3270
3271 if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
3272 (fcftab->reason == FCF_REASON_SEND_FAILED) ||
3273 (fcftab->attempts >= 3)) {
3274 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3275 "fc_fcftab_topo_failed_action:%x %s:%s arg=%p "
3276 "attempt=%d reason=%x. Giving up.",
3277 fcftab->TID,
3278 emlxs_fc_fcftab_state_xlate(fcftab->state),
3279 emlxs_fcf_event_xlate(evt), arg1,
3280 fcftab->attempts,
3281 fcftab->reason);
3282
3283 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO_CMPL,
3284 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3285
3286 } else {
3287 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3288 "fc_fcftab_topo_failed_action:%x %s:%s arg=%p "
3289 "attempt=%d reason=%x. Retrying.",
3290 fcftab->TID,
3291 emlxs_fc_fcftab_state_xlate(fcftab->state),
3292 emlxs_fcf_event_xlate(evt), arg1,
3293 fcftab->attempts,
3294 fcftab->reason);
3295
3296 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
3297 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3298 }
3299
3300 return (rval);
3301
3302 } /* emlxs_fc_fcftab_topo_failed_action() */
3303
3304
3305 /*ARGSUSED*/
3306 static uint32_t
emlxs_fc_fcftab_topo_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)3307 emlxs_fc_fcftab_topo_cmpl_action(emlxs_port_t *port, uint32_t evt,
3308 void *arg1)
3309 {
3310 emlxs_hba_t *hba = HBA;
3311 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3312 uint32_t rval = 0;
3313
3314 if (fcftab->state != FC_FCFTAB_STATE_TOPO_CMPL) {
3315 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3316 "fc_fcftab_topo_cmpl_action:%x %s:%s arg=%p. "
3317 "Invalid state. <",
3318 fcftab->TID,
3319 emlxs_fc_fcftab_state_xlate(fcftab->state),
3320 emlxs_fcf_event_xlate(evt), arg1);
3321 return (1);
3322 }
3323
3324 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3325 "fc_fcftab_topo_cmpl_action:%x attempts=%d. "
3326 "Config link.",
3327 fcftab->TID,
3328 fcftab->attempts);
3329
3330 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
3331 FCF_REASON_EVENT, evt, arg1);
3332
3333 return (rval);
3334
3335 } /* emlxs_fc_fcftab_topo_cmpl_action() */
3336
3337
3338 /*ARGSUSED*/
3339 static uint32_t
emlxs_fc_fcftab_cfglink_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)3340 emlxs_fc_fcftab_cfglink_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
3341 {
3342 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
3343 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3344 MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
3345 uint16_t TID;
3346
3347 mutex_enter(&EMLXS_FCF_LOCK);
3348 TID = (uint16_t)((unsigned long)mbq->context);
3349
3350 if (fcftab->state != FC_FCFTAB_STATE_CFGLINK) {
3351 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3352 "fc_fcftab_cfglink_mbcmpl:%x state=%s.",
3353 TID,
3354 emlxs_fc_fcftab_state_xlate(fcftab->state));
3355
3356 mutex_exit(&EMLXS_FCF_LOCK);
3357 return (0);
3358 }
3359
3360 if (TID != fcftab->generation) {
3361 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3362 "fc_fcftab_cfglink_mbcmpl:%x %s. "
3363 "Incorrect generation %x. Dropping.",
3364 TID,
3365 emlxs_fc_fcftab_state_xlate(fcftab->state),
3366 fcftab->generation);
3367
3368 mutex_exit(&EMLXS_FCF_LOCK);
3369 return (0);
3370 }
3371
3372 if (mb4->mbxStatus) {
3373 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3374 "fc_fcftab_cfglink_mbcmpl:%x failed. %s. >",
3375 fcftab->TID,
3376 emlxs_mb_xlate_status(mb4->mbxStatus));
3377
3378 if (mb4->mbxStatus == MBXERR_NO_RESOURCES) {
3379 (void) emlxs_fc_fcftab_state(port,
3380 FC_FCFTAB_STATE_CFGLINK_FAILED,
3381 FCF_REASON_MBOX_BUSY, mb4->mbxStatus, 0);
3382 } else {
3383 (void) emlxs_fc_fcftab_state(port,
3384 FC_FCFTAB_STATE_CFGLINK_FAILED,
3385 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
3386 }
3387
3388 mutex_exit(&EMLXS_FCF_LOCK);
3389 return (0);
3390 }
3391
3392 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3393 "fc_fcftab_cfglink_mbcmpl:%x. >",
3394 fcftab->TID);
3395
3396 (void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK_CMPL,
3397 0, 0, 0);
3398
3399 mutex_exit(&EMLXS_FCF_LOCK);
3400 return (0);
3401
3402 } /* emlxs_fc_fcftab_cfglink_mbcmpl() */
3403
3404
3405
3406 /*ARGSUSED*/
3407 static uint32_t
emlxs_fc_fcftab_cfglink_action(emlxs_port_t * port,uint32_t evt,void * arg1)3408 emlxs_fc_fcftab_cfglink_action(emlxs_port_t *port, uint32_t evt,
3409 void *arg1)
3410 {
3411 emlxs_hba_t *hba = HBA;
3412 emlxs_config_t *cfg = &CFG;
3413 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3414 MAILBOXQ *mbq;
3415 MAILBOX4 *mb4;
3416 uint32_t rval = 0;
3417
3418 if (fcftab->state != FC_FCFTAB_STATE_CFGLINK) {
3419 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3420 "fc_fcftab_cfglink_action:%x %s:%s arg=%p. "
3421 "Invalid state. <",
3422 fcftab->TID,
3423 emlxs_fc_fcftab_state_xlate(fcftab->state),
3424 emlxs_fcf_event_xlate(evt), arg1);
3425 return (1);
3426 }
3427
3428 if ((fcftab->prev_state != FC_FCFTAB_STATE_CFGLINK_FAILED) ||
3429 (fcftab->flag & EMLXS_FC_FCFTAB_CFGLINK_REQ)) {
3430 fcftab->flag &= ~EMLXS_FC_FCFTAB_CFGLINK_REQ;
3431 fcftab->attempts = 0;
3432 }
3433
3434 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3435 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3436 "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3437 "Handling request.",
3438 fcftab->TID,
3439 emlxs_fc_fcftab_state_xlate(fcftab->state),
3440 emlxs_fcf_event_xlate(evt), arg1,
3441 fcftab->generation,
3442 fcftab->flag);
3443
3444 rval = emlxs_fc_fcftab_req_handler(port, arg1);
3445 return (rval);
3446 }
3447
3448 if (fcftab->attempts == 0) {
3449 fcftab->TID = fcftab->generation;
3450 }
3451
3452 if (hba->topology != TOPOLOGY_LOOP) {
3453 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3454 "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3455 "Fabric Topology. Skipping CONFIG_LINK.",
3456 fcftab->TID,
3457 emlxs_fc_fcftab_state_xlate(fcftab->state),
3458 emlxs_fcf_event_xlate(evt), arg1,
3459 fcftab->generation,
3460 fcftab->flag);
3461
3462 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
3463 FCF_REASON_EVENT, evt, arg1);
3464 return (rval);
3465 }
3466
3467 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3468 "fc_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
3469 "Sending CONFIG_LINK. <",
3470 fcftab->TID,
3471 emlxs_fc_fcftab_state_xlate(fcftab->state),
3472 emlxs_fcf_event_xlate(evt), arg1,
3473 fcftab->generation,
3474 fcftab->flag);
3475
3476 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
3477 rval = emlxs_fc_fcftab_state(port,
3478 FC_FCFTAB_STATE_CFGLINK_FAILED,
3479 FCF_REASON_NO_MBOX, 0, arg1);
3480 return (rval);
3481 }
3482 mb4 = (MAILBOX4*)mbq;
3483 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
3484
3485 mbq->nonembed = NULL;
3486 mbq->mbox_cmpl = emlxs_fc_fcftab_cfglink_mbcmpl;
3487 mbq->context = (void *)((unsigned long)fcftab->TID);
3488 mbq->port = (void *)port;
3489
3490 mb4->un.varSLIConfig.be.embedded = 0;
3491 mb4->mbxCommand = MBX_CONFIG_LINK;
3492 mb4->mbxOwner = OWN_HOST;
3493
3494 if (cfg[CFG_CR_DELAY].current) {
3495 mb4->un.varCfgLnk.cr = 1;
3496 mb4->un.varCfgLnk.ci = 1;
3497 mb4->un.varCfgLnk.cr_delay = cfg[CFG_CR_DELAY].current;
3498 mb4->un.varCfgLnk.cr_count = cfg[CFG_CR_COUNT].current;
3499 }
3500
3501 if (cfg[CFG_ACK0].current) {
3502 mb4->un.varCfgLnk.ack0_enable = 1;
3503 }
3504
3505 mb4->un.varCfgLnk.myId = port->did;
3506 mb4->un.varCfgLnk.edtov = hba->fc_edtov;
3507 mb4->un.varCfgLnk.arbtov = hba->fc_arbtov;
3508 mb4->un.varCfgLnk.ratov = hba->fc_ratov;
3509 mb4->un.varCfgLnk.rttov = hba->fc_rttov;
3510 mb4->un.varCfgLnk.altov = hba->fc_altov;
3511 mb4->un.varCfgLnk.crtov = hba->fc_crtov;
3512 mb4->un.varCfgLnk.citov = hba->fc_citov;
3513
3514 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3515 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3516 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3517
3518 rval = emlxs_fc_fcftab_state(port,
3519 FC_FCFTAB_STATE_CFGLINK_FAILED,
3520 FCF_REASON_SEND_FAILED, rval, arg1);
3521
3522 return (rval);
3523 }
3524
3525 return (0);
3526
3527 } /* emlxs_fc_fcftab_cfglink_action() */
3528
3529
3530 /*ARGSUSED*/
3531 static uint32_t
emlxs_fc_fcftab_cfglink_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)3532 emlxs_fc_fcftab_cfglink_failed_action(emlxs_port_t *port, uint32_t evt,
3533 void *arg1)
3534 {
3535 emlxs_hba_t *hba = HBA;
3536 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3537 uint32_t rval = 0;
3538
3539 fcftab->attempts++;
3540
3541 if (fcftab->state != FC_FCFTAB_STATE_CFGLINK_FAILED) {
3542 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3543 "fc_fcftab_cfglink_failed_action:%x %s:%s arg=%p "
3544 "attempt=%d. Invalid state. <",
3545 fcftab->TID,
3546 emlxs_fc_fcftab_state_xlate(fcftab->state),
3547 emlxs_fcf_event_xlate(evt),
3548 arg1, fcftab->attempts);
3549 return (1);
3550 }
3551
3552 if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
3553 (fcftab->reason == FCF_REASON_SEND_FAILED) ||
3554 (fcftab->attempts >= 3)) {
3555 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3556 "fc_fcftab_cfglink_failed_action:%x %s:%s arg=%p "
3557 "attempt=%d reason=%x. Giving up.",
3558 fcftab->TID,
3559 emlxs_fc_fcftab_state_xlate(fcftab->state),
3560 emlxs_fcf_event_xlate(evt), arg1,
3561 fcftab->attempts,
3562 fcftab->reason);
3563
3564 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK_CMPL,
3565 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3566
3567 } else {
3568 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3569 "fc_fcftab_cfglink_failed_action:%x %s:%s arg=%p "
3570 "attempt=%d reason=%x. Retrying.",
3571 fcftab->TID,
3572 emlxs_fc_fcftab_state_xlate(fcftab->state),
3573 emlxs_fcf_event_xlate(evt), arg1,
3574 fcftab->attempts,
3575 fcftab->reason);
3576
3577 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
3578 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3579 }
3580
3581 return (rval);
3582
3583 } /* emlxs_fc_fcftab_cfglink_failed_action() */
3584
3585
3586 /*ARGSUSED*/
3587 static uint32_t
emlxs_fc_fcftab_cfglink_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)3588 emlxs_fc_fcftab_cfglink_cmpl_action(emlxs_port_t *port, uint32_t evt,
3589 void *arg1)
3590 {
3591 emlxs_hba_t *hba = HBA;
3592 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3593 uint32_t rval = 0;
3594
3595 if (fcftab->state != FC_FCFTAB_STATE_CFGLINK_CMPL) {
3596 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3597 "fc_fcftab_cfglink_cmpl_action:%x %s:%s arg=%p. "
3598 "Invalid state. <",
3599 fcftab->TID,
3600 emlxs_fc_fcftab_state_xlate(fcftab->state),
3601 emlxs_fcf_event_xlate(evt), arg1);
3602 return (1);
3603 }
3604
3605 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3606 "fc_fcftab_cfglink_cmpl_action:%x attempts=%d. "
3607 "Read SPARM.",
3608 fcftab->TID,
3609 fcftab->attempts);
3610
3611 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
3612 FCF_REASON_EVENT, evt, arg1);
3613
3614 return (rval);
3615
3616 } /* emlxs_fc_fcftab_cfglink_cmpl_action() */
3617
3618
3619 /*ARGSUSED*/
3620 static uint32_t
emlxs_fc_fcftab_sparm_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)3621 emlxs_fc_fcftab_sparm_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
3622 {
3623 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
3624 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3625 MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
3626 MATCHMAP *mp;
3627 emlxs_port_t *vport;
3628 VPIobj_t *vpip;
3629 int32_t i;
3630 uint8_t null_wwn[8];
3631 uint16_t TID;
3632
3633 mutex_enter(&EMLXS_FCF_LOCK);
3634 TID = (uint16_t)((unsigned long)mbq->context);
3635
3636 if (fcftab->state != FC_FCFTAB_STATE_SPARM) {
3637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3638 "fc_fcftab_sparm_mbcmpl:%x state=%s.",
3639 TID,
3640 emlxs_fc_fcftab_state_xlate(fcftab->state));
3641
3642 mutex_exit(&EMLXS_FCF_LOCK);
3643 return (0);
3644 }
3645
3646 if (TID != fcftab->generation) {
3647 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3648 "fc_fcftab_sparm_mbcmpl:%x %s. "
3649 "Incorrect generation %x. Dropping.",
3650 TID,
3651 emlxs_fc_fcftab_state_xlate(fcftab->state),
3652 fcftab->generation);
3653
3654 mutex_exit(&EMLXS_FCF_LOCK);
3655 return (0);
3656 }
3657
3658 if (mb4->mbxStatus) {
3659 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3660 "fc_fcftab_sparm_mbcmpl:%x failed. %s. >",
3661 fcftab->TID,
3662 emlxs_mb_xlate_status(mb4->mbxStatus));
3663
3664 if (mb4->mbxStatus == MBXERR_NO_RESOURCES) {
3665 (void) emlxs_fc_fcftab_state(port,
3666 FC_FCFTAB_STATE_SPARM_FAILED,
3667 FCF_REASON_MBOX_BUSY, mb4->mbxStatus, 0);
3668 } else {
3669 (void) emlxs_fc_fcftab_state(port,
3670 FC_FCFTAB_STATE_SPARM_FAILED,
3671 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
3672 }
3673
3674 mutex_exit(&EMLXS_FCF_LOCK);
3675 return (0);
3676 }
3677
3678 /* Save the parameters */
3679 mp = (MATCHMAP *)mbq->bp;
3680 bcopy((caddr_t)mp->virt, (caddr_t)&hba->sparam, sizeof (SERV_PARM));
3681
3682 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3683 "fc_fcftab_sparm_mbcmpl:%x edtov=%x,%x bbc=%x. >",
3684 fcftab->TID,
3685 hba->fc_edtov, hba->sparam.cmn.e_d_tov,
3686 hba->sparam.cmn.bbCreditlsb);
3687
3688 /* Initialize the node name and port name only once */
3689 bzero(null_wwn, 8);
3690 if ((bcmp((caddr_t)&hba->wwnn, (caddr_t)null_wwn, 8) == 0) &&
3691 (bcmp((caddr_t)&hba->wwpn, (caddr_t)null_wwn, 8) == 0)) {
3692 bcopy((caddr_t)&hba->sparam.nodeName,
3693 (caddr_t)&hba->wwnn, sizeof (NAME_TYPE));
3694
3695 bcopy((caddr_t)&hba->sparam.portName,
3696 (caddr_t)&hba->wwpn, sizeof (NAME_TYPE));
3697 } else {
3698 bcopy((caddr_t)&hba->wwnn,
3699 (caddr_t)&hba->sparam.nodeName, sizeof (NAME_TYPE));
3700
3701 bcopy((caddr_t)&hba->wwpn,
3702 (caddr_t)&hba->sparam.portName, sizeof (NAME_TYPE));
3703 }
3704
3705 /* Update all bound ports */
3706 for (i = 0; i < MAX_VPORTS; i++) {
3707 vport = &VPORT(i);
3708 vpip = vport->vpip;
3709
3710 if (!(vport->flag & EMLXS_PORT_BOUND) ||
3711 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
3712 continue;
3713 }
3714
3715 bcopy((caddr_t)&hba->sparam,
3716 (caddr_t)&vport->sparam,
3717 sizeof (SERV_PARM));
3718
3719 bcopy((caddr_t)&vport->wwnn,
3720 (caddr_t)&vport->sparam.nodeName,
3721 sizeof (NAME_TYPE));
3722
3723 bcopy((caddr_t)&vport->wwpn,
3724 (caddr_t)&vport->sparam.portName,
3725 sizeof (NAME_TYPE));
3726 }
3727
3728 (void) emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM_CMPL,
3729 0, 0, 0);
3730
3731 mutex_exit(&EMLXS_FCF_LOCK);
3732 return (0);
3733
3734 } /* emlxs_fc_fcftab_sparm_mbcmpl() */
3735
3736
3737 /*ARGSUSED*/
3738 static uint32_t
emlxs_fc_fcftab_sparm_action(emlxs_port_t * port,uint32_t evt,void * arg1)3739 emlxs_fc_fcftab_sparm_action(emlxs_port_t *port, uint32_t evt,
3740 void *arg1)
3741 {
3742 emlxs_hba_t *hba = HBA;
3743 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3744 MAILBOXQ *mbq;
3745 MAILBOX4 *mb4;
3746 uint32_t rval = 0;
3747 MATCHMAP *mp;
3748
3749 if (fcftab->state != FC_FCFTAB_STATE_SPARM) {
3750 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3751 "fc_fcftab_sparm_action:%x %s:%s arg=%p. "
3752 "Invalid state. <",
3753 fcftab->TID,
3754 emlxs_fc_fcftab_state_xlate(fcftab->state),
3755 emlxs_fcf_event_xlate(evt), arg1);
3756 return (1);
3757 }
3758
3759 if ((fcftab->prev_state != FC_FCFTAB_STATE_SPARM_FAILED) ||
3760 (fcftab->flag & EMLXS_FC_FCFTAB_SPARM_REQ)) {
3761 fcftab->flag &= ~EMLXS_FC_FCFTAB_SPARM_REQ;
3762 fcftab->attempts = 0;
3763 }
3764
3765 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
3766 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3767 "fc_fcftab_read_action:%x %s:%s arg=%p flag=%x. "
3768 "Handling request.",
3769 fcftab->TID,
3770 emlxs_fc_fcftab_state_xlate(fcftab->state),
3771 emlxs_fcf_event_xlate(evt), arg1,
3772 fcftab->flag);
3773
3774 rval = emlxs_fc_fcftab_req_handler(port, arg1);
3775 return (rval);
3776 }
3777
3778 if (fcftab->attempts == 0) {
3779 fcftab->TID = fcftab->generation;
3780 }
3781
3782 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3783 "fc_fcftab_read_action:%x %s:%s arg=%p attempts=%d. "
3784 "Reading SPARM. <",
3785 fcftab->TID,
3786 emlxs_fc_fcftab_state_xlate(fcftab->state),
3787 emlxs_fcf_event_xlate(evt), arg1,
3788 fcftab->attempts);
3789
3790 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
3791 rval = emlxs_fc_fcftab_state(port,
3792 FC_FCFTAB_STATE_SPARM_FAILED,
3793 FCF_REASON_NO_MBOX, 0, arg1);
3794 return (rval);
3795 }
3796 mb4 = (MAILBOX4*)mbq;
3797 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
3798
3799 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
3800 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3801
3802 rval = emlxs_fc_fcftab_state(port,
3803 FC_FCFTAB_STATE_SPARM_FAILED,
3804 FCF_REASON_NO_BUFFER, 0, arg1);
3805 return (rval);
3806 }
3807 bzero(mp->virt, mp->size);
3808
3809 mbq->nonembed = NULL;
3810 mbq->bp = (void *)mp;
3811 mbq->mbox_cmpl = emlxs_fc_fcftab_sparm_mbcmpl;
3812 mbq->context = (void *)((unsigned long)fcftab->TID);
3813 mbq->port = (void *)port;
3814
3815 mb4->un.varSLIConfig.be.embedded = 0;
3816 mb4->mbxCommand = MBX_READ_SPARM64;
3817 mb4->mbxOwner = OWN_HOST;
3818
3819 mb4->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
3820 mb4->un.varRdSparm.un.sp64.addrHigh = PADDR_HI(mp->phys);
3821 mb4->un.varRdSparm.un.sp64.addrLow = PADDR_LO(mp->phys);
3822
3823 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3824 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3825 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
3826 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3827
3828 rval = emlxs_fc_fcftab_state(port,
3829 FC_FCFTAB_STATE_SPARM_FAILED,
3830 FCF_REASON_SEND_FAILED, rval, arg1);
3831
3832 return (rval);
3833 }
3834
3835 return (0);
3836
3837 } /* emlxs_fc_fcftab_sparm_action() */
3838
3839
3840 /*ARGSUSED*/
3841 static uint32_t
emlxs_fc_fcftab_sparm_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)3842 emlxs_fc_fcftab_sparm_failed_action(emlxs_port_t *port, uint32_t evt,
3843 void *arg1)
3844 {
3845 emlxs_hba_t *hba = HBA;
3846 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3847 uint32_t rval = 0;
3848
3849 fcftab->attempts++;
3850
3851 if (fcftab->state != FC_FCFTAB_STATE_SPARM_FAILED) {
3852 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3853 "fc_fcftab_sparm_failed_action:%x %s:%s arg=%p "
3854 "attempt=%d. Invalid state. <",
3855 fcftab->TID,
3856 emlxs_fc_fcftab_state_xlate(fcftab->state),
3857 emlxs_fcf_event_xlate(evt),
3858 arg1, fcftab->attempts);
3859 return (1);
3860 }
3861
3862 if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
3863 (fcftab->reason == FCF_REASON_SEND_FAILED) ||
3864 (fcftab->attempts >= 3)) {
3865 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3866 "fc_fcftab_read_failed_action:%x %s:%s arg=%p "
3867 "attempt=%d reason=%x. Giving up.",
3868 fcftab->TID,
3869 emlxs_fc_fcftab_state_xlate(fcftab->state),
3870 emlxs_fcf_event_xlate(evt), arg1,
3871 fcftab->attempts,
3872 fcftab->reason);
3873
3874 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM_CMPL,
3875 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3876 } else {
3877 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3878 "fc_fcftab_read_failed_action:%x %s:%s arg=%p "
3879 "attempt=%d reason=%x. Retrying.",
3880 fcftab->TID,
3881 emlxs_fc_fcftab_state_xlate(fcftab->state),
3882 emlxs_fcf_event_xlate(evt), arg1,
3883 fcftab->attempts,
3884 fcftab->reason);
3885
3886 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
3887 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
3888 }
3889
3890 return (rval);
3891
3892 } /* emlxs_fc_fcftab_sparm_failed_action() */
3893
3894
3895 /*ARGSUSED*/
3896 static uint32_t
emlxs_fc_fcftab_sparm_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)3897 emlxs_fc_fcftab_sparm_cmpl_action(emlxs_port_t *port, uint32_t evt,
3898 void *arg1)
3899 {
3900 emlxs_hba_t *hba = HBA;
3901 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3902 uint32_t rval = 0;
3903
3904 if (fcftab->state != FC_FCFTAB_STATE_SPARM_CMPL) {
3905 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
3906 "fc_fcftab_sparm_cmpl_action:%x %s:%s arg=%p. "
3907 "Invalid state. <",
3908 fcftab->TID,
3909 emlxs_fc_fcftab_state_xlate(fcftab->state),
3910 emlxs_fcf_event_xlate(evt), arg1);
3911 return (1);
3912 }
3913
3914 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3915 "fc_fcftab_sparm_cmpl_action:%x attempts=%d. "
3916 "Bring FCFTAB online.",
3917 fcftab->TID,
3918 fcftab->attempts);
3919
3920 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE,
3921 FCF_REASON_EVENT, evt, arg1);
3922
3923 return (rval);
3924
3925 } /* emlxs_fc_fcftab_sparm_cmpl_action() */
3926
3927
3928 /*ARGSUSED*/
3929 static void
emlxs_fc_fcftab_process(emlxs_port_t * port)3930 emlxs_fc_fcftab_process(emlxs_port_t *port)
3931 {
3932 emlxs_hba_t *hba = HBA;
3933 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
3934 FCFIobj_t *fcfp;
3935 FCF_RECORD_t fcf_record;
3936 FCF_RECORD_t *fcf_rec;
3937 uint8_t bitmap[512];
3938 uint16_t i;
3939
3940 /* Get the FCFI */
3941 fcfp = fcftab->fcfi[0];
3942
3943 if (!fcfp) {
3944 /* Allocate an fcfi */
3945 fcfp = emlxs_fcfi_alloc(port);
3946 }
3947
3948 if (!fcfp) {
3949 fcftab->fcfi_count = 0;
3950
3951 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3952 "fc_fcftab_process:%x No FCF available.",
3953 fcftab->TID);
3954 return;
3955 }
3956
3957 if (fcfp->flag & EMLXS_FCFI_SELECTED) {
3958 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3959 "fc_fcftab_process:%x fcfi=%d %s. "
3960 "FCF still selected.",
3961 fcftab->TID,
3962 fcfp->fcf_index,
3963 emlxs_fcfi_state_xlate(fcfp->state));
3964 } else {
3965 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
3966 "fc_fcftab_process:%x fcfi=%d %s. "
3967 "New FCF selected.",
3968 fcftab->TID,
3969 fcfp->fcf_index,
3970 emlxs_fcfi_state_xlate(fcfp->state));
3971 }
3972
3973 /* Initalize an fcf_rec */
3974 fcf_rec = &fcf_record;
3975 bzero(fcf_rec, sizeof (FCF_RECORD_t));
3976
3977 fcf_rec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ;
3978 fcf_rec->fka_adv_period = 0;
3979 fcf_rec->fip_priority = 128;
3980
3981 #ifdef EMLXS_BIG_ENDIAN
3982 fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3;
3983 fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2;
3984 fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1;
3985 fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0;
3986 fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC5;
3987 fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC4;
3988 fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2];
3989 fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
3990 fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0];
3991 #endif /* EMLXS_BIG_ENDIAN */
3992 #ifdef EMLXS_LITTLE_ENDIAN
3993 fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0;
3994 fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1;
3995 fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2;
3996 fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3;
3997 fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC4;
3998 fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC5;
3999 fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0];
4000 fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
4001 fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2];
4002 #endif /* EMLXS_LITTLE_ENDIAN */
4003
4004 if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) {
4005 bzero((void *) bitmap, 512);
4006 i = hba->sli.sli4.cfgFCOE.VLanId;
4007 bitmap[i / 8] = (1 << (i % 8));
4008 BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
4009 } else {
4010 bzero((void *) bitmap, 512);
4011 bitmap[0] = 1; /* represents bit 0 */
4012 BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
4013 }
4014
4015 fcf_rec->fcf_valid = 1;
4016 fcf_rec->fcf_available = 1;
4017
4018 /* Update the FCFI */
4019 emlxs_fcfi_update(port, fcfp, fcf_rec, hba->link_event_tag);
4020
4021 /* Select the FCFI */
4022 fcfp->flag &= ~EMLXS_FCFI_FAILED;
4023 fcfp->flag |= EMLXS_FCFI_SELECTED;
4024 fcftab->fcfi[0] = fcfp;
4025 fcftab->fcfi_count = 1;
4026
4027 return;
4028
4029 } /* emlxs_fc_fcftab_process() */
4030
4031
4032 /*ARGSUSED*/
4033 static uint32_t
emlxs_fc_fcftab_fcfi_online_action(emlxs_port_t * port,uint32_t evt,void * arg1)4034 emlxs_fc_fcftab_fcfi_online_action(emlxs_port_t *port, uint32_t evt,
4035 void *arg1)
4036 {
4037 emlxs_hba_t *hba = HBA;
4038 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4039 uint32_t rval = 0;
4040 FCFIobj_t *fcfp;
4041
4042 if (fcftab->state != FC_FCFTAB_STATE_FCFI_ONLINE) {
4043 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4044 "fc_fcftab_fcfi_online_action:%x %s:%s arg=%p. "
4045 "Invalid state. <",
4046 fcftab->TID,
4047 emlxs_fc_fcftab_state_xlate(fcftab->state),
4048 emlxs_fcf_event_xlate(evt), arg1);
4049 return (1);
4050 }
4051
4052 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
4053 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4054 "fc_fcftab_fcfi_online_action:%x flag=%x. "
4055 "Handling request.",
4056 fcftab->TID,
4057 fcftab->flag);
4058
4059 rval = emlxs_fc_fcftab_req_handler(port, arg1);
4060 return (rval);
4061 }
4062
4063 emlxs_fc_fcftab_process(port);
4064
4065 fcfp = fcftab->fcfi[0];
4066 if (!fcfp) {
4067 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4068 "fc_fcftab_fcfi_online_action:%x. "
4069 "No FCF available. Offlining.",
4070 fcftab->TID);
4071
4072 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4073 fcftab->flag |= EMLXS_FC_FCFTAB_OFFLINE_REQ;
4074 rval = emlxs_fc_fcftab_req_handler(port, arg1);
4075
4076 mutex_exit(&EMLXS_FCF_LOCK);
4077 return (rval);
4078 }
4079
4080 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4081 "fc_fcftab_fcfi_online_action:%x fcfi_count=%d. "
4082 "Onlining FCFI:%d. >",
4083 fcftab->TID,
4084 fcftab->fcfi_count,
4085 fcfp->fcf_index);
4086
4087 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_ONLINE, fcfp);
4088
4089 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE_CMPL,
4090 FCF_REASON_EVENT, evt, arg1);
4091
4092 return (rval);
4093
4094 } /* emlxs_fc_fcftab_fcfi_online_action() */
4095
4096
4097 /*ARGSUSED*/
4098 static uint32_t
emlxs_fc_fcftab_fcfi_online_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)4099 emlxs_fc_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, uint32_t evt,
4100 void *arg1)
4101 {
4102 emlxs_hba_t *hba = HBA;
4103 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4104 uint32_t rval = 0;
4105
4106 if (fcftab->state != FC_FCFTAB_STATE_FCFI_ONLINE_CMPL) {
4107 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4108 "fc_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p. "
4109 "Invalid state. <",
4110 fcftab->TID,
4111 emlxs_fc_fcftab_state_xlate(fcftab->state),
4112 emlxs_fcf_event_xlate(evt), arg1);
4113 return (1);
4114 }
4115
4116 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
4117 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4118 "fc_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p "
4119 "flag=%x. Handling request.",
4120 fcftab->TID,
4121 emlxs_fc_fcftab_state_xlate(fcftab->state),
4122 emlxs_fcf_event_xlate(evt), arg1,
4123 fcftab->flag);
4124
4125 rval = emlxs_fc_fcftab_req_handler(port, arg1);
4126 return (rval);
4127 }
4128
4129 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4130 "fc_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p. "
4131 "Going online.",
4132 fcftab->TID,
4133 emlxs_fc_fcftab_state_xlate(fcftab->state),
4134 emlxs_fcf_event_xlate(evt), arg1);
4135
4136 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_ONLINE,
4137 FCF_REASON_EVENT, evt, arg1);
4138
4139 return (rval);
4140
4141 } /* emlxs_fc_fcftab_fcfi_online_cmpl_action() */
4142
4143
4144 /*ARGSUSED*/
4145 static uint32_t
emlxs_fc_fcftab_fcfi_offline_action(emlxs_port_t * port,uint32_t evt,void * arg1)4146 emlxs_fc_fcftab_fcfi_offline_action(emlxs_port_t *port, uint32_t evt,
4147 void *arg1)
4148 {
4149 emlxs_hba_t *hba = HBA;
4150 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4151 uint32_t rval = 0;
4152 FCFIobj_t *fcfp;
4153
4154 if (fcftab->state != FC_FCFTAB_STATE_FCFI_OFFLINE) {
4155 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4156 "fc_fcftab_fcftab_offline_action:%x %s:%s arg=%p. "
4157 "Invalid state. <",
4158 fcftab->TID,
4159 emlxs_fc_fcftab_state_xlate(fcftab->state),
4160 emlxs_fcf_event_xlate(evt), arg1);
4161 return (1);
4162 }
4163
4164 if (fcftab->fcfi_online) {
4165 fcfp = fcftab->fcfi[0];
4166
4167 if (!(fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
4168 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4169 "fc_fcftab_fcfi_offline_action:%d. "
4170 "Offlining FCFI:%d. >",
4171 fcftab->TID,
4172 fcfp->fcf_index);
4173
4174 rval = emlxs_fcfi_event(port,
4175 FCF_EVENT_FCFI_OFFLINE, fcfp);
4176
4177 return (rval);
4178 }
4179
4180 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4181 "fc_fcftab_fcfi_offline_action:%x fcfi_online=%d. "
4182 "Waiting on FCF. <",
4183 fcftab->TID,
4184 fcftab->fcfi_online);
4185
4186 return (0);
4187 }
4188
4189 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4190 "fc_fcftab_fcfi_offline_action:%x %s:%s arg=%p.",
4191 fcftab->TID,
4192 emlxs_fc_fcftab_state_xlate(fcftab->state),
4193 emlxs_fcf_event_xlate(evt), arg1);
4194
4195 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
4196 FCF_REASON_EVENT, evt, arg1);
4197
4198 return (rval);
4199
4200 } /* emlxs_fc_fcftab_fcfi_offline_action() */
4201
4202
4203 /*ARGSUSED*/
4204 static uint32_t
emlxs_fc_fcftab_fcfi_offline_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)4205 emlxs_fc_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, uint32_t evt,
4206 void *arg1)
4207 {
4208 emlxs_hba_t *hba = HBA;
4209 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4210 uint32_t rval = 0;
4211
4212 if (fcftab->state != FC_FCFTAB_STATE_FCFI_OFFLINE_CMPL) {
4213 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4214 "fc_fcftab_fcftab_offline_cmpl_action:%x %s:%s arg=%p. "
4215 "Invalid state. <",
4216 fcftab->TID,
4217 emlxs_fc_fcftab_state_xlate(fcftab->state),
4218 emlxs_fcf_event_xlate(evt), arg1);
4219 return (1);
4220 }
4221
4222 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
4223 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4224 "fc_fcftab_fcfi_offline_cmpl_action:%x %s:%s arg=%p. "
4225 "Handling request.",
4226 fcftab->TID,
4227 emlxs_fc_fcftab_state_xlate(fcftab->state),
4228 emlxs_fcf_event_xlate(evt), arg1);
4229
4230 rval = emlxs_fc_fcftab_req_handler(port, arg1);
4231 return (rval);
4232 }
4233
4234 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4235 "fc_fcftab_fcftab_offline_cmpl_action:%x %s:%s arg=%p. "
4236 "Returning FCF(s) online.",
4237 fcftab->TID,
4238 emlxs_fc_fcftab_state_xlate(fcftab->state),
4239 emlxs_fcf_event_xlate(evt), arg1);
4240
4241 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE,
4242 FCF_REASON_EVENT, evt, arg1);
4243
4244 return (rval);
4245
4246 } /* emlxs_fc_fcftab_fcfi_offline_cmpl_action() */
4247
4248
4249 /*ARGSUSED*/
4250 static uint32_t
emlxs_fc_fcftab_linkup_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4251 emlxs_fc_fcftab_linkup_evt_action(emlxs_port_t *port, uint32_t evt,
4252 void *arg1)
4253 {
4254 emlxs_hba_t *hba = HBA;
4255 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4256 uint32_t rval = 0;
4257
4258 if (evt != FCF_EVENT_LINKUP) {
4259 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4260 "fc_fcftab_linkup_evt_action:%x %s:%s arg=%p flag=%x. "
4261 "Invalid event type. <",
4262 fcftab->TID,
4263 emlxs_fc_fcftab_state_xlate(fcftab->state),
4264 emlxs_fcf_event_xlate(evt), arg1,
4265 fcftab->flag);
4266 return (1);
4267 }
4268
4269 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4270 "fc_fcftab_linkup_evt_action:%x %s:%s arg=%p gen=%x. Link up.",
4271 fcftab->TID,
4272 emlxs_fc_fcftab_state_xlate(fcftab->state),
4273 emlxs_fcf_event_xlate(evt), arg1,
4274 fcftab->generation);
4275
4276 emlxs_fcf_linkup(port);
4277
4278 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4279 fcftab->flag |= EMLXS_FC_FCFTAB_TOPO_REQ;
4280 fcftab->generation++;
4281
4282 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4283 "fc_fcftab_linkup_evt_action:%x %s gen=%x. "
4284 "Read topology.",
4285 fcftab->TID,
4286 emlxs_fc_fcftab_state_xlate(fcftab->state),
4287 fcftab->generation);
4288
4289 switch (fcftab->state) {
4290 case FC_FCFTAB_STATE_TOPO:
4291 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
4292 FCF_REASON_REENTER, evt, arg1);
4293 break;
4294
4295 default:
4296 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
4297 FCF_REASON_EVENT, evt, arg1);
4298 break;
4299 }
4300
4301 return (rval);
4302
4303 } /* emlxs_fc_fcftab_linkup_evt_action() */
4304
4305
4306 /*ARGSUSED*/
4307 static uint32_t
emlxs_fc_fcftab_linkdown_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4308 emlxs_fc_fcftab_linkdown_evt_action(emlxs_port_t *port, uint32_t evt,
4309 void *arg1)
4310 {
4311 emlxs_hba_t *hba = HBA;
4312 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4313 uint32_t rval = 0;
4314 uint32_t i;
4315 FCFIobj_t *fcfp;
4316
4317 if (evt != FCF_EVENT_LINKDOWN) {
4318 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4319 "fc_fcftab_linkdown_evt_action:%x %s:%s arg=%p flag=%x. "
4320 "Invalid event type. <",
4321 fcftab->TID,
4322 emlxs_fc_fcftab_state_xlate(fcftab->state),
4323 emlxs_fcf_event_xlate(evt), arg1,
4324 fcftab->flag);
4325 return (1);
4326 }
4327
4328 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4329 fcftab->flag |= EMLXS_FC_FCFTAB_OFFLINE_REQ;
4330
4331 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4332 "fc_fcftab_linkdown_evt_action:%x %s:%s arg=%p flag=%x. Linkdown.",
4333 fcftab->TID,
4334 emlxs_fc_fcftab_state_xlate(fcftab->state),
4335 emlxs_fcf_event_xlate(evt), arg1,
4336 fcftab->flag);
4337
4338 emlxs_fcf_linkdown(port);
4339
4340 /* Pause all active FCFI's */
4341 for (i = 0; i < fcftab->fcfi_count; i++) {
4342 fcfp = fcftab->fcfi[i];
4343
4344 if ((fcfp->state == FCFI_STATE_OFFLINE) ||
4345 (fcfp->state == FCFI_STATE_PAUSED)) {
4346 break;
4347 }
4348
4349 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4350 "fc_fcftab_linkdown_evt_action:%x. "
4351 "Pausing FCFI:%d. >",
4352 fcftab->TID,
4353 fcfp->fcf_index);
4354
4355 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_PAUSE, fcfp);
4356 }
4357
4358 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4359 "fc_fcftab_linkdown_evt_action:%x "
4360 "Going offline.",
4361 fcftab->TID);
4362
4363 switch (fcftab->state) {
4364 case FC_FCFTAB_STATE_OFFLINE:
4365 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_OFFLINE,
4366 FCF_REASON_REENTER, evt, arg1);
4367 break;
4368
4369 default:
4370 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_OFFLINE,
4371 FCF_REASON_EVENT, evt, arg1);
4372 break;
4373 }
4374
4375 return (rval);
4376
4377 } /* emlxs_fc_fcftab_linkdown_evt_action() */
4378
4379
4380 /*ARGSUSED*/
4381 static uint32_t
emlxs_fc_fcftab_fcfi_offline_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4382 emlxs_fc_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, uint32_t evt,
4383 void *arg1)
4384 {
4385 emlxs_hba_t *hba = HBA;
4386 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4387 uint32_t rval = 0;
4388 FCFIobj_t *fcfp;
4389
4390 if (evt != FCF_EVENT_FCFI_OFFLINE) {
4391 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4392 "fc_fcftab_fcftab_offline_evt_action:%x %s:%s arg=%p "
4393 "flag=%x. Invalid event type. <",
4394 fcftab->TID,
4395 emlxs_fc_fcftab_state_xlate(fcftab->state),
4396 emlxs_fcf_event_xlate(evt), arg1,
4397 fcftab->flag);
4398 return (1);
4399 }
4400
4401 fcfp = (FCFIobj_t *)arg1;
4402
4403 switch (fcftab->state) {
4404 case FC_FCFTAB_STATE_SHUTDOWN:
4405 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4406 "fc_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4407 "Shutting down.",
4408 fcftab->TID,
4409 fcfp->fcf_index);
4410
4411 /* This will trigger final shutdown */
4412 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SHUTDOWN,
4413 FCF_REASON_REENTER, evt, arg1);
4414 break;
4415
4416 case FC_FCFTAB_STATE_FCFI_OFFLINE:
4417 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4418 "fc_fcftab_fcfi_offline_evt_action:%x fcfi:%d. Offlining.",
4419 fcftab->TID,
4420 fcfp->fcf_index);
4421
4422 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_OFFLINE,
4423 FCF_REASON_REENTER, evt, arg1);
4424 break;
4425
4426 case FC_FCFTAB_STATE_FCFI_ONLINE:
4427 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4428 "fc_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4429 "Retrying FCF.",
4430 fcftab->TID,
4431 fcfp->fcf_index);
4432
4433 fcfp->flag |= EMLXS_FCFI_FAILED;
4434
4435 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_FCFI_ONLINE,
4436 FCF_REASON_REENTER, evt, arg1);
4437 break;
4438
4439 case FC_FCFTAB_STATE_ONLINE:
4440 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4441 "fc_fcftab_fcfi_offline_evt_action:%x fcfi:%d.",
4442 fcftab->TID,
4443 fcfp->fcf_index);
4444
4445 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_ONLINE,
4446 FCF_REASON_REENTER, evt, arg1);
4447 break;
4448
4449 default:
4450 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4451 "fc_fcftab_fcfi_offline_evt_action:%x %s fcfi:%d.",
4452 fcftab->TID,
4453 emlxs_fc_fcftab_state_xlate(fcftab->state),
4454 fcfp->fcf_index);
4455 break;
4456 }
4457
4458 return (rval);
4459
4460 } /* emlxs_fc_fcftab_fcfi_offline_evt_action() */
4461
4462
4463 /*ARGSUSED*/
4464 static uint32_t
emlxs_fc_fcftab_fcfi_online_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4465 emlxs_fc_fcftab_fcfi_online_evt_action(emlxs_port_t *port, uint32_t evt,
4466 void *arg1)
4467 {
4468 emlxs_hba_t *hba = HBA;
4469 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4470 uint32_t rval = 0;
4471 FCFIobj_t *fcfp;
4472
4473 if (evt != FCF_EVENT_FCFI_ONLINE) {
4474 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4475 "fc_fcftab_fcftab_online_evt_action:%x %s:%s arg=%p "
4476 "flag=%x. Invalid event type. <",
4477 fcftab->TID,
4478 emlxs_fc_fcftab_state_xlate(fcftab->state),
4479 emlxs_fcf_event_xlate(evt), arg1,
4480 fcftab->flag);
4481 return (1);
4482 }
4483
4484 fcfp = (FCFIobj_t *)arg1;
4485
4486 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4487 "fc_fcftab_fcfi_online_evt_action:%d fcfi:%d. <",
4488 fcftab->TID,
4489 fcfp->fcf_index);
4490
4491 return (rval);
4492
4493 } /* emlxs_fc_fcftab_fcfi_online_evt_action() */
4494
4495
4496 /*ARGSUSED*/
4497 static uint32_t
emlxs_fc_fcftab_shutdown_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4498 emlxs_fc_fcftab_shutdown_evt_action(emlxs_port_t *port, uint32_t evt,
4499 void *arg1)
4500 {
4501 emlxs_hba_t *hba = HBA;
4502 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4503 uint32_t rval = 0;
4504
4505 if (evt != FCF_EVENT_SHUTDOWN) {
4506 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4507 "fc_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
4508 "Invalid event type. <",
4509 fcftab->TID,
4510 emlxs_fc_fcftab_state_xlate(fcftab->state),
4511 emlxs_fcf_event_xlate(evt), arg1,
4512 fcftab->flag);
4513 return (1);
4514 }
4515
4516 if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) {
4517 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4518 "fc_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
4519 "Already shut down. <",
4520 fcftab->TID,
4521 emlxs_fc_fcftab_state_xlate(fcftab->state),
4522 emlxs_fcf_event_xlate(evt), arg1,
4523 fcftab->flag);
4524 return (1);
4525 }
4526
4527 if (fcftab->state == FC_FCFTAB_STATE_SHUTDOWN) {
4528 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4529 "fc_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
4530 "Already shutting down. <",
4531 fcftab->TID,
4532 emlxs_fc_fcftab_state_xlate(fcftab->state),
4533 emlxs_fcf_event_xlate(evt), arg1,
4534 fcftab->flag);
4535 return (1);
4536 }
4537
4538 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4539 "fc_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
4540 "Shutting down.",
4541 fcftab->TID,
4542 emlxs_fc_fcftab_state_xlate(fcftab->state),
4543 emlxs_fcf_event_xlate(evt), arg1,
4544 fcftab->flag);
4545
4546 emlxs_fcf_linkdown(port);
4547
4548 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SHUTDOWN,
4549 FCF_REASON_EVENT, evt, arg1);
4550
4551 return (rval);
4552
4553 } /* emlxs_fc_fcftab_shutdown_evt_action() */
4554
4555
4556 static uint32_t
emlxs_fc_fcftab_req_handler(emlxs_port_t * port,void * arg1)4557 emlxs_fc_fcftab_req_handler(emlxs_port_t *port, void *arg1)
4558 {
4559 emlxs_hba_t *hba = HBA;
4560 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4561 uint32_t rval = 0;
4562
4563 if (!(fcftab->flag & EMLXS_FCFTAB_REQ_MASK)) {
4564 return (1);
4565 }
4566
4567 if (fcftab->flag & EMLXS_FC_FCFTAB_OFFLINE_REQ) {
4568 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_OFFLINE,
4569 FCF_REASON_REQUESTED, 0, arg1);
4570 }
4571
4572 else if (fcftab->flag & EMLXS_FC_FCFTAB_TOPO_REQ) {
4573 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_TOPO,
4574 FCF_REASON_REQUESTED, 0, arg1);
4575 }
4576
4577 else if (fcftab->flag & EMLXS_FC_FCFTAB_CFGLINK_REQ) {
4578 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_CFGLINK,
4579 FCF_REASON_REQUESTED, 0, arg1);
4580 }
4581
4582 else if (fcftab->flag & EMLXS_FC_FCFTAB_SPARM_REQ) {
4583 rval = emlxs_fc_fcftab_state(port, FC_FCFTAB_STATE_SPARM,
4584 FCF_REASON_REQUESTED, 0, arg1);
4585 }
4586
4587 return (rval);
4588
4589 } /* emlxs_fc_fcftab_req_handler() */
4590
4591
4592
4593 /* ************************************************************************** */
4594 /* FCOE FCFTAB */
4595 /* ************************************************************************** */
4596
4597 static char *
emlxs_fcoe_fcftab_state_xlate(uint32_t state)4598 emlxs_fcoe_fcftab_state_xlate(uint32_t state)
4599 {
4600 static char buffer[32];
4601 uint32_t i;
4602 uint32_t count;
4603
4604 count = sizeof (emlxs_fcoe_fcftab_state_table) / sizeof (emlxs_table_t);
4605 for (i = 0; i < count; i++) {
4606 if (state == emlxs_fcoe_fcftab_state_table[i].code) {
4607 return (emlxs_fcoe_fcftab_state_table[i].string);
4608 }
4609 }
4610
4611 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
4612 return (buffer);
4613
4614 } /* emlxs_fcoe_fcftab_state_xlate() */
4615
4616
4617 static uint32_t
emlxs_fcoe_fcftab_action(emlxs_port_t * port,uint32_t evt,void * arg1)4618 emlxs_fcoe_fcftab_action(emlxs_port_t *port, uint32_t evt,
4619 void *arg1)
4620 {
4621 emlxs_hba_t *hba = HBA;
4622 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4623 uint32_t rval = 0;
4624 uint32_t(*func) (emlxs_port_t *, uint32_t, void *);
4625 uint32_t index;
4626 uint32_t events;
4627 uint16_t state;
4628
4629 /* Convert event to action table index */
4630 switch (evt) {
4631 case FCF_EVENT_STATE_ENTER:
4632 index = 0;
4633 break;
4634 case FCF_EVENT_SHUTDOWN:
4635 index = 1;
4636 break;
4637 case FCF_EVENT_LINKUP:
4638 index = 2;
4639 break;
4640 case FCF_EVENT_LINKDOWN:
4641 index = 3;
4642 break;
4643 case FCF_EVENT_CVL:
4644 index = 4;
4645 break;
4646 case FCF_EVENT_FCF_FOUND:
4647 index = 5;
4648 break;
4649 case FCF_EVENT_FCF_LOST:
4650 index = 6;
4651 break;
4652 case FCF_EVENT_FCF_CHANGED:
4653 index = 7;
4654 break;
4655 case FCF_EVENT_FCFTAB_FULL:
4656 index = 8;
4657 break;
4658 case FCF_EVENT_FCFI_ONLINE:
4659 index = 9;
4660 break;
4661 case FCF_EVENT_FCFI_OFFLINE:
4662 index = 10;
4663 break;
4664 default:
4665 return (1);
4666 }
4667
4668 events = FCOE_FCFTAB_ACTION_EVENTS;
4669 state = fcftab->state;
4670
4671 index += (state * events);
4672 func = (uint32_t(*) (emlxs_port_t *, uint32_t, void *))
4673 emlxs_fcoe_fcftab_action_table[index];
4674
4675 if (!func) {
4676 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
4677 "fcoe_fcftab_action:%x %s:%s arg=%p. No action. <",
4678 fcftab->TID,
4679 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4680 emlxs_fcf_event_xlate(evt), arg1);
4681
4682 return (1);
4683 }
4684
4685 rval = (func)(port, evt, arg1);
4686
4687 return (rval);
4688
4689 } /* emlxs_fcoe_fcftab_action() */
4690
4691
4692 static uint32_t
emlxs_fcoe_fcftab_event(emlxs_port_t * port,uint32_t evt,void * arg1)4693 emlxs_fcoe_fcftab_event(emlxs_port_t *port, uint32_t evt,
4694 void *arg1)
4695 {
4696 emlxs_hba_t *hba = HBA;
4697 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4698 uint32_t rval = 0;
4699
4700 /* Filter events */
4701 switch (evt) {
4702 case FCF_EVENT_SHUTDOWN:
4703 case FCF_EVENT_LINKUP:
4704 case FCF_EVENT_LINKDOWN:
4705 case FCF_EVENT_CVL:
4706 case FCF_EVENT_FCF_FOUND:
4707 case FCF_EVENT_FCF_LOST:
4708 case FCF_EVENT_FCF_CHANGED:
4709 case FCF_EVENT_FCFTAB_FULL:
4710 case FCF_EVENT_FCFI_OFFLINE:
4711 case FCF_EVENT_FCFI_ONLINE:
4712 break;
4713
4714 default:
4715 return (1);
4716 }
4717
4718 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
4719 "fcoe_fcftab_event:%x %s:%s arg=%p.",
4720 fcftab->TID,
4721 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4722 emlxs_fcf_event_xlate(evt), arg1);
4723
4724 rval = emlxs_fcoe_fcftab_action(port, evt, arg1);
4725
4726 return (rval);
4727
4728 } /* emlxs_fcoe_fcftab_event() */
4729
4730
4731 /* EMLXS_FCF_LOCK must be held to enter */
4732 /*ARGSUSED*/
4733 static uint32_t
emlxs_fcoe_fcftab_state(emlxs_port_t * port,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)4734 emlxs_fcoe_fcftab_state(emlxs_port_t *port, uint16_t state, uint16_t reason,
4735 uint32_t explain, void *arg1)
4736 {
4737 emlxs_hba_t *hba = HBA;
4738 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4739 uint32_t rval = 0;
4740
4741 if (state >= FCOE_FCFTAB_ACTION_STATES) {
4742 return (1);
4743 }
4744
4745 if ((fcftab->state == state) &&
4746 (reason != FCF_REASON_REENTER)) {
4747 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4748 "fcftab_state:%x %s:%s:0x%x arg=%p. "
4749 "State not changed. <",
4750 fcftab->TID,
4751 emlxs_fcoe_fcftab_state_xlate(state),
4752 emlxs_fcf_reason_xlate(reason),
4753 explain, arg1);
4754 return (1);
4755 }
4756
4757 if (!reason) {
4758 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4759 "fcftab_state:%x %s-->%s arg=%p",
4760 fcftab->TID,
4761 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4762 emlxs_fcoe_fcftab_state_xlate(state), arg1);
4763 } else if (reason == FCF_REASON_EVENT) {
4764 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4765 "fcftab_state:%x %s-->%s:%s:%s arg=%p",
4766 fcftab->TID,
4767 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4768 emlxs_fcoe_fcftab_state_xlate(state),
4769 emlxs_fcf_reason_xlate(reason),
4770 emlxs_fcf_event_xlate(explain), arg1);
4771 } else if (explain) {
4772 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4773 "fcftab_state:%x %s-->%s:%s:0x%x arg=%p",
4774 fcftab->TID,
4775 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4776 emlxs_fcoe_fcftab_state_xlate(state),
4777 emlxs_fcf_reason_xlate(reason),
4778 explain, arg1);
4779 } else {
4780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
4781 "fcftab_state:%x %s-->%s:%s arg=%p",
4782 fcftab->TID,
4783 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4784 emlxs_fcoe_fcftab_state_xlate(state),
4785 emlxs_fcf_reason_xlate(reason), arg1);
4786 }
4787
4788 fcftab->prev_state = fcftab->state;
4789 fcftab->prev_reason = fcftab->reason;
4790 fcftab->state = state;
4791 fcftab->reason = reason;
4792
4793 rval = emlxs_fcoe_fcftab_action(port, FCF_EVENT_STATE_ENTER, arg1);
4794
4795 return (rval);
4796
4797 } /* emlxs_fcoe_fcftab_state() */
4798
4799
4800 /*ARGSUSED*/
4801 static uint32_t
emlxs_fcoe_fcftab_fcfi_offline_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4802 emlxs_fcoe_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, uint32_t evt,
4803 void *arg1)
4804 {
4805 emlxs_hba_t *hba = HBA;
4806 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4807 uint32_t rval = 0;
4808 FCFIobj_t *fcfp;
4809
4810 if (evt != FCF_EVENT_FCFI_OFFLINE) {
4811 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4812 "fcoe_fcftab_fcfi_offline_evt_action:%x %s:%s arg=%p "
4813 "flag=%x. Invalid event type. <",
4814 fcftab->TID,
4815 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4816 emlxs_fcf_event_xlate(evt), arg1,
4817 fcftab->flag);
4818 return (1);
4819 }
4820
4821 fcfp = (FCFIobj_t *)arg1;
4822
4823 switch (fcftab->state) {
4824 case FCOE_FCFTAB_STATE_SHUTDOWN:
4825 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4826 "fcoe_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4827 "Shutting down.",
4828 fcftab->TID,
4829 fcfp->fcf_index);
4830
4831 /* This will trigger final shutdown */
4832 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SHUTDOWN,
4833 FCF_REASON_REENTER, evt, arg1);
4834 break;
4835
4836 case FCOE_FCFTAB_STATE_FCFI_OFFLINE:
4837 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4838 "fcoe_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4839 "Offlining.",
4840 fcftab->TID,
4841 fcfp->fcf_index);
4842
4843 rval = emlxs_fcoe_fcftab_state(port,
4844 FCOE_FCFTAB_STATE_FCFI_OFFLINE,
4845 FCF_REASON_REENTER, evt, arg1);
4846 break;
4847
4848 case FCOE_FCFTAB_STATE_FCFI_ONLINE:
4849 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4850 "fcoe_fcftab_fcfi_offline_evt_action:%x fcfi:%d. "
4851 "Attempting failover.",
4852 fcftab->TID,
4853 fcfp->fcf_index);
4854
4855 fcfp->flag |= EMLXS_FCFI_FAILED;
4856
4857 rval = emlxs_fcoe_fcftab_state(port,
4858 FCOE_FCFTAB_STATE_FCFI_ONLINE,
4859 FCF_REASON_REENTER, evt, arg1);
4860 break;
4861
4862 case FCOE_FCFTAB_STATE_ONLINE:
4863 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4864 "fcoe_fcftab_fcfi_offline_evt_action:%x fcfi:%d.",
4865 fcftab->TID,
4866 fcfp->fcf_index);
4867
4868 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_ONLINE,
4869 FCF_REASON_REENTER, evt, arg1);
4870 break;
4871
4872 default:
4873 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4874 "fcoe_fcftab_fcfi_offline_evt_action:%x %s fcfi:%d.",
4875 fcftab->TID,
4876 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4877 fcfp->fcf_index);
4878 break;
4879 }
4880
4881 return (rval);
4882
4883 } /* emlxs_fcoe_fcftab_fcfi_offline_evt_action() */
4884
4885
4886 /*ARGSUSED*/
4887 static uint32_t
emlxs_fcoe_fcftab_fcfi_online_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4888 emlxs_fcoe_fcftab_fcfi_online_evt_action(emlxs_port_t *port, uint32_t evt,
4889 void *arg1)
4890 {
4891 emlxs_hba_t *hba = HBA;
4892 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4893 uint32_t rval = 0;
4894 FCFIobj_t *fcfp;
4895
4896 if (evt != FCF_EVENT_FCFI_ONLINE) {
4897 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4898 "fcoe_fcftab_fcfi_online_evt_action:%x %s:%s arg=%p "
4899 "flag=%x. Invalid event type. <",
4900 fcftab->TID,
4901 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4902 emlxs_fcf_event_xlate(evt), arg1,
4903 fcftab->flag);
4904 return (1);
4905 }
4906
4907 fcfp = (FCFIobj_t *)arg1;
4908
4909 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4910 "fcoe_fcftab_fcfi_online_evt_action:%x fcfi:%d. <",
4911 fcftab->TID,
4912 fcfp->fcf_index);
4913
4914 return (rval);
4915
4916 } /* emlxs_fcoe_fcftab_fcfi_online_evt_action() */
4917
4918
4919 /*ARGSUSED*/
4920 static uint32_t
emlxs_fcoe_fcftab_cvl_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4921 emlxs_fcoe_fcftab_cvl_evt_action(emlxs_port_t *port, uint32_t evt,
4922 void *arg1)
4923 {
4924 emlxs_hba_t *hba = HBA;
4925 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4926 uint32_t rval = 0;
4927 emlxs_port_t *vport;
4928 uint32_t vpi;
4929 VPIobj_t *vpip;
4930
4931 if (evt != FCF_EVENT_CVL) {
4932 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4933 "fcoe_fcftab_cvl_evt_action:%x %s:%s arg=%p flag=%x. "
4934 "Invalid event type. <",
4935 fcftab->TID,
4936 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4937 emlxs_fcf_event_xlate(evt), arg1,
4938 fcftab->flag);
4939 return (1);
4940 }
4941
4942 /* Pause VPI */
4943 vpi = (uint32_t)((unsigned long)arg1);
4944 vport = &VPORT(vpi);
4945 vpip = vport->vpip;
4946
4947 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4948 "fcoe_fcftab_cvl_evt_action:%x %s gen=%x. Pausing VPI:%d. >",
4949 fcftab->TID,
4950 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4951 fcftab->generation,
4952 vpip->VPI);
4953
4954 rval = emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip);
4955
4956 switch (fcftab->state) {
4957 case FCOE_FCFTAB_STATE_SOLICIT:
4958 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4959 "fcoe_fcftab_cvl_evt_action:%x %s gen=%x. "
4960 "Already soliciting. <",
4961 fcftab->TID,
4962 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4963 fcftab->generation);
4964 break;
4965
4966 default:
4967 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
4968 fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
4969 fcftab->generation++;
4970
4971 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
4972 "fcoe_fcftab_cvl_evt_action:%x %s gen=%x. Soliciting.",
4973 fcftab->TID,
4974 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
4975 fcftab->generation);
4976
4977 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
4978 FCF_REASON_EVENT, evt, arg1);
4979 break;
4980 }
4981
4982 return (rval);
4983
4984 } /* emlxs_fcoe_fcftab_cvl_evt_action() */
4985
4986
4987 /*ARGSUSED*/
4988 static uint32_t
emlxs_fcoe_fcftab_linkup_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)4989 emlxs_fcoe_fcftab_linkup_evt_action(emlxs_port_t *port, uint32_t evt,
4990 void *arg1)
4991 {
4992 emlxs_hba_t *hba = HBA;
4993 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
4994 uint32_t rval = 0;
4995
4996 if (evt != FCF_EVENT_LINKUP) {
4997 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
4998 "fcoe_fcftab_linkup_evt_action:%x %s:%s arg=%p flag=%x. "
4999 "Invalid event type. <",
5000 fcftab->TID,
5001 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5002 emlxs_fcf_event_xlate(evt), arg1,
5003 fcftab->flag);
5004 return (1);
5005 }
5006
5007 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5008 "fcoe_fcftab_linkup_evt_action:%x %s:%s arg=%p gen=%x. Link up.",
5009 fcftab->TID,
5010 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5011 emlxs_fcf_event_xlate(evt), arg1,
5012 fcftab->generation);
5013
5014 emlxs_fcf_linkup(port);
5015
5016 switch (fcftab->state) {
5017 case FCOE_FCFTAB_STATE_SOLICIT:
5018 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5019 "fcoe_fcftab_linkup_evt_action:%x %s gen=%x. "
5020 "Already soliciting. <",
5021 fcftab->TID,
5022 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5023 fcftab->generation);
5024 break;
5025
5026 default:
5027 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
5028 fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
5029 fcftab->generation++;
5030
5031 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5032 "fcoe_fcftab_linkup_evt_action:%x %s gen=%x. Soliciting.",
5033 fcftab->TID,
5034 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5035 fcftab->generation);
5036
5037 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
5038 FCF_REASON_EVENT, evt, arg1);
5039 break;
5040 }
5041
5042 return (rval);
5043
5044 } /* emlxs_fcoe_fcftab_linkup_evt_action() */
5045
5046
5047 /*ARGSUSED*/
5048 static uint32_t
emlxs_fcoe_fcftab_linkdown_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)5049 emlxs_fcoe_fcftab_linkdown_evt_action(emlxs_port_t *port, uint32_t evt,
5050 void *arg1)
5051 {
5052 emlxs_hba_t *hba = HBA;
5053 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5054 uint32_t rval = 0;
5055 int32_t i;
5056 FCFIobj_t *fcfp;
5057
5058 if (evt != FCF_EVENT_LINKDOWN) {
5059 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5060 "fcoe_fcftab_linkdown_evt_action:%x %s:%s arg=%p "
5061 "flag=%x. Invalid event type. <",
5062 fcftab->TID,
5063 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5064 emlxs_fcf_event_xlate(evt), arg1,
5065 fcftab->flag);
5066 return (1);
5067 }
5068
5069 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
5070 fcftab->flag |= EMLXS_FCOE_FCFTAB_OFFLINE_REQ;
5071
5072 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5073 "fcoe_fcftab_linkdown_evt_action:%x %s:%s arg=%p flag=%x. "
5074 "Linkdown.",
5075 fcftab->TID,
5076 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5077 emlxs_fcf_event_xlate(evt), arg1,
5078 fcftab->flag);
5079
5080 emlxs_fcf_linkdown(port);
5081
5082 /* Pause all active FCFI's */
5083 for (i = 0; i < fcftab->fcfi_count; i++) {
5084 fcfp = fcftab->fcfi[i];
5085
5086 if ((fcfp->state == FCFI_STATE_OFFLINE) ||
5087 (fcfp->state == FCFI_STATE_PAUSED)) {
5088 break;
5089 }
5090
5091 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5092 "fcoe_fcftab_linkdown_evt_action:%x Pausing FCFI:%d. >",
5093 fcftab->TID,
5094 fcfp->fcf_index);
5095
5096 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_PAUSE, fcfp);
5097 }
5098
5099 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5100 "fcoe_fcftab_linkdown_evt_action:%x "
5101 "Going offline.",
5102 fcftab->TID);
5103
5104 switch (fcftab->state) {
5105 case FCOE_FCFTAB_STATE_OFFLINE:
5106 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_OFFLINE,
5107 FCF_REASON_REENTER, evt, arg1);
5108 break;
5109
5110 default:
5111 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_OFFLINE,
5112 FCF_REASON_EVENT, evt, arg1);
5113 break;
5114 }
5115
5116 return (rval);
5117
5118 } /* emlxs_fcoe_fcftab_linkdown_evt_action() */
5119
5120
5121 /*ARGSUSED*/
5122 static uint32_t
emlxs_fcoe_fcftab_shutdown_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)5123 emlxs_fcoe_fcftab_shutdown_evt_action(emlxs_port_t *port, uint32_t evt,
5124 void *arg1)
5125 {
5126 emlxs_hba_t *hba = HBA;
5127 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5128 uint32_t rval = 0;
5129
5130 if (evt != FCF_EVENT_SHUTDOWN) {
5131 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5132 "fcoe_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
5133 "Invalid event type. <",
5134 fcftab->TID,
5135 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5136 emlxs_fcf_event_xlate(evt), arg1,
5137 fcftab->flag);
5138 return (1);
5139 }
5140
5141 if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) {
5142 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5143 "fcoe_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
5144 "Already shut down. <",
5145 fcftab->TID,
5146 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5147 emlxs_fcf_event_xlate(evt), arg1,
5148 fcftab->flag);
5149 return (1);
5150 }
5151
5152 if (fcftab->state == FCOE_FCFTAB_STATE_SHUTDOWN) {
5153 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5154 "fcoe_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
5155 "Already shutting down. <",
5156 fcftab->TID,
5157 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5158 emlxs_fcf_event_xlate(evt), arg1,
5159 fcftab->flag);
5160 return (1);
5161 }
5162
5163 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5164 "fcoe_fcftab_shutdown_evt_action:%x %s:%s arg=%p flag=%x. "
5165 "Shutting down.",
5166 fcftab->TID,
5167 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5168 emlxs_fcf_event_xlate(evt), arg1,
5169 fcftab->flag);
5170
5171 emlxs_fcf_linkdown(port);
5172
5173 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SHUTDOWN,
5174 FCF_REASON_EVENT, evt, arg1);
5175
5176 return (rval);
5177
5178 } /* emlxs_fcoe_fcftab_shutdown_evt_action() */
5179
5180
5181 static uint32_t
emlxs_fcoe_fcftab_req_handler(emlxs_port_t * port,void * arg1)5182 emlxs_fcoe_fcftab_req_handler(emlxs_port_t *port, void *arg1)
5183 {
5184 emlxs_hba_t *hba = HBA;
5185 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5186 uint32_t rval = 0;
5187
5188 if (!(fcftab->flag & EMLXS_FCFTAB_REQ_MASK)) {
5189 return (1);
5190 }
5191
5192 if (fcftab->flag & EMLXS_FCOE_FCFTAB_OFFLINE_REQ) {
5193 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_OFFLINE,
5194 FCF_REASON_REQUESTED, 0, arg1);
5195 }
5196
5197 else if (fcftab->flag & EMLXS_FCOE_FCFTAB_SOL_REQ) {
5198 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
5199 FCF_REASON_REQUESTED, 0, arg1);
5200 }
5201
5202 else if (fcftab->flag & EMLXS_FCOE_FCFTAB_READ_REQ) {
5203 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
5204 FCF_REASON_REQUESTED, 0, FCFTAB_READ_ALL);
5205 }
5206
5207 return (rval);
5208
5209 } /* emlxs_fcoe_fcftab_req_handler() */
5210
5211
5212 static void
emlxs_fcoe_fcftab_read_timer(emlxs_hba_t * hba)5213 emlxs_fcoe_fcftab_read_timer(emlxs_hba_t *hba)
5214 {
5215 emlxs_port_t *port = &PPORT;
5216 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5217
5218 /* Check FCF timer */
5219 if (!fcftab->read_timer ||
5220 (hba->timer_tics < fcftab->read_timer)) {
5221 return;
5222 }
5223 fcftab->read_timer = 0;
5224 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
5225
5226 switch (fcftab->state) {
5227 case FCOE_FCFTAB_STATE_SOLICIT_CMPL:
5228 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5229 "fcoe_fcftab_timer:%x %s >",
5230 fcftab->TID,
5231 emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5232
5233 (void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
5234 0, 0, FCFTAB_READ_ALL);
5235 break;
5236
5237 default:
5238 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5239 "fcoe_fcftab_timer:%x %s",
5240 fcftab->TID,
5241 emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5242 break;
5243 }
5244
5245 return;
5246
5247 } /* emlxs_fcoe_fcftab_read_timer() */
5248
5249
5250 static void
emlxs_fcoe_fcftab_sol_timer(emlxs_hba_t * hba)5251 emlxs_fcoe_fcftab_sol_timer(emlxs_hba_t *hba)
5252 {
5253 emlxs_port_t *port = &PPORT;
5254 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5255
5256 /* Check FCF timer */
5257 if (!fcftab->sol_timer ||
5258 (hba->timer_tics < fcftab->sol_timer)) {
5259 return;
5260 }
5261 fcftab->sol_timer = 0;
5262
5263 switch (fcftab->state) {
5264 case FCOE_FCFTAB_STATE_ONLINE:
5265 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
5266 fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
5267 fcftab->generation++;
5268
5269 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5270 "fcoe_fcftab_sol_timer:%x %s gen=%x. Soliciting. >",
5271 fcftab->TID,
5272 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5273 fcftab->generation);
5274
5275 (void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
5276 FCF_REASON_EVENT, 0, 0);
5277 break;
5278
5279 default:
5280 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5281 "fcoe_fcftab_sol_timer:%x %s",
5282 fcftab->TID,
5283 emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5284 break;
5285 }
5286
5287 return;
5288
5289 } /* emlxs_fcoe_fcftab_sol_timer() */
5290
5291
5292 static void
emlxs_fcoe_fcftab_offline_timer(emlxs_hba_t * hba)5293 emlxs_fcoe_fcftab_offline_timer(emlxs_hba_t *hba)
5294 {
5295 emlxs_port_t *port = &PPORT;
5296 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5297 uint32_t i;
5298 FCFIobj_t *fcfp;
5299
5300 for (i = 0; i < fcftab->fcfi_count; i++) {
5301 fcfp = fcftab->fcfi[i];
5302
5303 /* Check offline timer */
5304 if (!fcfp->offline_timer ||
5305 (hba->timer_tics < fcfp->offline_timer)) {
5306 continue;
5307 }
5308 fcfp->offline_timer = 0;
5309
5310 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5311 "fcoe_fcftab_offline_timer:%x. Offlining FCFI:%d. >",
5312 fcftab->TID,
5313 fcfp->fcf_index);
5314
5315 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp);
5316 }
5317
5318 return;
5319
5320 } /* emlxs_fcoe_fcftab_offline_timer() */
5321
5322
5323 /*ARGSUSED*/
5324 static uint32_t
emlxs_fcoe_fcftab_sol_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)5325 emlxs_fcoe_fcftab_sol_failed_action(emlxs_port_t *port, uint32_t evt,
5326 void *arg1)
5327 {
5328 emlxs_hba_t *hba = HBA;
5329 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5330 uint32_t rval = 0;
5331
5332 fcftab->attempts++;
5333
5334 if (fcftab->state != FCOE_FCFTAB_STATE_SOLICIT_FAILED) {
5335 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5336 "fcoe_fcftab_sol_failed_action:%x %s:%s arg=%p "
5337 "attempt=%d. Invalid state. <",
5338 fcftab->TID,
5339 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5340 emlxs_fcf_event_xlate(evt),
5341 arg1, fcftab->attempts);
5342 return (1);
5343 }
5344
5345 if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
5346 (fcftab->reason == FCF_REASON_SEND_FAILED) ||
5347 (fcftab->attempts >= 3)) {
5348 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5349 "fcoe_fcftab_sol_failed_action:%x %s:%s arg=%p "
5350 "attempt=%d reason=%x. Giving up.",
5351 fcftab->TID,
5352 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5353 emlxs_fcf_event_xlate(evt), arg1,
5354 fcftab->attempts,
5355 fcftab->reason);
5356
5357 rval = emlxs_fcoe_fcftab_state(port,
5358 FCOE_FCFTAB_STATE_SOLICIT_CMPL,
5359 FCF_REASON_OP_FAILED, 0, arg1);
5360 } else {
5361 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5362 "fcoe_fcftab_sol_failed_action:%x %s:%s arg=%p "
5363 "attempt=%d reason=%x. Retrying.",
5364 fcftab->TID,
5365 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5366 emlxs_fcf_event_xlate(evt), arg1,
5367 fcftab->attempts,
5368 fcftab->reason);
5369
5370 rval = emlxs_fcoe_fcftab_state(port,
5371 FCOE_FCFTAB_STATE_SOLICIT,
5372 FCF_REASON_OP_FAILED, 0, arg1);
5373 }
5374
5375 return (rval);
5376
5377 } /* emlxs_fcoe_fcftab_sol_failed_action() */
5378
5379
5380 /*ARGSUSED*/
5381 static uint32_t
emlxs_fcoe_fcftab_sol_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)5382 emlxs_fcoe_fcftab_sol_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
5383 {
5384 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
5385 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5386 MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
5387 uint16_t TID;
5388 mbox_rsp_hdr_t *hdr_rsp;
5389 MATCHMAP *mp;
5390 uint32_t status = MGMT_STATUS_FCF_IN_USE;
5391 uint32_t xstatus = 0;
5392 uint32_t fip_mode = 1;
5393
5394 mutex_enter(&EMLXS_FCF_LOCK);
5395 TID = (uint16_t)((unsigned long)mbq->context);
5396
5397 if (mbq->nonembed) {
5398 fip_mode = 0;
5399
5400 mp = (MATCHMAP *)mbq->nonembed;
5401 mbq->nonembed = NULL;
5402
5403 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
5404 status = hdr_rsp->status;
5405 xstatus = hdr_rsp->extra_status;
5406
5407 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
5408 }
5409
5410 if (fcftab->state != FCOE_FCFTAB_STATE_SOLICIT) {
5411 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5412 "fcoe_fcftab_sol_mbcmpl:%x %s.",
5413 TID,
5414 emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5415
5416 mutex_exit(&EMLXS_FCF_LOCK);
5417 return (0);
5418 }
5419
5420 if (TID != fcftab->generation) {
5421 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5422 "fcoe_fcftab_sol_mbcmpl:%x %s. "
5423 "Incorrect generation %x. Dropping.",
5424 TID,
5425 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5426 fcftab->generation);
5427
5428 mutex_exit(&EMLXS_FCF_LOCK);
5429 return (0);
5430 }
5431
5432 if (mb4->mbxStatus) {
5433 if (fip_mode) {
5434 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5435 "fcoe_fcftab_sol_mbcmpl:%x failed. %s. >",
5436 fcftab->TID,
5437 emlxs_mb_xlate_status(mb4->mbxStatus));
5438
5439 (void) emlxs_fcoe_fcftab_state(port,
5440 FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5441 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
5442
5443 mutex_exit(&EMLXS_FCF_LOCK);
5444 return (0);
5445
5446 } else if ((status == 0)||(status != MGMT_STATUS_FCF_IN_USE)) {
5447 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5448 "fcoe_fcftab_sol_mbcmpl:%x failed. %s %x,%x. >",
5449 fcftab->TID,
5450 emlxs_mb_xlate_status(mb4->mbxStatus),
5451 status, xstatus);
5452
5453 (void) emlxs_fcoe_fcftab_state(port,
5454 FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5455 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
5456
5457 mutex_exit(&EMLXS_FCF_LOCK);
5458 return (0);
5459 }
5460 }
5461
5462 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5463 "fcoe_fcftab_sol_mbcmpl:%x %s gen=%x. Solicit complete. >",
5464 fcftab->TID,
5465 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5466 fcftab->generation);
5467
5468 (void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT_CMPL,
5469 0, 0, 0);
5470
5471 mutex_exit(&EMLXS_FCF_LOCK);
5472 return (0);
5473
5474 } /* emlxs_fcoe_fcftab_sol_mbcmpl() */
5475
5476
5477 /*ARGSUSED*/
5478 static uint32_t
emlxs_fcoe_fcftab_sol_action(emlxs_port_t * port,uint32_t evt,void * arg1)5479 emlxs_fcoe_fcftab_sol_action(emlxs_port_t *port, uint32_t evt,
5480 void *arg1)
5481 {
5482 emlxs_hba_t *hba = HBA;
5483 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5484 MAILBOXQ *mbq;
5485 MAILBOX4 *mb4;
5486 MATCHMAP *mp = NULL;
5487 uint32_t rval = 0;
5488
5489 if (fcftab->state != FCOE_FCFTAB_STATE_SOLICIT) {
5490 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5491 "fcoe_fcftab_sol_action:%x %s:%s arg=%p. "
5492 "Invalid state. <",
5493 fcftab->TID,
5494 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5495 emlxs_fcf_event_xlate(evt), arg1);
5496 return (1);
5497 }
5498
5499 if ((fcftab->prev_state != FCOE_FCFTAB_STATE_SOLICIT_FAILED) ||
5500 (fcftab->flag & EMLXS_FCOE_FCFTAB_SOL_REQ)) {
5501 fcftab->flag &= ~EMLXS_FCOE_FCFTAB_SOL_REQ;
5502 fcftab->attempts = 0;
5503 }
5504
5505 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
5506 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5507 "fcoe_fcftab_sol_action:%x %s:%s arg=%p gen=%d flag=%x. "
5508 "Handling request.",
5509 fcftab->TID,
5510 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5511 emlxs_fcf_event_xlate(evt), arg1,
5512 fcftab->generation,
5513 fcftab->flag);
5514
5515 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
5516 return (rval);
5517 }
5518
5519 if (fcftab->attempts == 0) {
5520 fcftab->TID = fcftab->generation;
5521 }
5522
5523 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5524 "fcoe_fcftab_sol_action:%x %s:%s arg=%p gen=%x fip=%x. "
5525 "Requesting solicit. <",
5526 fcftab->TID,
5527 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5528 emlxs_fcf_event_xlate(evt), arg1,
5529 fcftab->generation,
5530 ((hba->flag & FC_FIP_SUPPORTED)? 1:0));
5531
5532 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
5533 rval = emlxs_fcoe_fcftab_state(port,
5534 FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5535 FCF_REASON_NO_MBOX, 0, 0);
5536 return (rval);
5537 }
5538
5539 mb4 = (MAILBOX4*)mbq;
5540 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
5541
5542 if (hba->flag & FC_FIP_SUPPORTED) {
5543 IOCTL_FCOE_REDISCOVER_FCF_TABLE *fcf;
5544
5545 mbq->nonembed = NULL;
5546 mbq->mbox_cmpl = emlxs_fcoe_fcftab_sol_mbcmpl;
5547 mbq->context = (void *)((unsigned long)fcftab->TID);
5548 mbq->port = (void *)port;
5549
5550 mb4->un.varSLIConfig.be.embedded = 1;
5551 mb4->mbxCommand = MBX_SLI_CONFIG;
5552 mb4->mbxOwner = OWN_HOST;
5553 mb4->un.varSLIConfig.be.payload_length =
5554 sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE) +
5555 IOCTL_HEADER_SZ;
5556 mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
5557 IOCTL_SUBSYSTEM_FCOE;
5558 mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
5559 FCOE_OPCODE_REDISCOVER_FCF_TABLE;
5560 mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
5561 mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
5562 sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE);
5563
5564 fcf = (IOCTL_FCOE_REDISCOVER_FCF_TABLE *)
5565 &mb4->un.varSLIConfig.payload;
5566 fcf->params.request.fcf_count = 0; /* invalidate FCF table */
5567
5568 } else { /* Non-FIP */
5569
5570 /* Non-FIP uses a persistent FCF entry that */
5571 /* we must add to the table */
5572
5573 IOCTL_FCOE_ADD_FCF_TABLE *fcf;
5574 mbox_req_hdr_t *hdr_req;
5575 FCF_RECORD_t *fcf_rec;
5576 uint8_t bitmap[512];
5577 uint16_t i;
5578
5579 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
5580 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5581
5582 rval = emlxs_fcoe_fcftab_state(port,
5583 FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5584 FCF_REASON_NO_BUFFER, 0, arg1);
5585 return (rval);
5586 }
5587 bzero(mp->virt, mp->size);
5588
5589 mbq->nonembed = (void *)mp;
5590 mbq->mbox_cmpl = emlxs_fcoe_fcftab_sol_mbcmpl;
5591 mbq->context = (void *)((unsigned long)fcftab->generation);
5592 mbq->port = (void *)port;
5593
5594 mb4->un.varSLIConfig.be.embedded = 0;
5595 mb4->mbxCommand = MBX_SLI_CONFIG;
5596 mb4->mbxOwner = OWN_HOST;
5597
5598 hdr_req = (mbox_req_hdr_t *)mp->virt;
5599 hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
5600 hdr_req->opcode = FCOE_OPCODE_ADD_FCF_TABLE;
5601 hdr_req->timeout = 0;
5602 hdr_req->req_length = sizeof (IOCTL_FCOE_ADD_FCF_TABLE);
5603
5604 fcf = (IOCTL_FCOE_ADD_FCF_TABLE *)(hdr_req + 1);
5605 fcf->params.request.fcf_index = 0;
5606
5607 fcf_rec = &fcf->params.request.fcf_entry;
5608 fcf_rec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ;
5609 fcf_rec->fka_adv_period = 0;
5610 fcf_rec->fip_priority = 128;
5611
5612 #ifdef EMLXS_BIG_ENDIAN
5613 fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3;
5614 fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2;
5615 fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1;
5616 fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0;
5617 fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC5;
5618 fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC4;
5619 fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2];
5620 fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
5621 fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0];
5622 #endif /* EMLXS_BIG_ENDIAN */
5623 #ifdef EMLXS_LITTLE_ENDIAN
5624 fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0;
5625 fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1;
5626 fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2;
5627 fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3;
5628 fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC4;
5629 fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC5;
5630 fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0];
5631 fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
5632 fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2];
5633 #endif /* EMLXS_LITTLE_ENDIAN */
5634
5635 if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) {
5636 bzero((void *) bitmap, 512);
5637 i = hba->sli.sli4.cfgFCOE.VLanId;
5638 bitmap[i / 8] = (1 << (i % 8));
5639 BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
5640 } else {
5641 bzero((void *) bitmap, 512);
5642 bitmap[0] = 1; /* represents bit 0 */
5643 BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512);
5644 }
5645
5646 fcf_rec->fcf_valid = 1;
5647 fcf_rec->fcf_available = 1;
5648 }
5649
5650 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
5651 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
5652 if (mp) {
5653 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
5654 }
5655 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5656
5657 rval = emlxs_fcoe_fcftab_state(port,
5658 FCOE_FCFTAB_STATE_SOLICIT_FAILED,
5659 FCF_REASON_SEND_FAILED, rval, 0);
5660
5661 return (rval);
5662 }
5663
5664 return (0);
5665
5666 } /* emlxs_fcoe_fcftab_sol_action() */
5667
5668
5669 /*ARGSUSED*/
5670 static uint32_t
emlxs_fcoe_fcftab_sol_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)5671 emlxs_fcoe_fcftab_sol_cmpl_action(emlxs_port_t *port, uint32_t evt,
5672 void *arg1)
5673 {
5674 emlxs_hba_t *hba = HBA;
5675 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5676 uint32_t rval = 0;
5677 emlxs_config_t *cfg = &CFG;
5678
5679 if (fcftab->state != FCOE_FCFTAB_STATE_SOLICIT_CMPL) {
5680 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5681 "fcoe_fcftab_sol_cmpl_action:%x %s:%s arg=%p "
5682 "Invalid state. <",
5683 fcftab->TID,
5684 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5685 emlxs_fcf_event_xlate(evt), arg1);
5686 return (1);
5687 }
5688
5689 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
5690 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5691 "fcoe_fcftab_sol_cmpl_action:%x %s:%s arg=%p gen=%d "
5692 "flag=%x. Handling request.",
5693 fcftab->TID,
5694 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5695 emlxs_fcf_event_xlate(evt), arg1,
5696 fcftab->generation,
5697 fcftab->flag);
5698
5699 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
5700 return (rval);
5701 }
5702
5703 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5704 "fcoe_fcftab_sol_cmpl_action:%x %s:%s arg=%p gen=%d. "
5705 "Starting timer (%d secs).",
5706 fcftab->TID,
5707 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5708 emlxs_fcf_event_xlate(evt), arg1,
5709 fcftab->generation,
5710 cfg[CFG_FCF_SOLICIT_DELAY].current);
5711
5712 /* Start the read timer */
5713 fcftab->read_timer = hba->timer_tics +
5714 cfg[CFG_FCF_SOLICIT_DELAY].current;
5715
5716 return (0);
5717
5718 } /* emlxs_fcoe_fcftab_sol_cmpl_action() */
5719
5720
5721 /*ARGSUSED*/
5722 static uint32_t
emlxs_fcoe_fcftab_read_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)5723 emlxs_fcoe_fcftab_read_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
5724 {
5725 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
5726 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5727 MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
5728 mbox_rsp_hdr_t *hdr_rsp;
5729 IOCTL_FCOE_READ_FCF_TABLE *fcf;
5730 FCF_RECORD_t *fcfrec;
5731 FCFIobj_t *fcfp;
5732 MATCHMAP *mp;
5733 uint32_t context;
5734 uint16_t index;
5735 uint16_t TID;
5736 uint32_t event_tag;
5737
5738 mutex_enter(&EMLXS_FCF_LOCK);
5739 context = (uint32_t)((unsigned long)mbq->context);
5740 TID = (uint16_t)(context >> 16);
5741 index = (uint16_t)(context & 0xFFFF);
5742
5743 if (fcftab->state != FCOE_FCFTAB_STATE_READ) {
5744 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5745 "fcoe_fcftab_read_mbcmpl:%x index=%d %s.",
5746 TID, index,
5747 emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5748
5749 mutex_exit(&EMLXS_FCF_LOCK);
5750 return (0);
5751 }
5752
5753 if (TID != fcftab->generation) {
5754 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5755 "fcoe_fcftab_read_mbcmpl:%x index=%d %s. "
5756 "Incorrect generation %x. Dropping.",
5757 TID, index,
5758 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5759 fcftab->generation);
5760
5761 mutex_exit(&EMLXS_FCF_LOCK);
5762 return (0);
5763 }
5764
5765 mp = (MATCHMAP *)mbq->nonembed;
5766 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
5767
5768 if (mb4->mbxStatus || hdr_rsp->status) {
5769 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5770 "fcoe_fcftab_read_mbcmpl:%x index=%d failed. %s %x,%x. >",
5771 fcftab->TID, index,
5772 emlxs_mb_xlate_status(mb4->mbxStatus),
5773 hdr_rsp->status, hdr_rsp->extra_status);
5774
5775 (void) emlxs_fcoe_fcftab_state(port,
5776 FCOE_FCFTAB_STATE_READ_FAILED,
5777 FCF_REASON_MBOX_FAILED, mb4->mbxStatus,
5778 (void*)((unsigned long)index));
5779
5780 mutex_exit(&EMLXS_FCF_LOCK);
5781 return (0);
5782 }
5783
5784 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5785 "fcoe_fcftab_read_mbcmpl:%x index=%d %s",
5786 fcftab->TID, index,
5787 emlxs_fcoe_fcftab_state_xlate(fcftab->state));
5788
5789 fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_rsp + 1);
5790 fcfrec = &fcf->params.response.fcf_entry[0];
5791
5792 #ifdef EMLXS_BIG_ENDIAN
5793 {
5794 uint32_t *iptr;
5795 uint32_t i;
5796 uint8_t j;
5797 uint16_t s;
5798 uint16_t *sptr;
5799
5800 /* Fix up data in FCF record */
5801 SWAP32_BUFFER(&fcfrec->fabric_name_identifier[0], 8);
5802 SWAP32_BUFFER(&fcfrec->switch_name_identifier[0], 8);
5803 SWAP32_BUFFER(&fcfrec->vlan_bitmap[0], 512);
5804
5805 iptr = (uint32_t *)&fcfrec->fcf_mac_address_hi[0];
5806 i = *iptr;
5807 *iptr = SWAP32(i);
5808
5809 sptr = (uint16_t *)&fcfrec->fcf_mac_address_low[0];
5810 s = *sptr;
5811 *sptr = SWAP16(s);
5812
5813 j = fcfrec->fc_map[0];
5814 fcfrec->fc_map[0] = fcfrec->fc_map[2];
5815 fcfrec->fc_map[2] = j;
5816 }
5817 #endif /* EMLXS_BIG_ENDIAN */
5818
5819 event_tag = fcf->params.response.event_tag;
5820
5821 /* Try to find existing fcfrec */
5822 fcfp = emlxs_fcfi_find(port, fcfrec, 0);
5823
5824 /* If not found, allocate a new one */
5825 if (!fcfp) {
5826 fcfp = emlxs_fcfi_alloc(port);
5827 }
5828
5829 if (!fcfp) {
5830 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5831 "fcoe_fcftab_read_mbcmpl:%x index=%d failed. "
5832 "Unable to allocate fcfi. >",
5833 fcftab->TID, index);
5834
5835 (void) emlxs_fcoe_fcftab_state(port,
5836 FCOE_FCFTAB_STATE_READ_FAILED,
5837 FCF_REASON_NO_FCFI, 0,
5838 (void*)((unsigned long)index));
5839
5840 mutex_exit(&EMLXS_FCF_LOCK);
5841 return (0);
5842 }
5843
5844 /* Update the FCFI */
5845 emlxs_fcfi_update(port, fcfp, fcfrec, event_tag);
5846
5847 /* Check if another record needs to be acquired */
5848 if (fcf->params.response.next_valid_fcf_index != 0xffff) {
5849 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5850 "fcoe_fcftab_read_mbcmpl:%x. Read next. >",
5851 fcftab->TID);
5852
5853 (void) emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
5854 FCF_REASON_REENTER, 0,
5855 (void *)((unsigned long)fcf->params.response.
5856 next_valid_fcf_index));
5857 } else {
5858 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5859 "fcoe_fcftab_read_mbcmpl:%x. Read complete. >",
5860 fcftab->TID);
5861
5862 (void) emlxs_fcoe_fcftab_state(port,
5863 FCOE_FCFTAB_STATE_READ_CMPL,
5864 0, 0, (void*)((unsigned long)index));
5865 }
5866
5867 mutex_exit(&EMLXS_FCF_LOCK);
5868 return (0);
5869
5870 } /* emlxs_fcoe_fcftab_read_mbcmpl() */
5871
5872
5873 /*ARGSUSED*/
5874 static uint32_t
emlxs_fcoe_fcftab_read_action(emlxs_port_t * port,uint32_t evt,void * arg1)5875 emlxs_fcoe_fcftab_read_action(emlxs_port_t *port, uint32_t evt,
5876 void *arg1)
5877 {
5878 emlxs_hba_t *hba = HBA;
5879 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5880 MAILBOXQ *mbq;
5881 MAILBOX4 *mb4;
5882 IOCTL_FCOE_READ_FCF_TABLE *fcf;
5883 uint32_t rval = 0;
5884 MATCHMAP *mp;
5885 mbox_req_hdr_t *hdr_req;
5886 uint16_t index = (uint16_t)((unsigned long)arg1);
5887 uint32_t context;
5888
5889 if (fcftab->state != FCOE_FCFTAB_STATE_READ) {
5890 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5891 "fcoe_fcftab_read_action:%x %s:%s arg=%p. "
5892 "Invalid state. <",
5893 fcftab->TID,
5894 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5895 emlxs_fcf_event_xlate(evt), arg1);
5896 return (1);
5897 }
5898
5899 if ((fcftab->prev_state != FCOE_FCFTAB_STATE_READ_FAILED) ||
5900 (fcftab->flag & EMLXS_FCOE_FCFTAB_READ_REQ)) {
5901 fcftab->flag &= ~EMLXS_FCOE_FCFTAB_READ_REQ;
5902 fcftab->attempts = 0;
5903 }
5904
5905 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
5906 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5907 "fcoe_fcftab_read_action:%x %s:%s arg=%p flag=%x. "
5908 "Handling request.",
5909 fcftab->TID,
5910 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5911 emlxs_fcf_event_xlate(evt), arg1,
5912 fcftab->flag);
5913
5914 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
5915 return (rval);
5916 }
5917
5918 if (fcftab->attempts == 0) {
5919 fcftab->TID = fcftab->generation;
5920 }
5921
5922 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
5923 "fcoe_fcftab_read_action:%x %s:%s arg=%p attempts=%d. "
5924 "Reading FCF. <",
5925 fcftab->TID,
5926 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
5927 emlxs_fcf_event_xlate(evt), arg1,
5928 fcftab->attempts);
5929
5930 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
5931 rval = emlxs_fcoe_fcftab_state(port,
5932 FCOE_FCFTAB_STATE_READ_FAILED,
5933 FCF_REASON_NO_MBOX, 0, arg1);
5934 return (rval);
5935 }
5936 mb4 = (MAILBOX4*)mbq;
5937 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
5938
5939 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
5940 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5941
5942 rval = emlxs_fcoe_fcftab_state(port,
5943 FCOE_FCFTAB_STATE_READ_FAILED,
5944 FCF_REASON_NO_BUFFER, 0, arg1);
5945 return (rval);
5946 }
5947 bzero(mp->virt, mp->size);
5948
5949 mbq->nonembed = (void *)mp;
5950 mbq->mbox_cmpl = emlxs_fcoe_fcftab_read_mbcmpl;
5951
5952 context = ((uint32_t)fcftab->TID << 16) | (uint32_t)index;
5953 mbq->context = (void *)((unsigned long)context);
5954 mbq->port = (void *)port;
5955
5956 mb4->un.varSLIConfig.be.embedded = 0;
5957 mb4->mbxCommand = MBX_SLI_CONFIG;
5958 mb4->mbxOwner = OWN_HOST;
5959
5960 hdr_req = (mbox_req_hdr_t *)mp->virt;
5961 hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
5962 hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE;
5963 hdr_req->timeout = 0;
5964 hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE);
5965
5966 fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1);
5967 fcf->params.request.fcf_index = index;
5968
5969 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
5970 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
5971 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
5972 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5973
5974 rval = emlxs_fcoe_fcftab_state(port,
5975 FCOE_FCFTAB_STATE_READ_FAILED,
5976 FCF_REASON_SEND_FAILED, rval, arg1);
5977
5978 return (rval);
5979 }
5980
5981 return (0);
5982
5983 } /* emlxs_fcoe_fcftab_read_action() */
5984
5985
5986 /*ARGSUSED*/
5987 static uint32_t
emlxs_fcoe_fcftab_read_failed_action(emlxs_port_t * port,uint32_t evt,void * arg1)5988 emlxs_fcoe_fcftab_read_failed_action(emlxs_port_t *port, uint32_t evt,
5989 void *arg1)
5990 {
5991 emlxs_hba_t *hba = HBA;
5992 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
5993 uint32_t rval = 0;
5994
5995 fcftab->attempts++;
5996
5997 if (fcftab->state != FCOE_FCFTAB_STATE_READ_FAILED) {
5998 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
5999 "fcoe_fcftab_read_failed_action:%x %s:%s arg=%p "
6000 "attempt=%d. Invalid state. <",
6001 fcftab->TID,
6002 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6003 emlxs_fcf_event_xlate(evt),
6004 arg1, fcftab->attempts);
6005 return (1);
6006 }
6007
6008 if ((fcftab->reason == FCF_REASON_MBOX_FAILED) ||
6009 (fcftab->reason == FCF_REASON_SEND_FAILED) ||
6010 (fcftab->attempts >= 3)) {
6011 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6012 "fcoe_fcftab_read_failed_action:%x %s:%s arg=%p "
6013 "attempt=%d reason=%x. Giving up.",
6014 fcftab->TID,
6015 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6016 emlxs_fcf_event_xlate(evt), arg1,
6017 fcftab->attempts,
6018 fcftab->reason);
6019
6020 rval = emlxs_fcoe_fcftab_state(port,
6021 FCOE_FCFTAB_STATE_READ_CMPL,
6022 FCF_REASON_OP_FAILED, fcftab->attempts, arg1);
6023 } else {
6024 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6025 "fcoe_fcftab_read_failed_action:%x %s:%s arg=%p "
6026 "attempt=%d reason=%x. Retrying.",
6027 fcftab->TID,
6028 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6029 emlxs_fcf_event_xlate(evt), arg1,
6030 fcftab->attempts,
6031 fcftab->reason);
6032
6033 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_READ,
6034 FCF_REASON_OP_FAILED, fcftab->attempts, FCFTAB_READ_ALL);
6035 }
6036
6037 return (rval);
6038
6039 } /* emlxs_fcoe_fcftab_read_failed_action() */
6040
6041
6042 /*ARGSUSED*/
6043 static uint32_t
emlxs_fcoe_fcftab_read_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)6044 emlxs_fcoe_fcftab_read_cmpl_action(emlxs_port_t *port, uint32_t evt,
6045 void *arg1)
6046 {
6047 emlxs_hba_t *hba = HBA;
6048 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6049 uint32_t rval = 0;
6050 FCFIobj_t *fcfp;
6051 uint32_t i;
6052
6053 if (fcftab->state != FCOE_FCFTAB_STATE_READ_CMPL) {
6054 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6055 "fcoe_fcftab_read_cmpl_action:%x %s:%s arg=%p. "
6056 "Invalid state. <",
6057 fcftab->TID,
6058 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6059 emlxs_fcf_event_xlate(evt), arg1);
6060 return (1);
6061 }
6062
6063 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6064 "fcoe_fcftab_read_cmpl_action:%x %s:%s arg=%p attempts=%d. "
6065 "Cleaning table.",
6066 fcftab->TID,
6067 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6068 emlxs_fcf_event_xlate(evt), arg1,
6069 fcftab->attempts);
6070
6071 /* Clean FCFI table */
6072 fcfp = fcftab->table;
6073 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
6074 if (fcfp->state == FCFI_STATE_FREE) {
6075 continue;
6076 }
6077
6078 /* Adjust the freshness flag */
6079 if (fcfp->generation == fcftab->generation) {
6080 fcfp->flag |= EMLXS_FCFI_FRESH;
6081 } else {
6082 fcfp->flag &= ~EMLXS_FCFI_FRESH;
6083 }
6084
6085 /* Clear the failed bit */
6086 fcfp->flag &= ~EMLXS_FCFI_FAILED;
6087
6088 /* Free all stale unselected entries now */
6089 if (!(fcfp->flag & EMLXS_FCFI_FRESH) &&
6090 !(fcfp->flag & EMLXS_FCFI_SELECTED)) {
6091 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6092 "fcoe_fcftab_read_cmpl_action:%x. FCF stale. "
6093 "Freeing FCFI:%d. >",
6094 fcftab->TID,
6095 fcfp->fcf_index);
6096
6097 (void) emlxs_fcfi_free(port, fcfp);
6098 continue;
6099 }
6100 }
6101
6102 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_FCFI_ONLINE,
6103 FCF_REASON_EVENT, evt, arg1);
6104
6105 return (rval);
6106
6107 } /* emlxs_fcoe_fcftab_read_cmpl_action() */
6108
6109
6110 static FCFIobj_t *
emlxs_fcoe_fcftab_fcfi_select(emlxs_port_t * port,char * fabric_wwn)6111 emlxs_fcoe_fcftab_fcfi_select(emlxs_port_t *port, char *fabric_wwn)
6112 {
6113 emlxs_hba_t *hba = HBA;
6114 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6115 FCFIobj_t *fcfp;
6116 FCFIobj_t *fcfp1;
6117 uint32_t mask;
6118 uint32_t viable;
6119 uint32_t i;
6120 uint32_t j;
6121 uint32_t rnum;
6122 timespec_t time;
6123 FCFIobj_t **fcf_table;
6124 uint32_t fcf_table_count;
6125
6126 mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
6127 EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH|
6128 EMLXS_FCFI_FAILED|EMLXS_FCFI_SELECTED);
6129 viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
6130 EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH);
6131
6132 /* Tag & count viable entries */
6133 fcf_table_count = 0;
6134 fcfp = 0;
6135 fcfp1 = fcftab->table;
6136 for (i = 0; i < fcftab->table_count; i++, fcfp1++) {
6137 if (fcfp1->state == FCFI_STATE_FREE) {
6138 fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
6139 continue;
6140 }
6141
6142 if ((fcfp1->flag & mask) != viable) {
6143 fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
6144 continue;
6145 }
6146
6147 if (fabric_wwn &&
6148 bcmp(fabric_wwn,
6149 fcfp1->fcf_rec.fabric_name_identifier, 8)) {
6150 fcfp1->flag &= ~EMLXS_FCFI_TAGGED;
6151 continue;
6152 }
6153
6154 fcfp1->flag |= EMLXS_FCFI_TAGGED;
6155 fcfp = fcfp1;
6156 fcf_table_count++;
6157 }
6158
6159 if (fcf_table_count == 0) {
6160 return (NULL);
6161 }
6162
6163 if (fcf_table_count == 1) {
6164 return (fcfp);
6165 }
6166
6167 /* We found more than one viable entry */
6168
6169 fcf_table = (FCFIobj_t **)kmem_zalloc(
6170 (sizeof (uintptr_t) * fcf_table_count), KM_SLEEP);
6171
6172 /* Find the highest priority tagged entry(s) */
6173 for (i = 0; i < fcf_table_count; i++) {
6174 fcfp = 0;
6175 fcfp1 = fcftab->table;
6176 for (j = 0; j < fcftab->table_count; j++, fcfp1++) {
6177 if (!(fcfp1->flag & EMLXS_FCFI_TAGGED)) {
6178 continue;
6179 }
6180
6181 if (!fcfp ||
6182 (fcfp1->priority > fcfp->priority)) {
6183 fcfp = fcfp1;
6184 }
6185 }
6186
6187 if (fcf_table[0] &&
6188 (fcf_table[0]->priority > fcfp->priority)) {
6189 break;
6190 }
6191
6192 fcfp->flag &= ~EMLXS_FCFI_TAGGED;
6193 fcf_table[i] = fcfp;
6194 }
6195
6196 /* If more than one entry has the highest priority, */
6197 /* then randomly select one of the highest. */
6198 if (i > 1) {
6199 /* Pick a random number from 0 to (i-1) */
6200 /* This algorithm uses the lower 16 bits of the nanosecond */
6201 /* clock to determine the value */
6202 bzero(&time, sizeof (timespec_t));
6203 gethrestime(&time);
6204 rnum = (uint32_t)(time.tv_nsec & 0xFFFF);
6205
6206 fcfp = fcf_table[(rnum%i)];
6207 } else {
6208 fcfp = fcf_table[0];
6209 }
6210
6211 /* Free the priority table */
6212 kmem_free(fcf_table, (sizeof (uintptr_t) * fcf_table_count));
6213
6214 return (fcfp);
6215
6216 } /* emlxs_fcoe_fcftab_fcfi_select() */
6217
6218
6219 /*ARGSUSED*/
6220 static void
emlxs_fcoe_fcftab_process(emlxs_port_t * port)6221 emlxs_fcoe_fcftab_process(emlxs_port_t *port)
6222 {
6223 emlxs_hba_t *hba = HBA;
6224 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6225 FCFIobj_t *fcfp;
6226 FCFIobj_t *prev_fcfp;
6227 uint32_t i;
6228 uint32_t j;
6229 uint32_t count;
6230 uint32_t mask;
6231 uint32_t viable;
6232 emlxs_config_t *cfg = &CFG;
6233
6234 mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
6235 EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH|
6236 EMLXS_FCFI_FAILED);
6237 viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
6238 EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH);
6239
6240 /* Deselection process */
6241 for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
6242 fcfp = fcftab->fcfi[i];
6243
6244 if (!fcfp) {
6245 continue;
6246 }
6247
6248 /* Check if entry is viable */
6249 if ((fcfp->flag & mask) == viable) {
6250 if (fcfp->offline_timer) {
6251 fcfp->offline_timer = 0;
6252
6253 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6254 "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6255 "FCF viable. Offline timer disabled.",
6256 fcftab->TID,
6257 i, fcfp->fcf_index,
6258 emlxs_fcfi_state_xlate(fcfp->state),
6259 cfg[CFG_FCF_FAILOVER_DELAY].current);
6260 }
6261 continue;
6262 }
6263
6264 /* Previous entry is no longer viable */
6265
6266 /* If FCF is still online */
6267 if (fcfp->state > FCFI_STATE_OFFLINE) {
6268 if (fcfp->offline_timer == 0) {
6269 /* Set the offline timer */
6270 fcfp->offline_timer = hba->timer_tics +
6271 cfg[CFG_FCF_FAILOVER_DELAY].current;
6272
6273 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6274 "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6275 "No longer viable. "
6276 "Offlining FCF (%d secs).",
6277 fcftab->TID,
6278 i, fcfp->fcf_index,
6279 emlxs_fcfi_state_xlate(fcfp->state),
6280 cfg[CFG_FCF_FAILOVER_DELAY].current);
6281 }
6282 continue;
6283 }
6284
6285 /* Deselect it */
6286 fcfp->flag &= ~EMLXS_FCFI_SELECTED;
6287
6288 if (!(fcfp->flag & EMLXS_FCFI_FRESH)) {
6289 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6290 "fcoe_fcftab_process:%x %d. "
6291 "No longer viable. Freeing FCFI:%d. >",
6292 fcftab->TID,
6293 i, fcfp->fcf_index);
6294
6295 (void) emlxs_fcfi_free(port, fcfp);
6296 } else {
6297 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6298 "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6299 "No longer viable. FCF deselected.",
6300 fcftab->TID,
6301 i, fcfp->fcf_index,
6302 emlxs_fcfi_state_xlate(fcfp->state));
6303 }
6304 }
6305
6306 /* Reselection process */
6307 for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
6308 prev_fcfp = fcftab->fcfi[i];
6309 fcftab->fcfi[i] = NULL;
6310
6311 /* If no previous selection, then make new one */
6312 if (!prev_fcfp) {
6313 /* Select an fcf on any fabric */
6314 fcfp = emlxs_fcoe_fcftab_fcfi_select(port, 0);
6315
6316 if (fcfp) {
6317 fcfp->flag |= EMLXS_FCFI_SELECTED;
6318 fcftab->fcfi[i] = fcfp;
6319
6320 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6321 "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6322 "New FCF selected.",
6323 fcftab->TID,
6324 i, fcfp->fcf_index,
6325 emlxs_fcfi_state_xlate(fcfp->state));
6326 } else {
6327 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6328 "fcoe_fcftab_process:%x %d. "
6329 "No FCF available.",
6330 fcftab->TID,
6331 i);
6332 }
6333 continue;
6334 }
6335
6336 /* If previous entry is still selected, keep it */
6337 if (prev_fcfp->flag & EMLXS_FCFI_SELECTED) {
6338 fcfp = prev_fcfp;
6339 fcftab->fcfi[i] = fcfp;
6340
6341 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6342 "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6343 "FCF still selected.",
6344 fcftab->TID,
6345 i, fcfp->fcf_index,
6346 emlxs_fcfi_state_xlate(fcfp->state));
6347 continue;
6348 }
6349
6350 /* Previous entry is no longer selected */
6351
6352 /* Select a new fcf from same fabric */
6353 fcfp = emlxs_fcoe_fcftab_fcfi_select(port,
6354 (char *)prev_fcfp->fcf_rec.fabric_name_identifier);
6355
6356 if (fcfp) {
6357 fcfp->flag |= EMLXS_FCFI_SELECTED;
6358 fcftab->fcfi[i] = fcfp;
6359
6360 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6361 "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6362 "New FCF, same fabric selected.",
6363 fcftab->TID,
6364 i, fcfp->fcf_index,
6365 emlxs_fcfi_state_xlate(fcfp->state));
6366 continue;
6367 }
6368
6369 /* Select fcf from any fabric */
6370 fcfp = emlxs_fcoe_fcftab_fcfi_select(port, 0);
6371
6372 if (fcfp) {
6373 fcfp->flag |= EMLXS_FCFI_SELECTED;
6374 fcftab->fcfi[i] = fcfp;
6375
6376 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6377 "fcoe_fcftab_process:%x %d fcfi=%d %s. "
6378 "New FCF, new fabric selected.",
6379 fcftab->TID,
6380 i, fcfp->fcf_index,
6381 emlxs_fcfi_state_xlate(fcfp->state));
6382 continue;
6383 }
6384
6385 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6386 "fcoe_fcftab_process:%x %d. No FCF available.",
6387 fcftab->TID,
6388 i);
6389 }
6390
6391 /* Pack entries */
6392 count = 0;
6393 for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) {
6394 if (fcftab->fcfi[i]) {
6395 count++;
6396 continue;
6397 }
6398
6399 for (j = i+1; j < FCFTAB_MAX_FCFI_COUNT; j++) {
6400 if (fcftab->fcfi[j] == NULL) {
6401 continue;
6402 }
6403
6404 fcftab->fcfi[i] = fcftab->fcfi[j];
6405 fcftab->fcfi[j] = NULL;
6406 count++;
6407 break;
6408 }
6409
6410 if (j == FCFTAB_MAX_FCFI_COUNT) {
6411 break;
6412 }
6413 }
6414 fcftab->fcfi_count = count;
6415
6416 return;
6417
6418 } /* emlxs_fcoe_fcftab_process() */
6419
6420
6421 /*ARGSUSED*/
6422 static uint32_t
emlxs_fcoe_fcftab_fcfi_online_action(emlxs_port_t * port,uint32_t evt,void * arg1)6423 emlxs_fcoe_fcftab_fcfi_online_action(emlxs_port_t *port, uint32_t evt,
6424 void *arg1)
6425 {
6426 emlxs_hba_t *hba = HBA;
6427 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6428 FCFIobj_t *fcfp;
6429 uint32_t rval = 0;
6430 uint32_t i;
6431 uint32_t offline_count = 0;
6432 uint32_t online_count = 0;
6433
6434 if (fcftab->state != FCOE_FCFTAB_STATE_FCFI_ONLINE) {
6435 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6436 "fcoe_fcftab_fcfi_online_action:%x %s:%s arg=%p. "
6437 "Invalid state. <",
6438 fcftab->TID,
6439 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6440 emlxs_fcf_event_xlate(evt), arg1);
6441 return (1);
6442 }
6443
6444 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
6445 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6446 "fcoe_fcftab_fcfi_online_action:%x flag=%x. "
6447 "Handling request.",
6448 fcftab->TID,
6449 fcftab->flag);
6450
6451 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
6452 return (rval);
6453 }
6454
6455 emlxs_fcoe_fcftab_process(port);
6456
6457 for (i = 0; i < fcftab->fcfi_count; i++) {
6458 fcfp = fcftab->fcfi[i];
6459
6460 if (fcfp->offline_timer == 0) {
6461 online_count++;
6462
6463 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6464 "fcoe_fcftab_fcfi_online_action:%x fcfi_count=%d. "
6465 "Onlining FCFI:%d. >",
6466 fcftab->TID,
6467 fcftab->fcfi_count,
6468 fcfp->fcf_index);
6469
6470 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_ONLINE,
6471 fcfp);
6472 } else {
6473 offline_count++;
6474
6475 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6476 "fcoe_fcftab_fcfi_online_action:%x fcfi_count=%d. "
6477 "Offlining fcfi:%d.",
6478 fcftab->TID,
6479 fcftab->fcfi_count,
6480 fcfp->fcf_index);
6481 }
6482 }
6483
6484 if (offline_count) {
6485 /* Wait for FCF's to go offline */
6486 rval = emlxs_fcoe_fcftab_state(port,
6487 FCOE_FCFTAB_STATE_FCFI_OFFLINE,
6488 FCF_REASON_EVENT, evt, arg1);
6489
6490 /* Service timer now */
6491 emlxs_fcoe_fcftab_offline_timer(hba);
6492
6493 return (rval);
6494 }
6495
6496 if (!online_count) {
6497 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6498 "fcoe_fcftab_fcfi_online_action:%x fcfi_count=%d.",
6499 fcftab->TID,
6500 fcftab->fcfi_count);
6501 }
6502
6503 rval = emlxs_fcoe_fcftab_state(port,
6504 FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL,
6505 FCF_REASON_EVENT, evt, arg1);
6506
6507 return (rval);
6508
6509 } /* emlxs_fcoe_fcftab_fcfi_online_action() */
6510
6511
6512 /*ARGSUSED*/
6513 static uint32_t
emlxs_fcoe_fcftab_fcfi_online_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)6514 emlxs_fcoe_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, uint32_t evt,
6515 void *arg1)
6516 {
6517 emlxs_hba_t *hba = HBA;
6518 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6519 uint32_t rval = 0;
6520
6521 if (fcftab->state != FCOE_FCFTAB_STATE_FCFI_ONLINE_CMPL) {
6522 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6523 "fcoe_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p. "
6524 "Invalid state. <",
6525 fcftab->TID,
6526 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6527 emlxs_fcf_event_xlate(evt), arg1);
6528 return (1);
6529 }
6530
6531 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
6532 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6533 "fcoe_fcftab_fcfi_online_cmpl_action:%x %s:%s "
6534 "arg=%p flag=%x. Handling request.",
6535 fcftab->TID,
6536 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6537 emlxs_fcf_event_xlate(evt), arg1,
6538 fcftab->flag);
6539
6540 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
6541 return (rval);
6542 }
6543
6544 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6545 "fcoe_fcftab_fcfi_online_cmpl_action:%x %s:%s arg=%p. "
6546 "Going online.",
6547 fcftab->TID,
6548 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6549 emlxs_fcf_event_xlate(evt), arg1);
6550
6551 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_ONLINE,
6552 FCF_REASON_EVENT, evt, arg1);
6553
6554 return (rval);
6555
6556 } /* emlxs_fcoe_fcftab_fcfi_online_cmpl_action() */
6557
6558
6559 /*ARGSUSED*/
6560 static uint32_t
emlxs_fcoe_fcftab_fcfi_offline_action(emlxs_port_t * port,uint32_t evt,void * arg1)6561 emlxs_fcoe_fcftab_fcfi_offline_action(emlxs_port_t *port, uint32_t evt,
6562 void *arg1)
6563 {
6564 emlxs_hba_t *hba = HBA;
6565 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6566 FCFIobj_t *fcfp;
6567 uint32_t rval = 0;
6568 int32_t i;
6569 uint32_t fcfi_offline;
6570
6571 if (fcftab->state != FCOE_FCFTAB_STATE_FCFI_OFFLINE) {
6572 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6573 "fcoe_fcftab_fcfi_offline_action:%x %s:%s arg=%p. "
6574 "Invalid state. <",
6575 fcftab->TID,
6576 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6577 emlxs_fcf_event_xlate(evt), arg1);
6578 return (1);
6579 }
6580
6581 /* Check for FCF's going offline */
6582 fcfi_offline = 0;
6583 for (i = 0; i < fcftab->fcfi_count; i++) {
6584 fcfp = fcftab->fcfi[i];
6585
6586 if (fcfp->state <= FCFI_STATE_OFFLINE) {
6587 continue;
6588 }
6589
6590 if (fcfp->offline_timer ||
6591 (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
6592 fcfi_offline++;
6593 }
6594 }
6595
6596 if (fcfi_offline) {
6597 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6598 "fcoe_fcftab_fcfi_offline_action:%x %s:%s arg=%p "
6599 "fcfi_offline=%d. <",
6600 fcftab->TID,
6601 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6602 emlxs_fcf_event_xlate(evt), arg1,
6603 fcfi_offline);
6604
6605 return (0);
6606 }
6607
6608 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6609 "fcoe_fcftab_fcfi_offline_action:%x %s:%s arg=%p.",
6610 fcftab->TID,
6611 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6612 emlxs_fcf_event_xlate(evt), arg1);
6613
6614 rval = emlxs_fcoe_fcftab_state(port,
6615 FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL,
6616 FCF_REASON_EVENT, evt, arg1);
6617
6618 return (rval);
6619
6620 } /* emlxs_fcoe_fcftab_fcfi_offline_action() */
6621
6622
6623 /*ARGSUSED*/
6624 static uint32_t
emlxs_fcoe_fcftab_fcfi_offline_cmpl_action(emlxs_port_t * port,uint32_t evt,void * arg1)6625 emlxs_fcoe_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, uint32_t evt,
6626 void *arg1)
6627 {
6628 emlxs_hba_t *hba = HBA;
6629 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6630 uint32_t rval = 0;
6631
6632 if (fcftab->state != FCOE_FCFTAB_STATE_FCFI_OFFLINE_CMPL) {
6633 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
6634 "fcoe_fcftab_fcfi_offline_cmpl_action:%x %s:%s arg=%p. "
6635 "Invalid state. <",
6636 fcftab->TID,
6637 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6638 emlxs_fcf_event_xlate(evt), arg1);
6639 return (1);
6640 }
6641
6642 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
6643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6644 "fcoe_fcftab_fcfi_offline_cmpl_action:%x %s:%s arg=%p. "
6645 "Handling request.",
6646 fcftab->TID,
6647 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6648 emlxs_fcf_event_xlate(evt), arg1);
6649
6650 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
6651 return (rval);
6652 }
6653
6654 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6655 "fcoe_fcftab_fcfi_offline_cmpl_action:%x %s:%s arg=%p. "
6656 "Returning FCF(s) online.",
6657 fcftab->TID,
6658 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6659 emlxs_fcf_event_xlate(evt), arg1);
6660
6661 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_FCFI_ONLINE,
6662 FCF_REASON_EVENT, evt, arg1);
6663
6664 return (rval);
6665
6666 } /* emlxs_fcoe_fcftab_fcfi_offline_cmpl_action() */
6667
6668
6669 /*ARGSUSED*/
6670 static uint32_t
emlxs_fcoe_fcftab_found_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)6671 emlxs_fcoe_fcftab_found_evt_action(emlxs_port_t *port, uint32_t evt,
6672 void *arg1)
6673 {
6674 emlxs_hba_t *hba = HBA;
6675 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6676 uint32_t fcf_index = (uint32_t)((unsigned long)arg1);
6677 FCFIobj_t *fcfp;
6678 uint32_t rval = 0;
6679
6680 if (evt != FCF_EVENT_FCF_FOUND) {
6681 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6682 "fcoe_fcftab_found_evt_action:%x %s:%s fcf_index=%d. "
6683 "Invalid event type. <",
6684 fcftab->TID,
6685 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6686 emlxs_fcf_event_xlate(evt),
6687 fcf_index);
6688
6689 return (1);
6690 }
6691
6692 switch (fcftab->state) {
6693 case FCOE_FCFTAB_STATE_SOLICIT:
6694 case FCOE_FCFTAB_STATE_SOLICIT_CMPL:
6695 case FCOE_FCFTAB_STATE_READ:
6696 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6697 "fcoe_fcftab_found_evt_action:%x %s:%s "
6698 "fcf_index=%d gen=%x. <",
6699 fcftab->TID,
6700 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6701 emlxs_fcf_event_xlate(evt),
6702 fcf_index, fcftab->generation);
6703 break;
6704
6705 /* case FCOE_FCFTAB_STATE_FCFI_OFFLINE: */
6706 default:
6707
6708 /* Scan for matching fcf index in table */
6709 fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
6710
6711 if (fcfp && (fcfp->flag & EMLXS_FCFI_SELECTED)) {
6712
6713 /* Trigger table read */
6714 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6715 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6716 fcftab->generation++;
6717
6718 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6719 "fcoe_fcftab_found_evt_action:%x %s:%s "
6720 "fcf_index=%d gen=%x. Read FCF table.",
6721 fcftab->TID,
6722 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6723 emlxs_fcf_event_xlate(evt),
6724 fcf_index, fcftab->generation);
6725
6726 rval = emlxs_fcoe_fcftab_state(port,
6727 FCOE_FCFTAB_STATE_READ,
6728 FCF_REASON_EVENT, evt, arg1);
6729
6730 break;
6731 }
6732
6733 /* Check if we need more FCF's */
6734 if (fcftab->fcfi_online < FCFTAB_MAX_FCFI_COUNT) {
6735
6736 /* Trigger table read */
6737 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6738 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6739 fcftab->generation++;
6740
6741 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6742 "fcoe_fcftab_found_evt_action:%x %s:%s "
6743 "fcf_index=%d gen=%x fcfi_online=%d. "
6744 "Read FCF table.",
6745 fcftab->TID,
6746 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6747 emlxs_fcf_event_xlate(evt),
6748 fcf_index, fcftab->generation,
6749 fcftab->fcfi_online);
6750
6751 rval = emlxs_fcoe_fcftab_state(port,
6752 FCOE_FCFTAB_STATE_READ,
6753 FCF_REASON_EVENT, evt, arg1);
6754
6755 break;
6756 }
6757
6758 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6759 "fcoe_fcftab_found_evt_action:%x %s:%s fcfi=%d. "
6760 "FCF not needed. <",
6761 fcftab->TID,
6762 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6763 emlxs_fcf_event_xlate(evt),
6764 fcf_index);
6765
6766 break;
6767 }
6768
6769 return (rval);
6770
6771 } /* emlxs_fcoe_fcftab_found_evt_action() */
6772
6773
6774 /*ARGSUSED*/
6775 static uint32_t
emlxs_fcoe_fcftab_lost_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)6776 emlxs_fcoe_fcftab_lost_evt_action(emlxs_port_t *port, uint32_t evt,
6777 void *arg1)
6778 {
6779 emlxs_hba_t *hba = HBA;
6780 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6781 FCFIobj_t *fcfp;
6782 uint32_t fcf_index = (uint32_t)((unsigned long)arg1);
6783 emlxs_port_t *vport;
6784 VPIobj_t *vpip;
6785 uint32_t i;
6786 uint32_t rval = 0;
6787
6788 if (evt != FCF_EVENT_FCF_LOST) {
6789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6790 "fcoe_fcftab_lost_evt_action:%x %s:%s fcf_index=%d. "
6791 "Invalid event type. <",
6792 fcftab->TID,
6793 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6794 emlxs_fcf_event_xlate(evt),
6795 fcf_index);
6796
6797 return (1);
6798 }
6799
6800 /* Scan for matching fcf index in table */
6801 fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
6802
6803 if (!fcfp) {
6804 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6805 "fcoe_fcftab_lost_evt_action:%x %s:%s fcf_index=%d. "
6806 "FCF not found. <",
6807 fcftab->TID,
6808 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6809 emlxs_fcf_event_xlate(evt),
6810 fcf_index);
6811
6812 return (0);
6813 }
6814
6815 if (!(fcfp->flag & EMLXS_FCFI_SELECTED)) {
6816 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6817 "fcoe_fcftab_changed_evt_action:%x %s:%s fcf_index=%d. "
6818 "FCF not selected. <",
6819 fcftab->TID,
6820 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6821 emlxs_fcf_event_xlate(evt),
6822 fcf_index);
6823
6824 return (0);
6825 }
6826
6827 /* Offline VPI's of this FCFI */
6828 for (i = 0; i <= hba->vpi_max; i++) {
6829 vport = &VPORT(i);
6830 vpip = vport->vpip;
6831
6832 if ((vpip->state == VPI_STATE_OFFLINE) ||
6833 (vpip->vfip->fcfp != fcfp)) {
6834 continue;
6835 }
6836
6837 /* Fabric logo is implied */
6838 emlxs_vpi_logo_handler(port, vpip);
6839
6840 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6841 "fcoe_fcftab_lost_evt_action:%x %s:%s fcf_index=%d gen=%x. "
6842 "Offlining VPI:%d. >",
6843 fcftab->TID,
6844 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6845 emlxs_fcf_event_xlate(evt),
6846 fcf_index, fcftab->generation,
6847 vpip->VPI);
6848
6849 (void) emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
6850 }
6851
6852 switch (fcftab->state) {
6853 case FCOE_FCFTAB_STATE_SOLICIT:
6854 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6855 "fcoe_fcftab_lost_evt_action:%x %s gen=%x. "
6856 "Already soliciting. <",
6857 fcftab->TID,
6858 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6859 fcftab->generation);
6860 break;
6861
6862 default:
6863 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6864 fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
6865 fcftab->generation++;
6866
6867 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6868 "fcoe_fcftab_lost_evt_action:%x %s gen=%x. Soliciting.",
6869 fcftab->TID,
6870 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6871 fcftab->generation);
6872
6873 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
6874 FCF_REASON_EVENT, evt, arg1);
6875 break;
6876 }
6877
6878 return (rval);
6879
6880 } /* emlxs_fcoe_fcftab_lost_evt_action() */
6881
6882
6883 /*ARGSUSED*/
6884 static uint32_t
emlxs_fcoe_fcftab_changed_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)6885 emlxs_fcoe_fcftab_changed_evt_action(emlxs_port_t *port, uint32_t evt,
6886 void *arg1)
6887 {
6888 emlxs_hba_t *hba = HBA;
6889 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6890 FCFIobj_t *fcfp;
6891 uint32_t fcf_index = (uint32_t)((unsigned long)arg1);
6892 uint32_t rval = 0;
6893
6894 if (evt != FCF_EVENT_FCF_CHANGED) {
6895 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6896 "fcoe_fcftab_changed_evt_action:%x %s:%s fcf_index=%d. "
6897 "Invalid event type. <",
6898 fcftab->TID,
6899 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6900 emlxs_fcf_event_xlate(evt),
6901 fcf_index);
6902
6903 return (1);
6904 }
6905
6906 switch (fcftab->state) {
6907 case FCOE_FCFTAB_STATE_SOLICIT:
6908 case FCOE_FCFTAB_STATE_SOLICIT_CMPL:
6909 case FCOE_FCFTAB_STATE_READ:
6910 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6911 "fcoe_fcftab_changed_evt_action:%x %s:%s "
6912 "fcf_index=%d gen=%x. <",
6913 fcftab->TID,
6914 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6915 emlxs_fcf_event_xlate(evt),
6916 fcf_index, fcftab->generation);
6917 break;
6918
6919 /* case FCOE_FCFTAB_STATE_FCFI_OFFLINE: */
6920 default:
6921
6922 /* Scan for matching fcf index in table */
6923 fcfp = emlxs_fcfi_find(port, 0, &fcf_index);
6924
6925 if (fcfp && (fcfp->flag & EMLXS_FCFI_SELECTED)) {
6926
6927 /* Trigger table read */
6928 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6929 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6930 fcftab->generation++;
6931
6932 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6933 "fcoe_fcftab_changed_evt_action:%x %s:%s "
6934 "fcf_index=%d gen=%x. Read FCF table.",
6935 fcftab->TID,
6936 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6937 emlxs_fcf_event_xlate(evt),
6938 fcf_index, fcftab->generation);
6939
6940 rval = emlxs_fcoe_fcftab_state(port,
6941 FCOE_FCFTAB_STATE_READ,
6942 FCF_REASON_EVENT, evt, arg1);
6943
6944 break;
6945 }
6946
6947 /* Check if we need more FCF's */
6948 if (fcftab->fcfi_online < FCFTAB_MAX_FCFI_COUNT) {
6949
6950 /* Trigger table read */
6951 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
6952 fcftab->flag |= EMLXS_FCOE_FCFTAB_READ_REQ;
6953 fcftab->generation++;
6954
6955 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6956 "fcoe_fcftab_changed_evt_action:%x %s:%s "
6957 "fcf_index=%d gen=%x fcfi_online=%d. "
6958 "Read FCF table.",
6959 fcftab->TID,
6960 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6961 emlxs_fcf_event_xlate(evt),
6962 fcf_index, fcftab->generation,
6963 fcftab->fcfi_online);
6964
6965 rval = emlxs_fcoe_fcftab_state(port,
6966 FCOE_FCFTAB_STATE_READ,
6967 FCF_REASON_EVENT, evt, arg1);
6968
6969 break;
6970 }
6971
6972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
6973 "fcoe_fcftab_changed_evt_action:%x %s:%s fcfi=%d. "
6974 "FCF not needed. <",
6975 fcftab->TID,
6976 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
6977 emlxs_fcf_event_xlate(evt),
6978 fcf_index);
6979
6980 break;
6981 }
6982
6983 return (rval);
6984
6985 } /* emlxs_fcoe_fcftab_changed_evt_action() */
6986
6987
6988 /*ARGSUSED*/
6989 static uint32_t
emlxs_fcoe_fcftab_fcf_delete(emlxs_port_t * port,uint32_t fcf_index)6990 emlxs_fcoe_fcftab_fcf_delete(emlxs_port_t *port, uint32_t fcf_index)
6991 {
6992 emlxs_hba_t *hba = HBA;
6993 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
6994 MAILBOXQ *mbq;
6995 MAILBOX4 *mb4;
6996 MATCHMAP *mp = NULL;
6997 uint32_t rval = 0;
6998
6999 IOCTL_FCOE_DELETE_FCF_TABLE *fcf;
7000 mbox_req_hdr_t *hdr_req;
7001
7002 if (fcf_index >= fcftab->fcfi_count) {
7003 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7004 "fcoe_fcftab_fcf_delete:%x fcfi:%d failed. "
7005 "Out of range.",
7006 fcftab->TID,
7007 fcf_index);
7008
7009 return (1);
7010 }
7011
7012 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
7013 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7014 "fcoe_fcftab_fcf_delete:%x fcfi:%d failed. "
7015 "Unable to allocate mailbox.",
7016 fcftab->TID,
7017 fcf_index);
7018
7019 return (1);
7020 }
7021
7022 mb4 = (MAILBOX4*)mbq;
7023 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
7024
7025 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
7026 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7027 "fcoe_fcftab_fcf_delete:%x fcfi:%d failed. "
7028 "Unable to allocate buffer.",
7029 fcftab->TID,
7030 fcf_index);
7031
7032 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7033 return (1);
7034 }
7035 bzero(mp->virt, mp->size);
7036
7037 mbq->nonembed = (void *)mp;
7038 mbq->mbox_cmpl = NULL;
7039 mbq->context = (void *)((unsigned long)fcf_index);
7040 mbq->port = (void *)port;
7041
7042 mb4->un.varSLIConfig.be.embedded = 0;
7043 mb4->mbxCommand = MBX_SLI_CONFIG;
7044 mb4->mbxOwner = OWN_HOST;
7045
7046 hdr_req = (mbox_req_hdr_t *)mp->virt;
7047 hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
7048 hdr_req->opcode = FCOE_OPCODE_DELETE_FCF_TABLE;
7049 hdr_req->timeout = 0;
7050 hdr_req->req_length = sizeof (IOCTL_FCOE_DELETE_FCF_TABLE);
7051
7052 fcf = (IOCTL_FCOE_DELETE_FCF_TABLE *)(hdr_req + 1);
7053 fcf->params.request.fcf_count = 1;
7054 fcf->params.request.fcf_indexes[0] = (uint16_t)fcf_index;
7055
7056 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7057 "fcoe_fcftab_fcf_delete:%x fcfi:%d. <",
7058 fcftab->TID,
7059 fcf_index);
7060
7061 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
7062 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
7063 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7064 "fcoe_fcftab_fcf_delete:%x fcfi:%d failed. "
7065 "Unable to send request.",
7066 fcftab->TID,
7067 fcf_index);
7068
7069 if (mp) {
7070 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
7071 }
7072 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7073
7074 return (1);
7075 }
7076
7077 return (0);
7078
7079
7080 } /* emlxs_fcoe_fcftab_fcf_delete() */
7081
7082
7083 /*ARGSUSED*/
7084 static uint32_t
emlxs_fcoe_fcftab_full_evt_action(emlxs_port_t * port,uint32_t evt,void * arg1)7085 emlxs_fcoe_fcftab_full_evt_action(emlxs_port_t *port, uint32_t evt,
7086 void *arg1)
7087 {
7088 emlxs_hba_t *hba = HBA;
7089 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7090 FCFIobj_t *fcfp;
7091 uint32_t rval = 0;
7092 uint32_t mask;
7093 uint32_t viable;
7094 uint32_t i;
7095 uint32_t count;
7096
7097 if (evt != FCF_EVENT_FCFTAB_FULL) {
7098 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7099 "fcoe_fcftab_full_evt_action:%x %s:%s arg=%p. "
7100 "Invalid event type. <",
7101 fcftab->TID,
7102 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7103 emlxs_fcf_event_xlate(evt), arg1);
7104
7105 return (1);
7106 }
7107
7108 if (fcftab->fcfi_online == FCFTAB_MAX_FCFI_COUNT) {
7109 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7110 "fcoe_fcftab_full_evt_action:%x %s:%s arg=%p "
7111 "fcfi_online=%d. <",
7112 fcftab->TID,
7113 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7114 emlxs_fcf_event_xlate(evt), arg1,
7115 fcftab->fcfi_online);
7116
7117 return (0);
7118 }
7119
7120 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7121 "fcoe_fcftab_full_evt_action:%x %s:%s arg=%p fcfi_online=%d. "
7122 "Cleaning table...",
7123 fcftab->TID,
7124 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7125 emlxs_fcf_event_xlate(evt), arg1,
7126 fcftab->fcfi_online);
7127
7128 mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7129 EMLXS_FCFI_CONFIGURED);
7130 viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7131 EMLXS_FCFI_CONFIGURED);
7132
7133 count = 0;
7134 fcfp = fcftab->table;
7135 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7136 if (fcfp->state == FCFI_STATE_FREE) {
7137 continue;
7138 }
7139
7140 if (fcfp->flag & EMLXS_FCFI_SELECTED) {
7141 continue;
7142 }
7143
7144 if ((fcfp->flag & mask) == viable) {
7145 continue;
7146 }
7147
7148 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7149 "fcoe_fcftab_full_evt_action:%x. "
7150 "Deleting FCFI:%d %x. >",
7151 fcftab->TID,
7152 fcfp->fcf_index,
7153 fcfp->flag);
7154
7155 (void) emlxs_fcfi_free(port, fcfp);
7156
7157 (void) emlxs_fcoe_fcftab_fcf_delete(port, fcfp->fcf_index);
7158
7159 count++;
7160 }
7161
7162 if (!count) {
7163 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7164 "fcoe_fcftab_full_evt_action:%x %s:%s arg=%p. "
7165 "All FCF's are viable. <",
7166 fcftab->TID,
7167 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7168 emlxs_fcf_event_xlate(evt), arg1);
7169
7170 return (0);
7171 }
7172
7173 switch (fcftab->state) {
7174 case FCOE_FCFTAB_STATE_SOLICIT:
7175 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7176 "fcoe_fcftab_full_evt_action:%x %s gen=%x. "
7177 "Already soliciting. <",
7178 fcftab->TID,
7179 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7180 fcftab->generation);
7181 break;
7182
7183 default:
7184 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK;
7185 fcftab->flag |= EMLXS_FCOE_FCFTAB_SOL_REQ;
7186 fcftab->generation++;
7187
7188 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7189 "fcoe_fcftab_full_evt_action:%x %s gen=%x. Soliciting.",
7190 fcftab->TID,
7191 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7192 fcftab->generation);
7193
7194 rval = emlxs_fcoe_fcftab_state(port, FCOE_FCFTAB_STATE_SOLICIT,
7195 FCF_REASON_EVENT, evt, arg1);
7196 break;
7197 }
7198
7199 return (rval);
7200
7201 } /* emlxs_fcoe_fcftab_full_evt_action() */
7202
7203
7204 /*ARGSUSED*/
7205 static uint32_t
emlxs_fcoe_fcftab_online_action(emlxs_port_t * port,uint32_t evt,void * arg1)7206 emlxs_fcoe_fcftab_online_action(emlxs_port_t *port, uint32_t evt,
7207 void *arg1)
7208 {
7209 emlxs_hba_t *hba = HBA;
7210 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7211 emlxs_config_t *cfg = &CFG;
7212 FCFIobj_t *fcfp;
7213 uint32_t rval = 0;
7214 uint32_t mask;
7215 uint32_t viable;
7216 uint32_t i;
7217 uint32_t count = 0;
7218
7219 if (fcftab->state != FCOE_FCFTAB_STATE_ONLINE) {
7220 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7221 "fcoe_fcftab_online_action:%x %s:%s arg=%p. "
7222 "Invalid state. <",
7223 fcftab->TID,
7224 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7225 emlxs_fcf_event_xlate(evt), arg1);
7226 return (1);
7227 }
7228
7229 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
7230 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7231 "fcoe_fcftab_online_action:%x flag=%x. "
7232 "Handling request.",
7233 fcftab->TID,
7234 fcftab->flag);
7235
7236 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
7237 return (rval);
7238 }
7239
7240 if (fcftab->fcfi_online == 0) {
7241 mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7242 EMLXS_FCFI_CONFIGURED);
7243 viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE|
7244 EMLXS_FCFI_CONFIGURED);
7245
7246 /* Count viable FCF's in table */
7247 count = 0;
7248 fcfp = fcftab->table;
7249 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7250 if (fcfp->state == FCFI_STATE_FREE) {
7251 continue;
7252 }
7253
7254 if ((fcfp->flag & mask) == viable) {
7255 count++;
7256 }
7257 }
7258
7259 if (count) {
7260 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7261 "fcoe_fcftab_online_action:%x %s:%s "
7262 "fcfi_online=0,%d,%d. Starting resolicit timer. <",
7263 fcftab->TID,
7264 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7265 emlxs_fcf_event_xlate(evt),
7266 fcftab->fcfi_count, count);
7267
7268 /* Start the solicit timer */
7269 fcftab->sol_timer = hba->timer_tics +
7270 cfg[CFG_FCF_RESOLICIT_DELAY].current;
7271 } else {
7272 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7273 "fcoe_fcftab_online_action:%x %s:%s "
7274 "fcfi_online=0,%d,0. Wait for FCF event. <",
7275 fcftab->TID,
7276 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7277 emlxs_fcf_event_xlate(evt),
7278 fcftab->fcfi_count);
7279 }
7280
7281 emlxs_fcf_linkdown(port);
7282
7283 return (0);
7284 }
7285
7286 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7287 "fcoe_fcftab_online_action:%x flag=%x fcfi_online=%d. "
7288 "Online. <",
7289 fcftab->TID,
7290 fcftab->flag,
7291 fcftab->fcfi_online);
7292
7293 emlxs_fcf_linkup(port);
7294
7295 return (rval);
7296
7297 } /* emlxs_fcoe_fcftab_online_action() */
7298
7299
7300 /*ARGSUSED*/
7301 static uint32_t
emlxs_fcoe_fcftab_offline_action(emlxs_port_t * port,uint32_t evt,void * arg1)7302 emlxs_fcoe_fcftab_offline_action(emlxs_port_t *port, uint32_t evt,
7303 void *arg1)
7304 {
7305 emlxs_hba_t *hba = HBA;
7306 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7307 uint32_t rval = 0;
7308
7309 if (fcftab->state != FCOE_FCFTAB_STATE_OFFLINE) {
7310 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7311 "fcoe_fcftab_offline_action:%x %s:%s arg=%p. "
7312 "Invalid state. <",
7313 fcftab->TID,
7314 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7315 emlxs_fcf_event_xlate(evt), arg1);
7316 return (1);
7317 }
7318
7319
7320 fcftab->flag &= ~EMLXS_FCOE_FCFTAB_OFFLINE_REQ;
7321
7322 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) {
7323 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7324 "fcoe_fcftab_offline_action:%x %s:%s arg=%p flag=%x. "
7325 "Handling request.",
7326 fcftab->TID,
7327 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7328 emlxs_fcf_event_xlate(evt), arg1,
7329 fcftab->flag);
7330
7331 rval = emlxs_fcoe_fcftab_req_handler(port, arg1);
7332 return (rval);
7333 }
7334
7335 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7336 "fcoe_fcftab_offline_action:%x %s:%s arg=%p fcfi_online=%d. "
7337 "Offline. <",
7338 fcftab->TID,
7339 emlxs_fcoe_fcftab_state_xlate(fcftab->state),
7340 emlxs_fcf_event_xlate(evt), arg1,
7341 fcftab->fcfi_online);
7342
7343 return (rval);
7344
7345 } /* emlxs_fcoe_fcftab_offline_action() */
7346
7347
7348 /* ************************************************************************** */
7349 /* FCFI */
7350 /* ************************************************************************** */
7351
7352 static char *
emlxs_fcfi_state_xlate(uint32_t state)7353 emlxs_fcfi_state_xlate(uint32_t state)
7354 {
7355 static char buffer[32];
7356 uint32_t i;
7357 uint32_t count;
7358
7359 count = sizeof (emlxs_fcfi_state_table) / sizeof (emlxs_table_t);
7360 for (i = 0; i < count; i++) {
7361 if (state == emlxs_fcfi_state_table[i].code) {
7362 return (emlxs_fcfi_state_table[i].string);
7363 }
7364 }
7365
7366 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
7367 return (buffer);
7368
7369 } /* emlxs_fcfi_state_xlate() */
7370
7371
7372 static uint32_t
emlxs_fcfi_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7373 emlxs_fcfi_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
7374 void *arg1)
7375 {
7376 uint32_t rval = 0;
7377 uint32_t(*func) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *);
7378 uint32_t index;
7379 uint32_t events;
7380 uint16_t state;
7381
7382 /* Convert event to action table index */
7383 switch (evt) {
7384 case FCF_EVENT_STATE_ENTER:
7385 index = 0;
7386 break;
7387 case FCF_EVENT_FCFI_ONLINE:
7388 index = 1;
7389 break;
7390 case FCF_EVENT_FCFI_OFFLINE:
7391 index = 2;
7392 break;
7393 case FCF_EVENT_FCFI_PAUSE:
7394 index = 3;
7395 break;
7396 case FCF_EVENT_VFI_ONLINE:
7397 index = 4;
7398 break;
7399 case FCF_EVENT_VFI_OFFLINE:
7400 index = 5;
7401 break;
7402 default:
7403 return (1);
7404 }
7405
7406 events = FCFI_ACTION_EVENTS;
7407 state = fcfp->state;
7408
7409 index += (state * events);
7410 func = (uint32_t(*) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *))
7411 emlxs_fcfi_action_table[index];
7412
7413 if (!func) {
7414 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7415 "fcfi_action:%d %s:%s arg=%p. No action. <",
7416 fcfp->fcf_index,
7417 emlxs_fcfi_state_xlate(fcfp->state),
7418 emlxs_fcf_event_xlate(evt), arg1);
7419
7420 return (1);
7421 }
7422
7423 rval = (func)(port, fcfp, evt, arg1);
7424
7425 return (rval);
7426
7427 } /* emlxs_fcfi_action() */
7428
7429
7430 static uint32_t
emlxs_fcfi_event(emlxs_port_t * port,uint32_t evt,void * arg1)7431 emlxs_fcfi_event(emlxs_port_t *port, uint32_t evt,
7432 void *arg1)
7433 {
7434 FCFIobj_t *fcfp = NULL;
7435 VFIobj_t *vfip = NULL;
7436 uint32_t rval = 0;
7437
7438 /* Filter events and acquire fcfi context */
7439 switch (evt) {
7440 case FCF_EVENT_VFI_ONLINE:
7441 case FCF_EVENT_VFI_OFFLINE:
7442 vfip = (VFIobj_t *)arg1;
7443
7444 if (!vfip) {
7445 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7446 "fcfi_event: %s arg=%p. Null VFI found. <",
7447 emlxs_fcf_event_xlate(evt), arg1);
7448
7449 return (1);
7450 }
7451
7452 fcfp = vfip->fcfp;
7453 if (!fcfp) {
7454 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7455 "fcfi_event: %s arg=%p. FCF not found. <",
7456 emlxs_fcf_event_xlate(evt), arg1);
7457
7458 return (1);
7459 }
7460 break;
7461
7462 case FCF_EVENT_FCFI_ONLINE:
7463 case FCF_EVENT_FCFI_OFFLINE:
7464 case FCF_EVENT_FCFI_PAUSE:
7465 fcfp = (FCFIobj_t *)arg1;
7466 if (!fcfp) {
7467 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7468 "fcfi_event: %s arg=%p. Null FCFI found. <",
7469 emlxs_fcf_event_xlate(evt), arg1);
7470
7471 return (1);
7472 }
7473 break;
7474
7475 default:
7476 return (1);
7477 }
7478
7479 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
7480 "fcfi_event:%d %s:%s arg=%p",
7481 fcfp->fcf_index,
7482 emlxs_fcfi_state_xlate(fcfp->state),
7483 emlxs_fcf_event_xlate(evt), arg1);
7484
7485 rval = emlxs_fcfi_action(port, fcfp, evt, arg1);
7486
7487 return (rval);
7488
7489 } /* emlxs_fcfi_event() */
7490
7491
7492 /* EMLXS_FCF_LOCK must be held to enter */
7493 /*ARGSUSED*/
7494 static uint32_t
emlxs_fcfi_state(emlxs_port_t * port,FCFIobj_t * fcfp,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)7495 emlxs_fcfi_state(emlxs_port_t *port, FCFIobj_t *fcfp, uint16_t state,
7496 uint16_t reason, uint32_t explain, void *arg1)
7497 {
7498 uint32_t rval = 0;
7499
7500 if (state >= FCFI_ACTION_STATES) {
7501 return (1);
7502 }
7503
7504 if ((fcfp->state == state) &&
7505 (reason != FCF_REASON_REENTER)) {
7506 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7507 "fcfi_state:%d %s:%s:0x%x arg=%p. "
7508 "State not changed. <",
7509 fcfp->fcf_index,
7510 emlxs_fcfi_state_xlate(state),
7511 emlxs_fcf_reason_xlate(reason),
7512 explain, arg1);
7513 return (1);
7514 }
7515
7516 if (!reason) {
7517 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
7518 "fcfi_state:%d %s-->%s arg=%p",
7519 fcfp->fcf_index,
7520 emlxs_fcfi_state_xlate(fcfp->state),
7521 emlxs_fcfi_state_xlate(state), arg1);
7522 } else if (reason == FCF_REASON_EVENT) {
7523 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
7524 "fcfi_state:%d %s-->%s:%s:%s arg=%p",
7525 fcfp->fcf_index,
7526 emlxs_fcfi_state_xlate(fcfp->state),
7527 emlxs_fcfi_state_xlate(state),
7528 emlxs_fcf_reason_xlate(reason),
7529 emlxs_fcf_event_xlate(explain), arg1);
7530 } else if (explain) {
7531 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
7532 "fcfi_state:%d %s-->%s:%s:0x%x arg=%p",
7533 fcfp->fcf_index,
7534 emlxs_fcfi_state_xlate(fcfp->state),
7535 emlxs_fcfi_state_xlate(state),
7536 emlxs_fcf_reason_xlate(reason),
7537 explain, arg1);
7538 } else {
7539 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
7540 "fcfi_state:%d %s-->%s:%s arg=%p",
7541 fcfp->fcf_index,
7542 emlxs_fcfi_state_xlate(fcfp->state),
7543 emlxs_fcfi_state_xlate(state),
7544 emlxs_fcf_reason_xlate(reason), arg1);
7545 }
7546
7547 fcfp->prev_state = fcfp->state;
7548 fcfp->prev_reason = fcfp->reason;
7549 fcfp->state = state;
7550 fcfp->reason = reason;
7551
7552 rval = emlxs_fcfi_action(port, fcfp, FCF_EVENT_STATE_ENTER, arg1);
7553
7554 return (rval);
7555
7556 } /* emlxs_fcfi_state() */
7557
7558
7559 static FCFIobj_t *
emlxs_fcfi_alloc(emlxs_port_t * port)7560 emlxs_fcfi_alloc(emlxs_port_t *port)
7561 {
7562 emlxs_hba_t *hba = HBA;
7563 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7564 uint16_t i;
7565 FCFIobj_t *fcfp;
7566
7567 fcfp = fcftab->table;
7568 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7569 if (fcfp->state == FCFI_STATE_FREE) {
7570
7571 bzero(fcfp, sizeof (FCFIobj_t));
7572 fcfp->index = i;
7573 fcfp->FCFI = 0xFFFF;
7574
7575 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7576 "fcfi_alloc:%d. Allocating FCFI. >",
7577 fcfp->index);
7578
7579 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
7580 0, 0, 0);
7581 return (fcfp);
7582 }
7583 }
7584
7585 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7586 "fcfi_alloc: Out of FCFI objects.",
7587 fcfp->index);
7588
7589 return (NULL);
7590
7591 } /* emlxs_fcfi_alloc() */
7592
7593
7594 static uint32_t
emlxs_fcfi_free(emlxs_port_t * port,FCFIobj_t * fcfp)7595 emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp)
7596 {
7597 uint32_t rval = 0;
7598
7599 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_FREE, 0, 0, 0);
7600
7601 return (rval);
7602
7603 } /* emlxs_fcfi_free() */
7604
7605
7606 static FCFIobj_t *
emlxs_fcfi_find(emlxs_port_t * port,FCF_RECORD_t * fcfrec,uint32_t * fcf_index)7607 emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec, uint32_t *fcf_index)
7608 {
7609 emlxs_hba_t *hba = HBA;
7610 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7611 uint32_t i;
7612 uint32_t index;
7613 FCFIobj_t *fcfp;
7614
7615 if (fcfrec) {
7616 /* Check for a matching FCF index, fabric name, */
7617 /* and mac address */
7618 fcfp = fcftab->table;
7619 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7620 if (fcfp->state == FCFI_STATE_FREE) {
7621 continue;
7622 }
7623
7624 if ((fcfp->fcf_index == fcfrec->fcf_index) &&
7625 (bcmp((char *)fcfrec->fabric_name_identifier,
7626 fcfp->fcf_rec.fabric_name_identifier, 8) == 0) &&
7627 (bcmp((char *)fcfrec->fcf_mac_address_hi,
7628 fcfp->fcf_rec.fcf_mac_address_hi, 4) == 0) &&
7629 (bcmp((char *)fcfrec->fcf_mac_address_low,
7630 fcfp->fcf_rec.fcf_mac_address_low, 2) == 0)) {
7631 return (fcfp);
7632 }
7633 }
7634
7635 } else if (fcf_index) {
7636 /* Check for a matching FCF index only */
7637 index = *fcf_index;
7638 fcfp = fcftab->table;
7639 for (i = 0; i < fcftab->table_count; i++, fcfp++) {
7640 if (fcfp->state == FCFI_STATE_FREE) {
7641 continue;
7642 }
7643
7644 if (fcfp->fcf_index == index) {
7645 return (fcfp);
7646 }
7647 }
7648 }
7649
7650 return (NULL);
7651
7652 } /* emlxs_fcfi_find() */
7653
7654
7655 /*ARGSUSED*/
7656 static uint32_t
emlxs_fcfi_free_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7657 emlxs_fcfi_free_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
7658 void *arg1)
7659 {
7660
7661 if (fcfp->state != FCFI_STATE_FREE) {
7662 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7663 "fcfi_free_action:%d %s:%s arg=%p. "
7664 "Invalid state. <",
7665 fcfp->fcf_index,
7666 emlxs_fcfi_state_xlate(fcfp->state),
7667 emlxs_fcf_event_xlate(evt), arg1);
7668 return (1);
7669 }
7670
7671 if (fcfp->vfi_online) {
7672 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7673 "fcfi_free_action:%d flag=%x vfi_online=%d",
7674 fcfp->fcf_index,
7675 fcfp->flag,
7676 fcfp->vfi_online);
7677 }
7678
7679 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7680 "fcfi_free_action:%d flag=%x. FCF freed. <",
7681 fcfp->fcf_index,
7682 fcfp->flag);
7683
7684 fcfp->flag = 0;
7685
7686 return (0);
7687
7688 } /* emlxs_fcfi_free_action() */
7689
7690
7691 /*ARGSUSED*/
7692 static uint32_t
emlxs_fcfi_offline_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7693 emlxs_fcfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
7694 void *arg1)
7695 {
7696 emlxs_hba_t *hba = HBA;
7697 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
7698 uint32_t rval = 0;
7699
7700 if (fcfp->state != FCFI_STATE_OFFLINE) {
7701 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7702 "fcfi_offline_action:%d %s:%s arg=%p. "
7703 "Invalid state. <",
7704 fcfp->fcf_index,
7705 emlxs_fcfi_state_xlate(fcfp->state),
7706 emlxs_fcf_event_xlate(evt), arg1);
7707 return (1);
7708 }
7709
7710 fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
7711
7712 if (fcfp->prev_state == FCFI_STATE_FREE) {
7713 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7714 "fcfi_offline_action:%d fcfi_online=%d. <",
7715 fcfp->fcf_index,
7716 fcftab->fcfi_online);
7717
7718 return (0);
7719 }
7720
7721 if (fcfp->vfi_online) {
7722 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7723 "fcfi_offline_action:%d vfi_online=%d.",
7724 fcfp->fcf_index,
7725 fcfp->vfi_online);
7726 }
7727
7728 if (fcfp->flag & EMLXS_FCFI_FCFTAB) {
7729 fcfp->flag &= ~EMLXS_FCFI_FCFTAB;
7730
7731 if (fcftab->fcfi_online) {
7732 fcftab->fcfi_online--;
7733 }
7734 }
7735
7736 /* Check if online was requested */
7737 if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) {
7738
7739 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7740 "fcfi_offline_action:%d fcfi_online=%d. "
7741 "Online requested.",
7742 fcfp->fcf_index,
7743 fcftab->fcfi_online);
7744
7745 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
7746 FCF_REASON_REQUESTED, 0, arg1);
7747 return (rval);
7748 }
7749
7750 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7751 "fcfi_offline_action:%d fcfi_online=%d. "
7752 "FCFI offline. Notifying fcftab. >",
7753 fcfp->fcf_index,
7754 fcftab->fcfi_online);
7755
7756 /* Notify FCFTAB */
7757 rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp);
7758
7759 return (rval);
7760
7761 } /* emlxs_fcfi_offline_action() */
7762
7763
7764 /*ARGSUSED*/
7765 static uint32_t
emlxs_fcfi_vfi_online_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7766 emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
7767 uint32_t evt, void *arg1)
7768 {
7769 uint32_t rval = 0;
7770
7771 if (evt != FCF_EVENT_VFI_ONLINE) {
7772 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7773 "fcfi_vfi_online_evt_action:%d %s:%s arg=%p flag=%x. "
7774 "Invalid event type. <",
7775 fcfp->fcf_index,
7776 emlxs_fcfi_state_xlate(fcfp->state),
7777 emlxs_fcf_event_xlate(evt), arg1,
7778 fcfp->flag);
7779 return (1);
7780 }
7781
7782 switch (fcfp->state) {
7783 case FCFI_STATE_ONLINE:
7784 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7785 "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. "
7786 "Reentering online.",
7787 fcfp->fcf_index,
7788 fcfp->flag,
7789 fcfp->vfi_online);
7790
7791 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
7792 FCF_REASON_REENTER, evt, arg1);
7793 break;
7794
7795 case FCFI_STATE_VFI_ONLINE:
7796 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7797 "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. "
7798 "Online cmpl.",
7799 fcfp->fcf_index,
7800 fcfp->flag,
7801 fcfp->vfi_online);
7802
7803 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE_CMPL,
7804 FCF_REASON_EVENT, evt, arg1);
7805 break;
7806
7807 default:
7808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7809 "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. <",
7810 fcfp->fcf_index,
7811 fcfp->flag,
7812 fcfp->vfi_online);
7813 return (0);
7814 }
7815
7816 return (rval);
7817
7818 } /* emlxs_fcfi_vfi_online_evt_action() */
7819
7820
7821 /*ARGSUSED*/
7822 static uint32_t
emlxs_fcfi_offline_handler(emlxs_port_t * port,FCFIobj_t * fcfp,void * arg1)7823 emlxs_fcfi_offline_handler(emlxs_port_t *port, FCFIobj_t *fcfp, void *arg1)
7824 {
7825 uint32_t rval = 0;
7826
7827 if (!(fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
7828 return (0);
7829 }
7830
7831 if (fcfp->vfi_online) {
7832 if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) {
7833 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED,
7834 FCF_REASON_REQUESTED, 0, arg1);
7835 } else {
7836 rval = emlxs_fcfi_state(port, fcfp,
7837 FCFI_STATE_VFI_OFFLINE, FCF_REASON_REQUESTED,
7838 0, arg1);
7839 }
7840
7841 } else if (fcfp->flag & EMLXS_FCFI_REG) {
7842 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
7843 FCF_REASON_REQUESTED, 0, arg1);
7844
7845 } else {
7846 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
7847 FCF_REASON_REQUESTED, 0, arg1);
7848 }
7849
7850 return (rval);
7851
7852 } /* emlxs_fcfi_offline_handler() */
7853
7854
7855 /*ARGSUSED*/
7856 static uint32_t
emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7857 emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
7858 uint32_t evt, void *arg1)
7859 {
7860 uint32_t rval = 0;
7861 VFIobj_t *vfip;
7862
7863 if (evt != FCF_EVENT_VFI_OFFLINE) {
7864 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7865 "fcfi_vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
7866 "Invalid event type. <",
7867 fcfp->fcf_index,
7868 emlxs_fcfi_state_xlate(fcfp->state),
7869 emlxs_fcf_event_xlate(evt), arg1,
7870 fcfp->flag);
7871 return (1);
7872 }
7873
7874 vfip = (VFIobj_t *)arg1;
7875 vfip->fcfp = NULL;
7876
7877 switch (fcfp->state) {
7878 case FCFI_STATE_VFI_ONLINE:
7879 case FCFI_STATE_ONLINE:
7880 if (fcfp->vfi_online == 0) {
7881 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7882 "fcfi_vfi_offline_evt_action:%d flag=%x "
7883 "vfi_online=%d. Offlining.",
7884 fcfp->fcf_index,
7885 fcfp->flag, fcfp->vfi_online);
7886
7887 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
7888 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
7889
7890 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
7891 } else {
7892 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7893 "fcfi_vfi_offline_evt_action:%d flag=%x "
7894 "vfi_online=%d. <",
7895 fcfp->fcf_index,
7896 fcfp->flag, fcfp->vfi_online);
7897 }
7898 break;
7899
7900 case FCFI_STATE_PAUSED:
7901 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7902 "fcfi_vfi_offline_evt_action:%d flag=%x vfi_online=%d. <",
7903 fcfp->fcf_index,
7904 fcfp->flag, fcfp->vfi_online);
7905 break;
7906
7907 case FCFI_STATE_VFI_OFFLINE:
7908 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7909 "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.",
7910 fcfp->fcf_index,
7911 fcfp->flag);
7912
7913 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL,
7914 FCF_REASON_EVENT, evt, arg1);
7915 break;
7916
7917 case FCFI_STATE_VFI_OFFLINE_CMPL:
7918 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7919 "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.",
7920 fcfp->fcf_index,
7921 fcfp->flag);
7922
7923 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL,
7924 FCF_REASON_REENTER, evt, arg1);
7925 break;
7926
7927 default:
7928 if (fcfp->vfi_online == 0) {
7929 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7930 "fcfi_vfi_offline_evt_action:%d flag=%x "
7931 "vfi_online=%d. Offline requested. <",
7932 fcfp->fcf_index,
7933 fcfp->flag, fcfp->vfi_online);
7934
7935 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
7936 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
7937 } else {
7938 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7939 "fcfi_vfi_offline_evt_action:%d flag = %x "
7940 "vfi_online=%d. <",
7941 fcfp->fcf_index,
7942 fcfp->flag, fcfp->vfi_online);
7943 }
7944 return (0);
7945 }
7946
7947 return (rval);
7948
7949 } /* emlxs_fcfi_vfi_offline_evt_action() */
7950
7951
7952 /*ARGSUSED*/
7953 static uint32_t
emlxs_fcfi_online_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)7954 emlxs_fcfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp,
7955 uint32_t evt, void *arg1)
7956 {
7957 uint32_t rval = 0;
7958
7959 if (evt != FCF_EVENT_FCFI_ONLINE) {
7960 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
7961 "fcfi_online_evt_action:%d %s:%s arg=%p. "
7962 "Invalid event type. <",
7963 fcfp->fcf_index,
7964 emlxs_fcfi_state_xlate(fcfp->state),
7965 emlxs_fcf_event_xlate(evt), arg1);
7966 return (1);
7967 }
7968
7969 if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) {
7970 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7971 "fcfi_online_evt_action:%d. "
7972 "Online already requested. <",
7973 fcfp->fcf_index);
7974 return (1);
7975 }
7976
7977 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
7978 fcfp->flag |= EMLXS_FCFI_ONLINE_REQ;
7979
7980 switch (fcfp->state) {
7981 case FCFI_STATE_OFFLINE:
7982 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7983 "fcfi_online_evt_action:%d flag=%x. Initiating online.",
7984 fcfp->fcf_index,
7985 fcfp->flag);
7986
7987 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
7988 FCF_REASON_EVENT, evt, arg1);
7989 break;
7990
7991 case FCFI_STATE_VFI_OFFLINE:
7992 case FCFI_STATE_PAUSED:
7993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
7994 "fcfi_online_evt_action:%d flag=%x. Initiating online.",
7995 fcfp->fcf_index,
7996 fcfp->flag);
7997
7998 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
7999 FCF_REASON_EVENT, evt, arg1);
8000 break;
8001
8002 case FCFI_STATE_ONLINE:
8003 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8004 "fcfi_online_evt_action:%d flag=%x. Reentering online.",
8005 fcfp->fcf_index,
8006 fcfp->flag);
8007
8008 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
8009 FCF_REASON_REENTER, evt, arg1);
8010 break;
8011
8012 default:
8013 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8014 "fcfi_online_evt_action:%d flag=%x. <",
8015 fcfp->fcf_index,
8016 fcfp->flag);
8017 break;
8018 }
8019
8020 return (rval);
8021
8022 } /* emlxs_fcfi_online_evt_action() */
8023
8024
8025 /*ARGSUSED*/
8026 static uint32_t
emlxs_fcfi_vfi_online_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8027 emlxs_fcfi_vfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8028 uint32_t evt, void *arg1)
8029 {
8030 emlxs_hba_t *hba = HBA;
8031 uint32_t i;
8032 uint32_t rval = 0;
8033 VFIobj_t *vfip;
8034
8035 if (fcfp->state != FCFI_STATE_VFI_ONLINE) {
8036 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8037 "fcfi_vfi_online_action:%d %s:%s arg=%p. "
8038 "Invalid state. <",
8039 fcfp->fcf_index,
8040 emlxs_fcfi_state_xlate(fcfp->state),
8041 emlxs_fcf_event_xlate(evt), arg1);
8042 return (1);
8043 }
8044
8045 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8046 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8047 "fcfi_vfi_online_action:%d. Offline requested.",
8048 fcfp->fcf_index);
8049
8050 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8051 return (rval);
8052 }
8053
8054 if (fcfp->vfi_online > 0) {
8055 /* Waking up out after being paused */
8056
8057 /* Find first VFI of this FCFI */
8058 vfip = hba->sli.sli4.VFI_table;
8059 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
8060 if (vfip->fcfp == fcfp) {
8061 break;
8062 }
8063 }
8064
8065 } else {
8066
8067 /* Find first available VFI */
8068 vfip = hba->sli.sli4.VFI_table;
8069 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
8070 if (vfip->fcfp == NULL) {
8071 vfip->fcfp = fcfp;
8072 break;
8073 }
8074 }
8075 }
8076
8077 if (i == hba->sli.sli4.VFICount) {
8078 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8079 "fcfi_vfi_online_action:%d vfi_online=%d. "
8080 "No VFI found. Offlining.",
8081 fcfp->fcf_index,
8082 fcfp->vfi_online);
8083
8084 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8085 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8086
8087 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8088 return (rval);
8089 }
8090
8091 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8092 "fcfi_vfi_online_action:%d vfi_online=%d. Onlining VFI:%d. >",
8093 fcfp->fcf_index,
8094 fcfp->vfi_online,
8095 vfip->VFI);
8096
8097 rval = emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
8098
8099 /* Wait for FCF_EVENT_VFI_ONLINE in return */
8100
8101 return (rval);
8102
8103 } /* emlxs_fcfi_vfi_online_action() */
8104
8105
8106 /*ARGSUSED*/
8107 static uint32_t
emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8108 emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8109 uint32_t evt, void *arg1)
8110 {
8111 uint32_t rval = 0;
8112
8113 if (fcfp->state != FCFI_STATE_VFI_ONLINE_CMPL) {
8114 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8115 "fcfi_vfi_online_cmpl_action:%d %s:%s arg=%p. "
8116 "Invalid state. <",
8117 fcfp->fcf_index,
8118 emlxs_fcfi_state_xlate(fcfp->state),
8119 emlxs_fcf_event_xlate(evt), arg1);
8120 return (1);
8121 }
8122
8123 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8124 "fcfi_vfi_online_cmpl_action:%d. Going online.",
8125 fcfp->fcf_index);
8126
8127 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE,
8128 FCF_REASON_EVENT, evt, arg1);
8129
8130 return (rval);
8131
8132 } /* emlxs_fcfi_vfi_online_cmpl_action() */
8133
8134
8135 /*ARGSUSED*/
8136 static uint32_t
emlxs_fcfi_vfi_offline_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8137 emlxs_fcfi_vfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8138 void *arg1)
8139 {
8140 emlxs_hba_t *hba = HBA;
8141 VFIobj_t *vfip;
8142 uint32_t rval = 0;
8143 int32_t i;
8144
8145 if (fcfp->state != FCFI_STATE_VFI_OFFLINE) {
8146 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8147 "fcfi_vfi_offline_action:%d %s:%s arg=%p. "
8148 "Invalid state. <",
8149 fcfp->fcf_index,
8150 emlxs_fcfi_state_xlate(fcfp->state),
8151 emlxs_fcf_event_xlate(evt), arg1);
8152
8153 return (1);
8154 }
8155
8156 if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) {
8157 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8158 "fcfi_vfi_offline_action:%d vfi_online=%d. Pausing.",
8159 fcfp->fcf_index,
8160 fcfp->vfi_online);
8161
8162 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED,
8163 FCF_REASON_EVENT, evt, arg1);
8164
8165 return (rval);
8166 }
8167
8168 if (fcfp->vfi_online == 0) {
8169 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8170 "fcfi_vfi_offline_action:%d. "
8171 "VFI already offline. Skipping VFI offline.",
8172 fcfp->fcf_index);
8173
8174 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
8175 FCF_REASON_EVENT, evt, arg1);
8176
8177 return (rval);
8178 }
8179
8180 /* Offline VFI's of this FCFI */
8181 for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) {
8182 vfip = &hba->sli.sli4.VFI_table[i];
8183
8184 if ((vfip->fcfp != fcfp) ||
8185 (vfip->state == VFI_STATE_OFFLINE) ||
8186 (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
8187 continue;
8188 }
8189
8190 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8191 "fcfi_vfi_offline_action:%d. Offlining VFI:%d >",
8192 fcfp->fcf_index,
8193 vfip->VFI);
8194
8195 (void) emlxs_vfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip);
8196 }
8197
8198 /* Wait for FCF_EVENT_VFI_OFFLINE in return */
8199
8200 return (0);
8201
8202 } /* emlxs_fcfi_vfi_offline_action() */
8203
8204
8205 /*ARGSUSED*/
8206 static uint32_t
emlxs_fcfi_paused_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8207 emlxs_fcfi_paused_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8208 void *arg1)
8209 {
8210 emlxs_hba_t *hba = HBA;
8211 VFIobj_t *vfip;
8212 int32_t i;
8213
8214 if (fcfp->state != FCFI_STATE_PAUSED) {
8215 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8216 "fcfi_paused_action:%d %s:%s arg=%p. "
8217 "Invalid state. <",
8218 fcfp->fcf_index,
8219 emlxs_fcfi_state_xlate(fcfp->state),
8220 emlxs_fcf_event_xlate(evt), arg1);
8221
8222 return (1);
8223 }
8224
8225 fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
8226
8227 /* Pause all VFI's of this FCFI */
8228 for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) {
8229 vfip = &hba->sli.sli4.VFI_table[i];
8230
8231 if ((vfip->state == VFI_STATE_OFFLINE) ||
8232 (vfip->state == VFI_STATE_PAUSED) ||
8233 (vfip->fcfp != fcfp)) {
8234 continue;
8235 }
8236
8237 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8238 "fcfi_paused_action:%d vfi_online=%d. Pausing VFI:%d. >",
8239 fcfp->fcf_index,
8240 fcfp->vfi_online,
8241 vfip->VFI);
8242
8243 (void) emlxs_vfi_event(port, FCF_EVENT_VFI_PAUSE, vfip);
8244 }
8245
8246 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8247 "fcfi_paused_action:%d vfi_online=%d. FCFI paused. <",
8248 fcfp->fcf_index,
8249 fcfp->vfi_online);
8250
8251 return (0);
8252
8253 } /* emlxs_fcfi_paused_action() */
8254
8255
8256 /*ARGSUSED*/
8257 static uint32_t
emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8258 emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8259 uint32_t evt, void *arg1)
8260 {
8261 uint32_t rval = 0;
8262
8263 if (fcfp->state != FCFI_STATE_VFI_OFFLINE_CMPL) {
8264 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8265 "fcfi_vfi_offline_cmpl_action:%d %s:%s arg=%p. "
8266 "Invalid state. <",
8267 fcfp->fcf_index,
8268 emlxs_fcfi_state_xlate(fcfp->state),
8269 emlxs_fcf_event_xlate(evt), arg1);
8270 return (1);
8271 }
8272
8273 if ((fcfp->vfi_online == 0) &&
8274 (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) {
8275 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8276 "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. "
8277 "Unregistering.",
8278 fcfp->fcf_index,
8279 fcfp->vfi_online);
8280
8281 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
8282 FCF_REASON_EVENT, evt, arg1);
8283 } else {
8284 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8285 "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. <",
8286 fcfp->fcf_index,
8287 fcfp->vfi_online);
8288 }
8289
8290 return (rval);
8291
8292 } /* emlxs_fcfi_vfi_offline_cmpl_action() */
8293
8294
8295 /*ARGSUSED*/
8296 static uint32_t
emlxs_fcfi_offline_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8297 emlxs_fcfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8298 void *arg1)
8299 {
8300 uint32_t rval = 0;
8301
8302 if (evt != FCF_EVENT_FCFI_OFFLINE) {
8303 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8304 "fcfi_offline_evt_action:%d %s:%s arg=%p. "
8305 "Invalid event type. <",
8306 fcfp->fcf_index,
8307 emlxs_fcfi_state_xlate(fcfp->state),
8308 emlxs_fcf_event_xlate(evt), arg1);
8309 return (1);
8310 }
8311
8312 if ((fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) &&
8313 !(fcfp->flag & EMLXS_FCFI_PAUSE_REQ)) {
8314 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8315 "fcfi_offline_evt_action:%d. Offline already requested. <",
8316 fcfp->fcf_index);
8317 return (1);
8318 }
8319
8320 switch (fcfp->state) {
8321 case FCFI_STATE_OFFLINE:
8322 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8323 "fcfi_offline_evt_action:%d flag=%x. Already offline. <",
8324 fcfp->fcf_index,
8325 fcfp->flag);
8326 break;
8327
8328 /* Wait states */
8329 case FCFI_STATE_VFI_ONLINE:
8330 case FCFI_STATE_VFI_OFFLINE:
8331 case FCFI_STATE_REG:
8332 case FCFI_STATE_ONLINE:
8333 case FCFI_STATE_PAUSED:
8334 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8335 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8336
8337 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8338 "fcfi_offline_evt_action:%d flag=%x. Handling offline.",
8339 fcfp->fcf_index,
8340 fcfp->flag);
8341
8342 /* Handle offline now */
8343 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8344 break;
8345
8346 /* Transitional states */
8347 default:
8348 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8349 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8350
8351 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8352 "fcfi_offline_evt_action:%d. "
8353 "Invalid state. <",
8354 fcfp->fcf_index);
8355 break;
8356 }
8357
8358 return (rval);
8359
8360 } /* emlxs_fcfi_offline_evt_action() */
8361
8362
8363 /*ARGSUSED*/
8364 static uint32_t
emlxs_fcfi_pause_evt_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8365 emlxs_fcfi_pause_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8366 void *arg1)
8367 {
8368 uint32_t rval = 0;
8369
8370 if (evt != FCF_EVENT_FCFI_PAUSE) {
8371 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8372 "fcfi_pause_evt_action:%d %s:%s arg=%p. "
8373 "Invalid event type. <",
8374 fcfp->fcf_index,
8375 emlxs_fcfi_state_xlate(fcfp->state),
8376 emlxs_fcf_event_xlate(evt), arg1);
8377 return (1);
8378 }
8379
8380 if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) {
8381 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8382 "fcfi_pause_evt_action:%d. Pause already requested. <",
8383 fcfp->fcf_index);
8384 return (1);
8385 }
8386
8387 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8388 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8389 "fcfi_pause_evt_action:%d. Offline already requested. <",
8390 fcfp->fcf_index);
8391 return (1);
8392 }
8393
8394 switch (fcfp->state) {
8395 case FCFI_STATE_OFFLINE:
8396 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8397 "fcfi_pause_evt_action:%d flag=%x. Already offline. <",
8398 fcfp->fcf_index,
8399 fcfp->flag);
8400 break;
8401
8402 case FCFI_STATE_PAUSED:
8403 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8404 "fcfi_pause_evt_action:%d flag=%x. Already paused. <",
8405 fcfp->fcf_index,
8406 fcfp->flag);
8407 break;
8408
8409 /* Wait states */
8410 case FCFI_STATE_VFI_ONLINE:
8411 case FCFI_STATE_VFI_OFFLINE:
8412 case FCFI_STATE_REG:
8413 case FCFI_STATE_ONLINE:
8414 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8415 fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
8416
8417 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8418 "fcfi_pause_evt_action:%d flag=%x. Handle pause request.",
8419 fcfp->fcf_index,
8420 fcfp->flag);
8421
8422 /* Handle offline now */
8423 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8424 break;
8425
8426 /* Transitional states */
8427 default:
8428 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8429 fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ);
8430
8431 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8432 "fcfi_pause_evt_action:%d. "
8433 "Invalid state. <",
8434 fcfp->fcf_index);
8435 break;
8436 }
8437
8438 return (rval);
8439
8440 } /* emlxs_fcfi_pause_evt_action() */
8441
8442
8443 /*ARGSUSED*/
8444 static uint32_t
emlxs_fcfi_unreg_failed_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8445 emlxs_fcfi_unreg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp,
8446 uint32_t evt, void *arg1)
8447 {
8448 uint32_t rval = 0;
8449
8450 fcfp->attempts++;
8451
8452 if (fcfp->state != FCFI_STATE_UNREG_FAILED) {
8453 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8454 "fcfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
8455 "Invalid state. <",
8456 fcfp->fcf_index,
8457 emlxs_fcfi_state_xlate(fcfp->state),
8458 emlxs_fcf_event_xlate(evt),
8459 arg1, fcfp->attempts);
8460 return (1);
8461 }
8462
8463 if ((fcfp->reason == FCF_REASON_SEND_FAILED) ||
8464 (fcfp->attempts >= 3)) {
8465 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8466 "fcfi_unreg_failed_action:%d attempt=%d reason=%x. "
8467 "Unreg cmpl.",
8468 fcfp->fcf_index,
8469 fcfp->attempts,
8470 fcfp->reason);
8471
8472 fcfp->flag &= ~EMLXS_FCFI_REG;
8473
8474 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL,
8475 FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8476 } else {
8477 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8478 "fcfi_unreg_failed_action:%d attempt=%d. Unregistering.",
8479 fcfp->fcf_index,
8480 arg1, fcfp->attempts);
8481
8482 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG,
8483 FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8484 }
8485
8486 return (rval);
8487
8488 } /* emlxs_fcfi_unreg_failed_action() */
8489
8490
8491 /*ARGSUSED*/
8492 static uint32_t
emlxs_fcfi_reg_failed_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8493 emlxs_fcfi_reg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8494 void *arg1)
8495 {
8496 uint32_t rval = 0;
8497
8498 fcfp->attempts++;
8499
8500 if (fcfp->state != FCFI_STATE_REG_FAILED) {
8501 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8502 "fcfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
8503 "Invalid state. <",
8504 fcfp->fcf_index,
8505 emlxs_fcfi_state_xlate(fcfp->state),
8506 emlxs_fcf_event_xlate(evt), arg1,
8507 fcfp->attempts);
8508 return (1);
8509 }
8510
8511 if ((fcfp->reason == FCF_REASON_SEND_FAILED) ||
8512 (fcfp->attempts >= 3)) {
8513 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8514 "fcfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.",
8515 fcfp->fcf_index,
8516 fcfp->attempts,
8517 fcfp->reason);
8518
8519 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK;
8520 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ;
8521
8522 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL,
8523 FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8524 } else {
8525 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8526 "fcfi_reg_failed_action:%d attempt=%d. Registering.",
8527 fcfp->fcf_index,
8528 fcfp->attempts);
8529
8530 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG,
8531 FCF_REASON_OP_FAILED, fcfp->attempts, arg1);
8532 }
8533
8534 return (rval);
8535
8536 } /* emlxs_fcfi_reg_failed_action() */
8537
8538
8539 /*ARGSUSED*/
8540 static uint32_t
emlxs_fcfi_reg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)8541 emlxs_fcfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
8542 {
8543 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
8544 MAILBOX4 *mb4;
8545 FCFIobj_t *fcfp;
8546
8547 fcfp = (FCFIobj_t *)mbq->context;
8548 mb4 = (MAILBOX4 *)mbq;
8549
8550 mutex_enter(&EMLXS_FCF_LOCK);
8551
8552 if (fcfp->state != FCFI_STATE_REG) {
8553 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8554 "fcfi_reg_mbcmpl:%d state=%s.",
8555 fcfp->fcf_index,
8556 emlxs_fcfi_state_xlate(fcfp->state));
8557
8558 mutex_exit(&EMLXS_FCF_LOCK);
8559 return (0);
8560 }
8561
8562 if (mb4->mbxStatus) {
8563 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8564 "fcfi_reg_mbcmpl:%d failed. %s. >",
8565 fcfp->fcf_index,
8566 emlxs_mb_xlate_status(mb4->mbxStatus));
8567
8568 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
8569 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
8570
8571 mutex_exit(&EMLXS_FCF_LOCK);
8572 return (0);
8573 }
8574
8575 fcfp->FCFI = mb4->un.varRegFCFI.FCFI;
8576
8577 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8578 "fcfi_reg_mbcmpl:%d FCFI=%d. Reg complete. >",
8579 fcfp->fcf_index,
8580 fcfp->FCFI);
8581
8582 fcfp->flag |= EMLXS_FCFI_REG;
8583
8584 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL,
8585 0, 0, 0);
8586 mutex_exit(&EMLXS_FCF_LOCK);
8587 return (0);
8588
8589 } /* emlxs_fcfi_reg_mbcmpl() */
8590
8591
8592 /*ARGSUSED*/
8593 static uint32_t
emlxs_fcfi_reg_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8594 emlxs_fcfi_reg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8595 void *arg1)
8596 {
8597 emlxs_hba_t *hba = HBA;
8598 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
8599 MAILBOX4 *mb4;
8600 MAILBOXQ *mbq;
8601 uint32_t rval = 0;
8602
8603 if (fcfp->state != FCFI_STATE_REG) {
8604 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8605 "fcfi_reg_action:%d %s:%s arg=%p. "
8606 "Invalid state. <",
8607 fcfp->fcf_index,
8608 emlxs_fcfi_state_xlate(fcfp->state),
8609 emlxs_fcf_event_xlate(evt), arg1);
8610 return (1);
8611 }
8612
8613 if (!(fcfp->flag & EMLXS_FCFI_FCFTAB)) {
8614 fcfp->flag |= EMLXS_FCFI_FCFTAB;
8615 fcftab->fcfi_online++;
8616 }
8617
8618 if (fcfp->prev_state != FCFI_STATE_REG_FAILED) {
8619 fcfp->attempts = 0;
8620 }
8621
8622 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8623 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8624 "fcfi_reg_action:%d attempts=%d. Offline requested.",
8625 fcfp->fcf_index,
8626 fcfp->attempts);
8627
8628 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8629 return (rval);
8630 }
8631
8632 if (fcfp->flag & EMLXS_FCFI_REG) {
8633 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8634 "fcfi_reg_action:%d. Already registered. "
8635 "Skipping REG_FCFI update.",
8636 fcfp->fcf_index);
8637
8638 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
8639 FCF_REASON_EVENT, evt, arg1);
8640 return (rval);
8641 }
8642
8643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8644 "fcfi_reg_action:%d attempts=%d. Sending REG_FCFI. <",
8645 fcfp->fcf_index,
8646 fcfp->attempts);
8647
8648 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
8649 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
8650 FCF_REASON_NO_MBOX, 0, arg1);
8651
8652 return (rval);
8653 }
8654 mb4 = (MAILBOX4*)mbq;
8655 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
8656
8657 mbq->mbox_cmpl = emlxs_fcfi_reg_mbcmpl;
8658 mbq->context = (void *)fcfp;
8659 mbq->port = (void *)port;
8660
8661 mb4->mbxCommand = MBX_REG_FCFI;
8662 mb4->mbxOwner = OWN_HOST;
8663 mb4->un.varRegFCFI.FCFI = 0; /* FCFI will be returned by firmware */
8664 mb4->un.varRegFCFI.InfoIndex = fcfp->fcf_index;
8665
8666 mb4->un.varRegFCFI.RQId0 = hba->sli.sli4.rq[EMLXS_FCFI_RQ0_INDEX].qid;
8667 mb4->un.varRegFCFI.Id0_rctl_mask = EMLXS_FCFI_RQ0_RMASK;
8668 mb4->un.varRegFCFI.Id0_rctl = EMLXS_FCFI_RQ0_RCTL;
8669 mb4->un.varRegFCFI.Id0_type_mask = EMLXS_FCFI_RQ0_TMASK;
8670 mb4->un.varRegFCFI.Id0_type = EMLXS_FCFI_RQ0_TYPE;
8671
8672 mb4->un.varRegFCFI.RQId1 = 0xffff;
8673 mb4->un.varRegFCFI.RQId2 = 0xffff;
8674 mb4->un.varRegFCFI.RQId3 = 0xffff;
8675
8676 if (fcfp->flag & EMLXS_FCFI_VLAN_ID) {
8677 mb4->un.varRegFCFI.vv = 1;
8678 mb4->un.varRegFCFI.vlanTag = fcfp->vlan_id;
8679 }
8680
8681 /* Ignore the fcf record and force FPMA */
8682 mb4->un.varRegFCFI.mam = EMLXS_REG_FCFI_MAM_FPMA;
8683
8684 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
8685 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
8686 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
8687
8688 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED,
8689 FCF_REASON_SEND_FAILED, rval, arg1);
8690
8691 return (rval);
8692 }
8693
8694 return (0);
8695
8696 } /* emlxs_fcfi_reg_action() */
8697
8698
8699 /*ARGSUSED*/
8700 static uint32_t
emlxs_fcfi_reg_cmpl_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8701 emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8702 void *arg1)
8703 {
8704 uint32_t rval = 0;
8705
8706 if (fcfp->state != FCFI_STATE_REG_CMPL) {
8707 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8708 "fcfi_reg_cmpl_action:%d %s:%s arg=%p. "
8709 "Invalid state. <",
8710 fcfp->fcf_index,
8711 emlxs_fcfi_state_xlate(fcfp->state),
8712 emlxs_fcf_event_xlate(evt), arg1);
8713 return (1);
8714 }
8715
8716 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8717 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8718 "fcfi_reg_cmpl_action:%d. Offline requested.",
8719 fcfp->fcf_index);
8720
8721 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8722 return (rval);
8723 }
8724
8725 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8726 "fcfi_reg_cmpl_action:%d attempts=%d. Reg cmpl.",
8727 fcfp->fcf_index,
8728 fcfp->attempts);
8729
8730 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE,
8731 FCF_REASON_EVENT, evt, arg1);
8732
8733 return (rval);
8734
8735 } /* emlxs_fcfi_reg_cmpl_action() */
8736
8737
8738 /*ARGSUSED*/
8739 static uint32_t
emlxs_fcfi_unreg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)8740 emlxs_fcfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
8741 {
8742 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
8743 MAILBOX4 *mb4;
8744 FCFIobj_t *fcfp;
8745
8746 fcfp = (FCFIobj_t *)mbq->context;
8747 mb4 = (MAILBOX4 *)mbq;
8748
8749 mutex_enter(&EMLXS_FCF_LOCK);
8750
8751 if (fcfp->state != FCFI_STATE_UNREG) {
8752 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8753 "fcfi_unreg_mbcmpl:%d state=%s.",
8754 fcfp->fcf_index,
8755 emlxs_fcfi_state_xlate(fcfp->state));
8756
8757 mutex_exit(&EMLXS_FCF_LOCK);
8758 return (0);
8759 }
8760
8761 if (mb4->mbxStatus) {
8762 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8763 "fcfi_unreg_mbcmpl:%d failed. %s. >",
8764 fcfp->fcf_index,
8765 emlxs_mb_xlate_status(mb4->mbxStatus));
8766
8767 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
8768 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
8769
8770 mutex_exit(&EMLXS_FCF_LOCK);
8771 return (0);
8772 }
8773
8774 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8775 "fcfi_unreg_mbcmpl:%d. Unreg complete. >",
8776 fcfp->fcf_index);
8777
8778 fcfp->flag &= ~EMLXS_FCFI_REG;
8779 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL,
8780 0, 0, 0);
8781
8782 mutex_exit(&EMLXS_FCF_LOCK);
8783 return (0);
8784
8785 } /* emlxs_fcfi_unreg_mbcmpl() */
8786
8787
8788 /*ARGSUSED*/
8789 static uint32_t
emlxs_fcfi_unreg_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8790 emlxs_fcfi_unreg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8791 void *arg1)
8792 {
8793 emlxs_hba_t *hba = HBA;
8794 MAILBOX4 *mb4;
8795 MAILBOXQ *mbq;
8796 uint32_t rval = 0;
8797
8798 if (fcfp->state != FCFI_STATE_UNREG) {
8799 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8800 "fcfi_unreg_action:%d %s:%s arg=%p. "
8801 "Invalid state. <",
8802 fcfp->fcf_index,
8803 emlxs_fcfi_state_xlate(fcfp->state),
8804 emlxs_fcf_event_xlate(evt), arg1);
8805 return (1);
8806 }
8807
8808 if (!(fcfp->flag & EMLXS_FCFI_REG)) {
8809 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8810 "fcfi_unreg_action:%d. Not registered. "
8811 "Skipping UNREG_FCFI.",
8812 fcfp->fcf_index);
8813
8814 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
8815 FCF_REASON_EVENT, evt, arg1);
8816 return (rval);
8817 }
8818
8819 if (fcfp->prev_state != FCFI_STATE_UNREG_FAILED) {
8820 fcfp->attempts = 0;
8821 }
8822
8823 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8824 "fcfi_unreg_action:%d attempts=%d. Sending UNREG_FCFI. <",
8825 fcfp->fcf_index,
8826 fcfp->attempts);
8827
8828 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
8829 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
8830 FCF_REASON_NO_MBOX, 0, arg1);
8831 return (rval);
8832 }
8833 mb4 = (MAILBOX4*)mbq;
8834 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
8835
8836 mbq->mbox_cmpl = emlxs_fcfi_unreg_mbcmpl;
8837 mbq->context = (void *)fcfp;
8838 mbq->port = (void *)port;
8839
8840 mb4->mbxCommand = MBX_UNREG_FCFI;
8841 mb4->mbxOwner = OWN_HOST;
8842 mb4->un.varUnRegFCFI.FCFI = fcfp->FCFI;
8843
8844 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
8845 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
8846 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
8847
8848 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED,
8849 FCF_REASON_SEND_FAILED, rval, arg1);
8850
8851 return (rval);
8852 }
8853
8854 return (0);
8855
8856 } /* emlxs_fcfi_unreg_action() */
8857
8858
8859 /*ARGSUSED*/
8860 static uint32_t
emlxs_fcfi_unreg_cmpl_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8861 emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8862 void *arg1)
8863 {
8864 uint32_t rval = 0;
8865
8866 if (fcfp->state != FCFI_STATE_UNREG_CMPL) {
8867 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8868 "fcfi_unreg_cmpl_action:%d %s:%s arg=%p. "
8869 "Invalid state. <",
8870 fcfp->fcf_index,
8871 emlxs_fcfi_state_xlate(fcfp->state),
8872 emlxs_fcf_event_xlate(evt), arg1);
8873 return (1);
8874 }
8875
8876 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8877 "fcfi_unreg_cmpl_action:%d attempts=%d. Going offline.",
8878 fcfp->fcf_index,
8879 emlxs_fcfi_state_xlate(fcfp->state),
8880 emlxs_fcf_event_xlate(evt), arg1,
8881 fcfp->attempts);
8882
8883 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE,
8884 FCF_REASON_EVENT, evt, arg1);
8885
8886 return (rval);
8887
8888 } /* emlxs_fcfi_unreg_cmpl_action() */
8889
8890
8891 /*ARGSUSED*/
8892 static uint32_t
emlxs_fcfi_online_action(emlxs_port_t * port,FCFIobj_t * fcfp,uint32_t evt,void * arg1)8893 emlxs_fcfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt,
8894 void *arg1)
8895 {
8896 emlxs_hba_t *hba = HBA;
8897 uint32_t rval = 0;
8898 VFIobj_t *vfip;
8899 uint32_t i;
8900
8901 if (fcfp->state != FCFI_STATE_ONLINE) {
8902 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
8903 "fcfi_online_action:%d %s:%s arg=%p. "
8904 "Invalid state. <",
8905 fcfp->fcf_index,
8906 emlxs_fcfi_state_xlate(fcfp->state),
8907 emlxs_fcf_event_xlate(evt), arg1);
8908 return (1);
8909 }
8910
8911 fcfp->flag &= ~EMLXS_FCFI_ONLINE_REQ;
8912
8913 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) {
8914 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8915 "fcfi_online_action:%d attempts=%d. Offline requested.",
8916 fcfp->fcf_index,
8917 fcfp->attempts);
8918
8919 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1);
8920 return (rval);
8921 }
8922
8923 /* Online remaining VFI's for this FCFI */
8924 vfip = hba->sli.sli4.VFI_table;
8925 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) {
8926 if (vfip->fcfp != fcfp) {
8927 continue;
8928 }
8929
8930 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8931 "fcfi_online_action:%d vfi_online=%d. Onlining VFI:%d. >",
8932 fcfp->fcf_index,
8933 fcfp->vfi_online,
8934 vfip->VFI);
8935
8936 (void) emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
8937 }
8938
8939 if (fcfp->prev_state != FCFI_STATE_ONLINE) {
8940 /* Perform VSAN discovery check when first VFI goes online */
8941 if (fcfp->vfi_online < FCFI_MAX_VFI_COUNT) {
8942
8943 /* Perform VSAN Discovery (TBD) */
8944 /* For now we only need 1 VFI */
8945
8946 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8947 "fcfi_online_action:%d vfi_online=%d. "
8948 "VSAN discovery required.",
8949 fcfp->fcf_index,
8950 fcfp->vfi_online);
8951 }
8952 }
8953
8954 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
8955 "fcfi_online_action:%d vfi_online=%d. "
8956 "FCFI online. Notifying fcftab. >",
8957 fcfp->fcf_index,
8958 fcfp->vfi_online);
8959
8960 /* Notify FCFTAB */
8961 rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_ONLINE, fcfp);
8962
8963 return (rval);
8964
8965 } /* emlxs_fcfi_online_action() */
8966
8967
8968 /*ARGSUSED*/
8969 static int
emlxs_fcf_configured(emlxs_port_t * port,FCFIobj_t * fcfp)8970 emlxs_fcf_configured(emlxs_port_t *port, FCFIobj_t *fcfp)
8971 {
8972 emlxs_hba_t *hba = HBA;
8973 int i;
8974 uint32_t entry_count;
8975 uint32_t valid_entry;
8976 uint32_t match_found;
8977 uint16_t VLanId;
8978 FCF_RECORD_t *fcfrec = &fcfp->fcf_rec;
8979 uint32_t j;
8980 uint32_t k;
8981
8982 /* Init the primary flag, we may set it later */
8983 fcfp->flag &= ~(EMLXS_FCFI_PRIMARY|EMLXS_FCFI_BOOT);
8984
8985 if (!(hba->flag & FC_FIP_SUPPORTED)) {
8986 if (!hba->sli.sli4.cfgFCOE.length) {
8987 /* Nothing specified, so everything matches */
8988 /* For nonFIP only use index 0 */
8989 if (fcfrec->fcf_index == 0) {
8990 return (1); /* success */
8991 }
8992 return (0);
8993 }
8994
8995 /* Just check FCMap for now */
8996 if (bcmp((char *)fcfrec->fc_map,
8997 hba->sli.sli4.cfgFCOE.FCMap, 3) == 0) {
8998 return (1); /* success */
8999 }
9000 return (0);
9001 }
9002
9003 /* For FIP mode, the FCF record must match Config Region 23 */
9004
9005 entry_count = (hba->sli.sli4.cfgFCF.length * sizeof (uint32_t)) /
9006 sizeof (tlv_fcfconnectentry_t);
9007 valid_entry = 0;
9008 match_found = 0;
9009
9010 for (i = 0; i < entry_count; i++) {
9011
9012 if (!hba->sli.sli4.cfgFCF.entry[i].Valid) {
9013 continue;
9014 }
9015
9016 if (hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) {
9017 valid_entry = 1;
9018
9019 if (bcmp((char *)fcfrec->fabric_name_identifier,
9020 hba->sli.sli4.cfgFCF.entry[i].FabricName, 8)) {
9021 match_found = 0;
9022 continue;
9023 }
9024
9025 match_found = 1;
9026 }
9027
9028 if (hba->sli.sli4.cfgFCF.entry[i].SwitchNameValid) {
9029 valid_entry = 1;
9030
9031 if (bcmp((char *)fcfrec->switch_name_identifier,
9032 hba->sli.sli4.cfgFCF.entry[i].SwitchName, 8)) {
9033 match_found = 0;
9034 continue;
9035 }
9036
9037 match_found = 1;
9038 }
9039
9040 if (hba->sli.sli4.cfgFCF.entry[i].VLanValid) {
9041 valid_entry = 1;
9042
9043 if (!(fcfp->flag & EMLXS_FCFI_VLAN_ID)) {
9044 match_found = 0;
9045 continue;
9046 }
9047
9048 VLanId = hba->sli.sli4.cfgFCF.entry[i].VLanId;
9049 j = VLanId / 8;
9050 k = 1 << (VLanId % 8);
9051
9052 if (!(fcfrec->vlan_bitmap[j] & k)) {
9053 match_found = 0;
9054 continue;
9055 }
9056
9057 /* Assign requested vlan_id to this FCF */
9058 fcfp->vlan_id = VLanId;
9059
9060 match_found = 1;
9061 }
9062
9063 /* If a match was found */
9064 if (match_found) {
9065 if (hba->sli.sli4.cfgFCF.entry[i].Primary) {
9066 fcfp->flag |= EMLXS_FCFI_PRIMARY;
9067 }
9068 if (hba->sli.sli4.cfgFCF.entry[i].Boot) {
9069 fcfp->flag |= EMLXS_FCFI_BOOT;
9070 }
9071 return (1);
9072 }
9073 }
9074
9075 /* If no valid entries found, then allow any fabric */
9076 if (!valid_entry) {
9077 return (1);
9078 }
9079
9080 return (0);
9081
9082 } /* emlxs_fcf_configured() */
9083
9084
9085 static void
emlxs_fcfi_update(emlxs_port_t * port,FCFIobj_t * fcfp,FCF_RECORD_t * fcf_rec,uint32_t event_tag)9086 emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp, FCF_RECORD_t *fcf_rec,
9087 uint32_t event_tag)
9088 {
9089 emlxs_hba_t *hba = HBA;
9090 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
9091 uint16_t i;
9092
9093 bcopy((char *)fcf_rec, &fcfp->fcf_rec, sizeof (FCF_RECORD_t));
9094 fcfp->fcf_index = fcf_rec->fcf_index;
9095
9096 /* Clear VLAN info */
9097 fcfp->vlan_id = 0;
9098 fcfp->flag &= ~EMLXS_FCFI_VLAN_ID;
9099
9100 /* Check if fcf is a member of a VLAN */
9101 for (i = 0; i < 4096; i++) {
9102 if (fcf_rec->vlan_bitmap[i / 8] & (1 << (i % 8))) {
9103 /* For now assign the VLAN id of the first VLAN found */
9104 fcfp->vlan_id = i;
9105 fcfp->flag |= EMLXS_FCFI_VLAN_ID;
9106 break;
9107 }
9108 }
9109
9110 if (fcf_rec->fcf_available) {
9111 fcfp->flag |= EMLXS_FCFI_AVAILABLE;
9112 } else {
9113 fcfp->flag &= ~EMLXS_FCFI_AVAILABLE;
9114 }
9115
9116 if (fcf_rec->fcf_valid && !fcf_rec->fcf_sol) {
9117 fcfp->flag |= EMLXS_FCFI_VALID;
9118 } else {
9119 fcfp->flag &= ~EMLXS_FCFI_VALID;
9120 }
9121
9122 /* Check config region 23 */
9123 /* Also sets BOOT and PRIMARY cfg bits as needed */
9124 if (emlxs_fcf_configured(port, fcfp)) {
9125 fcfp->flag |= EMLXS_FCFI_CONFIGURED;
9126 } else {
9127 fcfp->flag &= ~EMLXS_FCFI_CONFIGURED;
9128 }
9129
9130 /* Set fcfp priority. Used by selection alogithm */
9131 /* Combination of BOOT:PRIMARY:~fip_priority */
9132 fcfp->priority = (fcfp->flag & EMLXS_FCFI_BOOT)? 0x200:0;
9133 fcfp->priority |= (fcfp->flag & EMLXS_FCFI_PRIMARY)? 0x100:0;
9134 fcfp->priority |= ~(fcf_rec->fip_priority & 0xff);
9135
9136 fcfp->event_tag = event_tag;
9137 fcfp->generation = fcftab->generation;
9138 fcfp->flag |= EMLXS_FCFI_FRESH;
9139
9140 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9141 "fcfi:%d gen=%x iotag=%d flag=%x sol=%x avl=%x val=%x state=%x "
9142 "map=%x pri=%x vid=%x",
9143 fcf_rec->fcf_index,
9144 fcfp->generation,
9145 fcfp->event_tag,
9146 fcfp->flag,
9147 fcf_rec->fcf_sol,
9148 fcf_rec->fcf_available,
9149 fcf_rec->fcf_valid,
9150 fcf_rec->fcf_state,
9151 fcf_rec->mac_address_provider,
9152 fcfp->priority,
9153 fcfp->vlan_id);
9154
9155 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9156 "fcfi:%d mac=%02x:%02x:%02x:%02x:%02x:%02x "
9157 "fabric=%02x%02x%02x%02x%02x%02x%02x%02x "
9158 "switch=%02x%02x%02x%02x%02x%02x%02x%02x",
9159 fcfp->fcf_index,
9160 fcf_rec->fcf_mac_address_hi[0],
9161 fcf_rec->fcf_mac_address_hi[1],
9162 fcf_rec->fcf_mac_address_hi[2],
9163 fcf_rec->fcf_mac_address_hi[3],
9164 fcf_rec->fcf_mac_address_low[0],
9165 fcf_rec->fcf_mac_address_low[1],
9166
9167 fcf_rec->fabric_name_identifier[0],
9168 fcf_rec->fabric_name_identifier[1],
9169 fcf_rec->fabric_name_identifier[2],
9170 fcf_rec->fabric_name_identifier[3],
9171 fcf_rec->fabric_name_identifier[4],
9172 fcf_rec->fabric_name_identifier[5],
9173 fcf_rec->fabric_name_identifier[6],
9174 fcf_rec->fabric_name_identifier[7],
9175
9176 fcf_rec->switch_name_identifier[0],
9177 fcf_rec->switch_name_identifier[1],
9178 fcf_rec->switch_name_identifier[2],
9179 fcf_rec->switch_name_identifier[3],
9180 fcf_rec->switch_name_identifier[4],
9181 fcf_rec->switch_name_identifier[5],
9182 fcf_rec->switch_name_identifier[6],
9183 fcf_rec->switch_name_identifier[7]);
9184
9185 return;
9186
9187 } /* emlxs_fcfi_update() */
9188
9189
9190 /* ************************************************************************** */
9191 /* VFI */
9192 /* ************************************************************************** */
9193
9194 static char *
emlxs_vfi_state_xlate(uint32_t state)9195 emlxs_vfi_state_xlate(uint32_t state)
9196 {
9197 static char buffer[32];
9198 uint32_t i;
9199 uint32_t count;
9200
9201 count = sizeof (emlxs_vfi_state_table) / sizeof (emlxs_table_t);
9202 for (i = 0; i < count; i++) {
9203 if (state == emlxs_vfi_state_table[i].code) {
9204 return (emlxs_vfi_state_table[i].string);
9205 }
9206 }
9207
9208 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
9209 return (buffer);
9210
9211 } /* emlxs_vfi_state_xlate() */
9212
9213
9214 static uint32_t
emlxs_vfi_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9215 emlxs_vfi_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9216 void *arg1)
9217 {
9218 uint32_t rval = 0;
9219 uint32_t(*func) (emlxs_port_t *, VFIobj_t *, uint32_t, void *);
9220 uint32_t index;
9221 uint32_t events;
9222 uint16_t state;
9223
9224 /* Convert event to action table index */
9225 switch (evt) {
9226 case FCF_EVENT_STATE_ENTER:
9227 index = 0;
9228 break;
9229 case FCF_EVENT_VFI_ONLINE:
9230 index = 1;
9231 break;
9232 case FCF_EVENT_VFI_OFFLINE:
9233 index = 2;
9234 break;
9235 case FCF_EVENT_VFI_PAUSE:
9236 index = 3;
9237 break;
9238 case FCF_EVENT_VPI_ONLINE:
9239 index = 4;
9240 break;
9241 case FCF_EVENT_VPI_OFFLINE:
9242 index = 5;
9243 break;
9244 default:
9245 return (1);
9246 }
9247
9248 events = VFI_ACTION_EVENTS;
9249 state = vfip->state;
9250
9251 index += (state * events);
9252 func = (uint32_t(*) (emlxs_port_t *, VFIobj_t *, uint32_t, void *))
9253 emlxs_vfi_action_table[index];
9254
9255 if (!func) {
9256 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9257 "vfi_action:%d %s:%s arg=%p. No action. <",
9258 vfip->VFI,
9259 emlxs_vfi_state_xlate(state),
9260 emlxs_fcf_event_xlate(evt), arg1);
9261
9262 return (1);
9263 }
9264
9265 rval = (func)(port, vfip, evt, arg1);
9266
9267 return (rval);
9268
9269 } /* emlxs_vfi_action() */
9270
9271
9272 static uint32_t
emlxs_vfi_event(emlxs_port_t * port,uint32_t evt,void * arg1)9273 emlxs_vfi_event(emlxs_port_t *port, uint32_t evt,
9274 void *arg1)
9275 {
9276 VPIobj_t *vpip = NULL;
9277 VFIobj_t *vfip = NULL;
9278 uint32_t rval = 0;
9279
9280 /* Filter events and acquire fcfi context */
9281 switch (evt) {
9282 case FCF_EVENT_VPI_ONLINE:
9283 case FCF_EVENT_VPI_OFFLINE:
9284 vpip = (VPIobj_t *)arg1;
9285
9286 if (!vpip) {
9287 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9288 "vfi_event: %s arg=%p. Null VPI found. <",
9289 emlxs_fcf_event_xlate(evt), arg1);
9290
9291 return (1);
9292 }
9293
9294 vfip = vpip->vfip;
9295
9296 if (!vfip) {
9297 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9298 "vfi_event: %s arg=%p. VFI not found. <",
9299 emlxs_fcf_event_xlate(evt), arg1);
9300
9301 return (1);
9302 }
9303 break;
9304
9305 case FCF_EVENT_VFI_ONLINE:
9306 case FCF_EVENT_VFI_OFFLINE:
9307 case FCF_EVENT_VFI_PAUSE:
9308 vfip = (VFIobj_t *)arg1;
9309
9310 if (!vfip) {
9311 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9312 "vfi_event: %s arg=%p. VFI not found. <",
9313 emlxs_fcf_event_xlate(evt), arg1);
9314
9315 return (1);
9316 }
9317 break;
9318
9319 default:
9320 return (1);
9321 }
9322
9323 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
9324 "vfi_event:%d %s:%s arg=%p",
9325 vfip->VFI,
9326 emlxs_vfi_state_xlate(vfip->state),
9327 emlxs_fcf_event_xlate(evt), arg1);
9328
9329 rval = emlxs_vfi_action(port, vfip, evt, arg1);
9330
9331 return (rval);
9332
9333 } /* emlxs_vfi_event() */
9334
9335
9336 /*ARGSUSED*/
9337 static uint32_t
emlxs_vfi_state(emlxs_port_t * port,VFIobj_t * vfip,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)9338 emlxs_vfi_state(emlxs_port_t *port, VFIobj_t *vfip, uint16_t state,
9339 uint16_t reason, uint32_t explain, void *arg1)
9340 {
9341 uint32_t rval = 0;
9342
9343 if (state >= VFI_ACTION_STATES) {
9344 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9345 "vfi_state:%d %s. "
9346 "Invalid state. <",
9347 vfip->VFI,
9348 emlxs_vfi_state_xlate(vfip->state));
9349 return (1);
9350 }
9351
9352 if ((vfip->state == state) &&
9353 (reason != FCF_REASON_REENTER)) {
9354 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9355 "vfi_state:%d %s:%s:0x%x arg=%p. "
9356 "State not changed. <",
9357 vfip->VFI,
9358 emlxs_vfi_state_xlate(vfip->state),
9359 emlxs_fcf_reason_xlate(reason),
9360 explain, arg1);
9361
9362 return (1);
9363 }
9364
9365 if (!reason) {
9366 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
9367 "vfi_state:%d %s-->%s arg=%p",
9368 vfip->VFI,
9369 emlxs_vfi_state_xlate(vfip->state),
9370 emlxs_vfi_state_xlate(state), arg1);
9371 } else if (reason == FCF_REASON_EVENT) {
9372 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
9373 "vfi_state:%d %s-->%s:%s:%s arg=%p",
9374 vfip->VFI,
9375 emlxs_vfi_state_xlate(vfip->state),
9376 emlxs_vfi_state_xlate(state),
9377 emlxs_fcf_reason_xlate(reason),
9378 emlxs_fcf_event_xlate(explain), arg1);
9379 } else if (explain) {
9380 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
9381 "vfi_state:%d %s-->%s:%s:0x%x arg=%p",
9382 vfip->VFI,
9383 emlxs_vfi_state_xlate(vfip->state),
9384 emlxs_vfi_state_xlate(state),
9385 emlxs_fcf_reason_xlate(reason),
9386 explain, arg1);
9387 } else {
9388 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
9389 "vfi_state:%d %s-->%s:%s arg=%p",
9390 vfip->VFI,
9391 emlxs_vfi_state_xlate(vfip->state),
9392 emlxs_vfi_state_xlate(state),
9393 emlxs_fcf_reason_xlate(reason), arg1);
9394 }
9395
9396 vfip->prev_state = vfip->state;
9397 vfip->prev_reason = vfip->reason;
9398 vfip->state = state;
9399 vfip->reason = reason;
9400
9401 rval = emlxs_vfi_action(port, vfip, FCF_EVENT_STATE_ENTER, arg1);
9402
9403 return (rval);
9404
9405 } /* emlxs_vfi_state() */
9406
9407
9408 /*ARGSUSED*/
9409 static uint32_t
emlxs_vfi_vpi_online_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9410 emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip,
9411 uint32_t evt, void *arg1)
9412 {
9413 uint32_t rval = 0;
9414
9415 if (evt != FCF_EVENT_VPI_ONLINE) {
9416 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9417 "vfi_vpi_online_evt_action:%d %s:%s arg=%p flag=%x. "
9418 "Invalid event type. <",
9419 vfip->VFI,
9420 emlxs_vfi_state_xlate(vfip->state),
9421 emlxs_fcf_event_xlate(evt), arg1,
9422 vfip->flag);
9423 return (1);
9424 }
9425
9426 switch (vfip->state) {
9427 case VFI_STATE_ONLINE:
9428 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9429 "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. "
9430 "Reentering online.",
9431 vfip->VFI,
9432 vfip->flag,
9433 vfip->vpi_online);
9434
9435 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
9436 FCF_REASON_REENTER, evt, arg1);
9437 break;
9438
9439 case VFI_STATE_VPI_ONLINE:
9440 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9441 "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. "
9442 "Online cmpl.",
9443 vfip->VFI,
9444 vfip->flag,
9445 vfip->vpi_online);
9446
9447 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE_CMPL,
9448 FCF_REASON_EVENT, evt, arg1);
9449 break;
9450
9451 default:
9452 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9453 "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. <",
9454 vfip->VFI,
9455 vfip->flag,
9456 vfip->vpi_online);
9457
9458 return (1);
9459 }
9460
9461 return (rval);
9462
9463 } /* emlxs_vfi_vpi_online_evt_action() */
9464
9465
9466 /*ARGSUSED*/
9467 static uint32_t
emlxs_vfi_offline_handler(emlxs_port_t * port,VFIobj_t * vfip,void * arg1)9468 emlxs_vfi_offline_handler(emlxs_port_t *port, VFIobj_t *vfip, void *arg1)
9469 {
9470 uint32_t rval = 0;
9471
9472 if (!(vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
9473 return (0);
9474 }
9475
9476 if (vfip->vpi_online) {
9477 if (vfip->flag & EMLXS_VFI_PAUSE_REQ) {
9478 rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED,
9479 FCF_REASON_REQUESTED, 0, arg1);
9480 } else {
9481 rval = emlxs_vfi_state(port, vfip,
9482 VFI_STATE_VPI_OFFLINE, FCF_REASON_REQUESTED,
9483 0, arg1);
9484 }
9485
9486 } else if (vfip->flag & EMLXS_VFI_REG) {
9487 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
9488 FCF_REASON_REQUESTED, 0, arg1);
9489
9490 } else if (vfip->flag & EMLXS_VFI_INIT) {
9491 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
9492 FCF_REASON_REQUESTED, 0, arg1);
9493
9494 } else {
9495 rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
9496 FCF_REASON_REQUESTED, 0, arg1);
9497 }
9498
9499 return (rval);
9500
9501 } /* emlxs_vfi_offline_handler() */
9502
9503
9504 /*ARGSUSED*/
9505 static uint32_t
emlxs_vfi_vpi_offline_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9506 emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip,
9507 uint32_t evt, void *arg1)
9508 {
9509 uint32_t rval = 0;
9510 VPIobj_t *vpip;
9511
9512 if (evt != FCF_EVENT_VPI_OFFLINE) {
9513 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9514 "vfi_vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
9515 "Invalid event type. <",
9516 vfip->VFI,
9517 emlxs_vfi_state_xlate(vfip->state),
9518 emlxs_fcf_event_xlate(evt), arg1,
9519 vfip->flag);
9520 return (1);
9521 }
9522
9523 /* Disconnect VPI object from VFI */
9524 vpip = (VPIobj_t *)arg1;
9525 vpip->vfip = NULL;
9526
9527 switch (vfip->state) {
9528 case VFI_STATE_ONLINE:
9529 case VFI_STATE_VPI_ONLINE:
9530 if (vfip->vpi_online == 0) {
9531 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9532 "vfi_vpi_offline_evt_action:%d flag=%x "
9533 "vpi_online=%d. Offlining.",
9534 vfip->VFI,
9535 vfip->flag, vfip->vpi_online);
9536
9537 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9538 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
9539 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
9540 } else {
9541 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9542 "vfi_vpi_offline_evt_action:%d flag=%x "
9543 "vpi_online=%d. <",
9544 vfip->VFI,
9545 vfip->flag, vfip->vpi_online);
9546 }
9547 break;
9548
9549 case VFI_STATE_PAUSED:
9550 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9551 "vfi_vpi_offline_evt_action:%d flag=%x vpi_online=%d. <",
9552 vfip->VFI,
9553 vfip->flag, vfip->vpi_online);
9554 break;
9555
9556 case VFI_STATE_VPI_OFFLINE:
9557 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9558 "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.",
9559 vfip->VFI,
9560 vfip->flag);
9561
9562 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL,
9563 FCF_REASON_EVENT, evt, arg1);
9564 break;
9565
9566 case VFI_STATE_VPI_OFFLINE_CMPL:
9567 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9568 "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.",
9569 vfip->VFI,
9570 vfip->flag);
9571
9572 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL,
9573 FCF_REASON_REENTER, evt, arg1);
9574 break;
9575
9576 default:
9577 if (vfip->vpi_online == 0) {
9578 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9579 "vfi_vpi_offline_evt_action:%d flag=%x "
9580 "vpi_online=%d. Requesting offline. <",
9581 vfip->VFI,
9582 vfip->flag, vfip->vpi_online);
9583
9584 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9585 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
9586 } else {
9587 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9588 "vfi_vpi_offline_evt_action:%d flag=%x "
9589 "vpi_online=%d. <",
9590 vfip->VFI,
9591 vfip->flag, vfip->vpi_online);
9592 }
9593 return (1);
9594 }
9595
9596 return (rval);
9597
9598 } /* emlxs_vfi_vpi_offline_evt_action() */
9599
9600
9601 /*ARGSUSED*/
9602 static uint32_t
emlxs_vfi_online_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9603 emlxs_vfi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9604 void *arg1)
9605 {
9606 emlxs_hba_t *hba = HBA;
9607 emlxs_port_t *vport;
9608 VPIobj_t *vpip;
9609 uint32_t rval = 0;
9610 uint32_t i;
9611
9612 if (evt != FCF_EVENT_VFI_ONLINE) {
9613 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9614 "vfi_online_evt_action:%d %s:%s arg=%p flag=%x. "
9615 "Invalid event type. <",
9616 vfip->VFI,
9617 emlxs_vfi_state_xlate(vfip->state),
9618 emlxs_fcf_event_xlate(evt), arg1,
9619 vfip->flag);
9620 return (1);
9621 }
9622
9623 if (vfip->flag & EMLXS_VFI_ONLINE_REQ) {
9624 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9625 "vfi_online_evt_action:%d flag=%x. "
9626 "Online already requested. <",
9627 vfip->VFI,
9628 vfip->flag);
9629 return (0);
9630 }
9631
9632 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9633
9634 switch (vfip->state) {
9635 case VFI_STATE_OFFLINE:
9636 vfip->flag |= EMLXS_VFI_ONLINE_REQ;
9637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9638 "vfi_online_evt_action:%d flag=%x. Initiating online.",
9639 vfip->VFI,
9640 vfip->flag);
9641
9642 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
9643 FCF_REASON_EVENT, evt, arg1);
9644 break;
9645
9646 case VFI_STATE_VPI_OFFLINE:
9647 case VFI_STATE_PAUSED:
9648 vfip->flag |= EMLXS_VFI_ONLINE_REQ;
9649 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9650 "vfi_online_evt_action:%d flag=%x. Initiating online.",
9651 vfip->VFI,
9652 vfip->flag);
9653
9654 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
9655 FCF_REASON_EVENT, evt, arg1);
9656 break;
9657
9658 case VFI_STATE_ONLINE:
9659 /* Online all VPI's belonging to this vfi */
9660 for (i = 0; i <= hba->vpi_max; i++) {
9661 vport = &VPORT(i);
9662 vpip = vport->vpip;
9663
9664 if (!(vport->flag & EMLXS_PORT_BOUND) ||
9665 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
9666 continue;
9667 }
9668
9669 if (vpip->vfip != vfip) {
9670 continue;
9671 }
9672
9673 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9674 "vfi_online_evt_action:%d. Onlining VPI:%d >",
9675 vfip->VFI,
9676 vpip->VPI);
9677
9678 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE,
9679 vpip);
9680 }
9681 break;
9682
9683 default:
9684 vfip->flag |= EMLXS_VFI_ONLINE_REQ;
9685 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9686 "vfi_online_evt_action:%d flag=%x. <",
9687 vfip->VFI,
9688 vfip->flag);
9689 return (1);
9690 }
9691
9692 return (rval);
9693
9694 } /* emlxs_vfi_online_evt_action() */
9695
9696
9697 /*ARGSUSED*/
9698 static uint32_t
emlxs_vfi_offline_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9699 emlxs_vfi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9700 void *arg1)
9701 {
9702 uint32_t rval = 0;
9703
9704 if (evt != FCF_EVENT_VFI_OFFLINE) {
9705 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9706 "vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
9707 "Invalid event type. <",
9708 vfip->VFI,
9709 emlxs_vfi_state_xlate(vfip->state),
9710 emlxs_fcf_event_xlate(evt), arg1,
9711 vfip->flag);
9712 return (1);
9713 }
9714
9715 if ((vfip->flag & EMLXS_VFI_OFFLINE_REQ) &&
9716 !(vfip->flag & EMLXS_VFI_PAUSE_REQ)) {
9717 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9718 "vfi_offline_evt_action:%d flag=%x. "
9719 "Offline already requested. <",
9720 vfip->VFI,
9721 vfip->flag);
9722 return (0);
9723 }
9724
9725 switch (vfip->state) {
9726 case VFI_STATE_OFFLINE:
9727 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9728 "vfi_offline_evt_action:%d flag=%x. "
9729 "Already offline. <",
9730 vfip->VFI,
9731 vfip->flag);
9732 break;
9733
9734 /* Wait states */
9735 case VFI_STATE_VPI_ONLINE:
9736 case VFI_STATE_VPI_OFFLINE:
9737 case VFI_STATE_VPI_OFFLINE_CMPL:
9738 case VFI_STATE_INIT:
9739 case VFI_STATE_REG:
9740 case VFI_STATE_ONLINE:
9741 case VFI_STATE_PAUSED:
9742 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9743 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
9744
9745 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9746 "vfi_offline_evt_action:%d flag=%x. Handling offline.",
9747 vfip->VFI,
9748 vfip->flag);
9749
9750 /* Handle offline now */
9751 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
9752 break;
9753
9754 default:
9755 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9756 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
9757
9758 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9759 "vfi_offline_evt_action:%d flag=%x. <",
9760 vfip->VFI,
9761 vfip->flag);
9762 break;
9763 }
9764
9765 return (rval);
9766
9767 } /* emlxs_vfi_offline_evt_action() */
9768
9769
9770 /*ARGSUSED*/
9771 static uint32_t
emlxs_vfi_pause_evt_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9772 emlxs_vfi_pause_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9773 void *arg1)
9774 {
9775 uint32_t rval = 0;
9776
9777 if (evt != FCF_EVENT_VFI_PAUSE) {
9778 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9779 "vfi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
9780 "Invalid event type. <",
9781 vfip->VFI,
9782 emlxs_vfi_state_xlate(vfip->state),
9783 emlxs_fcf_event_xlate(evt), arg1,
9784 vfip->flag);
9785 return (1);
9786 }
9787
9788 if (vfip->flag & EMLXS_VFI_PAUSE_REQ) {
9789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9790 "vfi_pause_evt_action:%d flag=%x. "
9791 "Pause already requested. <",
9792 vfip->VFI,
9793 vfip->flag);
9794 return (0);
9795 }
9796
9797 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
9798 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9799 "vfi_pause_evt_action:%d flag=%x. "
9800 "Offline already requested. <",
9801 vfip->VFI,
9802 vfip->flag);
9803 return (0);
9804 }
9805
9806 switch (vfip->state) {
9807 case VFI_STATE_OFFLINE:
9808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9809 "vfi_pause_evt_action:%d flag=%x. "
9810 "Already offline. <",
9811 vfip->VFI,
9812 vfip->flag);
9813 break;
9814
9815 case VFI_STATE_PAUSED:
9816 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9817 "vfi_pause_evt_action:%d flag=%x. "
9818 "Already paused. <",
9819 vfip->VFI,
9820 vfip->flag);
9821 break;
9822
9823 /* Wait states */
9824 case VFI_STATE_VPI_ONLINE:
9825 case VFI_STATE_VPI_OFFLINE_CMPL:
9826 case VFI_STATE_INIT:
9827 case VFI_STATE_REG:
9828 case VFI_STATE_ONLINE:
9829 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9830 vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
9831
9832 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9833 "vfi_pause_evt_action:%d flag=%x. Handling offline.",
9834 vfip->VFI,
9835 vfip->flag);
9836
9837 /* Handle offline now */
9838 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
9839 break;
9840
9841 default:
9842 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
9843 vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
9844
9845 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9846 "vfi_pause_evt_action:%d flag=%x. <",
9847 vfip->VFI,
9848 vfip->flag);
9849 break;
9850 }
9851
9852 return (rval);
9853
9854 } /* emlxs_vfi_pause_evt_action() */
9855
9856
9857 /*ARGSUSED*/
9858 static uint32_t
emlxs_vfi_offline_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9859 emlxs_vfi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9860 void *arg1)
9861 {
9862 uint32_t rval = 0;
9863
9864 if (vfip->state != VFI_STATE_OFFLINE) {
9865 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9866 "vfi_offline_action:%d %s:%s arg=%p. "
9867 "Invalid state. <",
9868 vfip->VFI,
9869 emlxs_vfi_state_xlate(vfip->state),
9870 emlxs_fcf_event_xlate(evt), arg1);
9871 return (1);
9872 }
9873
9874 if (!vfip->fcfp) {
9875 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9876 "vfi_offline_action:%d %s:%s arg=%p flag=%x. "
9877 "Null fcfp found. <",
9878 vfip->VFI,
9879 emlxs_vfi_state_xlate(vfip->state),
9880 emlxs_fcf_event_xlate(evt), arg1,
9881 vfip->flag);
9882 return (1);
9883 }
9884
9885 vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
9886
9887 if (vfip->prev_state == VFI_STATE_OFFLINE) {
9888 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9889 "vfi_offline_action:%d vfi_online=%d. <",
9890 vfip->VFI,
9891 vfip->fcfp->vfi_online);
9892
9893 return (0);
9894 }
9895
9896 if (vfip->vpi_online) {
9897 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
9898 "vfi_offline_action:%d vpi_online=%d. VPI's still online.",
9899 vfip->VFI,
9900 vfip->vpi_online);
9901 }
9902
9903 if (vfip->flag & EMLXS_VFI_FCFI) {
9904 vfip->flag &= ~EMLXS_VFI_FCFI;
9905
9906 if (vfip->fcfp->vfi_online) {
9907 vfip->fcfp->vfi_online--;
9908 }
9909 }
9910
9911 /* Check if online was requested */
9912 if (vfip->flag & EMLXS_VFI_ONLINE_REQ) {
9913 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9914 "vfi_offline_action:%d vfi_online=%d. Online requested.",
9915 vfip->VFI,
9916 vfip->fcfp->vfi_online);
9917
9918 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
9919 FCF_REASON_REQUESTED, 0, arg1);
9920 return (rval);
9921 }
9922
9923 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9924 "vfi_offline_action:%d vfi_online=%d. "
9925 "VFI offline. Notifying FCFI:%d >",
9926 vfip->VFI,
9927 vfip->fcfp->vfi_online,
9928 vfip->fcfp->fcf_index);
9929
9930 /* Notify FCFI */
9931 rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip);
9932
9933 return (rval);
9934
9935 } /* emlxs_vfi_offline_action() */
9936
9937
9938 /*ARGSUSED*/
9939 static uint32_t
emlxs_vfi_init_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)9940 emlxs_vfi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
9941 {
9942 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
9943 VFIobj_t *vfip;
9944 MAILBOX4 *mb4;
9945
9946 vfip = (VFIobj_t *)mbq->context;
9947 mb4 = (MAILBOX4 *)mbq;
9948
9949 mutex_enter(&EMLXS_FCF_LOCK);
9950
9951 if (vfip->state != VFI_STATE_INIT) {
9952 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9953 "vfi_init_mbcmpl:%d %s.",
9954 vfip->VFI,
9955 emlxs_vfi_state_xlate(vfip->state));
9956
9957 mutex_exit(&EMLXS_FCF_LOCK);
9958 return (0);
9959 }
9960
9961 if (mb4->mbxStatus) {
9962 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9963 "vfi_init_mbcmpl:%d failed. %s. >",
9964 vfip->VFI,
9965 emlxs_mb_xlate_status(mb4->mbxStatus));
9966
9967 (void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED,
9968 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
9969
9970 mutex_exit(&EMLXS_FCF_LOCK);
9971 return (0);
9972 }
9973
9974 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
9975 "vfi_init_mbcmpl:%d. Init complete. >",
9976 vfip->VFI,
9977 mb4->mbxStatus);
9978
9979 vfip->flag |= EMLXS_VFI_INIT;
9980 (void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL, 0, 0, 0);
9981
9982 mutex_exit(&EMLXS_FCF_LOCK);
9983 return (0);
9984
9985 } /* emlxs_vfi_init_mbcmpl() */
9986
9987
9988 /*ARGSUSED*/
9989 static uint32_t
emlxs_vfi_init_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)9990 emlxs_vfi_init_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
9991 void *arg1)
9992 {
9993 emlxs_hba_t *hba = HBA;
9994 MAILBOXQ *mbq;
9995 MAILBOX4 *mb4;
9996 uint32_t rval = 0;
9997
9998 if (vfip->state != VFI_STATE_INIT) {
9999 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10000 "vfi_init_action:%d %s:%s arg=%p. "
10001 "Invalid state. <",
10002 vfip->VFI,
10003 emlxs_vfi_state_xlate(vfip->state),
10004 emlxs_fcf_event_xlate(evt), arg1);
10005 return (1);
10006 }
10007
10008 if (!(vfip->flag & EMLXS_VFI_FCFI)) {
10009 vfip->flag |= EMLXS_VFI_FCFI;
10010 vfip->fcfp->vfi_online++;
10011 }
10012
10013 if (vfip->prev_state != VFI_STATE_INIT_FAILED) {
10014 vfip->attempts = 0;
10015 }
10016
10017 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
10018 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10019 "vfi_init_action:%d attempts=%d. Offline requested.",
10020 vfip->VFI,
10021 vfip->attempts);
10022
10023 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10024 return (rval);
10025 }
10026
10027 if (vfip->flag & EMLXS_VFI_INIT) {
10028 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10029 "vfi_init_action:%d flag=%x. "
10030 "Already init'd. Skipping INIT_VFI.",
10031 vfip->VFI);
10032
10033 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
10034 FCF_REASON_EVENT, evt, arg1);
10035 return (rval);
10036 }
10037
10038 if (((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) ==
10039 SLI_INTF_IF_TYPE_0) && (vfip->fcfp->vfi_online == 1)) {
10040 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10041 "vfi_init_action:%d. First VFI. Skipping INIT_VFI.",
10042 vfip->VFI);
10043
10044 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
10045 FCF_REASON_EVENT, evt, arg1);
10046 return (rval);
10047 }
10048
10049 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10050 "vfi_init_action:%d vfi_online=%d attempts=%d. Sending INIT_VFI. <",
10051 vfip->VFI,
10052 vfip->fcfp->vfi_online,
10053 vfip->attempts);
10054
10055 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
10056 rval = emlxs_vfi_state(port, vfip, FCFI_STATE_REG_FAILED,
10057 FCF_REASON_NO_MBOX, 0, arg1);
10058 return (rval);
10059 }
10060 mb4 = (MAILBOX4*)mbq;
10061 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10062
10063 mbq->nonembed = NULL;
10064 mbq->mbox_cmpl = emlxs_vfi_init_mbcmpl;
10065 mbq->context = (void *)vfip;
10066 mbq->port = (void *)port;
10067
10068 mb4->mbxCommand = MBX_INIT_VFI;
10069 mb4->mbxOwner = OWN_HOST;
10070 mb4->un.varInitVFI4.fcfi = vfip->fcfp->FCFI;
10071 mb4->un.varInitVFI4.vfi = vfip->VFI;
10072
10073 /* ??? This function is untested and incomplete */
10074
10075 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
10076 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
10077 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10078
10079 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED,
10080 FCF_REASON_SEND_FAILED, rval, arg1);
10081
10082 return (rval);
10083 }
10084
10085 return (0);
10086
10087 } /* emlxs_vfi_init_action() */
10088
10089
10090 /*ARGSUSED*/
10091 static uint32_t
emlxs_vfi_init_failed_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10092 emlxs_vfi_init_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10093 void *arg1)
10094 {
10095 uint32_t rval = 0;
10096
10097 vfip->attempts++;
10098
10099 if (vfip->state != VFI_STATE_INIT_FAILED) {
10100 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10101 "vfi_init_action:%d %s:%s arg=%p attempt=%d. "
10102 "Invalid state. <",
10103 vfip->VFI,
10104 emlxs_vfi_state_xlate(vfip->state),
10105 emlxs_fcf_event_xlate(evt), arg1,
10106 vfip->attempts);
10107 return (1);
10108 }
10109
10110 if ((vfip->reason == FCF_REASON_SEND_FAILED) ||
10111 (vfip->attempts >= 3)) {
10112 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10113 "vfi_init_action:%d attempt=%d reason=%x. Init cmpl.",
10114 vfip->VFI,
10115 vfip->attempts,
10116 vfip->reason);
10117
10118 vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT);
10119
10120 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10121 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10122 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL,
10123 FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10124 } else {
10125 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10126 "vfi_init_action:%d attempt=%d. Initializing.",
10127 vfip->VFI,
10128 vfip->attempts);
10129
10130 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT,
10131 FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10132 }
10133
10134 return (rval);
10135
10136 } /* emlxs_vfi_init_failed_action() */
10137
10138
10139 /*ARGSUSED*/
10140 static uint32_t
emlxs_vfi_init_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10141 emlxs_vfi_init_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10142 void *arg1)
10143 {
10144 uint32_t rval = 0;
10145
10146 if (vfip->state != VFI_STATE_INIT_CMPL) {
10147 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10148 "vfi_init_cmpl_action:%d %s:%s arg=%p. "
10149 "Invalid state. <",
10150 vfip->VFI,
10151 emlxs_vfi_state_xlate(vfip->state),
10152 emlxs_fcf_event_xlate(evt), arg1);
10153 return (1);
10154 }
10155
10156 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10157 "vfi_init_cmpl_action:%d attempts=%d. Init cmpl.",
10158 vfip->VFI,
10159 vfip->attempts);
10160
10161 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE,
10162 FCF_REASON_EVENT, evt, arg1);
10163
10164 return (rval);
10165
10166 } /* emlxs_vfi_init_cmpl_action() */
10167
10168
10169 /*ARGSUSED*/
10170 static uint32_t
emlxs_vfi_vpi_online_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10171 emlxs_vfi_vpi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10172 void *arg1)
10173 {
10174 emlxs_hba_t *hba = HBA;
10175 uint32_t rval = 0;
10176 uint32_t i;
10177 emlxs_port_t *vport;
10178 VPIobj_t *vpip;
10179
10180 if (vfip->state != VFI_STATE_VPI_ONLINE) {
10181 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10182 "vfi_vpi_online_action:%d %s:%s arg=%p. "
10183 "Invalid state. <",
10184 vfip->VFI,
10185 emlxs_vfi_state_xlate(vfip->state),
10186 emlxs_fcf_event_xlate(evt), arg1);
10187 return (1);
10188 }
10189
10190 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
10191 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10192 "vfi_vpi_online_action:%d. Offline requested.",
10193 vfip->VFI);
10194
10195 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10196 return (rval);
10197 }
10198
10199 if (vfip->logi_count) {
10200 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10201 "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. "
10202 "VPI already logged in.",
10203 vfip->VFI,
10204 vfip->vpi_online,
10205 vfip->logi_count);
10206 }
10207
10208 if (vfip->vpi_online) {
10209 /* Waking up after being paused */
10210
10211 /* Find first VPI of this VFI */
10212 for (i = 0; i <= hba->vpi_max; i++) {
10213 vport = &VPORT(i);
10214 vpip = vport->vpip;
10215
10216 if (!(vport->flag & EMLXS_PORT_BOUND) ||
10217 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
10218 continue;
10219 }
10220
10221 if (vpip->vfip == vfip) {
10222 break;
10223 }
10224 }
10225
10226 } else {
10227
10228 /* Find first available VPI */
10229 for (i = 0; i <= hba->vpi_max; i++) {
10230 vport = &VPORT(i);
10231 vpip = vport->vpip;
10232
10233 if (!(vport->flag & EMLXS_PORT_BOUND) ||
10234 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
10235 continue;
10236 }
10237
10238 if (vpip->vfip == NULL) {
10239 vpip->vfip = vfip;
10240 break;
10241 }
10242 }
10243 }
10244
10245 if (i > hba->vpi_max) {
10246 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10247 "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. "
10248 "No VPI found. Offlining.",
10249 vfip->VFI,
10250 vfip->vpi_online,
10251 vfip->logi_count);
10252
10253 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10254 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10255 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10256 return (rval);
10257 }
10258
10259 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10260 "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. "
10261 "Onlining VPI:%d >",
10262 vfip->VFI,
10263 vfip->vpi_online,
10264 vfip->logi_count,
10265 vpip->VPI);
10266
10267 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
10268
10269 /* Wait for FCF_EVENT_VPI_ONLINE in return */
10270
10271 return (rval);
10272
10273 } /* emlxs_vfi_vpi_online_action() */
10274
10275
10276 /*ARGSUSED*/
10277 static uint32_t
emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10278 emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip,
10279 uint32_t evt, void *arg1)
10280 {
10281 uint32_t rval = 0;
10282 VPIobj_t *vpip = (VPIobj_t *)arg1;
10283
10284 if (vfip->state != VFI_STATE_VPI_ONLINE_CMPL) {
10285 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10286 "vfi_vpi_online_cmpl_action:%d %s:%s arg=%p. "
10287 "Invalid state. <",
10288 vfip->VFI,
10289 emlxs_vfi_state_xlate(vfip->state),
10290 emlxs_fcf_event_xlate(evt), arg1);
10291 return (1);
10292 }
10293
10294 if (vpip == vfip->flogi_vpip) {
10295 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10296 "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d "
10297 "logi_count=%d. flogi_vpi. Registering.",
10298 vfip->VFI,
10299 vfip->flag,
10300 vfip->vpi_online,
10301 vfip->logi_count);
10302
10303 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG,
10304 FCF_REASON_EVENT, evt, arg1);
10305 } else {
10306 /* Waking up after pause */
10307 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10308 "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d "
10309 "logi_count=%d. Going online.",
10310 vfip->VFI,
10311 vfip->flag,
10312 vfip->vpi_online,
10313 vfip->logi_count);
10314
10315 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
10316 FCF_REASON_EVENT, evt, arg1);
10317 }
10318
10319 return (rval);
10320
10321 } /* emlxs_vfi_vpi_online_cmpl_action() */
10322
10323
10324 /*ARGSUSED*/
10325 static uint32_t
emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10326 emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip,
10327 uint32_t evt, void *arg1)
10328 {
10329 uint32_t rval = 0;
10330
10331 if (vfip->state != VFI_STATE_VPI_OFFLINE_CMPL) {
10332 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10333 "vfi_vpi_offline_cmpl_action:%d %s:%s arg=%p. "
10334 "Invalid state. <",
10335 vfip->VFI,
10336 emlxs_vfi_state_xlate(vfip->state),
10337 emlxs_fcf_event_xlate(evt), arg1);
10338 return (1);
10339 }
10340
10341 if ((vfip->vpi_online == 0) &&
10342 (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) {
10343 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10344 "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. "
10345 "Unregistering.",
10346 vfip->VFI,
10347 vfip->vpi_online);
10348
10349 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
10350 FCF_REASON_EVENT, evt, arg1);
10351 } else {
10352 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10353 "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. <",
10354 vfip->VFI,
10355 vfip->vpi_online);
10356 }
10357
10358 return (rval);
10359
10360 } /* emlxs_vfi_vpi_offline_cmpl_action() */
10361
10362
10363 /*ARGSUSED*/
10364 static uint32_t
emlxs_vfi_vpi_offline_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10365 emlxs_vfi_vpi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10366 void *arg1)
10367 {
10368 emlxs_hba_t *hba = HBA;
10369 emlxs_port_t *vport;
10370 uint32_t rval = 0;
10371 int32_t i;
10372 VPIobj_t *vpip;
10373
10374 if (vfip->state != VFI_STATE_VPI_OFFLINE) {
10375 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10376 "vfi_vpi_offline_action:%d %s:%s arg=%p. "
10377 "Invalid state. <",
10378 vfip->VFI,
10379 emlxs_vfi_state_xlate(vfip->state),
10380 emlxs_fcf_event_xlate(evt), arg1);
10381 return (1);
10382 }
10383
10384 if (vfip->flag & EMLXS_VFI_PAUSE_REQ) {
10385 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10386 "vfi_vpi_offline_action:%d vpi_online=%d. Pausing.",
10387 vfip->VFI,
10388 vfip->vpi_online);
10389
10390 rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED,
10391 FCF_REASON_EVENT, evt, arg1);
10392
10393 return (rval);
10394 }
10395
10396 if (vfip->vpi_online == 0) {
10397 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10398 "vfi_vpi_offline_action:%d vpi_online=%d. "
10399 "VPI already offline. Skipping VPI offline.",
10400 vfip->VFI,
10401 vfip->vpi_online);
10402
10403 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
10404 FCF_REASON_EVENT, evt, arg1);
10405
10406 return (rval);
10407 }
10408
10409 /* Offline all VPI's of this VFI */
10410 for (i = hba->vpi_max; i >= 0; i--) {
10411 vport = &VPORT(i);
10412 vpip = vport->vpip;
10413
10414 if ((vpip->state == VPI_STATE_OFFLINE) ||
10415 (vpip->vfip != vfip)) {
10416 continue;
10417 }
10418
10419 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10420 "vfi_vpi_offline_action:%d. Offlining VPI:%d. >",
10421 vfip->VFI,
10422 vpip->VPI);
10423
10424 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_OFFLINE, vpip);
10425 }
10426
10427 /* Wait for FCF_EVENT_VPI_OFFLINE in return */
10428
10429 return (0);
10430
10431 } /* emlxs_vfi_vpi_offline_action() */
10432
10433
10434 /*ARGSUSED*/
10435 static uint32_t
emlxs_vfi_paused_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10436 emlxs_vfi_paused_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10437 void *arg1)
10438 {
10439 emlxs_hba_t *hba = HBA;
10440 emlxs_port_t *vport;
10441 int32_t i;
10442 VPIobj_t *vpip;
10443
10444 if (vfip->state != VFI_STATE_PAUSED) {
10445 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10446 "vfi_paused_action:%d %s:%s arg=%p. "
10447 "Invalid state. <",
10448 vfip->VFI,
10449 emlxs_vfi_state_xlate(vfip->state),
10450 emlxs_fcf_event_xlate(evt), arg1);
10451 return (1);
10452 }
10453
10454 vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ);
10455
10456 /* Pause all VPI's of this VFI */
10457 for (i = hba->vpi_max; i >= 0; i--) {
10458 vport = &VPORT(i);
10459 vpip = vport->vpip;
10460
10461 if ((vpip->state == VPI_STATE_PAUSED) ||
10462 (vpip->vfip != vfip)) {
10463 continue;
10464 }
10465
10466 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10467 "vfi_paused_action:%d vpi_online=%d. Pausing VPI:%d. >",
10468 vfip->VFI,
10469 vfip->vpi_online,
10470 vpip->VPI);
10471
10472 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip);
10473 }
10474
10475 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10476 "vfi_paused_action:%d vpi_online=%d. VFI paused. <",
10477 vfip->VFI,
10478 vfip->vpi_online);
10479
10480 return (0);
10481
10482 } /* emlxs_vfi_paused_action() */
10483
10484
10485 /*ARGSUSED*/
10486 static uint32_t
emlxs_vfi_unreg_failed_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10487 emlxs_vfi_unreg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10488 void *arg1)
10489 {
10490 uint32_t rval = 0;
10491
10492 vfip->attempts++;
10493
10494 if (vfip->state != VFI_STATE_UNREG_FAILED) {
10495 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10496 "vfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
10497 "Invalid state. <",
10498 vfip->VFI,
10499 emlxs_vfi_state_xlate(vfip->state),
10500 emlxs_fcf_event_xlate(evt), arg1,
10501 vfip->attempts);
10502 return (1);
10503 }
10504
10505 if (vfip->attempts >= 3) {
10506 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10507 "vfi_unreg_failed_action:%d attempt=%d. Unreg cmpl.",
10508 vfip->VFI,
10509 vfip->attempts);
10510
10511 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10512 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10513 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL,
10514 FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10515 } else {
10516 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10517 "vfi_unreg_failed_action:%d attempt=%d. Unregistering.",
10518 vfip->VFI,
10519 vfip->attempts);
10520
10521 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG,
10522 FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10523 }
10524
10525 return (rval);
10526
10527 } /* emlxs_vfi_unreg_failed_action() */
10528
10529
10530 /*ARGSUSED*/
10531 static uint32_t
emlxs_vfi_unreg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)10532 emlxs_vfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
10533 {
10534 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
10535 MAILBOX4 *mb4;
10536 VFIobj_t *vfip;
10537
10538 vfip = (VFIobj_t *)mbq->context;
10539 mb4 = (MAILBOX4 *)mbq;
10540
10541 mutex_enter(&EMLXS_FCF_LOCK);
10542
10543 if (vfip->state != VFI_STATE_UNREG) {
10544 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10545 "vfi_unreg_mbcmpl:%d state=%s.",
10546 vfip->VFI,
10547 emlxs_vfi_state_xlate(vfip->state));
10548
10549 mutex_exit(&EMLXS_FCF_LOCK);
10550 return (0);
10551 }
10552
10553 if (mb4->mbxStatus) {
10554 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10555 "vfi_unreg_mbcmpl:%d failed. %s. >",
10556 vfip->VFI,
10557 emlxs_mb_xlate_status(mb4->mbxStatus));
10558
10559 (void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
10560 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
10561
10562 mutex_exit(&EMLXS_FCF_LOCK);
10563 return (0);
10564 }
10565
10566 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10567 "vfi_unreg_mbcmpl:%d. Unreg complete. >",
10568 vfip->VFI);
10569
10570 vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT);
10571 (void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL,
10572 0, 0, 0);
10573
10574 mutex_exit(&EMLXS_FCF_LOCK);
10575 return (0);
10576
10577 } /* emlxs_vfi_unreg_mbcmpl() */
10578
10579
10580 /*ARGSUSED*/
10581 static uint32_t
emlxs_vfi_unreg_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10582 emlxs_vfi_unreg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10583 void *arg1)
10584 {
10585 emlxs_hba_t *hba = HBA;
10586 MAILBOX4 *mb4;
10587 MAILBOXQ *mbq;
10588 uint32_t rval = 0;
10589
10590 if (vfip->state != VFI_STATE_UNREG) {
10591 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10592 "vfi_unreg_action:%d %s:%s arg=%p. "
10593 "Invalid state. <",
10594 vfip->VFI,
10595 emlxs_vfi_state_xlate(vfip->state),
10596 emlxs_fcf_event_xlate(evt), arg1);
10597 return (1);
10598 }
10599
10600 if (!(vfip->flag & EMLXS_VFI_REG)) {
10601 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10602 "vfi_unreg_action:%d. Not registered. Skipping UNREG_VFI.",
10603 vfip->VFI);
10604
10605 rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
10606 FCF_REASON_EVENT, evt, arg1);
10607 return (rval);
10608 }
10609
10610 if (vfip->prev_state != VFI_STATE_UNREG_FAILED) {
10611 vfip->attempts = 0;
10612 }
10613
10614 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10615 "vfi_unreg_action:%d attempts=%d. Sending UNREG_VFI. <",
10616 vfip->VFI,
10617 vfip->attempts);
10618
10619 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
10620 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
10621 FCF_REASON_NO_MBOX, 0, arg1);
10622
10623 return (rval);
10624 }
10625 mb4 = (MAILBOX4*)mbq;
10626 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10627
10628 mbq->nonembed = NULL;
10629 mbq->mbox_cmpl = emlxs_vfi_unreg_mbcmpl;
10630 mbq->context = (void *)vfip;
10631 mbq->port = (void *)port;
10632
10633 mb4->un.varUnRegVFI4.vfi = vfip->VFI;
10634 mb4->mbxCommand = MBX_UNREG_VFI;
10635 mb4->mbxOwner = OWN_HOST;
10636
10637 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
10638 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
10639 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10640
10641 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED,
10642 FCF_REASON_SEND_FAILED, rval, arg1);
10643
10644 return (rval);
10645 }
10646
10647 return (0);
10648
10649 } /* emlxs_vfi_unreg_action() */
10650
10651
10652 /*ARGSUSED*/
10653 static uint32_t
emlxs_vfi_unreg_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10654 emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10655 void *arg1)
10656 {
10657 uint32_t rval = 0;
10658
10659 if (vfip->state != VFI_STATE_UNREG_CMPL) {
10660 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10661 "vfi_unreg_cmpl_action:%d %s:%s arg=%p. "
10662 "Invalid state. <",
10663 vfip->VFI,
10664 emlxs_vfi_state_xlate(vfip->state),
10665 emlxs_fcf_event_xlate(evt), arg1);
10666 return (1);
10667 }
10668
10669 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10670 "vfi_unreg_cmpl_action:%d attempts=%d. Going offline.",
10671 vfip->VFI,
10672 vfip->attempts);
10673
10674 rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE,
10675 FCF_REASON_EVENT, evt, arg1);
10676
10677 return (rval);
10678
10679 } /* emlxs_vfi_unreg_cmpl_action() */
10680
10681
10682 /*ARGSUSED*/
10683 static uint32_t
emlxs_vfi_reg_failed_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10684 emlxs_vfi_reg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10685 void *arg1)
10686 {
10687 uint32_t rval = 0;
10688
10689 vfip->attempts++;
10690
10691 if (vfip->state != VFI_STATE_REG_FAILED) {
10692 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10693 "vfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
10694 "Invalid state. <",
10695 vfip->VFI,
10696 emlxs_vfi_state_xlate(vfip->state),
10697 emlxs_fcf_event_xlate(evt), arg1,
10698 vfip->attempts);
10699 return (1);
10700 }
10701
10702 if ((vfip->reason == FCF_REASON_SEND_FAILED) ||
10703 (vfip->attempts >= 3)) {
10704 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10705 "vfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.",
10706 vfip->VFI,
10707 vfip->attempts,
10708 vfip->reason);
10709
10710 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10711 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10712 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL,
10713 FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10714 } else {
10715 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10716 "vfi_reg_failed_action:%d attempt=%d. Registering.",
10717 vfip->VFI,
10718 vfip->attempts);
10719
10720 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG,
10721 FCF_REASON_OP_FAILED, vfip->attempts, arg1);
10722 }
10723
10724 return (rval);
10725
10726 } /* emlxs_vfi_reg_failed_action() */
10727
10728
10729 /*ARGSUSED*/
10730 static uint32_t
emlxs_vfi_reg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)10731 emlxs_vfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
10732 {
10733 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
10734 MAILBOX4 *mb4;
10735 VFIobj_t *vfip;
10736 MATCHMAP *mp;
10737
10738 vfip = (VFIobj_t *)mbq->context;
10739 mb4 = (MAILBOX4 *)mbq;
10740
10741 mutex_enter(&EMLXS_FCF_LOCK);
10742
10743 if (vfip->state != VFI_STATE_REG) {
10744 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10745 "vfi_reg_mbcmpl:%d state=%s.",
10746 vfip->VFI,
10747 emlxs_vfi_state_xlate(vfip->state));
10748
10749 mutex_exit(&EMLXS_FCF_LOCK);
10750 return (0);
10751 }
10752
10753 if (mb4->mbxStatus) {
10754 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10755 "vfi_reg_mbcmpl:%d failed. %s. >",
10756 vfip->VFI,
10757 emlxs_mb_xlate_status(mb4->mbxStatus));
10758
10759 (void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10760 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
10761
10762 mutex_exit(&EMLXS_FCF_LOCK);
10763 return (0);
10764 }
10765
10766 /* Archive a copy of the sparams in case we need them later */
10767 mp = (MATCHMAP *)mbq->bp;
10768 bcopy((uint32_t *)mp->virt, (uint32_t *)&vfip->sparam,
10769 sizeof (SERV_PARM));
10770
10771 if (vfip->flogi_vpip) {
10772 if (mb4->un.varRegVFI4.vp == 1) {
10773 vfip->flogi_vpip->flag |= EMLXS_VPI_REG;
10774 }
10775 vfip->flogi_vpip = NULL;
10776 }
10777
10778 vfip->flag |= EMLXS_VFI_REG;
10779
10780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10781 "vfi_reg_mbcmpl:%d. Reg complete. >",
10782 vfip->VFI);
10783
10784 (void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL, 0, 0, 0);
10785
10786 mutex_exit(&EMLXS_FCF_LOCK);
10787 return (0);
10788
10789 } /* emlxs_vfi_reg_mbcmpl() */
10790
10791
10792 /*ARGSUSED*/
10793 static uint32_t
emlxs_vfi_reg_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10794 emlxs_vfi_reg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10795 void *arg1)
10796 {
10797 emlxs_hba_t *hba = HBA;
10798 MAILBOX4 *mb4;
10799 MAILBOXQ *mbq;
10800 MATCHMAP *mp;
10801 uint32_t rval = 0;
10802 uint32_t edtov;
10803 uint32_t ratov;
10804 SERV_PARM *flogi_sparam;
10805 uint32_t *wwpn;
10806
10807 if (vfip->state != VFI_STATE_REG) {
10808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10809 "vfi_reg_action:%d %s:%s arg=%p. "
10810 "Invalid state. <",
10811 vfip->VFI,
10812 emlxs_vfi_state_xlate(vfip->state),
10813 emlxs_fcf_event_xlate(evt), arg1);
10814 return (1);
10815 }
10816
10817 if (vfip->prev_state != VFI_STATE_REG_FAILED) {
10818 vfip->attempts = 0;
10819 }
10820
10821 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
10822 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10823 "vfi_reg_action:%d %attempts=%d. Offline requested.",
10824 vfip->VFI,
10825 vfip->attempts);
10826
10827 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10828 return (rval);
10829 }
10830
10831 if (!vfip->flogi_vpip) {
10832 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10833 "vfi_reg_action:%d %attempts=%d. No flogi_vpi found.",
10834 vfip->VFI,
10835 vfip->attempts);
10836
10837 vfip->flag &= ~EMLXS_VFI_REQ_MASK;
10838 vfip->flag |= EMLXS_VFI_OFFLINE_REQ;
10839
10840 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10841 return (rval);
10842 }
10843
10844 if ((hba->model_info.chip & EMLXS_BE_CHIPS) &&
10845 (vfip->flag & EMLXS_VFI_REG)) {
10846 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10847 "vfi_reg_action:%d flag=%x. "
10848 "Already registered. Skipping REG_VFI update.",
10849 vfip->VFI);
10850
10851 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
10852 FCF_REASON_EVENT, evt, arg1);
10853 return (rval);
10854 }
10855
10856 /* Get the flogi_vpip's fabric_rpip's service parameters */
10857 flogi_sparam = &vfip->flogi_vpip->fabric_rpip->sparam;
10858
10859 if (flogi_sparam->cmn.edtovResolution) {
10860 edtov = (LE_SWAP32(flogi_sparam->cmn.e_d_tov) + 999999) /
10861 1000000;
10862 } else {
10863 edtov = LE_SWAP32(flogi_sparam->cmn.e_d_tov);
10864 }
10865
10866 ratov = (LE_SWAP32(flogi_sparam->cmn.w2.r_a_tov) + 999) / 1000;
10867
10868 if (vfip->flag & EMLXS_VFI_REG) {
10869 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10870 "vfi_reg_action:%d attempts=%d edtov=%d ratov=%d. "
10871 "Updating REG_VFI. <",
10872 vfip->VFI,
10873 vfip->attempts,
10874 edtov, ratov);
10875 } else {
10876 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10877 "vfi_reg_action:%d attempts=%d edtov=%d ratov=%d. "
10878 "Sending REG_VFI. <",
10879 vfip->VFI,
10880 vfip->attempts,
10881 edtov, ratov);
10882 }
10883
10884 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
10885 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10886 FCF_REASON_NO_MBOX, 0, arg1);
10887
10888 return (rval);
10889 }
10890 mb4 = (MAILBOX4*)mbq;
10891 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
10892
10893 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
10894 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10895
10896 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10897 FCF_REASON_NO_BUFFER, 0, arg1);
10898
10899 return (1);
10900 }
10901
10902 mbq->bp = (void *)mp;
10903 mbq->nonembed = NULL;
10904
10905 mbq->mbox_cmpl = emlxs_vfi_reg_mbcmpl;
10906 mbq->context = (void *)vfip;
10907 mbq->port = (void *)port;
10908
10909 mb4->mbxCommand = MBX_REG_VFI;
10910 mb4->mbxOwner = OWN_HOST;
10911
10912 mb4->un.varRegVFI4.vfi = vfip->VFI;
10913 mb4->un.varRegVFI4.upd = (vfip->flag & EMLXS_VFI_REG)? 1:0;
10914
10915 /* If the flogi_vpip was not previously registered, */
10916 /* perform the REG_VPI now */
10917 if (!(vfip->flogi_vpip->flag & EMLXS_VPI_REG)) {
10918 mb4->un.varRegVFI4.vp = 1;
10919 mb4->un.varRegVFI4.vpi = vfip->flogi_vpip->VPI;
10920 }
10921
10922 mb4->un.varRegVFI4.fcfi = vfip->fcfp->FCFI;
10923 wwpn = (uint32_t *)&port->wwpn;
10924 mb4->un.varRegVFI4.portname[0] = BE_SWAP32(*wwpn);
10925 wwpn++;
10926 mb4->un.varRegVFI4.portname[1] = BE_SWAP32(*wwpn);
10927 mb4->un.varRegVFI4.sid = port->did;
10928 mb4->un.varRegVFI4.edtov = edtov;
10929 mb4->un.varRegVFI4.ratov = ratov;
10930 mb4->un.varRegVFI4.bde.tus.f.bdeSize = sizeof (SERV_PARM);
10931 mb4->un.varRegVFI4.bde.addrHigh = PADDR_HI(mp->phys);
10932 mb4->un.varRegVFI4.bde.addrLow = PADDR_LO(mp->phys);
10933 bcopy((uint32_t *)flogi_sparam, (uint32_t *)mp->virt,
10934 sizeof (SERV_PARM));
10935
10936 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
10937 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
10938 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
10939 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
10940
10941 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED,
10942 FCF_REASON_SEND_FAILED, rval, arg1);
10943
10944 return (rval);
10945 }
10946
10947 return (0);
10948
10949 } /* emlxs_vfi_reg_action() */
10950
10951
10952 /*ARGSUSED*/
10953 static uint32_t
emlxs_vfi_reg_cmpl_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10954 emlxs_vfi_reg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10955 void *arg1)
10956 {
10957 uint32_t rval = 0;
10958
10959 if (vfip->state != VFI_STATE_REG_CMPL) {
10960 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
10961 "vfi_reg_cmpl_action:%d %s:%s arg=%p. "
10962 "Invalid state. <",
10963 vfip->VFI,
10964 emlxs_vfi_state_xlate(vfip->state),
10965 emlxs_fcf_event_xlate(evt), arg1);
10966 return (1);
10967 }
10968
10969 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
10970 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10971 "vfi_reg_cmpl_action:%d attempts=%d. Offline requested.",
10972 vfip->VFI,
10973 vfip->attempts);
10974
10975 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
10976 return (rval);
10977 }
10978
10979 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
10980 "vfi_reg_cmpl_action:%d attempts=%d. Going online.",
10981 vfip->VFI,
10982 vfip->attempts);
10983
10984 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE,
10985 FCF_REASON_EVENT, evt, arg1);
10986
10987 return (rval);
10988
10989 } /* emlxs_vfi_reg_cmpl_action() */
10990
10991
10992 /*ARGSUSED*/
10993 static uint32_t
emlxs_vfi_online_action(emlxs_port_t * port,VFIobj_t * vfip,uint32_t evt,void * arg1)10994 emlxs_vfi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt,
10995 void *arg1)
10996 {
10997 emlxs_hba_t *hba = HBA;
10998 uint32_t i;
10999 uint32_t rval = 0;
11000 VPIobj_t *vpip = port->vpip;
11001 emlxs_port_t *vport;
11002
11003 if (vfip->state != VFI_STATE_ONLINE) {
11004 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11005 "vfi_online_action:%d %s:%s arg=%p. "
11006 "Invalid state. <",
11007 vfip->VFI,
11008 emlxs_vfi_state_xlate(vfip->state),
11009 emlxs_fcf_event_xlate(evt), arg1);
11010 return (1);
11011 }
11012
11013 vfip->flag &= ~EMLXS_VFI_ONLINE_REQ;
11014
11015 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) {
11016 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11017 "vfi_online_action:%d attempts=%d. Offline requested.",
11018 vfip->VFI,
11019 vfip->attempts);
11020
11021 rval = emlxs_vfi_offline_handler(port, vfip, arg1);
11022 return (rval);
11023 }
11024
11025 /* Take the port's Fabric RPI online now */
11026 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11027 "vfi_online_action:%d. Onlining Fabric RPI. >",
11028 vfip->VFI);
11029
11030 /* This will complete the FLOGI/FDISC back to Leadville */
11031 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE,
11032 vpip->fabric_rpip);
11033
11034 /* FLOGI/FDISC has been completed back to Leadville */
11035 /* It is now safe to accept unsolicited requests */
11036 vpip->flag |= EMLXS_VPI_PORT_ENABLED;
11037
11038 /* Online remaining VPI's */
11039 for (i = 0; i <= hba->vpi_max; i++) {
11040 vport = &VPORT(i);
11041 vpip = vport->vpip;
11042
11043 if (!(vport->flag & EMLXS_PORT_BOUND) ||
11044 (vpip->flag & EMLXS_VPI_PORT_UNBIND)) {
11045 continue;
11046 }
11047
11048 if ((vpip->state == VPI_STATE_ONLINE) ||
11049 (vpip->flag & EMLXS_VPI_ONLINE_REQ)) {
11050 continue;
11051 }
11052
11053 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11054 "vfi_online_action:%d vpi_online=%d logi_count=%d. "
11055 "Onlining VPI:%d >",
11056 vfip->VFI,
11057 vfip->vpi_online,
11058 vfip->logi_count,
11059 vpip->VPI);
11060
11061 vpip->vfip = vfip;
11062 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE, vpip);
11063 }
11064
11065 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11066 "vfi_online_action:%d vpi_online=%d logi_count=%d. "
11067 "VFI online. Notifying FCFI:%d. >",
11068 vfip->VFI,
11069 vfip->vpi_online,
11070 vfip->logi_count,
11071 vfip->fcfp->fcf_index);
11072
11073 /* Notify FCFI */
11074 rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_ONLINE, vfip);
11075
11076 return (rval);
11077
11078 } /* emlxs_vfi_online_action() */
11079
11080
11081 /* ************************************************************************** */
11082 /* VPI */
11083 /* ************************************************************************** */
11084
11085 static char *
emlxs_vpi_state_xlate(uint32_t state)11086 emlxs_vpi_state_xlate(uint32_t state)
11087 {
11088 static char buffer[32];
11089 uint32_t i;
11090 uint32_t count;
11091
11092 count = sizeof (emlxs_vpi_state_table) / sizeof (emlxs_table_t);
11093 for (i = 0; i < count; i++) {
11094 if (state == emlxs_vpi_state_table[i].code) {
11095 return (emlxs_vpi_state_table[i].string);
11096 }
11097 }
11098
11099 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
11100 return (buffer);
11101
11102 } /* emlxs_vpi_state_xlate() */
11103
11104
11105 static uint32_t
emlxs_vpi_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11106 emlxs_vpi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11107 void *arg1)
11108 {
11109 uint32_t rval = 0;
11110 uint32_t(*func) (emlxs_port_t *, VPIobj_t *, uint32_t, void *);
11111 uint32_t index;
11112 uint32_t events;
11113 uint16_t state;
11114
11115 /* Convert event to action table index */
11116 switch (evt) {
11117 case FCF_EVENT_STATE_ENTER:
11118 index = 0;
11119 break;
11120 case FCF_EVENT_VPI_ONLINE:
11121 index = 1;
11122 break;
11123 case FCF_EVENT_VPI_OFFLINE:
11124 index = 2;
11125 break;
11126 case FCF_EVENT_VPI_PAUSE:
11127 index = 3;
11128 break;
11129 case FCF_EVENT_RPI_ONLINE:
11130 index = 4;
11131 break;
11132 case FCF_EVENT_RPI_OFFLINE:
11133 index = 5;
11134 break;
11135 case FCF_EVENT_RPI_PAUSE:
11136 index = 6;
11137 break;
11138 default:
11139 return (1);
11140 }
11141
11142 events = VPI_ACTION_EVENTS;
11143 state = vpip->state;
11144
11145 index += (state * events);
11146 func = (uint32_t(*) (emlxs_port_t *, VPIobj_t *, uint32_t, void *))
11147 emlxs_vpi_action_table[index];
11148
11149 if (!func) {
11150 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11151 "vpi_action:%d %s:%s arg=%p. No action. <",
11152 vpip->VPI,
11153 emlxs_vpi_state_xlate(vpip->state),
11154 emlxs_fcf_event_xlate(evt), arg1);
11155
11156 return (1);
11157 }
11158
11159 rval = (func)(port, vpip, evt, arg1);
11160
11161 return (rval);
11162
11163 } /* emlxs_vpi_action() */
11164
11165
11166 static uint32_t
emlxs_vpi_event(emlxs_port_t * port,uint32_t evt,void * arg1)11167 emlxs_vpi_event(emlxs_port_t *port, uint32_t evt,
11168 void *arg1)
11169 {
11170 VPIobj_t *vpip = NULL;
11171 RPIobj_t *rpip;
11172 uint32_t rval = 0;
11173
11174 /* Filter events and acquire fcfi context */
11175 switch (evt) {
11176 case FCF_EVENT_RPI_ONLINE:
11177 case FCF_EVENT_RPI_OFFLINE:
11178 case FCF_EVENT_RPI_PAUSE:
11179 rpip = (RPIobj_t *)arg1;
11180
11181 if (!rpip) {
11182 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11183 "vpi_event: %s arg=%p. Null RPI found. <",
11184 emlxs_fcf_event_xlate(evt), arg1);
11185
11186 return (1);
11187 }
11188
11189 vpip = rpip->vpip;
11190 break;
11191
11192 case FCF_EVENT_VPI_ONLINE:
11193 case FCF_EVENT_VPI_PAUSE:
11194 case FCF_EVENT_VPI_OFFLINE:
11195 vpip = (VPIobj_t *)arg1;
11196
11197 if (!vpip) {
11198 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11199 "vpi_event: %s arg=%p. Null VPI found. <",
11200 emlxs_fcf_event_xlate(evt), arg1);
11201
11202 return (1);
11203 }
11204
11205 break;
11206
11207 default:
11208 return (1);
11209 }
11210
11211 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
11212 "vpi_event:%d %s:%s arg=%p",
11213 vpip->VPI,
11214 emlxs_vpi_state_xlate(vpip->state),
11215 emlxs_fcf_event_xlate(evt), arg1);
11216
11217 rval = emlxs_vpi_action(port, vpip, evt, arg1);
11218
11219 return (rval);
11220
11221 } /* emlxs_vpi_event() */
11222
11223
11224 /*ARGSUSED*/
11225 static uint32_t
emlxs_vpi_state(emlxs_port_t * port,VPIobj_t * vpip,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)11226 emlxs_vpi_state(emlxs_port_t *port, VPIobj_t *vpip, uint16_t state,
11227 uint16_t reason, uint32_t explain, void *arg1)
11228 {
11229 uint32_t rval = 0;
11230
11231 if (state >= VPI_ACTION_STATES) {
11232 return (1);
11233 }
11234
11235 if ((vpip->state == state) &&
11236 (reason != FCF_REASON_REENTER)) {
11237 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11238 "vpi_state:%d %s:%s:0x%x arg=%p. "
11239 "State not changed. <",
11240 vpip->VPI,
11241 emlxs_vpi_state_xlate(vpip->state),
11242 emlxs_fcf_reason_xlate(reason),
11243 explain, arg1);
11244 return (1);
11245 }
11246
11247 if (!reason) {
11248 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11249 "vpi_state:%d %s-->%s arg=%p",
11250 vpip->VPI,
11251 emlxs_vpi_state_xlate(vpip->state),
11252 emlxs_vpi_state_xlate(state), arg1);
11253 } else if (reason == FCF_REASON_EVENT) {
11254 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11255 "vpi_state:%d %s-->%s:%s:%s arg=%p",
11256 vpip->VPI,
11257 emlxs_vpi_state_xlate(vpip->state),
11258 emlxs_vpi_state_xlate(state),
11259 emlxs_fcf_reason_xlate(reason),
11260 emlxs_fcf_event_xlate(explain), arg1);
11261 } else if (explain) {
11262 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11263 "vpi_state:%d %s-->%s:%s:0x%x arg=%p",
11264 vpip->VPI,
11265 emlxs_vpi_state_xlate(vpip->state),
11266 emlxs_vpi_state_xlate(state),
11267 emlxs_fcf_reason_xlate(reason),
11268 explain, arg1);
11269 } else {
11270 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
11271 "vpi_state:%d %s-->%s:%s arg=%p",
11272 vpip->VPI,
11273 emlxs_vpi_state_xlate(vpip->state),
11274 emlxs_vpi_state_xlate(state),
11275 emlxs_fcf_reason_xlate(reason), arg1);
11276 }
11277
11278 vpip->prev_state = vpip->state;
11279 vpip->prev_reason = vpip->reason;
11280 vpip->state = state;
11281 vpip->reason = reason;
11282
11283 rval = emlxs_vpi_action(port, vpip, FCF_EVENT_STATE_ENTER, arg1);
11284
11285 return (rval);
11286
11287 } /* emlxs_vpi_state() */
11288
11289
11290 extern uint32_t
emlxs_vpi_port_bind_notify(emlxs_port_t * port)11291 emlxs_vpi_port_bind_notify(emlxs_port_t *port)
11292 {
11293 emlxs_hba_t *hba = HBA;
11294 VPIobj_t *vpip = port->vpip;
11295 FCFTable_t *fcftab = &hba->sli.sli4.fcftab;
11296 uint32_t rval = 0;
11297 VFIobj_t *vfip;
11298 VFIobj_t *vfip1;
11299 uint32_t i = 0;
11300 FCFIobj_t *fcfp;
11301 FCFIobj_t *fcfp1;
11302
11303 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
11304 return (1);
11305 }
11306
11307 if (hba->state < FC_LINK_UP) {
11308 if (port->vpi == 0) {
11309 (void) emlxs_reset_link(hba, 1, 0);
11310
11311 /* Wait for VPI to go online */
11312 while ((vpip->state != VPI_STATE_PORT_ONLINE) &&
11313 (hba->state != FC_ERROR)) {
11314 delay(drv_usectohz(500000));
11315 if (i++ > 30) {
11316 break;
11317 }
11318 }
11319 }
11320 return (0);
11321 }
11322
11323 mutex_enter(&EMLXS_FCF_LOCK);
11324
11325 if (vpip->vfip) {
11326 vfip = vpip->vfip;
11327 fcfp = vfip->fcfp;
11328 goto done;
11329 }
11330
11331 /* We need to select a VFI for this VPI */
11332
11333 /* First find a selected Fabric */
11334 fcfp = NULL;
11335 for (i = 0; i < fcftab->fcfi_count; i++) {
11336 fcfp1 = fcftab->fcfi[i];
11337
11338 if (fcfp1->flag & EMLXS_FCFI_SELECTED) {
11339 fcfp = fcfp1;
11340 break;
11341 }
11342 }
11343
11344 if (!fcfp) {
11345 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11346 "vpi_port_bind_notify:%d %s. "
11347 "No FCF available yet.",
11348 vpip->VPI,
11349 emlxs_vpi_state_xlate(vpip->state));
11350
11351 mutex_exit(&EMLXS_FCF_LOCK);
11352 return (0);
11353 }
11354
11355 /* Find first available VFI for this FCFI */
11356 vfip = NULL;
11357 vfip1 = hba->sli.sli4.VFI_table;
11358 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip1++) {
11359 if (vfip1->fcfp == fcfp) {
11360 vfip = vfip1;
11361 break;
11362 }
11363 }
11364
11365 if (!vfip) {
11366 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11367 "vpi_port_bind_notify:%d %s fcfi:%d. "
11368 "No VFI available yet.",
11369 vpip->VPI,
11370 emlxs_vpi_state_xlate(vpip->state),
11371 fcfp->fcf_index);
11372
11373 mutex_exit(&EMLXS_FCF_LOCK);
11374 return (0);
11375 }
11376
11377 vpip->vfip = vfip;
11378 done:
11379
11380 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11381 "vpi_port_bind_notify:%d %s fcfi:%d vfi:%d. Onlining VPI:%d >",
11382 vpip->VPI,
11383 emlxs_vpi_state_xlate(vpip->state),
11384 fcfp->fcf_index,
11385 vfip->VFI,
11386 vpip->VPI);
11387
11388 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
11389
11390 mutex_exit(&EMLXS_FCF_LOCK);
11391
11392 return (rval);
11393
11394 } /* emlxs_vpi_port_bind_notify() */
11395
11396
11397 extern uint32_t
emlxs_vpi_port_unbind_notify(emlxs_port_t * port,uint32_t wait)11398 emlxs_vpi_port_unbind_notify(emlxs_port_t *port, uint32_t wait)
11399 {
11400 emlxs_hba_t *hba = HBA;
11401 VPIobj_t *vpip = port->vpip;
11402 uint32_t rval = 0;
11403 VFIobj_t *vfip;
11404 uint32_t i;
11405 FCFIobj_t *fcfp;
11406
11407 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
11408 return (1);
11409 }
11410
11411 if (!(hba->sli.sli4.flag & EMLXS_SLI4_FCF_INIT)) {
11412 return (0);
11413 }
11414
11415 mutex_enter(&EMLXS_FCF_LOCK);
11416
11417 if (vpip->state == VPI_STATE_OFFLINE) {
11418 mutex_exit(&EMLXS_FCF_LOCK);
11419 return (0);
11420 }
11421
11422 /*
11423 * Set flag to indicate that emlxs_vpi_port_unbind_notify
11424 * has been called
11425 */
11426 vpip->flag |= EMLXS_VPI_PORT_UNBIND;
11427
11428 vfip = vpip->vfip;
11429 fcfp = vfip->fcfp;
11430
11431 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11432 "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d. "
11433 "Offlining VPI:%d,%d >",
11434 vpip->VPI,
11435 emlxs_vpi_state_xlate(vpip->state),
11436 fcfp->fcf_index,
11437 vfip->VFI,
11438 vpip->index, vpip->VPI);
11439
11440 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
11441
11442 if (wait && (rval == 0)) {
11443 /* Wait for VPI to go offline */
11444 i = 0;
11445 while (i++ < 120) {
11446 if (vpip->state == VPI_STATE_OFFLINE) {
11447 break;
11448 }
11449
11450 mutex_exit(&EMLXS_FCF_LOCK);
11451 BUSYWAIT_MS(1000);
11452 mutex_enter(&EMLXS_FCF_LOCK);
11453 }
11454
11455 if (i >= 120) {
11456 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11457 "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d "
11458 "rpi_online=%d,%d. Offline timeout.",
11459 vpip->VPI,
11460 emlxs_vpi_state_xlate(vpip->state),
11461 fcfp->fcf_index,
11462 vfip->VFI,
11463 vpip->rpi_online, vpip->rpi_paused);
11464 }
11465 }
11466
11467 vpip->flag &= ~EMLXS_VPI_PORT_UNBIND;
11468
11469 mutex_exit(&EMLXS_FCF_LOCK);
11470
11471 return (rval);
11472
11473 } /* emlxs_vpi_port_unbind_notify() */
11474
11475
11476 /*ARGSUSED*/
11477 static uint32_t
emlxs_vpi_rpi_offline_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11478 emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
11479 uint32_t evt, void *arg1)
11480 {
11481 uint32_t rval = 0;
11482 RPIobj_t *rpip = (RPIobj_t *)arg1;
11483
11484 if (evt != FCF_EVENT_RPI_OFFLINE) {
11485 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11486 "vpi_rpi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
11487 "Invalid event type. <",
11488 vpip->VPI,
11489 emlxs_vpi_state_xlate(vpip->state),
11490 emlxs_fcf_event_xlate(evt), arg1,
11491 vpip->flag);
11492 return (1);
11493 }
11494
11495 switch (vpip->state) {
11496 case VPI_STATE_LOGO:
11497 /* rpi_online will be checked when LOGO is complete */
11498 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11499 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11500 "rpi=%d. Waiting for LOGO. <",
11501 vpip->VPI,
11502 vpip->rpi_online, vpip->rpi_paused,
11503 rpip->did, rpip->RPI);
11504
11505 rval = 0;
11506 break;
11507
11508 case VPI_STATE_PORT_OFFLINE:
11509 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11510 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11511 "rpi=%d.",
11512 vpip->VPI,
11513 vpip->rpi_online, vpip->rpi_paused,
11514 rpip->did, rpip->RPI);
11515
11516 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
11517 FCF_REASON_REENTER, evt, arg1);
11518 break;
11519
11520 case VPI_STATE_PAUSED:
11521 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11522 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11523 "rpi=%d. VPI paused. <",
11524 vpip->VPI,
11525 vpip->rpi_online, vpip->rpi_paused,
11526 rpip->did, rpip->RPI);
11527
11528 rval = 0;
11529 break;
11530
11531 case VPI_STATE_ONLINE:
11532 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11533 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11534 "rpi=%d. <",
11535 vpip->VPI,
11536 vpip->rpi_online, vpip->rpi_paused,
11537 rpip->did, rpip->RPI);
11538
11539 rval = 0;
11540 break;
11541
11542 default:
11543 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11544 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x "
11545 "rpi=%d. "
11546 "Invalid state. <",
11547 vpip->VPI,
11548 vpip->rpi_online, vpip->rpi_paused,
11549 rpip->did, rpip->RPI);
11550
11551 rval = 1;
11552 break;
11553 }
11554
11555 return (rval);
11556
11557 } /* emlxs_vpi_rpi_offline_evt_action() */
11558
11559
11560 /*ARGSUSED*/
11561 static uint32_t
emlxs_vpi_rpi_pause_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11562 emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
11563 uint32_t evt, void *arg1)
11564 {
11565 uint32_t rval = 0;
11566 RPIobj_t *rpip = (RPIobj_t *)arg1;
11567
11568 if (evt != FCF_EVENT_RPI_PAUSE) {
11569 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11570 "vpi_rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
11571 "Invalid event type. <",
11572 vpip->VPI,
11573 emlxs_vpi_state_xlate(vpip->state),
11574 emlxs_fcf_event_xlate(evt), arg1,
11575 vpip->flag);
11576 return (1);
11577 }
11578
11579 switch (vpip->state) {
11580 case VPI_STATE_LOGO:
11581 /* rpi_online will be checked when LOGO is complete */
11582 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11583 "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
11584 "rpi=%d. Waiting for LOGO. <",
11585 vpip->VPI,
11586 vpip->rpi_online, vpip->rpi_paused,
11587 rpip->did, rpip->RPI);
11588
11589 rval = 0;
11590 break;
11591
11592 case VPI_STATE_PORT_OFFLINE:
11593 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11594 "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
11595 "rpi=%d.",
11596 vpip->VPI,
11597 vpip->rpi_online, vpip->rpi_paused,
11598 rpip->did, rpip->RPI);
11599
11600 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
11601 FCF_REASON_REENTER, 0, 0);
11602 break;
11603
11604 case VPI_STATE_PAUSED:
11605 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11606 "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
11607 "rpi=%d. VPI already paused. <",
11608 vpip->VPI,
11609 vpip->rpi_online, vpip->rpi_paused,
11610 rpip->did, rpip->RPI);
11611
11612 rval = 0;
11613 break;
11614
11615 default:
11616 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11617 "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x "
11618 "rpi=%d. "
11619 "Invalid state. <",
11620 vpip->VPI,
11621 vpip->rpi_online, vpip->rpi_paused,
11622 rpip->did, rpip->RPI);
11623
11624 rval = 1;
11625 break;
11626 }
11627
11628 return (rval);
11629
11630 } /* emlxs_vpi_rpi_pause_evt_action() */
11631
11632
11633 /*ARGSUSED*/
11634 static uint32_t
emlxs_vpi_rpi_online_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11635 emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip,
11636 uint32_t evt, void *arg1)
11637 {
11638 RPIobj_t *rpip = (RPIobj_t *)arg1;
11639
11640 if (evt != FCF_EVENT_RPI_ONLINE) {
11641 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11642 "vpi_rpi_online_evt_action:%d %s:%s arg=%p flag=%x. "
11643 "Invalid event type. <",
11644 vpip->VPI,
11645 emlxs_vpi_state_xlate(vpip->state),
11646 emlxs_fcf_event_xlate(evt), arg1,
11647 vpip->flag);
11648 return (1);
11649 }
11650
11651 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11652 "vpi_rpi_online_evt_action:%d rpi_online=%d,%d did=%x rpi=%d. <",
11653 vpip->VPI,
11654 vpip->rpi_online, vpip->rpi_paused,
11655 rpip->did, rpip->RPI);
11656
11657 return (0);
11658
11659 } /* emlxs_vpi_rpi_online_evt_action() */
11660
11661
11662 /*ARGSUSED*/
11663 static uint32_t
emlxs_vpi_online_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11664 emlxs_vpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11665 void *arg1)
11666 {
11667 uint32_t rval = 0;
11668
11669 if (evt != FCF_EVENT_VPI_ONLINE) {
11670 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11671 "vpi_online_evt_action:%d %s:%s arg=%p flag=%x. "
11672 "Invalid event type. <",
11673 vpip->VPI,
11674 emlxs_vpi_state_xlate(vpip->state),
11675 emlxs_fcf_event_xlate(evt), arg1,
11676 vpip->flag);
11677 return (1);
11678 }
11679
11680 if (vpip->flag & EMLXS_VPI_ONLINE_REQ) {
11681 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11682 "vpi_online_evt_action:%d flag=%x. "
11683 "Online already requested. <",
11684 vpip->VPI,
11685 vpip->flag);
11686 return (1);
11687 }
11688
11689 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11690 vpip->flag |= EMLXS_VPI_ONLINE_REQ;
11691
11692 switch (vpip->state) {
11693 case VPI_STATE_OFFLINE:
11694 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11695 "vpi_online_evt_action:%d flag=%x. Initiating online.",
11696 vpip->VPI,
11697 vpip->flag);
11698
11699 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
11700 FCF_REASON_EVENT, evt, arg1);
11701 break;
11702
11703 case VPI_STATE_PORT_OFFLINE:
11704 case VPI_STATE_PAUSED:
11705 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11706 "vpi_online_evt_action:%d flag=%x. Initiating online.",
11707 vpip->VPI,
11708 vpip->flag);
11709
11710 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
11711 FCF_REASON_EVENT, evt, arg1);
11712 break;
11713
11714 default:
11715 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11716 "vpi_online_evt_action:%d flag=%x. <",
11717 vpip->VPI,
11718 vpip->flag);
11719 return (1);
11720 }
11721
11722 return (rval);
11723
11724 } /* emlxs_vpi_online_evt_action() */
11725
11726
11727 /*ARGSUSED*/
11728 static uint32_t
emlxs_vpi_offline_handler(emlxs_port_t * port,VPIobj_t * vpip,void * arg1)11729 emlxs_vpi_offline_handler(emlxs_port_t *port, VPIobj_t *vpip, void *arg1)
11730 {
11731 uint32_t rval = 0;
11732
11733 if (!(vpip->flag & EMLXS_VPI_OFFLINE_REQ)) {
11734 return (0);
11735 }
11736
11737 if (vpip->flag & EMLXS_VPI_PORT_ONLINE) {
11738 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
11739 FCF_REASON_REQUESTED, 0, arg1);
11740
11741 } else if (vpip->flag & EMLXS_VPI_LOGI) {
11742 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
11743 FCF_REASON_REQUESTED, 0, arg1);
11744
11745 } else if (vpip->flag & EMLXS_VPI_REG) {
11746 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
11747 FCF_REASON_REQUESTED, 0, arg1);
11748
11749 } else if (vpip->flag & EMLXS_VPI_INIT) {
11750 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
11751 FCF_REASON_REQUESTED, 0, arg1);
11752
11753 } else {
11754 rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
11755 FCF_REASON_REQUESTED, 0, arg1);
11756 }
11757
11758 return (rval);
11759
11760 } /* emlxs_vpi_offline_handler() */
11761
11762
11763 /*ARGSUSED*/
11764 static uint32_t
emlxs_vpi_offline_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11765 emlxs_vpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11766 void *arg1)
11767 {
11768 uint32_t rval = 0;
11769 uint32_t pause_req;
11770
11771 if (evt != FCF_EVENT_VPI_OFFLINE) {
11772 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11773 "vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. "
11774 "Invalid event type. <",
11775 vpip->VPI,
11776 emlxs_vpi_state_xlate(vpip->state),
11777 emlxs_fcf_event_xlate(evt), arg1,
11778 vpip->flag);
11779 return (1);
11780 }
11781
11782 if ((vpip->flag & EMLXS_VPI_OFFLINE_REQ) &&
11783 !(vpip->flag & EMLXS_VPI_PAUSE_REQ)) {
11784 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11785 "vpi_offline_evt_action:%d flag=%x. "
11786 "Offline already requested. <",
11787 vpip->VPI,
11788 vpip->flag);
11789 return (1);
11790 }
11791
11792 pause_req = vpip->flag & EMLXS_VPI_PAUSE_REQ;
11793
11794 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11795 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
11796
11797 switch (vpip->state) {
11798 case VPI_STATE_PORT_OFFLINE:
11799 if (pause_req || vpip->rpi_paused) {
11800 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11801 "vpi_offline_evt_action:%d flag=%x. Clear nodes.",
11802 vpip->VPI,
11803 vpip->flag);
11804
11805 vpip->flag |= EMLXS_VPI_PORT_ONLINE;
11806
11807 rval = emlxs_vpi_state(port, vpip,
11808 VPI_STATE_PORT_OFFLINE, FCF_REASON_REENTER, evt,
11809 arg1);
11810
11811 break;
11812 }
11813
11814 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11815 "vpi_offline_evt_action:%d flag=%x. Handling offline.",
11816 vpip->VPI,
11817 vpip->flag);
11818
11819 /* Handle offline now */
11820 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11821 break;
11822
11823 case VPI_STATE_PAUSED:
11824 if (vpip->rpi_paused) {
11825 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11826 "vpi_offline_evt_action:%d flag=%x. Clear nodes.",
11827 vpip->VPI,
11828 vpip->flag);
11829
11830 vpip->flag |= EMLXS_VPI_PORT_ONLINE;
11831
11832 rval = emlxs_vpi_state(port, vpip,
11833 VPI_STATE_PORT_OFFLINE, FCF_REASON_EVENT, evt,
11834 arg1);
11835
11836 break;
11837 }
11838
11839 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11840 "vpi_offline_evt_action:%d flag=%x. Handling offline.",
11841 vpip->VPI,
11842 vpip->flag);
11843
11844 /* Handle offline now */
11845 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11846 break;
11847
11848 /* wait states */
11849 case VPI_STATE_UNREG:
11850 case VPI_STATE_PORT_ONLINE:
11851 case VPI_STATE_LOGI:
11852 case VPI_STATE_INIT:
11853 case VPI_STATE_REG:
11854 case VPI_STATE_ONLINE:
11855 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11856 "vpi_offline_evt_action:%d flag=%x. Handling offline.",
11857 vpip->VPI,
11858 vpip->flag);
11859
11860 /* Handle offline now */
11861 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11862 break;
11863
11864 /* Transitional states */
11865 default:
11866 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11867 "vpi_offline_evt_action:%d flag=%x. <",
11868 vpip->VPI,
11869 vpip->flag);
11870 break;
11871 }
11872
11873 return (rval);
11874
11875 } /* emlxs_vpi_offline_evt_action() */
11876
11877
11878 /*ARGSUSED*/
11879 static uint32_t
emlxs_vpi_pause_evt_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)11880 emlxs_vpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
11881 void *arg1)
11882 {
11883 emlxs_hba_t *hba = HBA;
11884 uint32_t rval = 0;
11885
11886 if (evt != FCF_EVENT_VPI_PAUSE) {
11887 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
11888 "vpi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
11889 "Invalid event type. <",
11890 vpip->VPI,
11891 emlxs_vpi_state_xlate(vpip->state),
11892 emlxs_fcf_event_xlate(evt), arg1,
11893 vpip->flag);
11894 return (1);
11895 }
11896
11897 if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
11898 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11899 "vpi_pause_evt_action:%d flag=%x. "
11900 "Pause already requested. <",
11901 vpip->VPI,
11902 vpip->flag);
11903 return (1);
11904 }
11905
11906 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
11907 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11908 "vpi_pause_evt_action:%d flag=%x. "
11909 "Offline already requested. <",
11910 vpip->VPI,
11911 vpip->flag);
11912 return (1);
11913 }
11914
11915 if (SLI4_FC_MODE || !(hba->sli.sli4.flag & EMLXS_SLI4_DOWN_LINK)) {
11916 /* Fabric logo is implied */
11917 emlxs_vpi_logo_handler(port, vpip);
11918 }
11919
11920 switch (vpip->state) {
11921 case VPI_STATE_PORT_OFFLINE:
11922 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11923 "vpi_pause_evt_action:%d flag=%x. "
11924 "Already offline. <",
11925 vpip->VPI,
11926 vpip->flag);
11927 break;
11928
11929 case VPI_STATE_PAUSED:
11930 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11931 "vpi_pause_evt_action:%d flag=%x. "
11932 "Already paused. <",
11933 vpip->VPI,
11934 vpip->flag);
11935 break;
11936
11937 /* Wait states */
11938 case VPI_STATE_UNREG:
11939 case VPI_STATE_PORT_ONLINE:
11940 case VPI_STATE_LOGI:
11941 case VPI_STATE_INIT:
11942 case VPI_STATE_REG:
11943 case VPI_STATE_ONLINE:
11944 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11945 vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
11946
11947 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11948 "vpi_pause_evt_action:%d flag=%x. Handling offline.",
11949 vpip->VPI,
11950 vpip->flag);
11951
11952 /* Handle offline now */
11953 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
11954 break;
11955
11956 /* Transitional states */
11957 default:
11958 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
11959 vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
11960
11961 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
11962 "vpi_pause_evt_action:%d flag=%x. <",
11963 vpip->VPI,
11964 vpip->flag);
11965 break;
11966 }
11967
11968 return (rval);
11969
11970 } /* emlxs_vpi_pause_evt_action() */
11971
11972
11973 /* ARGSUSED */
11974 static void
emlxs_deferred_cmpl_thread(emlxs_hba_t * hba,void * arg1,void * arg2)11975 emlxs_deferred_cmpl_thread(emlxs_hba_t *hba,
11976 void *arg1, void *arg2)
11977 {
11978 emlxs_deferred_cmpl_t *cmpl = (emlxs_deferred_cmpl_t *)arg1;
11979 uint32_t status = (uint32_t)((unsigned long)arg2);
11980 emlxs_port_t *port;
11981 uint32_t mbxStatus;
11982 emlxs_buf_t *sbp;
11983 fc_unsol_buf_t *ubp;
11984 IOCBQ *iocbq;
11985
11986 mbxStatus = (status)? MBX_FAILURE:MBX_SUCCESS;
11987
11988 port = cmpl->port;
11989 sbp = (emlxs_buf_t *)cmpl->arg1;
11990 ubp = (fc_unsol_buf_t *)cmpl->arg2;
11991 iocbq = (IOCBQ *)cmpl->arg3;
11992
11993 kmem_free(cmpl, sizeof (emlxs_deferred_cmpl_t));
11994
11995 emlxs_mb_deferred_cmpl(port, mbxStatus, sbp, ubp, iocbq);
11996
11997 return;
11998
11999 } /* emlxs_deferred_cmpl_thread() */
12000
12001
12002
12003
12004 /* ARGSUSED */
12005 static void
emlxs_port_offline_thread(emlxs_hba_t * hba,void * arg1,void * arg2)12006 emlxs_port_offline_thread(emlxs_hba_t *hba,
12007 void *arg1, void *arg2)
12008 {
12009 emlxs_port_t *port = (emlxs_port_t *)arg1;
12010 uint32_t scope = (uint32_t)((unsigned long)arg2);
12011
12012 (void) emlxs_port_offline(port, scope);
12013 return;
12014
12015 } /* emlxs_port_offline_thread() */
12016
12017
12018 /* ARGSUSED */
12019 static void
emlxs_port_online_thread(emlxs_hba_t * hba,void * arg1,void * arg2)12020 emlxs_port_online_thread(emlxs_hba_t *hba,
12021 void *arg1, void *arg2)
12022 {
12023 emlxs_port_t *port = (emlxs_port_t *)arg1;
12024
12025 (void) emlxs_port_online(port);
12026 return;
12027
12028 } /* emlxs_port_online_thread() */
12029
12030
12031 /*ARGSUSED*/
12032 static void
emlxs_vpi_logo_handler(emlxs_port_t * port,VPIobj_t * vpip)12033 emlxs_vpi_logo_handler(emlxs_port_t *port, VPIobj_t *vpip)
12034 {
12035 vpip->flag &= ~EMLXS_VPI_LOGI;
12036 if (vpip->flag & EMLXS_VPI_VFI_LOGI) {
12037 vpip->flag &= ~EMLXS_VPI_VFI_LOGI;
12038
12039 if (vpip->vfip->logi_count) {
12040 vpip->vfip->logi_count--;
12041 }
12042 if (vpip == vpip->vfip->flogi_vpip) {
12043 vpip->vfip->flogi_vpip = NULL;
12044 }
12045 }
12046
12047 } /* emlxs_vpi_logo_handler() */
12048
12049
12050 /*ARGSUSED*/
12051 static uint32_t
emlxs_vpi_port_offline_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12052 emlxs_vpi_port_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12053 void *arg1)
12054 {
12055 emlxs_hba_t *hba = HBA;
12056 uint32_t rval = 0;
12057 uint32_t scope;
12058
12059 if (vpip->state != VPI_STATE_PORT_OFFLINE) {
12060 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12061 "vpi_port_offline_action:%d %s:%s arg=%p. "
12062 "Invalid state. <",
12063 vpip->VPI,
12064 emlxs_vpi_state_xlate(vpip->state),
12065 emlxs_fcf_event_xlate(evt), arg1);
12066 return (1);
12067 }
12068
12069 if (vpip->flag & EMLXS_VPI_PORT_ONLINE) {
12070 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12071 "vpi_port_offline_action:%d flag=%x. Offlining port...",
12072 vpip->VPI,
12073 vpip->flag);
12074
12075 vpip->flag &= ~(EMLXS_VPI_PORT_ONLINE|EMLXS_VPI_PORT_ENABLED);
12076
12077 if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
12078 scope = 0xFFFFFFFF; /* Clear all non-FCP2 nodes */
12079 /* Pause FCP2 nodes */
12080 } else {
12081 scope = 0xFDFFFFFF; /* Clear all nodes */
12082 }
12083
12084 emlxs_thread_spawn(hba, emlxs_port_offline_thread,
12085 (void *)vpip->port, (void *)((unsigned long)scope));
12086
12087 if (vpip->flag & EMLXS_VPI_LOGI) {
12088 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
12089 FCF_REASON_EVENT, evt, arg1);
12090
12091 return (rval);
12092 }
12093 }
12094
12095 if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
12096 if (vpip->rpi_online > vpip->rpi_paused) {
12097 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12098 "vpi_port_offline_action:%d rpi_online=%d,%d. "
12099 "Pausing. Waiting for RPI's. <",
12100 vpip->VPI,
12101 vpip->rpi_online, vpip->rpi_paused);
12102 return (0);
12103 }
12104
12105 /* Take the Fabric RPI offline now */
12106 if (vpip->fabric_rpip->state != RPI_STATE_FREE) {
12107 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12108 "vpi_port_offline_action:%d. "
12109 "Offlining Fabric RPI. >",
12110 vpip->VPI);
12111
12112 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
12113 vpip->fabric_rpip);
12114 }
12115
12116 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12117 "vpi_port_offline_action:%d rpi_online=%d,%d. Pausing.",
12118 vpip->VPI,
12119 vpip->rpi_online, vpip->rpi_paused);
12120
12121 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED,
12122 FCF_REASON_EVENT, evt, arg1);
12123
12124 return (rval);
12125 }
12126
12127 if (vpip->rpi_online > 0) {
12128 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12129 "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. "
12130 "Waiting for RPI's. <",
12131 vpip->VPI,
12132 vpip->rpi_online, vpip->rpi_paused);
12133
12134 return (0);
12135 }
12136
12137 /* Take the Fabric RPI offline now */
12138 if (vpip->fabric_rpip->state != RPI_STATE_FREE) {
12139 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12140 "vpi_port_offline_action:%d. Offlining Fabric RPI. >",
12141 vpip->VPI);
12142
12143 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
12144 vpip->fabric_rpip);
12145 }
12146
12147 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12148 "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. "
12149 "Unreg VPI.",
12150 vpip->VPI,
12151 vpip->rpi_online, vpip->rpi_paused);
12152
12153 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
12154 FCF_REASON_EVENT, evt, arg1);
12155
12156 return (rval);
12157
12158 } /* emlxs_vpi_port_offline_action() */
12159
12160
12161 /*ARGSUSED*/
12162 static uint32_t
emlxs_vpi_paused_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12163 emlxs_vpi_paused_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12164 void *arg1)
12165 {
12166 if (vpip->state != VPI_STATE_PAUSED) {
12167 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12168 "vpi_paused_action:%d %s:%s arg=%p. "
12169 "Invalid state. <",
12170 vpip->VPI,
12171 emlxs_vpi_state_xlate(vpip->state),
12172 emlxs_fcf_event_xlate(evt), arg1);
12173 return (1);
12174 }
12175
12176 vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
12177
12178 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12179 "vpi_paused_action:%d rpi_online=%d,%d. VPI paused. <",
12180 vpip->VPI,
12181 vpip->rpi_online, vpip->rpi_paused);
12182
12183 return (0);
12184
12185 } /* emlxs_vpi_paused_action() */
12186
12187
12188 /*ARGSUSED*/
12189 static uint32_t
emlxs_vpi_offline_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12190 emlxs_vpi_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12191 void *arg1)
12192 {
12193 uint32_t rval = 0;
12194
12195 if (vpip->state != VPI_STATE_OFFLINE) {
12196 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12197 "vpi_offline_action:%d %s:%s arg=%p. "
12198 "Invalid state. <",
12199 vpip->VPI,
12200 emlxs_vpi_state_xlate(vpip->state),
12201 emlxs_fcf_event_xlate(evt), arg1);
12202 return (1);
12203 }
12204
12205 if (!vpip->vfip) {
12206 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12207 "vpi_offline_action:%d %s:%s arg=%p flag=%x. "
12208 "Null vfip found. <",
12209 vpip->VPI,
12210 emlxs_vpi_state_xlate(vpip->state),
12211 emlxs_fcf_event_xlate(evt), arg1,
12212 vpip->flag);
12213 return (1);
12214 }
12215
12216 /* Take the Fabric RPI offline, if still active */
12217 if (vpip->fabric_rpip->state != RPI_STATE_FREE) {
12218 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12219 "vpi_offline_action:%d. Offlining Fabric RPI. >",
12220 vpip->VPI);
12221
12222 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE,
12223 vpip->fabric_rpip);
12224 }
12225
12226 vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ);
12227
12228 if (vpip->flag & EMLXS_VPI_VFI) {
12229 vpip->flag &= ~EMLXS_VPI_VFI;
12230
12231 if (vpip->vfip->vpi_online) {
12232 vpip->vfip->vpi_online--;
12233 }
12234 }
12235
12236 /* Check if online was requested */
12237 if (vpip->flag & EMLXS_VPI_ONLINE_REQ) {
12238 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12239 "vpi_offline_action:%d vpi_online=%d. Online requested.",
12240 vpip->VPI,
12241 vpip->vfip->vpi_online);
12242
12243 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
12244 FCF_REASON_REQUESTED, 0, arg1);
12245 return (rval);
12246 }
12247
12248 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12249 "vpi_offline_action:%d vpi_online=%d. "
12250 "VPI offline. Notifying VFI:%d. >",
12251 vpip->VPI,
12252 vpip->vfip->vpi_online,
12253 vpip->vfip->VFI);
12254
12255 /* Notify VFI */
12256 rval = emlxs_vfi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
12257
12258 return (rval);
12259
12260 } /* emlxs_vpi_offline_action() */
12261
12262
12263 /*ARGSUSED*/
12264 static uint32_t
emlxs_vpi_init_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)12265 emlxs_vpi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
12266 {
12267 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
12268 VPIobj_t *vpip;
12269 MAILBOX4 *mb4;
12270
12271 vpip = (VPIobj_t *)mbq->context;
12272 mb4 = (MAILBOX4 *)mbq;
12273
12274 mutex_enter(&EMLXS_FCF_LOCK);
12275
12276 if (vpip->state != VPI_STATE_INIT) {
12277 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12278 "vpi_init_mbcmpl:%d %s.",
12279 vpip->VPI,
12280 emlxs_vpi_state_xlate(vpip->state));
12281
12282 mutex_exit(&EMLXS_FCF_LOCK);
12283 return (0);
12284 }
12285
12286 if (mb4->mbxStatus) {
12287 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12288 "vpi_init_mbcmpl:%d failed. %s. >",
12289 vpip->VPI,
12290 emlxs_mb_xlate_status(mb4->mbxStatus));
12291
12292 (void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED,
12293 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
12294
12295 mutex_exit(&EMLXS_FCF_LOCK);
12296 return (0);
12297 }
12298
12299 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12300 "vpi_init_mbcmpl:%d. Init complete. >",
12301 vpip->VPI,
12302 mb4->mbxStatus);
12303
12304 vpip->flag |= EMLXS_VPI_INIT;
12305 (void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL,
12306 0, 0, 0);
12307
12308 mutex_exit(&EMLXS_FCF_LOCK);
12309 return (0);
12310
12311 } /* emlxs_vpi_init_mbcmpl() */
12312
12313
12314 /*ARGSUSED*/
12315 static uint32_t
emlxs_vpi_init_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12316 emlxs_vpi_init_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12317 void *arg1)
12318 {
12319 emlxs_hba_t *hba = HBA;
12320 MAILBOXQ *mbq;
12321 MAILBOX4 *mb4;
12322 uint32_t rval = 0;
12323
12324 if (vpip->state != VPI_STATE_INIT) {
12325 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12326 "vpi_init_action:%d %s:%s arg=%p. "
12327 "Invalid state. <",
12328 vpip->VPI,
12329 emlxs_vpi_state_xlate(vpip->state),
12330 emlxs_fcf_event_xlate(evt), arg1);
12331 return (1);
12332 }
12333
12334 if (vpip->prev_state != VPI_STATE_INIT_FAILED) {
12335 vpip->attempts = 0;
12336 }
12337
12338 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
12339 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12340 "vpi_init_action:%d attempts=%d. Offline requested.",
12341 vpip->VPI,
12342 vpip->attempts);
12343
12344 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12345 return (rval);
12346 }
12347
12348 if (!(vpip->flag & EMLXS_VPI_VFI)) {
12349 vpip->flag |= EMLXS_VPI_VFI;
12350 vpip->vfip->vpi_online++;
12351 }
12352
12353 if (((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) ==
12354 SLI_INTF_IF_TYPE_0) && (vpip->vfip->vpi_online == 1)) {
12355 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12356 "vpi_init_action:%d. First VPI. Skipping INIT_VPI.",
12357 vpip->VPI);
12358
12359 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
12360 FCF_REASON_EVENT, evt, arg1);
12361 return (rval);
12362 }
12363
12364 if (vpip->flag & EMLXS_VPI_INIT) {
12365 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12366 "vpi_init_action:%d flag=%x. "
12367 "Already init'd. Skipping INIT_VPI.",
12368 vpip->VPI);
12369
12370 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
12371 FCF_REASON_EVENT, evt, arg1);
12372 return (rval);
12373 }
12374
12375 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12376 "vpi_init_action:%d vpi_online=%d attempts=%d. Sending INIT_VPI. <",
12377 vpip->VPI,
12378 vpip->vfip->vpi_online,
12379 vpip->attempts);
12380
12381 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
12382 rval = emlxs_vpi_state(port, vpip, FCFI_STATE_REG_FAILED,
12383 FCF_REASON_NO_MBOX, 0, arg1);
12384 return (rval);
12385 }
12386 mb4 = (MAILBOX4*)mbq;
12387 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
12388
12389 mbq->nonembed = NULL;
12390 mbq->mbox_cmpl = emlxs_vpi_init_mbcmpl;
12391 mbq->context = (void *)vpip;
12392 mbq->port = (void *)port;
12393
12394 mb4->mbxCommand = MBX_INIT_VPI;
12395 mb4->mbxOwner = OWN_HOST;
12396 mb4->un.varInitVPI4.vfi = vpip->vfip->VFI;
12397 mb4->un.varInitVPI4.vpi = vpip->VPI;
12398
12399 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
12400 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
12401 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
12402
12403 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED,
12404 FCF_REASON_SEND_FAILED, rval, arg1);
12405
12406 return (rval);
12407 }
12408
12409 return (0);
12410
12411 } /* emlxs_vpi_init_action() */
12412
12413
12414 /*ARGSUSED*/
12415 static uint32_t
emlxs_vpi_init_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12416 emlxs_vpi_init_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12417 void *arg1)
12418 {
12419 uint32_t rval = 0;
12420
12421 vpip->attempts++;
12422
12423 if (vpip->state != VPI_STATE_INIT_FAILED) {
12424 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12425 "vpi_init_action:%d %s:%s arg=%p attempt=%d. "
12426 "Invalid state. <",
12427 vpip->VPI,
12428 emlxs_vpi_state_xlate(vpip->state),
12429 emlxs_fcf_event_xlate(evt), arg1,
12430 vpip->attempts);
12431 return (1);
12432 }
12433
12434 if ((vpip->reason == FCF_REASON_SEND_FAILED) ||
12435 (vpip->attempts >= 3)) {
12436 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12437 "vpi_init_action:%d attempt=%d reason=%x. Init cmpl.",
12438 vpip->VPI,
12439 vpip->attempts,
12440 vpip->reason);
12441
12442 vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
12443
12444 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
12445 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
12446 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL,
12447 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
12448 } else {
12449 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12450 "vpi_init_action:%d attempt=%d. Initializing.",
12451 vpip->VPI,
12452 vpip->attempts);
12453
12454 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT,
12455 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
12456 }
12457
12458 return (rval);
12459
12460 } /* emlxs_vpi_init_failed_action() */
12461
12462
12463 /*ARGSUSED*/
12464 static uint32_t
emlxs_vpi_init_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12465 emlxs_vpi_init_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12466 void *arg1)
12467 {
12468 uint32_t rval = 0;
12469
12470 if (vpip->state != VPI_STATE_INIT_CMPL) {
12471 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12472 "vpi_init_cmpl_action:%d %s:%s arg=%p. "
12473 "Invalid state. <",
12474 vpip->VPI,
12475 emlxs_vpi_state_xlate(vpip->state),
12476 emlxs_fcf_event_xlate(evt), arg1);
12477 return (1);
12478 }
12479
12480 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12481 "vpi_init_cmpl_action:%d attempts=%d. Onlining port.",
12482 vpip->VPI,
12483 vpip->attempts);
12484
12485 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE,
12486 FCF_REASON_EVENT, evt, arg1);
12487 return (rval);
12488
12489 } /* emlxs_vpi_init_cmpl_action() */
12490
12491
12492 /*ARGSUSED*/
12493 static uint32_t
emlxs_vpi_port_online_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12494 emlxs_vpi_port_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12495 void *arg1)
12496 {
12497 emlxs_hba_t *hba = HBA;
12498 emlxs_config_t *cfg = &CFG;
12499 uint32_t rval = 0;
12500
12501 if (vpip->state != VPI_STATE_PORT_ONLINE) {
12502 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12503 "vpi_port_online_action:%d %s:%s arg=%p. "
12504 "Invalid state. <",
12505 vpip->VPI,
12506 emlxs_vpi_state_xlate(vpip->state),
12507 emlxs_fcf_event_xlate(evt), arg1);
12508 return (1);
12509 }
12510
12511 if (vpip->flag & EMLXS_VPI_PORT_ONLINE) {
12512 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12513 "vpi_port_online_action:%d. Port already online.",
12514 vpip->VPI);
12515 }
12516
12517 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
12518 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12519 "vpi_port_online_action:%d. Offline requested.",
12520 vpip->VPI);
12521
12522 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12523 return (rval);
12524 }
12525
12526 /* Initialize the Fabric RPI */
12527 if (vpip->fabric_rpip->state == RPI_STATE_FREE) {
12528 emlxs_rpi_alloc_fabric_rpi(vpip->port);
12529 }
12530
12531 /* Notify ULP */
12532 vpip->flag |= EMLXS_VPI_PORT_ONLINE;
12533
12534 if (hba->flag & FC_LOOPBACK_MODE) {
12535 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12536 "vpi_port_online_action:%d. Loopback mode. "
12537 "Registering VPI.",
12538 vpip->VPI);
12539
12540 if (hba->topology != TOPOLOGY_LOOP) {
12541 port->did = 1;
12542 }
12543
12544 vpip->vfip->flogi_vpip = vpip;
12545
12546 bcopy((void *)&vpip->port->sparam,
12547 (void *)&vpip->fabric_rpip->sparam,
12548 sizeof (SERV_PARM));
12549
12550 /* Update the VPI Fabric RPI */
12551 vpip->fabric_rpip->sparam.cmn.w2.r_a_tov =
12552 LE_SWAP32((FF_DEF_RATOV * 1000));
12553
12554 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
12555 FCF_REASON_EVENT, evt, arg1);
12556
12557 return (rval);
12558 }
12559
12560 if ((hba->topology == TOPOLOGY_LOOP) && ! (port->did)) {
12561 port->did = port->granted_alpa;
12562 }
12563
12564 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12565 "vpi_port_online_action:%d vpi_online=%d. Onlining port... <",
12566 vpip->VPI,
12567 vpip->vfip->vpi_online);
12568
12569 if (SLI4_FC_MODE && (port->vpi == 0)) {
12570 mutex_enter(&EMLXS_PORT_LOCK);
12571 hba->linkup_timer = hba->timer_tics +
12572 cfg[CFG_LINKUP_TIMEOUT].current;
12573 mutex_exit(&EMLXS_PORT_LOCK);
12574 } else {
12575 emlxs_thread_spawn(hba, emlxs_port_online_thread,
12576 (void *)vpip->port, 0);
12577 }
12578
12579 /* Wait for emlxs_vpi_logi_notify() */
12580
12581 return (0);
12582
12583 } /* emlxs_vpi_port_online_action() */
12584
12585
12586 extern uint32_t
emlxs_vpi_logi_notify(emlxs_port_t * port,emlxs_buf_t * sbp)12587 emlxs_vpi_logi_notify(emlxs_port_t *port, emlxs_buf_t *sbp)
12588 {
12589 VPIobj_t *vpip = port->vpip;
12590 emlxs_hba_t *hba = HBA;
12591 uint32_t rval = 0;
12592
12593 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
12594 return (1);
12595 }
12596
12597 mutex_enter(&EMLXS_FCF_LOCK);
12598
12599 if (vpip->state == VPI_STATE_OFFLINE) {
12600 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12601 "vpi_logi_notify:%d %s.",
12602 vpip->VPI,
12603 emlxs_vpi_state_xlate(vpip->state));
12604
12605 mutex_exit(&EMLXS_FCF_LOCK);
12606
12607 return (1);
12608 }
12609
12610 if (vpip->state != VPI_STATE_PORT_ONLINE) {
12611 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12612 "vpi_logi_notify:%d %s. "
12613 "Invalid state.",
12614 vpip->VPI,
12615 emlxs_vpi_state_xlate(vpip->state));
12616
12617 mutex_exit(&EMLXS_FCF_LOCK);
12618
12619 return (1);
12620 }
12621
12622 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12623 "vpi_logi_notify:%d %s. "
12624 "Logging in. >",
12625 vpip->VPI,
12626 emlxs_vpi_state_xlate(vpip->state));
12627
12628 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI,
12629 0, 0, sbp);
12630
12631 if (rval) {
12632 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12633 "vpi_logi_notify:%d %s rval=%d.",
12634 vpip->VPI,
12635 emlxs_vpi_state_xlate(vpip->state),
12636 rval);
12637 }
12638
12639 mutex_exit(&EMLXS_FCF_LOCK);
12640
12641 return (rval);
12642
12643 } /* emlxs_vpi_logi_notify() */
12644
12645
12646 static uint32_t
emlxs_vpi_logi_cmpl_notify(emlxs_port_t * port,RPIobj_t * rpip)12647 emlxs_vpi_logi_cmpl_notify(emlxs_port_t *port, RPIobj_t *rpip)
12648 {
12649 emlxs_hba_t *hba = HBA;
12650 VPIobj_t *vpip = port->vpip;
12651 uint32_t rval = 0;
12652
12653 /* EMLXS_FCF_LOCK must be held when calling this routine */
12654
12655 if (vpip->state != VPI_STATE_LOGI) {
12656 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12657 "vpi_logi_cmpl_notify:%d %s. "
12658 "Invalid state.",
12659 vpip->VPI,
12660 emlxs_vpi_state_xlate(vpip->state));
12661 return (1);
12662 }
12663
12664 if (rpip->RPI == FABRIC_RPI) {
12665 if (hba->flag & FC_PT_TO_PT) {
12666 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12667 "vpi_logi_cmpl_notify:%d %s. P2P mode. "
12668 "Completing FLOGI.",
12669 vpip->VPI,
12670 emlxs_vpi_state_xlate(vpip->state));
12671
12672 /* Complete the FLOGI/FDISC now */
12673 if (rpip->cmpl) {
12674 emlxs_rpi_deferred_cmpl(port, rpip, 0);
12675 }
12676
12677 /* Wait for P2P PLOGI completion to continue */
12678 return (0);
12679 }
12680
12681 if (!rpip->cmpl || !rpip->cmpl->arg1) {
12682 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12683 "vpi_logi_cmpl_notify:%d. Null sbp.",
12684 vpip->VPI);
12685 return (1);
12686 }
12687
12688 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12689 "vpi_logi_cmpl_notify:%d %s. Fabric mode. "
12690 "Completing login. >",
12691 vpip->VPI,
12692 emlxs_vpi_state_xlate(vpip->state));
12693
12694 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_CMPL,
12695 0, 0, 0);
12696
12697 if (rval) {
12698 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12699 "vpi_logi_cmpl_notify:%d %s rval=%d.",
12700 vpip->VPI,
12701 emlxs_vpi_state_xlate(vpip->state),
12702 rval);
12703 }
12704
12705 return (rval);
12706 }
12707
12708 if (hba->flag & FC_PT_TO_PT) {
12709 if (port->did == 0) {
12710 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12711 "vpi_logi_cmpl_notify:%d %s did=0. P2P mode. "
12712 "Wait for PLOGI compl.",
12713 vpip->VPI,
12714 emlxs_vpi_state_xlate(vpip->state));
12715
12716 if (rpip->cmpl) {
12717 emlxs_rpi_deferred_cmpl(port, rpip, 0);
12718 }
12719
12720 /* Wait for P2P PLOGI completion to continue */
12721 return (0);
12722 }
12723
12724 vpip->p2p_rpip = rpip;
12725
12726 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12727 "vpi_logi_cmpl_notify:%d %s. P2P mode. "
12728 "Completing login. >",
12729 vpip->VPI,
12730 emlxs_vpi_state_xlate(vpip->state));
12731
12732 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_CMPL,
12733 0, 0, 0);
12734
12735 if (rval) {
12736 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12737 "vpi_logi_cmpl_notify:%d %s rval=%d.",
12738 vpip->VPI,
12739 emlxs_vpi_state_xlate(vpip->state),
12740 rval);
12741 }
12742
12743 return (rval);
12744 }
12745
12746 return (1);
12747
12748 } /* emlxs_vpi_logi_cmpl_notify() */
12749
12750
12751 extern uint32_t
emlxs_vpi_logi_failed_notify(emlxs_port_t * port,emlxs_buf_t * sbp)12752 emlxs_vpi_logi_failed_notify(emlxs_port_t *port, emlxs_buf_t *sbp)
12753 {
12754 emlxs_hba_t *hba = HBA;
12755 VPIobj_t *vpip = port->vpip;
12756 RPIobj_t *rpip = vpip->fabric_rpip;
12757 uint32_t rval = 0;
12758 emlxs_deferred_cmpl_t *cmpl;
12759
12760 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
12761 return (1);
12762 }
12763
12764 mutex_enter(&EMLXS_FCF_LOCK);
12765
12766 if (vpip->state != VPI_STATE_LOGI) {
12767 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12768 "vpi_logi_failed_notify:%d %s. "
12769 "Invalid state.",
12770 vpip->VPI,
12771 emlxs_vpi_state_xlate(vpip->state));
12772
12773 /* Fabric logo is implied */
12774 emlxs_vpi_logo_handler(port, vpip);
12775
12776 mutex_exit(&EMLXS_FCF_LOCK);
12777
12778 return (1);
12779 }
12780
12781 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12782 "vpi_logi_failed_notify:%d %s. "
12783 "Failing login. >",
12784 vpip->VPI,
12785 emlxs_vpi_state_xlate(vpip->state));
12786
12787 /* For safety */
12788 if (rpip->cmpl) {
12789 emlxs_rpi_deferred_cmpl(port, rpip, 1);
12790 }
12791
12792 if (sbp) {
12793 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
12794 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
12795
12796 cmpl->port = port;
12797 cmpl->arg1 = (void *)sbp;
12798 cmpl->arg2 = 0;
12799 cmpl->arg3 = 0;
12800
12801 rpip->cmpl = cmpl;
12802 }
12803
12804 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_FAILED,
12805 FCF_REASON_OP_FAILED, 1, 0);
12806
12807 if (rval && rpip->cmpl) {
12808 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
12809 rpip->cmpl = 0;
12810 }
12811
12812 mutex_exit(&EMLXS_FCF_LOCK);
12813 return (rval);
12814
12815 } /* emlxs_vpi_logi_failed_notify() */
12816
12817
12818 extern uint32_t
emlxs_vpi_logo_cmpl_notify(emlxs_port_t * port)12819 emlxs_vpi_logo_cmpl_notify(emlxs_port_t *port)
12820 {
12821 emlxs_hba_t *hba = HBA;
12822 VPIobj_t *vpip = port->vpip;
12823 uint32_t rval = 0;
12824 VFIobj_t *vfip;
12825 FCFIobj_t *fcfp;
12826
12827 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
12828 return (1);
12829 }
12830
12831 mutex_enter(&EMLXS_FCF_LOCK);
12832
12833 /* Fabric logo is complete */
12834 emlxs_vpi_logo_handler(port, vpip);
12835
12836 if ((vpip->state == VPI_STATE_OFFLINE) ||
12837 (vpip->flag & EMLXS_VPI_OFFLINE_REQ)) {
12838 /* Already offline. Do nothing */
12839 mutex_exit(&EMLXS_FCF_LOCK);
12840 return (0);
12841 }
12842
12843 vfip = vpip->vfip;
12844 fcfp = vfip->fcfp;
12845
12846 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12847 "vpi_logo_cmpl_notify:%d %s fcfi:%d vfi:%d. "
12848 "Offlining VPI:%d,%d >",
12849 vpip->VPI,
12850 emlxs_vpi_state_xlate(vpip->state),
12851 fcfp->fcf_index,
12852 vfip->VFI,
12853 vpip->index, vpip->VPI);
12854
12855 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip);
12856
12857 mutex_exit(&EMLXS_FCF_LOCK);
12858
12859 return (rval);
12860
12861 } /* emlxs_vpi_logo_cmpl_notify() */
12862
12863
12864 /*ARGSUSED*/
12865 static uint32_t
emlxs_vpi_logi_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12866 emlxs_vpi_logi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12867 void *arg1)
12868 {
12869 emlxs_hba_t *hba = HBA;
12870 emlxs_buf_t *sbp = (emlxs_buf_t *)arg1;
12871 fc_packet_t *pkt = PRIV2PKT(sbp);
12872 uint32_t rval = 0;
12873
12874 if (vpip->state != VPI_STATE_LOGI) {
12875 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12876 "vpi_logi_action:%d %s:%s arg=%p. "
12877 "Invalid state. <",
12878 vpip->VPI,
12879 emlxs_vpi_state_xlate(vpip->state),
12880 emlxs_fcf_event_xlate(evt), arg1);
12881 return (1);
12882 }
12883
12884 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
12885 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12886 "vpi_logi_action:%d. Offline requested.",
12887 vpip->VPI);
12888
12889 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12890 return (rval);
12891 }
12892
12893 if (vpip->flag & EMLXS_VPI_LOGI) {
12894 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
12895 "vpi_logi_action:%d flag=%x. LOGI already set.",
12896 vpip->VPI, vpip->flag);
12897
12898 /* Fabric logo is implied */
12899 emlxs_vpi_logo_handler(port, vpip);
12900 }
12901
12902 /* Check if FC_PT_TO_PT is set */
12903 if (hba->flag & FC_PT_TO_PT) {
12904 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12905 "vpi_logi_action:%d logi_count=%d. FLOGI set. P2P. <",
12906 vpip->VPI,
12907 vpip->vfip->logi_count);
12908
12909 *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FLOGI;
12910
12911 vpip->vfip->flogi_vpip = vpip;
12912
12913 if (vpip->vfip->logi_count == 0) {
12914 vpip->vfip->logi_count++;
12915 vpip->flag |= EMLXS_VPI_VFI_LOGI;
12916 }
12917
12918 return (0);
12919 }
12920
12921 /* Set login command based on vfi logi_count */
12922 if (vpip->vfip->logi_count == 0) {
12923 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12924 "vpi_logi_action:%d logi_count=%d. FLOGI set. <",
12925 vpip->VPI,
12926 vpip->vfip->logi_count);
12927
12928 *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FLOGI;
12929
12930 vpip->vfip->flogi_vpip = vpip;
12931 } else {
12932 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12933 "vpi_logi_action:%d logi_count=%d. FDISC set. <",
12934 vpip->VPI,
12935 vpip->vfip->logi_count);
12936
12937 *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FDISC;
12938 }
12939
12940 vpip->vfip->logi_count++;
12941 vpip->flag |= EMLXS_VPI_VFI_LOGI;
12942
12943 return (0);
12944
12945 } /* emlxs_vpi_logi_action() */
12946
12947
12948 /*ARGSUSED*/
12949 static uint32_t
emlxs_vpi_logi_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)12950 emlxs_vpi_logi_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
12951 void *arg1)
12952 {
12953 emlxs_hba_t *hba = HBA;
12954 uint32_t rval = 0;
12955
12956 if (vpip->state != VPI_STATE_LOGI_FAILED) {
12957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12958 "vpi_logi_failed_action:%d %s:%s arg=%p. "
12959 "Invalid state. <",
12960 vpip->VPI,
12961 emlxs_vpi_state_xlate(vpip->state),
12962 emlxs_fcf_event_xlate(evt), arg1);
12963 return (1);
12964 }
12965
12966 /* Fabric logo is implied */
12967 emlxs_vpi_logo_handler(port, vpip);
12968
12969 if (hba->topology == TOPOLOGY_LOOP) {
12970 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12971 "vpi_logi_failed_action:%d. Private loop. "
12972 "Registering VPI.",
12973 vpip->VPI);
12974
12975 /* Update the VPI flogi_vpip pointer for loop */
12976 /* because the vpi_logo_handler cleared it */
12977 vpip->vfip->flogi_vpip = vpip;
12978
12979 bcopy((void *)&vpip->port->sparam,
12980 (void *)&vpip->fabric_rpip->sparam,
12981 sizeof (SERV_PARM));
12982
12983 /* Update the VPI Fabric RPI */
12984 vpip->fabric_rpip->sparam.cmn.w2.r_a_tov =
12985 LE_SWAP32((FF_DEF_RATOV * 1000));
12986
12987 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
12988 FCF_REASON_EVENT, evt, arg1);
12989 return (rval);
12990 }
12991
12992 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
12993 "vpi_logi_failed_action:%d. Requesting offline.",
12994 vpip->VPI);
12995
12996 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
12997 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
12998 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
12999
13000 return (rval);
13001
13002 } /* emlxs_vpi_logi_failed_action() */
13003
13004
13005 /*ARGSUSED*/
13006 static uint32_t
emlxs_vpi_logi_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13007 emlxs_vpi_logi_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13008 void *arg1)
13009 {
13010 emlxs_hba_t *hba = HBA;
13011 uint32_t rval = 0;
13012 char buffer1[64];
13013 char buffer2[64];
13014 uint32_t new_config = 0;
13015
13016 if (vpip->state != VPI_STATE_LOGI_CMPL) {
13017 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13018 "vpi_logi_cmpl_action:%d %s:%s arg=%p. "
13019 "Invalid state. <",
13020 vpip->VPI,
13021 emlxs_vpi_state_xlate(vpip->state),
13022 emlxs_fcf_event_xlate(evt), arg1);
13023 return (1);
13024 }
13025
13026 vpip->flag |= EMLXS_VPI_LOGI;
13027
13028 /* Check for new fabric */
13029 if (port->prev_did) {
13030 if (SLI4_FCOE_MODE) {
13031 /* Check for FCF change */
13032 if (((port->prev_did != port->did) ||
13033 bcmp(&port->prev_fabric_sparam.portName,
13034 &port->fabric_sparam.portName, 8)) &&
13035 emlxs_nport_count(port)) {
13036 new_config = 1;
13037 }
13038 } else {
13039 uint32_t old_topo;
13040 uint32_t new_topo;
13041
13042 /* Check for topology change (0=loop 1=fabric) */
13043 old_topo = ((port->prev_did && 0xFFFF00) == 0)? 0:1;
13044 new_topo = ((port->did && 0xFFFF00) == 0)? 0:1;
13045
13046 if (old_topo != new_topo) {
13047 new_config = 1;
13048
13049 /* Check for any switch change */
13050 } else if ((port->prev_did != port->did) ||
13051 bcmp(&port->prev_fabric_sparam.portName,
13052 &port->fabric_sparam.portName, 8)) {
13053 new_config = 1;
13054 }
13055 }
13056 }
13057
13058 if (new_config) {
13059 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13060 "vpi_logi_cmpl_action:%d. "
13061 "New config. Offlining port.",
13062 vpip->VPI);
13063
13064 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13065 "vpi_logi_cmpl_action: prev_wwpn=%s wwpn=%s prev_did=%x "
13066 "did=%x.",
13067 emlxs_wwn_xlate(buffer1, sizeof (buffer1),
13068 (uint8_t *)&port->prev_fabric_sparam.portName),
13069 emlxs_wwn_xlate(buffer2, sizeof (buffer2),
13070 (uint8_t *)&port->fabric_sparam.portName),
13071 port->prev_did, port->did);
13072
13073 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
13074 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13075 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13076
13077 return (rval);
13078 }
13079
13080 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13081 "vpi_logi_cmpl_action:%d. Registering.",
13082 vpip->VPI);
13083
13084 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
13085 FCF_REASON_EVENT, evt, arg1);
13086
13087 return (rval);
13088
13089 } /* emlxs_vpi_logi_cmpl_action() */
13090
13091
13092 /*ARGSUSED*/
13093 static uint32_t
emlxs_vpi_logo_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13094 emlxs_vpi_logo_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13095 void *arg1)
13096 {
13097 emlxs_hba_t *hba = HBA;
13098 uint32_t rval = 0;
13099
13100 vpip->attempts++;
13101
13102 if (vpip->state != VPI_STATE_LOGO_FAILED) {
13103 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13104 "vpi_logo_failed_action:%d %s:%s arg=%p attempt=%d. "
13105 "Invalid state. <",
13106 vpip->VPI,
13107 emlxs_vpi_state_xlate(vpip->state),
13108 emlxs_fcf_event_xlate(evt), arg1,
13109 vpip->attempts);
13110 return (1);
13111 }
13112
13113 if (hba->state <= FC_LINK_DOWN) {
13114 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13115 "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.",
13116 vpip->VPI,
13117 vpip->attempts);
13118
13119 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL,
13120 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13121 } else if (vpip->attempts >= 3) {
13122 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13123 "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.",
13124 vpip->VPI,
13125 vpip->attempts);
13126
13127 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL,
13128 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13129 } else {
13130 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13131 "vpi_logo_failed_action:%d attempt=%d. Logging out.",
13132 vpip->VPI,
13133 vpip->attempts);
13134
13135 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO,
13136 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13137 }
13138
13139 return (rval);
13140
13141 } /* emlxs_vpi_logo_failed_action() */
13142
13143
13144 /*ARGSUSED*/
13145 static uint32_t
emlxs_vpi_logo_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13146 emlxs_vpi_logo_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13147 void *arg1)
13148 {
13149 emlxs_hba_t *hba = HBA;
13150 emlxs_port_t *vport = vpip->port;
13151 uint32_t rval = 0;
13152 uint32_t did;
13153 uint32_t sid;
13154 fc_packet_t *pkt;
13155 ELS_PKT *els;
13156
13157 if (vpip->state != VPI_STATE_LOGO) {
13158 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13159 "vpi_logo_action:%d %s:%s arg=%p. "
13160 "Invalid state. <",
13161 vpip->VPI,
13162 emlxs_vpi_state_xlate(vpip->state),
13163 emlxs_fcf_event_xlate(evt), arg1);
13164 return (1);
13165 }
13166
13167 if (!(vpip->flag & EMLXS_VPI_LOGI)) {
13168 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13169 "vpi_logo_action:%d. No login. Skipping LOGO.",
13170 vpip->VPI);
13171
13172 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13173 FCF_REASON_EVENT, evt, arg1);
13174 return (rval);
13175 }
13176
13177 if (!(hba->flag & FC_ONLINE_MODE) &&
13178 !(hba->flag & FC_OFFLINING_MODE)) {
13179 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13180 "vpi_logo_action:%d. HBA offline. Skipping LOGO.",
13181 vpip->VPI);
13182
13183 /* Fabric logo is implied */
13184 emlxs_vpi_logo_handler(port, vpip);
13185
13186 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13187 FCF_REASON_EVENT, evt, arg1);
13188 return (rval);
13189 }
13190
13191 if (SLI4_FC_MODE) {
13192 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13193 "vpi_logo_action:%d. FC mode. Skipping LOGO.",
13194 vpip->VPI);
13195
13196 /* Fabric logo is implied */
13197 emlxs_vpi_logo_handler(port, vpip);
13198
13199 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13200 FCF_REASON_EVENT, evt, arg1);
13201 return (rval);
13202 }
13203
13204 if (vpip->prev_state != VPI_STATE_LOGO_FAILED) {
13205 vpip->attempts = 0;
13206 }
13207
13208 did = FABRIC_DID;
13209 sid = (vport->did)? vport->did:vport->prev_did;
13210
13211 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13212 "vpi_logo_action:%d attempts=%d sid=%x did=%x. Sending LOGO. <",
13213 vpip->VPI,
13214 vpip->attempts,
13215 sid, did);
13216
13217 pkt = emlxs_pkt_alloc(vport,
13218 (sizeof (uint32_t) + sizeof (LOGO)),
13219 (sizeof (uint32_t) + sizeof (LOGO)), 0, KM_NOSLEEP);
13220
13221 if (!pkt) {
13222 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED,
13223 FCF_REASON_NO_PKT, 0, arg1);
13224
13225 return (rval);
13226 }
13227
13228 pkt->pkt_tran_type = FC_PKT_EXCHANGE;
13229 pkt->pkt_timeout = (2 * hba->fc_ratov);
13230
13231 /* Build the fc header */
13232 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
13233 pkt->pkt_cmd_fhdr.r_ctl =
13234 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL;
13235 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid);
13236 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
13237 pkt->pkt_cmd_fhdr.f_ctl =
13238 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
13239 pkt->pkt_cmd_fhdr.seq_id = 0;
13240 pkt->pkt_cmd_fhdr.df_ctl = 0;
13241 pkt->pkt_cmd_fhdr.seq_cnt = 0;
13242 pkt->pkt_cmd_fhdr.ox_id = 0xffff;
13243 pkt->pkt_cmd_fhdr.rx_id = 0xffff;
13244 pkt->pkt_cmd_fhdr.ro = 0;
13245
13246 /* Build the command */
13247 els = (ELS_PKT *)pkt->pkt_cmd;
13248 els->elsCode = 0x05;
13249 els->un.logo.un.nPortId32 = pkt->pkt_cmd_fhdr.s_id;
13250 bcopy((uint8_t *)&vport->wwpn,
13251 (uint8_t *)&els->un.logo.portName, 8);
13252
13253 /* Send the pkt now */
13254 rval = emlxs_pkt_send(pkt, 0);
13255 if (rval != FC_SUCCESS) {
13256 /* Free the pkt */
13257 emlxs_pkt_free(pkt);
13258
13259 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED,
13260 FCF_REASON_SEND_FAILED, rval, arg1);
13261
13262 return (rval);
13263 }
13264
13265 /* For now we will send and forget */
13266 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL,
13267 FCF_REASON_EVENT, evt, arg1);
13268
13269 return (rval);
13270
13271 } /* emlxs_vpi_logo_action() */
13272
13273
13274 /*ARGSUSED*/
13275 static uint32_t
emlxs_vpi_logo_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13276 emlxs_vpi_logo_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13277 void *arg1)
13278 {
13279 uint32_t rval = 0;
13280
13281 if (vpip->state != VPI_STATE_LOGO_CMPL) {
13282 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13283 "vpi_logo_cmpl_action:%d %s:%s arg=%p. "
13284 "Invalid state. <",
13285 vpip->VPI,
13286 emlxs_vpi_state_xlate(vpip->state),
13287 emlxs_fcf_event_xlate(evt), arg1);
13288 return (1);
13289 }
13290
13291 /* Fabric logo is complete */
13292 emlxs_vpi_logo_handler(port, vpip);
13293
13294 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13295 "vpi_logo_cmpl_action:%d attempts=%d. Offline RPI's.",
13296 vpip->VPI,
13297 vpip->attempts);
13298
13299 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13300 FCF_REASON_EVENT, evt, arg1);
13301
13302 return (rval);
13303
13304 } /* emlxs_vpi_logo_cmpl_action() */
13305
13306
13307 /*ARGSUSED*/
13308 static uint32_t
emlxs_vpi_unreg_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13309 emlxs_vpi_unreg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13310 void *arg1)
13311 {
13312 uint32_t rval = 0;
13313
13314 vpip->attempts++;
13315
13316 if (vpip->state != VPI_STATE_UNREG_FAILED) {
13317 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13318 "vpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
13319 "Invalid state. <",
13320 vpip->VPI,
13321 emlxs_vpi_state_xlate(vpip->state),
13322 emlxs_fcf_event_xlate(evt), arg1,
13323 vpip->attempts);
13324 return (1);
13325 }
13326
13327 if ((vpip->reason == FCF_REASON_SEND_FAILED) ||
13328 (vpip->attempts >= 3)) {
13329 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13330 "vpi_unreg_failed_action:%d attempt=%d. Unreg cmpl.",
13331 vpip->VPI,
13332 vpip->attempts);
13333
13334 vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
13335
13336 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
13337 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13338 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL,
13339 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13340 } else {
13341 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13342 "vpi_unreg_failed_action:%d attempt=%d. Unregistering.",
13343 vpip->VPI,
13344 vpip->attempts);
13345
13346 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG,
13347 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13348 }
13349
13350 return (rval);
13351
13352 } /* emlxs_vpi_unreg_failed_action() */
13353
13354
13355 /*ARGSUSED*/
13356 static uint32_t
emlxs_vpi_unreg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)13357 emlxs_vpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
13358 {
13359 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
13360 MAILBOX4 *mb4;
13361 VPIobj_t *vpip;
13362
13363 vpip = (VPIobj_t *)mbq->context;
13364 mb4 = (MAILBOX4 *)mbq;
13365
13366 mutex_enter(&EMLXS_FCF_LOCK);
13367
13368 if (vpip->state != VPI_STATE_UNREG) {
13369 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13370 "vpi_unreg_mbcmpl:%d state=%s.",
13371 vpip->VPI,
13372 emlxs_vpi_state_xlate(vpip->state));
13373
13374 mutex_exit(&EMLXS_FCF_LOCK);
13375 return (0);
13376 }
13377
13378 if (mb4->mbxStatus) {
13379 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13380 "vpi_unreg_mbcmpl:%d failed. %s. >",
13381 vpip->VPI,
13382 emlxs_mb_xlate_status(mb4->mbxStatus));
13383
13384 (void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
13385 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
13386
13387 mutex_exit(&EMLXS_FCF_LOCK);
13388 return (0);
13389 }
13390
13391 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13392 "vpi_unreg_mbcmpl:%d. Unreg complete. >",
13393 vpip->VPI);
13394
13395 vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT);
13396 (void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL, 0, 0, 0);
13397
13398 mutex_exit(&EMLXS_FCF_LOCK);
13399 return (0);
13400
13401 } /* emlxs_vpi_unreg_mbcmpl() */
13402
13403
13404 /*ARGSUSED*/
13405 static uint32_t
emlxs_vpi_unreg_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13406 emlxs_vpi_unreg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13407 void *arg1)
13408 {
13409 emlxs_hba_t *hba = HBA;
13410 MAILBOX4 *mb4;
13411 MAILBOXQ *mbq;
13412 uint32_t rval = 0;
13413
13414 if (vpip->state != VPI_STATE_UNREG) {
13415 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13416 "vpi_unreg_action:%d %s:%s arg=%p. "
13417 "Invalid state. <",
13418 vpip->VPI,
13419 emlxs_vpi_state_xlate(vpip->state),
13420 emlxs_fcf_event_xlate(evt), arg1);
13421 return (1);
13422 }
13423
13424 if ((vpip->rpi_online > vpip->rpi_paused) ||
13425 (vpip->fabric_rpip->state != RPI_STATE_FREE)) {
13426 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13427 "vpi_unreg_action:%d rpi_online=%d,%d fstate=%x. "
13428 "Waiting for RPI's.", vpip->VPI, vpip->rpi_online,
13429 vpip->rpi_paused, vpip->fabric_rpip->state);
13430
13431 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE,
13432 FCF_REASON_EVENT, evt, arg1);
13433 return (rval);
13434 }
13435
13436 if (!(vpip->flag & EMLXS_VPI_REG)) {
13437 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13438 "vpi_unreg_action:%d. Not registered. Skipping UNREG_VPI.",
13439 vpip->VPI);
13440
13441 rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
13442 FCF_REASON_EVENT, evt, arg1);
13443 return (rval);
13444 }
13445
13446 if (vpip->flag & EMLXS_VPI_PAUSE_REQ) {
13447 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13448 "vpi_unreg_action:%d rpi_online=%d,%d. Pausing.",
13449 vpip->VPI,
13450 vpip->rpi_online, vpip->rpi_paused);
13451
13452 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED,
13453 FCF_REASON_EVENT, evt, arg1);
13454 return (rval);
13455 }
13456
13457 if (vpip->prev_state != VPI_STATE_UNREG_FAILED) {
13458 vpip->attempts = 0;
13459 }
13460
13461 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13462 "vpi_unreg_action:%d attempts=%d. Sending UNREG_VPI. <",
13463 vpip->VPI,
13464 vpip->attempts);
13465
13466 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
13467 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
13468 FCF_REASON_NO_MBOX, 0, arg1);
13469
13470 return (rval);
13471 }
13472 mb4 = (MAILBOX4*)mbq;
13473 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
13474
13475 mbq->nonembed = NULL;
13476 mbq->mbox_cmpl = emlxs_vpi_unreg_mbcmpl;
13477 mbq->context = (void *)vpip;
13478 mbq->port = (void *)vpip->port;
13479
13480 mb4->un.varUnRegVPI4.ii = 0; /* index is a VPI */
13481 mb4->un.varUnRegVPI4.index = vpip->VPI;
13482 mb4->mbxCommand = MBX_UNREG_VPI;
13483 mb4->mbxOwner = OWN_HOST;
13484
13485 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
13486 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
13487 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
13488
13489 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED,
13490 FCF_REASON_SEND_FAILED, rval, arg1);
13491
13492 return (rval);
13493 }
13494
13495 return (0);
13496
13497 } /* emlxs_vpi_unreg_action() */
13498
13499
13500 /*ARGSUSED*/
13501 static uint32_t
emlxs_vpi_unreg_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13502 emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13503 void *arg1)
13504 {
13505 uint32_t rval = 0;
13506
13507 if (vpip->state != VPI_STATE_UNREG_CMPL) {
13508 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13509 "vpi_unreg_cmpl_action:%d %s:%s arg=%p. "
13510 "Invalid state. <",
13511 vpip->VPI,
13512 emlxs_vpi_state_xlate(vpip->state),
13513 emlxs_fcf_event_xlate(evt), arg1);
13514 return (1);
13515 }
13516
13517 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13518 "vpi_unreg_cmpl_action:%d attempts=%d. Going offline.",
13519 vpip->VPI,
13520 vpip->attempts);
13521
13522 rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE,
13523 FCF_REASON_EVENT, evt, arg1);
13524
13525 return (rval);
13526
13527 } /* emlxs_vpi_unreg_cmpl_action() */
13528
13529
13530 /*ARGSUSED*/
13531 static uint32_t
emlxs_vpi_reg_failed_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13532 emlxs_vpi_reg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13533 void *arg1)
13534 {
13535 uint32_t rval = 0;
13536
13537 vpip->attempts++;
13538
13539 if (vpip->state != VPI_STATE_REG_FAILED) {
13540 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13541 "vpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
13542 "Invalid state. <",
13543 vpip->VPI,
13544 emlxs_vpi_state_xlate(vpip->state),
13545 emlxs_fcf_event_xlate(evt), arg1,
13546 vpip->attempts);
13547 return (1);
13548 }
13549
13550 if ((vpip->reason == FCF_REASON_SEND_FAILED) ||
13551 (vpip->attempts >= 3)) {
13552 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13553 "vpi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.",
13554 vpip->VPI,
13555 vpip->attempts,
13556 vpip->reason);
13557
13558 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
13559 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13560 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL,
13561 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13562 } else {
13563 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13564 "vpi_reg_failed_action:%d attempt=%d. Registering.",
13565 vpip->VPI,
13566 vpip->attempts);
13567
13568 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG,
13569 FCF_REASON_OP_FAILED, vpip->attempts, arg1);
13570 }
13571
13572 return (rval);
13573
13574 } /* emlxs_vpi_reg_failed_action() */
13575
13576
13577 /*ARGSUSED*/
13578 static uint32_t
emlxs_vpi_reg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)13579 emlxs_vpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
13580 {
13581 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
13582 MAILBOX4 *mb4;
13583 VPIobj_t *vpip;
13584
13585 vpip = (VPIobj_t *)mbq->context;
13586 mb4 = (MAILBOX4 *)mbq;
13587
13588 mutex_enter(&EMLXS_FCF_LOCK);
13589
13590 if (vpip->state != VPI_STATE_REG) {
13591 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13592 "vpi_reg_mbcmpl:%d state=%s.",
13593 vpip->VPI,
13594 emlxs_vpi_state_xlate(vpip->state));
13595
13596 mutex_exit(&EMLXS_FCF_LOCK);
13597 return (0);
13598 }
13599
13600 if (mb4->mbxStatus) {
13601 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13602 "vpi_reg_mbcmpl:%d failed. %s. >",
13603 vpip->VPI,
13604 emlxs_mb_xlate_status(mb4->mbxStatus));
13605
13606 if (mb4->mbxStatus == MBXERR_DID_INCONSISTENT) {
13607 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13608 }
13609
13610 (void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
13611 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
13612
13613 mutex_exit(&EMLXS_FCF_LOCK);
13614 return (0);
13615 }
13616
13617 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13618 "vpi_reg_mbcmpl:%d. Reg complete. >",
13619 vpip->VPI);
13620
13621 vpip->flag |= EMLXS_VPI_REG;
13622 (void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL,
13623 0, 0, 0);
13624
13625 mutex_exit(&EMLXS_FCF_LOCK);
13626 return (0);
13627
13628 } /* emlxs_vpi_reg_mbcmpl() */
13629
13630
13631 /*ARGSUSED*/
13632 static uint32_t
emlxs_vpi_reg_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13633 emlxs_vpi_reg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13634 void *arg1)
13635 {
13636 emlxs_hba_t *hba = HBA;
13637 uint32_t *wwpn;
13638 MAILBOX *mb;
13639 MAILBOXQ *mbq;
13640 uint32_t rval = 0;
13641
13642 if (vpip->state != VPI_STATE_REG) {
13643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13644 "vpi_reg_action:%d %s:%s arg=%p. "
13645 "Invalid state. <",
13646 vpip->VPI,
13647 emlxs_vpi_state_xlate(vpip->state),
13648 emlxs_fcf_event_xlate(evt), arg1);
13649 return (1);
13650 }
13651
13652 if (vpip->prev_state != VPI_STATE_REG_FAILED) {
13653 vpip->attempts = 0;
13654 }
13655
13656 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
13657 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13658 "vpi_reg_action:%d attempts=%d. Offline requested.",
13659 vpip->VPI,
13660 vpip->attempts);
13661
13662 rval = emlxs_vpi_offline_handler(port, vpip, 0);
13663 return (rval);
13664 }
13665
13666 if (!(vpip->vfip->flag & EMLXS_VFI_REG)) {
13667 /* We can't register the VPI until our VFI is registered */
13668
13669 /* If this is the flogi_vpip, then we can skip the REG_VPI. */
13670 /* REG_VPI will be performed later during REG_VFI */
13671 if (vpip == vpip->vfip->flogi_vpip) {
13672 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13673 "vpi_reg_action:%d. flogi_vpi. Skipping REG_VPI.",
13674 vpip->VPI);
13675
13676 rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE,
13677 FCF_REASON_EVENT, evt, arg1);
13678
13679 return (rval);
13680 }
13681
13682 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13683 "vpi_reg_action:%d attempts=%d. VFI not registered. "
13684 "Offlining.",
13685 vpip->VPI,
13686 vpip->attempts);
13687
13688 vpip->flag &= ~EMLXS_VPI_REQ_MASK;
13689 vpip->flag |= EMLXS_VPI_OFFLINE_REQ;
13690 rval = emlxs_vpi_offline_handler(port, vpip, 0);
13691 return (rval);
13692 }
13693
13694 if (vpip->flag & EMLXS_VPI_REG) {
13695 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13696 "vpi_reg_action:%d attempts=%d. Updating REG_VPI. <",
13697 vpip->VPI,
13698 vpip->attempts);
13699 } else {
13700 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13701 "vpi_reg_action:%d attempts=%d. Sending REG_VPI. <",
13702 vpip->VPI,
13703 vpip->attempts);
13704 }
13705
13706 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
13707 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
13708 FCF_REASON_NO_MBOX, 0, arg1);
13709
13710 return (rval);
13711 }
13712 mb = (MAILBOX*)mbq;
13713 bzero((void *) mb, MAILBOX_CMD_BSIZE);
13714
13715 mbq->nonembed = NULL;
13716 mbq->mbox_cmpl = emlxs_vpi_reg_mbcmpl;
13717 mbq->context = (void *)vpip;
13718 mbq->port = (void *)vpip->port;
13719
13720 mb->un.varRegVpi.vfi = vpip->vfip->VFI;
13721 mb->un.varRegVpi.upd = (vpip->flag & EMLXS_VPI_REG)? 1:0;
13722
13723 wwpn = (uint32_t *)&port->wwpn;
13724 mb->un.varRegVpi.portname[0] = BE_SWAP32(*wwpn);
13725 wwpn++;
13726 mb->un.varRegVpi.portname[1] = BE_SWAP32(*wwpn);
13727
13728 mb->un.varRegVpi.vpi = vpip->VPI;
13729 mb->un.varRegVpi.sid = vpip->port->did;
13730 mb->mbxCommand = MBX_REG_VPI;
13731 mb->mbxOwner = OWN_HOST;
13732
13733 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
13734 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
13735 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
13736
13737 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED,
13738 FCF_REASON_SEND_FAILED, rval, arg1);
13739
13740 return (rval);
13741 }
13742
13743 return (0);
13744
13745 } /* emlxs_vpi_reg_action() */
13746
13747
13748 /*ARGSUSED*/
13749 static uint32_t
emlxs_vpi_reg_cmpl_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13750 emlxs_vpi_reg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13751 void *arg1)
13752 {
13753 uint32_t rval = 0;
13754
13755 if (vpip->state != VPI_STATE_REG_CMPL) {
13756 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13757 "vpi_reg_cmpl_action:%d %s:%s arg=%p. "
13758 "Invalid state. <",
13759 vpip->VPI,
13760 emlxs_vpi_state_xlate(vpip->state),
13761 emlxs_fcf_event_xlate(evt), arg1);
13762 return (1);
13763 }
13764
13765 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
13766 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13767 "vpi_reg_cmpl_action:%d attempts=%d. Offline requested.",
13768 vpip->VPI,
13769 vpip->attempts);
13770
13771 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13772 return (rval);
13773 }
13774
13775 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13776 "vpi_reg_cmpl_action:%d attempts=%d. Going online.",
13777 vpip->VPI,
13778 vpip->attempts);
13779
13780 rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE,
13781 FCF_REASON_EVENT, evt, arg1);
13782
13783 return (rval);
13784
13785 } /* emlxs_vpi_reg_cmpl_action() */
13786
13787
13788 /*ARGSUSED*/
13789 static uint32_t
emlxs_vpi_online_action(emlxs_port_t * port,VPIobj_t * vpip,uint32_t evt,void * arg1)13790 emlxs_vpi_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt,
13791 void *arg1)
13792 {
13793 uint32_t rval = 0;
13794
13795 if (vpip->state != VPI_STATE_ONLINE) {
13796 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13797 "vpi_online_action:%d %s:%s arg=%p. "
13798 "Invalid state. <",
13799 vpip->VPI,
13800 emlxs_vpi_state_xlate(vpip->state),
13801 emlxs_fcf_event_xlate(evt), arg1);
13802 return (1);
13803 }
13804
13805 vpip->flag &= ~EMLXS_VPI_ONLINE_REQ;
13806
13807 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) {
13808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13809 "vpi_online_action:%d attempts=%d. Offline requested.",
13810 vpip->VPI,
13811 vpip->attempts);
13812
13813 rval = emlxs_vpi_offline_handler(port, vpip, arg1);
13814 return (rval);
13815 }
13816
13817 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
13818 "vpi_online_action:%d. VPI online. Notifying VFI:%d >",
13819 vpip->VPI,
13820 vpip->vfip->VFI);
13821
13822 /* Notify VFI */
13823 rval = emlxs_vfi_event(port, FCF_EVENT_VPI_ONLINE, vpip);
13824
13825 return (rval);
13826
13827 } /* emlxs_vpi_online_action() */
13828
13829
13830 /* ************************************************************************** */
13831 /* RPI */
13832 /* ************************************************************************** */
13833
13834 static char *
emlxs_rpi_state_xlate(uint32_t state)13835 emlxs_rpi_state_xlate(uint32_t state)
13836 {
13837 static char buffer[32];
13838 uint32_t i;
13839 uint32_t count;
13840
13841 count = sizeof (emlxs_rpi_state_table) / sizeof (emlxs_table_t);
13842 for (i = 0; i < count; i++) {
13843 if (state == emlxs_rpi_state_table[i].code) {
13844 return (emlxs_rpi_state_table[i].string);
13845 }
13846 }
13847
13848 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
13849 return (buffer);
13850
13851 } /* emlxs_rpi_state_xlate() */
13852
13853
13854 static uint32_t
emlxs_rpi_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)13855 emlxs_rpi_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
13856 void *arg1)
13857 {
13858 uint32_t rval = 0;
13859 uint32_t(*func) (emlxs_port_t *, RPIobj_t *, uint32_t, void *);
13860 uint32_t index;
13861 uint32_t events;
13862 uint16_t state;
13863
13864 /* Convert event to action table index */
13865 switch (evt) {
13866 case FCF_EVENT_STATE_ENTER:
13867 index = 0;
13868 break;
13869 case FCF_EVENT_RPI_ONLINE:
13870 index = 1;
13871 break;
13872 case FCF_EVENT_RPI_OFFLINE:
13873 index = 2;
13874 break;
13875 case FCF_EVENT_RPI_PAUSE:
13876 index = 3;
13877 break;
13878 case FCF_EVENT_RPI_RESUME:
13879 index = 4;
13880 break;
13881 default:
13882 return (1);
13883 }
13884
13885 events = RPI_ACTION_EVENTS;
13886 state = rpip->state;
13887
13888 index += (state * events);
13889 func = (uint32_t(*) (emlxs_port_t *, RPIobj_t *, uint32_t, void *))
13890 emlxs_rpi_action_table[index];
13891
13892 if (!func) {
13893 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
13894 "rpi_action:%d %s:%s arg=%p. No action. <",
13895 rpip->RPI,
13896 emlxs_rpi_state_xlate(rpip->state),
13897 emlxs_fcf_event_xlate(evt), arg1);
13898
13899 return (1);
13900 }
13901
13902 rval = (func)(port, rpip, evt, arg1);
13903
13904 return (rval);
13905
13906 } /* emlxs_rpi_action() */
13907
13908
13909 static uint32_t
emlxs_rpi_event(emlxs_port_t * port,uint32_t evt,void * arg1)13910 emlxs_rpi_event(emlxs_port_t *port, uint32_t evt,
13911 void *arg1)
13912 {
13913 RPIobj_t *rpip = NULL;
13914 uint32_t rval = 0;
13915
13916 /* Filter events and acquire fcfi context */
13917 switch (evt) {
13918 case FCF_EVENT_RPI_ONLINE:
13919 case FCF_EVENT_RPI_OFFLINE:
13920 case FCF_EVENT_RPI_PAUSE:
13921 case FCF_EVENT_RPI_RESUME:
13922 rpip = (RPIobj_t *)arg1;
13923
13924 if (!rpip) {
13925 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
13926 "rpi_event: %s arg=%p. Null RPI found. <",
13927 emlxs_fcf_event_xlate(evt), arg1);
13928
13929 return (1);
13930 }
13931
13932 break;
13933
13934 default:
13935 return (1);
13936 }
13937
13938 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg,
13939 "rpi_event:%d %s:%s arg=%p",
13940 rpip->RPI,
13941 emlxs_rpi_state_xlate(rpip->state),
13942 emlxs_fcf_event_xlate(evt), arg1);
13943
13944 rval = emlxs_rpi_action(port, rpip, evt, arg1);
13945
13946 return (rval);
13947
13948 } /* emlxs_rpi_event() */
13949
13950
13951 /*ARGSUSED*/
13952 static uint32_t
emlxs_rpi_state(emlxs_port_t * port,RPIobj_t * rpip,uint16_t state,uint16_t reason,uint32_t explain,void * arg1)13953 emlxs_rpi_state(emlxs_port_t *port, RPIobj_t *rpip, uint16_t state,
13954 uint16_t reason, uint32_t explain, void *arg1)
13955 {
13956 uint32_t rval = 0;
13957
13958 if (state >= RPI_ACTION_STATES) {
13959 return (1);
13960 }
13961
13962 if ((rpip->state == state) &&
13963 (reason != FCF_REASON_REENTER)) {
13964 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
13965 "rpi_state:%d %s:%s:0x%x arg=%p. State not changed. <",
13966 rpip->RPI,
13967 emlxs_rpi_state_xlate(rpip->state),
13968 emlxs_fcf_reason_xlate(reason),
13969 explain, arg1);
13970 return (1);
13971 }
13972
13973 if (!reason) {
13974 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
13975 "rpi_state:%d %s-->%s arg=%p",
13976 rpip->RPI,
13977 emlxs_rpi_state_xlate(rpip->state),
13978 emlxs_rpi_state_xlate(state), arg1);
13979 } else if (reason == FCF_REASON_EVENT) {
13980 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
13981 "rpi_state:%d %s-->%s:%s:%s arg=%p",
13982 rpip->RPI,
13983 emlxs_rpi_state_xlate(rpip->state),
13984 emlxs_rpi_state_xlate(state),
13985 emlxs_fcf_reason_xlate(reason),
13986 emlxs_fcf_event_xlate(explain), arg1);
13987 } else if (explain) {
13988 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
13989 "rpi_state:%d %s-->%s:%s:0x%x arg=%p",
13990 rpip->RPI,
13991 emlxs_rpi_state_xlate(rpip->state),
13992 emlxs_rpi_state_xlate(state),
13993 emlxs_fcf_reason_xlate(reason),
13994 explain, arg1);
13995 } else {
13996 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg,
13997 "rpi_state:%d %s-->%s:%s arg=%p",
13998 rpip->RPI,
13999 emlxs_rpi_state_xlate(rpip->state),
14000 emlxs_rpi_state_xlate(state),
14001 emlxs_fcf_reason_xlate(reason), arg1);
14002 }
14003
14004 rpip->prev_state = rpip->state;
14005 rpip->prev_reason = rpip->reason;
14006 rpip->state = state;
14007 rpip->reason = reason;
14008
14009 rval = emlxs_rpi_action(port, rpip, FCF_EVENT_STATE_ENTER, arg1);
14010
14011 return (rval);
14012
14013 } /* emlxs_rpi_state() */
14014
14015
14016 static void
emlxs_rpi_deferred_cmpl(emlxs_port_t * port,RPIobj_t * rpip,uint32_t status)14017 emlxs_rpi_deferred_cmpl(emlxs_port_t *port, RPIobj_t *rpip, uint32_t status)
14018 {
14019 emlxs_hba_t *hba = HBA;
14020 emlxs_deferred_cmpl_t *cmpl;
14021
14022 if (!rpip->cmpl) {
14023 return;
14024 }
14025
14026 cmpl = rpip->cmpl;
14027 rpip->cmpl = 0;
14028
14029 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14030 "rpi_deferred_cmpl:%d. status=%x ...",
14031 port->vpip->VPI,
14032 status);
14033
14034 emlxs_thread_spawn(hba, emlxs_deferred_cmpl_thread, (void *)cmpl,
14035 (void*)(uintptr_t)status);
14036
14037 return;
14038
14039 } /* emlxs_rpi_deferred_cmpl() */
14040
14041
14042 static void
emlxs_rpi_idle_timer(emlxs_hba_t * hba)14043 emlxs_rpi_idle_timer(emlxs_hba_t *hba)
14044 {
14045 emlxs_config_t *cfg = &CFG;
14046 RPIobj_t *rpip;
14047 uint32_t i;
14048
14049 /* This timer monitors for idle timeout of an RPI in a */
14050 /* RESERVED state. */
14051 /* This means that the RPI was reserved, but never registered. */
14052 /* If the RPI sits for too long (~2 secs) in this state we free it */
14053 rpip = hba->sli.sli4.RPIp;
14054 for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
14055 if (rpip->state != RPI_STATE_RESERVED) {
14056 continue;
14057 }
14058
14059 /* If RPI is active, then clear timer. */
14060 if (rpip->xri_count) {
14061 rpip->idle_timer = 0;
14062 continue;
14063 }
14064
14065 /* If an F-port RPI is found idle, then free it. */
14066 /* Since an F-port RPI is never registered after the login */
14067 /* completes, it is safe to free it immediately. */
14068 if ((rpip->did == FABRIC_DID) ||
14069 (rpip->did == SCR_DID)) {
14070 goto free_it;
14071 }
14072
14073 /* Start idle timer if not already active */
14074 if (!rpip->idle_timer) {
14075 rpip->idle_timer = hba->timer_tics +
14076 cfg[CFG_FCF_RPI_IDLE_TIMEOUT].current;
14077 }
14078
14079 /* Check for idle timeout */
14080 if (hba->timer_tics < rpip->idle_timer) {
14081 continue;
14082 }
14083 rpip->idle_timer = 0;
14084
14085 free_it:
14086 (void) emlxs_rpi_state(rpip->vpip->port, rpip, RPI_STATE_FREE,
14087 FCF_REASON_UNUSED, 0, 0);
14088 }
14089
14090 return;
14091
14092 } /* emlxs_rpi_idle_timer() */
14093
14094
14095 static RPIobj_t *
emlxs_rpi_alloc(emlxs_port_t * port,uint32_t did)14096 emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did)
14097 {
14098 emlxs_hba_t *hba = HBA;
14099 uint16_t i;
14100 RPIobj_t *rpip;
14101
14102 rpip = hba->sli.sli4.RPIp;
14103 for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
14104 /* To be consistent with SLI3, the RPI assignment */
14105 /* starts with 1. ONLY one SLI4 HBA in the entire */
14106 /* system will be sacrificed by one RPI and that */
14107 /* is the one having RPI base equal 0. */
14108 if ((rpip->state == RPI_STATE_FREE) && (rpip->RPI != 0)) {
14109
14110 bzero(rpip, sizeof (RPIobj_t));
14111 rpip->index = i;
14112 rpip->RPI = emlxs_sli4_index_to_rpi(hba, i);
14113 rpip->vpip = port->vpip;
14114 rpip->did = did;
14115
14116 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14117 "rpi_alloc:%d. RPI allocated. >",
14118 rpip->RPI);
14119
14120 (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESERVED,
14121 0, 0, 0);
14122
14123 return (rpip);
14124 }
14125 }
14126
14127 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14128 "rpi_alloc: Out of RPI objects.");
14129
14130 return (NULL);
14131
14132 } /* emlxs_rpi_alloc() */
14133
14134
14135 /* Special routine for VPI object */
14136 static void
emlxs_rpi_alloc_fabric_rpi(emlxs_port_t * port)14137 emlxs_rpi_alloc_fabric_rpi(emlxs_port_t *port)
14138 {
14139 RPIobj_t *fabric_rpip;
14140
14141 fabric_rpip = port->vpip->fabric_rpip;
14142
14143 if (fabric_rpip->state != RPI_STATE_FREE) {
14144 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14145 "rpi_alloc_fabric_rpi: Fabric RPI active:%s.",
14146 emlxs_rpi_state_xlate(fabric_rpip->state));
14147 return;
14148 }
14149
14150 bzero(fabric_rpip, sizeof (RPIobj_t));
14151 fabric_rpip->index = 0xffff;
14152 fabric_rpip->RPI = FABRIC_RPI;
14153 fabric_rpip->did = FABRIC_DID;
14154 fabric_rpip->vpip = port->vpip;
14155
14156 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14157 "rpi_alloc_fabric_rpi: Allocating Fabric RPI. >");
14158
14159 (void) emlxs_rpi_state(port, fabric_rpip, RPI_STATE_RESERVED,
14160 0, 0, 0);
14161
14162 return;
14163
14164 } /* emlxs_rpi_alloc_fabric_rpi() */
14165
14166
14167 static uint32_t
emlxs_rpi_free(emlxs_port_t * port,RPIobj_t * rpip)14168 emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip)
14169 {
14170 uint32_t rval = 0;
14171
14172 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14173 "rpi_free:%d did=%x. Freeing RPI. >",
14174 rpip->RPI, rpip->did);
14175
14176 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
14177
14178 return (rval);
14179
14180 } /* emlxs_rpi_free() */
14181
14182
14183 extern RPIobj_t *
emlxs_rpi_find(emlxs_port_t * port,uint16_t rpi)14184 emlxs_rpi_find(emlxs_port_t *port, uint16_t rpi)
14185 {
14186 emlxs_hba_t *hba = HBA;
14187 RPIobj_t *rpip;
14188 uint32_t index;
14189
14190 /* Special handling for Fabric RPI */
14191 if (rpi == FABRIC_RPI) {
14192 return (port->vpip->fabric_rpip);
14193 }
14194
14195 index = emlxs_sli4_rpi_to_index(hba, rpi);
14196
14197 if (index >= hba->sli.sli4.RPICount) {
14198 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14199 "rpi_find:%d. RPI Invalid.",
14200 rpi);
14201
14202 return (NULL);
14203 }
14204
14205 rpip = &hba->sli.sli4.RPIp[index];
14206
14207 if (rpip->state == RPI_STATE_FREE) {
14208 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14209 "rpi_find:%d RPI not active",
14210 rpi);
14211
14212 return (NULL);
14213 }
14214
14215 return (rpip);
14216
14217 } /* emlxs_rpi_find() */
14218
14219
14220 static RPIobj_t *
emlxs_rpi_find_did(emlxs_port_t * port,uint32_t did)14221 emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did)
14222 {
14223 emlxs_hba_t *hba = HBA;
14224 RPIobj_t *rpip;
14225 RPIobj_t *rpip1;
14226 uint32_t i;
14227
14228 rpip1 = NULL;
14229 rpip = hba->sli.sli4.RPIp;
14230 for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) {
14231 if (rpip->state == RPI_STATE_FREE) {
14232 continue;
14233 }
14234
14235 if ((rpip->did == did) && (rpip->vpip == port->vpip)) {
14236 rpip1 = rpip;
14237 break;
14238 }
14239 }
14240
14241 return (rpip1);
14242
14243 } /* emlxs_rpi_find_did() */
14244
14245
14246 extern RPIobj_t *
emlxs_rpi_reserve_notify(emlxs_port_t * port,uint32_t did,XRIobj_t * xrip)14247 emlxs_rpi_reserve_notify(emlxs_port_t *port, uint32_t did, XRIobj_t *xrip)
14248 {
14249 emlxs_hba_t *hba = HBA;
14250 RPIobj_t *rpip;
14251
14252 /* xrip will be NULL for unsolicited BLS requests */
14253
14254 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14255 return (NULL);
14256 }
14257
14258 mutex_enter(&EMLXS_FCF_LOCK);
14259
14260 rpip = emlxs_rpi_find_did(port, did);
14261
14262 if (!rpip) {
14263 rpip = emlxs_rpi_alloc(port, did);
14264 }
14265
14266 if (!rpip) {
14267 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14268 "rpi_reserve_notify: Unable to reserve an rpi. "
14269 "did=%x xri=%d.",
14270 did, ((xrip)?xrip->XRI:0));
14271
14272 mutex_exit(&EMLXS_FCF_LOCK);
14273 return (NULL);
14274 }
14275
14276 /* Bind the XRI */
14277 if (xrip) {
14278 mutex_enter(&EMLXS_FCTAB_LOCK);
14279 xrip->reserved_rpip = rpip;
14280 rpip->xri_count++;
14281 mutex_exit(&EMLXS_FCTAB_LOCK);
14282 }
14283
14284 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14285 "rpi_reserve_notify:%d did=%x xri=%d.",
14286 rpip->RPI, rpip->did, ((xrip)?xrip->XRI:0));
14287
14288 mutex_exit(&EMLXS_FCF_LOCK);
14289
14290 return (rpip);
14291
14292 } /* emlxs_rpi_reserve_notify() */
14293
14294
14295 extern RPIobj_t *
emlxs_rpi_alloc_notify(emlxs_port_t * port,uint32_t did)14296 emlxs_rpi_alloc_notify(emlxs_port_t *port, uint32_t did)
14297 {
14298 emlxs_hba_t *hba = HBA;
14299 RPIobj_t *rpip;
14300
14301 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14302 return (NULL);
14303 }
14304
14305 mutex_enter(&EMLXS_FCF_LOCK);
14306
14307 rpip = emlxs_rpi_alloc(port, did);
14308
14309 mutex_exit(&EMLXS_FCF_LOCK);
14310
14311 return (rpip);
14312
14313 } /* emlxs_rpi_alloc_notify() */
14314
14315
14316 extern uint32_t
emlxs_rpi_free_notify(emlxs_port_t * port,RPIobj_t * rpip)14317 emlxs_rpi_free_notify(emlxs_port_t *port, RPIobj_t *rpip)
14318 {
14319 emlxs_hba_t *hba = HBA;
14320 uint32_t rval = 0;
14321
14322 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14323 return (1);
14324 }
14325
14326 if (!rpip) {
14327 return (1);
14328 }
14329
14330 /* Fabric RPI will be handled automatically */
14331 if (rpip->RPI == FABRIC_RPI) {
14332 return (1);
14333 }
14334
14335 mutex_enter(&EMLXS_FCF_LOCK);
14336
14337 rval = emlxs_rpi_free(port, rpip);
14338
14339 mutex_exit(&EMLXS_FCF_LOCK);
14340
14341 return (rval);
14342
14343 } /* emlxs_rpi_free_notify() */
14344
14345
14346 extern uint32_t
emlxs_rpi_pause_notify(emlxs_port_t * port,RPIobj_t * rpip)14347 emlxs_rpi_pause_notify(emlxs_port_t *port, RPIobj_t *rpip)
14348 {
14349 emlxs_hba_t *hba = HBA;
14350
14351 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14352 return (1);
14353 }
14354
14355 if (!rpip) {
14356 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14357 "rpi_pause_notify: No RPI provided.");
14358 return (1);
14359 }
14360
14361 /* Fabric RPI will be handled automatically */
14362 if (rpip->RPI == FABRIC_RPI) {
14363 return (1);
14364 }
14365
14366 mutex_enter(&EMLXS_FCF_LOCK);
14367
14368 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14369 "rpi_pause_notify:%d %s. Pausing RPI. >",
14370 rpip->RPI,
14371 emlxs_rpi_state_xlate(rpip->state));
14372
14373 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_PAUSE, rpip);
14374
14375 mutex_exit(&EMLXS_FCF_LOCK);
14376
14377 return (0);
14378
14379 } /* emlxs_rpi_pause_notify() */
14380
14381
14382 extern uint32_t
emlxs_rpi_online_notify(emlxs_port_t * port,RPIobj_t * rpip,uint32_t did,SERV_PARM * sparam,void * arg1,void * arg2,void * arg3)14383 emlxs_rpi_online_notify(emlxs_port_t *port, RPIobj_t *rpip, uint32_t did,
14384 SERV_PARM *sparam, void *arg1, void *arg2, void *arg3)
14385 {
14386 emlxs_hba_t *hba = HBA;
14387 emlxs_deferred_cmpl_t *cmpl;
14388 uint32_t allocated = 0;
14389 uint32_t rval = 0;
14390
14391 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14392 return (1);
14393 }
14394
14395 if ((did == port->did) && (!(hba->flag & FC_LOOPBACK_MODE))) {
14396 /* We never register our local port */
14397 return (1);
14398 }
14399
14400 mutex_enter(&EMLXS_FCF_LOCK);
14401
14402 if (!rpip && (did == FABRIC_DID)) {
14403 /* We never online the Fabric DID other */
14404 /* than the fabric_rpip */
14405 rpip = port->vpip->fabric_rpip;
14406 }
14407
14408 if (!rpip) {
14409 rpip = emlxs_rpi_find_did(port, did);
14410 }
14411
14412 if (!rpip) {
14413 rpip = emlxs_rpi_alloc(port, did);
14414 allocated = 1;
14415 }
14416
14417 if (!rpip) {
14418 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14419 "rpi_online_notify: Unable to allocate an rpi. did=%x",
14420 did);
14421
14422 mutex_exit(&EMLXS_FCF_LOCK);
14423 return (1);
14424 }
14425
14426 /* Initialize RPI node info */
14427 bcopy((void *)sparam, (void *)&rpip->sparam, sizeof (SERV_PARM));
14428
14429 if (arg1 || arg2 || arg3) {
14430 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
14431 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
14432
14433 cmpl->port = port;
14434 cmpl->arg1 = arg1;
14435 cmpl->arg2 = arg2;
14436 cmpl->arg3 = arg3;
14437
14438 /* For safety */
14439 if (rpip->cmpl) {
14440 emlxs_rpi_deferred_cmpl(port, rpip, 1);
14441 }
14442
14443 rpip->cmpl = cmpl;
14444 }
14445
14446 if ((rpip->RPI == FABRIC_RPI) ||
14447 (hba->flag & FC_PT_TO_PT)) {
14448 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14449 "rpi_online_notify:%d %s. %s. Login cmpl.",
14450 rpip->RPI,
14451 emlxs_rpi_state_xlate(rpip->state),
14452 ((allocated)? "Allocated":"Updated"));
14453
14454 rval = emlxs_vpi_logi_cmpl_notify(port, rpip);
14455
14456 if (rval && rpip->cmpl) {
14457 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14458 rpip->cmpl = 0;
14459 }
14460
14461 mutex_exit(&EMLXS_FCF_LOCK);
14462 return (rval);
14463 }
14464
14465 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14466 "rpi_online_notify:%d %s. %s. Onlining RPI. >",
14467 rpip->RPI,
14468 emlxs_rpi_state_xlate(rpip->state),
14469 ((allocated)? "Allocated":"Updated"));
14470
14471 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE, rpip);
14472
14473 if (rpip->cmpl) {
14474 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14475 "rpi_online_notify:%d %s. Deferred args not completed.",
14476 rpip->RPI,
14477 emlxs_rpi_state_xlate(rpip->state));
14478
14479 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14480 rpip->cmpl = 0;
14481
14482 mutex_exit(&EMLXS_FCF_LOCK);
14483 return (1);
14484 }
14485
14486 mutex_exit(&EMLXS_FCF_LOCK);
14487 return (0);
14488
14489 } /* emlxs_rpi_online_notify() */
14490
14491
14492 extern uint32_t
emlxs_rpi_offline_notify(emlxs_port_t * port,RPIobj_t * rpip,void * arg1,void * arg2,void * arg3)14493 emlxs_rpi_offline_notify(emlxs_port_t *port, RPIobj_t *rpip,
14494 void *arg1, void *arg2, void *arg3)
14495 {
14496 emlxs_hba_t *hba = HBA;
14497 emlxs_deferred_cmpl_t *cmpl;
14498
14499 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14500 return (1);
14501 }
14502
14503 if (!rpip) {
14504 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14505 "rpi_offline_notify: No RPI provided.");
14506 return (1);
14507 }
14508
14509 /* Fabric RPI will be handled automatically */
14510 if (rpip->RPI == FABRIC_RPI) {
14511 return (1);
14512 }
14513
14514 mutex_enter(&EMLXS_FCF_LOCK);
14515
14516 if (arg1 || arg2 || arg3) {
14517 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
14518 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
14519
14520 cmpl->port = port;
14521 cmpl->arg1 = arg1;
14522 cmpl->arg2 = arg2;
14523 cmpl->arg3 = arg3;
14524
14525 rpip->cmpl = cmpl;
14526 }
14527
14528 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14529 "rpi_offline_notify:%d %s. Offlining RPI. >",
14530 rpip->RPI,
14531 emlxs_rpi_state_xlate(rpip->state));
14532
14533 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip);
14534
14535 if (rpip->cmpl) {
14536 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14537 "rpi_offline_notify:%d %s. Deferred args not completed.",
14538 rpip->RPI,
14539 emlxs_rpi_state_xlate(rpip->state));
14540
14541 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14542 rpip->cmpl = 0;
14543
14544 mutex_exit(&EMLXS_FCF_LOCK);
14545 return (1);
14546 }
14547
14548 mutex_exit(&EMLXS_FCF_LOCK);
14549
14550 return (0);
14551
14552 } /* emlxs_rpi_offline_notify() */
14553
14554
14555 extern uint32_t
emlxs_rpi_resume_notify(emlxs_port_t * port,RPIobj_t * rpip,emlxs_buf_t * sbp)14556 emlxs_rpi_resume_notify(emlxs_port_t *port, RPIobj_t *rpip, emlxs_buf_t *sbp)
14557 {
14558 emlxs_hba_t *hba = HBA;
14559 emlxs_deferred_cmpl_t *cmpl;
14560
14561 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
14562 return (1);
14563 }
14564
14565 if (!rpip) {
14566 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14567 "rpi_resume_notify: No RPI provided.");
14568 return (1);
14569 }
14570
14571 /* Fabric RPI will be handled automatically */
14572 if (rpip->RPI == FABRIC_RPI) {
14573 return (1);
14574 }
14575
14576 mutex_enter(&EMLXS_FCF_LOCK);
14577
14578 if (rpip->state != RPI_STATE_PAUSED) {
14579 mutex_exit(&EMLXS_FCF_LOCK);
14580 return (1);
14581 }
14582
14583 if (sbp) {
14584 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc(
14585 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP);
14586
14587 cmpl->port = port;
14588 cmpl->arg1 = (void *)sbp;
14589 cmpl->arg2 = 0;
14590 cmpl->arg3 = 0;
14591
14592 rpip->cmpl = cmpl;
14593 }
14594
14595 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14596 "rpi_resume_notify:%d %s. Resuming RPI. >",
14597 rpip->RPI,
14598 emlxs_rpi_state_xlate(rpip->state));
14599
14600 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_RESUME, rpip);
14601
14602 if (rpip->cmpl) {
14603 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14604 "rpi_resume_notify:%d %s. Deferred args not completed.",
14605 rpip->RPI,
14606 emlxs_rpi_state_xlate(rpip->state));
14607
14608 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
14609 rpip->cmpl = 0;
14610
14611 mutex_exit(&EMLXS_FCF_LOCK);
14612 return (1);
14613 }
14614
14615 mutex_exit(&EMLXS_FCF_LOCK);
14616
14617 return (0);
14618
14619 } /* emlxs_rpi_resume_notify() */
14620
14621
14622 /*ARGSUSED*/
14623 static uint32_t
emlxs_rpi_free_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14624 emlxs_rpi_free_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14625 void *arg1)
14626 {
14627 emlxs_hba_t *hba = HBA;
14628 XRIobj_t *xrip;
14629 XRIobj_t *next_xrip;
14630
14631 if (rpip->state != RPI_STATE_FREE) {
14632 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14633 "rpi_free_action:%d %s:%s arg=%p. "
14634 "Invalid state. <",
14635 rpip->RPI,
14636 emlxs_rpi_state_xlate(rpip->state),
14637 emlxs_fcf_event_xlate(evt), arg1);
14638 return (1);
14639 }
14640
14641 if (rpip->cmpl) {
14642 emlxs_rpi_deferred_cmpl(port, rpip, 1);
14643 }
14644
14645 if (rpip->vpip->p2p_rpip == rpip) {
14646 rpip->vpip->p2p_rpip = NULL;
14647 }
14648
14649 /* Break node/RPI binding */
14650 rw_enter(&port->node_rwlock, RW_WRITER);
14651 if (rpip->node) {
14652 rpip->node->rpip = NULL;
14653 rpip->node = NULL;
14654 }
14655 rw_exit(&port->node_rwlock);
14656
14657 /* Remove all XRIs under this RPI */
14658 mutex_enter(&EMLXS_FCTAB_LOCK);
14659 xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
14660 while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
14661 next_xrip = xrip->_f;
14662 if (xrip->rpip == rpip) {
14663 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14664 "rpi_free_action:%d xri_count=%d. "
14665 "Removing XRI:%d iotag:%d.",
14666 rpip->RPI,
14667 rpip->xri_count,
14668 xrip->XRI, xrip->iotag);
14669
14670 rpip->xri_count--;
14671 xrip->rpip = NULL;
14672 }
14673
14674 if (xrip->reserved_rpip == rpip) {
14675 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14676 "rpi_free_action:%d xri_count=%d. "
14677 "Removing XRI:%d iotag:%d.",
14678 rpip->RPI,
14679 rpip->xri_count,
14680 xrip->XRI, xrip->iotag);
14681
14682 rpip->xri_count--;
14683 xrip->reserved_rpip = NULL;
14684 }
14685
14686 xrip = next_xrip;
14687 }
14688 mutex_exit(&EMLXS_FCTAB_LOCK);
14689
14690 if (rpip->xri_count) {
14691 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14692 "rpi_free_action:%d. xri_count=%d",
14693 rpip->RPI,
14694 rpip->xri_count);
14695 }
14696
14697 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14698 "rpi_free_action:%d flag=%x. RPI freed. <",
14699 rpip->RPI,
14700 rpip->flag);
14701
14702 rpip->flag = 0;
14703
14704 return (0);
14705
14706 } /* emlxs_rpi_free_action() */
14707
14708
14709 /*ARGSUSED*/
14710 static uint32_t
emlxs_rpi_online_evt_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14711 emlxs_rpi_online_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14712 void *arg1)
14713 {
14714 uint32_t rval = 1;
14715
14716 if (evt != FCF_EVENT_RPI_ONLINE) {
14717 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14718 "rpi_online_evt_action:%d %s:%s arg=%p. "
14719 "Invalid event type. <",
14720 rpip->RPI,
14721 emlxs_rpi_state_xlate(rpip->state),
14722 emlxs_fcf_event_xlate(evt), arg1);
14723 return (1);
14724 }
14725
14726 switch (rpip->state) {
14727 case RPI_STATE_REG:
14728 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14729 "rpi_online_evt_action:%d flag=%x. Registering.",
14730 rpip->RPI,
14731 rpip->flag);
14732
14733 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG,
14734 FCF_REASON_REENTER, evt, arg1);
14735 break;
14736
14737 default:
14738 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14739 "rpi_online_evt_action:%d flag=%x. Registering.",
14740 rpip->RPI,
14741 rpip->flag);
14742
14743 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG,
14744 FCF_REASON_EVENT, evt, arg1);
14745 break;
14746 }
14747
14748 return (rval);
14749
14750 } /* emlxs_rpi_online_evt_action() */
14751
14752
14753 /*ARGSUSED*/
14754 static uint32_t
emlxs_rpi_offline_evt_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14755 emlxs_rpi_offline_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14756 void *arg1)
14757 {
14758 uint32_t rval = 1;
14759
14760 if (evt != FCF_EVENT_RPI_OFFLINE) {
14761 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14762 "rpi_offline_evt_action:%d %s:%s arg=%p. "
14763 "Invalid event type. <",
14764 rpip->RPI,
14765 emlxs_rpi_state_xlate(rpip->state),
14766 emlxs_fcf_event_xlate(evt), arg1);
14767 return (1);
14768 }
14769
14770 switch (rpip->state) {
14771 case RPI_STATE_RESERVED:
14772 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14773 "rpi_offline_evt_action:%d flag=%x. Freeing RPI.",
14774 rpip->RPI,
14775 rpip->flag);
14776
14777 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE,
14778 FCF_REASON_EVENT, evt, arg1);
14779 break;
14780
14781 case RPI_STATE_UNREG:
14782 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14783 "rpi_offline_evt_action:%d flag=%x. "
14784 "Already unregistering. <",
14785 rpip->RPI,
14786 rpip->flag);
14787
14788 break;
14789
14790 default:
14791 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14792 "rpi_offline_evt_action:%d flag=%x. Unregistering.",
14793 rpip->RPI,
14794 rpip->flag);
14795
14796 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
14797 FCF_REASON_EVENT, evt, arg1);
14798 break;
14799
14800 }
14801
14802 return (rval);
14803
14804 } /* emlxs_rpi_offline_evt_action() */
14805
14806
14807 /*ARGSUSED*/
14808 static uint32_t
emlxs_rpi_pause_evt_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14809 emlxs_rpi_pause_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14810 void *arg1)
14811 {
14812 VPIobj_t *vpip;
14813 uint32_t rval = 1;
14814
14815 vpip = rpip->vpip;
14816
14817 if (evt != FCF_EVENT_RPI_PAUSE) {
14818 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14819 "rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. "
14820 "Invalid event type. <",
14821 rpip->RPI,
14822 emlxs_rpi_state_xlate(rpip->state),
14823 emlxs_fcf_event_xlate(evt), arg1,
14824 rpip->flag);
14825 return (1);
14826 }
14827
14828 switch (rpip->state) {
14829 case RPI_STATE_RESERVED:
14830 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14831 "rpi_pause_evt_action:%d flag=%x. Freeing RPI.",
14832 rpip->RPI,
14833 rpip->flag);
14834
14835 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE,
14836 FCF_REASON_EVENT, evt, arg1);
14837 break;
14838
14839 case RPI_STATE_UNREG:
14840 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14841 "rpi_pause_evt_action:%d flag=%x. Not online. <",
14842 rpip->RPI,
14843 rpip->flag);
14844
14845 break;
14846
14847 case RPI_STATE_PAUSED:
14848 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14849 "rpi_pause_evt_action:%d flag=%x. Already paused. <",
14850 rpip->RPI,
14851 rpip->flag);
14852
14853 break;
14854
14855 case RPI_STATE_REG:
14856 case RPI_STATE_ONLINE:
14857 case RPI_STATE_RESUME:
14858 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14859 "rpi_pause_evt_action:%d flag=%x. Pausing.",
14860 rpip->RPI,
14861 rpip->flag);
14862
14863 /* Don't pause an RPI, if the VPI is not pausing too */
14864 if (!(vpip->flag & EMLXS_VPI_PAUSE_REQ)) {
14865 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14866 "rpi_pause_evt_action:%d rpi_online=%d,%d "
14867 "xri_count=%d. VPI:%d pause not requested. "
14868 "Unregistering.", rpip->RPI,
14869 vpip->rpi_online, vpip->rpi_paused,
14870 rpip->xri_count, vpip->VPI);
14871
14872 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
14873 FCF_REASON_EVENT, evt, arg1);
14874 break;
14875 }
14876
14877 rval = emlxs_rpi_state(port, rpip, RPI_STATE_PAUSED,
14878 FCF_REASON_EVENT, evt, arg1);
14879 break;
14880
14881 default:
14882 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14883 "rpi_pause_evt_action:%d flag=%x. <",
14884 rpip->RPI,
14885 rpip->flag);
14886 break;
14887 }
14888
14889 return (rval);
14890
14891 } /* emlxs_rpi_pause_evt_action() */
14892
14893
14894 /*ARGSUSED*/
14895 static uint32_t
emlxs_rpi_resume_evt_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14896 emlxs_rpi_resume_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14897 void *arg1)
14898 {
14899 uint32_t rval = 1;
14900
14901 if (evt != FCF_EVENT_RPI_RESUME) {
14902 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
14903 "rpi_resume_evt_action:%d %s:%s arg=%p flag=%x. "
14904 "Invalid event type. <",
14905 rpip->RPI,
14906 emlxs_rpi_state_xlate(rpip->state),
14907 emlxs_fcf_event_xlate(evt), arg1,
14908 rpip->flag);
14909 return (1);
14910 }
14911
14912 switch (rpip->state) {
14913 case RPI_STATE_PAUSED:
14914 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14915 "rpi_resume_evt_action:%d flag=%x. Resuming.",
14916 rpip->RPI,
14917 rpip->flag);
14918
14919 rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME,
14920 FCF_REASON_EVENT, evt, arg1);
14921 break;
14922
14923 default:
14924 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14925 "rpi_resume_evt_action:%d flag=%x. Not paused. <",
14926 rpip->RPI,
14927 rpip->flag);
14928 break;
14929 }
14930
14931 return (rval);
14932
14933 } /* emlxs_rpi_resume_evt_action() */
14934
14935
14936 /*ARGSUSED*/
14937 static uint32_t
emlxs_rpi_reserved_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14938 emlxs_rpi_reserved_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14939 void *arg1)
14940 {
14941 VPIobj_t *vpip;
14942
14943 vpip = rpip->vpip;
14944
14945 if (rpip->state != RPI_STATE_RESERVED) {
14946 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14947 "rpi_reserved_action:%d %s:%s arg=%p. "
14948 "Invalid state. <",
14949 rpip->RPI,
14950 emlxs_rpi_state_xlate(rpip->state),
14951 emlxs_fcf_event_xlate(evt), arg1);
14952 return (1);
14953 }
14954
14955 if (rpip->prev_state != RPI_STATE_FREE) {
14956 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14957 "rpi_reserved_action:%d %s:%s arg=%p. "
14958 "Invalid previous state. %s <",
14959 rpip->RPI,
14960 emlxs_rpi_state_xlate(rpip->state),
14961 emlxs_fcf_event_xlate(evt), arg1,
14962 emlxs_rpi_state_xlate(rpip->prev_state));
14963
14964 return (1);
14965 }
14966
14967 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14968 "rpi_reserved_action:%d rpi_online=%d,%d. <",
14969 rpip->RPI,
14970 vpip->rpi_online, vpip->rpi_paused);
14971
14972 return (0);
14973
14974 } /* emlxs_rpi_reserved_action() */
14975
14976
14977 /*ARGSUSED*/
14978 static uint32_t
emlxs_rpi_offline_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)14979 emlxs_rpi_offline_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
14980 void *arg1)
14981 {
14982 uint32_t rval = 0;
14983 VPIobj_t *vpip;
14984
14985 vpip = rpip->vpip;
14986
14987 if (rpip->state != RPI_STATE_OFFLINE) {
14988 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
14989 "rpi_offline_action:%d %s:%s arg=%p. "
14990 "Invalid state. <",
14991 rpip->RPI,
14992 emlxs_rpi_state_xlate(rpip->state),
14993 emlxs_fcf_event_xlate(evt), arg1);
14994 return (1);
14995 }
14996
14997 if (rpip->flag & EMLXS_RPI_PAUSED) {
14998 rpip->flag &= ~EMLXS_RPI_PAUSED;
14999
15000 if (vpip->rpi_paused) {
15001 vpip->rpi_paused--;
15002 }
15003 }
15004
15005 if (rpip->flag & EMLXS_RPI_VPI) {
15006 rpip->flag &= ~EMLXS_RPI_VPI;
15007
15008 if (vpip->rpi_online) {
15009 vpip->rpi_online--;
15010 }
15011
15012 /* Added protection */
15013 if (vpip->rpi_online < vpip->rpi_paused) {
15014 vpip->rpi_paused = vpip->rpi_online;
15015 }
15016 }
15017
15018 if (rpip->RPI == FABRIC_RPI) {
15019 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15020 "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. "
15021 "Fabric RPI offline. Freeing.",
15022 rpip->RPI,
15023 vpip->rpi_online, vpip->rpi_paused,
15024 rpip->xri_count);
15025
15026 /* Free RPI */
15027 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
15028
15029 return (rval);
15030 }
15031
15032 if ((vpip->rpi_online == 0) ||
15033 (vpip->rpi_online == vpip->rpi_paused)) {
15034 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15035 "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. "
15036 "RPI offline. "
15037 "Notifying VPI:%d >",
15038 rpip->RPI,
15039 vpip->rpi_online, vpip->rpi_paused,
15040 rpip->xri_count,
15041 vpip->VPI);
15042
15043 /* Notify VPI */
15044 (void) emlxs_vpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip);
15045
15046 } else {
15047 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15048 "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. "
15049 "RPI offline. Freeing.",
15050 rpip->RPI,
15051 vpip->rpi_online, vpip->rpi_paused,
15052 rpip->xri_count);
15053 }
15054
15055 /* Free RPI */
15056 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0);
15057
15058 return (rval);
15059
15060 } /* emlxs_rpi_offline_action() */
15061
15062
15063 /*ARGSUSED*/
15064 static uint32_t
emlxs_rpi_paused_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15065 emlxs_rpi_paused_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15066 void *arg1)
15067 {
15068 VPIobj_t *vpip;
15069 uint32_t rval = 0;
15070
15071 vpip = rpip->vpip;
15072
15073 if (rpip->state != RPI_STATE_PAUSED) {
15074 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15075 "rpi_paused_action:%d %s:%s arg=%p. "
15076 "Invalid state. <",
15077 rpip->RPI,
15078 emlxs_rpi_state_xlate(rpip->state),
15079 emlxs_fcf_event_xlate(evt), arg1);
15080 return (1);
15081 }
15082
15083 if (!(vpip->flag & EMLXS_VPI_PAUSE_REQ)) {
15084 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15085 "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. "
15086 "VPI:%d pause not requested. Unregistering.",
15087 rpip->RPI,
15088 vpip->rpi_online, vpip->rpi_paused,
15089 rpip->xri_count,
15090 vpip->VPI);
15091
15092 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
15093 FCF_REASON_EVENT, evt, arg1);
15094 return (rval);
15095 }
15096
15097 if (!(rpip->flag & EMLXS_RPI_PAUSED)) {
15098 rpip->flag |= EMLXS_RPI_PAUSED;
15099 vpip->rpi_paused++;
15100 }
15101
15102 /* Check if all RPI's have been paused for a VPI */
15103 if (vpip->rpi_online == vpip->rpi_paused) {
15104 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15105 "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. "
15106 "RPI paused. "
15107 "Notifying VPI:%d >",
15108 rpip->RPI,
15109 vpip->rpi_online, vpip->rpi_paused,
15110 rpip->xri_count,
15111 vpip->VPI);
15112
15113 /* Notify VPI */
15114 (void) emlxs_vpi_event(port, FCF_EVENT_RPI_PAUSE, rpip);
15115
15116 } else {
15117 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15118 "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. "
15119 "RPI paused. <",
15120 rpip->RPI,
15121 vpip->rpi_online, vpip->rpi_paused,
15122 rpip->xri_count);
15123 }
15124
15125 return (0);
15126
15127 } /* emlxs_rpi_paused_action() */
15128
15129
15130 /*ARGSUSED*/
15131 static uint32_t
emlxs_rpi_unreg_failed_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15132 emlxs_rpi_unreg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15133 void *arg1)
15134 {
15135 uint32_t rval = 0;
15136
15137 rpip->attempts++;
15138
15139 if (rpip->state != RPI_STATE_UNREG_FAILED) {
15140 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15141 "rpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. "
15142 "Invalid state. <",
15143 rpip->RPI,
15144 emlxs_rpi_state_xlate(rpip->state),
15145 emlxs_fcf_event_xlate(evt), arg1,
15146 rpip->attempts);
15147 return (1);
15148 }
15149
15150 if ((rpip->reason == FCF_REASON_SEND_FAILED) ||
15151 !(rpip->flag & EMLXS_RPI_REG)) {
15152
15153 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15154 "rpi_unreg_failed_action:%d reason=%x flag=%x. "
15155 "Going offline.",
15156 rpip->RPI,
15157 rpip->reason,
15158 rpip->flag);
15159
15160 rpip->flag &= ~EMLXS_RPI_REG;
15161
15162 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15163 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15164 } else {
15165 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15166 "rpi_unreg_failed_action:%d flag=%x. Going online.",
15167 rpip->RPI,
15168 rpip->flag);
15169
15170 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15171 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15172 }
15173
15174 return (rval);
15175
15176 } /* emlxs_rpi_unreg_failed_action() */
15177
15178
15179 static void
emlxs_rpi_unreg_handler(emlxs_port_t * port,RPIobj_t * rpip)15180 emlxs_rpi_unreg_handler(emlxs_port_t *port, RPIobj_t *rpip)
15181 {
15182 emlxs_hba_t *hba = HBA;
15183 VPIobj_t *vpip = rpip->vpip;
15184 emlxs_node_t *node = rpip->node;
15185 XRIobj_t *xrip;
15186 XRIobj_t *next_xrip;
15187
15188 /* Special handling for Fabric RPI */
15189 if (rpip->RPI == FABRIC_RPI) {
15190 if (node) {
15191 (void) emlxs_tx_node_flush(port, node, 0, 0, 0);
15192 (void) emlxs_chipq_node_flush(port, 0, node, 0);
15193 }
15194
15195 /* Clear all reserved XRIs under this RPI */
15196 mutex_enter(&EMLXS_FCTAB_LOCK);
15197 xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
15198 while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
15199 next_xrip = xrip->_f;
15200 /* We don't need to worry about xrip->reserved_rpip */
15201 /* here because the Fabric RPI can never be reserved */
15202 /* by an xri. */
15203 if ((xrip->rpip == rpip) &&
15204 (xrip->flag & EMLXS_XRI_RESERVED)) {
15205 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15206 "rpi_unreg_action:%d xri_count=%d. "
15207 "Unreserving XRI:%d iotag:%d.",
15208 rpip->RPI,
15209 rpip->xri_count,
15210 xrip->XRI, xrip->iotag);
15211
15212 (void) emlxs_sli4_unreserve_xri(port,
15213 xrip->XRI, 0);
15214 }
15215 xrip = next_xrip;
15216 }
15217 mutex_exit(&EMLXS_FCTAB_LOCK);
15218 }
15219
15220 rpip->flag &= ~EMLXS_RPI_REG;
15221
15222 if (rpip->flag & EMLXS_RPI_PAUSED) {
15223 rpip->flag &= ~EMLXS_RPI_PAUSED;
15224
15225 if (vpip->rpi_paused) {
15226 vpip->rpi_paused--;
15227 }
15228 }
15229
15230 if (rpip->flag & EMLXS_RPI_VPI) {
15231 rpip->flag &= ~EMLXS_RPI_VPI;
15232
15233 if (vpip->rpi_online) {
15234 vpip->rpi_online--;
15235 }
15236
15237 /* Added protection */
15238 if (vpip->rpi_online < vpip->rpi_paused) {
15239 vpip->rpi_paused = vpip->rpi_online;
15240 }
15241 }
15242
15243 rw_enter(&port->node_rwlock, RW_WRITER);
15244 if (node) {
15245 rpip->node = NULL;
15246 node->rpip = NULL;
15247 }
15248 rw_exit(&port->node_rwlock);
15249
15250 if (node) {
15251 emlxs_node_rm(port, node);
15252 }
15253
15254 return;
15255
15256 } /* emlxs_rpi_unreg_handler() */
15257
15258
15259 /*ARGSUSED*/
15260 static uint32_t
emlxs_rpi_unreg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)15261 emlxs_rpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
15262 {
15263 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
15264 MAILBOX4 *mb4;
15265 RPIobj_t *rpip;
15266
15267 mutex_enter(&EMLXS_FCF_LOCK);
15268
15269 rpip = (RPIobj_t *)mbq->context;
15270
15271 mb4 = (MAILBOX4 *)mbq;
15272
15273 if (rpip->state != RPI_STATE_UNREG) {
15274 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15275 "rpi_unreg_mbcmpl:%d state=%s. "
15276 "No longer in RPI_STATE_UNREG.",
15277 rpip->RPI,
15278 emlxs_rpi_state_xlate(rpip->state));
15279
15280 mutex_exit(&EMLXS_FCF_LOCK);
15281 return (0);
15282 }
15283
15284 if (mb4->mbxStatus) {
15285 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15286 "rpi_unreg_mbcmpl:%d failed. %s. >",
15287 rpip->RPI,
15288 emlxs_mb_xlate_status(mb4->mbxStatus));
15289
15290 (void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
15291 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
15292
15293 mutex_exit(&EMLXS_FCF_LOCK);
15294 return (0);
15295 }
15296
15297 emlxs_rpi_unreg_handler(port, rpip);
15298
15299 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15300 "rpi_unreg_mbcmpl:%d Unregistered. Unreg complete. >",
15301 rpip->RPI);
15302
15303 (void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_CMPL,
15304 0, 0, 0);
15305
15306 mutex_exit(&EMLXS_FCF_LOCK);
15307 return (0);
15308
15309 } /* emlxs_rpi_unreg_mbcmpl() */
15310
15311
15312 /*ARGSUSED*/
15313 static uint32_t
emlxs_rpi_unreg_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15314 emlxs_rpi_unreg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15315 void *arg1)
15316 {
15317 emlxs_hba_t *hba = HBA;
15318 MAILBOX4 *mb4;
15319 MAILBOXQ *mbq;
15320 uint32_t rval = 0;
15321 VPIobj_t *vpip = rpip->vpip;
15322
15323 if (rpip->state != RPI_STATE_UNREG) {
15324 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15325 "rpi_unreg_action:%d %s:%s arg=%p. "
15326 "Invalid state. <",
15327 rpip->RPI,
15328 emlxs_rpi_state_xlate(rpip->state),
15329 emlxs_fcf_event_xlate(evt), arg1);
15330 return (1);
15331 }
15332
15333 if (!(rpip->flag & EMLXS_RPI_REG)) {
15334 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15335 "rpi_unreg_action:%d. Not registered. Going offline.",
15336 rpip->RPI);
15337
15338 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15339 FCF_REASON_EVENT, evt, arg1);
15340
15341 return (rval);
15342 }
15343
15344 if (rpip->prev_state != RPI_STATE_UNREG_FAILED) {
15345 rpip->attempts = 0;
15346 }
15347
15348 if (rpip->RPI == FABRIC_RPI) {
15349 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15350 "rpi_unreg_action:%d did=%x vpi=%d. Fabric RPI. "
15351 "Going offline.",
15352 rpip->RPI,
15353 rpip->did,
15354 rpip->vpip->VPI);
15355
15356 /* Don't send UNREG_RPI, but process it as if we did */
15357 emlxs_rpi_unreg_handler(port, rpip);
15358
15359 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15360 FCF_REASON_EVENT, evt, arg1);
15361
15362 return (rval);
15363 }
15364
15365 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15366 "rpi_unreg_action:%d attempts=%d. Sending UNREG_RPI. <",
15367 rpip->RPI,
15368 rpip->attempts);
15369
15370 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
15371
15372 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
15373 FCF_REASON_NO_MBOX, 0, arg1);
15374
15375 return (rval);
15376 }
15377 mb4 = (MAILBOX4*)mbq;
15378 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
15379
15380 mbq->nonembed = NULL;
15381 mbq->mbox_cmpl = emlxs_rpi_unreg_mbcmpl;
15382 mbq->context = (void *)rpip;
15383 mbq->port = (void *)port;
15384
15385 mb4->mbxCommand = MBX_UNREG_RPI;
15386 mb4->mbxOwner = OWN_HOST;
15387 mb4->un.varUnregLogin.rpi = rpip->RPI;
15388 mb4->un.varUnregLogin.vpi = vpip->VPI;
15389
15390 if (rpip->cmpl) {
15391 mbq->sbp = rpip->cmpl->arg1;
15392 mbq->ubp = rpip->cmpl->arg2;
15393 mbq->iocbq = rpip->cmpl->arg3;
15394 }
15395
15396 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
15397 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
15398 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
15399
15400 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED,
15401 FCF_REASON_SEND_FAILED, rval, arg1);
15402
15403 return (rval);
15404 }
15405
15406 if (rpip->cmpl) {
15407 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
15408 rpip->cmpl = 0;
15409 }
15410
15411 return (0);
15412
15413 } /* emlxs_rpi_unreg_action() */
15414
15415
15416 /*ARGSUSED*/
15417 static uint32_t
emlxs_rpi_unreg_cmpl_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15418 emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15419 void *arg1)
15420 {
15421 uint32_t rval = 0;
15422
15423 if (rpip->state != RPI_STATE_UNREG_CMPL) {
15424 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15425 "rpi_unreg_cmpl_action:%d %s:%s arg=%p. "
15426 "Invalid state. <",
15427 rpip->RPI,
15428 emlxs_rpi_state_xlate(rpip->state),
15429 emlxs_fcf_event_xlate(evt), arg1);
15430 return (1);
15431 }
15432
15433 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15434 "rpi_unreg_cmpl_action:%d flag=%x. Going offline.",
15435 rpip->RPI,
15436 rpip->flag);
15437
15438 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15439 FCF_REASON_EVENT, evt, arg1);
15440
15441 return (rval);
15442
15443 } /* emlxs_rpi_unreg_cmpl_action() */
15444
15445
15446 /*ARGSUSED*/
15447 static uint32_t
emlxs_rpi_reg_failed_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15448 emlxs_rpi_reg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15449 void *arg1)
15450 {
15451 uint32_t rval = 0;
15452
15453 rpip->attempts++;
15454
15455 if (rpip->state != RPI_STATE_REG_FAILED) {
15456 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15457 "rpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. "
15458 "Invalid state. <",
15459 rpip->RPI,
15460 emlxs_rpi_state_xlate(rpip->state),
15461 emlxs_fcf_event_xlate(evt), arg1,
15462 rpip->attempts);
15463 return (1);
15464 }
15465
15466 if ((rpip->reason == FCF_REASON_SEND_FAILED) ||
15467 !(rpip->flag & EMLXS_RPI_REG)) {
15468 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15469 "rpi_reg_failed_action:%d reason=%x flag=%x. "
15470 "Going offline.",
15471 rpip->RPI,
15472 rpip->reason,
15473 rpip->flag);
15474
15475 rpip->flag &= ~EMLXS_RPI_REG;
15476
15477 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15478 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15479 } else {
15480 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15481 "rpi_reg_failed_action:%d flag=%x. Unregistering",
15482 rpip->RPI,
15483 rpip->flag);
15484
15485 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
15486 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15487 }
15488
15489 return (rval);
15490
15491 } /* emlxs_rpi_reg_failed_action() */
15492
15493
15494 static uint32_t
emlxs_rpi_reg_handler(emlxs_port_t * port,RPIobj_t * rpip)15495 emlxs_rpi_reg_handler(emlxs_port_t *port, RPIobj_t *rpip)
15496 {
15497 emlxs_hba_t *hba = HBA;
15498 VPIobj_t *vpip;
15499 emlxs_node_t *node;
15500
15501 vpip = rpip->vpip;
15502
15503 rpip->flag |= EMLXS_RPI_REG;
15504
15505 if (rpip->flag & EMLXS_RPI_PAUSED) {
15506 rpip->flag &= ~EMLXS_RPI_PAUSED;
15507
15508 if (vpip->rpi_paused) {
15509 vpip->rpi_paused--;
15510 }
15511 }
15512
15513 if (!(rpip->flag & EMLXS_RPI_VPI) && (rpip->RPI != FABRIC_RPI)) {
15514 rpip->flag |= EMLXS_RPI_VPI;
15515 vpip->rpi_online++;
15516 }
15517
15518 /* If private loop and this is fabric RPI, then exit now */
15519 if (!(hba->flag & FC_FABRIC_ATTACHED) && (rpip->RPI == FABRIC_RPI)) {
15520 return (0);
15521 }
15522
15523 /* Create or update the node */
15524 node = emlxs_node_create(port, rpip->did, rpip->RPI, &rpip->sparam);
15525
15526 if (!node) {
15527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15528 "rpi_reg_handler:%d. Node create failed. Reg failed.",
15529 rpip->RPI);
15530
15531 return (FCF_REASON_NO_NODE);
15532 }
15533
15534 return (0);
15535
15536 } /* emlxs_rpi_reg_handler() */
15537
15538
15539 /*ARGSUSED*/
15540 static uint32_t
emlxs_rpi_reg_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)15541 emlxs_rpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
15542 {
15543 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
15544 MAILBOX4 *mb4;
15545 RPIobj_t *rpip;
15546 emlxs_node_t *node;
15547 uint32_t rval = 0;
15548
15549 mutex_enter(&EMLXS_FCF_LOCK);
15550
15551 rpip = (RPIobj_t *)mbq->context;
15552 mb4 = (MAILBOX4 *)mbq;
15553
15554 if (rpip->state != RPI_STATE_REG) {
15555 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15556 "rpi_reg_mbcmpl:%d state=%s. No longer in RPI_STATE_REG.",
15557 rpip->RPI,
15558 emlxs_rpi_state_xlate(rpip->state));
15559
15560 mutex_exit(&EMLXS_FCF_LOCK);
15561 return (0);
15562 }
15563
15564 if (mb4->mbxStatus) {
15565 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15566 "rpi_reg_mbcmpl:%d failed. %s. >",
15567 rpip->RPI,
15568 emlxs_mb_xlate_status(mb4->mbxStatus));
15569
15570 (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15571 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0);
15572
15573 mutex_exit(&EMLXS_FCF_LOCK);
15574 return (0);
15575 }
15576
15577 rval = emlxs_rpi_reg_handler(port, rpip);
15578
15579 if (rval) {
15580 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15581 "rpi_reg_mbcmpl:%d. Reg failed. >",
15582 rpip->RPI);
15583
15584 mb4->mbxStatus = MBX_FAILURE;
15585
15586 (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15587 rval, 0, 0);
15588
15589 mutex_exit(&EMLXS_FCF_LOCK);
15590 return (0);
15591 }
15592
15593 node = rpip->node;
15594
15595 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15596 "rpi_reg_mbcmpl:%d Registered. Reg complete. >",
15597 rpip->RPI);
15598
15599 (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_CMPL, 0, 0, 0);
15600
15601 mutex_exit(&EMLXS_FCF_LOCK);
15602
15603 /* Needed for FCT trigger in emlxs_mb_deferred_cmpl */
15604 if (mbq->sbp) {
15605 ((emlxs_buf_t *)mbq->sbp)->node = node;
15606 }
15607
15608 #ifdef DHCHAP_SUPPORT
15609 if (mbq->sbp || mbq->ubp) {
15610 if (emlxs_dhc_auth_start(port, node, (uint8_t *)mbq->sbp,
15611 (uint8_t *)mbq->ubp) == 0) {
15612 /* Auth started - auth completion will */
15613 /* handle sbp and ubp now */
15614 mbq->sbp = NULL;
15615 mbq->ubp = NULL;
15616 }
15617 }
15618 #endif /* DHCHAP_SUPPORT */
15619
15620 return (0);
15621
15622 } /* emlxs_rpi_reg_mbcmpl() */
15623
15624
15625 /*ARGSUSED*/
15626 static uint32_t
emlxs_rpi_reg_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15627 emlxs_rpi_reg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15628 void *arg1)
15629 {
15630 emlxs_hba_t *hba = HBA;
15631 MAILBOX4 *mb4;
15632 MAILBOXQ *mbq;
15633 MATCHMAP *mp;
15634 uint32_t rval = 0;
15635
15636 if (rpip->state != RPI_STATE_REG) {
15637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15638 "rpi_reg_action:%d %s:%s arg=%p. "
15639 "Invalid state. <",
15640 rpip->RPI,
15641 emlxs_rpi_state_xlate(rpip->state),
15642 emlxs_fcf_event_xlate(evt), arg1);
15643 return (1);
15644 }
15645
15646 if (rpip->RPI == FABRIC_RPI) {
15647 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15648 "rpi_reg_action:%d did=%x vpi=%d. Fabric RPI. "
15649 "Going online.",
15650 rpip->RPI,
15651 rpip->did,
15652 rpip->vpip->VPI);
15653
15654 /* Don't send REG_RPI, but process it as if we did */
15655 rval = emlxs_rpi_reg_handler(port, rpip);
15656
15657 if (rval) {
15658 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15659 rval, 0, 0);
15660
15661 return (rval);
15662 }
15663
15664 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15665 FCF_REASON_EVENT, evt, arg1);
15666
15667 return (rval);
15668 }
15669
15670 if (rpip->prev_state != RPI_STATE_REG_FAILED) {
15671 rpip->attempts = 0;
15672 }
15673
15674 if (rpip->flag & EMLXS_RPI_REG) {
15675 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15676 "rpi_reg_action:%d attempts=%d. "
15677 "Updating REG_RPI. <",
15678 rpip->RPI,
15679 rpip->attempts);
15680 } else {
15681 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15682 "rpi_reg_action:%d attempts=%d. "
15683 "Sending REG_RPI. <",
15684 rpip->RPI,
15685 rpip->attempts);
15686 }
15687
15688 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
15689
15690 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15691 FCF_REASON_NO_MBOX, 0, arg1);
15692
15693 return (rval);
15694 }
15695
15696 mb4 = (MAILBOX4*)mbq;
15697 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
15698
15699 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
15700 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
15701
15702 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15703 FCF_REASON_NO_BUFFER, 0, arg1);
15704
15705 return (rval);
15706 }
15707
15708 mbq->bp = (void *)mp;
15709 mbq->nonembed = NULL;
15710
15711 mbq->mbox_cmpl = emlxs_rpi_reg_mbcmpl;
15712 mbq->context = (void *)rpip;
15713 mbq->port = (void *)port;
15714
15715 mb4->mbxCommand = MBX_REG_RPI;
15716 mb4->mbxOwner = OWN_HOST;
15717
15718 mb4->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
15719 mb4->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys);
15720 mb4->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys);
15721 mb4->un.varRegLogin.did = rpip->did;
15722 mb4->un.varWords[30] = 0; /* flags */
15723
15724 mb4->un.varRegLogin.vpi = rpip->vpip->VPI;
15725 mb4->un.varRegLogin.rpi = rpip->RPI;
15726 mb4->un.varRegLogin.update = (rpip->flag & EMLXS_RPI_REG)? 1:0;
15727
15728 bcopy((void *)&rpip->sparam, (void *)mp->virt, sizeof (SERV_PARM));
15729
15730 if (rpip->cmpl) {
15731 mbq->sbp = rpip->cmpl->arg1;
15732 mbq->ubp = rpip->cmpl->arg2;
15733 mbq->iocbq = rpip->cmpl->arg3;
15734 }
15735
15736 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
15737 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
15738 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
15739 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
15740
15741 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED,
15742 FCF_REASON_SEND_FAILED, rval, arg1);
15743
15744 return (rval);
15745 }
15746
15747 if (rpip->cmpl) {
15748 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
15749 rpip->cmpl = 0;
15750 }
15751
15752 return (0);
15753
15754 } /* emlxs_rpi_reg_action() */
15755
15756
15757 /*ARGSUSED*/
15758 static uint32_t
emlxs_rpi_reg_cmpl_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15759 emlxs_rpi_reg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15760 void *arg1)
15761 {
15762 uint32_t rval = 0;
15763
15764 if (rpip->state != RPI_STATE_REG_CMPL) {
15765 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15766 "rpi_reg_cmpl_action:%d %s:%s arg=%p. "
15767 "Invalid state. <",
15768 rpip->RPI,
15769 emlxs_rpi_state_xlate(rpip->state),
15770 emlxs_fcf_event_xlate(evt), arg1);
15771 return (1);
15772 }
15773
15774 if (rpip->flag & EMLXS_RPI_REG) {
15775 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15776 "rpi_reg_cmpl_action:%d flag=%x. Going online.",
15777 rpip->RPI,
15778 rpip->flag);
15779
15780 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15781 FCF_REASON_EVENT, evt, arg1);
15782 } else {
15783 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15784 "rpi_reg_cmpl_action:%d flag=%x. Going offline.",
15785 rpip->RPI,
15786 rpip->flag);
15787
15788 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
15789 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15790 }
15791
15792 return (rval);
15793
15794 } /* emlxs_rpi_reg_cmpl_action() */
15795
15796
15797 /*ARGSUSED*/
15798 static uint32_t
emlxs_rpi_resume_failed_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15799 emlxs_rpi_resume_failed_action(emlxs_port_t *port, RPIobj_t *rpip,
15800 uint32_t evt, void *arg1)
15801 {
15802 uint32_t rval = 0;
15803
15804 rpip->attempts++;
15805
15806 if (rpip->state != RPI_STATE_RESUME_FAILED) {
15807 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15808 "rpi_resume_failed_action:%d %s:%s arg=%p attempt=%d. "
15809 "Invalid state. <",
15810 rpip->RPI,
15811 emlxs_rpi_state_xlate(rpip->state),
15812 emlxs_fcf_event_xlate(evt), arg1,
15813 rpip->attempts);
15814 return (1);
15815 }
15816
15817 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15818 "rpi_resume_failed_action:%d attempt=%d. Unregistering.",
15819 rpip->RPI,
15820 rpip->attempts);
15821
15822 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
15823 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
15824
15825 return (rval);
15826
15827 } /* emlxs_rpi_resume_failed_action() */
15828
15829
15830 /*ARGSUSED*/
15831 static void
emlxs_rpi_resume_handler(emlxs_port_t * port,RPIobj_t * rpip)15832 emlxs_rpi_resume_handler(emlxs_port_t *port, RPIobj_t *rpip)
15833 {
15834 if (rpip->flag & EMLXS_RPI_PAUSED) {
15835 rpip->flag &= ~EMLXS_RPI_PAUSED;
15836
15837 if (rpip->vpip->rpi_paused) {
15838 rpip->vpip->rpi_paused--;
15839 }
15840 }
15841
15842 return;
15843
15844 } /* emlxs_rpi_resume_handler() */
15845
15846
15847 /*ARGSUSED*/
15848 static uint32_t
emlxs_rpi_resume_mbcmpl(emlxs_hba_t * hba,MAILBOXQ * mbq)15849 emlxs_rpi_resume_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
15850 {
15851 emlxs_port_t *port = (emlxs_port_t *)mbq->port;
15852 MAILBOX4 *mb4;
15853 RPIobj_t *rpip;
15854
15855 mutex_enter(&EMLXS_FCF_LOCK);
15856
15857 rpip = (RPIobj_t *)mbq->context;
15858 mb4 = (MAILBOX4 *)mbq;
15859
15860 if (rpip->state != RPI_STATE_RESUME) {
15861 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15862 "rpi_resume_mbcmpl:%d state=%s. "
15863 "No longer in RPI_STATE_RESUME.",
15864 rpip->RPI,
15865 emlxs_rpi_state_xlate(rpip->state));
15866
15867 mutex_exit(&EMLXS_FCF_LOCK);
15868 return (0);
15869 }
15870
15871 if (mb4->mbxStatus) {
15872 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15873 "rpi_resume_mbcmpl:%d failed. %s. >",
15874 rpip->RPI,
15875 emlxs_mb_xlate_status(mb4->mbxStatus));
15876
15877 (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
15878 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp);
15879
15880 mutex_exit(&EMLXS_FCF_LOCK);
15881 return (0);
15882 }
15883
15884 emlxs_rpi_resume_handler(port, rpip);
15885
15886 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15887 "rpi_resume_mbcmpl:%d Resumed. Resume complete. >",
15888 rpip->RPI);
15889
15890 (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_CMPL, 0, 0, 0);
15891
15892 mutex_exit(&EMLXS_FCF_LOCK);
15893
15894 return (0);
15895
15896 } /* emlxs_rpi_resume_mbcmpl() */
15897
15898
15899 /*ARGSUSED*/
15900 static uint32_t
emlxs_rpi_resume_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)15901 emlxs_rpi_resume_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
15902 void *arg1)
15903 {
15904 emlxs_hba_t *hba = HBA;
15905 MAILBOX4 *mb4;
15906 MAILBOXQ *mbq;
15907 uint32_t rval = 0;
15908
15909 if (rpip->state != RPI_STATE_RESUME) {
15910 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
15911 "rpi_resume_action:%d %s:%s arg=%p. "
15912 "Invalid state. <",
15913 rpip->RPI,
15914 emlxs_rpi_state_xlate(rpip->state),
15915 emlxs_fcf_event_xlate(evt), arg1);
15916 return (1);
15917 }
15918
15919 if (!(rpip->flag & EMLXS_RPI_PAUSED)) {
15920 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15921 "rpi_resume_action:%d flag=%x. Not Paused. Going online.",
15922 rpip->RPI, rpip->flag);
15923
15924 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15925 FCF_REASON_EVENT, evt, arg1);
15926
15927 return (rval);
15928 }
15929
15930 if (rpip->RPI == FABRIC_RPI) {
15931 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15932 "rpi_resume_action:%d. Fabric RPI. "
15933 "Going online.",
15934 rpip->RPI);
15935
15936 /* Don't send RESUME_RPI, but process it as if we did */
15937 emlxs_rpi_resume_handler(port, rpip);
15938
15939 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
15940 FCF_REASON_EVENT, evt, arg1);
15941
15942 return (rval);
15943 }
15944
15945 if (rpip->prev_state != RPI_STATE_RESUME_FAILED) {
15946 rpip->attempts = 0;
15947 }
15948
15949 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
15950 "rpi_resume_action:%d attempts=%d. Sending RESUME_RPI. <",
15951 rpip->RPI,
15952 rpip->attempts);
15953
15954 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
15955
15956 rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
15957 FCF_REASON_NO_MBOX, 0, arg1);
15958
15959 return (rval);
15960 }
15961 mb4 = (MAILBOX4*)mbq;
15962 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
15963
15964 mbq->nonembed = NULL;
15965 mbq->mbox_cmpl = emlxs_rpi_resume_mbcmpl;
15966 mbq->context = (void *)rpip;
15967 mbq->port = (void *)port;
15968
15969 mb4->mbxCommand = MBX_RESUME_RPI;
15970 mb4->mbxOwner = OWN_HOST;
15971
15972 mb4->un.varResumeRPI.EventTag = hba->link_event_tag;
15973 mb4->un.varResumeRPI.RPI = rpip->RPI;
15974
15975 if (rpip->cmpl) {
15976 mbq->sbp = rpip->cmpl->arg1;
15977 mbq->ubp = rpip->cmpl->arg2;
15978 mbq->iocbq = rpip->cmpl->arg3;
15979 }
15980
15981 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
15982 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
15983 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
15984
15985 rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED,
15986 FCF_REASON_SEND_FAILED, rval, arg1);
15987
15988 return (rval);
15989 }
15990
15991 if (rpip->cmpl) {
15992 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t));
15993 rpip->cmpl = 0;
15994 }
15995
15996 return (0);
15997
15998 } /* emlxs_rpi_resume_action() */
15999
16000
16001 static uint32_t
emlxs_rpi_resume_cmpl_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)16002 emlxs_rpi_resume_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
16003 void *arg1)
16004 {
16005 uint32_t rval = 0;
16006
16007 if (rpip->state != RPI_STATE_RESUME_CMPL) {
16008 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg,
16009 "rpi_resume_cmpl_action:%d %s:%s arg=%p. "
16010 "Invalid state. <",
16011 rpip->RPI,
16012 emlxs_rpi_state_xlate(rpip->state),
16013 emlxs_fcf_event_xlate(evt), arg1);
16014 return (1);
16015 }
16016
16017 if (rpip->flag & EMLXS_RPI_PAUSED) {
16018 if (rpip->flag & EMLXS_RPI_REG) {
16019 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16020 "rpi_reg_cmpl_action:%d flag=%x. Unregistering.",
16021 rpip->RPI,
16022 rpip->flag);
16023
16024 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG,
16025 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
16026 } else {
16027 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16028 "rpi_reg_cmpl_action:%d flag=%x. Going offline.",
16029 rpip->RPI,
16030 rpip->flag);
16031
16032 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE,
16033 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
16034 }
16035 } else {
16036 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16037 "rpi_resume_cmpl_action:%d flag=%x. Going online.",
16038 rpip->RPI,
16039 rpip->flag);
16040
16041 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE,
16042 FCF_REASON_OP_FAILED, rpip->attempts, arg1);
16043 }
16044
16045 return (rval);
16046
16047 } /* emlxs_rpi_resume_cmpl_action() */
16048
16049
16050 /*ARGSUSED*/
16051 static uint32_t
emlxs_rpi_online_action(emlxs_port_t * port,RPIobj_t * rpip,uint32_t evt,void * arg1)16052 emlxs_rpi_online_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt,
16053 void *arg1)
16054 {
16055 emlxs_hba_t *hba = HBA;
16056 uint32_t rval = 0;
16057 RPIobj_t *p2p_rpip;
16058
16059 if (rpip->state != RPI_STATE_ONLINE) {
16060 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16061 "rpi_online_action:%d %s:%s arg=%p. "
16062 "Invalid state. <",
16063 rpip->RPI,
16064 emlxs_rpi_state_xlate(rpip->state),
16065 emlxs_fcf_event_xlate(evt), arg1);
16066 return (1);
16067 }
16068
16069 if (rpip->RPI == FABRIC_RPI) {
16070 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16071 "rpi_online_action:%d did=%x. Fabric RPI online. <",
16072 rpip->RPI,
16073 rpip->did,
16074 rpip->vpip->VPI);
16075
16076 /* Now register the p2p_rpip */
16077 p2p_rpip = rpip->vpip->p2p_rpip;
16078 if (p2p_rpip) {
16079 rpip->vpip->p2p_rpip = NULL;
16080
16081 rval = emlxs_rpi_state(port, p2p_rpip, RPI_STATE_REG,
16082 FCF_REASON_EVENT, evt, arg1);
16083 }
16084
16085 EMLXS_STATE_CHANGE(hba, FC_READY);
16086
16087 if (rpip->cmpl) {
16088 emlxs_rpi_deferred_cmpl(port, rpip, 0);
16089 }
16090
16091 return (0);
16092 }
16093
16094 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg,
16095 "rpi_online_action:%d did=%x. RPI online. Notifying VPI:%d. >",
16096 rpip->RPI,
16097 rpip->did,
16098 rpip->vpip->VPI);
16099
16100 /* Notify VPI */
16101 rval = emlxs_vpi_event(port, FCF_EVENT_RPI_ONLINE, rpip);
16102
16103 return (rval);
16104
16105 } /* emlxs_rpi_online_action() */
16106