2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
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
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.
19 * bfa_fcs.c BFA FCS main
24 #include "bfa_fcbuild.h"
26 BFA_TRC_FILE(FCS
, FCS
);
31 struct bfa_fcs_mod_s
{
32 void (*attach
) (struct bfa_fcs_s
*fcs
);
33 void (*modinit
) (struct bfa_fcs_s
*fcs
);
34 void (*modexit
) (struct bfa_fcs_s
*fcs
);
37 #define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
39 static struct bfa_fcs_mod_s fcs_modules
[] = {
40 { bfa_fcs_port_attach
, NULL
, NULL
},
41 { bfa_fcs_uf_attach
, NULL
, NULL
},
42 { bfa_fcs_fabric_attach
, bfa_fcs_fabric_modinit
,
43 bfa_fcs_fabric_modexit
},
51 bfa_fcs_exit_comp(void *fcs_cbarg
)
53 struct bfa_fcs_s
*fcs
= fcs_cbarg
;
54 struct bfad_s
*bfad
= fcs
->bfad
;
56 complete(&bfad
->comp
);
66 * fcs attach -- called once to initialize data structures at driver attach time
69 bfa_fcs_attach(struct bfa_fcs_s
*fcs
, struct bfa_s
*bfa
, struct bfad_s
*bfad
,
70 bfa_boolean_t min_cfg
)
73 struct bfa_fcs_mod_s
*mod
;
77 fcs
->min_cfg
= min_cfg
;
82 for (i
= 0; i
< sizeof(fcs_modules
) / sizeof(fcs_modules
[0]); i
++) {
83 mod
= &fcs_modules
[i
];
90 * fcs initialization, called once after bfa initialization is complete
93 bfa_fcs_init(struct bfa_fcs_s
*fcs
)
96 struct bfa_fcs_mod_s
*mod
;
97 struct bfi_pbc_vport_s pbc_vports
[BFI_PBC_MAX_VPORTS
];
99 for (i
= 0; i
< sizeof(fcs_modules
) / sizeof(fcs_modules
[0]); i
++) {
100 mod
= &fcs_modules
[i
];
104 /* Initialize pbc vports */
107 bfa_iocfc_get_pbc_vports(fcs
->bfa
, pbc_vports
);
108 for (i
= 0; i
< npbc_vports
; i
++)
109 bfa_fcb_pbc_vport_create(fcs
->bfa
->bfad
, pbc_vports
[i
]);
116 * FCS driver details initialization.
118 * param[in] fcs FCS instance
119 * param[in] driver_info Driver Details
124 bfa_fcs_driver_info_init(struct bfa_fcs_s
*fcs
,
125 struct bfa_fcs_driver_info_s
*driver_info
)
128 fcs
->driver_info
= *driver_info
;
130 bfa_fcs_fabric_psymb_init(&fcs
->fabric
);
135 * FCS instance cleanup and exit.
137 * param[in] fcs FCS instance
141 bfa_fcs_exit(struct bfa_fcs_s
*fcs
)
143 struct bfa_fcs_mod_s
*mod
;
146 bfa_wc_init(&fcs
->wc
, bfa_fcs_exit_comp
, fcs
);
148 nmods
= sizeof(fcs_modules
) / sizeof(fcs_modules
[0]);
150 for (i
= 0; i
< nmods
; i
++) {
152 mod
= &fcs_modules
[i
];
159 bfa_wc_wait(&fcs
->wc
);
164 * Fabric module implementation.
167 #define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */
168 #define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */
170 #define bfa_fcs_fabric_set_opertype(__fabric) do { \
171 if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \
172 == BFA_PORT_TOPOLOGY_P2P) \
173 (__fabric)->oper_type = BFA_PORT_TYPE_NPORT; \
175 (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT; \
179 * forward declarations
181 static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s
*fabric
);
182 static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s
*fabric
);
183 static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s
*fabric
);
184 static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s
*fabric
);
185 static void bfa_fcs_fabric_delay(void *cbarg
);
186 static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s
*fabric
);
187 static void bfa_fcs_fabric_delete_comp(void *cbarg
);
188 static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s
*fabric
,
189 struct fchs_s
*fchs
, u16 len
);
190 static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s
*fabric
,
191 struct fchs_s
*fchs
, u16 len
);
192 static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s
*fabric
);
193 static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg
,
194 struct bfa_fcxp_s
*fcxp
, void *cbarg
,
198 struct fchs_s
*rspfchs
);
200 static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s
*fabric
,
201 enum bfa_fcs_fabric_event event
);
202 static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s
*fabric
,
203 enum bfa_fcs_fabric_event event
);
204 static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s
*fabric
,
205 enum bfa_fcs_fabric_event event
);
206 static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s
*fabric
,
207 enum bfa_fcs_fabric_event event
);
208 static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s
*fabric
,
209 enum bfa_fcs_fabric_event event
);
210 static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s
*fabric
,
211 enum bfa_fcs_fabric_event event
);
212 static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s
*fabric
,
213 enum bfa_fcs_fabric_event event
);
214 static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s
*fabric
,
215 enum bfa_fcs_fabric_event event
);
216 static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s
*fabric
,
217 enum bfa_fcs_fabric_event event
);
218 static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s
*fabric
,
219 enum bfa_fcs_fabric_event event
);
220 static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s
*fabric
,
221 enum bfa_fcs_fabric_event event
);
223 * Beginning state before fabric creation.
226 bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s
*fabric
,
227 enum bfa_fcs_fabric_event event
)
229 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
230 bfa_trc(fabric
->fcs
, event
);
233 case BFA_FCS_FABRIC_SM_CREATE
:
234 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_created
);
235 bfa_fcs_fabric_init(fabric
);
236 bfa_fcs_lport_init(&fabric
->bport
, &fabric
->bport
.port_cfg
);
239 case BFA_FCS_FABRIC_SM_LINK_UP
:
240 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
244 bfa_sm_fault(fabric
->fcs
, event
);
249 * Beginning state before fabric creation.
252 bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s
*fabric
,
253 enum bfa_fcs_fabric_event event
)
255 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
256 bfa_trc(fabric
->fcs
, event
);
259 case BFA_FCS_FABRIC_SM_START
:
260 if (bfa_fcport_is_linkup(fabric
->fcs
->bfa
)) {
261 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_flogi
);
262 bfa_fcs_fabric_login(fabric
);
264 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
267 case BFA_FCS_FABRIC_SM_LINK_UP
:
268 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
271 case BFA_FCS_FABRIC_SM_DELETE
:
272 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_uninit
);
273 bfa_wc_down(&fabric
->fcs
->wc
);
277 bfa_sm_fault(fabric
->fcs
, event
);
282 * Link is down, awaiting LINK UP event from port. This is also the
283 * first state at fabric creation.
286 bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s
*fabric
,
287 enum bfa_fcs_fabric_event event
)
289 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
290 bfa_trc(fabric
->fcs
, event
);
293 case BFA_FCS_FABRIC_SM_LINK_UP
:
294 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_flogi
);
295 bfa_fcs_fabric_login(fabric
);
298 case BFA_FCS_FABRIC_SM_RETRY_OP
:
301 case BFA_FCS_FABRIC_SM_DELETE
:
302 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
303 bfa_fcs_fabric_delete(fabric
);
307 bfa_sm_fault(fabric
->fcs
, event
);
312 * FLOGI is in progress, awaiting FLOGI reply.
315 bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s
*fabric
,
316 enum bfa_fcs_fabric_event event
)
318 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
319 bfa_trc(fabric
->fcs
, event
);
322 case BFA_FCS_FABRIC_SM_CONT_OP
:
324 bfa_fcport_set_tx_bbcredit(fabric
->fcs
->bfa
,
326 fabric
->fab_type
= BFA_FCS_FABRIC_SWITCHED
;
328 if (fabric
->auth_reqd
&& fabric
->is_auth
) {
329 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_auth
);
330 bfa_trc(fabric
->fcs
, event
);
332 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_online
);
333 bfa_fcs_fabric_notify_online(fabric
);
337 case BFA_FCS_FABRIC_SM_RETRY_OP
:
338 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_flogi_retry
);
339 bfa_timer_start(fabric
->fcs
->bfa
, &fabric
->delay_timer
,
340 bfa_fcs_fabric_delay
, fabric
,
341 BFA_FCS_FABRIC_RETRY_DELAY
);
344 case BFA_FCS_FABRIC_SM_LOOPBACK
:
345 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_loopback
);
346 bfa_sm_send_event(fabric
->lps
, BFA_LPS_SM_OFFLINE
);
347 bfa_fcs_fabric_set_opertype(fabric
);
350 case BFA_FCS_FABRIC_SM_NO_FABRIC
:
351 fabric
->fab_type
= BFA_FCS_FABRIC_N2N
;
352 bfa_fcport_set_tx_bbcredit(fabric
->fcs
->bfa
,
354 bfa_fcs_fabric_notify_online(fabric
);
355 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_nofabric
);
358 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
359 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
360 bfa_sm_send_event(fabric
->lps
, BFA_LPS_SM_OFFLINE
);
363 case BFA_FCS_FABRIC_SM_DELETE
:
364 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
365 bfa_sm_send_event(fabric
->lps
, BFA_LPS_SM_OFFLINE
);
366 bfa_fcs_fabric_delete(fabric
);
370 bfa_sm_fault(fabric
->fcs
, event
);
376 bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s
*fabric
,
377 enum bfa_fcs_fabric_event event
)
379 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
380 bfa_trc(fabric
->fcs
, event
);
383 case BFA_FCS_FABRIC_SM_DELAYED
:
384 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_flogi
);
385 bfa_fcs_fabric_login(fabric
);
388 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
389 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
390 bfa_timer_stop(&fabric
->delay_timer
);
393 case BFA_FCS_FABRIC_SM_DELETE
:
394 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
395 bfa_timer_stop(&fabric
->delay_timer
);
396 bfa_fcs_fabric_delete(fabric
);
400 bfa_sm_fault(fabric
->fcs
, event
);
405 * Authentication is in progress, awaiting authentication results.
408 bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s
*fabric
,
409 enum bfa_fcs_fabric_event event
)
411 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
412 bfa_trc(fabric
->fcs
, event
);
415 case BFA_FCS_FABRIC_SM_AUTH_FAILED
:
416 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_auth_failed
);
417 bfa_sm_send_event(fabric
->lps
, BFA_LPS_SM_OFFLINE
);
420 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS
:
421 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_online
);
422 bfa_fcs_fabric_notify_online(fabric
);
425 case BFA_FCS_FABRIC_SM_PERF_EVFP
:
426 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_evfp
);
429 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
430 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
431 bfa_sm_send_event(fabric
->lps
, BFA_LPS_SM_OFFLINE
);
434 case BFA_FCS_FABRIC_SM_DELETE
:
435 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
436 bfa_fcs_fabric_delete(fabric
);
440 bfa_sm_fault(fabric
->fcs
, event
);
445 * Authentication failed
448 bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s
*fabric
,
449 enum bfa_fcs_fabric_event event
)
451 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
452 bfa_trc(fabric
->fcs
, event
);
455 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
456 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
457 bfa_fcs_fabric_notify_offline(fabric
);
460 case BFA_FCS_FABRIC_SM_DELETE
:
461 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
462 bfa_fcs_fabric_delete(fabric
);
466 bfa_sm_fault(fabric
->fcs
, event
);
471 * Port is in loopback mode.
474 bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s
*fabric
,
475 enum bfa_fcs_fabric_event event
)
477 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
478 bfa_trc(fabric
->fcs
, event
);
481 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
482 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
483 bfa_fcs_fabric_notify_offline(fabric
);
486 case BFA_FCS_FABRIC_SM_DELETE
:
487 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
488 bfa_fcs_fabric_delete(fabric
);
492 bfa_sm_fault(fabric
->fcs
, event
);
497 * There is no attached fabric - private loop or NPort-to-NPort topology.
500 bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s
*fabric
,
501 enum bfa_fcs_fabric_event event
)
503 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
504 bfa_trc(fabric
->fcs
, event
);
507 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
508 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
509 bfa_sm_send_event(fabric
->lps
, BFA_LPS_SM_OFFLINE
);
510 bfa_fcs_fabric_notify_offline(fabric
);
513 case BFA_FCS_FABRIC_SM_DELETE
:
514 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
515 bfa_fcs_fabric_delete(fabric
);
518 case BFA_FCS_FABRIC_SM_NO_FABRIC
:
519 bfa_trc(fabric
->fcs
, fabric
->bb_credit
);
520 bfa_fcport_set_tx_bbcredit(fabric
->fcs
->bfa
,
525 bfa_sm_fault(fabric
->fcs
, event
);
530 * Fabric is online - normal operating state.
533 bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s
*fabric
,
534 enum bfa_fcs_fabric_event event
)
536 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
537 bfa_trc(fabric
->fcs
, event
);
540 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
541 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
542 bfa_sm_send_event(fabric
->lps
, BFA_LPS_SM_OFFLINE
);
543 bfa_fcs_fabric_notify_offline(fabric
);
546 case BFA_FCS_FABRIC_SM_DELETE
:
547 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
548 bfa_fcs_fabric_delete(fabric
);
551 case BFA_FCS_FABRIC_SM_AUTH_FAILED
:
552 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_auth_failed
);
553 bfa_sm_send_event(fabric
->lps
, BFA_LPS_SM_OFFLINE
);
556 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS
:
560 bfa_sm_fault(fabric
->fcs
, event
);
565 * Exchanging virtual fabric parameters.
568 bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s
*fabric
,
569 enum bfa_fcs_fabric_event event
)
571 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
572 bfa_trc(fabric
->fcs
, event
);
575 case BFA_FCS_FABRIC_SM_CONT_OP
:
576 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_evfp_done
);
579 case BFA_FCS_FABRIC_SM_ISOLATE
:
580 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_isolated
);
584 bfa_sm_fault(fabric
->fcs
, event
);
589 * EVFP exchange complete and VFT tagging is enabled.
592 bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s
*fabric
,
593 enum bfa_fcs_fabric_event event
)
595 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
596 bfa_trc(fabric
->fcs
, event
);
600 * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
603 bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s
*fabric
,
604 enum bfa_fcs_fabric_event event
)
606 struct bfad_s
*bfad
= (struct bfad_s
*)fabric
->fcs
->bfad
;
607 char pwwn_ptr
[BFA_STRING_32
];
609 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
610 bfa_trc(fabric
->fcs
, event
);
611 wwn2str(pwwn_ptr
, fabric
->bport
.port_cfg
.pwwn
);
613 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
614 "Port is isolated due to VF_ID mismatch. "
615 "PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",
616 pwwn_ptr
, fabric
->fcs
->port_vfid
,
617 fabric
->event_arg
.swp_vfid
);
621 * Fabric is being deleted, awaiting vport delete completions.
624 bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s
*fabric
,
625 enum bfa_fcs_fabric_event event
)
627 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
628 bfa_trc(fabric
->fcs
, event
);
631 case BFA_FCS_FABRIC_SM_DELCOMP
:
632 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_uninit
);
633 bfa_wc_down(&fabric
->fcs
->wc
);
636 case BFA_FCS_FABRIC_SM_LINK_UP
:
639 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
640 bfa_fcs_fabric_notify_offline(fabric
);
644 bfa_sm_fault(fabric
->fcs
, event
);
651 * fcs_fabric_private fabric private functions
655 bfa_fcs_fabric_init(struct bfa_fcs_fabric_s
*fabric
)
657 struct bfa_lport_cfg_s
*port_cfg
= &fabric
->bport
.port_cfg
;
659 port_cfg
->roles
= BFA_LPORT_ROLE_FCP_IM
;
660 port_cfg
->nwwn
= fabric
->fcs
->bfa
->ioc
.attr
->nwwn
;
661 port_cfg
->pwwn
= fabric
->fcs
->bfa
->ioc
.attr
->pwwn
;
665 * Port Symbolic Name Creation for base port.
668 bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s
*fabric
)
670 struct bfa_lport_cfg_s
*port_cfg
= &fabric
->bport
.port_cfg
;
671 char model
[BFA_ADAPTER_MODEL_NAME_LEN
] = {0};
672 struct bfa_fcs_driver_info_s
*driver_info
= &fabric
->fcs
->driver_info
;
674 bfa_ioc_get_adapter_model(&fabric
->fcs
->bfa
->ioc
, model
);
676 /* Model name/number */
677 strncpy((char *)&port_cfg
->sym_name
, model
,
678 BFA_FCS_PORT_SYMBNAME_MODEL_SZ
);
679 strncat((char *)&port_cfg
->sym_name
, BFA_FCS_PORT_SYMBNAME_SEPARATOR
,
680 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR
));
683 strncat((char *)&port_cfg
->sym_name
, (char *)driver_info
->version
,
684 BFA_FCS_PORT_SYMBNAME_VERSION_SZ
);
685 strncat((char *)&port_cfg
->sym_name
, BFA_FCS_PORT_SYMBNAME_SEPARATOR
,
686 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR
));
688 /* Host machine name */
689 strncat((char *)&port_cfg
->sym_name
,
690 (char *)driver_info
->host_machine_name
,
691 BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ
);
692 strncat((char *)&port_cfg
->sym_name
, BFA_FCS_PORT_SYMBNAME_SEPARATOR
,
693 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR
));
697 * If OS Patch Info is not there, do not truncate any bytes from the
698 * OS name string and instead copy the entire OS info string (64 bytes).
700 if (driver_info
->host_os_patch
[0] == '\0') {
701 strncat((char *)&port_cfg
->sym_name
,
702 (char *)driver_info
->host_os_name
,
704 strncat((char *)&port_cfg
->sym_name
,
705 BFA_FCS_PORT_SYMBNAME_SEPARATOR
,
706 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR
));
708 strncat((char *)&port_cfg
->sym_name
,
709 (char *)driver_info
->host_os_name
,
710 BFA_FCS_PORT_SYMBNAME_OSINFO_SZ
);
711 strncat((char *)&port_cfg
->sym_name
,
712 BFA_FCS_PORT_SYMBNAME_SEPARATOR
,
713 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR
));
715 /* Append host OS Patch Info */
716 strncat((char *)&port_cfg
->sym_name
,
717 (char *)driver_info
->host_os_patch
,
718 BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ
);
722 port_cfg
->sym_name
.symname
[BFA_SYMNAME_MAXLEN
- 1] = 0;
726 * bfa lps login completion callback
729 bfa_cb_lps_flogi_comp(void *bfad
, void *uarg
, bfa_status_t status
)
731 struct bfa_fcs_fabric_s
*fabric
= uarg
;
733 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
734 bfa_trc(fabric
->fcs
, status
);
738 fabric
->stats
.flogi_accepts
++;
741 case BFA_STATUS_INVALID_MAC
:
743 fabric
->stats
.flogi_acc_err
++;
744 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_RETRY_OP
);
748 case BFA_STATUS_EPROTOCOL
:
749 switch (fabric
->lps
->ext_status
) {
750 case BFA_EPROTO_BAD_ACCEPT
:
751 fabric
->stats
.flogi_acc_err
++;
754 case BFA_EPROTO_UNKNOWN_RSP
:
755 fabric
->stats
.flogi_unknown_rsp
++;
761 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_RETRY_OP
);
765 case BFA_STATUS_FABRIC_RJT
:
766 fabric
->stats
.flogi_rejects
++;
767 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_RETRY_OP
);
771 fabric
->stats
.flogi_rsp_err
++;
772 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_RETRY_OP
);
776 fabric
->bb_credit
= fabric
->lps
->pr_bbcred
;
777 bfa_trc(fabric
->fcs
, fabric
->bb_credit
);
779 if (!(fabric
->lps
->brcd_switch
))
780 fabric
->fabric_name
= fabric
->lps
->pr_nwwn
;
783 * Check port type. It should be 1 = F-port.
785 if (fabric
->lps
->fport
) {
786 fabric
->bport
.pid
= fabric
->lps
->lp_pid
;
787 fabric
->is_npiv
= fabric
->lps
->npiv_en
;
788 fabric
->is_auth
= fabric
->lps
->auth_req
;
789 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_CONT_OP
);
792 * Nport-2-Nport direct attached
794 fabric
->bport
.port_topo
.pn2n
.rem_port_wwn
=
795 fabric
->lps
->pr_pwwn
;
796 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_NO_FABRIC
);
799 bfa_trc(fabric
->fcs
, fabric
->bport
.pid
);
800 bfa_trc(fabric
->fcs
, fabric
->is_npiv
);
801 bfa_trc(fabric
->fcs
, fabric
->is_auth
);
804 * Allocate and send FLOGI.
807 bfa_fcs_fabric_login(struct bfa_fcs_fabric_s
*fabric
)
809 struct bfa_s
*bfa
= fabric
->fcs
->bfa
;
810 struct bfa_lport_cfg_s
*pcfg
= &fabric
->bport
.port_cfg
;
813 if (bfa_fcport_get_topology(bfa
) == BFA_PORT_TOPOLOGY_LOOP
)
814 alpa
= bfa_fcport_get_myalpa(bfa
);
816 bfa_lps_flogi(fabric
->lps
, fabric
, alpa
, bfa_fcport_get_maxfrsize(bfa
),
817 pcfg
->pwwn
, pcfg
->nwwn
, fabric
->auth_reqd
);
819 fabric
->stats
.flogi_sent
++;
823 bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s
*fabric
)
825 struct bfa_fcs_vport_s
*vport
;
826 struct list_head
*qe
, *qen
;
828 bfa_trc(fabric
->fcs
, fabric
->fabric_name
);
830 bfa_fcs_fabric_set_opertype(fabric
);
831 fabric
->stats
.fabric_onlines
++;
834 * notify online event to base and then virtual ports
836 bfa_fcs_lport_online(&fabric
->bport
);
838 list_for_each_safe(qe
, qen
, &fabric
->vport_q
) {
839 vport
= (struct bfa_fcs_vport_s
*) qe
;
840 bfa_fcs_vport_online(vport
);
845 bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s
*fabric
)
847 struct bfa_fcs_vport_s
*vport
;
848 struct list_head
*qe
, *qen
;
850 bfa_trc(fabric
->fcs
, fabric
->fabric_name
);
851 fabric
->stats
.fabric_offlines
++;
854 * notify offline event first to vports and then base port.
856 list_for_each_safe(qe
, qen
, &fabric
->vport_q
) {
857 vport
= (struct bfa_fcs_vport_s
*) qe
;
858 bfa_fcs_vport_offline(vport
);
861 bfa_fcs_lport_offline(&fabric
->bport
);
863 fabric
->fabric_name
= 0;
864 fabric
->fabric_ip_addr
[0] = 0;
868 bfa_fcs_fabric_delay(void *cbarg
)
870 struct bfa_fcs_fabric_s
*fabric
= cbarg
;
872 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_DELAYED
);
876 * Delete all vports and wait for vport delete completions.
879 bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s
*fabric
)
881 struct bfa_fcs_vport_s
*vport
;
882 struct list_head
*qe
, *qen
;
884 list_for_each_safe(qe
, qen
, &fabric
->vport_q
) {
885 vport
= (struct bfa_fcs_vport_s
*) qe
;
886 bfa_fcs_vport_fcs_delete(vport
);
889 bfa_fcs_lport_delete(&fabric
->bport
);
890 bfa_wc_wait(&fabric
->wc
);
894 bfa_fcs_fabric_delete_comp(void *cbarg
)
896 struct bfa_fcs_fabric_s
*fabric
= cbarg
;
898 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_DELCOMP
);
902 * fcs_fabric_public fabric public functions
906 * Attach time initialization.
909 bfa_fcs_fabric_attach(struct bfa_fcs_s
*fcs
)
911 struct bfa_fcs_fabric_s
*fabric
;
913 fabric
= &fcs
->fabric
;
914 memset(fabric
, 0, sizeof(struct bfa_fcs_fabric_s
));
917 * Initialize base fabric.
920 INIT_LIST_HEAD(&fabric
->vport_q
);
921 INIT_LIST_HEAD(&fabric
->vf_q
);
922 fabric
->lps
= bfa_lps_alloc(fcs
->bfa
);
923 WARN_ON(!fabric
->lps
);
926 * Initialize fabric delete completion handler. Fabric deletion is
927 * complete when the last vport delete is complete.
929 bfa_wc_init(&fabric
->wc
, bfa_fcs_fabric_delete_comp
, fabric
);
930 bfa_wc_up(&fabric
->wc
); /* For the base port */
932 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_uninit
);
933 bfa_fcs_lport_attach(&fabric
->bport
, fabric
->fcs
, FC_VF_ID_NULL
, NULL
);
937 bfa_fcs_fabric_modinit(struct bfa_fcs_s
*fcs
)
939 bfa_sm_send_event(&fcs
->fabric
, BFA_FCS_FABRIC_SM_CREATE
);
947 bfa_fcs_fabric_modexit(struct bfa_fcs_s
*fcs
)
949 struct bfa_fcs_fabric_s
*fabric
;
954 * Cleanup base fabric.
956 fabric
= &fcs
->fabric
;
957 bfa_lps_delete(fabric
->lps
);
958 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_DELETE
);
962 * Fabric module start -- kick starts FCS actions
965 bfa_fcs_fabric_modstart(struct bfa_fcs_s
*fcs
)
967 struct bfa_fcs_fabric_s
*fabric
;
970 fabric
= &fcs
->fabric
;
971 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_START
);
976 * Link up notification from BFA physical port module.
979 bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s
*fabric
)
981 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
982 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_LINK_UP
);
986 * Link down notification from BFA physical port module.
989 bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s
*fabric
)
991 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
992 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_LINK_DOWN
);
996 * A child vport is being created in the fabric.
998 * Call from vport module at vport creation. A list of base port and vports
999 * belonging to a fabric is maintained to propagate link events.
1001 * param[in] fabric - Fabric instance. This can be a base fabric or vf.
1002 * param[in] vport - Vport being created.
1004 * @return None (always succeeds)
1007 bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s
*fabric
,
1008 struct bfa_fcs_vport_s
*vport
)
1011 * - add vport to fabric's vport_q
1013 bfa_trc(fabric
->fcs
, fabric
->vf_id
);
1015 list_add_tail(&vport
->qe
, &fabric
->vport_q
);
1016 fabric
->num_vports
++;
1017 bfa_wc_up(&fabric
->wc
);
1021 * A child vport is being deleted from fabric.
1023 * Vport is being deleted.
1026 bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s
*fabric
,
1027 struct bfa_fcs_vport_s
*vport
)
1029 list_del(&vport
->qe
);
1030 fabric
->num_vports
--;
1031 bfa_wc_down(&fabric
->wc
);
1036 * Lookup for a vport within a fabric given its pwwn
1038 struct bfa_fcs_vport_s
*
1039 bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s
*fabric
, wwn_t pwwn
)
1041 struct bfa_fcs_vport_s
*vport
;
1042 struct list_head
*qe
;
1044 list_for_each(qe
, &fabric
->vport_q
) {
1045 vport
= (struct bfa_fcs_vport_s
*) qe
;
1046 if (bfa_fcs_lport_get_pwwn(&vport
->lport
) == pwwn
)
1055 * Get OUI of the attached switch.
1057 * Note : Use of this function should be avoided as much as possible.
1058 * This function should be used only if there is any requirement
1059 * to check for FOS version below 6.3.
1060 * To check if the attached fabric is a brocade fabric, use
1061 * bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
1066 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s
*fabric
)
1072 fab_nwwn
= fabric
->lps
->pr_nwwn
;
1074 tmp
= (u8
*)&fab_nwwn
;
1075 oui
= (tmp
[3] << 8) | tmp
[4];
1080 * Unsolicited frame receive handling.
1083 bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s
*fabric
, struct fchs_s
*fchs
,
1086 u32 pid
= fchs
->d_id
;
1087 struct bfa_fcs_vport_s
*vport
;
1088 struct list_head
*qe
;
1089 struct fc_els_cmd_s
*els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
1090 struct fc_logi_s
*flogi
= (struct fc_logi_s
*) els_cmd
;
1092 bfa_trc(fabric
->fcs
, len
);
1093 bfa_trc(fabric
->fcs
, pid
);
1096 * Look for our own FLOGI frames being looped back. This means an
1097 * external loopback cable is in place. Our own FLOGI frames are
1098 * sometimes looped back when switch port gets temporarily bypassed.
1100 if ((pid
== bfa_ntoh3b(FC_FABRIC_PORT
)) &&
1101 (els_cmd
->els_code
== FC_ELS_FLOGI
) &&
1102 (flogi
->port_name
== bfa_fcs_lport_get_pwwn(&fabric
->bport
))) {
1103 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_LOOPBACK
);
1108 * FLOGI/EVFP exchanges should be consumed by base fabric.
1110 if (fchs
->d_id
== bfa_hton3b(FC_FABRIC_PORT
)) {
1111 bfa_trc(fabric
->fcs
, pid
);
1112 bfa_fcs_fabric_process_uf(fabric
, fchs
, len
);
1116 if (fabric
->bport
.pid
== pid
) {
1118 * All authentication frames should be routed to auth
1120 bfa_trc(fabric
->fcs
, els_cmd
->els_code
);
1121 if (els_cmd
->els_code
== FC_ELS_AUTH
) {
1122 bfa_trc(fabric
->fcs
, els_cmd
->els_code
);
1126 bfa_trc(fabric
->fcs
, *(u8
*) ((u8
*) fchs
));
1127 bfa_fcs_lport_uf_recv(&fabric
->bport
, fchs
, len
);
1132 * look for a matching local port ID
1134 list_for_each(qe
, &fabric
->vport_q
) {
1135 vport
= (struct bfa_fcs_vport_s
*) qe
;
1136 if (vport
->lport
.pid
== pid
) {
1137 bfa_fcs_lport_uf_recv(&vport
->lport
, fchs
, len
);
1141 bfa_trc(fabric
->fcs
, els_cmd
->els_code
);
1142 bfa_fcs_lport_uf_recv(&fabric
->bport
, fchs
, len
);
1146 * Unsolicited frames to be processed by fabric.
1149 bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s
*fabric
, struct fchs_s
*fchs
,
1152 struct fc_els_cmd_s
*els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
1154 bfa_trc(fabric
->fcs
, els_cmd
->els_code
);
1156 switch (els_cmd
->els_code
) {
1158 bfa_fcs_fabric_process_flogi(fabric
, fchs
, len
);
1163 * need to generate a LS_RJT
1170 * Process incoming FLOGI
1173 bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s
*fabric
,
1174 struct fchs_s
*fchs
, u16 len
)
1176 struct fc_logi_s
*flogi
= (struct fc_logi_s
*) (fchs
+ 1);
1177 struct bfa_fcs_lport_s
*bport
= &fabric
->bport
;
1179 bfa_trc(fabric
->fcs
, fchs
->s_id
);
1181 fabric
->stats
.flogi_rcvd
++;
1183 * Check port type. It should be 0 = n-port.
1185 if (flogi
->csp
.port_type
) {
1187 * @todo: may need to send a LS_RJT
1189 bfa_trc(fabric
->fcs
, flogi
->port_name
);
1190 fabric
->stats
.flogi_rejected
++;
1194 fabric
->bb_credit
= be16_to_cpu(flogi
->csp
.bbcred
);
1195 bport
->port_topo
.pn2n
.rem_port_wwn
= flogi
->port_name
;
1196 bport
->port_topo
.pn2n
.reply_oxid
= fchs
->ox_id
;
1201 bfa_fcs_fabric_send_flogi_acc(fabric
);
1202 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_NO_FABRIC
);
1206 bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s
*fabric
)
1208 struct bfa_lport_cfg_s
*pcfg
= &fabric
->bport
.port_cfg
;
1209 struct bfa_fcs_lport_n2n_s
*n2n_port
= &fabric
->bport
.port_topo
.pn2n
;
1210 struct bfa_s
*bfa
= fabric
->fcs
->bfa
;
1211 struct bfa_fcxp_s
*fcxp
;
1215 fcxp
= bfa_fcs_fcxp_alloc(fabric
->fcs
);
1217 * Do not expect this failure -- expect remote node to retry
1222 reqlen
= fc_flogi_acc_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
),
1223 bfa_hton3b(FC_FABRIC_PORT
),
1224 n2n_port
->reply_oxid
, pcfg
->pwwn
,
1226 bfa_fcport_get_maxfrsize(bfa
),
1227 bfa_fcport_get_rx_bbcredit(bfa
));
1229 bfa_fcxp_send(fcxp
, NULL
, fabric
->vf_id
, fabric
->lps
->lp_tag
,
1230 BFA_FALSE
, FC_CLASS_3
,
1231 reqlen
, &fchs
, bfa_fcs_fabric_flogiacc_comp
, fabric
,
1236 * Flogi Acc completion callback.
1239 bfa_fcs_fabric_flogiacc_comp(void *fcsarg
, struct bfa_fcxp_s
*fcxp
, void *cbarg
,
1240 bfa_status_t status
, u32 rsp_len
,
1241 u32 resid_len
, struct fchs_s
*rspfchs
)
1243 struct bfa_fcs_fabric_s
*fabric
= cbarg
;
1245 bfa_trc(fabric
->fcs
, status
);
1250 * @param[in] fabric - fabric
1251 * @param[in] wwn_t - new fabric name
1256 bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s
*fabric
,
1259 struct bfad_s
*bfad
= (struct bfad_s
*)fabric
->fcs
->bfad
;
1260 char pwwn_ptr
[BFA_STRING_32
];
1261 char fwwn_ptr
[BFA_STRING_32
];
1263 bfa_trc(fabric
->fcs
, fabric_name
);
1265 if (fabric
->fabric_name
== 0) {
1267 * With BRCD switches, we don't get Fabric Name in FLOGI.
1268 * Don't generate a fabric name change event in this case.
1270 fabric
->fabric_name
= fabric_name
;
1272 fabric
->fabric_name
= fabric_name
;
1273 wwn2str(pwwn_ptr
, bfa_fcs_lport_get_pwwn(&fabric
->bport
));
1275 bfa_fcs_lport_get_fabric_name(&fabric
->bport
));
1276 BFA_LOG(KERN_WARNING
, bfad
, bfa_log_level
,
1277 "Base port WWN = %s Fabric WWN = %s\n",
1278 pwwn_ptr
, fwwn_ptr
);
1283 * Returns FCS vf structure for a given vf_id.
1285 * param[in] vf_id - VF_ID
1288 * If lookup succeeds, retuns fcs vf object, otherwise returns NULL
1291 bfa_fcs_vf_lookup(struct bfa_fcs_s
*fcs
, u16 vf_id
)
1293 bfa_trc(fcs
, vf_id
);
1294 if (vf_id
== FC_VF_ID_NULL
)
1295 return &fcs
->fabric
;
1301 * BFA FCS PPORT ( physical port)
1304 bfa_fcs_port_event_handler(void *cbarg
, enum bfa_port_linkstate event
)
1306 struct bfa_fcs_s
*fcs
= cbarg
;
1308 bfa_trc(fcs
, event
);
1311 case BFA_PORT_LINKUP
:
1312 bfa_fcs_fabric_link_up(&fcs
->fabric
);
1315 case BFA_PORT_LINKDOWN
:
1316 bfa_fcs_fabric_link_down(&fcs
->fabric
);
1325 bfa_fcs_port_attach(struct bfa_fcs_s
*fcs
)
1327 bfa_fcport_event_register(fcs
->bfa
, bfa_fcs_port_event_handler
, fcs
);
1331 * BFA FCS UF ( Unsolicited Frames)
1335 * BFA callback for unsolicited frame receive handler.
1337 * @param[in] cbarg callback arg for receive handler
1338 * @param[in] uf unsolicited frame descriptor
1343 bfa_fcs_uf_recv(void *cbarg
, struct bfa_uf_s
*uf
)
1345 struct bfa_fcs_s
*fcs
= (struct bfa_fcs_s
*) cbarg
;
1346 struct fchs_s
*fchs
= bfa_uf_get_frmbuf(uf
);
1347 u16 len
= bfa_uf_get_frmlen(uf
);
1348 struct fc_vft_s
*vft
;
1349 struct bfa_fcs_fabric_s
*fabric
;
1352 * check for VFT header
1354 if (fchs
->routing
== FC_RTG_EXT_HDR
&&
1355 fchs
->cat_info
== FC_CAT_VFT_HDR
) {
1356 bfa_stats(fcs
, uf
.tagged
);
1357 vft
= bfa_uf_get_frmbuf(uf
);
1358 if (fcs
->port_vfid
== vft
->vf_id
)
1359 fabric
= &fcs
->fabric
;
1361 fabric
= bfa_fcs_vf_lookup(fcs
, (u16
) vft
->vf_id
);
1364 * drop frame if vfid is unknown
1368 bfa_stats(fcs
, uf
.vfid_unknown
);
1376 fchs
= (struct fchs_s
*) (vft
+ 1);
1377 len
-= sizeof(struct fc_vft_s
);
1379 bfa_trc(fcs
, vft
->vf_id
);
1381 bfa_stats(fcs
, uf
.untagged
);
1382 fabric
= &fcs
->fabric
;
1385 bfa_trc(fcs
, ((u32
*) fchs
)[0]);
1386 bfa_trc(fcs
, ((u32
*) fchs
)[1]);
1387 bfa_trc(fcs
, ((u32
*) fchs
)[2]);
1388 bfa_trc(fcs
, ((u32
*) fchs
)[3]);
1389 bfa_trc(fcs
, ((u32
*) fchs
)[4]);
1390 bfa_trc(fcs
, ((u32
*) fchs
)[5]);
1393 bfa_fcs_fabric_uf_recv(fabric
, fchs
, len
);
1398 bfa_fcs_uf_attach(struct bfa_fcs_s
*fcs
)
1400 bfa_uf_recv_register(fcs
->bfa
, bfa_fcs_uf_recv
, fcs
);