diff options
Diffstat (limited to 'drivers/scsi/bfa/fabric.c')
-rw-r--r-- | drivers/scsi/bfa/fabric.c | 1323 |
1 files changed, 0 insertions, 1323 deletions
diff --git a/drivers/scsi/bfa/fabric.c b/drivers/scsi/bfa/fabric.c deleted file mode 100644 index ddd4ba9317e6..000000000000 --- a/drivers/scsi/bfa/fabric.c +++ /dev/null | |||
@@ -1,1323 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. | ||
3 | * All rights reserved | ||
4 | * www.brocade.com | ||
5 | * | ||
6 | * Linux driver for Brocade Fibre Channel Host Bus Adapter. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License (GPL) Version 2 as | ||
10 | * published by the Free Software Foundation | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | /** | ||
19 | * fabric.c Fabric module implementation. | ||
20 | */ | ||
21 | |||
22 | #include "fcs_fabric.h" | ||
23 | #include "fcs_lport.h" | ||
24 | #include "fcs_vport.h" | ||
25 | #include "fcs_trcmod.h" | ||
26 | #include "fcs_fcxp.h" | ||
27 | #include "fcs_auth.h" | ||
28 | #include "fcs.h" | ||
29 | #include "fcbuild.h" | ||
30 | #include <log/bfa_log_fcs.h> | ||
31 | #include <aen/bfa_aen_port.h> | ||
32 | #include <bfa_svc.h> | ||
33 | |||
34 | BFA_TRC_FILE(FCS, FABRIC); | ||
35 | |||
36 | #define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */ | ||
37 | #define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */ | ||
38 | |||
39 | #define bfa_fcs_fabric_set_opertype(__fabric) do { \ | ||
40 | if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \ | ||
41 | == BFA_PPORT_TOPOLOGY_P2P) \ | ||
42 | (__fabric)->oper_type = BFA_PPORT_TYPE_NPORT; \ | ||
43 | else \ | ||
44 | (__fabric)->oper_type = BFA_PPORT_TYPE_NLPORT; \ | ||
45 | } while (0) | ||
46 | |||
47 | /* | ||
48 | * forward declarations | ||
49 | */ | ||
50 | static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric); | ||
51 | static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric); | ||
52 | static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric); | ||
53 | static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric); | ||
54 | static void bfa_fcs_fabric_delay(void *cbarg); | ||
55 | static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric); | ||
56 | static void bfa_fcs_fabric_delete_comp(void *cbarg); | ||
57 | static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, | ||
58 | struct fchs_s *fchs, u16 len); | ||
59 | static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, | ||
60 | struct fchs_s *fchs, u16 len); | ||
61 | static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric); | ||
62 | static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg, | ||
63 | struct bfa_fcxp_s *fcxp, | ||
64 | void *cbarg, bfa_status_t status, | ||
65 | u32 rsp_len, | ||
66 | u32 resid_len, | ||
67 | struct fchs_s *rspfchs); | ||
68 | /** | ||
69 | * fcs_fabric_sm fabric state machine functions | ||
70 | */ | ||
71 | |||
72 | /** | ||
73 | * Fabric state machine events | ||
74 | */ | ||
75 | enum bfa_fcs_fabric_event { | ||
76 | BFA_FCS_FABRIC_SM_CREATE = 1, /* fabric create from driver */ | ||
77 | BFA_FCS_FABRIC_SM_DELETE = 2, /* fabric delete from driver */ | ||
78 | BFA_FCS_FABRIC_SM_LINK_DOWN = 3, /* link down from port */ | ||
79 | BFA_FCS_FABRIC_SM_LINK_UP = 4, /* link up from port */ | ||
80 | BFA_FCS_FABRIC_SM_CONT_OP = 5, /* continue op from flogi/auth */ | ||
81 | BFA_FCS_FABRIC_SM_RETRY_OP = 6, /* continue op from flogi/auth */ | ||
82 | BFA_FCS_FABRIC_SM_NO_FABRIC = 7, /* no fabric from flogi/auth | ||
83 | */ | ||
84 | BFA_FCS_FABRIC_SM_PERF_EVFP = 8, /* perform EVFP from | ||
85 | *flogi/auth */ | ||
86 | BFA_FCS_FABRIC_SM_ISOLATE = 9, /* isolate from EVFP processing */ | ||
87 | BFA_FCS_FABRIC_SM_NO_TAGGING = 10,/* no VFT tagging from EVFP */ | ||
88 | BFA_FCS_FABRIC_SM_DELAYED = 11, /* timeout delay event */ | ||
89 | BFA_FCS_FABRIC_SM_AUTH_FAILED = 12, /* authentication failed */ | ||
90 | BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13, /* authentication successful | ||
91 | */ | ||
92 | BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */ | ||
93 | BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */ | ||
94 | BFA_FCS_FABRIC_SM_START = 16, /* fabric delete from driver */ | ||
95 | }; | ||
96 | |||
97 | static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, | ||
98 | enum bfa_fcs_fabric_event event); | ||
99 | static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric, | ||
100 | enum bfa_fcs_fabric_event event); | ||
101 | static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric, | ||
102 | enum bfa_fcs_fabric_event event); | ||
103 | static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, | ||
104 | enum bfa_fcs_fabric_event event); | ||
105 | static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric, | ||
106 | enum bfa_fcs_fabric_event event); | ||
107 | static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, | ||
108 | enum bfa_fcs_fabric_event event); | ||
109 | static void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, | ||
110 | enum bfa_fcs_fabric_event event); | ||
111 | static void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, | ||
112 | enum bfa_fcs_fabric_event event); | ||
113 | static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, | ||
114 | enum bfa_fcs_fabric_event event); | ||
115 | static void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, | ||
116 | enum bfa_fcs_fabric_event event); | ||
117 | static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric, | ||
118 | enum bfa_fcs_fabric_event event); | ||
119 | static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric, | ||
120 | enum bfa_fcs_fabric_event event); | ||
121 | static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric, | ||
122 | enum bfa_fcs_fabric_event event); | ||
123 | static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric, | ||
124 | enum bfa_fcs_fabric_event event); | ||
125 | /** | ||
126 | * Beginning state before fabric creation. | ||
127 | */ | ||
128 | static void | ||
129 | bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, | ||
130 | enum bfa_fcs_fabric_event event) | ||
131 | { | ||
132 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
133 | bfa_trc(fabric->fcs, event); | ||
134 | |||
135 | switch (event) { | ||
136 | case BFA_FCS_FABRIC_SM_CREATE: | ||
137 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created); | ||
138 | bfa_fcs_fabric_init(fabric); | ||
139 | bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg); | ||
140 | break; | ||
141 | |||
142 | case BFA_FCS_FABRIC_SM_LINK_UP: | ||
143 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
144 | break; | ||
145 | |||
146 | default: | ||
147 | bfa_sm_fault(fabric->fcs, event); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * Beginning state before fabric creation. | ||
153 | */ | ||
154 | static void | ||
155 | bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric, | ||
156 | enum bfa_fcs_fabric_event event) | ||
157 | { | ||
158 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
159 | bfa_trc(fabric->fcs, event); | ||
160 | |||
161 | switch (event) { | ||
162 | case BFA_FCS_FABRIC_SM_START: | ||
163 | if (bfa_fcport_is_linkup(fabric->fcs->bfa)) { | ||
164 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); | ||
165 | bfa_fcs_fabric_login(fabric); | ||
166 | } else | ||
167 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
168 | break; | ||
169 | |||
170 | case BFA_FCS_FABRIC_SM_LINK_UP: | ||
171 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
172 | break; | ||
173 | |||
174 | case BFA_FCS_FABRIC_SM_DELETE: | ||
175 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | ||
176 | bfa_fcs_modexit_comp(fabric->fcs); | ||
177 | break; | ||
178 | |||
179 | default: | ||
180 | bfa_sm_fault(fabric->fcs, event); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * Link is down, awaiting LINK UP event from port. This is also the | ||
186 | * first state at fabric creation. | ||
187 | */ | ||
188 | static void | ||
189 | bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric, | ||
190 | enum bfa_fcs_fabric_event event) | ||
191 | { | ||
192 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
193 | bfa_trc(fabric->fcs, event); | ||
194 | |||
195 | switch (event) { | ||
196 | case BFA_FCS_FABRIC_SM_LINK_UP: | ||
197 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); | ||
198 | bfa_fcs_fabric_login(fabric); | ||
199 | break; | ||
200 | |||
201 | case BFA_FCS_FABRIC_SM_RETRY_OP: | ||
202 | break; | ||
203 | |||
204 | case BFA_FCS_FABRIC_SM_DELETE: | ||
205 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
206 | bfa_fcs_fabric_delete(fabric); | ||
207 | break; | ||
208 | |||
209 | default: | ||
210 | bfa_sm_fault(fabric->fcs, event); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * FLOGI is in progress, awaiting FLOGI reply. | ||
216 | */ | ||
217 | static void | ||
218 | bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, | ||
219 | enum bfa_fcs_fabric_event event) | ||
220 | { | ||
221 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
222 | bfa_trc(fabric->fcs, event); | ||
223 | |||
224 | switch (event) { | ||
225 | case BFA_FCS_FABRIC_SM_CONT_OP: | ||
226 | |||
227 | bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit); | ||
228 | fabric->fab_type = BFA_FCS_FABRIC_SWITCHED; | ||
229 | |||
230 | if (fabric->auth_reqd && fabric->is_auth) { | ||
231 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth); | ||
232 | bfa_trc(fabric->fcs, event); | ||
233 | } else { | ||
234 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online); | ||
235 | bfa_fcs_fabric_notify_online(fabric); | ||
236 | } | ||
237 | break; | ||
238 | |||
239 | case BFA_FCS_FABRIC_SM_RETRY_OP: | ||
240 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry); | ||
241 | bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer, | ||
242 | bfa_fcs_fabric_delay, fabric, | ||
243 | BFA_FCS_FABRIC_RETRY_DELAY); | ||
244 | break; | ||
245 | |||
246 | case BFA_FCS_FABRIC_SM_LOOPBACK: | ||
247 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback); | ||
248 | bfa_lps_discard(fabric->lps); | ||
249 | bfa_fcs_fabric_set_opertype(fabric); | ||
250 | break; | ||
251 | |||
252 | case BFA_FCS_FABRIC_SM_NO_FABRIC: | ||
253 | fabric->fab_type = BFA_FCS_FABRIC_N2N; | ||
254 | bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit); | ||
255 | bfa_fcs_fabric_notify_online(fabric); | ||
256 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric); | ||
257 | break; | ||
258 | |||
259 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
260 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
261 | bfa_lps_discard(fabric->lps); | ||
262 | break; | ||
263 | |||
264 | case BFA_FCS_FABRIC_SM_DELETE: | ||
265 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
266 | bfa_lps_discard(fabric->lps); | ||
267 | bfa_fcs_fabric_delete(fabric); | ||
268 | break; | ||
269 | |||
270 | default: | ||
271 | bfa_sm_fault(fabric->fcs, event); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | |||
276 | static void | ||
277 | bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric, | ||
278 | enum bfa_fcs_fabric_event event) | ||
279 | { | ||
280 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
281 | bfa_trc(fabric->fcs, event); | ||
282 | |||
283 | switch (event) { | ||
284 | case BFA_FCS_FABRIC_SM_DELAYED: | ||
285 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); | ||
286 | bfa_fcs_fabric_login(fabric); | ||
287 | break; | ||
288 | |||
289 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
290 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
291 | bfa_timer_stop(&fabric->delay_timer); | ||
292 | break; | ||
293 | |||
294 | case BFA_FCS_FABRIC_SM_DELETE: | ||
295 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
296 | bfa_timer_stop(&fabric->delay_timer); | ||
297 | bfa_fcs_fabric_delete(fabric); | ||
298 | break; | ||
299 | |||
300 | default: | ||
301 | bfa_sm_fault(fabric->fcs, event); | ||
302 | } | ||
303 | } | ||
304 | |||
305 | /** | ||
306 | * Authentication is in progress, awaiting authentication results. | ||
307 | */ | ||
308 | static void | ||
309 | bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, | ||
310 | enum bfa_fcs_fabric_event event) | ||
311 | { | ||
312 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
313 | bfa_trc(fabric->fcs, event); | ||
314 | |||
315 | switch (event) { | ||
316 | case BFA_FCS_FABRIC_SM_AUTH_FAILED: | ||
317 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); | ||
318 | bfa_lps_discard(fabric->lps); | ||
319 | break; | ||
320 | |||
321 | case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: | ||
322 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online); | ||
323 | bfa_fcs_fabric_notify_online(fabric); | ||
324 | break; | ||
325 | |||
326 | case BFA_FCS_FABRIC_SM_PERF_EVFP: | ||
327 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp); | ||
328 | break; | ||
329 | |||
330 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
331 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
332 | bfa_lps_discard(fabric->lps); | ||
333 | break; | ||
334 | |||
335 | case BFA_FCS_FABRIC_SM_DELETE: | ||
336 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
337 | bfa_fcs_fabric_delete(fabric); | ||
338 | break; | ||
339 | |||
340 | default: | ||
341 | bfa_sm_fault(fabric->fcs, event); | ||
342 | } | ||
343 | } | ||
344 | |||
345 | /** | ||
346 | * Authentication failed | ||
347 | */ | ||
348 | static void | ||
349 | bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, | ||
350 | enum bfa_fcs_fabric_event event) | ||
351 | { | ||
352 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
353 | bfa_trc(fabric->fcs, event); | ||
354 | |||
355 | switch (event) { | ||
356 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
357 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
358 | bfa_fcs_fabric_notify_offline(fabric); | ||
359 | break; | ||
360 | |||
361 | case BFA_FCS_FABRIC_SM_DELETE: | ||
362 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
363 | bfa_fcs_fabric_delete(fabric); | ||
364 | break; | ||
365 | |||
366 | default: | ||
367 | bfa_sm_fault(fabric->fcs, event); | ||
368 | } | ||
369 | } | ||
370 | |||
371 | /** | ||
372 | * Port is in loopback mode. | ||
373 | */ | ||
374 | static void | ||
375 | bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, | ||
376 | enum bfa_fcs_fabric_event event) | ||
377 | { | ||
378 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
379 | bfa_trc(fabric->fcs, event); | ||
380 | |||
381 | switch (event) { | ||
382 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
383 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
384 | bfa_fcs_fabric_notify_offline(fabric); | ||
385 | break; | ||
386 | |||
387 | case BFA_FCS_FABRIC_SM_DELETE: | ||
388 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
389 | bfa_fcs_fabric_delete(fabric); | ||
390 | break; | ||
391 | |||
392 | default: | ||
393 | bfa_sm_fault(fabric->fcs, event); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * There is no attached fabric - private loop or NPort-to-NPort topology. | ||
399 | */ | ||
400 | static void | ||
401 | bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, | ||
402 | enum bfa_fcs_fabric_event event) | ||
403 | { | ||
404 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
405 | bfa_trc(fabric->fcs, event); | ||
406 | |||
407 | switch (event) { | ||
408 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
409 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
410 | bfa_lps_discard(fabric->lps); | ||
411 | bfa_fcs_fabric_notify_offline(fabric); | ||
412 | break; | ||
413 | |||
414 | case BFA_FCS_FABRIC_SM_DELETE: | ||
415 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
416 | bfa_fcs_fabric_delete(fabric); | ||
417 | break; | ||
418 | |||
419 | case BFA_FCS_FABRIC_SM_NO_FABRIC: | ||
420 | bfa_trc(fabric->fcs, fabric->bb_credit); | ||
421 | bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit); | ||
422 | break; | ||
423 | |||
424 | default: | ||
425 | bfa_sm_fault(fabric->fcs, event); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * Fabric is online - normal operating state. | ||
431 | */ | ||
432 | static void | ||
433 | bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, | ||
434 | enum bfa_fcs_fabric_event event) | ||
435 | { | ||
436 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
437 | bfa_trc(fabric->fcs, event); | ||
438 | |||
439 | switch (event) { | ||
440 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
441 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
442 | bfa_lps_discard(fabric->lps); | ||
443 | bfa_fcs_fabric_notify_offline(fabric); | ||
444 | break; | ||
445 | |||
446 | case BFA_FCS_FABRIC_SM_DELETE: | ||
447 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
448 | bfa_fcs_fabric_delete(fabric); | ||
449 | break; | ||
450 | |||
451 | case BFA_FCS_FABRIC_SM_AUTH_FAILED: | ||
452 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); | ||
453 | bfa_lps_discard(fabric->lps); | ||
454 | break; | ||
455 | |||
456 | case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: | ||
457 | break; | ||
458 | |||
459 | default: | ||
460 | bfa_sm_fault(fabric->fcs, event); | ||
461 | } | ||
462 | } | ||
463 | |||
464 | /** | ||
465 | * Exchanging virtual fabric parameters. | ||
466 | */ | ||
467 | static void | ||
468 | bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric, | ||
469 | enum bfa_fcs_fabric_event event) | ||
470 | { | ||
471 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
472 | bfa_trc(fabric->fcs, event); | ||
473 | |||
474 | switch (event) { | ||
475 | case BFA_FCS_FABRIC_SM_CONT_OP: | ||
476 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done); | ||
477 | break; | ||
478 | |||
479 | case BFA_FCS_FABRIC_SM_ISOLATE: | ||
480 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated); | ||
481 | break; | ||
482 | |||
483 | default: | ||
484 | bfa_sm_fault(fabric->fcs, event); | ||
485 | } | ||
486 | } | ||
487 | |||
488 | /** | ||
489 | * EVFP exchange complete and VFT tagging is enabled. | ||
490 | */ | ||
491 | static void | ||
492 | bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric, | ||
493 | enum bfa_fcs_fabric_event event) | ||
494 | { | ||
495 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
496 | bfa_trc(fabric->fcs, event); | ||
497 | } | ||
498 | |||
499 | /** | ||
500 | * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F). | ||
501 | */ | ||
502 | static void | ||
503 | bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric, | ||
504 | enum bfa_fcs_fabric_event event) | ||
505 | { | ||
506 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
507 | bfa_trc(fabric->fcs, event); | ||
508 | |||
509 | bfa_log(fabric->fcs->logm, BFA_LOG_FCS_FABRIC_ISOLATED, | ||
510 | fabric->bport.port_cfg.pwwn, fabric->fcs->port_vfid, | ||
511 | fabric->event_arg.swp_vfid); | ||
512 | } | ||
513 | |||
514 | /** | ||
515 | * Fabric is being deleted, awaiting vport delete completions. | ||
516 | */ | ||
517 | static void | ||
518 | bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric, | ||
519 | enum bfa_fcs_fabric_event event) | ||
520 | { | ||
521 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
522 | bfa_trc(fabric->fcs, event); | ||
523 | |||
524 | switch (event) { | ||
525 | case BFA_FCS_FABRIC_SM_DELCOMP: | ||
526 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | ||
527 | bfa_fcs_modexit_comp(fabric->fcs); | ||
528 | break; | ||
529 | |||
530 | case BFA_FCS_FABRIC_SM_LINK_UP: | ||
531 | break; | ||
532 | |||
533 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
534 | bfa_fcs_fabric_notify_offline(fabric); | ||
535 | break; | ||
536 | |||
537 | default: | ||
538 | bfa_sm_fault(fabric->fcs, event); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | |||
543 | |||
544 | /** | ||
545 | * fcs_fabric_private fabric private functions | ||
546 | */ | ||
547 | |||
548 | static void | ||
549 | bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric) | ||
550 | { | ||
551 | struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg; | ||
552 | |||
553 | port_cfg->roles = BFA_PORT_ROLE_FCP_IM; | ||
554 | port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc); | ||
555 | port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc); | ||
556 | } | ||
557 | |||
558 | /** | ||
559 | * Port Symbolic Name Creation for base port. | ||
560 | */ | ||
561 | void | ||
562 | bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric) | ||
563 | { | ||
564 | struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg; | ||
565 | char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0}; | ||
566 | struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info; | ||
567 | |||
568 | bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model); | ||
569 | |||
570 | /* | ||
571 | * Model name/number | ||
572 | */ | ||
573 | strncpy((char *)&port_cfg->sym_name, model, | ||
574 | BFA_FCS_PORT_SYMBNAME_MODEL_SZ); | ||
575 | strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
576 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
577 | |||
578 | /* | ||
579 | * Driver Version | ||
580 | */ | ||
581 | strncat((char *)&port_cfg->sym_name, (char *)driver_info->version, | ||
582 | BFA_FCS_PORT_SYMBNAME_VERSION_SZ); | ||
583 | strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
584 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
585 | |||
586 | /* | ||
587 | * Host machine name | ||
588 | */ | ||
589 | strncat((char *)&port_cfg->sym_name, | ||
590 | (char *)driver_info->host_machine_name, | ||
591 | BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ); | ||
592 | strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
593 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
594 | |||
595 | /* | ||
596 | * Host OS Info : | ||
597 | * If OS Patch Info is not there, do not truncate any bytes from the | ||
598 | * OS name string and instead copy the entire OS info string (64 bytes). | ||
599 | */ | ||
600 | if (driver_info->host_os_patch[0] == '\0') { | ||
601 | strncat((char *)&port_cfg->sym_name, | ||
602 | (char *)driver_info->host_os_name, BFA_FCS_OS_STR_LEN); | ||
603 | strncat((char *)&port_cfg->sym_name, | ||
604 | BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
605 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
606 | } else { | ||
607 | strncat((char *)&port_cfg->sym_name, | ||
608 | (char *)driver_info->host_os_name, | ||
609 | BFA_FCS_PORT_SYMBNAME_OSINFO_SZ); | ||
610 | strncat((char *)&port_cfg->sym_name, | ||
611 | BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
612 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
613 | |||
614 | /* | ||
615 | * Append host OS Patch Info | ||
616 | */ | ||
617 | strncat((char *)&port_cfg->sym_name, | ||
618 | (char *)driver_info->host_os_patch, | ||
619 | BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ); | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | * null terminate | ||
624 | */ | ||
625 | port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0; | ||
626 | } | ||
627 | |||
628 | /** | ||
629 | * bfa lps login completion callback | ||
630 | */ | ||
631 | void | ||
632 | bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status) | ||
633 | { | ||
634 | struct bfa_fcs_fabric_s *fabric = uarg; | ||
635 | |||
636 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
637 | bfa_trc(fabric->fcs, status); | ||
638 | |||
639 | switch (status) { | ||
640 | case BFA_STATUS_OK: | ||
641 | fabric->stats.flogi_accepts++; | ||
642 | break; | ||
643 | |||
644 | case BFA_STATUS_INVALID_MAC: | ||
645 | /* | ||
646 | * Only for CNA | ||
647 | */ | ||
648 | fabric->stats.flogi_acc_err++; | ||
649 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | ||
650 | |||
651 | return; | ||
652 | |||
653 | case BFA_STATUS_EPROTOCOL: | ||
654 | switch (bfa_lps_get_extstatus(fabric->lps)) { | ||
655 | case BFA_EPROTO_BAD_ACCEPT: | ||
656 | fabric->stats.flogi_acc_err++; | ||
657 | break; | ||
658 | |||
659 | case BFA_EPROTO_UNKNOWN_RSP: | ||
660 | fabric->stats.flogi_unknown_rsp++; | ||
661 | break; | ||
662 | |||
663 | default: | ||
664 | break; | ||
665 | } | ||
666 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | ||
667 | |||
668 | return; | ||
669 | |||
670 | case BFA_STATUS_FABRIC_RJT: | ||
671 | fabric->stats.flogi_rejects++; | ||
672 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | ||
673 | return; | ||
674 | |||
675 | default: | ||
676 | fabric->stats.flogi_rsp_err++; | ||
677 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | ||
678 | return; | ||
679 | } | ||
680 | |||
681 | fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps); | ||
682 | bfa_trc(fabric->fcs, fabric->bb_credit); | ||
683 | |||
684 | if (!bfa_lps_is_brcd_fabric(fabric->lps)) | ||
685 | fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps); | ||
686 | |||
687 | /* | ||
688 | * Check port type. It should be 1 = F-port. | ||
689 | */ | ||
690 | if (bfa_lps_is_fport(fabric->lps)) { | ||
691 | fabric->bport.pid = bfa_lps_get_pid(fabric->lps); | ||
692 | fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps); | ||
693 | fabric->is_auth = bfa_lps_is_authreq(fabric->lps); | ||
694 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP); | ||
695 | } else { | ||
696 | /* | ||
697 | * Nport-2-Nport direct attached | ||
698 | */ | ||
699 | fabric->bport.port_topo.pn2n.rem_port_wwn = | ||
700 | bfa_lps_get_peer_pwwn(fabric->lps); | ||
701 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC); | ||
702 | } | ||
703 | |||
704 | bfa_trc(fabric->fcs, fabric->bport.pid); | ||
705 | bfa_trc(fabric->fcs, fabric->is_npiv); | ||
706 | bfa_trc(fabric->fcs, fabric->is_auth); | ||
707 | } | ||
708 | |||
709 | /** | ||
710 | * Allocate and send FLOGI. | ||
711 | */ | ||
712 | static void | ||
713 | bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric) | ||
714 | { | ||
715 | struct bfa_s *bfa = fabric->fcs->bfa; | ||
716 | struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg; | ||
717 | u8 alpa = 0; | ||
718 | |||
719 | if (bfa_fcport_get_topology(bfa) == BFA_PPORT_TOPOLOGY_LOOP) | ||
720 | alpa = bfa_fcport_get_myalpa(bfa); | ||
721 | |||
722 | bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa), | ||
723 | pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd); | ||
724 | |||
725 | fabric->stats.flogi_sent++; | ||
726 | } | ||
727 | |||
728 | static void | ||
729 | bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric) | ||
730 | { | ||
731 | struct bfa_fcs_vport_s *vport; | ||
732 | struct list_head *qe, *qen; | ||
733 | |||
734 | bfa_trc(fabric->fcs, fabric->fabric_name); | ||
735 | |||
736 | bfa_fcs_fabric_set_opertype(fabric); | ||
737 | fabric->stats.fabric_onlines++; | ||
738 | |||
739 | /** | ||
740 | * notify online event to base and then virtual ports | ||
741 | */ | ||
742 | bfa_fcs_port_online(&fabric->bport); | ||
743 | |||
744 | list_for_each_safe(qe, qen, &fabric->vport_q) { | ||
745 | vport = (struct bfa_fcs_vport_s *)qe; | ||
746 | bfa_fcs_vport_online(vport); | ||
747 | } | ||
748 | } | ||
749 | |||
750 | static void | ||
751 | bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric) | ||
752 | { | ||
753 | struct bfa_fcs_vport_s *vport; | ||
754 | struct list_head *qe, *qen; | ||
755 | |||
756 | bfa_trc(fabric->fcs, fabric->fabric_name); | ||
757 | fabric->stats.fabric_offlines++; | ||
758 | |||
759 | /** | ||
760 | * notify offline event first to vports and then base port. | ||
761 | */ | ||
762 | list_for_each_safe(qe, qen, &fabric->vport_q) { | ||
763 | vport = (struct bfa_fcs_vport_s *)qe; | ||
764 | bfa_fcs_vport_offline(vport); | ||
765 | } | ||
766 | |||
767 | bfa_fcs_port_offline(&fabric->bport); | ||
768 | |||
769 | fabric->fabric_name = 0; | ||
770 | fabric->fabric_ip_addr[0] = 0; | ||
771 | } | ||
772 | |||
773 | static void | ||
774 | bfa_fcs_fabric_delay(void *cbarg) | ||
775 | { | ||
776 | struct bfa_fcs_fabric_s *fabric = cbarg; | ||
777 | |||
778 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED); | ||
779 | } | ||
780 | |||
781 | /** | ||
782 | * Delete all vports and wait for vport delete completions. | ||
783 | */ | ||
784 | static void | ||
785 | bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric) | ||
786 | { | ||
787 | struct bfa_fcs_vport_s *vport; | ||
788 | struct list_head *qe, *qen; | ||
789 | |||
790 | list_for_each_safe(qe, qen, &fabric->vport_q) { | ||
791 | vport = (struct bfa_fcs_vport_s *)qe; | ||
792 | bfa_fcs_vport_fcs_delete(vport); | ||
793 | } | ||
794 | |||
795 | bfa_fcs_port_delete(&fabric->bport); | ||
796 | bfa_wc_wait(&fabric->wc); | ||
797 | } | ||
798 | |||
799 | static void | ||
800 | bfa_fcs_fabric_delete_comp(void *cbarg) | ||
801 | { | ||
802 | struct bfa_fcs_fabric_s *fabric = cbarg; | ||
803 | |||
804 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP); | ||
805 | } | ||
806 | |||
807 | |||
808 | |||
809 | /** | ||
810 | * fcs_fabric_public fabric public functions | ||
811 | */ | ||
812 | |||
813 | /** | ||
814 | * Attach time initialization | ||
815 | */ | ||
816 | void | ||
817 | bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs) | ||
818 | { | ||
819 | struct bfa_fcs_fabric_s *fabric; | ||
820 | |||
821 | fabric = &fcs->fabric; | ||
822 | bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s)); | ||
823 | |||
824 | /** | ||
825 | * Initialize base fabric. | ||
826 | */ | ||
827 | fabric->fcs = fcs; | ||
828 | INIT_LIST_HEAD(&fabric->vport_q); | ||
829 | INIT_LIST_HEAD(&fabric->vf_q); | ||
830 | fabric->lps = bfa_lps_alloc(fcs->bfa); | ||
831 | bfa_assert(fabric->lps); | ||
832 | |||
833 | /** | ||
834 | * Initialize fabric delete completion handler. Fabric deletion is complete | ||
835 | * when the last vport delete is complete. | ||
836 | */ | ||
837 | bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric); | ||
838 | bfa_wc_up(&fabric->wc); /* For the base port */ | ||
839 | |||
840 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | ||
841 | bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL); | ||
842 | } | ||
843 | |||
844 | void | ||
845 | bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs) | ||
846 | { | ||
847 | bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE); | ||
848 | bfa_trc(fcs, 0); | ||
849 | } | ||
850 | |||
851 | /** | ||
852 | * Module cleanup | ||
853 | */ | ||
854 | void | ||
855 | bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs) | ||
856 | { | ||
857 | struct bfa_fcs_fabric_s *fabric; | ||
858 | |||
859 | bfa_trc(fcs, 0); | ||
860 | |||
861 | /** | ||
862 | * Cleanup base fabric. | ||
863 | */ | ||
864 | fabric = &fcs->fabric; | ||
865 | bfa_lps_delete(fabric->lps); | ||
866 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE); | ||
867 | } | ||
868 | |||
869 | /** | ||
870 | * Fabric module start -- kick starts FCS actions | ||
871 | */ | ||
872 | void | ||
873 | bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs) | ||
874 | { | ||
875 | struct bfa_fcs_fabric_s *fabric; | ||
876 | |||
877 | bfa_trc(fcs, 0); | ||
878 | fabric = &fcs->fabric; | ||
879 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START); | ||
880 | } | ||
881 | |||
882 | /** | ||
883 | * Suspend fabric activity as part of driver suspend. | ||
884 | */ | ||
885 | void | ||
886 | bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs) | ||
887 | { | ||
888 | } | ||
889 | |||
890 | bfa_boolean_t | ||
891 | bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric) | ||
892 | { | ||
893 | return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback); | ||
894 | } | ||
895 | |||
896 | bfa_boolean_t | ||
897 | bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric) | ||
898 | { | ||
899 | return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed); | ||
900 | } | ||
901 | |||
902 | enum bfa_pport_type | ||
903 | bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric) | ||
904 | { | ||
905 | return fabric->oper_type; | ||
906 | } | ||
907 | |||
908 | /** | ||
909 | * Link up notification from BFA physical port module. | ||
910 | */ | ||
911 | void | ||
912 | bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric) | ||
913 | { | ||
914 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
915 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP); | ||
916 | } | ||
917 | |||
918 | /** | ||
919 | * Link down notification from BFA physical port module. | ||
920 | */ | ||
921 | void | ||
922 | bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric) | ||
923 | { | ||
924 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
925 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN); | ||
926 | } | ||
927 | |||
928 | /** | ||
929 | * A child vport is being created in the fabric. | ||
930 | * | ||
931 | * Call from vport module at vport creation. A list of base port and vports | ||
932 | * belonging to a fabric is maintained to propagate link events. | ||
933 | * | ||
934 | * param[in] fabric - Fabric instance. This can be a base fabric or vf. | ||
935 | * param[in] vport - Vport being created. | ||
936 | * | ||
937 | * @return None (always succeeds) | ||
938 | */ | ||
939 | void | ||
940 | bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric, | ||
941 | struct bfa_fcs_vport_s *vport) | ||
942 | { | ||
943 | /** | ||
944 | * - add vport to fabric's vport_q | ||
945 | */ | ||
946 | bfa_trc(fabric->fcs, fabric->vf_id); | ||
947 | |||
948 | list_add_tail(&vport->qe, &fabric->vport_q); | ||
949 | fabric->num_vports++; | ||
950 | bfa_wc_up(&fabric->wc); | ||
951 | } | ||
952 | |||
953 | /** | ||
954 | * A child vport is being deleted from fabric. | ||
955 | * | ||
956 | * Vport is being deleted. | ||
957 | */ | ||
958 | void | ||
959 | bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric, | ||
960 | struct bfa_fcs_vport_s *vport) | ||
961 | { | ||
962 | list_del(&vport->qe); | ||
963 | fabric->num_vports--; | ||
964 | bfa_wc_down(&fabric->wc); | ||
965 | } | ||
966 | |||
967 | /** | ||
968 | * Base port is deleted. | ||
969 | */ | ||
970 | void | ||
971 | bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric) | ||
972 | { | ||
973 | bfa_wc_down(&fabric->wc); | ||
974 | } | ||
975 | |||
976 | /** | ||
977 | * Check if fabric is online. | ||
978 | * | ||
979 | * param[in] fabric - Fabric instance. This can be a base fabric or vf. | ||
980 | * | ||
981 | * @return TRUE/FALSE | ||
982 | */ | ||
983 | int | ||
984 | bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric) | ||
985 | { | ||
986 | return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online); | ||
987 | } | ||
988 | |||
989 | |||
990 | bfa_status_t | ||
991 | bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs, | ||
992 | struct bfa_port_cfg_s *port_cfg, | ||
993 | struct bfad_vf_s *vf_drv) | ||
994 | { | ||
995 | bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit); | ||
996 | return BFA_STATUS_OK; | ||
997 | } | ||
998 | |||
999 | /** | ||
1000 | * Lookup for a vport withing a fabric given its pwwn | ||
1001 | */ | ||
1002 | struct bfa_fcs_vport_s * | ||
1003 | bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn) | ||
1004 | { | ||
1005 | struct bfa_fcs_vport_s *vport; | ||
1006 | struct list_head *qe; | ||
1007 | |||
1008 | list_for_each(qe, &fabric->vport_q) { | ||
1009 | vport = (struct bfa_fcs_vport_s *)qe; | ||
1010 | if (bfa_fcs_port_get_pwwn(&vport->lport) == pwwn) | ||
1011 | return vport; | ||
1012 | } | ||
1013 | |||
1014 | return NULL; | ||
1015 | } | ||
1016 | |||
1017 | /** | ||
1018 | * In a given fabric, return the number of lports. | ||
1019 | * | ||
1020 | * param[in] fabric - Fabric instance. This can be a base fabric or vf. | ||
1021 | * | ||
1022 | * @return : 1 or more. | ||
1023 | */ | ||
1024 | u16 | ||
1025 | bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric) | ||
1026 | { | ||
1027 | return fabric->num_vports; | ||
1028 | } | ||
1029 | |||
1030 | /* | ||
1031 | * Get OUI of the attached switch. | ||
1032 | * | ||
1033 | * Note : Use of this function should be avoided as much as possible. | ||
1034 | * This function should be used only if there is any requirement | ||
1035 | * to check for FOS version below 6.3. | ||
1036 | * To check if the attached fabric is a brocade fabric, use | ||
1037 | * bfa_lps_is_brcd_fabric() which works for FOS versions 6.3 | ||
1038 | * or above only. | ||
1039 | */ | ||
1040 | |||
1041 | u16 | ||
1042 | bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric) | ||
1043 | { | ||
1044 | wwn_t fab_nwwn; | ||
1045 | u8 *tmp; | ||
1046 | u16 oui; | ||
1047 | |||
1048 | fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps); | ||
1049 | |||
1050 | tmp = (uint8_t *)&fab_nwwn; | ||
1051 | oui = (tmp[3] << 8) | tmp[4]; | ||
1052 | |||
1053 | return oui; | ||
1054 | } | ||
1055 | |||
1056 | /** | ||
1057 | * Unsolicited frame receive handling. | ||
1058 | */ | ||
1059 | void | ||
1060 | bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs, | ||
1061 | u16 len) | ||
1062 | { | ||
1063 | u32 pid = fchs->d_id; | ||
1064 | struct bfa_fcs_vport_s *vport; | ||
1065 | struct list_head *qe; | ||
1066 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
1067 | struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd; | ||
1068 | |||
1069 | bfa_trc(fabric->fcs, len); | ||
1070 | bfa_trc(fabric->fcs, pid); | ||
1071 | |||
1072 | /** | ||
1073 | * Look for our own FLOGI frames being looped back. This means an | ||
1074 | * external loopback cable is in place. Our own FLOGI frames are | ||
1075 | * sometimes looped back when switch port gets temporarily bypassed. | ||
1076 | */ | ||
1077 | if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT)) | ||
1078 | && (els_cmd->els_code == FC_ELS_FLOGI) | ||
1079 | && (flogi->port_name == bfa_fcs_port_get_pwwn(&fabric->bport))) { | ||
1080 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK); | ||
1081 | return; | ||
1082 | } | ||
1083 | |||
1084 | /** | ||
1085 | * FLOGI/EVFP exchanges should be consumed by base fabric. | ||
1086 | */ | ||
1087 | if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) { | ||
1088 | bfa_trc(fabric->fcs, pid); | ||
1089 | bfa_fcs_fabric_process_uf(fabric, fchs, len); | ||
1090 | return; | ||
1091 | } | ||
1092 | |||
1093 | if (fabric->bport.pid == pid) { | ||
1094 | /** | ||
1095 | * All authentication frames should be routed to auth | ||
1096 | */ | ||
1097 | bfa_trc(fabric->fcs, els_cmd->els_code); | ||
1098 | if (els_cmd->els_code == FC_ELS_AUTH) { | ||
1099 | bfa_trc(fabric->fcs, els_cmd->els_code); | ||
1100 | fabric->auth.response = (u8 *) els_cmd; | ||
1101 | return; | ||
1102 | } | ||
1103 | |||
1104 | bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs)); | ||
1105 | bfa_fcs_port_uf_recv(&fabric->bport, fchs, len); | ||
1106 | return; | ||
1107 | } | ||
1108 | |||
1109 | /** | ||
1110 | * look for a matching local port ID | ||
1111 | */ | ||
1112 | list_for_each(qe, &fabric->vport_q) { | ||
1113 | vport = (struct bfa_fcs_vport_s *)qe; | ||
1114 | if (vport->lport.pid == pid) { | ||
1115 | bfa_fcs_port_uf_recv(&vport->lport, fchs, len); | ||
1116 | return; | ||
1117 | } | ||
1118 | } | ||
1119 | bfa_trc(fabric->fcs, els_cmd->els_code); | ||
1120 | bfa_fcs_port_uf_recv(&fabric->bport, fchs, len); | ||
1121 | } | ||
1122 | |||
1123 | /** | ||
1124 | * Unsolicited frames to be processed by fabric. | ||
1125 | */ | ||
1126 | static void | ||
1127 | bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs, | ||
1128 | u16 len) | ||
1129 | { | ||
1130 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
1131 | |||
1132 | bfa_trc(fabric->fcs, els_cmd->els_code); | ||
1133 | |||
1134 | switch (els_cmd->els_code) { | ||
1135 | case FC_ELS_FLOGI: | ||
1136 | bfa_fcs_fabric_process_flogi(fabric, fchs, len); | ||
1137 | break; | ||
1138 | |||
1139 | default: | ||
1140 | /* | ||
1141 | * need to generate a LS_RJT | ||
1142 | */ | ||
1143 | break; | ||
1144 | } | ||
1145 | } | ||
1146 | |||
1147 | /** | ||
1148 | * Process incoming FLOGI | ||
1149 | */ | ||
1150 | static void | ||
1151 | bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, | ||
1152 | struct fchs_s *fchs, u16 len) | ||
1153 | { | ||
1154 | struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1); | ||
1155 | struct bfa_fcs_port_s *bport = &fabric->bport; | ||
1156 | |||
1157 | bfa_trc(fabric->fcs, fchs->s_id); | ||
1158 | |||
1159 | fabric->stats.flogi_rcvd++; | ||
1160 | /* | ||
1161 | * Check port type. It should be 0 = n-port. | ||
1162 | */ | ||
1163 | if (flogi->csp.port_type) { | ||
1164 | /* | ||
1165 | * @todo: may need to send a LS_RJT | ||
1166 | */ | ||
1167 | bfa_trc(fabric->fcs, flogi->port_name); | ||
1168 | fabric->stats.flogi_rejected++; | ||
1169 | return; | ||
1170 | } | ||
1171 | |||
1172 | fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred); | ||
1173 | bport->port_topo.pn2n.rem_port_wwn = flogi->port_name; | ||
1174 | bport->port_topo.pn2n.reply_oxid = fchs->ox_id; | ||
1175 | |||
1176 | /* | ||
1177 | * Send a Flogi Acc | ||
1178 | */ | ||
1179 | bfa_fcs_fabric_send_flogi_acc(fabric); | ||
1180 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC); | ||
1181 | } | ||
1182 | |||
1183 | static void | ||
1184 | bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric) | ||
1185 | { | ||
1186 | struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg; | ||
1187 | struct bfa_fcs_port_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n; | ||
1188 | struct bfa_s *bfa = fabric->fcs->bfa; | ||
1189 | struct bfa_fcxp_s *fcxp; | ||
1190 | u16 reqlen; | ||
1191 | struct fchs_s fchs; | ||
1192 | |||
1193 | fcxp = bfa_fcs_fcxp_alloc(fabric->fcs); | ||
1194 | /** | ||
1195 | * Do not expect this failure -- expect remote node to retry | ||
1196 | */ | ||
1197 | if (!fcxp) | ||
1198 | return; | ||
1199 | |||
1200 | reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
1201 | bfa_os_hton3b(FC_FABRIC_PORT), | ||
1202 | n2n_port->reply_oxid, pcfg->pwwn, | ||
1203 | pcfg->nwwn, bfa_fcport_get_maxfrsize(bfa), | ||
1204 | bfa_fcport_get_rx_bbcredit(bfa)); | ||
1205 | |||
1206 | bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps), | ||
1207 | BFA_FALSE, FC_CLASS_3, reqlen, &fchs, | ||
1208 | bfa_fcs_fabric_flogiacc_comp, fabric, | ||
1209 | FC_MAX_PDUSZ, 0); /* Timeout 0 indicates no | ||
1210 | * response expected | ||
1211 | */ | ||
1212 | } | ||
1213 | |||
1214 | /** | ||
1215 | * Flogi Acc completion callback. | ||
1216 | */ | ||
1217 | static void | ||
1218 | bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, | ||
1219 | bfa_status_t status, u32 rsp_len, | ||
1220 | u32 resid_len, struct fchs_s *rspfchs) | ||
1221 | { | ||
1222 | struct bfa_fcs_fabric_s *fabric = cbarg; | ||
1223 | |||
1224 | bfa_trc(fabric->fcs, status); | ||
1225 | } | ||
1226 | |||
1227 | /* | ||
1228 | * | ||
1229 | * @param[in] fabric - fabric | ||
1230 | * @param[in] result - 1 | ||
1231 | * | ||
1232 | * @return - none | ||
1233 | */ | ||
1234 | void | ||
1235 | bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, enum auth_status status) | ||
1236 | { | ||
1237 | bfa_trc(fabric->fcs, status); | ||
1238 | |||
1239 | if (status == FC_AUTH_STATE_SUCCESS) | ||
1240 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_SUCCESS); | ||
1241 | else | ||
1242 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_FAILED); | ||
1243 | } | ||
1244 | |||
1245 | /** | ||
1246 | * Send AEN notification | ||
1247 | */ | ||
1248 | static void | ||
1249 | bfa_fcs_fabric_aen_post(struct bfa_fcs_port_s *port, | ||
1250 | enum bfa_port_aen_event event) | ||
1251 | { | ||
1252 | union bfa_aen_data_u aen_data; | ||
1253 | struct bfa_log_mod_s *logmod = port->fcs->logm; | ||
1254 | wwn_t pwwn = bfa_fcs_port_get_pwwn(port); | ||
1255 | wwn_t fwwn = bfa_fcs_port_get_fabric_name(port); | ||
1256 | char pwwn_ptr[BFA_STRING_32]; | ||
1257 | char fwwn_ptr[BFA_STRING_32]; | ||
1258 | |||
1259 | wwn2str(pwwn_ptr, pwwn); | ||
1260 | wwn2str(fwwn_ptr, fwwn); | ||
1261 | |||
1262 | bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, event), | ||
1263 | pwwn_ptr, fwwn_ptr); | ||
1264 | |||
1265 | aen_data.port.pwwn = pwwn; | ||
1266 | aen_data.port.fwwn = fwwn; | ||
1267 | } | ||
1268 | |||
1269 | /* | ||
1270 | * | ||
1271 | * @param[in] fabric - fabric | ||
1272 | * @param[in] wwn_t - new fabric name | ||
1273 | * | ||
1274 | * @return - none | ||
1275 | */ | ||
1276 | void | ||
1277 | bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, | ||
1278 | wwn_t fabric_name) | ||
1279 | { | ||
1280 | bfa_trc(fabric->fcs, fabric_name); | ||
1281 | |||
1282 | if (fabric->fabric_name == 0) { | ||
1283 | /* | ||
1284 | * With BRCD switches, we don't get Fabric Name in FLOGI. | ||
1285 | * Don't generate a fabric name change event in this case. | ||
1286 | */ | ||
1287 | fabric->fabric_name = fabric_name; | ||
1288 | } else { | ||
1289 | fabric->fabric_name = fabric_name; | ||
1290 | /* | ||
1291 | * Generate a Event | ||
1292 | */ | ||
1293 | bfa_fcs_fabric_aen_post(&fabric->bport, | ||
1294 | BFA_PORT_AEN_FABRIC_NAME_CHANGE); | ||
1295 | } | ||
1296 | |||
1297 | } | ||
1298 | |||
1299 | /** | ||
1300 | * | ||
1301 | * @param[in] fabric - fabric | ||
1302 | * @param[in] node_symname - | ||
1303 | * Caller allocated buffer to receive the symbolic name | ||
1304 | * | ||
1305 | * @return - none | ||
1306 | */ | ||
1307 | void | ||
1308 | bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname) | ||
1309 | { | ||
1310 | bfa_os_memcpy(node_symname, | ||
1311 | fcs->fabric.bport.port_cfg.sym_name.symname, | ||
1312 | BFA_SYMNAME_MAXLEN); | ||
1313 | } | ||
1314 | |||
1315 | /** | ||
1316 | * Not used by FCS. | ||
1317 | */ | ||
1318 | void | ||
1319 | bfa_cb_lps_flogo_comp(void *bfad, void *uarg) | ||
1320 | { | ||
1321 | } | ||
1322 | |||
1323 | |||