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