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 26 BFA_TRC_FILE(FCS, FCS); 27 28 /* 29 * FCS sub-modules 30 */ 31 struct bfa_fcs_mod_s { 32 void (*attach) (struct bfa_fcs_s *fcs); 33 void (*modinit) (struct bfa_fcs_s *fcs); 34 void (*modexit) (struct bfa_fcs_s *fcs); 35 }; 36 37 #define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit } 38 39 static struct bfa_fcs_mod_s fcs_modules[] = { 40 { bfa_fcs_port_attach, NULL, NULL }, 41 { bfa_fcs_uf_attach, NULL, NULL }, 42 { bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit, 43 bfa_fcs_fabric_modexit }, 44 }; 45 46 /* 47 * fcs_api BFA FCS API 48 */ 49 50 static void 51 bfa_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 */ 68 void 69 bfa_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 */ 92 void 93 bfa_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 */ 123 void 124 bfa_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 */ 140 void 141 bfa_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 */ 181 static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric); 182 static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric); 183 static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric); 184 static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric); 185 static void bfa_fcs_fabric_delay(void *cbarg); 186 static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric); 187 static void bfa_fcs_fabric_delete_comp(void *cbarg); 188 static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, 189 struct fchs_s *fchs, u16 len); 190 static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, 191 struct fchs_s *fchs, u16 len); 192 static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric); 193 static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg, 194 struct bfa_fcxp_s *fcxp, void *cbarg, 195 bfa_status_t status, 196 u32 rsp_len, 197 u32 resid_len, 198 struct fchs_s *rspfchs); 199 200 static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, 201 enum bfa_fcs_fabric_event event); 202 static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric, 203 enum bfa_fcs_fabric_event event); 204 static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric, 205 enum bfa_fcs_fabric_event event); 206 static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, 207 enum bfa_fcs_fabric_event event); 208 static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric, 209 enum bfa_fcs_fabric_event event); 210 static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, 211 enum bfa_fcs_fabric_event event); 212 static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, 213 enum bfa_fcs_fabric_event event); 214 static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric, 215 enum bfa_fcs_fabric_event event); 216 static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric, 217 enum bfa_fcs_fabric_event event); 218 static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric, 219 enum bfa_fcs_fabric_event event); 220 static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric, 221 enum bfa_fcs_fabric_event event); 222 /* 223 * Beginning state before fabric creation. 224 */ 225 static void 226 bfa_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 */ 251 static void 252 bfa_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 */ 285 static void 286 bfa_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 */ 314 static void 315 bfa_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 375 static void 376 bfa_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 */ 407 static void 408 bfa_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 */ 447 void 448 bfa_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 */ 473 void 474 bfa_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 */ 499 static void 500 bfa_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 */ 532 void 533 bfa_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 */ 567 static void 568 bfa_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 */ 591 static void 592 bfa_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 */ 602 static void 603 bfa_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 */ 623 static void 624 bfa_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 654 static void 655 bfa_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 */ 667 void 668 bfa_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 */ 728 void 729 bfa_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 */ 806 static void 807 bfa_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 822 static void 823 bfa_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 844 static void 845 bfa_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 867 static void 868 bfa_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 */ 878 static void 879 bfa_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 893 static void 894 bfa_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 */ 908 void 909 bfa_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 936 void 937 bfa_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 */ 946 void 947 bfa_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 */ 964 void 965 bfa_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 */ 978 void 979 bfa_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 */ 988 void 989 bfa_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 */ 1006 void 1007 bfa_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 */ 1025 void 1026 bfa_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 withing a fabric given its pwwn 1037 */ 1038 struct bfa_fcs_vport_s * 1039 bfa_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 1065 u16 1066 bfa_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 */ 1082 void 1083 bfa_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 */ 1148 static void 1149 bfa_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 */ 1172 static void 1173 bfa_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 1205 static void 1206 bfa_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 */ 1238 static void 1239 bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, 1240 bfa_status_t status, u32 rsp_len, 1241 u32 resid_len, struct fchs_s *rspfchs) 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 */ 1255 void 1256 bfa_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 */ 1290 bfa_fcs_vf_t * 1291 bfa_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 */ 1303 static void 1304 bfa_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 1324 void 1325 bfa_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 */ 1342 static void 1343 bfa_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 1397 void 1398 bfa_fcs_uf_attach(struct bfa_fcs_s *fcs) 1399 { 1400 bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs); 1401 } 1402