Commit | Line | Data |
---|---|---|
7725ccfd | 1 | /* |
a36c61f9 | 2 | * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. |
7725ccfd JH |
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 | ||
5fbe25c7 | 18 | /* |
7725ccfd JH |
19 | * bfa_fcs.c BFA FCS main |
20 | */ | |
21 | ||
f16a1750 | 22 | #include "bfad_drv.h" |
a36c61f9 KG |
23 | #include "bfa_fcs.h" |
24 | #include "bfa_fcbuild.h" | |
a36c61f9 KG |
25 | |
26 | BFA_TRC_FILE(FCS, FCS); | |
7725ccfd | 27 | |
5fbe25c7 | 28 | /* |
7725ccfd JH |
29 | * FCS sub-modules |
30 | */ | |
31 | struct bfa_fcs_mod_s { | |
82794a2e | 32 | void (*attach) (struct bfa_fcs_s *fcs); |
a36c61f9 KG |
33 | void (*modinit) (struct bfa_fcs_s *fcs); |
34 | void (*modexit) (struct bfa_fcs_s *fcs); | |
7725ccfd JH |
35 | }; |
36 | ||
37 | #define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit } | |
38 | ||
39 | static struct bfa_fcs_mod_s fcs_modules[] = { | |
a36c61f9 | 40 | { bfa_fcs_port_attach, NULL, NULL }, |
82794a2e KG |
41 | { bfa_fcs_uf_attach, NULL, NULL }, |
42 | { bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit, | |
a36c61f9 | 43 | bfa_fcs_fabric_modexit }, |
7725ccfd JH |
44 | }; |
45 | ||
5fbe25c7 | 46 | /* |
7725ccfd JH |
47 | * fcs_api BFA FCS API |
48 | */ | |
49 | ||
50 | static void | |
51 | bfa_fcs_exit_comp(void *fcs_cbarg) | |
52 | { | |
a36c61f9 KG |
53 | struct bfa_fcs_s *fcs = fcs_cbarg; |
54 | struct bfad_s *bfad = fcs->bfad; | |
7725ccfd JH |
55 | |
56 | complete(&bfad->comp); | |
57 | } | |
58 | ||
59 | ||
60 | ||
5fbe25c7 | 61 | /* |
7725ccfd JH |
62 | * fcs_api BFA FCS API |
63 | */ | |
64 | ||
5fbe25c7 | 65 | /* |
82794a2e | 66 | * fcs attach -- called once to initialize data structures at driver attach time |
7725ccfd JH |
67 | */ |
68 | void | |
82794a2e | 69 | bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, |
a36c61f9 | 70 | bfa_boolean_t min_cfg) |
7725ccfd | 71 | { |
a36c61f9 | 72 | int i; |
7725ccfd JH |
73 | struct bfa_fcs_mod_s *mod; |
74 | ||
75 | fcs->bfa = bfa; | |
76 | fcs->bfad = bfad; | |
77 | fcs->min_cfg = min_cfg; | |
78 | ||
f7f73812 | 79 | bfa->fcs = BFA_TRUE; |
7725ccfd JH |
80 | fcbuild_init(); |
81 | ||
a36c61f9 | 82 | for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { |
7725ccfd | 83 | mod = &fcs_modules[i]; |
82794a2e KG |
84 | if (mod->attach) |
85 | mod->attach(fcs); | |
86 | } | |
87 | } | |
88 | ||
5fbe25c7 | 89 | /* |
82794a2e KG |
90 | * fcs initialization, called once after bfa initialization is complete |
91 | */ | |
92 | void | |
93 | bfa_fcs_init(struct bfa_fcs_s *fcs) | |
94 | { | |
75332a70 | 95 | int i; |
82794a2e KG |
96 | struct bfa_fcs_mod_s *mod; |
97 | ||
a36c61f9 | 98 | for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { |
82794a2e KG |
99 | mod = &fcs_modules[i]; |
100 | if (mod->modinit) | |
101 | mod->modinit(fcs); | |
7725ccfd | 102 | } |
75332a70 KG |
103 | } |
104 | ||
105 | /* | |
106 | * FCS update cfg - reset the pwwn/nwwn of fabric base logical port | |
107 | * with values learned during bfa_init firmware GETATTR REQ. | |
108 | */ | |
109 | void | |
110 | bfa_fcs_update_cfg(struct bfa_fcs_s *fcs) | |
111 | { | |
112 | struct bfa_fcs_fabric_s *fabric = &fcs->fabric; | |
113 | struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg; | |
114 | struct bfa_ioc_s *ioc = &fabric->fcs->bfa->ioc; | |
115 | ||
116 | port_cfg->nwwn = ioc->attr->nwwn; | |
117 | port_cfg->pwwn = ioc->attr->pwwn; | |
118 | } | |
119 | ||
120 | /* | |
121 | * fcs pbc vport initialization | |
122 | */ | |
123 | void | |
124 | bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs) | |
125 | { | |
126 | int i, npbc_vports; | |
127 | struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS]; | |
128 | ||
d9883548 JH |
129 | /* Initialize pbc vports */ |
130 | if (!fcs->min_cfg) { | |
131 | npbc_vports = | |
75332a70 | 132 | bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports); |
d9883548 JH |
133 | for (i = 0; i < npbc_vports; i++) |
134 | bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]); | |
135 | } | |
7725ccfd JH |
136 | } |
137 | ||
5fbe25c7 | 138 | /* |
a36c61f9 KG |
139 | * brief |
140 | * FCS driver details initialization. | |
7725ccfd | 141 | * |
a36c61f9 KG |
142 | * param[in] fcs FCS instance |
143 | * param[in] driver_info Driver Details | |
7725ccfd | 144 | * |
a36c61f9 | 145 | * return None |
7725ccfd JH |
146 | */ |
147 | void | |
148 | bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, | |
149 | struct bfa_fcs_driver_info_s *driver_info) | |
150 | { | |
151 | ||
152 | fcs->driver_info = *driver_info; | |
153 | ||
154 | bfa_fcs_fabric_psymb_init(&fcs->fabric); | |
155 | } | |
156 | ||
5fbe25c7 | 157 | /* |
a36c61f9 KG |
158 | * brief |
159 | * FCS instance cleanup and exit. | |
7725ccfd | 160 | * |
a36c61f9 KG |
161 | * param[in] fcs FCS instance |
162 | * return None | |
7725ccfd JH |
163 | */ |
164 | void | |
165 | bfa_fcs_exit(struct bfa_fcs_s *fcs) | |
166 | { | |
167 | struct bfa_fcs_mod_s *mod; | |
a36c61f9 | 168 | int nmods, i; |
7725ccfd JH |
169 | |
170 | bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs); | |
171 | ||
a36c61f9 KG |
172 | nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]); |
173 | ||
174 | for (i = 0; i < nmods; i++) { | |
7725ccfd JH |
175 | |
176 | mod = &fcs_modules[i]; | |
82794a2e KG |
177 | if (mod->modexit) { |
178 | bfa_wc_up(&fcs->wc); | |
179 | mod->modexit(fcs); | |
180 | } | |
7725ccfd JH |
181 | } |
182 | ||
183 | bfa_wc_wait(&fcs->wc); | |
184 | } | |
185 | ||
186 | ||
5fbe25c7 | 187 | /* |
a36c61f9 KG |
188 | * Fabric module implementation. |
189 | */ | |
190 | ||
191 | #define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */ | |
192 | #define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */ | |
193 | ||
194 | #define bfa_fcs_fabric_set_opertype(__fabric) do { \ | |
195 | if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \ | |
196 | == BFA_PORT_TOPOLOGY_P2P) \ | |
197 | (__fabric)->oper_type = BFA_PORT_TYPE_NPORT; \ | |
198 | else \ | |
199 | (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT; \ | |
200 | } while (0) | |
201 | ||
202 | /* | |
203 | * forward declarations | |
204 | */ | |
205 | static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric); | |
206 | static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric); | |
207 | static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric); | |
208 | static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric); | |
209 | static void bfa_fcs_fabric_delay(void *cbarg); | |
210 | static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric); | |
211 | static void bfa_fcs_fabric_delete_comp(void *cbarg); | |
212 | static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, | |
213 | struct fchs_s *fchs, u16 len); | |
214 | static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, | |
215 | struct fchs_s *fchs, u16 len); | |
216 | static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric); | |
217 | static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg, | |
218 | struct bfa_fcxp_s *fcxp, void *cbarg, | |
219 | bfa_status_t status, | |
220 | u32 rsp_len, | |
221 | u32 resid_len, | |
222 | struct fchs_s *rspfchs); | |
be540a99 KG |
223 | static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric); |
224 | static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled( | |
225 | struct bfa_fcs_fabric_s *fabric); | |
a36c61f9 KG |
226 | |
227 | static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, | |
228 | enum bfa_fcs_fabric_event event); | |
229 | static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric, | |
230 | enum bfa_fcs_fabric_event event); | |
231 | static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric, | |
232 | enum bfa_fcs_fabric_event event); | |
233 | static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, | |
234 | enum bfa_fcs_fabric_event event); | |
235 | static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric, | |
236 | enum bfa_fcs_fabric_event event); | |
237 | static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, | |
238 | enum bfa_fcs_fabric_event event); | |
a36c61f9 KG |
239 | static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, |
240 | enum bfa_fcs_fabric_event event); | |
a36c61f9 KG |
241 | static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric, |
242 | enum bfa_fcs_fabric_event event); | |
243 | static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric, | |
244 | enum bfa_fcs_fabric_event event); | |
245 | static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric, | |
246 | enum bfa_fcs_fabric_event event); | |
247 | static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric, | |
248 | enum bfa_fcs_fabric_event event); | |
5fbe25c7 | 249 | /* |
a36c61f9 KG |
250 | * Beginning state before fabric creation. |
251 | */ | |
252 | static void | |
253 | bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, | |
254 | enum bfa_fcs_fabric_event event) | |
255 | { | |
256 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
257 | bfa_trc(fabric->fcs, event); | |
258 | ||
259 | switch (event) { | |
260 | case BFA_FCS_FABRIC_SM_CREATE: | |
261 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created); | |
262 | bfa_fcs_fabric_init(fabric); | |
263 | bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg); | |
264 | break; | |
265 | ||
266 | case BFA_FCS_FABRIC_SM_LINK_UP: | |
267 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
268 | break; | |
269 | ||
270 | default: | |
271 | bfa_sm_fault(fabric->fcs, event); | |
272 | } | |
273 | } | |
274 | ||
5fbe25c7 | 275 | /* |
a36c61f9 KG |
276 | * Beginning state before fabric creation. |
277 | */ | |
278 | static void | |
279 | bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric, | |
280 | enum bfa_fcs_fabric_event event) | |
281 | { | |
282 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
283 | bfa_trc(fabric->fcs, event); | |
284 | ||
285 | switch (event) { | |
286 | case BFA_FCS_FABRIC_SM_START: | |
287 | if (bfa_fcport_is_linkup(fabric->fcs->bfa)) { | |
288 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); | |
289 | bfa_fcs_fabric_login(fabric); | |
290 | } else | |
291 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | |
292 | break; | |
293 | ||
294 | case BFA_FCS_FABRIC_SM_LINK_UP: | |
295 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
296 | break; | |
297 | ||
298 | case BFA_FCS_FABRIC_SM_DELETE: | |
dd5aaf45 KG |
299 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); |
300 | bfa_fcs_fabric_delete(fabric); | |
a36c61f9 KG |
301 | break; |
302 | ||
303 | default: | |
304 | bfa_sm_fault(fabric->fcs, event); | |
305 | } | |
306 | } | |
307 | ||
5fbe25c7 | 308 | /* |
a36c61f9 KG |
309 | * Link is down, awaiting LINK UP event from port. This is also the |
310 | * first state at fabric creation. | |
311 | */ | |
312 | static void | |
313 | bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric, | |
314 | enum bfa_fcs_fabric_event event) | |
315 | { | |
316 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
317 | bfa_trc(fabric->fcs, event); | |
318 | ||
319 | switch (event) { | |
320 | case BFA_FCS_FABRIC_SM_LINK_UP: | |
321 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); | |
322 | bfa_fcs_fabric_login(fabric); | |
323 | break; | |
324 | ||
325 | case BFA_FCS_FABRIC_SM_RETRY_OP: | |
326 | break; | |
327 | ||
328 | case BFA_FCS_FABRIC_SM_DELETE: | |
329 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | |
330 | bfa_fcs_fabric_delete(fabric); | |
331 | break; | |
332 | ||
333 | default: | |
334 | bfa_sm_fault(fabric->fcs, event); | |
335 | } | |
336 | } | |
337 | ||
5fbe25c7 | 338 | /* |
a36c61f9 KG |
339 | * FLOGI is in progress, awaiting FLOGI reply. |
340 | */ | |
341 | static void | |
342 | bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, | |
343 | enum bfa_fcs_fabric_event event) | |
344 | { | |
345 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
346 | bfa_trc(fabric->fcs, event); | |
347 | ||
348 | switch (event) { | |
349 | case BFA_FCS_FABRIC_SM_CONT_OP: | |
350 | ||
351 | bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, | |
be540a99 KG |
352 | fabric->bb_credit, |
353 | bfa_fcs_fabric_oper_bbscn(fabric)); | |
a36c61f9 KG |
354 | fabric->fab_type = BFA_FCS_FABRIC_SWITCHED; |
355 | ||
356 | if (fabric->auth_reqd && fabric->is_auth) { | |
357 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth); | |
358 | bfa_trc(fabric->fcs, event); | |
359 | } else { | |
360 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online); | |
361 | bfa_fcs_fabric_notify_online(fabric); | |
362 | } | |
363 | break; | |
364 | ||
365 | case BFA_FCS_FABRIC_SM_RETRY_OP: | |
366 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry); | |
367 | bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer, | |
368 | bfa_fcs_fabric_delay, fabric, | |
369 | BFA_FCS_FABRIC_RETRY_DELAY); | |
370 | break; | |
371 | ||
372 | case BFA_FCS_FABRIC_SM_LOOPBACK: | |
373 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback); | |
f7f73812 | 374 | bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
375 | bfa_fcs_fabric_set_opertype(fabric); |
376 | break; | |
377 | ||
378 | case BFA_FCS_FABRIC_SM_NO_FABRIC: | |
379 | fabric->fab_type = BFA_FCS_FABRIC_N2N; | |
380 | bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, | |
be540a99 KG |
381 | fabric->bb_credit, |
382 | bfa_fcs_fabric_oper_bbscn(fabric)); | |
a36c61f9 KG |
383 | bfa_fcs_fabric_notify_online(fabric); |
384 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric); | |
385 | break; | |
386 | ||
387 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
388 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | |
f7f73812 | 389 | bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
390 | break; |
391 | ||
392 | case BFA_FCS_FABRIC_SM_DELETE: | |
393 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | |
f7f73812 | 394 | bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
395 | bfa_fcs_fabric_delete(fabric); |
396 | break; | |
397 | ||
398 | default: | |
399 | bfa_sm_fault(fabric->fcs, event); | |
400 | } | |
401 | } | |
402 | ||
403 | ||
404 | static void | |
405 | bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric, | |
406 | enum bfa_fcs_fabric_event event) | |
407 | { | |
408 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
409 | bfa_trc(fabric->fcs, event); | |
410 | ||
411 | switch (event) { | |
412 | case BFA_FCS_FABRIC_SM_DELAYED: | |
413 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); | |
414 | bfa_fcs_fabric_login(fabric); | |
415 | break; | |
416 | ||
417 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
418 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | |
419 | bfa_timer_stop(&fabric->delay_timer); | |
420 | break; | |
421 | ||
422 | case BFA_FCS_FABRIC_SM_DELETE: | |
423 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | |
424 | bfa_timer_stop(&fabric->delay_timer); | |
425 | bfa_fcs_fabric_delete(fabric); | |
426 | break; | |
427 | ||
428 | default: | |
429 | bfa_sm_fault(fabric->fcs, event); | |
430 | } | |
431 | } | |
432 | ||
5fbe25c7 | 433 | /* |
a36c61f9 KG |
434 | * Authentication is in progress, awaiting authentication results. |
435 | */ | |
436 | static void | |
437 | bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, | |
438 | enum bfa_fcs_fabric_event event) | |
439 | { | |
440 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
441 | bfa_trc(fabric->fcs, event); | |
442 | ||
443 | switch (event) { | |
444 | case BFA_FCS_FABRIC_SM_AUTH_FAILED: | |
445 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); | |
f7f73812 | 446 | bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
447 | break; |
448 | ||
449 | case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: | |
450 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online); | |
451 | bfa_fcs_fabric_notify_online(fabric); | |
452 | break; | |
453 | ||
454 | case BFA_FCS_FABRIC_SM_PERF_EVFP: | |
455 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp); | |
456 | break; | |
457 | ||
458 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
459 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | |
f7f73812 | 460 | bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
461 | break; |
462 | ||
463 | case BFA_FCS_FABRIC_SM_DELETE: | |
464 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | |
465 | bfa_fcs_fabric_delete(fabric); | |
466 | break; | |
467 | ||
468 | default: | |
469 | bfa_sm_fault(fabric->fcs, event); | |
470 | } | |
471 | } | |
472 | ||
5fbe25c7 | 473 | /* |
a36c61f9 KG |
474 | * Authentication failed |
475 | */ | |
f7f73812 | 476 | void |
a36c61f9 KG |
477 | bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, |
478 | enum bfa_fcs_fabric_event event) | |
479 | { | |
480 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
481 | bfa_trc(fabric->fcs, event); | |
482 | ||
483 | switch (event) { | |
484 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
485 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | |
486 | bfa_fcs_fabric_notify_offline(fabric); | |
487 | break; | |
488 | ||
489 | case BFA_FCS_FABRIC_SM_DELETE: | |
490 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | |
491 | bfa_fcs_fabric_delete(fabric); | |
492 | break; | |
493 | ||
494 | default: | |
495 | bfa_sm_fault(fabric->fcs, event); | |
496 | } | |
497 | } | |
498 | ||
5fbe25c7 | 499 | /* |
a36c61f9 KG |
500 | * Port is in loopback mode. |
501 | */ | |
f7f73812 | 502 | void |
a36c61f9 KG |
503 | bfa_fcs_fabric_sm_loopback(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 | switch (event) { | |
510 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
511 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | |
512 | bfa_fcs_fabric_notify_offline(fabric); | |
513 | break; | |
514 | ||
515 | case BFA_FCS_FABRIC_SM_DELETE: | |
516 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | |
517 | bfa_fcs_fabric_delete(fabric); | |
518 | break; | |
519 | ||
520 | default: | |
521 | bfa_sm_fault(fabric->fcs, event); | |
522 | } | |
523 | } | |
524 | ||
5fbe25c7 | 525 | /* |
a36c61f9 KG |
526 | * There is no attached fabric - private loop or NPort-to-NPort topology. |
527 | */ | |
528 | static void | |
529 | bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, | |
530 | enum bfa_fcs_fabric_event event) | |
531 | { | |
532 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
533 | bfa_trc(fabric->fcs, event); | |
534 | ||
535 | switch (event) { | |
536 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
537 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | |
f7f73812 | 538 | bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
539 | bfa_fcs_fabric_notify_offline(fabric); |
540 | break; | |
541 | ||
542 | case BFA_FCS_FABRIC_SM_DELETE: | |
543 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | |
544 | bfa_fcs_fabric_delete(fabric); | |
545 | break; | |
546 | ||
547 | case BFA_FCS_FABRIC_SM_NO_FABRIC: | |
548 | bfa_trc(fabric->fcs, fabric->bb_credit); | |
549 | bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, | |
be540a99 KG |
550 | fabric->bb_credit, |
551 | bfa_fcs_fabric_oper_bbscn(fabric)); | |
a36c61f9 KG |
552 | break; |
553 | ||
554 | default: | |
555 | bfa_sm_fault(fabric->fcs, event); | |
556 | } | |
557 | } | |
558 | ||
5fbe25c7 | 559 | /* |
a36c61f9 KG |
560 | * Fabric is online - normal operating state. |
561 | */ | |
f7f73812 | 562 | void |
a36c61f9 KG |
563 | bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, |
564 | enum bfa_fcs_fabric_event event) | |
565 | { | |
566 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
567 | bfa_trc(fabric->fcs, event); | |
568 | ||
569 | switch (event) { | |
570 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
571 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | |
f7f73812 | 572 | bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
573 | bfa_fcs_fabric_notify_offline(fabric); |
574 | break; | |
575 | ||
576 | case BFA_FCS_FABRIC_SM_DELETE: | |
577 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | |
578 | bfa_fcs_fabric_delete(fabric); | |
579 | break; | |
580 | ||
581 | case BFA_FCS_FABRIC_SM_AUTH_FAILED: | |
582 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); | |
f7f73812 | 583 | bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); |
a36c61f9 KG |
584 | break; |
585 | ||
586 | case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: | |
587 | break; | |
588 | ||
589 | default: | |
590 | bfa_sm_fault(fabric->fcs, event); | |
591 | } | |
592 | } | |
593 | ||
5fbe25c7 | 594 | /* |
a36c61f9 KG |
595 | * Exchanging virtual fabric parameters. |
596 | */ | |
597 | static void | |
598 | bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric, | |
599 | enum bfa_fcs_fabric_event event) | |
600 | { | |
601 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
602 | bfa_trc(fabric->fcs, event); | |
603 | ||
604 | switch (event) { | |
605 | case BFA_FCS_FABRIC_SM_CONT_OP: | |
606 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done); | |
607 | break; | |
608 | ||
609 | case BFA_FCS_FABRIC_SM_ISOLATE: | |
610 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated); | |
611 | break; | |
612 | ||
613 | default: | |
614 | bfa_sm_fault(fabric->fcs, event); | |
615 | } | |
616 | } | |
617 | ||
5fbe25c7 | 618 | /* |
a36c61f9 KG |
619 | * EVFP exchange complete and VFT tagging is enabled. |
620 | */ | |
621 | static void | |
622 | bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric, | |
623 | enum bfa_fcs_fabric_event event) | |
624 | { | |
625 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
626 | bfa_trc(fabric->fcs, event); | |
627 | } | |
628 | ||
5fbe25c7 | 629 | /* |
a36c61f9 KG |
630 | * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F). |
631 | */ | |
632 | static void | |
633 | bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric, | |
634 | enum bfa_fcs_fabric_event event) | |
635 | { | |
636 | struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad; | |
637 | char pwwn_ptr[BFA_STRING_32]; | |
638 | ||
639 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
640 | bfa_trc(fabric->fcs, event); | |
641 | wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn); | |
642 | ||
88166242 | 643 | BFA_LOG(KERN_INFO, bfad, bfa_log_level, |
a36c61f9 KG |
644 | "Port is isolated due to VF_ID mismatch. " |
645 | "PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.", | |
646 | pwwn_ptr, fabric->fcs->port_vfid, | |
647 | fabric->event_arg.swp_vfid); | |
648 | } | |
649 | ||
5fbe25c7 | 650 | /* |
a36c61f9 KG |
651 | * Fabric is being deleted, awaiting vport delete completions. |
652 | */ | |
653 | static void | |
654 | bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric, | |
655 | enum bfa_fcs_fabric_event event) | |
7725ccfd | 656 | { |
a36c61f9 KG |
657 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); |
658 | bfa_trc(fabric->fcs, event); | |
659 | ||
660 | switch (event) { | |
661 | case BFA_FCS_FABRIC_SM_DELCOMP: | |
662 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | |
f7f73812 | 663 | bfa_wc_down(&fabric->fcs->wc); |
a36c61f9 KG |
664 | break; |
665 | ||
666 | case BFA_FCS_FABRIC_SM_LINK_UP: | |
667 | break; | |
668 | ||
669 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | |
670 | bfa_fcs_fabric_notify_offline(fabric); | |
671 | break; | |
672 | ||
673 | default: | |
674 | bfa_sm_fault(fabric->fcs, event); | |
675 | } | |
7725ccfd JH |
676 | } |
677 | ||
678 | ||
a36c61f9 | 679 | |
5fbe25c7 | 680 | /* |
a36c61f9 KG |
681 | * fcs_fabric_private fabric private functions |
682 | */ | |
683 | ||
684 | static void | |
685 | bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric) | |
686 | { | |
687 | struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg; | |
688 | ||
689 | port_cfg->roles = BFA_LPORT_ROLE_FCP_IM; | |
f7f73812 MZ |
690 | port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn; |
691 | port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn; | |
a36c61f9 KG |
692 | } |
693 | ||
5fbe25c7 | 694 | /* |
a36c61f9 KG |
695 | * Port Symbolic Name Creation for base port. |
696 | */ | |
7725ccfd | 697 | void |
a36c61f9 | 698 | bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric) |
7725ccfd | 699 | { |
a36c61f9 KG |
700 | struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg; |
701 | char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0}; | |
702 | struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info; | |
703 | ||
704 | bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model); | |
705 | ||
706 | /* Model name/number */ | |
707 | strncpy((char *)&port_cfg->sym_name, model, | |
708 | BFA_FCS_PORT_SYMBNAME_MODEL_SZ); | |
709 | strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | |
710 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | |
711 | ||
712 | /* Driver Version */ | |
713 | strncat((char *)&port_cfg->sym_name, (char *)driver_info->version, | |
714 | BFA_FCS_PORT_SYMBNAME_VERSION_SZ); | |
715 | strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | |
716 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | |
717 | ||
718 | /* Host machine name */ | |
719 | strncat((char *)&port_cfg->sym_name, | |
720 | (char *)driver_info->host_machine_name, | |
721 | BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ); | |
722 | strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | |
723 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | |
724 | ||
725 | /* | |
726 | * Host OS Info : | |
727 | * If OS Patch Info is not there, do not truncate any bytes from the | |
728 | * OS name string and instead copy the entire OS info string (64 bytes). | |
729 | */ | |
730 | if (driver_info->host_os_patch[0] == '\0') { | |
731 | strncat((char *)&port_cfg->sym_name, | |
732 | (char *)driver_info->host_os_name, | |
733 | BFA_FCS_OS_STR_LEN); | |
734 | strncat((char *)&port_cfg->sym_name, | |
735 | BFA_FCS_PORT_SYMBNAME_SEPARATOR, | |
736 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | |
737 | } else { | |
738 | strncat((char *)&port_cfg->sym_name, | |
739 | (char *)driver_info->host_os_name, | |
740 | BFA_FCS_PORT_SYMBNAME_OSINFO_SZ); | |
741 | strncat((char *)&port_cfg->sym_name, | |
742 | BFA_FCS_PORT_SYMBNAME_SEPARATOR, | |
743 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | |
744 | ||
745 | /* Append host OS Patch Info */ | |
746 | strncat((char *)&port_cfg->sym_name, | |
747 | (char *)driver_info->host_os_patch, | |
748 | BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ); | |
749 | } | |
750 | ||
751 | /* null terminate */ | |
752 | port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0; | |
7725ccfd JH |
753 | } |
754 | ||
5fbe25c7 | 755 | /* |
a36c61f9 KG |
756 | * bfa lps login completion callback |
757 | */ | |
7725ccfd | 758 | void |
a36c61f9 | 759 | bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status) |
7725ccfd | 760 | { |
a36c61f9 KG |
761 | struct bfa_fcs_fabric_s *fabric = uarg; |
762 | ||
763 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
764 | bfa_trc(fabric->fcs, status); | |
765 | ||
766 | switch (status) { | |
767 | case BFA_STATUS_OK: | |
768 | fabric->stats.flogi_accepts++; | |
769 | break; | |
770 | ||
771 | case BFA_STATUS_INVALID_MAC: | |
772 | /* Only for CNA */ | |
773 | fabric->stats.flogi_acc_err++; | |
774 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | |
775 | ||
776 | return; | |
777 | ||
778 | case BFA_STATUS_EPROTOCOL: | |
f7f73812 | 779 | switch (fabric->lps->ext_status) { |
a36c61f9 KG |
780 | case BFA_EPROTO_BAD_ACCEPT: |
781 | fabric->stats.flogi_acc_err++; | |
782 | break; | |
783 | ||
784 | case BFA_EPROTO_UNKNOWN_RSP: | |
785 | fabric->stats.flogi_unknown_rsp++; | |
786 | break; | |
787 | ||
788 | default: | |
789 | break; | |
790 | } | |
791 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | |
792 | ||
793 | return; | |
794 | ||
795 | case BFA_STATUS_FABRIC_RJT: | |
796 | fabric->stats.flogi_rejects++; | |
be540a99 KG |
797 | if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR && |
798 | fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO) | |
799 | fabric->fcs->bbscn_flogi_rjt = BFA_TRUE; | |
800 | ||
a36c61f9 KG |
801 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); |
802 | return; | |
803 | ||
804 | default: | |
805 | fabric->stats.flogi_rsp_err++; | |
806 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | |
807 | return; | |
808 | } | |
809 | ||
f7f73812 | 810 | fabric->bb_credit = fabric->lps->pr_bbcred; |
a36c61f9 KG |
811 | bfa_trc(fabric->fcs, fabric->bb_credit); |
812 | ||
f7f73812 MZ |
813 | if (!(fabric->lps->brcd_switch)) |
814 | fabric->fabric_name = fabric->lps->pr_nwwn; | |
a36c61f9 KG |
815 | |
816 | /* | |
817 | * Check port type. It should be 1 = F-port. | |
818 | */ | |
f7f73812 MZ |
819 | if (fabric->lps->fport) { |
820 | fabric->bport.pid = fabric->lps->lp_pid; | |
821 | fabric->is_npiv = fabric->lps->npiv_en; | |
822 | fabric->is_auth = fabric->lps->auth_req; | |
a36c61f9 KG |
823 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP); |
824 | } else { | |
825 | /* | |
826 | * Nport-2-Nport direct attached | |
827 | */ | |
828 | fabric->bport.port_topo.pn2n.rem_port_wwn = | |
f7f73812 | 829 | fabric->lps->pr_pwwn; |
a36c61f9 KG |
830 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC); |
831 | } | |
832 | ||
833 | bfa_trc(fabric->fcs, fabric->bport.pid); | |
834 | bfa_trc(fabric->fcs, fabric->is_npiv); | |
835 | bfa_trc(fabric->fcs, fabric->is_auth); | |
836 | } | |
5fbe25c7 | 837 | /* |
a36c61f9 KG |
838 | * Allocate and send FLOGI. |
839 | */ | |
840 | static void | |
841 | bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric) | |
842 | { | |
843 | struct bfa_s *bfa = fabric->fcs->bfa; | |
844 | struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg; | |
be540a99 | 845 | u8 alpa = 0, bb_scn = 0; |
a36c61f9 KG |
846 | |
847 | if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) | |
848 | alpa = bfa_fcport_get_myalpa(bfa); | |
849 | ||
be540a99 KG |
850 | if (bfa_fcs_fabric_is_bbscn_enabled(fabric) && |
851 | (!fabric->fcs->bbscn_flogi_rjt)) | |
852 | bb_scn = BFA_FCS_PORT_DEF_BB_SCN; | |
853 | ||
a36c61f9 | 854 | bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa), |
be540a99 | 855 | pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn); |
a36c61f9 KG |
856 | |
857 | fabric->stats.flogi_sent++; | |
858 | } | |
859 | ||
860 | static void | |
861 | bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric) | |
862 | { | |
863 | struct bfa_fcs_vport_s *vport; | |
864 | struct list_head *qe, *qen; | |
865 | ||
866 | bfa_trc(fabric->fcs, fabric->fabric_name); | |
867 | ||
868 | bfa_fcs_fabric_set_opertype(fabric); | |
869 | fabric->stats.fabric_onlines++; | |
870 | ||
5fbe25c7 | 871 | /* |
a36c61f9 KG |
872 | * notify online event to base and then virtual ports |
873 | */ | |
874 | bfa_fcs_lport_online(&fabric->bport); | |
875 | ||
876 | list_for_each_safe(qe, qen, &fabric->vport_q) { | |
877 | vport = (struct bfa_fcs_vport_s *) qe; | |
878 | bfa_fcs_vport_online(vport); | |
879 | } | |
880 | } | |
881 | ||
882 | static void | |
883 | bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric) | |
884 | { | |
885 | struct bfa_fcs_vport_s *vport; | |
886 | struct list_head *qe, *qen; | |
887 | ||
888 | bfa_trc(fabric->fcs, fabric->fabric_name); | |
889 | fabric->stats.fabric_offlines++; | |
890 | ||
5fbe25c7 | 891 | /* |
a36c61f9 KG |
892 | * notify offline event first to vports and then base port. |
893 | */ | |
894 | list_for_each_safe(qe, qen, &fabric->vport_q) { | |
895 | vport = (struct bfa_fcs_vport_s *) qe; | |
896 | bfa_fcs_vport_offline(vport); | |
897 | } | |
898 | ||
899 | bfa_fcs_lport_offline(&fabric->bport); | |
900 | ||
901 | fabric->fabric_name = 0; | |
902 | fabric->fabric_ip_addr[0] = 0; | |
903 | } | |
904 | ||
905 | static void | |
906 | bfa_fcs_fabric_delay(void *cbarg) | |
907 | { | |
908 | struct bfa_fcs_fabric_s *fabric = cbarg; | |
909 | ||
910 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED); | |
911 | } | |
912 | ||
be540a99 KG |
913 | /* |
914 | * Computes operating BB_SCN value | |
915 | */ | |
916 | static u8 | |
917 | bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric) | |
918 | { | |
919 | u8 pr_bbscn = fabric->lps->pr_bbscn; | |
920 | ||
921 | if (!(fabric->fcs->bbscn_enabled && pr_bbscn)) | |
922 | return 0; | |
923 | ||
924 | /* return max of local/remote bb_scn values */ | |
925 | return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ? | |
926 | pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN); | |
927 | } | |
928 | ||
929 | /* | |
930 | * Check if BB_SCN can be enabled. | |
931 | */ | |
932 | static bfa_boolean_t | |
933 | bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric) | |
934 | { | |
935 | if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) && | |
936 | fabric->fcs->bbscn_enabled && | |
937 | !bfa_fcport_is_qos_enabled(fabric->fcs->bfa) && | |
938 | !bfa_fcport_is_trunk_enabled(fabric->fcs->bfa)) | |
939 | return BFA_TRUE; | |
940 | else | |
941 | return BFA_FALSE; | |
942 | } | |
943 | ||
5fbe25c7 | 944 | /* |
a36c61f9 KG |
945 | * Delete all vports and wait for vport delete completions. |
946 | */ | |
947 | static void | |
948 | bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric) | |
949 | { | |
950 | struct bfa_fcs_vport_s *vport; | |
951 | struct list_head *qe, *qen; | |
952 | ||
953 | list_for_each_safe(qe, qen, &fabric->vport_q) { | |
954 | vport = (struct bfa_fcs_vport_s *) qe; | |
955 | bfa_fcs_vport_fcs_delete(vport); | |
956 | } | |
957 | ||
958 | bfa_fcs_lport_delete(&fabric->bport); | |
959 | bfa_wc_wait(&fabric->wc); | |
7725ccfd JH |
960 | } |
961 | ||
a36c61f9 KG |
962 | static void |
963 | bfa_fcs_fabric_delete_comp(void *cbarg) | |
964 | { | |
965 | struct bfa_fcs_fabric_s *fabric = cbarg; | |
966 | ||
967 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP); | |
968 | } | |
7725ccfd | 969 | |
5fbe25c7 | 970 | /* |
a36c61f9 KG |
971 | * fcs_fabric_public fabric public functions |
972 | */ | |
973 | ||
5fbe25c7 | 974 | /* |
a36c61f9 KG |
975 | * Attach time initialization. |
976 | */ | |
977 | void | |
978 | bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs) | |
979 | { | |
980 | struct bfa_fcs_fabric_s *fabric; | |
981 | ||
982 | fabric = &fcs->fabric; | |
6a18b167 | 983 | memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s)); |
a36c61f9 | 984 | |
5fbe25c7 | 985 | /* |
a36c61f9 KG |
986 | * Initialize base fabric. |
987 | */ | |
988 | fabric->fcs = fcs; | |
989 | INIT_LIST_HEAD(&fabric->vport_q); | |
990 | INIT_LIST_HEAD(&fabric->vf_q); | |
991 | fabric->lps = bfa_lps_alloc(fcs->bfa); | |
d4b671c5 | 992 | WARN_ON(!fabric->lps); |
a36c61f9 | 993 | |
5fbe25c7 | 994 | /* |
a36c61f9 KG |
995 | * Initialize fabric delete completion handler. Fabric deletion is |
996 | * complete when the last vport delete is complete. | |
997 | */ | |
998 | bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric); | |
999 | bfa_wc_up(&fabric->wc); /* For the base port */ | |
1000 | ||
1001 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | |
1002 | bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL); | |
1003 | } | |
1004 | ||
1005 | void | |
1006 | bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs) | |
1007 | { | |
1008 | bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE); | |
1009 | bfa_trc(fcs, 0); | |
1010 | } | |
1011 | ||
5fbe25c7 | 1012 | /* |
a36c61f9 KG |
1013 | * Module cleanup |
1014 | */ | |
1015 | void | |
1016 | bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs) | |
1017 | { | |
1018 | struct bfa_fcs_fabric_s *fabric; | |
1019 | ||
1020 | bfa_trc(fcs, 0); | |
1021 | ||
5fbe25c7 | 1022 | /* |
a36c61f9 KG |
1023 | * Cleanup base fabric. |
1024 | */ | |
1025 | fabric = &fcs->fabric; | |
1026 | bfa_lps_delete(fabric->lps); | |
1027 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE); | |
1028 | } | |
1029 | ||
5fbe25c7 | 1030 | /* |
a36c61f9 KG |
1031 | * Fabric module start -- kick starts FCS actions |
1032 | */ | |
1033 | void | |
1034 | bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs) | |
1035 | { | |
1036 | struct bfa_fcs_fabric_s *fabric; | |
1037 | ||
1038 | bfa_trc(fcs, 0); | |
1039 | fabric = &fcs->fabric; | |
1040 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START); | |
1041 | } | |
1042 | ||
a36c61f9 | 1043 | |
5fbe25c7 | 1044 | /* |
a36c61f9 KG |
1045 | * Link up notification from BFA physical port module. |
1046 | */ | |
1047 | void | |
1048 | bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric) | |
1049 | { | |
1050 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
1051 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP); | |
1052 | } | |
1053 | ||
5fbe25c7 | 1054 | /* |
a36c61f9 KG |
1055 | * Link down notification from BFA physical port module. |
1056 | */ | |
1057 | void | |
1058 | bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric) | |
1059 | { | |
1060 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | |
be540a99 | 1061 | fabric->fcs->bbscn_flogi_rjt = BFA_FALSE; |
a36c61f9 KG |
1062 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN); |
1063 | } | |
1064 | ||
5fbe25c7 | 1065 | /* |
a36c61f9 KG |
1066 | * A child vport is being created in the fabric. |
1067 | * | |
1068 | * Call from vport module at vport creation. A list of base port and vports | |
1069 | * belonging to a fabric is maintained to propagate link events. | |
1070 | * | |
1071 | * param[in] fabric - Fabric instance. This can be a base fabric or vf. | |
1072 | * param[in] vport - Vport being created. | |
1073 | * | |
1074 | * @return None (always succeeds) | |
1075 | */ | |
1076 | void | |
1077 | bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric, | |
1078 | struct bfa_fcs_vport_s *vport) | |
1079 | { | |
5fbe25c7 | 1080 | /* |
a36c61f9 KG |
1081 | * - add vport to fabric's vport_q |
1082 | */ | |
1083 | bfa_trc(fabric->fcs, fabric->vf_id); | |
1084 | ||
1085 | list_add_tail(&vport->qe, &fabric->vport_q); | |
1086 | fabric->num_vports++; | |
1087 | bfa_wc_up(&fabric->wc); | |
1088 | } | |
1089 | ||
5fbe25c7 | 1090 | /* |
a36c61f9 KG |
1091 | * A child vport is being deleted from fabric. |
1092 | * | |
1093 | * Vport is being deleted. | |
1094 | */ | |
1095 | void | |
1096 | bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric, | |
1097 | struct bfa_fcs_vport_s *vport) | |
1098 | { | |
1099 | list_del(&vport->qe); | |
1100 | fabric->num_vports--; | |
1101 | bfa_wc_down(&fabric->wc); | |
1102 | } | |
1103 | ||
a36c61f9 | 1104 | |
5fbe25c7 | 1105 | /* |
25985edc | 1106 | * Lookup for a vport within a fabric given its pwwn |
a36c61f9 KG |
1107 | */ |
1108 | struct bfa_fcs_vport_s * | |
1109 | bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn) | |
1110 | { | |
1111 | struct bfa_fcs_vport_s *vport; | |
1112 | struct list_head *qe; | |
1113 | ||
1114 | list_for_each(qe, &fabric->vport_q) { | |
1115 | vport = (struct bfa_fcs_vport_s *) qe; | |
1116 | if (bfa_fcs_lport_get_pwwn(&vport->lport) == pwwn) | |
1117 | return vport; | |
1118 | } | |
1119 | ||
1120 | return NULL; | |
1121 | } | |
1122 | ||
a36c61f9 KG |
1123 | |
1124 | /* | |
1125 | * Get OUI of the attached switch. | |
1126 | * | |
1127 | * Note : Use of this function should be avoided as much as possible. | |
1128 | * This function should be used only if there is any requirement | |
1129 | * to check for FOS version below 6.3. | |
1130 | * To check if the attached fabric is a brocade fabric, use | |
1131 | * bfa_lps_is_brcd_fabric() which works for FOS versions 6.3 | |
1132 | * or above only. | |
1133 | */ | |
1134 | ||
1135 | u16 | |
1136 | bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric) | |
1137 | { | |
1138 | wwn_t fab_nwwn; | |
1139 | u8 *tmp; | |
1140 | u16 oui; | |
1141 | ||
f7f73812 | 1142 | fab_nwwn = fabric->lps->pr_nwwn; |
a36c61f9 KG |
1143 | |
1144 | tmp = (u8 *)&fab_nwwn; | |
1145 | oui = (tmp[3] << 8) | tmp[4]; | |
1146 | ||
1147 | return oui; | |
1148 | } | |
5fbe25c7 | 1149 | /* |
a36c61f9 KG |
1150 | * Unsolicited frame receive handling. |
1151 | */ | |
1152 | void | |
1153 | bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs, | |
1154 | u16 len) | |
1155 | { | |
1156 | u32 pid = fchs->d_id; | |
1157 | struct bfa_fcs_vport_s *vport; | |
1158 | struct list_head *qe; | |
1159 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | |
1160 | struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd; | |
1161 | ||
1162 | bfa_trc(fabric->fcs, len); | |
1163 | bfa_trc(fabric->fcs, pid); | |
1164 | ||
5fbe25c7 | 1165 | /* |
a36c61f9 KG |
1166 | * Look for our own FLOGI frames being looped back. This means an |
1167 | * external loopback cable is in place. Our own FLOGI frames are | |
1168 | * sometimes looped back when switch port gets temporarily bypassed. | |
1169 | */ | |
f16a1750 | 1170 | if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) && |
a36c61f9 KG |
1171 | (els_cmd->els_code == FC_ELS_FLOGI) && |
1172 | (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) { | |
1173 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK); | |
1174 | return; | |
1175 | } | |
1176 | ||
5fbe25c7 | 1177 | /* |
a36c61f9 KG |
1178 | * FLOGI/EVFP exchanges should be consumed by base fabric. |
1179 | */ | |
f16a1750 | 1180 | if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) { |
a36c61f9 KG |
1181 | bfa_trc(fabric->fcs, pid); |
1182 | bfa_fcs_fabric_process_uf(fabric, fchs, len); | |
1183 | return; | |
1184 | } | |
1185 | ||
1186 | if (fabric->bport.pid == pid) { | |
5fbe25c7 | 1187 | /* |
a36c61f9 KG |
1188 | * All authentication frames should be routed to auth |
1189 | */ | |
1190 | bfa_trc(fabric->fcs, els_cmd->els_code); | |
1191 | if (els_cmd->els_code == FC_ELS_AUTH) { | |
1192 | bfa_trc(fabric->fcs, els_cmd->els_code); | |
1193 | return; | |
1194 | } | |
1195 | ||
1196 | bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs)); | |
1197 | bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len); | |
1198 | return; | |
1199 | } | |
1200 | ||
5fbe25c7 | 1201 | /* |
a36c61f9 KG |
1202 | * look for a matching local port ID |
1203 | */ | |
1204 | list_for_each(qe, &fabric->vport_q) { | |
1205 | vport = (struct bfa_fcs_vport_s *) qe; | |
1206 | if (vport->lport.pid == pid) { | |
1207 | bfa_fcs_lport_uf_recv(&vport->lport, fchs, len); | |
1208 | return; | |
1209 | } | |
1210 | } | |
1211 | bfa_trc(fabric->fcs, els_cmd->els_code); | |
1212 | bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len); | |
1213 | } | |
1214 | ||
5fbe25c7 | 1215 | /* |
a36c61f9 KG |
1216 | * Unsolicited frames to be processed by fabric. |
1217 | */ | |
1218 | static void | |
1219 | bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs, | |
1220 | u16 len) | |
1221 | { | |
1222 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | |
1223 | ||
1224 | bfa_trc(fabric->fcs, els_cmd->els_code); | |
1225 | ||
1226 | switch (els_cmd->els_code) { | |
1227 | case FC_ELS_FLOGI: | |
1228 | bfa_fcs_fabric_process_flogi(fabric, fchs, len); | |
1229 | break; | |
1230 | ||
1231 | default: | |
1232 | /* | |
1233 | * need to generate a LS_RJT | |
1234 | */ | |
1235 | break; | |
1236 | } | |
1237 | } | |
1238 | ||
5fbe25c7 | 1239 | /* |
a36c61f9 KG |
1240 | * Process incoming FLOGI |
1241 | */ | |
1242 | static void | |
1243 | bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, | |
1244 | struct fchs_s *fchs, u16 len) | |
1245 | { | |
1246 | struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1); | |
1247 | struct bfa_fcs_lport_s *bport = &fabric->bport; | |
1248 | ||
1249 | bfa_trc(fabric->fcs, fchs->s_id); | |
1250 | ||
1251 | fabric->stats.flogi_rcvd++; | |
1252 | /* | |
1253 | * Check port type. It should be 0 = n-port. | |
1254 | */ | |
1255 | if (flogi->csp.port_type) { | |
1256 | /* | |
1257 | * @todo: may need to send a LS_RJT | |
1258 | */ | |
1259 | bfa_trc(fabric->fcs, flogi->port_name); | |
1260 | fabric->stats.flogi_rejected++; | |
1261 | return; | |
1262 | } | |
1263 | ||
ba816ea8 | 1264 | fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred); |
be540a99 | 1265 | fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12); |
a36c61f9 KG |
1266 | bport->port_topo.pn2n.rem_port_wwn = flogi->port_name; |
1267 | bport->port_topo.pn2n.reply_oxid = fchs->ox_id; | |
1268 | ||
1269 | /* | |
1270 | * Send a Flogi Acc | |
1271 | */ | |
1272 | bfa_fcs_fabric_send_flogi_acc(fabric); | |
1273 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC); | |
1274 | } | |
1275 | ||
1276 | static void | |
1277 | bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric) | |
1278 | { | |
1279 | struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg; | |
1280 | struct bfa_fcs_lport_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n; | |
1281 | struct bfa_s *bfa = fabric->fcs->bfa; | |
1282 | struct bfa_fcxp_s *fcxp; | |
1283 | u16 reqlen; | |
1284 | struct fchs_s fchs; | |
1285 | ||
1286 | fcxp = bfa_fcs_fcxp_alloc(fabric->fcs); | |
5fbe25c7 | 1287 | /* |
a36c61f9 KG |
1288 | * Do not expect this failure -- expect remote node to retry |
1289 | */ | |
1290 | if (!fcxp) | |
1291 | return; | |
1292 | ||
1293 | reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | |
f16a1750 | 1294 | bfa_hton3b(FC_FABRIC_PORT), |
a36c61f9 KG |
1295 | n2n_port->reply_oxid, pcfg->pwwn, |
1296 | pcfg->nwwn, | |
1297 | bfa_fcport_get_maxfrsize(bfa), | |
be540a99 KG |
1298 | bfa_fcport_get_rx_bbcredit(bfa), |
1299 | bfa_fcs_fabric_oper_bbscn(fabric)); | |
a36c61f9 | 1300 | |
f7f73812 | 1301 | bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag, |
a36c61f9 KG |
1302 | BFA_FALSE, FC_CLASS_3, |
1303 | reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric, | |
1304 | FC_MAX_PDUSZ, 0); | |
1305 | } | |
1306 | ||
5fbe25c7 | 1307 | /* |
a36c61f9 KG |
1308 | * Flogi Acc completion callback. |
1309 | */ | |
1310 | static void | |
1311 | bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, | |
1312 | bfa_status_t status, u32 rsp_len, | |
1313 | u32 resid_len, struct fchs_s *rspfchs) | |
1314 | { | |
1315 | struct bfa_fcs_fabric_s *fabric = cbarg; | |
1316 | ||
1317 | bfa_trc(fabric->fcs, status); | |
1318 | } | |
1319 | ||
1320 | /* | |
1321 | * | |
1322 | * @param[in] fabric - fabric | |
1323 | * @param[in] wwn_t - new fabric name | |
1324 | * | |
1325 | * @return - none | |
1326 | */ | |
1327 | void | |
1328 | bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, | |
1329 | wwn_t fabric_name) | |
1330 | { | |
1331 | struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad; | |
1332 | char pwwn_ptr[BFA_STRING_32]; | |
1333 | char fwwn_ptr[BFA_STRING_32]; | |
1334 | ||
1335 | bfa_trc(fabric->fcs, fabric_name); | |
1336 | ||
1337 | if (fabric->fabric_name == 0) { | |
1338 | /* | |
1339 | * With BRCD switches, we don't get Fabric Name in FLOGI. | |
1340 | * Don't generate a fabric name change event in this case. | |
1341 | */ | |
1342 | fabric->fabric_name = fabric_name; | |
1343 | } else { | |
1344 | fabric->fabric_name = fabric_name; | |
1345 | wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport)); | |
1346 | wwn2str(fwwn_ptr, | |
1347 | bfa_fcs_lport_get_fabric_name(&fabric->bport)); | |
88166242 | 1348 | BFA_LOG(KERN_WARNING, bfad, bfa_log_level, |
a36c61f9 KG |
1349 | "Base port WWN = %s Fabric WWN = %s\n", |
1350 | pwwn_ptr, fwwn_ptr); | |
1351 | } | |
1352 | } | |
1353 | ||
5fbe25c7 | 1354 | /* |
a36c61f9 KG |
1355 | * Returns FCS vf structure for a given vf_id. |
1356 | * | |
1357 | * param[in] vf_id - VF_ID | |
1358 | * | |
1359 | * return | |
1360 | * If lookup succeeds, retuns fcs vf object, otherwise returns NULL | |
1361 | */ | |
1362 | bfa_fcs_vf_t * | |
1363 | bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id) | |
1364 | { | |
1365 | bfa_trc(fcs, vf_id); | |
1366 | if (vf_id == FC_VF_ID_NULL) | |
1367 | return &fcs->fabric; | |
1368 | ||
1369 | return NULL; | |
1370 | } | |
1371 | ||
5fbe25c7 | 1372 | /* |
a36c61f9 KG |
1373 | * BFA FCS PPORT ( physical port) |
1374 | */ | |
1375 | static void | |
1376 | bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event) | |
1377 | { | |
1378 | struct bfa_fcs_s *fcs = cbarg; | |
1379 | ||
1380 | bfa_trc(fcs, event); | |
1381 | ||
1382 | switch (event) { | |
1383 | case BFA_PORT_LINKUP: | |
1384 | bfa_fcs_fabric_link_up(&fcs->fabric); | |
1385 | break; | |
1386 | ||
1387 | case BFA_PORT_LINKDOWN: | |
1388 | bfa_fcs_fabric_link_down(&fcs->fabric); | |
1389 | break; | |
1390 | ||
1391 | default: | |
d4b671c5 | 1392 | WARN_ON(1); |
a36c61f9 KG |
1393 | } |
1394 | } | |
1395 | ||
1396 | void | |
1397 | bfa_fcs_port_attach(struct bfa_fcs_s *fcs) | |
1398 | { | |
1399 | bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs); | |
1400 | } | |
1401 | ||
5fbe25c7 | 1402 | /* |
a36c61f9 KG |
1403 | * BFA FCS UF ( Unsolicited Frames) |
1404 | */ | |
1405 | ||
5fbe25c7 | 1406 | /* |
a36c61f9 KG |
1407 | * BFA callback for unsolicited frame receive handler. |
1408 | * | |
1409 | * @param[in] cbarg callback arg for receive handler | |
1410 | * @param[in] uf unsolicited frame descriptor | |
1411 | * | |
1412 | * @return None | |
1413 | */ | |
1414 | static void | |
1415 | bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf) | |
1416 | { | |
1417 | struct bfa_fcs_s *fcs = (struct bfa_fcs_s *) cbarg; | |
1418 | struct fchs_s *fchs = bfa_uf_get_frmbuf(uf); | |
1419 | u16 len = bfa_uf_get_frmlen(uf); | |
1420 | struct fc_vft_s *vft; | |
1421 | struct bfa_fcs_fabric_s *fabric; | |
1422 | ||
5fbe25c7 | 1423 | /* |
a36c61f9 KG |
1424 | * check for VFT header |
1425 | */ | |
1426 | if (fchs->routing == FC_RTG_EXT_HDR && | |
1427 | fchs->cat_info == FC_CAT_VFT_HDR) { | |
1428 | bfa_stats(fcs, uf.tagged); | |
1429 | vft = bfa_uf_get_frmbuf(uf); | |
1430 | if (fcs->port_vfid == vft->vf_id) | |
1431 | fabric = &fcs->fabric; | |
1432 | else | |
1433 | fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id); | |
1434 | ||
5fbe25c7 | 1435 | /* |
a36c61f9 KG |
1436 | * drop frame if vfid is unknown |
1437 | */ | |
1438 | if (!fabric) { | |
d4b671c5 | 1439 | WARN_ON(1); |
a36c61f9 KG |
1440 | bfa_stats(fcs, uf.vfid_unknown); |
1441 | bfa_uf_free(uf); | |
1442 | return; | |
1443 | } | |
1444 | ||
5fbe25c7 | 1445 | /* |
a36c61f9 KG |
1446 | * skip vft header |
1447 | */ | |
1448 | fchs = (struct fchs_s *) (vft + 1); | |
1449 | len -= sizeof(struct fc_vft_s); | |
1450 | ||
1451 | bfa_trc(fcs, vft->vf_id); | |
1452 | } else { | |
1453 | bfa_stats(fcs, uf.untagged); | |
1454 | fabric = &fcs->fabric; | |
1455 | } | |
1456 | ||
1457 | bfa_trc(fcs, ((u32 *) fchs)[0]); | |
1458 | bfa_trc(fcs, ((u32 *) fchs)[1]); | |
1459 | bfa_trc(fcs, ((u32 *) fchs)[2]); | |
1460 | bfa_trc(fcs, ((u32 *) fchs)[3]); | |
1461 | bfa_trc(fcs, ((u32 *) fchs)[4]); | |
1462 | bfa_trc(fcs, ((u32 *) fchs)[5]); | |
1463 | bfa_trc(fcs, len); | |
1464 | ||
1465 | bfa_fcs_fabric_uf_recv(fabric, fchs, len); | |
1466 | bfa_uf_free(uf); | |
1467 | } | |
1468 | ||
1469 | void | |
1470 | bfa_fcs_uf_attach(struct bfa_fcs_s *fcs) | |
1471 | { | |
1472 | bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs); | |
1473 | } |