1 /* 2 * Copyright (c) 2005-2009 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_port.c BFA FCS port 20 */ 21 22 #include <fcs/bfa_fcs.h> 23 #include <fcs/bfa_fcs_lport.h> 24 #include <fcs/bfa_fcs_rport.h> 25 #include <fcb/bfa_fcb_port.h> 26 #include <bfa_svc.h> 27 #include <log/bfa_log_fcs.h> 28 #include "fcs.h" 29 #include "fcs_lport.h" 30 #include "fcs_vport.h" 31 #include "fcs_rport.h" 32 #include "fcs_fcxp.h" 33 #include "fcs_trcmod.h" 34 #include "lport_priv.h" 35 #include <aen/bfa_aen_lport.h> 36 37 BFA_TRC_FILE(FCS, PORT); 38 39 /** 40 * Forward declarations 41 */ 42 43 static void bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port, 44 enum bfa_lport_aen_event event); 45 static void bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, 46 struct fchs_s *rx_fchs, u8 reason_code, 47 u8 reason_code_expl); 48 static void bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, 49 struct fchs_s *rx_fchs, 50 struct fc_logi_s *plogi); 51 static void bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port); 52 static void bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port); 53 static void bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port); 54 static void bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port); 55 static void bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port); 56 static void bfa_fcs_port_deleted(struct bfa_fcs_port_s *port); 57 static void bfa_fcs_port_echo(struct bfa_fcs_port_s *port, 58 struct fchs_s *rx_fchs, 59 struct fc_echo_s *echo, u16 len); 60 static void bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, 61 struct fchs_s *rx_fchs, 62 struct fc_rnid_cmd_s *rnid, u16 len); 63 static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port, 64 struct fc_rnid_general_topology_data_s *gen_topo_data); 65 66 static struct { 67 void (*init) (struct bfa_fcs_port_s *port); 68 void (*online) (struct bfa_fcs_port_s *port); 69 void (*offline) (struct bfa_fcs_port_s *port); 70 } __port_action[] = { 71 { 72 bfa_fcs_port_unknown_init, bfa_fcs_port_unknown_online, 73 bfa_fcs_port_unknown_offline}, { 74 bfa_fcs_port_fab_init, bfa_fcs_port_fab_online, 75 bfa_fcs_port_fab_offline}, { 76 bfa_fcs_port_loop_init, bfa_fcs_port_loop_online, 77 bfa_fcs_port_loop_offline}, { 78 bfa_fcs_port_n2n_init, bfa_fcs_port_n2n_online, 79 bfa_fcs_port_n2n_offline},}; 80 81 /** 82 * fcs_port_sm FCS logical port state machine 83 */ 84 85 enum bfa_fcs_port_event { 86 BFA_FCS_PORT_SM_CREATE = 1, 87 BFA_FCS_PORT_SM_ONLINE = 2, 88 BFA_FCS_PORT_SM_OFFLINE = 3, 89 BFA_FCS_PORT_SM_DELETE = 4, 90 BFA_FCS_PORT_SM_DELRPORT = 5, 91 }; 92 93 static void bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port, 94 enum bfa_fcs_port_event event); 95 static void bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, 96 enum bfa_fcs_port_event event); 97 static void bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port, 98 enum bfa_fcs_port_event event); 99 static void bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port, 100 enum bfa_fcs_port_event event); 101 static void bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port, 102 enum bfa_fcs_port_event event); 103 104 static void 105 bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port, 106 enum bfa_fcs_port_event event) 107 { 108 bfa_trc(port->fcs, port->port_cfg.pwwn); 109 bfa_trc(port->fcs, event); 110 111 switch (event) { 112 case BFA_FCS_PORT_SM_CREATE: 113 bfa_sm_set_state(port, bfa_fcs_port_sm_init); 114 break; 115 116 default: 117 bfa_sm_fault(port->fcs, event); 118 } 119 } 120 121 static void 122 bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event) 123 { 124 bfa_trc(port->fcs, port->port_cfg.pwwn); 125 bfa_trc(port->fcs, event); 126 127 switch (event) { 128 case BFA_FCS_PORT_SM_ONLINE: 129 bfa_sm_set_state(port, bfa_fcs_port_sm_online); 130 bfa_fcs_port_online_actions(port); 131 break; 132 133 case BFA_FCS_PORT_SM_DELETE: 134 bfa_sm_set_state(port, bfa_fcs_port_sm_uninit); 135 bfa_fcs_port_deleted(port); 136 break; 137 138 case BFA_FCS_PORT_SM_OFFLINE: 139 break; 140 141 default: 142 bfa_sm_fault(port->fcs, event); 143 } 144 } 145 146 static void 147 bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port, 148 enum bfa_fcs_port_event event) 149 { 150 struct bfa_fcs_rport_s *rport; 151 struct list_head *qe, *qen; 152 153 bfa_trc(port->fcs, port->port_cfg.pwwn); 154 bfa_trc(port->fcs, event); 155 156 switch (event) { 157 case BFA_FCS_PORT_SM_OFFLINE: 158 bfa_sm_set_state(port, bfa_fcs_port_sm_offline); 159 bfa_fcs_port_offline_actions(port); 160 break; 161 162 case BFA_FCS_PORT_SM_DELETE: 163 164 __port_action[port->fabric->fab_type].offline(port); 165 166 if (port->num_rports == 0) { 167 bfa_sm_set_state(port, bfa_fcs_port_sm_uninit); 168 bfa_fcs_port_deleted(port); 169 } else { 170 bfa_sm_set_state(port, bfa_fcs_port_sm_deleting); 171 list_for_each_safe(qe, qen, &port->rport_q) { 172 rport = (struct bfa_fcs_rport_s *)qe; 173 bfa_fcs_rport_delete(rport); 174 } 175 } 176 break; 177 178 case BFA_FCS_PORT_SM_DELRPORT: 179 break; 180 181 default: 182 bfa_sm_fault(port->fcs, event); 183 } 184 } 185 186 static void 187 bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port, 188 enum bfa_fcs_port_event event) 189 { 190 struct bfa_fcs_rport_s *rport; 191 struct list_head *qe, *qen; 192 193 bfa_trc(port->fcs, port->port_cfg.pwwn); 194 bfa_trc(port->fcs, event); 195 196 switch (event) { 197 case BFA_FCS_PORT_SM_ONLINE: 198 bfa_sm_set_state(port, bfa_fcs_port_sm_online); 199 bfa_fcs_port_online_actions(port); 200 break; 201 202 case BFA_FCS_PORT_SM_DELETE: 203 if (port->num_rports == 0) { 204 bfa_sm_set_state(port, bfa_fcs_port_sm_uninit); 205 bfa_fcs_port_deleted(port); 206 } else { 207 bfa_sm_set_state(port, bfa_fcs_port_sm_deleting); 208 list_for_each_safe(qe, qen, &port->rport_q) { 209 rport = (struct bfa_fcs_rport_s *)qe; 210 bfa_fcs_rport_delete(rport); 211 } 212 } 213 break; 214 215 case BFA_FCS_PORT_SM_DELRPORT: 216 case BFA_FCS_PORT_SM_OFFLINE: 217 break; 218 219 default: 220 bfa_sm_fault(port->fcs, event); 221 } 222 } 223 224 static void 225 bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port, 226 enum bfa_fcs_port_event event) 227 { 228 bfa_trc(port->fcs, port->port_cfg.pwwn); 229 bfa_trc(port->fcs, event); 230 231 switch (event) { 232 case BFA_FCS_PORT_SM_DELRPORT: 233 if (port->num_rports == 0) { 234 bfa_sm_set_state(port, bfa_fcs_port_sm_uninit); 235 bfa_fcs_port_deleted(port); 236 } 237 break; 238 239 default: 240 bfa_sm_fault(port->fcs, event); 241 } 242 } 243 244 245 246 /** 247 * fcs_port_pvt 248 */ 249 250 /** 251 * Send AEN notification 252 */ 253 static void 254 bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port, 255 enum bfa_lport_aen_event event) 256 { 257 union bfa_aen_data_u aen_data; 258 struct bfa_log_mod_s *logmod = port->fcs->logm; 259 enum bfa_port_role role = port->port_cfg.roles; 260 wwn_t lpwwn = bfa_fcs_port_get_pwwn(port); 261 char lpwwn_ptr[BFA_STRING_32]; 262 char *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] = 263 { "Initiator", "Target", "IPFC" }; 264 265 wwn2str(lpwwn_ptr, lpwwn); 266 267 bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX); 268 269 bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, event), lpwwn_ptr, 270 role_str[role/2]); 271 272 aen_data.lport.vf_id = port->fabric->vf_id; 273 aen_data.lport.roles = role; 274 aen_data.lport.ppwwn = 275 bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs)); 276 aen_data.lport.lpwwn = lpwwn; 277 } 278 279 /* 280 * Send a LS reject 281 */ 282 static void 283 bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs, 284 u8 reason_code, u8 reason_code_expl) 285 { 286 struct fchs_s fchs; 287 struct bfa_fcxp_s *fcxp; 288 struct bfa_rport_s *bfa_rport = NULL; 289 int len; 290 291 bfa_trc(port->fcs, rx_fchs->s_id); 292 293 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 294 if (!fcxp) 295 return; 296 297 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, 298 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, 299 reason_code, reason_code_expl); 300 301 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 302 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 303 FC_MAX_PDUSZ, 0); 304 } 305 306 /** 307 * Process incoming plogi from a remote port. 308 */ 309 static void 310 bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs, 311 struct fc_logi_s *plogi) 312 { 313 struct bfa_fcs_rport_s *rport; 314 315 bfa_trc(port->fcs, rx_fchs->d_id); 316 bfa_trc(port->fcs, rx_fchs->s_id); 317 318 /* 319 * If min cfg mode is enabled, drop any incoming PLOGIs 320 */ 321 if (__fcs_min_cfg(port->fcs)) { 322 bfa_trc(port->fcs, rx_fchs->s_id); 323 return; 324 } 325 326 if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) { 327 bfa_trc(port->fcs, rx_fchs->s_id); 328 /* 329 * send a LS reject 330 */ 331 bfa_fcs_port_send_ls_rjt(port, rx_fchs, 332 FC_LS_RJT_RSN_PROTOCOL_ERROR, 333 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS); 334 return; 335 } 336 337 /** 338 * Direct Attach P2P mode : verify address assigned by the r-port. 339 */ 340 if ((!bfa_fcs_fabric_is_switched(port->fabric)) 341 && 342 (memcmp 343 ((void *)&bfa_fcs_port_get_pwwn(port), (void *)&plogi->port_name, 344 sizeof(wwn_t)) < 0)) { 345 if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) { 346 /* 347 * Address assigned to us cannot be a WKA 348 */ 349 bfa_fcs_port_send_ls_rjt(port, rx_fchs, 350 FC_LS_RJT_RSN_PROTOCOL_ERROR, 351 FC_LS_RJT_EXP_INVALID_NPORT_ID); 352 return; 353 } 354 port->pid = rx_fchs->d_id; 355 } 356 357 /** 358 * First, check if we know the device by pwwn. 359 */ 360 rport = bfa_fcs_port_get_rport_by_pwwn(port, plogi->port_name); 361 if (rport) { 362 /** 363 * Direct Attach P2P mode: handle address assigned by the rport. 364 */ 365 if ((!bfa_fcs_fabric_is_switched(port->fabric)) 366 && 367 (memcmp 368 ((void *)&bfa_fcs_port_get_pwwn(port), 369 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) { 370 port->pid = rx_fchs->d_id; 371 rport->pid = rx_fchs->s_id; 372 } 373 bfa_fcs_rport_plogi(rport, rx_fchs, plogi); 374 return; 375 } 376 377 /** 378 * Next, lookup rport by PID. 379 */ 380 rport = bfa_fcs_port_get_rport_by_pid(port, rx_fchs->s_id); 381 if (!rport) { 382 /** 383 * Inbound PLOGI from a new device. 384 */ 385 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); 386 return; 387 } 388 389 /** 390 * Rport is known only by PID. 391 */ 392 if (rport->pwwn) { 393 /** 394 * This is a different device with the same pid. Old device 395 * disappeared. Send implicit LOGO to old device. 396 */ 397 bfa_assert(rport->pwwn != plogi->port_name); 398 bfa_fcs_rport_logo_imp(rport); 399 400 /** 401 * Inbound PLOGI from a new device (with old PID). 402 */ 403 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); 404 return; 405 } 406 407 /** 408 * PLOGI crossing each other. 409 */ 410 bfa_assert(rport->pwwn == WWN_NULL); 411 bfa_fcs_rport_plogi(rport, rx_fchs, plogi); 412 } 413 414 /* 415 * Process incoming ECHO. 416 * Since it does not require a login, it is processed here. 417 */ 418 static void 419 bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs, 420 struct fc_echo_s *echo, u16 rx_len) 421 { 422 struct fchs_s fchs; 423 struct bfa_fcxp_s *fcxp; 424 struct bfa_rport_s *bfa_rport = NULL; 425 int len, pyld_len; 426 427 bfa_trc(port->fcs, rx_fchs->s_id); 428 bfa_trc(port->fcs, rx_fchs->d_id); 429 bfa_trc(port->fcs, rx_len); 430 431 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 432 if (!fcxp) 433 return; 434 435 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, 436 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id); 437 438 /* 439 * Copy the payload (if any) from the echo frame 440 */ 441 pyld_len = rx_len - sizeof(struct fchs_s); 442 bfa_trc(port->fcs, pyld_len); 443 444 if (pyld_len > len) 445 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) + 446 sizeof(struct fc_echo_s), (echo + 1), 447 (pyld_len - sizeof(struct fc_echo_s))); 448 449 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 450 BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL, 451 FC_MAX_PDUSZ, 0); 452 } 453 454 /* 455 * Process incoming RNID. 456 * Since it does not require a login, it is processed here. 457 */ 458 static void 459 bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs, 460 struct fc_rnid_cmd_s *rnid, u16 rx_len) 461 { 462 struct fc_rnid_common_id_data_s common_id_data; 463 struct fc_rnid_general_topology_data_s gen_topo_data; 464 struct fchs_s fchs; 465 struct bfa_fcxp_s *fcxp; 466 struct bfa_rport_s *bfa_rport = NULL; 467 u16 len; 468 u32 data_format; 469 470 bfa_trc(port->fcs, rx_fchs->s_id); 471 bfa_trc(port->fcs, rx_fchs->d_id); 472 bfa_trc(port->fcs, rx_len); 473 474 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 475 if (!fcxp) 476 return; 477 478 /* 479 * Check Node Indentification Data Format 480 * We only support General Topology Discovery Format. 481 * For any other requested Data Formats, we return Common Node Id Data 482 * only, as per FC-LS. 483 */ 484 bfa_trc(port->fcs, rnid->node_id_data_format); 485 if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) { 486 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY; 487 /* 488 * Get General topology data for this port 489 */ 490 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data); 491 } else { 492 data_format = RNID_NODEID_DATA_FORMAT_COMMON; 493 } 494 495 /* 496 * Copy the Node Id Info 497 */ 498 common_id_data.port_name = bfa_fcs_port_get_pwwn(port); 499 common_id_data.node_name = bfa_fcs_port_get_nwwn(port); 500 501 len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, 502 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, 503 data_format, &common_id_data, &gen_topo_data); 504 505 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 506 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 507 FC_MAX_PDUSZ, 0); 508 509 return; 510 } 511 512 /* 513 * Fill out General Topolpgy Discovery Data for RNID ELS. 514 */ 515 static void 516 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port, 517 struct fc_rnid_general_topology_data_s *gen_topo_data) 518 { 519 520 bfa_os_memset(gen_topo_data, 0, 521 sizeof(struct fc_rnid_general_topology_data_s)); 522 523 gen_topo_data->asso_type = bfa_os_htonl(RNID_ASSOCIATED_TYPE_HOST); 524 gen_topo_data->phy_port_num = 0; /* @todo */ 525 gen_topo_data->num_attached_nodes = bfa_os_htonl(1); 526 } 527 528 static void 529 bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port) 530 { 531 bfa_trc(port->fcs, port->fabric->oper_type); 532 533 __port_action[port->fabric->fab_type].init(port); 534 __port_action[port->fabric->fab_type].online(port); 535 536 bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_ONLINE); 537 bfa_fcb_port_online(port->fcs->bfad, port->port_cfg.roles, 538 port->fabric->vf_drv, (port->vport == NULL) ? 539 NULL : port->vport->vport_drv); 540 } 541 542 static void 543 bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port) 544 { 545 struct list_head *qe, *qen; 546 struct bfa_fcs_rport_s *rport; 547 548 bfa_trc(port->fcs, port->fabric->oper_type); 549 550 __port_action[port->fabric->fab_type].offline(port); 551 552 if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) 553 bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT); 554 else 555 bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE); 556 bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles, 557 port->fabric->vf_drv, 558 (port->vport == NULL) ? NULL : port->vport->vport_drv); 559 560 list_for_each_safe(qe, qen, &port->rport_q) { 561 rport = (struct bfa_fcs_rport_s *)qe; 562 bfa_fcs_rport_offline(rport); 563 } 564 } 565 566 static void 567 bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port) 568 { 569 bfa_assert(0); 570 } 571 572 static void 573 bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port) 574 { 575 bfa_assert(0); 576 } 577 578 static void 579 bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port) 580 { 581 bfa_assert(0); 582 } 583 584 static void 585 bfa_fcs_port_deleted(struct bfa_fcs_port_s *port) 586 { 587 bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DELETE); 588 589 /* 590 * Base port will be deleted by the OS driver 591 */ 592 if (port->vport) { 593 bfa_fcb_port_delete(port->fcs->bfad, port->port_cfg.roles, 594 port->fabric->vf_drv, 595 port->vport ? port->vport->vport_drv : NULL); 596 bfa_fcs_vport_delete_comp(port->vport); 597 } else { 598 bfa_fcs_fabric_port_delete_comp(port->fabric); 599 } 600 } 601 602 603 604 /** 605 * fcs_lport_api BFA FCS port API 606 */ 607 /** 608 * Module initialization 609 */ 610 void 611 bfa_fcs_port_modinit(struct bfa_fcs_s *fcs) 612 { 613 614 } 615 616 /** 617 * Module cleanup 618 */ 619 void 620 bfa_fcs_port_modexit(struct bfa_fcs_s *fcs) 621 { 622 bfa_fcs_modexit_comp(fcs); 623 } 624 625 /** 626 * Unsolicited frame receive handling. 627 */ 628 void 629 bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs, 630 u16 len) 631 { 632 u32 pid = fchs->s_id; 633 struct bfa_fcs_rport_s *rport = NULL; 634 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); 635 636 bfa_stats(lport, uf_recvs); 637 638 if (!bfa_fcs_port_is_online(lport)) { 639 bfa_stats(lport, uf_recv_drops); 640 return; 641 } 642 643 /** 644 * First, handle ELSs that donot require a login. 645 */ 646 /* 647 * Handle PLOGI first 648 */ 649 if ((fchs->type == FC_TYPE_ELS) && 650 (els_cmd->els_code == FC_ELS_PLOGI)) { 651 bfa_fcs_port_plogi(lport, fchs, (struct fc_logi_s *) els_cmd); 652 return; 653 } 654 655 /* 656 * Handle ECHO separately. 657 */ 658 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) { 659 bfa_fcs_port_echo(lport, fchs, 660 (struct fc_echo_s *) els_cmd, len); 661 return; 662 } 663 664 /* 665 * Handle RNID separately. 666 */ 667 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) { 668 bfa_fcs_port_rnid(lport, fchs, 669 (struct fc_rnid_cmd_s *) els_cmd, len); 670 return; 671 } 672 673 /** 674 * look for a matching remote port ID 675 */ 676 rport = bfa_fcs_port_get_rport_by_pid(lport, pid); 677 if (rport) { 678 bfa_trc(rport->fcs, fchs->s_id); 679 bfa_trc(rport->fcs, fchs->d_id); 680 bfa_trc(rport->fcs, fchs->type); 681 682 bfa_fcs_rport_uf_recv(rport, fchs, len); 683 return; 684 } 685 686 /** 687 * Only handles ELS frames for now. 688 */ 689 if (fchs->type != FC_TYPE_ELS) { 690 bfa_trc(lport->fcs, fchs->type); 691 bfa_assert(0); 692 return; 693 } 694 695 bfa_trc(lport->fcs, els_cmd->els_code); 696 if (els_cmd->els_code == FC_ELS_RSCN) { 697 bfa_fcs_port_scn_process_rscn(lport, fchs, len); 698 return; 699 } 700 701 if (els_cmd->els_code == FC_ELS_LOGO) { 702 /** 703 * @todo Handle LOGO frames received. 704 */ 705 bfa_trc(lport->fcs, els_cmd->els_code); 706 return; 707 } 708 709 if (els_cmd->els_code == FC_ELS_PRLI) { 710 /** 711 * @todo Handle PRLI frames received. 712 */ 713 bfa_trc(lport->fcs, els_cmd->els_code); 714 return; 715 } 716 717 /** 718 * Unhandled ELS frames. Send a LS_RJT. 719 */ 720 bfa_fcs_port_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP, 721 FC_LS_RJT_EXP_NO_ADDL_INFO); 722 723 } 724 725 /** 726 * PID based Lookup for a R-Port in the Port R-Port Queue 727 */ 728 struct bfa_fcs_rport_s * 729 bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid) 730 { 731 struct bfa_fcs_rport_s *rport; 732 struct list_head *qe; 733 734 list_for_each(qe, &port->rport_q) { 735 rport = (struct bfa_fcs_rport_s *)qe; 736 if (rport->pid == pid) 737 return rport; 738 } 739 740 bfa_trc(port->fcs, pid); 741 return NULL; 742 } 743 744 /** 745 * PWWN based Lookup for a R-Port in the Port R-Port Queue 746 */ 747 struct bfa_fcs_rport_s * 748 bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn) 749 { 750 struct bfa_fcs_rport_s *rport; 751 struct list_head *qe; 752 753 list_for_each(qe, &port->rport_q) { 754 rport = (struct bfa_fcs_rport_s *)qe; 755 if (wwn_is_equal(rport->pwwn, pwwn)) 756 return rport; 757 } 758 759 bfa_trc(port->fcs, pwwn); 760 return NULL; 761 } 762 763 /** 764 * NWWN based Lookup for a R-Port in the Port R-Port Queue 765 */ 766 struct bfa_fcs_rport_s * 767 bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn) 768 { 769 struct bfa_fcs_rport_s *rport; 770 struct list_head *qe; 771 772 list_for_each(qe, &port->rport_q) { 773 rport = (struct bfa_fcs_rport_s *)qe; 774 if (wwn_is_equal(rport->nwwn, nwwn)) 775 return rport; 776 } 777 778 bfa_trc(port->fcs, nwwn); 779 return NULL; 780 } 781 782 /** 783 * Called by rport module when new rports are discovered. 784 */ 785 void 786 bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port, 787 struct bfa_fcs_rport_s *rport) 788 { 789 list_add_tail(&rport->qe, &port->rport_q); 790 port->num_rports++; 791 } 792 793 /** 794 * Called by rport module to when rports are deleted. 795 */ 796 void 797 bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port, 798 struct bfa_fcs_rport_s *rport) 799 { 800 bfa_assert(bfa_q_is_on_q(&port->rport_q, rport)); 801 list_del(&rport->qe); 802 port->num_rports--; 803 804 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT); 805 } 806 807 /** 808 * Called by fabric for base port when fabric login is complete. 809 * Called by vport for virtual ports when FDISC is complete. 810 */ 811 void 812 bfa_fcs_port_online(struct bfa_fcs_port_s *port) 813 { 814 bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE); 815 } 816 817 /** 818 * Called by fabric for base port when fabric goes offline. 819 * Called by vport for virtual ports when virtual port becomes offline. 820 */ 821 void 822 bfa_fcs_port_offline(struct bfa_fcs_port_s *port) 823 { 824 bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE); 825 } 826 827 /** 828 * Called by fabric to delete base lport and associated resources. 829 * 830 * Called by vport to delete lport and associated resources. Should call 831 * bfa_fcs_vport_delete_comp() for vports on completion. 832 */ 833 void 834 bfa_fcs_port_delete(struct bfa_fcs_port_s *port) 835 { 836 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE); 837 } 838 839 /** 840 * Called by fabric in private loop topology to process LIP event. 841 */ 842 void 843 bfa_fcs_port_lip(struct bfa_fcs_port_s *port) 844 { 845 } 846 847 /** 848 * Return TRUE if port is online, else return FALSE 849 */ 850 bfa_boolean_t 851 bfa_fcs_port_is_online(struct bfa_fcs_port_s *port) 852 { 853 return bfa_sm_cmp_state(port, bfa_fcs_port_sm_online); 854 } 855 856 /** 857 * Attach time initialization of logical ports. 858 */ 859 void 860 bfa_fcs_lport_attach(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs, 861 uint16_t vf_id, struct bfa_fcs_vport_s *vport) 862 { 863 lport->fcs = fcs; 864 lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id); 865 lport->vport = vport; 866 lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) : 867 bfa_lps_get_tag(lport->fabric->lps); 868 869 INIT_LIST_HEAD(&lport->rport_q); 870 lport->num_rports = 0; 871 } 872 873 /** 874 * Logical port initialization of base or virtual port. 875 * Called by fabric for base port or by vport for virtual ports. 876 */ 877 878 void 879 bfa_fcs_lport_init(struct bfa_fcs_port_s *lport, 880 struct bfa_port_cfg_s *port_cfg) 881 { 882 struct bfa_fcs_vport_s *vport = lport->vport; 883 884 bfa_os_assign(lport->port_cfg, *port_cfg); 885 886 lport->bfad_port = bfa_fcb_port_new(lport->fcs->bfad, lport, 887 lport->port_cfg.roles, 888 lport->fabric->vf_drv, 889 vport ? vport->vport_drv : NULL); 890 891 bfa_fcs_port_aen_post(lport, BFA_LPORT_AEN_NEW); 892 893 bfa_sm_set_state(lport, bfa_fcs_port_sm_uninit); 894 bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE); 895 } 896 897 /** 898 * fcs_lport_api 899 */ 900 901 void 902 bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port, 903 struct bfa_port_attr_s *port_attr) 904 { 905 if (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online)) 906 port_attr->pid = port->pid; 907 else 908 port_attr->pid = 0; 909 910 port_attr->port_cfg = port->port_cfg; 911 912 if (port->fabric) { 913 port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric); 914 port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric); 915 port_attr->authfail = 916 bfa_fcs_fabric_is_auth_failed(port->fabric); 917 port_attr->fabric_name = bfa_fcs_port_get_fabric_name(port); 918 memcpy(port_attr->fabric_ip_addr, 919 bfa_fcs_port_get_fabric_ipaddr(port), 920 BFA_FCS_FABRIC_IPADDR_SZ); 921 922 if (port->vport != NULL) { 923 port_attr->port_type = BFA_PPORT_TYPE_VPORT; 924 port_attr->fpma_mac = 925 bfa_lps_get_lp_mac(port->vport->lps); 926 } else 927 port_attr->fpma_mac = 928 bfa_lps_get_lp_mac(port->fabric->lps); 929 930 } else { 931 port_attr->port_type = BFA_PPORT_TYPE_UNKNOWN; 932 port_attr->state = BFA_PORT_UNINIT; 933 } 934 935 } 936 937 938