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, 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 bfa_os_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 = bfa_os_ntohs(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, log_level, 1415 "Base port WWN = %s Fabric WWN = %s\n", 1416 pwwn_ptr, fwwn_ptr); 1417 } 1418 } 1419 1420 /** 1421 * fcs_vf_api virtual fabrics API 1422 */ 1423 1424 /** 1425 * Enable VF mode. 1426 * 1427 * @param[in] fcs fcs module instance 1428 * @param[in] vf_id default vf_id of port, FC_VF_ID_NULL 1429 * to use standard default vf_id of 1. 1430 * 1431 * @retval BFA_STATUS_OK vf mode is enabled 1432 * @retval BFA_STATUS_BUSY Port is active. Port must be disabled 1433 * before VF mode can be enabled. 1434 */ 1435 bfa_status_t 1436 bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id) 1437 { 1438 return BFA_STATUS_OK; 1439 } 1440 1441 /** 1442 * Disable VF mode. 1443 * 1444 * @param[in] fcs fcs module instance 1445 * 1446 * @retval BFA_STATUS_OK vf mode is disabled 1447 * @retval BFA_STATUS_BUSY VFs are present and being used. All 1448 * VFs must be deleted before disabling 1449 * VF mode. 1450 */ 1451 bfa_status_t 1452 bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs) 1453 { 1454 return BFA_STATUS_OK; 1455 } 1456 1457 /** 1458 * Create a new VF instance. 1459 * 1460 * A new VF is created using the given VF configuration. A VF is identified 1461 * by VF id. No duplicate VF creation is allowed with the same VF id. Once 1462 * a VF is created, VF is automatically started after link initialization 1463 * and EVFP exchange is completed. 1464 * 1465 * param[in] vf - FCS vf data structure. Memory is 1466 * allocated by caller (driver) 1467 * param[in] fcs - FCS module 1468 * param[in] vf_cfg - VF configuration 1469 * param[in] vf_drv - Opaque handle back to the driver's 1470 * virtual vf structure 1471 * 1472 * retval BFA_STATUS_OK VF creation is successful 1473 * retval BFA_STATUS_FAILED VF creation failed 1474 * retval BFA_STATUS_EEXIST A VF exists with the given vf_id 1475 */ 1476 bfa_status_t 1477 bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, u16 vf_id, 1478 struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv) 1479 { 1480 bfa_trc(fcs, vf_id); 1481 return BFA_STATUS_OK; 1482 } 1483 1484 /** 1485 * Use this function to delete a BFA VF object. VF object should 1486 * be stopped before this function call. 1487 * 1488 * param[in] vf - pointer to bfa_vf_t. 1489 * 1490 * retval BFA_STATUS_OK On vf deletion success 1491 * retval BFA_STATUS_BUSY VF is not in a stopped state 1492 * retval BFA_STATUS_INPROGRESS VF deletion in in progress 1493 */ 1494 bfa_status_t 1495 bfa_fcs_vf_delete(bfa_fcs_vf_t *vf) 1496 { 1497 bfa_trc(vf->fcs, vf->vf_id); 1498 return BFA_STATUS_OK; 1499 } 1500 1501 1502 /** 1503 * Returns attributes of the given VF. 1504 * 1505 * param[in] vf pointer to bfa_vf_t. 1506 * param[out] vf_attr vf attributes returned 1507 * 1508 * return None 1509 */ 1510 void 1511 bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr) 1512 { 1513 bfa_trc(vf->fcs, vf->vf_id); 1514 } 1515 1516 /** 1517 * Return statistics associated with the given vf. 1518 * 1519 * param[in] vf pointer to bfa_vf_t. 1520 * param[out] vf_stats vf statistics returned 1521 * 1522 * @return None 1523 */ 1524 void 1525 bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, struct bfa_vf_stats_s *vf_stats) 1526 { 1527 bfa_os_memcpy(vf_stats, &vf->stats, sizeof(struct bfa_vf_stats_s)); 1528 } 1529 1530 /** 1531 * clear statistics associated with the given vf. 1532 * 1533 * param[in] vf pointer to bfa_vf_t. 1534 * 1535 * @return None 1536 */ 1537 void 1538 bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf) 1539 { 1540 bfa_os_memset(&vf->stats, 0, sizeof(struct bfa_vf_stats_s)); 1541 } 1542 1543 /** 1544 * Returns FCS vf structure for a given vf_id. 1545 * 1546 * param[in] vf_id - VF_ID 1547 * 1548 * return 1549 * If lookup succeeds, retuns fcs vf object, otherwise returns NULL 1550 */ 1551 bfa_fcs_vf_t * 1552 bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id) 1553 { 1554 bfa_trc(fcs, vf_id); 1555 if (vf_id == FC_VF_ID_NULL) 1556 return &fcs->fabric; 1557 1558 return NULL; 1559 } 1560 1561 /** 1562 * Return the list of VFs configured. 1563 * 1564 * param[in] fcs fcs module instance 1565 * param[out] vf_ids returned list of vf_ids 1566 * param[in,out] nvfs in:size of vf_ids array, 1567 * out:total elements present, 1568 * actual elements returned is limited by the size 1569 * 1570 * return Driver VF structure 1571 */ 1572 void 1573 bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs) 1574 { 1575 bfa_trc(fcs, *nvfs); 1576 } 1577 1578 /** 1579 * Return the list of all VFs visible from fabric. 1580 * 1581 * param[in] fcs fcs module instance 1582 * param[out] vf_ids returned list of vf_ids 1583 * param[in,out] nvfs in:size of vf_ids array, 1584 * out:total elements present, 1585 * actual elements returned is limited by the size 1586 * 1587 * return Driver VF structure 1588 */ 1589 void 1590 bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs) 1591 { 1592 bfa_trc(fcs, *nvfs); 1593 } 1594 1595 /** 1596 * Return the list of local logical ports present in the given VF. 1597 * 1598 * param[in] vf vf for which logical ports are returned 1599 * param[out] lpwwn returned logical port wwn list 1600 * param[in,out] nlports in:size of lpwwn list; 1601 * out:total elements present, 1602 * actual elements returned is limited by the size 1603 */ 1604 void 1605 bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports) 1606 { 1607 struct list_head *qe; 1608 struct bfa_fcs_vport_s *vport; 1609 int i; 1610 struct bfa_fcs_s *fcs; 1611 1612 if (vf == NULL || lpwwn == NULL || *nlports == 0) 1613 return; 1614 1615 fcs = vf->fcs; 1616 1617 bfa_trc(fcs, vf->vf_id); 1618 bfa_trc(fcs, (u32) *nlports); 1619 1620 i = 0; 1621 lpwwn[i++] = vf->bport.port_cfg.pwwn; 1622 1623 list_for_each(qe, &vf->vport_q) { 1624 if (i >= *nlports) 1625 break; 1626 1627 vport = (struct bfa_fcs_vport_s *) qe; 1628 lpwwn[i++] = vport->lport.port_cfg.pwwn; 1629 } 1630 1631 bfa_trc(fcs, i); 1632 *nlports = i; 1633 } 1634 1635 /** 1636 * BFA FCS PPORT ( physical port) 1637 */ 1638 static void 1639 bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event) 1640 { 1641 struct bfa_fcs_s *fcs = cbarg; 1642 1643 bfa_trc(fcs, event); 1644 1645 switch (event) { 1646 case BFA_PORT_LINKUP: 1647 bfa_fcs_fabric_link_up(&fcs->fabric); 1648 break; 1649 1650 case BFA_PORT_LINKDOWN: 1651 bfa_fcs_fabric_link_down(&fcs->fabric); 1652 break; 1653 1654 default: 1655 bfa_assert(0); 1656 } 1657 } 1658 1659 void 1660 bfa_fcs_port_attach(struct bfa_fcs_s *fcs) 1661 { 1662 bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs); 1663 } 1664 1665 /** 1666 * BFA FCS UF ( Unsolicited Frames) 1667 */ 1668 1669 /** 1670 * BFA callback for unsolicited frame receive handler. 1671 * 1672 * @param[in] cbarg callback arg for receive handler 1673 * @param[in] uf unsolicited frame descriptor 1674 * 1675 * @return None 1676 */ 1677 static void 1678 bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf) 1679 { 1680 struct bfa_fcs_s *fcs = (struct bfa_fcs_s *) cbarg; 1681 struct fchs_s *fchs = bfa_uf_get_frmbuf(uf); 1682 u16 len = bfa_uf_get_frmlen(uf); 1683 struct fc_vft_s *vft; 1684 struct bfa_fcs_fabric_s *fabric; 1685 1686 /** 1687 * check for VFT header 1688 */ 1689 if (fchs->routing == FC_RTG_EXT_HDR && 1690 fchs->cat_info == FC_CAT_VFT_HDR) { 1691 bfa_stats(fcs, uf.tagged); 1692 vft = bfa_uf_get_frmbuf(uf); 1693 if (fcs->port_vfid == vft->vf_id) 1694 fabric = &fcs->fabric; 1695 else 1696 fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id); 1697 1698 /** 1699 * drop frame if vfid is unknown 1700 */ 1701 if (!fabric) { 1702 bfa_assert(0); 1703 bfa_stats(fcs, uf.vfid_unknown); 1704 bfa_uf_free(uf); 1705 return; 1706 } 1707 1708 /** 1709 * skip vft header 1710 */ 1711 fchs = (struct fchs_s *) (vft + 1); 1712 len -= sizeof(struct fc_vft_s); 1713 1714 bfa_trc(fcs, vft->vf_id); 1715 } else { 1716 bfa_stats(fcs, uf.untagged); 1717 fabric = &fcs->fabric; 1718 } 1719 1720 bfa_trc(fcs, ((u32 *) fchs)[0]); 1721 bfa_trc(fcs, ((u32 *) fchs)[1]); 1722 bfa_trc(fcs, ((u32 *) fchs)[2]); 1723 bfa_trc(fcs, ((u32 *) fchs)[3]); 1724 bfa_trc(fcs, ((u32 *) fchs)[4]); 1725 bfa_trc(fcs, ((u32 *) fchs)[5]); 1726 bfa_trc(fcs, len); 1727 1728 bfa_fcs_fabric_uf_recv(fabric, fchs, len); 1729 bfa_uf_free(uf); 1730 } 1731 1732 void 1733 bfa_fcs_uf_attach(struct bfa_fcs_s *fcs) 1734 { 1735 bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs); 1736 } 1737