Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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