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