2 * Copyright (c) 2005-2009 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 * fabric.c Fabric module implementation.
22 #include "fcs_fabric.h"
23 #include "fcs_lport.h"
24 #include "fcs_vport.h"
25 #include "fcs_trcmod.h"
30 #include <log/bfa_log_fcs.h>
31 #include <aen/bfa_aen_port.h>
34 BFA_TRC_FILE(FCS
, FABRIC
);
36 #define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */
37 #define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */
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; \
44 (__fabric)->oper_type = BFA_PPORT_TYPE_NLPORT; \
48 * forward declarations
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
,
67 struct fchs_s
*rspfchs
);
69 * fcs_fabric_sm fabric state machine functions
73 * Fabric state machine events
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
84 BFA_FCS_FABRIC_SM_PERF_EVFP
= 8, /* perform EVFP from
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
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 */
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
);
126 * Beginning state before fabric creation.
129 bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s
*fabric
,
130 enum bfa_fcs_fabric_event event
)
132 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
133 bfa_trc(fabric
->fcs
, 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
);
143 case BFA_FCS_FABRIC_SM_LINK_UP
:
144 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
148 bfa_sm_fault(fabric
->fcs
, event
);
153 * Beginning state before fabric creation.
156 bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s
*fabric
,
157 enum bfa_fcs_fabric_event event
)
159 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
160 bfa_trc(fabric
->fcs
, 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
);
168 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
171 case BFA_FCS_FABRIC_SM_LINK_UP
:
172 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
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
);
181 bfa_sm_fault(fabric
->fcs
, event
);
186 * Link is down, awaiting LINK UP event from port. This is also the
187 * first state at fabric creation.
190 bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s
*fabric
,
191 enum bfa_fcs_fabric_event event
)
193 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
194 bfa_trc(fabric
->fcs
, 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
);
202 case BFA_FCS_FABRIC_SM_RETRY_OP
:
205 case BFA_FCS_FABRIC_SM_DELETE
:
206 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
207 bfa_fcs_fabric_delete(fabric
);
211 bfa_sm_fault(fabric
->fcs
, event
);
216 * FLOGI is in progress, awaiting FLOGI reply.
219 bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s
*fabric
,
220 enum bfa_fcs_fabric_event event
)
222 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
223 bfa_trc(fabric
->fcs
, event
);
226 case BFA_FCS_FABRIC_SM_CONT_OP
:
228 bfa_pport_set_tx_bbcredit(fabric
->fcs
->bfa
, fabric
->bb_credit
);
229 fabric
->fab_type
= BFA_FCS_FABRIC_SWITCHED
;
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
);
235 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_online
);
236 bfa_fcs_fabric_notify_online(fabric
);
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
);
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
);
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
);
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
);
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
);
272 bfa_sm_fault(fabric
->fcs
, event
);
278 bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s
*fabric
,
279 enum bfa_fcs_fabric_event event
)
281 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
282 bfa_trc(fabric
->fcs
, 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
);
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
);
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
);
302 bfa_sm_fault(fabric
->fcs
, event
);
307 * Authentication is in progress, awaiting authentication results.
310 bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s
*fabric
,
311 enum bfa_fcs_fabric_event event
)
313 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
314 bfa_trc(fabric
->fcs
, 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
);
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
);
327 case BFA_FCS_FABRIC_SM_PERF_EVFP
:
328 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_evfp
);
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
);
336 case BFA_FCS_FABRIC_SM_DELETE
:
337 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
338 bfa_fcs_fabric_delete(fabric
);
342 bfa_sm_fault(fabric
->fcs
, event
);
347 * Authentication failed
350 bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s
*fabric
,
351 enum bfa_fcs_fabric_event event
)
353 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
354 bfa_trc(fabric
->fcs
, 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
);
362 case BFA_FCS_FABRIC_SM_DELETE
:
363 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
364 bfa_fcs_fabric_delete(fabric
);
368 bfa_sm_fault(fabric
->fcs
, event
);
373 * Port is in loopback mode.
376 bfa_fcs_fabric_sm_loopback(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_LINK_DOWN
:
384 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_linkdown
);
385 bfa_fcs_fabric_notify_offline(fabric
);
388 case BFA_FCS_FABRIC_SM_DELETE
:
389 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
390 bfa_fcs_fabric_delete(fabric
);
394 bfa_sm_fault(fabric
->fcs
, event
);
399 * There is no attached fabric - private loop or NPort-to-NPort topology.
402 bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s
*fabric
,
403 enum bfa_fcs_fabric_event event
)
405 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
406 bfa_trc(fabric
->fcs
, 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
);
415 case BFA_FCS_FABRIC_SM_DELETE
:
416 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
417 bfa_fcs_fabric_delete(fabric
);
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
);
426 bfa_sm_fault(fabric
->fcs
, event
);
431 * Fabric is online - normal operating state.
434 bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s
*fabric
,
435 enum bfa_fcs_fabric_event event
)
437 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
438 bfa_trc(fabric
->fcs
, 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
);
447 case BFA_FCS_FABRIC_SM_DELETE
:
448 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_deleting
);
449 bfa_fcs_fabric_delete(fabric
);
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
);
457 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS
:
461 bfa_sm_fault(fabric
->fcs
, event
);
466 * Exchanging virtual fabric parameters.
469 bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s
*fabric
,
470 enum bfa_fcs_fabric_event event
)
472 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
473 bfa_trc(fabric
->fcs
, event
);
476 case BFA_FCS_FABRIC_SM_CONT_OP
:
477 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_evfp_done
);
480 case BFA_FCS_FABRIC_SM_ISOLATE
:
481 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_isolated
);
485 bfa_sm_fault(fabric
->fcs
, event
);
490 * EVFP exchange complete and VFT tagging is enabled.
493 bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s
*fabric
,
494 enum bfa_fcs_fabric_event event
)
496 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
497 bfa_trc(fabric
->fcs
, event
);
501 * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
504 bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s
*fabric
,
505 enum bfa_fcs_fabric_event event
)
507 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
508 bfa_trc(fabric
->fcs
, event
);
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
);
516 * Fabric is being deleted, awaiting vport delete completions.
519 bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s
*fabric
,
520 enum bfa_fcs_fabric_event event
)
522 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
523 bfa_trc(fabric
->fcs
, 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
);
531 case BFA_FCS_FABRIC_SM_LINK_UP
:
534 case BFA_FCS_FABRIC_SM_LINK_DOWN
:
535 bfa_fcs_fabric_notify_offline(fabric
);
539 bfa_sm_fault(fabric
->fcs
, event
);
546 * fcs_fabric_private fabric private functions
550 bfa_fcs_fabric_init(struct bfa_fcs_fabric_s
*fabric
)
552 struct bfa_port_cfg_s
*port_cfg
= &fabric
->bport
.port_cfg
;
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
);
560 * Port Symbolic Name Creation for base port.
563 bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s
*fabric
)
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
;
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
);
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
));
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
));
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
));
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).
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
));
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
));
618 * Append host OS Patch Info
620 strncat((char *)&port_cfg
->sym_name
,
621 (char *)driver_info
->host_os_patch
,
622 BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ
);
628 port_cfg
->sym_name
.symname
[BFA_SYMNAME_MAXLEN
- 1] = 0;
632 * bfa lps login completion callback
635 bfa_cb_lps_flogi_comp(void *bfad
, void *uarg
, bfa_status_t status
)
637 struct bfa_fcs_fabric_s
*fabric
= uarg
;
639 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
640 bfa_trc(fabric
->fcs
, status
);
644 fabric
->stats
.flogi_accepts
++;
647 case BFA_STATUS_INVALID_MAC
:
651 fabric
->stats
.flogi_acc_err
++;
652 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_RETRY_OP
);
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
++;
662 case BFA_EPROTO_UNKNOWN_RSP
:
663 fabric
->stats
.flogi_unknown_rsp
++;
669 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_RETRY_OP
);
673 case BFA_STATUS_FABRIC_RJT
:
674 fabric
->stats
.flogi_rejects
++;
675 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_RETRY_OP
);
679 fabric
->stats
.flogi_rsp_err
++;
680 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_RETRY_OP
);
684 fabric
->bb_credit
= bfa_lps_get_peer_bbcredit(fabric
->lps
);
685 bfa_trc(fabric
->fcs
, fabric
->bb_credit
);
687 if (!bfa_lps_is_brcd_fabric(fabric
->lps
))
688 fabric
->fabric_name
= bfa_lps_get_peer_nwwn(fabric
->lps
);
691 * Check port type. It should be 1 = F-port.
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
);
700 * Nport-2-Nport direct attached
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
);
707 bfa_trc(fabric
->fcs
, fabric
->bport
.pid
);
708 bfa_trc(fabric
->fcs
, fabric
->is_npiv
);
709 bfa_trc(fabric
->fcs
, fabric
->is_auth
);
713 * Allocate and send FLOGI.
716 bfa_fcs_fabric_login(struct bfa_fcs_fabric_s
*fabric
)
718 struct bfa_s
*bfa
= fabric
->fcs
->bfa
;
719 struct bfa_port_cfg_s
*pcfg
= &fabric
->bport
.port_cfg
;
722 if (bfa_pport_get_topology(bfa
) == BFA_PPORT_TOPOLOGY_LOOP
)
723 alpa
= bfa_pport_get_myalpa(bfa
);
725 bfa_lps_flogi(fabric
->lps
, fabric
, alpa
, bfa_pport_get_maxfrsize(bfa
),
726 pcfg
->pwwn
, pcfg
->nwwn
, fabric
->auth_reqd
);
728 fabric
->stats
.flogi_sent
++;
732 bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s
*fabric
)
734 struct bfa_fcs_vport_s
*vport
;
735 struct list_head
*qe
, *qen
;
737 bfa_trc(fabric
->fcs
, fabric
->fabric_name
);
739 bfa_fcs_fabric_set_opertype(fabric
);
740 fabric
->stats
.fabric_onlines
++;
743 * notify online event to base and then virtual ports
745 bfa_fcs_port_online(&fabric
->bport
);
747 list_for_each_safe(qe
, qen
, &fabric
->vport_q
) {
748 vport
= (struct bfa_fcs_vport_s
*)qe
;
749 bfa_fcs_vport_online(vport
);
754 bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s
*fabric
)
756 struct bfa_fcs_vport_s
*vport
;
757 struct list_head
*qe
, *qen
;
759 bfa_trc(fabric
->fcs
, fabric
->fabric_name
);
760 fabric
->stats
.fabric_offlines
++;
763 * notify offline event first to vports and then base port.
765 list_for_each_safe(qe
, qen
, &fabric
->vport_q
) {
766 vport
= (struct bfa_fcs_vport_s
*)qe
;
767 bfa_fcs_vport_offline(vport
);
770 bfa_fcs_port_offline(&fabric
->bport
);
772 fabric
->fabric_name
= 0;
773 fabric
->fabric_ip_addr
[0] = 0;
777 bfa_fcs_fabric_delay(void *cbarg
)
779 struct bfa_fcs_fabric_s
*fabric
= cbarg
;
781 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_DELAYED
);
785 * Delete all vports and wait for vport delete completions.
788 bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s
*fabric
)
790 struct bfa_fcs_vport_s
*vport
;
791 struct list_head
*qe
, *qen
;
793 list_for_each_safe(qe
, qen
, &fabric
->vport_q
) {
794 vport
= (struct bfa_fcs_vport_s
*)qe
;
795 bfa_fcs_vport_delete(vport
);
798 bfa_fcs_port_delete(&fabric
->bport
);
799 bfa_wc_wait(&fabric
->wc
);
803 bfa_fcs_fabric_delete_comp(void *cbarg
)
805 struct bfa_fcs_fabric_s
*fabric
= cbarg
;
807 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_DELCOMP
);
813 * fcs_fabric_public fabric public functions
817 * Module initialization
820 bfa_fcs_fabric_modinit(struct bfa_fcs_s
*fcs
)
822 struct bfa_fcs_fabric_s
*fabric
;
824 fabric
= &fcs
->fabric
;
825 bfa_os_memset(fabric
, 0, sizeof(struct bfa_fcs_fabric_s
));
828 * Initialize base fabric.
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
);
837 * Initialize fabric delete completion handler. Fabric deletion is complete
838 * when the last vport delete is complete.
840 bfa_wc_init(&fabric
->wc
, bfa_fcs_fabric_delete_comp
, fabric
);
841 bfa_wc_up(&fabric
->wc
); /* For the base port */
843 bfa_sm_set_state(fabric
, bfa_fcs_fabric_sm_uninit
);
844 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_CREATE
);
852 bfa_fcs_fabric_modexit(struct bfa_fcs_s
*fcs
)
854 struct bfa_fcs_fabric_s
*fabric
;
859 * Cleanup base fabric.
861 fabric
= &fcs
->fabric
;
862 bfa_lps_delete(fabric
->lps
);
863 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_DELETE
);
867 * Fabric module start -- kick starts FCS actions
870 bfa_fcs_fabric_modstart(struct bfa_fcs_s
*fcs
)
872 struct bfa_fcs_fabric_s
*fabric
;
875 fabric
= &fcs
->fabric
;
876 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_START
);
880 * Suspend fabric activity as part of driver suspend.
883 bfa_fcs_fabric_modsusp(struct bfa_fcs_s
*fcs
)
888 bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s
*fabric
)
890 return (bfa_sm_cmp_state(fabric
, bfa_fcs_fabric_sm_loopback
));
894 bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s
*fabric
)
896 return fabric
->oper_type
;
900 * Link up notification from BFA physical port module.
903 bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s
*fabric
)
905 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
906 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_LINK_UP
);
910 * Link down notification from BFA physical port module.
913 bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s
*fabric
)
915 bfa_trc(fabric
->fcs
, fabric
->bport
.port_cfg
.pwwn
);
916 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_LINK_DOWN
);
920 * A child vport is being created in the fabric.
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.
925 * param[in] fabric - Fabric instance. This can be a base fabric or vf.
926 * param[in] vport - Vport being created.
928 * @return None (always succeeds)
931 bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s
*fabric
,
932 struct bfa_fcs_vport_s
*vport
)
935 * - add vport to fabric's vport_q
937 bfa_trc(fabric
->fcs
, fabric
->vf_id
);
939 list_add_tail(&vport
->qe
, &fabric
->vport_q
);
940 fabric
->num_vports
++;
941 bfa_wc_up(&fabric
->wc
);
945 * A child vport is being deleted from fabric.
947 * Vport is being deleted.
950 bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s
*fabric
,
951 struct bfa_fcs_vport_s
*vport
)
953 list_del(&vport
->qe
);
954 fabric
->num_vports
--;
955 bfa_wc_down(&fabric
->wc
);
959 * Base port is deleted.
962 bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s
*fabric
)
964 bfa_wc_down(&fabric
->wc
);
968 * Check if fabric is online.
970 * param[in] fabric - Fabric instance. This can be a base fabric or vf.
975 bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s
*fabric
)
977 return (bfa_sm_cmp_state(fabric
, bfa_fcs_fabric_sm_online
));
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
)
986 bfa_sm_set_state(vf
, bfa_fcs_fabric_sm_uninit
);
987 return BFA_STATUS_OK
;
991 * Lookup for a vport withing a fabric given its pwwn
993 struct bfa_fcs_vport_s
*
994 bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s
*fabric
, wwn_t pwwn
)
996 struct bfa_fcs_vport_s
*vport
;
997 struct list_head
*qe
;
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
)
1009 * In a given fabric, return the number of lports.
1011 * param[in] fabric - Fabric instance. This can be a base fabric or vf.
1013 * @return : 1 or more.
1016 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s
*fabric
)
1018 return (fabric
->num_vports
);
1022 * Unsolicited frame receive handling.
1025 bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s
*fabric
, struct fchs_s
*fchs
,
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
;
1034 bfa_trc(fabric
->fcs
, len
);
1035 bfa_trc(fabric
->fcs
, pid
);
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.
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
);
1050 * FLOGI/EVFP exchanges should be consumed by base fabric.
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
);
1058 if (fabric
->bport
.pid
== pid
) {
1060 * All authentication frames should be routed to auth
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
;
1069 bfa_trc(fabric
->fcs
, *(u8
*) ((u8
*) fchs
));
1070 bfa_fcs_port_uf_recv(&fabric
->bport
, fchs
, len
);
1075 * look for a matching local port ID
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
);
1084 bfa_trc(fabric
->fcs
, els_cmd
->els_code
);
1085 bfa_fcs_port_uf_recv(&fabric
->bport
, fchs
, len
);
1089 * Unsolicited frames to be processed by fabric.
1092 bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s
*fabric
, struct fchs_s
*fchs
,
1095 struct fc_els_cmd_s
*els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
1097 bfa_trc(fabric
->fcs
, els_cmd
->els_code
);
1099 switch (els_cmd
->els_code
) {
1101 bfa_fcs_fabric_process_flogi(fabric
, fchs
, len
);
1106 * need to generate a LS_RJT
1113 * Process incoming FLOGI
1116 bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s
*fabric
,
1117 struct fchs_s
*fchs
, u16 len
)
1119 struct fc_logi_s
*flogi
= (struct fc_logi_s
*) (fchs
+ 1);
1120 struct bfa_fcs_port_s
*bport
= &fabric
->bport
;
1122 bfa_trc(fabric
->fcs
, fchs
->s_id
);
1124 fabric
->stats
.flogi_rcvd
++;
1126 * Check port type. It should be 0 = n-port.
1128 if (flogi
->csp
.port_type
) {
1130 * @todo: may need to send a LS_RJT
1132 bfa_trc(fabric
->fcs
, flogi
->port_name
);
1133 fabric
->stats
.flogi_rejected
++;
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
;
1144 bfa_fcs_fabric_send_flogi_acc(fabric
);
1145 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_NO_FABRIC
);
1149 bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s
*fabric
)
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
;
1158 fcxp
= bfa_fcs_fcxp_alloc(fabric
->fcs
);
1160 * Do not expect this failure -- expect remote node to retry
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
));
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
1180 * Flogi Acc completion callback.
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
)
1187 struct bfa_fcs_fabric_s
*fabric
= cbarg
;
1189 bfa_trc(fabric
->fcs
, status
);
1194 * @param[in] fabric - fabric
1195 * @param[in] result - 1
1200 bfa_fcs_auth_finished(struct bfa_fcs_fabric_s
*fabric
, enum auth_status status
)
1202 bfa_trc(fabric
->fcs
, status
);
1204 if (status
== FC_AUTH_STATE_SUCCESS
)
1205 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_AUTH_SUCCESS
);
1207 bfa_sm_send_event(fabric
, BFA_FCS_FABRIC_SM_AUTH_FAILED
);
1211 * Send AEN notification
1214 bfa_fcs_fabric_aen_post(struct bfa_fcs_port_s
*port
,
1215 enum bfa_port_aen_event event
)
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
];
1224 wwn2str(pwwn_ptr
, pwwn
);
1225 wwn2str(fwwn_ptr
, fwwn
);
1228 case BFA_PORT_AEN_FABRIC_NAME_CHANGE
:
1229 bfa_log(logmod
, BFA_AEN_PORT_FABRIC_NAME_CHANGE
, pwwn_ptr
,
1236 aen_data
.port
.pwwn
= pwwn
;
1237 aen_data
.port
.fwwn
= fwwn
;
1242 * @param[in] fabric - fabric
1243 * @param[in] wwn_t - new fabric name
1248 bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s
*fabric
,
1251 bfa_trc(fabric
->fcs
, fabric_name
);
1253 if (fabric
->fabric_name
== 0) {
1255 * With BRCD switches, we don't get Fabric Name in FLOGI.
1256 * Don't generate a fabric name change event in this case.
1258 fabric
->fabric_name
= fabric_name
;
1260 fabric
->fabric_name
= fabric_name
;
1264 bfa_fcs_fabric_aen_post(&fabric
->bport
,
1265 BFA_PORT_AEN_FABRIC_NAME_CHANGE
);
1274 bfa_cb_lps_flogo_comp(void *bfad
, void *uarg
)