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