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