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_fcport_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->bport.port_cfg);
142 case BFA_FCS_FABRIC_SM_LINK_UP:
143 case BFA_FCS_FABRIC_SM_LINK_DOWN:
147 bfa_sm_fault(fabric->fcs, event);
152 * Beginning state before fabric creation.
155 bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
156 enum bfa_fcs_fabric_event event)
158 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
159 bfa_trc(fabric->fcs, event);
162 case BFA_FCS_FABRIC_SM_START:
163 if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
164 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
165 bfa_fcs_fabric_login(fabric);
167 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
170 case BFA_FCS_FABRIC_SM_LINK_UP:
171 case BFA_FCS_FABRIC_SM_LINK_DOWN:
174 case BFA_FCS_FABRIC_SM_DELETE:
175 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
176 bfa_fcs_modexit_comp(fabric->fcs);
180 bfa_sm_fault(fabric->fcs, event);
185 * Link is down, awaiting LINK UP event from port. This is also the
186 * first state at fabric creation.
189 bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
190 enum bfa_fcs_fabric_event event)
192 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
193 bfa_trc(fabric->fcs, event);
196 case BFA_FCS_FABRIC_SM_LINK_UP:
197 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
198 bfa_fcs_fabric_login(fabric);
201 case BFA_FCS_FABRIC_SM_RETRY_OP:
204 case BFA_FCS_FABRIC_SM_DELETE:
205 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
206 bfa_fcs_fabric_delete(fabric);
210 bfa_sm_fault(fabric->fcs, event);
215 * FLOGI is in progress, awaiting FLOGI reply.
218 bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
219 enum bfa_fcs_fabric_event event)
221 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
222 bfa_trc(fabric->fcs, event);
225 case BFA_FCS_FABRIC_SM_CONT_OP:
227 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
228 fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
230 if (fabric->auth_reqd && fabric->is_auth) {
231 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
232 bfa_trc(fabric->fcs, event);
234 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
235 bfa_fcs_fabric_notify_online(fabric);
239 case BFA_FCS_FABRIC_SM_RETRY_OP:
240 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
241 bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
242 bfa_fcs_fabric_delay, fabric,
243 BFA_FCS_FABRIC_RETRY_DELAY);
246 case BFA_FCS_FABRIC_SM_LOOPBACK:
247 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
248 bfa_lps_discard(fabric->lps);
249 bfa_fcs_fabric_set_opertype(fabric);
252 case BFA_FCS_FABRIC_SM_NO_FABRIC:
253 fabric->fab_type = BFA_FCS_FABRIC_N2N;
254 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
255 bfa_fcs_fabric_notify_online(fabric);
256 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
259 case BFA_FCS_FABRIC_SM_LINK_DOWN:
260 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
261 bfa_lps_discard(fabric->lps);
264 case BFA_FCS_FABRIC_SM_DELETE:
265 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
266 bfa_lps_discard(fabric->lps);
267 bfa_fcs_fabric_delete(fabric);
271 bfa_sm_fault(fabric->fcs, event);
277 bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
278 enum bfa_fcs_fabric_event event)
280 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
281 bfa_trc(fabric->fcs, event);
284 case BFA_FCS_FABRIC_SM_DELAYED:
285 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
286 bfa_fcs_fabric_login(fabric);
289 case BFA_FCS_FABRIC_SM_LINK_DOWN:
290 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
291 bfa_timer_stop(&fabric->delay_timer);
294 case BFA_FCS_FABRIC_SM_DELETE:
295 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
296 bfa_timer_stop(&fabric->delay_timer);
297 bfa_fcs_fabric_delete(fabric);
301 bfa_sm_fault(fabric->fcs, event);
306 * Authentication is in progress, awaiting authentication results.
309 bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
310 enum bfa_fcs_fabric_event event)
312 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
313 bfa_trc(fabric->fcs, event);
316 case BFA_FCS_FABRIC_SM_AUTH_FAILED:
317 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
318 bfa_lps_discard(fabric->lps);
321 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
322 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
323 bfa_fcs_fabric_notify_online(fabric);
326 case BFA_FCS_FABRIC_SM_PERF_EVFP:
327 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
330 case BFA_FCS_FABRIC_SM_LINK_DOWN:
331 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
332 bfa_lps_discard(fabric->lps);
335 case BFA_FCS_FABRIC_SM_DELETE:
336 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
337 bfa_fcs_fabric_delete(fabric);
341 bfa_sm_fault(fabric->fcs, event);
346 * Authentication failed
349 bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
350 enum bfa_fcs_fabric_event event)
352 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
353 bfa_trc(fabric->fcs, event);
356 case BFA_FCS_FABRIC_SM_LINK_DOWN:
357 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
358 bfa_fcs_fabric_notify_offline(fabric);
361 case BFA_FCS_FABRIC_SM_DELETE:
362 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
363 bfa_fcs_fabric_delete(fabric);
367 bfa_sm_fault(fabric->fcs, event);
372 * Port is in loopback mode.
375 bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
376 enum bfa_fcs_fabric_event event)
378 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
379 bfa_trc(fabric->fcs, event);
382 case BFA_FCS_FABRIC_SM_LINK_DOWN:
383 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
384 bfa_fcs_fabric_notify_offline(fabric);
387 case BFA_FCS_FABRIC_SM_DELETE:
388 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
389 bfa_fcs_fabric_delete(fabric);
393 bfa_sm_fault(fabric->fcs, event);
398 * There is no attached fabric - private loop or NPort-to-NPort topology.
401 bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
402 enum bfa_fcs_fabric_event event)
404 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
405 bfa_trc(fabric->fcs, event);
408 case BFA_FCS_FABRIC_SM_LINK_DOWN:
409 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
410 bfa_lps_discard(fabric->lps);
411 bfa_fcs_fabric_notify_offline(fabric);
414 case BFA_FCS_FABRIC_SM_DELETE:
415 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
416 bfa_fcs_fabric_delete(fabric);
419 case BFA_FCS_FABRIC_SM_NO_FABRIC:
420 bfa_trc(fabric->fcs, fabric->bb_credit);
421 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
425 bfa_sm_fault(fabric->fcs, event);
430 * Fabric is online - normal operating state.
433 bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
434 enum bfa_fcs_fabric_event event)
436 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
437 bfa_trc(fabric->fcs, event);
440 case BFA_FCS_FABRIC_SM_LINK_DOWN:
441 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
442 bfa_lps_discard(fabric->lps);
443 bfa_fcs_fabric_notify_offline(fabric);
446 case BFA_FCS_FABRIC_SM_DELETE:
447 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
448 bfa_fcs_fabric_delete(fabric);
451 case BFA_FCS_FABRIC_SM_AUTH_FAILED:
452 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
453 bfa_lps_discard(fabric->lps);
456 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
460 bfa_sm_fault(fabric->fcs, event);
465 * Exchanging virtual fabric parameters.
468 bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
469 enum bfa_fcs_fabric_event event)
471 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
472 bfa_trc(fabric->fcs, event);
475 case BFA_FCS_FABRIC_SM_CONT_OP:
476 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
479 case BFA_FCS_FABRIC_SM_ISOLATE:
480 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
484 bfa_sm_fault(fabric->fcs, event);
489 * EVFP exchange complete and VFT tagging is enabled.
492 bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
493 enum bfa_fcs_fabric_event event)
495 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
496 bfa_trc(fabric->fcs, event);
500 * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
503 bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
504 enum bfa_fcs_fabric_event event)
506 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
507 bfa_trc(fabric->fcs, event);
509 bfa_log(fabric->fcs->logm, BFA_LOG_FCS_FABRIC_ISOLATED,
510 fabric->bport.port_cfg.pwwn, fabric->fcs->port_vfid,
511 fabric->event_arg.swp_vfid);
515 * Fabric is being deleted, awaiting vport delete completions.
518 bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
519 enum bfa_fcs_fabric_event event)
521 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
522 bfa_trc(fabric->fcs, event);
525 case BFA_FCS_FABRIC_SM_DELCOMP:
526 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
527 bfa_fcs_modexit_comp(fabric->fcs);
530 case BFA_FCS_FABRIC_SM_LINK_UP:
533 case BFA_FCS_FABRIC_SM_LINK_DOWN:
534 bfa_fcs_fabric_notify_offline(fabric);
538 bfa_sm_fault(fabric->fcs, event);
545 * fcs_fabric_private fabric private functions
549 bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
551 struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
553 port_cfg->roles = BFA_PORT_ROLE_FCP_IM;
554 port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
555 port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
559 * Port Symbolic Name Creation for base port.
562 bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
564 struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
565 char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
566 struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
568 bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
573 strncpy((char *)&port_cfg->sym_name, model,
574 BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
575 strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
576 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
581 strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
582 BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
583 strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
584 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
589 strncat((char *)&port_cfg->sym_name,
590 (char *)driver_info->host_machine_name,
591 BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
592 strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
593 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
597 * If OS Patch Info is not there, do not truncate any bytes from the
598 * OS name string and instead copy the entire OS info string (64 bytes).
600 if (driver_info->host_os_patch[0] == '\0') {
601 strncat((char *)&port_cfg->sym_name,
602 (char *)driver_info->host_os_name, BFA_FCS_OS_STR_LEN);
603 strncat((char *)&port_cfg->sym_name,
604 BFA_FCS_PORT_SYMBNAME_SEPARATOR,
605 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
607 strncat((char *)&port_cfg->sym_name,
608 (char *)driver_info->host_os_name,
609 BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
610 strncat((char *)&port_cfg->sym_name,
611 BFA_FCS_PORT_SYMBNAME_SEPARATOR,
612 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
615 * Append host OS Patch Info
617 strncat((char *)&port_cfg->sym_name,
618 (char *)driver_info->host_os_patch,
619 BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
625 port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
629 * bfa lps login completion callback
632 bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
634 struct bfa_fcs_fabric_s *fabric = uarg;
636 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
637 bfa_trc(fabric->fcs, status);
641 fabric->stats.flogi_accepts++;
644 case BFA_STATUS_INVALID_MAC:
648 fabric->stats.flogi_acc_err++;
649 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
653 case BFA_STATUS_EPROTOCOL:
654 switch (bfa_lps_get_extstatus(fabric->lps)) {
655 case BFA_EPROTO_BAD_ACCEPT:
656 fabric->stats.flogi_acc_err++;
659 case BFA_EPROTO_UNKNOWN_RSP:
660 fabric->stats.flogi_unknown_rsp++;
666 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
670 case BFA_STATUS_FABRIC_RJT:
671 fabric->stats.flogi_rejects++;
672 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
676 fabric->stats.flogi_rsp_err++;
677 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
681 fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
682 bfa_trc(fabric->fcs, fabric->bb_credit);
684 if (!bfa_lps_is_brcd_fabric(fabric->lps))
685 fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps);
688 * Check port type. It should be 1 = F-port.
690 if (bfa_lps_is_fport(fabric->lps)) {
691 fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
692 fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
693 fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
694 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
697 * Nport-2-Nport direct attached
699 fabric->bport.port_topo.pn2n.rem_port_wwn =
700 bfa_lps_get_peer_pwwn(fabric->lps);
701 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
704 bfa_trc(fabric->fcs, fabric->bport.pid);
705 bfa_trc(fabric->fcs, fabric->is_npiv);
706 bfa_trc(fabric->fcs, fabric->is_auth);
710 * Allocate and send FLOGI.
713 bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
715 struct bfa_s *bfa = fabric->fcs->bfa;
716 struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
719 if (bfa_fcport_get_topology(bfa) == BFA_PPORT_TOPOLOGY_LOOP)
720 alpa = bfa_fcport_get_myalpa(bfa);
722 bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
723 pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
725 fabric->stats.flogi_sent++;
729 bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
731 struct bfa_fcs_vport_s *vport;
732 struct list_head *qe, *qen;
734 bfa_trc(fabric->fcs, fabric->fabric_name);
736 bfa_fcs_fabric_set_opertype(fabric);
737 fabric->stats.fabric_onlines++;
740 * notify online event to base and then virtual ports
742 bfa_fcs_port_online(&fabric->bport);
744 list_for_each_safe(qe, qen, &fabric->vport_q) {
745 vport = (struct bfa_fcs_vport_s *)qe;
746 bfa_fcs_vport_online(vport);
751 bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
753 struct bfa_fcs_vport_s *vport;
754 struct list_head *qe, *qen;
756 bfa_trc(fabric->fcs, fabric->fabric_name);
757 fabric->stats.fabric_offlines++;
760 * notify offline event first to vports and then base port.
762 list_for_each_safe(qe, qen, &fabric->vport_q) {
763 vport = (struct bfa_fcs_vport_s *)qe;
764 bfa_fcs_vport_offline(vport);
767 bfa_fcs_port_offline(&fabric->bport);
769 fabric->fabric_name = 0;
770 fabric->fabric_ip_addr[0] = 0;
774 bfa_fcs_fabric_delay(void *cbarg)
776 struct bfa_fcs_fabric_s *fabric = cbarg;
778 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
782 * Delete all vports and wait for vport delete completions.
785 bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
787 struct bfa_fcs_vport_s *vport;
788 struct list_head *qe, *qen;
790 list_for_each_safe(qe, qen, &fabric->vport_q) {
791 vport = (struct bfa_fcs_vport_s *)qe;
792 bfa_fcs_vport_delete(vport);
795 bfa_fcs_port_delete(&fabric->bport);
796 bfa_wc_wait(&fabric->wc);
800 bfa_fcs_fabric_delete_comp(void *cbarg)
802 struct bfa_fcs_fabric_s *fabric = cbarg;
804 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
810 * fcs_fabric_public fabric public functions
814 * Attach time initialization
817 bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
819 struct bfa_fcs_fabric_s *fabric;
821 fabric = &fcs->fabric;
822 bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
825 * Initialize base fabric.
828 INIT_LIST_HEAD(&fabric->vport_q);
829 INIT_LIST_HEAD(&fabric->vf_q);
830 fabric->lps = bfa_lps_alloc(fcs->bfa);
831 bfa_assert(fabric->lps);
834 * Initialize fabric delete completion handler. Fabric deletion is complete
835 * when the last vport delete is complete.
837 bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
838 bfa_wc_up(&fabric->wc); /* For the base port */
840 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
841 bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
845 bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
847 bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
855 bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
857 struct bfa_fcs_fabric_s *fabric;
862 * Cleanup base fabric.
864 fabric = &fcs->fabric;
865 bfa_lps_delete(fabric->lps);
866 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
870 * Fabric module start -- kick starts FCS actions
873 bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
875 struct bfa_fcs_fabric_s *fabric;
878 fabric = &fcs->fabric;
879 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
883 * Suspend fabric activity as part of driver suspend.
886 bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
891 bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
893 return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
897 bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric)
899 return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed);
903 bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
905 return fabric->oper_type;
909 * Link up notification from BFA physical port module.
912 bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
914 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
915 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
919 * Link down notification from BFA physical port module.
922 bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
924 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
925 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
929 * A child vport is being created in the fabric.
931 * Call from vport module at vport creation. A list of base port and vports
932 * belonging to a fabric is maintained to propagate link events.
934 * param[in] fabric - Fabric instance. This can be a base fabric or vf.
935 * param[in] vport - Vport being created.
937 * @return None (always succeeds)
940 bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
941 struct bfa_fcs_vport_s *vport)
944 * - add vport to fabric's vport_q
946 bfa_trc(fabric->fcs, fabric->vf_id);
948 list_add_tail(&vport->qe, &fabric->vport_q);
949 fabric->num_vports++;
950 bfa_wc_up(&fabric->wc);
954 * A child vport is being deleted from fabric.
956 * Vport is being deleted.
959 bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
960 struct bfa_fcs_vport_s *vport)
962 list_del(&vport->qe);
963 fabric->num_vports--;
964 bfa_wc_down(&fabric->wc);
968 * Base port is deleted.
971 bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
973 bfa_wc_down(&fabric->wc);
977 * Check if fabric is online.
979 * param[in] fabric - Fabric instance. This can be a base fabric or vf.
984 bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
986 return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
991 bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
992 struct bfa_port_cfg_s *port_cfg,
993 struct bfad_vf_s *vf_drv)
995 bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
996 return BFA_STATUS_OK;
1000 * Lookup for a vport withing a fabric given its pwwn
1002 struct bfa_fcs_vport_s *
1003 bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
1005 struct bfa_fcs_vport_s *vport;
1006 struct list_head *qe;
1008 list_for_each(qe, &fabric->vport_q) {
1009 vport = (struct bfa_fcs_vport_s *)qe;
1010 if (bfa_fcs_port_get_pwwn(&vport->lport) == pwwn)
1018 * In a given fabric, return the number of lports.
1020 * param[in] fabric - Fabric instance. This can be a base fabric or vf.
1022 * @return : 1 or more.
1025 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
1027 return fabric->num_vports;
1031 * Unsolicited frame receive handling.
1034 bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
1037 u32 pid = fchs->d_id;
1038 struct bfa_fcs_vport_s *vport;
1039 struct list_head *qe;
1040 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1041 struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;
1043 bfa_trc(fabric->fcs, len);
1044 bfa_trc(fabric->fcs, pid);
1047 * Look for our own FLOGI frames being looped back. This means an
1048 * external loopback cable is in place. Our own FLOGI frames are
1049 * sometimes looped back when switch port gets temporarily bypassed.
1051 if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT))
1052 && (els_cmd->els_code == FC_ELS_FLOGI)
1053 && (flogi->port_name == bfa_fcs_port_get_pwwn(&fabric->bport))) {
1054 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
1059 * FLOGI/EVFP exchanges should be consumed by base fabric.
1061 if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
1062 bfa_trc(fabric->fcs, pid);
1063 bfa_fcs_fabric_process_uf(fabric, fchs, len);
1067 if (fabric->bport.pid == pid) {
1069 * All authentication frames should be routed to auth
1071 bfa_trc(fabric->fcs, els_cmd->els_code);
1072 if (els_cmd->els_code == FC_ELS_AUTH) {
1073 bfa_trc(fabric->fcs, els_cmd->els_code);
1074 fabric->auth.response = (u8 *) els_cmd;
1078 bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
1079 bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
1084 * look for a matching local port ID
1086 list_for_each(qe, &fabric->vport_q) {
1087 vport = (struct bfa_fcs_vport_s *)qe;
1088 if (vport->lport.pid == pid) {
1089 bfa_fcs_port_uf_recv(&vport->lport, fchs, len);
1093 bfa_trc(fabric->fcs, els_cmd->els_code);
1094 bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
1098 * Unsolicited frames to be processed by fabric.
1101 bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
1104 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1106 bfa_trc(fabric->fcs, els_cmd->els_code);
1108 switch (els_cmd->els_code) {
1110 bfa_fcs_fabric_process_flogi(fabric, fchs, len);
1115 * need to generate a LS_RJT
1122 * Process incoming FLOGI
1125 bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
1126 struct fchs_s *fchs, u16 len)
1128 struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);
1129 struct bfa_fcs_port_s *bport = &fabric->bport;
1131 bfa_trc(fabric->fcs, fchs->s_id);
1133 fabric->stats.flogi_rcvd++;
1135 * Check port type. It should be 0 = n-port.
1137 if (flogi->csp.port_type) {
1139 * @todo: may need to send a LS_RJT
1141 bfa_trc(fabric->fcs, flogi->port_name);
1142 fabric->stats.flogi_rejected++;
1146 fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred);
1147 bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
1148 bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
1153 bfa_fcs_fabric_send_flogi_acc(fabric);
1154 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
1158 bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
1160 struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
1161 struct bfa_fcs_port_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
1162 struct bfa_s *bfa = fabric->fcs->bfa;
1163 struct bfa_fcxp_s *fcxp;
1167 fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
1169 * Do not expect this failure -- expect remote node to retry
1174 reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1175 bfa_os_hton3b(FC_FABRIC_PORT),
1176 n2n_port->reply_oxid, pcfg->pwwn,
1177 pcfg->nwwn, bfa_fcport_get_maxfrsize(bfa),
1178 bfa_fcport_get_rx_bbcredit(bfa));
1180 bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
1181 BFA_FALSE, FC_CLASS_3, reqlen, &fchs,
1182 bfa_fcs_fabric_flogiacc_comp, fabric,
1183 FC_MAX_PDUSZ, 0); /* Timeout 0 indicates no
1189 * Flogi Acc completion callback.
1192 bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1193 bfa_status_t status, u32 rsp_len,
1194 u32 resid_len, struct fchs_s *rspfchs)
1196 struct bfa_fcs_fabric_s *fabric = cbarg;
1198 bfa_trc(fabric->fcs, status);
1203 * @param[in] fabric - fabric
1204 * @param[in] result - 1
1209 bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, enum auth_status status)
1211 bfa_trc(fabric->fcs, status);
1213 if (status == FC_AUTH_STATE_SUCCESS)
1214 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_SUCCESS);
1216 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_FAILED);
1220 * Send AEN notification
1223 bfa_fcs_fabric_aen_post(struct bfa_fcs_port_s *port,
1224 enum bfa_port_aen_event event)
1226 union bfa_aen_data_u aen_data;
1227 struct bfa_log_mod_s *logmod = port->fcs->logm;
1228 wwn_t pwwn = bfa_fcs_port_get_pwwn(port);
1229 wwn_t fwwn = bfa_fcs_port_get_fabric_name(port);
1230 char pwwn_ptr[BFA_STRING_32];
1231 char fwwn_ptr[BFA_STRING_32];
1233 wwn2str(pwwn_ptr, pwwn);
1234 wwn2str(fwwn_ptr, fwwn);
1236 bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, event),
1237 pwwn_ptr, fwwn_ptr);
1239 aen_data.port.pwwn = pwwn;
1240 aen_data.port.fwwn = fwwn;
1245 * @param[in] fabric - fabric
1246 * @param[in] wwn_t - new fabric name
1251 bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
1254 bfa_trc(fabric->fcs, fabric_name);
1256 if (fabric->fabric_name == 0) {
1258 * With BRCD switches, we don't get Fabric Name in FLOGI.
1259 * Don't generate a fabric name change event in this case.
1261 fabric->fabric_name = fabric_name;
1263 fabric->fabric_name = fabric_name;
1267 bfa_fcs_fabric_aen_post(&fabric->bport,
1268 BFA_PORT_AEN_FABRIC_NAME_CHANGE);
1277 bfa_cb_lps_flogo_comp(void *bfad, void *uarg)