1617 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.4 * Copyright (c) 2014- QLogic Corporation.5 * All rights reserved6 * www.qlogic.com7 *8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.9 */10 11/*12 * bfa_fcs.c BFA FCS main13 */14 15#include "bfad_drv.h"16#include "bfad_im.h"17#include "bfa_fcs.h"18#include "bfa_fcbuild.h"19 20BFA_TRC_FILE(FCS, FCS);21 22/*23 * fcs_api BFA FCS API24 */25 26static void27bfa_fcs_exit_comp(void *fcs_cbarg)28{29 struct bfa_fcs_s *fcs = fcs_cbarg;30 struct bfad_s *bfad = fcs->bfad;31 32 complete(&bfad->comp);33}34 35/*36 * fcs initialization, called once after bfa initialization is complete37 */38void39bfa_fcs_init(struct bfa_fcs_s *fcs)40{41 bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);42 bfa_trc(fcs, 0);43}44 45/*46 * fcs_api BFA FCS API47 */48 49/*50 * FCS update cfg - reset the pwwn/nwwn of fabric base logical port51 * with values learned during bfa_init firmware GETATTR REQ.52 */53void54bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)55{56 struct bfa_fcs_fabric_s *fabric = &fcs->fabric;57 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;58 struct bfa_ioc_s *ioc = &fabric->fcs->bfa->ioc;59 60 port_cfg->nwwn = ioc->attr->nwwn;61 port_cfg->pwwn = ioc->attr->pwwn;62}63 64/*65 * Stop FCS operations.66 */67void68bfa_fcs_stop(struct bfa_fcs_s *fcs)69{70 bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);71 bfa_wc_up(&fcs->wc);72 bfa_fcs_fabric_modstop(fcs);73 bfa_wc_wait(&fcs->wc);74}75 76/*77 * fcs pbc vport initialization78 */79void80bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs)81{82 int i, npbc_vports;83 struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];84 85 /* Initialize pbc vports */86 if (!fcs->min_cfg) {87 npbc_vports =88 bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);89 for (i = 0; i < npbc_vports; i++)90 bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);91 }92}93 94/*95 * brief96 * FCS driver details initialization.97 *98 * param[in] fcs FCS instance99 * param[in] driver_info Driver Details100 *101 * return None102 */103void104bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,105 struct bfa_fcs_driver_info_s *driver_info)106{107 108 fcs->driver_info = *driver_info;109 110 bfa_fcs_fabric_psymb_init(&fcs->fabric);111 bfa_fcs_fabric_nsymb_init(&fcs->fabric);112}113 114/*115 * brief116 * FCS instance cleanup and exit.117 *118 * param[in] fcs FCS instance119 * return None120 */121void122bfa_fcs_exit(struct bfa_fcs_s *fcs)123{124 bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);125 bfa_wc_up(&fcs->wc);126 bfa_trc(fcs, 0);127 bfa_lps_delete(fcs->fabric.lps);128 bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_DELETE);129 bfa_wc_wait(&fcs->wc);130}131 132/*133 * Fabric module implementation.134 */135 136#define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */137#define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */138 139#define bfa_fcs_fabric_set_opertype(__fabric) do { \140 if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \141 == BFA_PORT_TOPOLOGY_P2P) { \142 if (fabric->fab_type == BFA_FCS_FABRIC_SWITCHED) \143 (__fabric)->oper_type = BFA_PORT_TYPE_NPORT; \144 else \145 (__fabric)->oper_type = BFA_PORT_TYPE_P2P; \146 } else \147 (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT; \148} while (0)149 150/*151 * forward declarations152 */153static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);154static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);155static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);156static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);157static void bfa_fcs_fabric_delay(void *cbarg);158static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);159static void bfa_fcs_fabric_delete_comp(void *cbarg);160static void bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric);161static void bfa_fcs_fabric_stop_comp(void *cbarg);162static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,163 struct fchs_s *fchs, u16 len);164static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,165 struct fchs_s *fchs, u16 len);166static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);167static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,168 struct bfa_fcxp_s *fcxp, void *cbarg,169 bfa_status_t status,170 u32 rsp_len,171 u32 resid_len,172 struct fchs_s *rspfchs);173 174static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,175 enum bfa_fcs_fabric_event event);176static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,177 enum bfa_fcs_fabric_event event);178static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,179 enum bfa_fcs_fabric_event event);180static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,181 enum bfa_fcs_fabric_event event);182static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,183 enum bfa_fcs_fabric_event event);184static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,185 enum bfa_fcs_fabric_event event);186static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,187 enum bfa_fcs_fabric_event event);188static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,189 enum bfa_fcs_fabric_event event);190static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,191 enum bfa_fcs_fabric_event event);192static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,193 enum bfa_fcs_fabric_event event);194static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,195 enum bfa_fcs_fabric_event event);196static void bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,197 enum bfa_fcs_fabric_event event);198static void bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,199 enum bfa_fcs_fabric_event event);200/*201 * Beginning state before fabric creation.202 */203static void204bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,205 enum bfa_fcs_fabric_event event)206{207 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);208 bfa_trc(fabric->fcs, event);209 210 switch (event) {211 case BFA_FCS_FABRIC_SM_CREATE:212 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);213 bfa_fcs_fabric_init(fabric);214 bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);215 break;216 217 case BFA_FCS_FABRIC_SM_LINK_UP:218 case BFA_FCS_FABRIC_SM_LINK_DOWN:219 break;220 221 default:222 bfa_sm_fault(fabric->fcs, event);223 }224}225 226/*227 * Beginning state before fabric creation.228 */229static void230bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,231 enum bfa_fcs_fabric_event event)232{233 struct bfa_s *bfa = fabric->fcs->bfa;234 235 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);236 bfa_trc(fabric->fcs, event);237 238 switch (event) {239 case BFA_FCS_FABRIC_SM_START:240 if (!bfa_fcport_is_linkup(fabric->fcs->bfa)) {241 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);242 break;243 }244 if (bfa_fcport_get_topology(bfa) ==245 BFA_PORT_TOPOLOGY_LOOP) {246 fabric->fab_type = BFA_FCS_FABRIC_LOOP;247 fabric->bport.pid = bfa_fcport_get_myalpa(bfa);248 fabric->bport.pid = bfa_hton3b(fabric->bport.pid);249 bfa_sm_set_state(fabric,250 bfa_fcs_fabric_sm_online);251 bfa_fcs_fabric_set_opertype(fabric);252 bfa_fcs_lport_online(&fabric->bport);253 } else {254 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);255 bfa_fcs_fabric_login(fabric);256 }257 break;258 259 case BFA_FCS_FABRIC_SM_LINK_UP:260 case BFA_FCS_FABRIC_SM_LINK_DOWN:261 break;262 263 case BFA_FCS_FABRIC_SM_DELETE:264 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);265 bfa_fcs_fabric_delete(fabric);266 break;267 268 default:269 bfa_sm_fault(fabric->fcs, event);270 }271}272 273/*274 * Link is down, awaiting LINK UP event from port. This is also the275 * first state at fabric creation.276 */277static void278bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,279 enum bfa_fcs_fabric_event event)280{281 struct bfa_s *bfa = fabric->fcs->bfa;282 283 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);284 bfa_trc(fabric->fcs, event);285 286 switch (event) {287 case BFA_FCS_FABRIC_SM_LINK_UP:288 if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP) {289 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);290 bfa_fcs_fabric_login(fabric);291 break;292 }293 fabric->fab_type = BFA_FCS_FABRIC_LOOP;294 fabric->bport.pid = bfa_fcport_get_myalpa(bfa);295 fabric->bport.pid = bfa_hton3b(fabric->bport.pid);296 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);297 bfa_fcs_fabric_set_opertype(fabric);298 bfa_fcs_lport_online(&fabric->bport);299 break;300 301 case BFA_FCS_FABRIC_SM_RETRY_OP:302 case BFA_FCS_FABRIC_SM_LOOPBACK:303 break;304 305 case BFA_FCS_FABRIC_SM_DELETE:306 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);307 bfa_fcs_fabric_delete(fabric);308 break;309 310 case BFA_FCS_FABRIC_SM_STOP:311 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);312 bfa_fcs_fabric_stop(fabric);313 break;314 315 default:316 bfa_sm_fault(fabric->fcs, event);317 }318}319 320/*321 * FLOGI is in progress, awaiting FLOGI reply.322 */323static void324bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,325 enum bfa_fcs_fabric_event event)326{327 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);328 bfa_trc(fabric->fcs, event);329 330 switch (event) {331 case BFA_FCS_FABRIC_SM_CONT_OP:332 333 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,334 fabric->bb_credit);335 fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;336 337 if (fabric->auth_reqd && fabric->is_auth) {338 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);339 bfa_trc(fabric->fcs, event);340 } else {341 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);342 bfa_fcs_fabric_notify_online(fabric);343 }344 break;345 346 case BFA_FCS_FABRIC_SM_RETRY_OP:347 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);348 bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,349 bfa_fcs_fabric_delay, fabric,350 BFA_FCS_FABRIC_RETRY_DELAY);351 break;352 353 case BFA_FCS_FABRIC_SM_LOOPBACK:354 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);355 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);356 bfa_fcs_fabric_set_opertype(fabric);357 break;358 359 case BFA_FCS_FABRIC_SM_NO_FABRIC:360 fabric->fab_type = BFA_FCS_FABRIC_N2N;361 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,362 fabric->bb_credit);363 bfa_fcs_fabric_notify_online(fabric);364 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);365 break;366 367 case BFA_FCS_FABRIC_SM_LINK_DOWN:368 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);369 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);370 break;371 372 case BFA_FCS_FABRIC_SM_DELETE:373 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);374 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);375 bfa_fcs_fabric_delete(fabric);376 break;377 378 default:379 bfa_sm_fault(fabric->fcs, event);380 }381}382 383 384static void385bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,386 enum bfa_fcs_fabric_event event)387{388 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);389 bfa_trc(fabric->fcs, event);390 391 switch (event) {392 case BFA_FCS_FABRIC_SM_DELAYED:393 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);394 bfa_fcs_fabric_login(fabric);395 break;396 397 case BFA_FCS_FABRIC_SM_LINK_DOWN:398 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);399 bfa_timer_stop(&fabric->delay_timer);400 break;401 402 case BFA_FCS_FABRIC_SM_DELETE:403 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);404 bfa_timer_stop(&fabric->delay_timer);405 bfa_fcs_fabric_delete(fabric);406 break;407 408 default:409 bfa_sm_fault(fabric->fcs, event);410 }411}412 413/*414 * Authentication is in progress, awaiting authentication results.415 */416static void417bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,418 enum bfa_fcs_fabric_event event)419{420 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);421 bfa_trc(fabric->fcs, event);422 423 switch (event) {424 case BFA_FCS_FABRIC_SM_AUTH_FAILED:425 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);426 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);427 break;428 429 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:430 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);431 bfa_fcs_fabric_notify_online(fabric);432 break;433 434 case BFA_FCS_FABRIC_SM_PERF_EVFP:435 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);436 break;437 438 case BFA_FCS_FABRIC_SM_LINK_DOWN:439 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);440 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);441 break;442 443 case BFA_FCS_FABRIC_SM_DELETE:444 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);445 bfa_fcs_fabric_delete(fabric);446 break;447 448 default:449 bfa_sm_fault(fabric->fcs, event);450 }451}452 453/*454 * Authentication failed455 */456void457bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,458 enum bfa_fcs_fabric_event event)459{460 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);461 bfa_trc(fabric->fcs, event);462 463 switch (event) {464 case BFA_FCS_FABRIC_SM_LINK_DOWN:465 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);466 bfa_fcs_fabric_notify_offline(fabric);467 break;468 469 case BFA_FCS_FABRIC_SM_DELETE:470 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);471 bfa_fcs_fabric_delete(fabric);472 break;473 474 default:475 bfa_sm_fault(fabric->fcs, event);476 }477}478 479/*480 * Port is in loopback mode.481 */482void483bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,484 enum bfa_fcs_fabric_event event)485{486 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);487 bfa_trc(fabric->fcs, event);488 489 switch (event) {490 case BFA_FCS_FABRIC_SM_LINK_DOWN:491 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);492 bfa_fcs_fabric_notify_offline(fabric);493 break;494 495 case BFA_FCS_FABRIC_SM_DELETE:496 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);497 bfa_fcs_fabric_delete(fabric);498 break;499 500 default:501 bfa_sm_fault(fabric->fcs, event);502 }503}504 505/*506 * There is no attached fabric - private loop or NPort-to-NPort topology.507 */508static void509bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,510 enum bfa_fcs_fabric_event event)511{512 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);513 bfa_trc(fabric->fcs, event);514 515 switch (event) {516 case BFA_FCS_FABRIC_SM_LINK_DOWN:517 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);518 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);519 bfa_fcs_fabric_notify_offline(fabric);520 break;521 522 case BFA_FCS_FABRIC_SM_DELETE:523 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);524 bfa_fcs_fabric_delete(fabric);525 break;526 527 case BFA_FCS_FABRIC_SM_NO_FABRIC:528 bfa_trc(fabric->fcs, fabric->bb_credit);529 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,530 fabric->bb_credit);531 break;532 533 case BFA_FCS_FABRIC_SM_RETRY_OP:534 break;535 536 default:537 bfa_sm_fault(fabric->fcs, event);538 }539}540 541/*542 * Fabric is online - normal operating state.543 */544void545bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,546 enum bfa_fcs_fabric_event event)547{548 struct bfa_s *bfa = fabric->fcs->bfa;549 550 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);551 bfa_trc(fabric->fcs, event);552 553 switch (event) {554 case BFA_FCS_FABRIC_SM_LINK_DOWN:555 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);556 if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {557 bfa_fcs_lport_offline(&fabric->bport);558 } else {559 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);560 bfa_fcs_fabric_notify_offline(fabric);561 }562 break;563 564 case BFA_FCS_FABRIC_SM_DELETE:565 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);566 bfa_fcs_fabric_delete(fabric);567 break;568 569 case BFA_FCS_FABRIC_SM_STOP:570 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_stopping);571 bfa_fcs_fabric_stop(fabric);572 break;573 574 case BFA_FCS_FABRIC_SM_AUTH_FAILED:575 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);576 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);577 break;578 579 case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:580 break;581 582 default:583 bfa_sm_fault(fabric->fcs, event);584 }585}586 587/*588 * Exchanging virtual fabric parameters.589 */590static void591bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,592 enum bfa_fcs_fabric_event event)593{594 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);595 bfa_trc(fabric->fcs, event);596 597 switch (event) {598 case BFA_FCS_FABRIC_SM_CONT_OP:599 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);600 break;601 602 case BFA_FCS_FABRIC_SM_ISOLATE:603 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);604 break;605 606 default:607 bfa_sm_fault(fabric->fcs, event);608 }609}610 611/*612 * EVFP exchange complete and VFT tagging is enabled.613 */614static void615bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,616 enum bfa_fcs_fabric_event event)617{618 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);619 bfa_trc(fabric->fcs, event);620}621 622/*623 * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).624 */625static void626bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,627 enum bfa_fcs_fabric_event event)628{629 struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;630 char pwwn_ptr[BFA_STRING_32];631 632 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);633 bfa_trc(fabric->fcs, event);634 wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn);635 636 BFA_LOG(KERN_INFO, bfad, bfa_log_level,637 "Port is isolated due to VF_ID mismatch. "638 "PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",639 pwwn_ptr, fabric->fcs->port_vfid,640 fabric->event_arg.swp_vfid);641}642 643/*644 * Fabric is being deleted, awaiting vport delete completions.645 */646static void647bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,648 enum bfa_fcs_fabric_event event)649{650 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);651 bfa_trc(fabric->fcs, event);652 653 switch (event) {654 case BFA_FCS_FABRIC_SM_DELCOMP:655 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);656 bfa_wc_down(&fabric->fcs->wc);657 break;658 659 case BFA_FCS_FABRIC_SM_LINK_UP:660 break;661 662 case BFA_FCS_FABRIC_SM_LINK_DOWN:663 bfa_fcs_fabric_notify_offline(fabric);664 break;665 666 default:667 bfa_sm_fault(fabric->fcs, event);668 }669}670 671/*672 * Fabric is being stopped, awaiting vport stop completions.673 */674static void675bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,676 enum bfa_fcs_fabric_event event)677{678 struct bfa_s *bfa = fabric->fcs->bfa;679 680 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);681 bfa_trc(fabric->fcs, event);682 683 switch (event) {684 case BFA_FCS_FABRIC_SM_STOPCOMP:685 if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {686 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);687 } else {688 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);689 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);690 }691 break;692 693 case BFA_FCS_FABRIC_SM_LINK_UP:694 break;695 696 case BFA_FCS_FABRIC_SM_LINK_DOWN:697 if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)698 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);699 else700 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);701 break;702 703 default:704 bfa_sm_fault(fabric->fcs, event);705 }706}707 708/*709 * Fabric is being stopped, cleanup without FLOGO710 */711static void712bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,713 enum bfa_fcs_fabric_event event)714{715 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);716 bfa_trc(fabric->fcs, event);717 718 switch (event) {719 case BFA_FCS_FABRIC_SM_STOPCOMP:720 case BFA_FCS_FABRIC_SM_LOGOCOMP:721 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);722 bfa_wc_down(&(fabric->fcs)->wc);723 break;724 725 case BFA_FCS_FABRIC_SM_LINK_DOWN:726 /*727 * Ignore - can get this event if we get notified about IOC down728 * before the fabric completion callbk is done.729 */730 break;731 732 default:733 bfa_sm_fault(fabric->fcs, event);734 }735}736 737/*738 * fcs_fabric_private fabric private functions739 */740 741static void742bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)743{744 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;745 746 port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;747 port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn;748 port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn;749}750 751/*752 * Port Symbolic Name Creation for base port.753 */754void755bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)756{757 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;758 char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};759 struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;760 761 bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);762 763 /* Model name/number */764 strscpy(port_cfg->sym_name.symname, model,765 BFA_SYMNAME_MAXLEN);766 strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,767 BFA_SYMNAME_MAXLEN);768 769 /* Driver Version */770 strlcat(port_cfg->sym_name.symname, driver_info->version,771 BFA_SYMNAME_MAXLEN);772 strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,773 BFA_SYMNAME_MAXLEN);774 775 /* Host machine name */776 strlcat(port_cfg->sym_name.symname,777 driver_info->host_machine_name,778 BFA_SYMNAME_MAXLEN);779 strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,780 BFA_SYMNAME_MAXLEN);781 782 /*783 * Host OS Info :784 * If OS Patch Info is not there, do not truncate any bytes from the785 * OS name string and instead copy the entire OS info string (64 bytes).786 */787 if (driver_info->host_os_patch[0] == '\0') {788 strlcat(port_cfg->sym_name.symname,789 driver_info->host_os_name,790 BFA_SYMNAME_MAXLEN);791 strlcat(port_cfg->sym_name.symname,792 BFA_FCS_PORT_SYMBNAME_SEPARATOR,793 BFA_SYMNAME_MAXLEN);794 } else {795 strlcat(port_cfg->sym_name.symname,796 driver_info->host_os_name,797 BFA_SYMNAME_MAXLEN);798 strlcat(port_cfg->sym_name.symname,799 BFA_FCS_PORT_SYMBNAME_SEPARATOR,800 BFA_SYMNAME_MAXLEN);801 802 /* Append host OS Patch Info */803 strlcat(port_cfg->sym_name.symname,804 driver_info->host_os_patch,805 BFA_SYMNAME_MAXLEN);806 }807 808 /* null terminate */809 port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;810}811 812/*813 * Node Symbolic Name Creation for base port and all vports814 */815void816bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric)817{818 struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;819 char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};820 struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;821 822 bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);823 824 /* Model name/number */825 strscpy(port_cfg->node_sym_name.symname, model,826 BFA_SYMNAME_MAXLEN);827 strlcat(port_cfg->node_sym_name.symname,828 BFA_FCS_PORT_SYMBNAME_SEPARATOR,829 BFA_SYMNAME_MAXLEN);830 831 /* Driver Version */832 strlcat(port_cfg->node_sym_name.symname, (char *)driver_info->version,833 BFA_SYMNAME_MAXLEN);834 strlcat(port_cfg->node_sym_name.symname,835 BFA_FCS_PORT_SYMBNAME_SEPARATOR,836 BFA_SYMNAME_MAXLEN);837 838 /* Host machine name */839 strlcat(port_cfg->node_sym_name.symname,840 driver_info->host_machine_name,841 BFA_SYMNAME_MAXLEN);842 strlcat(port_cfg->node_sym_name.symname,843 BFA_FCS_PORT_SYMBNAME_SEPARATOR,844 BFA_SYMNAME_MAXLEN);845 846 /* null terminate */847 port_cfg->node_sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;848}849 850/*851 * bfa lps login completion callback852 */853void854bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)855{856 struct bfa_fcs_fabric_s *fabric = uarg;857 858 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);859 bfa_trc(fabric->fcs, status);860 861 switch (status) {862 case BFA_STATUS_OK:863 fabric->stats.flogi_accepts++;864 break;865 866 case BFA_STATUS_INVALID_MAC:867 /* Only for CNA */868 fabric->stats.flogi_acc_err++;869 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);870 871 return;872 873 case BFA_STATUS_EPROTOCOL:874 switch (fabric->lps->ext_status) {875 case BFA_EPROTO_BAD_ACCEPT:876 fabric->stats.flogi_acc_err++;877 break;878 879 case BFA_EPROTO_UNKNOWN_RSP:880 fabric->stats.flogi_unknown_rsp++;881 break;882 883 default:884 break;885 }886 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);887 888 return;889 890 case BFA_STATUS_FABRIC_RJT:891 fabric->stats.flogi_rejects++;892 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);893 return;894 895 default:896 fabric->stats.flogi_rsp_err++;897 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);898 return;899 }900 901 fabric->bb_credit = fabric->lps->pr_bbcred;902 bfa_trc(fabric->fcs, fabric->bb_credit);903 904 if (!(fabric->lps->brcd_switch))905 fabric->fabric_name = fabric->lps->pr_nwwn;906 907 /*908 * Check port type. It should be 1 = F-port.909 */910 if (fabric->lps->fport) {911 fabric->bport.pid = fabric->lps->lp_pid;912 fabric->is_npiv = fabric->lps->npiv_en;913 fabric->is_auth = fabric->lps->auth_req;914 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);915 } else {916 /*917 * Nport-2-Nport direct attached918 */919 fabric->bport.port_topo.pn2n.rem_port_wwn =920 fabric->lps->pr_pwwn;921 fabric->fab_type = BFA_FCS_FABRIC_N2N;922 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);923 }924 925 bfa_trc(fabric->fcs, fabric->bport.pid);926 bfa_trc(fabric->fcs, fabric->is_npiv);927 bfa_trc(fabric->fcs, fabric->is_auth);928}929/*930 * Allocate and send FLOGI.931 */932static void933bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)934{935 struct bfa_s *bfa = fabric->fcs->bfa;936 struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;937 u8 alpa = 0;938 939 940 bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),941 pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);942 943 fabric->stats.flogi_sent++;944}945 946static void947bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)948{949 struct bfa_fcs_vport_s *vport;950 struct list_head *qe, *qen;951 952 bfa_trc(fabric->fcs, fabric->fabric_name);953 954 bfa_fcs_fabric_set_opertype(fabric);955 fabric->stats.fabric_onlines++;956 957 /*958 * notify online event to base and then virtual ports959 */960 bfa_fcs_lport_online(&fabric->bport);961 962 list_for_each_safe(qe, qen, &fabric->vport_q) {963 vport = (struct bfa_fcs_vport_s *) qe;964 bfa_fcs_vport_online(vport);965 }966}967 968static void969bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)970{971 struct bfa_fcs_vport_s *vport;972 struct list_head *qe, *qen;973 974 bfa_trc(fabric->fcs, fabric->fabric_name);975 fabric->stats.fabric_offlines++;976 977 /*978 * notify offline event first to vports and then base port.979 */980 list_for_each_safe(qe, qen, &fabric->vport_q) {981 vport = (struct bfa_fcs_vport_s *) qe;982 bfa_fcs_vport_offline(vport);983 }984 985 bfa_fcs_lport_offline(&fabric->bport);986 987 fabric->fabric_name = 0;988 fabric->fabric_ip_addr[0] = 0;989}990 991static void992bfa_fcs_fabric_delay(void *cbarg)993{994 struct bfa_fcs_fabric_s *fabric = cbarg;995 996 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);997}998 999/*1000 * Stop all vports and wait for vport stop completions.1001 */1002static void1003bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric)1004{1005 struct bfa_fcs_vport_s *vport;1006 struct list_head *qe, *qen;1007 1008 bfa_wc_init(&fabric->stop_wc, bfa_fcs_fabric_stop_comp, fabric);1009 1010 list_for_each_safe(qe, qen, &fabric->vport_q) {1011 vport = (struct bfa_fcs_vport_s *) qe;1012 bfa_wc_up(&fabric->stop_wc);1013 bfa_fcs_vport_fcs_stop(vport);1014 }1015 1016 bfa_wc_up(&fabric->stop_wc);1017 bfa_fcs_lport_stop(&fabric->bport);1018 bfa_wc_wait(&fabric->stop_wc);1019}1020 1021/*1022 * Delete all vports and wait for vport delete completions.1023 */1024static void1025bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)1026{1027 struct bfa_fcs_vport_s *vport;1028 struct list_head *qe, *qen;1029 1030 list_for_each_safe(qe, qen, &fabric->vport_q) {1031 vport = (struct bfa_fcs_vport_s *) qe;1032 bfa_fcs_vport_fcs_delete(vport);1033 }1034 1035 bfa_fcs_lport_delete(&fabric->bport);1036 bfa_wc_wait(&fabric->wc);1037}1038 1039static void1040bfa_fcs_fabric_delete_comp(void *cbarg)1041{1042 struct bfa_fcs_fabric_s *fabric = cbarg;1043 1044 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);1045}1046 1047static void1048bfa_fcs_fabric_stop_comp(void *cbarg)1049{1050 struct bfa_fcs_fabric_s *fabric = cbarg;1051 1052 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOPCOMP);1053}1054 1055/*1056 * fcs_fabric_public fabric public functions1057 */1058 1059/*1060 * Fabric module stop -- stop FCS actions1061 */1062void1063bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs)1064{1065 struct bfa_fcs_fabric_s *fabric;1066 1067 bfa_trc(fcs, 0);1068 fabric = &fcs->fabric;1069 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOP);1070}1071 1072/*1073 * Fabric module start -- kick starts FCS actions1074 */1075void1076bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)1077{1078 struct bfa_fcs_fabric_s *fabric;1079 1080 bfa_trc(fcs, 0);1081 fabric = &fcs->fabric;1082 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);1083}1084 1085 1086/*1087 * Link up notification from BFA physical port module.1088 */1089void1090bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)1091{1092 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);1093 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);1094}1095 1096/*1097 * Link down notification from BFA physical port module.1098 */1099void1100bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)1101{1102 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);1103 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);1104}1105 1106/*1107 * A child vport is being created in the fabric.1108 *1109 * Call from vport module at vport creation. A list of base port and vports1110 * belonging to a fabric is maintained to propagate link events.1111 *1112 * param[in] fabric - Fabric instance. This can be a base fabric or vf.1113 * param[in] vport - Vport being created.1114 *1115 * @return None (always succeeds)1116 */1117void1118bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,1119 struct bfa_fcs_vport_s *vport)1120{1121 /*1122 * - add vport to fabric's vport_q1123 */1124 bfa_trc(fabric->fcs, fabric->vf_id);1125 1126 list_add_tail(&vport->qe, &fabric->vport_q);1127 fabric->num_vports++;1128 bfa_wc_up(&fabric->wc);1129}1130 1131/*1132 * A child vport is being deleted from fabric.1133 *1134 * Vport is being deleted.1135 */1136void1137bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,1138 struct bfa_fcs_vport_s *vport)1139{1140 list_del(&vport->qe);1141 fabric->num_vports--;1142 bfa_wc_down(&fabric->wc);1143}1144 1145 1146/*1147 * Lookup for a vport within a fabric given its pwwn1148 */1149struct bfa_fcs_vport_s *1150bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)1151{1152 struct bfa_fcs_vport_s *vport;1153 struct list_head *qe;1154 1155 list_for_each(qe, &fabric->vport_q) {1156 vport = (struct bfa_fcs_vport_s *) qe;1157 if (bfa_fcs_lport_get_pwwn(&vport->lport) == pwwn)1158 return vport;1159 }1160 1161 return NULL;1162}1163 1164 1165/*1166 * Get OUI of the attached switch.1167 *1168 * Note : Use of this function should be avoided as much as possible.1169 * This function should be used only if there is any requirement1170* to check for FOS version below 6.3.1171 * To check if the attached fabric is a brocade fabric, use1172 * bfa_lps_is_brcd_fabric() which works for FOS versions 6.31173 * or above only.1174 */1175 1176u161177bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)1178{1179 wwn_t fab_nwwn;1180 u8 *tmp;1181 u16 oui;1182 1183 fab_nwwn = fabric->lps->pr_nwwn;1184 1185 tmp = (u8 *)&fab_nwwn;1186 oui = (tmp[3] << 8) | tmp[4];1187 1188 return oui;1189}1190/*1191 * Unsolicited frame receive handling.1192 */1193void1194bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,1195 u16 len)1196{1197 u32 pid = fchs->d_id;1198 struct bfa_fcs_vport_s *vport;1199 struct list_head *qe;1200 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);1201 struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;1202 1203 bfa_trc(fabric->fcs, len);1204 bfa_trc(fabric->fcs, pid);1205 1206 /*1207 * Look for our own FLOGI frames being looped back. This means an1208 * external loopback cable is in place. Our own FLOGI frames are1209 * sometimes looped back when switch port gets temporarily bypassed.1210 */1211 if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) &&1212 (els_cmd->els_code == FC_ELS_FLOGI) &&1213 (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {1214 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);1215 return;1216 }1217 1218 /*1219 * FLOGI/EVFP exchanges should be consumed by base fabric.1220 */1221 if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) {1222 bfa_trc(fabric->fcs, pid);1223 bfa_fcs_fabric_process_uf(fabric, fchs, len);1224 return;1225 }1226 1227 if (fabric->bport.pid == pid) {1228 /*1229 * All authentication frames should be routed to auth1230 */1231 bfa_trc(fabric->fcs, els_cmd->els_code);1232 if (els_cmd->els_code == FC_ELS_AUTH) {1233 bfa_trc(fabric->fcs, els_cmd->els_code);1234 return;1235 }1236 1237 bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));1238 bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);1239 return;1240 }1241 1242 /*1243 * look for a matching local port ID1244 */1245 list_for_each(qe, &fabric->vport_q) {1246 vport = (struct bfa_fcs_vport_s *) qe;1247 if (vport->lport.pid == pid) {1248 bfa_fcs_lport_uf_recv(&vport->lport, fchs, len);1249 return;1250 }1251 }1252 1253 if (!bfa_fcs_fabric_is_switched(fabric))1254 bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);1255 1256 bfa_trc(fabric->fcs, fchs->type);1257}1258 1259/*1260 * Unsolicited frames to be processed by fabric.1261 */1262static void1263bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,1264 u16 len)1265{1266 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);1267 1268 bfa_trc(fabric->fcs, els_cmd->els_code);1269 1270 switch (els_cmd->els_code) {1271 case FC_ELS_FLOGI:1272 bfa_fcs_fabric_process_flogi(fabric, fchs, len);1273 break;1274 1275 default:1276 /*1277 * need to generate a LS_RJT1278 */1279 break;1280 }1281}1282 1283/*1284 * Process incoming FLOGI1285 */1286static void1287bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,1288 struct fchs_s *fchs, u16 len)1289{1290 struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);1291 struct bfa_fcs_lport_s *bport = &fabric->bport;1292 1293 bfa_trc(fabric->fcs, fchs->s_id);1294 1295 fabric->stats.flogi_rcvd++;1296 /*1297 * Check port type. It should be 0 = n-port.1298 */1299 if (flogi->csp.port_type) {1300 /*1301 * @todo: may need to send a LS_RJT1302 */1303 bfa_trc(fabric->fcs, flogi->port_name);1304 fabric->stats.flogi_rejected++;1305 return;1306 }1307 1308 fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);1309 bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;1310 bport->port_topo.pn2n.reply_oxid = fchs->ox_id;1311 1312 /*1313 * Send a Flogi Acc1314 */1315 bfa_fcs_fabric_send_flogi_acc(fabric);1316 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);1317}1318 1319static void1320bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)1321{1322 struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;1323 struct bfa_fcs_lport_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;1324 struct bfa_s *bfa = fabric->fcs->bfa;1325 struct bfa_fcxp_s *fcxp;1326 u16 reqlen;1327 struct fchs_s fchs;1328 1329 fcxp = bfa_fcs_fcxp_alloc(fabric->fcs, BFA_FALSE);1330 /*1331 * Do not expect this failure -- expect remote node to retry1332 */1333 if (!fcxp)1334 return;1335 1336 reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),1337 bfa_hton3b(FC_FABRIC_PORT),1338 n2n_port->reply_oxid, pcfg->pwwn,1339 pcfg->nwwn,1340 bfa_fcport_get_maxfrsize(bfa),1341 bfa_fcport_get_rx_bbcredit(bfa), 0);1342 1343 bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag,1344 BFA_FALSE, FC_CLASS_3,1345 reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,1346 FC_MAX_PDUSZ, 0);1347}1348 1349/*1350 * Flogi Acc completion callback.1351 */1352static void1353bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,1354 bfa_status_t status, u32 rsp_len,1355 u32 resid_len, struct fchs_s *rspfchs)1356{1357 struct bfa_fcs_fabric_s *fabric = cbarg;1358 1359 bfa_trc(fabric->fcs, status);1360}1361 1362 1363/*1364 * Send AEN notification1365 */1366static void1367bfa_fcs_fabric_aen_post(struct bfa_fcs_lport_s *port,1368 enum bfa_port_aen_event event)1369{1370 struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;1371 struct bfa_aen_entry_s *aen_entry;1372 1373 bfad_get_aen_entry(bfad, aen_entry);1374 if (!aen_entry)1375 return;1376 1377 aen_entry->aen_data.port.pwwn = bfa_fcs_lport_get_pwwn(port);1378 aen_entry->aen_data.port.fwwn = bfa_fcs_lport_get_fabric_name(port);1379 1380 /* Send the AEN notification */1381 bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,1382 BFA_AEN_CAT_PORT, event);1383}1384 1385/*1386 *1387 * @param[in] fabric - fabric1388 * @param[in] wwn_t - new fabric name1389 *1390 * @return - none1391 */1392void1393bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,1394 wwn_t fabric_name)1395{1396 struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;1397 char pwwn_ptr[BFA_STRING_32];1398 char fwwn_ptr[BFA_STRING_32];1399 1400 bfa_trc(fabric->fcs, fabric_name);1401 1402 if (fabric->fabric_name == 0) {1403 /*1404 * With BRCD switches, we don't get Fabric Name in FLOGI.1405 * Don't generate a fabric name change event in this case.1406 */1407 fabric->fabric_name = fabric_name;1408 } else {1409 fabric->fabric_name = fabric_name;1410 wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));1411 wwn2str(fwwn_ptr,1412 bfa_fcs_lport_get_fabric_name(&fabric->bport));1413 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,1414 "Base port WWN = %s Fabric WWN = %s\n",1415 pwwn_ptr, fwwn_ptr);1416 bfa_fcs_fabric_aen_post(&fabric->bport,1417 BFA_PORT_AEN_FABRIC_NAME_CHANGE);1418 }1419}1420 1421void1422bfa_cb_lps_flogo_comp(void *bfad, void *uarg)1423{1424 struct bfa_fcs_fabric_s *fabric = uarg;1425 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOGOCOMP);1426}1427 1428/*1429 * Returns FCS vf structure for a given vf_id.1430 *1431 * param[in] vf_id - VF_ID1432 *1433 * return1434 * If lookup succeeds, returns fcs vf object, otherwise returns NULL1435 */1436bfa_fcs_vf_t *1437bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)1438{1439 bfa_trc(fcs, vf_id);1440 if (vf_id == FC_VF_ID_NULL)1441 return &fcs->fabric;1442 1443 return NULL;1444}1445 1446/*1447 * Return the list of local logical ports present in the given VF.1448 *1449 * @param[in] vf vf for which logical ports are returned1450 * @param[out] lpwwn returned logical port wwn list1451 * @param[in,out] nlports in:size of lpwwn list;1452 * out:total elements present,1453 * actual elements returned is limited by the size1454 */1455void1456bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)1457{1458 struct list_head *qe;1459 struct bfa_fcs_vport_s *vport;1460 int i = 0;1461 struct bfa_fcs_s *fcs;1462 1463 if (vf == NULL || lpwwn == NULL || *nlports == 0)1464 return;1465 1466 fcs = vf->fcs;1467 1468 bfa_trc(fcs, vf->vf_id);1469 bfa_trc(fcs, (uint32_t) *nlports);1470 1471 lpwwn[i++] = vf->bport.port_cfg.pwwn;1472 1473 list_for_each(qe, &vf->vport_q) {1474 if (i >= *nlports)1475 break;1476 1477 vport = (struct bfa_fcs_vport_s *) qe;1478 lpwwn[i++] = vport->lport.port_cfg.pwwn;1479 }1480 1481 bfa_trc(fcs, i);1482 *nlports = i;1483}1484 1485/*1486 * BFA FCS PPORT ( physical port)1487 */1488static void1489bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)1490{1491 struct bfa_fcs_s *fcs = cbarg;1492 1493 bfa_trc(fcs, event);1494 1495 switch (event) {1496 case BFA_PORT_LINKUP:1497 bfa_fcs_fabric_link_up(&fcs->fabric);1498 break;1499 1500 case BFA_PORT_LINKDOWN:1501 bfa_fcs_fabric_link_down(&fcs->fabric);1502 break;1503 1504 default:1505 WARN_ON(1);1506 }1507}1508 1509/*1510 * BFA FCS UF ( Unsolicited Frames)1511 */1512 1513/*1514 * BFA callback for unsolicited frame receive handler.1515 *1516 * @param[in] cbarg callback arg for receive handler1517 * @param[in] uf unsolicited frame descriptor1518 *1519 * @return None1520 */1521static void1522bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)1523{1524 struct bfa_fcs_s *fcs = (struct bfa_fcs_s *) cbarg;1525 struct fchs_s *fchs = bfa_uf_get_frmbuf(uf);1526 u16 len = bfa_uf_get_frmlen(uf);1527 struct fc_vft_s *vft;1528 struct bfa_fcs_fabric_s *fabric;1529 1530 /*1531 * check for VFT header1532 */1533 if (fchs->routing == FC_RTG_EXT_HDR &&1534 fchs->cat_info == FC_CAT_VFT_HDR) {1535 bfa_stats(fcs, uf.tagged);1536 vft = bfa_uf_get_frmbuf(uf);1537 if (fcs->port_vfid == vft->vf_id)1538 fabric = &fcs->fabric;1539 else1540 fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);1541 1542 /*1543 * drop frame if vfid is unknown1544 */1545 if (!fabric) {1546 WARN_ON(1);1547 bfa_stats(fcs, uf.vfid_unknown);1548 bfa_uf_free(uf);1549 return;1550 }1551 1552 /*1553 * skip vft header1554 */1555 fchs = (struct fchs_s *) (vft + 1);1556 len -= sizeof(struct fc_vft_s);1557 1558 bfa_trc(fcs, vft->vf_id);1559 } else {1560 bfa_stats(fcs, uf.untagged);1561 fabric = &fcs->fabric;1562 }1563 1564 bfa_trc(fcs, ((u32 *) fchs)[0]);1565 bfa_trc(fcs, ((u32 *) fchs)[1]);1566 bfa_trc(fcs, ((u32 *) fchs)[2]);1567 bfa_trc(fcs, ((u32 *) fchs)[3]);1568 bfa_trc(fcs, ((u32 *) fchs)[4]);1569 bfa_trc(fcs, ((u32 *) fchs)[5]);1570 bfa_trc(fcs, len);1571 1572 bfa_fcs_fabric_uf_recv(fabric, fchs, len);1573 bfa_uf_free(uf);1574}1575 1576/*1577 * fcs attach -- called once to initialize data structures at driver attach time1578 */1579void1580bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,1581 bfa_boolean_t min_cfg)1582{1583 struct bfa_fcs_fabric_s *fabric = &fcs->fabric;1584 1585 fcs->bfa = bfa;1586 fcs->bfad = bfad;1587 fcs->min_cfg = min_cfg;1588 fcs->num_rport_logins = 0;1589 1590 bfa->fcs = BFA_TRUE;1591 fcbuild_init();1592 1593 bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);1594 bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);1595 1596 memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));1597 1598 /*1599 * Initialize base fabric.1600 */1601 fabric->fcs = fcs;1602 INIT_LIST_HEAD(&fabric->vport_q);1603 INIT_LIST_HEAD(&fabric->vf_q);1604 fabric->lps = bfa_lps_alloc(fcs->bfa);1605 WARN_ON(!fabric->lps);1606 1607 /*1608 * Initialize fabric delete completion handler. Fabric deletion is1609 * complete when the last vport delete is complete.1610 */1611 bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);1612 bfa_wc_up(&fabric->wc); /* For the base port */1613 1614 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);1615 bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);1616}1617