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