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