1 /* 2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. 3 * All rights reserved 4 * www.brocade.com 5 * 6 * Linux driver for Brocade Fibre Channel Host Bus Adapter. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License (GPL) Version 2 as 10 * published by the Free Software Foundation 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 */ 17 18 #include "bfa_fcs.h" 19 #include "bfa_fcbuild.h" 20 #include "bfa_fc.h" 21 #include "bfad_drv.h" 22 23 BFA_TRC_FILE(FCS, PORT); 24 25 static void bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, 26 struct fchs_s *rx_fchs, u8 reason_code, 27 u8 reason_code_expl); 28 static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, 29 struct fchs_s *rx_fchs, struct fc_logi_s *plogi); 30 static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port); 31 static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port); 32 static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port); 33 static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port); 34 static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port); 35 static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port); 36 static void bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, 37 struct fchs_s *rx_fchs, 38 struct fc_echo_s *echo, u16 len); 39 static void bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, 40 struct fchs_s *rx_fchs, 41 struct fc_rnid_cmd_s *rnid, u16 len); 42 static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port, 43 struct fc_rnid_general_topology_data_s *gen_topo_data); 44 45 static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port); 46 static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port); 47 static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port); 48 49 static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port); 50 static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port); 51 static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port); 52 53 static struct { 54 void (*init) (struct bfa_fcs_lport_s *port); 55 void (*online) (struct bfa_fcs_lport_s *port); 56 void (*offline) (struct bfa_fcs_lport_s *port); 57 } __port_action[] = { 58 { 59 bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online, 60 bfa_fcs_lport_unknown_offline}, { 61 bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online, 62 bfa_fcs_lport_fab_offline}, { 63 bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online, 64 bfa_fcs_lport_n2n_offline}, 65 }; 66 67 /* 68 * fcs_port_sm FCS logical port state machine 69 */ 70 71 enum bfa_fcs_lport_event { 72 BFA_FCS_PORT_SM_CREATE = 1, 73 BFA_FCS_PORT_SM_ONLINE = 2, 74 BFA_FCS_PORT_SM_OFFLINE = 3, 75 BFA_FCS_PORT_SM_DELETE = 4, 76 BFA_FCS_PORT_SM_DELRPORT = 5, 77 }; 78 79 static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port, 80 enum bfa_fcs_lport_event event); 81 static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port, 82 enum bfa_fcs_lport_event event); 83 static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port, 84 enum bfa_fcs_lport_event event); 85 static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port, 86 enum bfa_fcs_lport_event event); 87 static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port, 88 enum bfa_fcs_lport_event event); 89 90 static void 91 bfa_fcs_lport_sm_uninit( 92 struct bfa_fcs_lport_s *port, 93 enum bfa_fcs_lport_event event) 94 { 95 bfa_trc(port->fcs, port->port_cfg.pwwn); 96 bfa_trc(port->fcs, event); 97 98 switch (event) { 99 case BFA_FCS_PORT_SM_CREATE: 100 bfa_sm_set_state(port, bfa_fcs_lport_sm_init); 101 break; 102 103 default: 104 bfa_sm_fault(port->fcs, event); 105 } 106 } 107 108 static void 109 bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port, 110 enum bfa_fcs_lport_event event) 111 { 112 bfa_trc(port->fcs, port->port_cfg.pwwn); 113 bfa_trc(port->fcs, event); 114 115 switch (event) { 116 case BFA_FCS_PORT_SM_ONLINE: 117 bfa_sm_set_state(port, bfa_fcs_lport_sm_online); 118 bfa_fcs_lport_online_actions(port); 119 break; 120 121 case BFA_FCS_PORT_SM_DELETE: 122 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); 123 bfa_fcs_lport_deleted(port); 124 break; 125 126 case BFA_FCS_PORT_SM_OFFLINE: 127 break; 128 129 default: 130 bfa_sm_fault(port->fcs, event); 131 } 132 } 133 134 static void 135 bfa_fcs_lport_sm_online( 136 struct bfa_fcs_lport_s *port, 137 enum bfa_fcs_lport_event event) 138 { 139 struct bfa_fcs_rport_s *rport; 140 struct list_head *qe, *qen; 141 142 bfa_trc(port->fcs, port->port_cfg.pwwn); 143 bfa_trc(port->fcs, event); 144 145 switch (event) { 146 case BFA_FCS_PORT_SM_OFFLINE: 147 bfa_sm_set_state(port, bfa_fcs_lport_sm_offline); 148 bfa_fcs_lport_offline_actions(port); 149 break; 150 151 case BFA_FCS_PORT_SM_DELETE: 152 153 __port_action[port->fabric->fab_type].offline(port); 154 155 if (port->num_rports == 0) { 156 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); 157 bfa_fcs_lport_deleted(port); 158 } else { 159 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting); 160 list_for_each_safe(qe, qen, &port->rport_q) { 161 rport = (struct bfa_fcs_rport_s *) qe; 162 bfa_fcs_rport_delete(rport); 163 } 164 } 165 break; 166 167 case BFA_FCS_PORT_SM_DELRPORT: 168 break; 169 170 default: 171 bfa_sm_fault(port->fcs, event); 172 } 173 } 174 175 static void 176 bfa_fcs_lport_sm_offline( 177 struct bfa_fcs_lport_s *port, 178 enum bfa_fcs_lport_event event) 179 { 180 struct bfa_fcs_rport_s *rport; 181 struct list_head *qe, *qen; 182 183 bfa_trc(port->fcs, port->port_cfg.pwwn); 184 bfa_trc(port->fcs, event); 185 186 switch (event) { 187 case BFA_FCS_PORT_SM_ONLINE: 188 bfa_sm_set_state(port, bfa_fcs_lport_sm_online); 189 bfa_fcs_lport_online_actions(port); 190 break; 191 192 case BFA_FCS_PORT_SM_DELETE: 193 if (port->num_rports == 0) { 194 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); 195 bfa_fcs_lport_deleted(port); 196 } else { 197 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting); 198 list_for_each_safe(qe, qen, &port->rport_q) { 199 rport = (struct bfa_fcs_rport_s *) qe; 200 bfa_fcs_rport_delete(rport); 201 } 202 } 203 break; 204 205 case BFA_FCS_PORT_SM_DELRPORT: 206 case BFA_FCS_PORT_SM_OFFLINE: 207 break; 208 209 default: 210 bfa_sm_fault(port->fcs, event); 211 } 212 } 213 214 static void 215 bfa_fcs_lport_sm_deleting( 216 struct bfa_fcs_lport_s *port, 217 enum bfa_fcs_lport_event event) 218 { 219 bfa_trc(port->fcs, port->port_cfg.pwwn); 220 bfa_trc(port->fcs, event); 221 222 switch (event) { 223 case BFA_FCS_PORT_SM_DELRPORT: 224 if (port->num_rports == 0) { 225 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); 226 bfa_fcs_lport_deleted(port); 227 } 228 break; 229 230 default: 231 bfa_sm_fault(port->fcs, event); 232 } 233 } 234 235 /* 236 * fcs_port_pvt 237 */ 238 239 /* 240 * Send a LS reject 241 */ 242 static void 243 bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, 244 u8 reason_code, u8 reason_code_expl) 245 { 246 struct fchs_s fchs; 247 struct bfa_fcxp_s *fcxp; 248 struct bfa_rport_s *bfa_rport = NULL; 249 int len; 250 251 bfa_trc(port->fcs, rx_fchs->d_id); 252 bfa_trc(port->fcs, rx_fchs->s_id); 253 254 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 255 if (!fcxp) 256 return; 257 258 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 259 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 260 rx_fchs->ox_id, reason_code, reason_code_expl); 261 262 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 263 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 264 FC_MAX_PDUSZ, 0); 265 } 266 267 /* 268 * Process incoming plogi from a remote port. 269 */ 270 static void 271 bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, 272 struct fchs_s *rx_fchs, struct fc_logi_s *plogi) 273 { 274 struct bfa_fcs_rport_s *rport; 275 276 bfa_trc(port->fcs, rx_fchs->d_id); 277 bfa_trc(port->fcs, rx_fchs->s_id); 278 279 /* 280 * If min cfg mode is enabled, drop any incoming PLOGIs 281 */ 282 if (__fcs_min_cfg(port->fcs)) { 283 bfa_trc(port->fcs, rx_fchs->s_id); 284 return; 285 } 286 287 if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) { 288 bfa_trc(port->fcs, rx_fchs->s_id); 289 /* 290 * send a LS reject 291 */ 292 bfa_fcs_lport_send_ls_rjt(port, rx_fchs, 293 FC_LS_RJT_RSN_PROTOCOL_ERROR, 294 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS); 295 return; 296 } 297 298 /* 299 * Direct Attach P2P mode : verify address assigned by the r-port. 300 */ 301 if ((!bfa_fcs_fabric_is_switched(port->fabric)) && 302 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port), 303 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) { 304 if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) { 305 /* Address assigned to us cannot be a WKA */ 306 bfa_fcs_lport_send_ls_rjt(port, rx_fchs, 307 FC_LS_RJT_RSN_PROTOCOL_ERROR, 308 FC_LS_RJT_EXP_INVALID_NPORT_ID); 309 return; 310 } 311 port->pid = rx_fchs->d_id; 312 } 313 314 /* 315 * First, check if we know the device by pwwn. 316 */ 317 rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name); 318 if (rport) { 319 /* 320 * Direct Attach P2P mode : handle address assigned by r-port. 321 */ 322 if ((!bfa_fcs_fabric_is_switched(port->fabric)) && 323 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port), 324 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) { 325 port->pid = rx_fchs->d_id; 326 rport->pid = rx_fchs->s_id; 327 } 328 bfa_fcs_rport_plogi(rport, rx_fchs, plogi); 329 return; 330 } 331 332 /* 333 * Next, lookup rport by PID. 334 */ 335 rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id); 336 if (!rport) { 337 /* 338 * Inbound PLOGI from a new device. 339 */ 340 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); 341 return; 342 } 343 344 /* 345 * Rport is known only by PID. 346 */ 347 if (rport->pwwn) { 348 /* 349 * This is a different device with the same pid. Old device 350 * disappeared. Send implicit LOGO to old device. 351 */ 352 bfa_assert(rport->pwwn != plogi->port_name); 353 bfa_fcs_rport_logo_imp(rport); 354 355 /* 356 * Inbound PLOGI from a new device (with old PID). 357 */ 358 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); 359 return; 360 } 361 362 /* 363 * PLOGI crossing each other. 364 */ 365 bfa_assert(rport->pwwn == WWN_NULL); 366 bfa_fcs_rport_plogi(rport, rx_fchs, plogi); 367 } 368 369 /* 370 * Process incoming ECHO. 371 * Since it does not require a login, it is processed here. 372 */ 373 static void 374 bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, 375 struct fc_echo_s *echo, u16 rx_len) 376 { 377 struct fchs_s fchs; 378 struct bfa_fcxp_s *fcxp; 379 struct bfa_rport_s *bfa_rport = NULL; 380 int len, pyld_len; 381 382 bfa_trc(port->fcs, rx_fchs->s_id); 383 bfa_trc(port->fcs, rx_fchs->d_id); 384 385 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 386 if (!fcxp) 387 return; 388 389 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 390 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 391 rx_fchs->ox_id); 392 393 /* 394 * Copy the payload (if any) from the echo frame 395 */ 396 pyld_len = rx_len - sizeof(struct fchs_s); 397 bfa_trc(port->fcs, rx_len); 398 bfa_trc(port->fcs, pyld_len); 399 400 if (pyld_len > len) 401 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) + 402 sizeof(struct fc_echo_s), (echo + 1), 403 (pyld_len - sizeof(struct fc_echo_s))); 404 405 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 406 BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL, 407 FC_MAX_PDUSZ, 0); 408 } 409 410 /* 411 * Process incoming RNID. 412 * Since it does not require a login, it is processed here. 413 */ 414 static void 415 bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, 416 struct fc_rnid_cmd_s *rnid, u16 rx_len) 417 { 418 struct fc_rnid_common_id_data_s common_id_data; 419 struct fc_rnid_general_topology_data_s gen_topo_data; 420 struct fchs_s fchs; 421 struct bfa_fcxp_s *fcxp; 422 struct bfa_rport_s *bfa_rport = NULL; 423 u16 len; 424 u32 data_format; 425 426 bfa_trc(port->fcs, rx_fchs->s_id); 427 bfa_trc(port->fcs, rx_fchs->d_id); 428 bfa_trc(port->fcs, rx_len); 429 430 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 431 if (!fcxp) 432 return; 433 434 /* 435 * Check Node Indentification Data Format 436 * We only support General Topology Discovery Format. 437 * For any other requested Data Formats, we return Common Node Id Data 438 * only, as per FC-LS. 439 */ 440 bfa_trc(port->fcs, rnid->node_id_data_format); 441 if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) { 442 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY; 443 /* 444 * Get General topology data for this port 445 */ 446 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data); 447 } else { 448 data_format = RNID_NODEID_DATA_FORMAT_COMMON; 449 } 450 451 /* 452 * Copy the Node Id Info 453 */ 454 common_id_data.port_name = bfa_fcs_lport_get_pwwn(port); 455 common_id_data.node_name = bfa_fcs_lport_get_nwwn(port); 456 457 len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 458 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 459 rx_fchs->ox_id, data_format, &common_id_data, 460 &gen_topo_data); 461 462 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 463 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 464 FC_MAX_PDUSZ, 0); 465 } 466 467 /* 468 * Fill out General Topolpgy Discovery Data for RNID ELS. 469 */ 470 static void 471 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port, 472 struct fc_rnid_general_topology_data_s *gen_topo_data) 473 { 474 memset(gen_topo_data, 0, 475 sizeof(struct fc_rnid_general_topology_data_s)); 476 477 gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST); 478 gen_topo_data->phy_port_num = 0; /* @todo */ 479 gen_topo_data->num_attached_nodes = cpu_to_be32(1); 480 } 481 482 static void 483 bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port) 484 { 485 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; 486 char lpwwn_buf[BFA_STRING_32]; 487 488 bfa_trc(port->fcs, port->fabric->oper_type); 489 490 __port_action[port->fabric->fab_type].init(port); 491 __port_action[port->fabric->fab_type].online(port); 492 493 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); 494 BFA_LOG(KERN_INFO, bfad, bfa_log_level, 495 "Logical port online: WWN = %s Role = %s\n", 496 lpwwn_buf, "Initiator"); 497 498 bfad->bfad_flags |= BFAD_PORT_ONLINE; 499 } 500 501 static void 502 bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port) 503 { 504 struct list_head *qe, *qen; 505 struct bfa_fcs_rport_s *rport; 506 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; 507 char lpwwn_buf[BFA_STRING_32]; 508 509 bfa_trc(port->fcs, port->fabric->oper_type); 510 511 __port_action[port->fabric->fab_type].offline(port); 512 513 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); 514 if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) 515 BFA_LOG(KERN_ERR, bfad, bfa_log_level, 516 "Logical port lost fabric connectivity: WWN = %s Role = %s\n", 517 lpwwn_buf, "Initiator"); 518 else 519 BFA_LOG(KERN_INFO, bfad, bfa_log_level, 520 "Logical port taken offline: WWN = %s Role = %s\n", 521 lpwwn_buf, "Initiator"); 522 523 list_for_each_safe(qe, qen, &port->rport_q) { 524 rport = (struct bfa_fcs_rport_s *) qe; 525 bfa_fcs_rport_offline(rport); 526 } 527 } 528 529 static void 530 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port) 531 { 532 bfa_assert(0); 533 } 534 535 static void 536 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port) 537 { 538 bfa_assert(0); 539 } 540 541 static void 542 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port) 543 { 544 bfa_assert(0); 545 } 546 547 static void 548 bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs) 549 { 550 struct fchs_s fchs; 551 struct bfa_fcxp_s *fcxp; 552 int len; 553 554 bfa_trc(port->fcs, rx_fchs->d_id); 555 bfa_trc(port->fcs, rx_fchs->s_id); 556 557 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 558 if (!fcxp) 559 return; 560 561 len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 562 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 563 rx_fchs->ox_id, 0); 564 565 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, 566 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 567 FC_MAX_PDUSZ, 0); 568 } 569 static void 570 bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port) 571 { 572 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; 573 char lpwwn_buf[BFA_STRING_32]; 574 575 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); 576 BFA_LOG(KERN_INFO, bfad, bfa_log_level, 577 "Logical port deleted: WWN = %s Role = %s\n", 578 lpwwn_buf, "Initiator"); 579 580 /* Base port will be deleted by the OS driver */ 581 if (port->vport) { 582 bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles, 583 port->fabric->vf_drv, 584 port->vport ? port->vport->vport_drv : NULL); 585 bfa_fcs_vport_delete_comp(port->vport); 586 } else { 587 bfa_fcs_fabric_port_delete_comp(port->fabric); 588 } 589 } 590 591 592 593 /* 594 * fcs_lport_api BFA FCS port API 595 */ 596 /* 597 * Module initialization 598 */ 599 void 600 bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs) 601 { 602 603 } 604 605 /* 606 * Module cleanup 607 */ 608 void 609 bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs) 610 { 611 bfa_fcs_modexit_comp(fcs); 612 } 613 614 /* 615 * Unsolicited frame receive handling. 616 */ 617 void 618 bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport, 619 struct fchs_s *fchs, u16 len) 620 { 621 u32 pid = fchs->s_id; 622 struct bfa_fcs_rport_s *rport = NULL; 623 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); 624 625 bfa_stats(lport, uf_recvs); 626 627 if (!bfa_fcs_lport_is_online(lport)) { 628 bfa_stats(lport, uf_recv_drops); 629 return; 630 } 631 632 /* 633 * First, handle ELSs that donot require a login. 634 */ 635 /* 636 * Handle PLOGI first 637 */ 638 if ((fchs->type == FC_TYPE_ELS) && 639 (els_cmd->els_code == FC_ELS_PLOGI)) { 640 bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd); 641 return; 642 } 643 644 /* 645 * Handle ECHO separately. 646 */ 647 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) { 648 bfa_fcs_lport_echo(lport, fchs, 649 (struct fc_echo_s *)els_cmd, len); 650 return; 651 } 652 653 /* 654 * Handle RNID separately. 655 */ 656 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) { 657 bfa_fcs_lport_rnid(lport, fchs, 658 (struct fc_rnid_cmd_s *) els_cmd, len); 659 return; 660 } 661 662 if (fchs->type == FC_TYPE_BLS) { 663 if ((fchs->routing == FC_RTG_BASIC_LINK) && 664 (fchs->cat_info == FC_CAT_ABTS)) 665 bfa_fcs_lport_abts_acc(lport, fchs); 666 return; 667 } 668 /* 669 * look for a matching remote port ID 670 */ 671 rport = bfa_fcs_lport_get_rport_by_pid(lport, pid); 672 if (rport) { 673 bfa_trc(rport->fcs, fchs->s_id); 674 bfa_trc(rport->fcs, fchs->d_id); 675 bfa_trc(rport->fcs, fchs->type); 676 677 bfa_fcs_rport_uf_recv(rport, fchs, len); 678 return; 679 } 680 681 /* 682 * Only handles ELS frames for now. 683 */ 684 if (fchs->type != FC_TYPE_ELS) { 685 bfa_trc(lport->fcs, fchs->type); 686 bfa_assert(0); 687 return; 688 } 689 690 bfa_trc(lport->fcs, els_cmd->els_code); 691 if (els_cmd->els_code == FC_ELS_RSCN) { 692 bfa_fcs_lport_scn_process_rscn(lport, fchs, len); 693 return; 694 } 695 696 if (els_cmd->els_code == FC_ELS_LOGO) { 697 /* 698 * @todo Handle LOGO frames received. 699 */ 700 return; 701 } 702 703 if (els_cmd->els_code == FC_ELS_PRLI) { 704 /* 705 * @todo Handle PRLI frames received. 706 */ 707 return; 708 } 709 710 /* 711 * Unhandled ELS frames. Send a LS_RJT. 712 */ 713 bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP, 714 FC_LS_RJT_EXP_NO_ADDL_INFO); 715 716 } 717 718 /* 719 * PID based Lookup for a R-Port in the Port R-Port Queue 720 */ 721 struct bfa_fcs_rport_s * 722 bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid) 723 { 724 struct bfa_fcs_rport_s *rport; 725 struct list_head *qe; 726 727 list_for_each(qe, &port->rport_q) { 728 rport = (struct bfa_fcs_rport_s *) qe; 729 if (rport->pid == pid) 730 return rport; 731 } 732 733 bfa_trc(port->fcs, pid); 734 return NULL; 735 } 736 737 /* 738 * PWWN based Lookup for a R-Port in the Port R-Port Queue 739 */ 740 struct bfa_fcs_rport_s * 741 bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn) 742 { 743 struct bfa_fcs_rport_s *rport; 744 struct list_head *qe; 745 746 list_for_each(qe, &port->rport_q) { 747 rport = (struct bfa_fcs_rport_s *) qe; 748 if (wwn_is_equal(rport->pwwn, pwwn)) 749 return rport; 750 } 751 752 bfa_trc(port->fcs, pwwn); 753 return NULL; 754 } 755 756 /* 757 * NWWN based Lookup for a R-Port in the Port R-Port Queue 758 */ 759 struct bfa_fcs_rport_s * 760 bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn) 761 { 762 struct bfa_fcs_rport_s *rport; 763 struct list_head *qe; 764 765 list_for_each(qe, &port->rport_q) { 766 rport = (struct bfa_fcs_rport_s *) qe; 767 if (wwn_is_equal(rport->nwwn, nwwn)) 768 return rport; 769 } 770 771 bfa_trc(port->fcs, nwwn); 772 return NULL; 773 } 774 775 /* 776 * Called by rport module when new rports are discovered. 777 */ 778 void 779 bfa_fcs_lport_add_rport( 780 struct bfa_fcs_lport_s *port, 781 struct bfa_fcs_rport_s *rport) 782 { 783 list_add_tail(&rport->qe, &port->rport_q); 784 port->num_rports++; 785 } 786 787 /* 788 * Called by rport module to when rports are deleted. 789 */ 790 void 791 bfa_fcs_lport_del_rport( 792 struct bfa_fcs_lport_s *port, 793 struct bfa_fcs_rport_s *rport) 794 { 795 bfa_assert(bfa_q_is_on_q(&port->rport_q, rport)); 796 list_del(&rport->qe); 797 port->num_rports--; 798 799 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT); 800 } 801 802 /* 803 * Called by fabric for base port when fabric login is complete. 804 * Called by vport for virtual ports when FDISC is complete. 805 */ 806 void 807 bfa_fcs_lport_online(struct bfa_fcs_lport_s *port) 808 { 809 bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE); 810 } 811 812 /* 813 * Called by fabric for base port when fabric goes offline. 814 * Called by vport for virtual ports when virtual port becomes offline. 815 */ 816 void 817 bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port) 818 { 819 bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE); 820 } 821 822 /* 823 * Called by fabric to delete base lport and associated resources. 824 * 825 * Called by vport to delete lport and associated resources. Should call 826 * bfa_fcs_vport_delete_comp() for vports on completion. 827 */ 828 void 829 bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port) 830 { 831 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE); 832 } 833 834 /* 835 * Return TRUE if port is online, else return FALSE 836 */ 837 bfa_boolean_t 838 bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port) 839 { 840 return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online); 841 } 842 843 /* 844 * Attach time initialization of logical ports. 845 */ 846 void 847 bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs, 848 u16 vf_id, struct bfa_fcs_vport_s *vport) 849 { 850 lport->fcs = fcs; 851 lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id); 852 lport->vport = vport; 853 lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) : 854 bfa_lps_get_tag(lport->fabric->lps); 855 856 INIT_LIST_HEAD(&lport->rport_q); 857 lport->num_rports = 0; 858 } 859 860 /* 861 * Logical port initialization of base or virtual port. 862 * Called by fabric for base port or by vport for virtual ports. 863 */ 864 865 void 866 bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport, 867 struct bfa_lport_cfg_s *port_cfg) 868 { 869 struct bfa_fcs_vport_s *vport = lport->vport; 870 struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad; 871 char lpwwn_buf[BFA_STRING_32]; 872 873 lport->port_cfg = *port_cfg; 874 875 lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport, 876 lport->port_cfg.roles, 877 lport->fabric->vf_drv, 878 vport ? vport->vport_drv : NULL); 879 880 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport)); 881 BFA_LOG(KERN_INFO, bfad, bfa_log_level, 882 "New logical port created: WWN = %s Role = %s\n", 883 lpwwn_buf, "Initiator"); 884 885 bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit); 886 bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE); 887 } 888 889 /* 890 * fcs_lport_api 891 */ 892 893 void 894 bfa_fcs_lport_get_attr( 895 struct bfa_fcs_lport_s *port, 896 struct bfa_lport_attr_s *port_attr) 897 { 898 if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online)) 899 port_attr->pid = port->pid; 900 else 901 port_attr->pid = 0; 902 903 port_attr->port_cfg = port->port_cfg; 904 905 if (port->fabric) { 906 port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric); 907 port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric); 908 port_attr->authfail = 909 bfa_fcs_fabric_is_auth_failed(port->fabric); 910 port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port); 911 memcpy(port_attr->fabric_ip_addr, 912 bfa_fcs_lport_get_fabric_ipaddr(port), 913 BFA_FCS_FABRIC_IPADDR_SZ); 914 915 if (port->vport != NULL) { 916 port_attr->port_type = BFA_PORT_TYPE_VPORT; 917 port_attr->fpma_mac = 918 bfa_lps_get_lp_mac(port->vport->lps); 919 } else { 920 port_attr->fpma_mac = 921 bfa_lps_get_lp_mac(port->fabric->lps); 922 } 923 } else { 924 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN; 925 port_attr->state = BFA_LPORT_UNINIT; 926 } 927 } 928 929 /* 930 * bfa_fcs_lport_fab port fab functions 931 */ 932 933 /* 934 * Called by port to initialize fabric services of the base port. 935 */ 936 static void 937 bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port) 938 { 939 bfa_fcs_lport_ns_init(port); 940 bfa_fcs_lport_scn_init(port); 941 bfa_fcs_lport_ms_init(port); 942 } 943 944 /* 945 * Called by port to notify transition to online state. 946 */ 947 static void 948 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port) 949 { 950 bfa_fcs_lport_ns_online(port); 951 bfa_fcs_lport_scn_online(port); 952 } 953 954 /* 955 * Called by port to notify transition to offline state. 956 */ 957 static void 958 bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port) 959 { 960 bfa_fcs_lport_ns_offline(port); 961 bfa_fcs_lport_scn_offline(port); 962 bfa_fcs_lport_ms_offline(port); 963 } 964 965 /* 966 * bfa_fcs_lport_n2n functions 967 */ 968 969 /* 970 * Called by fcs/port to initialize N2N topology. 971 */ 972 static void 973 bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port) 974 { 975 } 976 977 /* 978 * Called by fcs/port to notify transition to online state. 979 */ 980 static void 981 bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port) 982 { 983 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n; 984 struct bfa_lport_cfg_s *pcfg = &port->port_cfg; 985 struct bfa_fcs_rport_s *rport; 986 987 bfa_trc(port->fcs, pcfg->pwwn); 988 989 /* 990 * If our PWWN is > than that of the r-port, we have to initiate PLOGI 991 * and assign an Address. if not, we need to wait for its PLOGI. 992 * 993 * If our PWWN is < than that of the remote port, it will send a PLOGI 994 * with the PIDs assigned. The rport state machine take care of this 995 * incoming PLOGI. 996 */ 997 if (memcmp 998 ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn, 999 sizeof(wwn_t)) > 0) { 1000 port->pid = N2N_LOCAL_PID; 1001 /* 1002 * First, check if we know the device by pwwn. 1003 */ 1004 rport = bfa_fcs_lport_get_rport_by_pwwn(port, 1005 n2n_port->rem_port_wwn); 1006 if (rport) { 1007 bfa_trc(port->fcs, rport->pid); 1008 bfa_trc(port->fcs, rport->pwwn); 1009 rport->pid = N2N_REMOTE_PID; 1010 bfa_fcs_rport_online(rport); 1011 return; 1012 } 1013 1014 /* 1015 * In n2n there can be only one rport. Delete the old one 1016 * whose pid should be zero, because it is offline. 1017 */ 1018 if (port->num_rports > 0) { 1019 rport = bfa_fcs_lport_get_rport_by_pid(port, 0); 1020 bfa_assert(rport != NULL); 1021 if (rport) { 1022 bfa_trc(port->fcs, rport->pwwn); 1023 bfa_fcs_rport_delete(rport); 1024 } 1025 } 1026 bfa_fcs_rport_create(port, N2N_REMOTE_PID); 1027 } 1028 } 1029 1030 /* 1031 * Called by fcs/port to notify transition to offline state. 1032 */ 1033 static void 1034 bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port) 1035 { 1036 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n; 1037 1038 bfa_trc(port->fcs, port->pid); 1039 port->pid = 0; 1040 n2n_port->rem_port_wwn = 0; 1041 n2n_port->reply_oxid = 0; 1042 } 1043 1044 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2 1045 1046 /* 1047 * forward declarations 1048 */ 1049 static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, 1050 struct bfa_fcxp_s *fcxp_alloced); 1051 static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, 1052 struct bfa_fcxp_s *fcxp_alloced); 1053 static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, 1054 struct bfa_fcxp_s *fcxp_alloced); 1055 static void bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, 1056 struct bfa_fcxp_s *fcxp, 1057 void *cbarg, 1058 bfa_status_t req_status, 1059 u32 rsp_len, 1060 u32 resid_len, 1061 struct fchs_s *rsp_fchs); 1062 static void bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, 1063 struct bfa_fcxp_s *fcxp, 1064 void *cbarg, 1065 bfa_status_t req_status, 1066 u32 rsp_len, 1067 u32 resid_len, 1068 struct fchs_s *rsp_fchs); 1069 static void bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, 1070 struct bfa_fcxp_s *fcxp, 1071 void *cbarg, 1072 bfa_status_t req_status, 1073 u32 rsp_len, 1074 u32 resid_len, 1075 struct fchs_s *rsp_fchs); 1076 static void bfa_fcs_lport_fdmi_timeout(void *arg); 1077 static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, 1078 u8 *pyld); 1079 static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, 1080 u8 *pyld); 1081 static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, 1082 u8 *pyld); 1083 static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s * 1084 fdmi, u8 *pyld); 1085 static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, 1086 struct bfa_fcs_fdmi_hba_attr_s *hba_attr); 1087 static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, 1088 struct bfa_fcs_fdmi_port_attr_s *port_attr); 1089 /* 1090 * fcs_fdmi_sm FCS FDMI state machine 1091 */ 1092 1093 /* 1094 * FDMI State Machine events 1095 */ 1096 enum port_fdmi_event { 1097 FDMISM_EVENT_PORT_ONLINE = 1, 1098 FDMISM_EVENT_PORT_OFFLINE = 2, 1099 FDMISM_EVENT_RSP_OK = 4, 1100 FDMISM_EVENT_RSP_ERROR = 5, 1101 FDMISM_EVENT_TIMEOUT = 6, 1102 FDMISM_EVENT_RHBA_SENT = 7, 1103 FDMISM_EVENT_RPRT_SENT = 8, 1104 FDMISM_EVENT_RPA_SENT = 9, 1105 }; 1106 1107 static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi, 1108 enum port_fdmi_event event); 1109 static void bfa_fcs_lport_fdmi_sm_sending_rhba( 1110 struct bfa_fcs_lport_fdmi_s *fdmi, 1111 enum port_fdmi_event event); 1112 static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi, 1113 enum port_fdmi_event event); 1114 static void bfa_fcs_lport_fdmi_sm_rhba_retry( 1115 struct bfa_fcs_lport_fdmi_s *fdmi, 1116 enum port_fdmi_event event); 1117 static void bfa_fcs_lport_fdmi_sm_sending_rprt( 1118 struct bfa_fcs_lport_fdmi_s *fdmi, 1119 enum port_fdmi_event event); 1120 static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi, 1121 enum port_fdmi_event event); 1122 static void bfa_fcs_lport_fdmi_sm_rprt_retry( 1123 struct bfa_fcs_lport_fdmi_s *fdmi, 1124 enum port_fdmi_event event); 1125 static void bfa_fcs_lport_fdmi_sm_sending_rpa( 1126 struct bfa_fcs_lport_fdmi_s *fdmi, 1127 enum port_fdmi_event event); 1128 static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi, 1129 enum port_fdmi_event event); 1130 static void bfa_fcs_lport_fdmi_sm_rpa_retry( 1131 struct bfa_fcs_lport_fdmi_s *fdmi, 1132 enum port_fdmi_event event); 1133 static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi, 1134 enum port_fdmi_event event); 1135 static void bfa_fcs_lport_fdmi_sm_disabled( 1136 struct bfa_fcs_lport_fdmi_s *fdmi, 1137 enum port_fdmi_event event); 1138 /* 1139 * Start in offline state - awaiting MS to send start. 1140 */ 1141 static void 1142 bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi, 1143 enum port_fdmi_event event) 1144 { 1145 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1146 1147 bfa_trc(port->fcs, port->port_cfg.pwwn); 1148 bfa_trc(port->fcs, event); 1149 1150 fdmi->retry_cnt = 0; 1151 1152 switch (event) { 1153 case FDMISM_EVENT_PORT_ONLINE: 1154 if (port->vport) { 1155 /* 1156 * For Vports, register a new port. 1157 */ 1158 bfa_sm_set_state(fdmi, 1159 bfa_fcs_lport_fdmi_sm_sending_rprt); 1160 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL); 1161 } else { 1162 /* 1163 * For a base port, we should first register the HBA 1164 * atribute. The HBA attribute also contains the base 1165 * port registration. 1166 */ 1167 bfa_sm_set_state(fdmi, 1168 bfa_fcs_lport_fdmi_sm_sending_rhba); 1169 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL); 1170 } 1171 break; 1172 1173 case FDMISM_EVENT_PORT_OFFLINE: 1174 break; 1175 1176 default: 1177 bfa_sm_fault(port->fcs, event); 1178 } 1179 } 1180 1181 static void 1182 bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi, 1183 enum port_fdmi_event event) 1184 { 1185 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1186 1187 bfa_trc(port->fcs, port->port_cfg.pwwn); 1188 bfa_trc(port->fcs, event); 1189 1190 switch (event) { 1191 case FDMISM_EVENT_RHBA_SENT: 1192 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba); 1193 break; 1194 1195 case FDMISM_EVENT_PORT_OFFLINE: 1196 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1197 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), 1198 &fdmi->fcxp_wqe); 1199 break; 1200 1201 default: 1202 bfa_sm_fault(port->fcs, event); 1203 } 1204 } 1205 1206 static void 1207 bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi, 1208 enum port_fdmi_event event) 1209 { 1210 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1211 1212 bfa_trc(port->fcs, port->port_cfg.pwwn); 1213 bfa_trc(port->fcs, event); 1214 1215 switch (event) { 1216 case FDMISM_EVENT_RSP_ERROR: 1217 /* 1218 * if max retries have not been reached, start timer for a 1219 * delayed retry 1220 */ 1221 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { 1222 bfa_sm_set_state(fdmi, 1223 bfa_fcs_lport_fdmi_sm_rhba_retry); 1224 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), 1225 &fdmi->timer, 1226 bfa_fcs_lport_fdmi_timeout, fdmi, 1227 BFA_FCS_RETRY_TIMEOUT); 1228 } else { 1229 /* 1230 * set state to offline 1231 */ 1232 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1233 } 1234 break; 1235 1236 case FDMISM_EVENT_RSP_OK: 1237 /* 1238 * Initiate Register Port Attributes 1239 */ 1240 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa); 1241 fdmi->retry_cnt = 0; 1242 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL); 1243 break; 1244 1245 case FDMISM_EVENT_PORT_OFFLINE: 1246 bfa_fcxp_discard(fdmi->fcxp); 1247 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1248 break; 1249 1250 default: 1251 bfa_sm_fault(port->fcs, event); 1252 } 1253 } 1254 1255 static void 1256 bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi, 1257 enum port_fdmi_event event) 1258 { 1259 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1260 1261 bfa_trc(port->fcs, port->port_cfg.pwwn); 1262 bfa_trc(port->fcs, event); 1263 1264 switch (event) { 1265 case FDMISM_EVENT_TIMEOUT: 1266 /* 1267 * Retry Timer Expired. Re-send 1268 */ 1269 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba); 1270 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL); 1271 break; 1272 1273 case FDMISM_EVENT_PORT_OFFLINE: 1274 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1275 bfa_timer_stop(&fdmi->timer); 1276 break; 1277 1278 default: 1279 bfa_sm_fault(port->fcs, event); 1280 } 1281 } 1282 1283 /* 1284 * RPRT : Register Port 1285 */ 1286 static void 1287 bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi, 1288 enum port_fdmi_event event) 1289 { 1290 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1291 1292 bfa_trc(port->fcs, port->port_cfg.pwwn); 1293 bfa_trc(port->fcs, event); 1294 1295 switch (event) { 1296 case FDMISM_EVENT_RPRT_SENT: 1297 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt); 1298 break; 1299 1300 case FDMISM_EVENT_PORT_OFFLINE: 1301 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1302 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), 1303 &fdmi->fcxp_wqe); 1304 break; 1305 1306 default: 1307 bfa_sm_fault(port->fcs, event); 1308 } 1309 } 1310 1311 static void 1312 bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi, 1313 enum port_fdmi_event event) 1314 { 1315 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1316 1317 bfa_trc(port->fcs, port->port_cfg.pwwn); 1318 bfa_trc(port->fcs, event); 1319 1320 switch (event) { 1321 case FDMISM_EVENT_RSP_ERROR: 1322 /* 1323 * if max retries have not been reached, start timer for a 1324 * delayed retry 1325 */ 1326 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { 1327 bfa_sm_set_state(fdmi, 1328 bfa_fcs_lport_fdmi_sm_rprt_retry); 1329 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), 1330 &fdmi->timer, 1331 bfa_fcs_lport_fdmi_timeout, fdmi, 1332 BFA_FCS_RETRY_TIMEOUT); 1333 1334 } else { 1335 /* 1336 * set state to offline 1337 */ 1338 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1339 fdmi->retry_cnt = 0; 1340 } 1341 break; 1342 1343 case FDMISM_EVENT_RSP_OK: 1344 fdmi->retry_cnt = 0; 1345 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online); 1346 break; 1347 1348 case FDMISM_EVENT_PORT_OFFLINE: 1349 bfa_fcxp_discard(fdmi->fcxp); 1350 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1351 break; 1352 1353 default: 1354 bfa_sm_fault(port->fcs, event); 1355 } 1356 } 1357 1358 static void 1359 bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi, 1360 enum port_fdmi_event event) 1361 { 1362 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1363 1364 bfa_trc(port->fcs, port->port_cfg.pwwn); 1365 bfa_trc(port->fcs, event); 1366 1367 switch (event) { 1368 case FDMISM_EVENT_TIMEOUT: 1369 /* 1370 * Retry Timer Expired. Re-send 1371 */ 1372 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt); 1373 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL); 1374 break; 1375 1376 case FDMISM_EVENT_PORT_OFFLINE: 1377 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1378 bfa_timer_stop(&fdmi->timer); 1379 break; 1380 1381 default: 1382 bfa_sm_fault(port->fcs, event); 1383 } 1384 } 1385 1386 /* 1387 * Register Port Attributes 1388 */ 1389 static void 1390 bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi, 1391 enum port_fdmi_event event) 1392 { 1393 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1394 1395 bfa_trc(port->fcs, port->port_cfg.pwwn); 1396 bfa_trc(port->fcs, event); 1397 1398 switch (event) { 1399 case FDMISM_EVENT_RPA_SENT: 1400 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa); 1401 break; 1402 1403 case FDMISM_EVENT_PORT_OFFLINE: 1404 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1405 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), 1406 &fdmi->fcxp_wqe); 1407 break; 1408 1409 default: 1410 bfa_sm_fault(port->fcs, event); 1411 } 1412 } 1413 1414 static void 1415 bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi, 1416 enum port_fdmi_event event) 1417 { 1418 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1419 1420 bfa_trc(port->fcs, port->port_cfg.pwwn); 1421 bfa_trc(port->fcs, event); 1422 1423 switch (event) { 1424 case FDMISM_EVENT_RSP_ERROR: 1425 /* 1426 * if max retries have not been reached, start timer for a 1427 * delayed retry 1428 */ 1429 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { 1430 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry); 1431 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), 1432 &fdmi->timer, 1433 bfa_fcs_lport_fdmi_timeout, fdmi, 1434 BFA_FCS_RETRY_TIMEOUT); 1435 } else { 1436 /* 1437 * set state to offline 1438 */ 1439 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1440 fdmi->retry_cnt = 0; 1441 } 1442 break; 1443 1444 case FDMISM_EVENT_RSP_OK: 1445 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online); 1446 fdmi->retry_cnt = 0; 1447 break; 1448 1449 case FDMISM_EVENT_PORT_OFFLINE: 1450 bfa_fcxp_discard(fdmi->fcxp); 1451 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1452 break; 1453 1454 default: 1455 bfa_sm_fault(port->fcs, event); 1456 } 1457 } 1458 1459 static void 1460 bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi, 1461 enum port_fdmi_event event) 1462 { 1463 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1464 1465 bfa_trc(port->fcs, port->port_cfg.pwwn); 1466 bfa_trc(port->fcs, event); 1467 1468 switch (event) { 1469 case FDMISM_EVENT_TIMEOUT: 1470 /* 1471 * Retry Timer Expired. Re-send 1472 */ 1473 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa); 1474 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL); 1475 break; 1476 1477 case FDMISM_EVENT_PORT_OFFLINE: 1478 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1479 bfa_timer_stop(&fdmi->timer); 1480 break; 1481 1482 default: 1483 bfa_sm_fault(port->fcs, event); 1484 } 1485 } 1486 1487 static void 1488 bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi, 1489 enum port_fdmi_event event) 1490 { 1491 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1492 1493 bfa_trc(port->fcs, port->port_cfg.pwwn); 1494 bfa_trc(port->fcs, event); 1495 1496 switch (event) { 1497 case FDMISM_EVENT_PORT_OFFLINE: 1498 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1499 break; 1500 1501 default: 1502 bfa_sm_fault(port->fcs, event); 1503 } 1504 } 1505 /* 1506 * FDMI is disabled state. 1507 */ 1508 static void 1509 bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi, 1510 enum port_fdmi_event event) 1511 { 1512 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1513 1514 bfa_trc(port->fcs, port->port_cfg.pwwn); 1515 bfa_trc(port->fcs, event); 1516 1517 /* No op State. It can only be enabled at Driver Init. */ 1518 } 1519 1520 /* 1521 * RHBA : Register HBA Attributes. 1522 */ 1523 static void 1524 bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) 1525 { 1526 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg; 1527 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1528 struct fchs_s fchs; 1529 int len, attr_len; 1530 struct bfa_fcxp_s *fcxp; 1531 u8 *pyld; 1532 1533 bfa_trc(port->fcs, port->port_cfg.pwwn); 1534 1535 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1536 if (!fcxp) { 1537 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, 1538 bfa_fcs_lport_fdmi_send_rhba, fdmi); 1539 return; 1540 } 1541 fdmi->fcxp = fcxp; 1542 1543 pyld = bfa_fcxp_get_reqbuf(fcxp); 1544 memset(pyld, 0, FC_MAX_PDUSZ); 1545 1546 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port), 1547 FDMI_RHBA); 1548 1549 attr_len = 1550 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi, 1551 (u8 *) ((struct ct_hdr_s *) pyld 1552 + 1)); 1553 1554 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1555 FC_CLASS_3, (len + attr_len), &fchs, 1556 bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi, 1557 FC_MAX_PDUSZ, FC_FCCT_TOV); 1558 1559 bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT); 1560 } 1561 1562 static u16 1563 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) 1564 { 1565 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1566 struct bfa_fcs_fdmi_hba_attr_s hba_attr; 1567 struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr; 1568 struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld; 1569 struct fdmi_attr_s *attr; 1570 u8 *curr_ptr; 1571 u16 len, count; 1572 1573 /* 1574 * get hba attributes 1575 */ 1576 bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr); 1577 1578 rhba->hba_id = bfa_fcs_lport_get_pwwn(port); 1579 rhba->port_list.num_ports = cpu_to_be32(1); 1580 rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port); 1581 1582 len = sizeof(rhba->hba_id) + sizeof(rhba->port_list); 1583 1584 count = 0; 1585 len += sizeof(rhba->hba_attr_blk.attr_count); 1586 1587 /* 1588 * fill out the invididual entries of the HBA attrib Block 1589 */ 1590 curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr; 1591 1592 /* 1593 * Node Name 1594 */ 1595 attr = (struct fdmi_attr_s *) curr_ptr; 1596 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME); 1597 attr->len = sizeof(wwn_t); 1598 memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len); 1599 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1600 len += attr->len; 1601 count++; 1602 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1603 sizeof(attr->len)); 1604 1605 /* 1606 * Manufacturer 1607 */ 1608 attr = (struct fdmi_attr_s *) curr_ptr; 1609 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER); 1610 attr->len = (u16) strlen(fcs_hba_attr->manufacturer); 1611 memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len); 1612 attr->len = fc_roundup(attr->len, sizeof(u32)); 1613 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1614 len += attr->len; 1615 count++; 1616 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1617 sizeof(attr->len)); 1618 1619 /* 1620 * Serial Number 1621 */ 1622 attr = (struct fdmi_attr_s *) curr_ptr; 1623 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM); 1624 attr->len = (u16) strlen(fcs_hba_attr->serial_num); 1625 memcpy(attr->value, fcs_hba_attr->serial_num, attr->len); 1626 attr->len = fc_roundup(attr->len, sizeof(u32)); 1627 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1628 len += attr->len; 1629 count++; 1630 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1631 sizeof(attr->len)); 1632 1633 /* 1634 * Model 1635 */ 1636 attr = (struct fdmi_attr_s *) curr_ptr; 1637 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL); 1638 attr->len = (u16) strlen(fcs_hba_attr->model); 1639 memcpy(attr->value, fcs_hba_attr->model, attr->len); 1640 attr->len = fc_roundup(attr->len, sizeof(u32)); 1641 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1642 len += attr->len; 1643 count++; 1644 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1645 sizeof(attr->len)); 1646 1647 /* 1648 * Model Desc 1649 */ 1650 attr = (struct fdmi_attr_s *) curr_ptr; 1651 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC); 1652 attr->len = (u16) strlen(fcs_hba_attr->model_desc); 1653 memcpy(attr->value, fcs_hba_attr->model_desc, attr->len); 1654 attr->len = fc_roundup(attr->len, sizeof(u32)); 1655 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1656 len += attr->len; 1657 count++; 1658 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1659 sizeof(attr->len)); 1660 1661 /* 1662 * H/W Version 1663 */ 1664 if (fcs_hba_attr->hw_version[0] != '\0') { 1665 attr = (struct fdmi_attr_s *) curr_ptr; 1666 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION); 1667 attr->len = (u16) strlen(fcs_hba_attr->hw_version); 1668 memcpy(attr->value, fcs_hba_attr->hw_version, attr->len); 1669 attr->len = fc_roundup(attr->len, sizeof(u32)); 1670 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1671 len += attr->len; 1672 count++; 1673 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1674 sizeof(attr->len)); 1675 } 1676 1677 /* 1678 * Driver Version 1679 */ 1680 attr = (struct fdmi_attr_s *) curr_ptr; 1681 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION); 1682 attr->len = (u16) strlen(fcs_hba_attr->driver_version); 1683 memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); 1684 attr->len = fc_roundup(attr->len, sizeof(u32)); 1685 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1686 len += attr->len;; 1687 count++; 1688 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1689 sizeof(attr->len)); 1690 1691 /* 1692 * Option Rom Version 1693 */ 1694 if (fcs_hba_attr->option_rom_ver[0] != '\0') { 1695 attr = (struct fdmi_attr_s *) curr_ptr; 1696 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION); 1697 attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver); 1698 memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len); 1699 attr->len = fc_roundup(attr->len, sizeof(u32)); 1700 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1701 len += attr->len; 1702 count++; 1703 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1704 sizeof(attr->len)); 1705 } 1706 1707 /* 1708 * f/w Version = driver version 1709 */ 1710 attr = (struct fdmi_attr_s *) curr_ptr; 1711 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION); 1712 attr->len = (u16) strlen(fcs_hba_attr->driver_version); 1713 memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); 1714 attr->len = fc_roundup(attr->len, sizeof(u32)); 1715 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1716 len += attr->len; 1717 count++; 1718 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1719 sizeof(attr->len)); 1720 1721 /* 1722 * OS Name 1723 */ 1724 if (fcs_hba_attr->os_name[0] != '\0') { 1725 attr = (struct fdmi_attr_s *) curr_ptr; 1726 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME); 1727 attr->len = (u16) strlen(fcs_hba_attr->os_name); 1728 memcpy(attr->value, fcs_hba_attr->os_name, attr->len); 1729 attr->len = fc_roundup(attr->len, sizeof(u32)); 1730 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1731 len += attr->len; 1732 count++; 1733 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1734 sizeof(attr->len)); 1735 } 1736 1737 /* 1738 * MAX_CT_PAYLOAD 1739 */ 1740 attr = (struct fdmi_attr_s *) curr_ptr; 1741 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT); 1742 attr->len = sizeof(fcs_hba_attr->max_ct_pyld); 1743 memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len); 1744 len += attr->len; 1745 count++; 1746 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1747 sizeof(attr->len)); 1748 1749 /* 1750 * Update size of payload 1751 */ 1752 len += ((sizeof(attr->type) + sizeof(attr->len)) * count); 1753 1754 rhba->hba_attr_blk.attr_count = cpu_to_be32(count); 1755 return len; 1756 } 1757 1758 static void 1759 bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 1760 void *cbarg, bfa_status_t req_status, 1761 u32 rsp_len, u32 resid_len, 1762 struct fchs_s *rsp_fchs) 1763 { 1764 struct bfa_fcs_lport_fdmi_s *fdmi = 1765 (struct bfa_fcs_lport_fdmi_s *) cbarg; 1766 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1767 struct ct_hdr_s *cthdr = NULL; 1768 1769 bfa_trc(port->fcs, port->port_cfg.pwwn); 1770 1771 /* 1772 * Sanity Checks 1773 */ 1774 if (req_status != BFA_STATUS_OK) { 1775 bfa_trc(port->fcs, req_status); 1776 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); 1777 return; 1778 } 1779 1780 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 1781 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 1782 1783 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 1784 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); 1785 return; 1786 } 1787 1788 bfa_trc(port->fcs, cthdr->reason_code); 1789 bfa_trc(port->fcs, cthdr->exp_code); 1790 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); 1791 } 1792 1793 /* 1794 * RPRT : Register Port 1795 */ 1796 static void 1797 bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) 1798 { 1799 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg; 1800 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1801 struct fchs_s fchs; 1802 u16 len, attr_len; 1803 struct bfa_fcxp_s *fcxp; 1804 u8 *pyld; 1805 1806 bfa_trc(port->fcs, port->port_cfg.pwwn); 1807 1808 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1809 if (!fcxp) { 1810 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, 1811 bfa_fcs_lport_fdmi_send_rprt, fdmi); 1812 return; 1813 } 1814 fdmi->fcxp = fcxp; 1815 1816 pyld = bfa_fcxp_get_reqbuf(fcxp); 1817 memset(pyld, 0, FC_MAX_PDUSZ); 1818 1819 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port), 1820 FDMI_RPRT); 1821 1822 attr_len = 1823 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi, 1824 (u8 *) ((struct ct_hdr_s *) pyld 1825 + 1)); 1826 1827 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1828 FC_CLASS_3, len + attr_len, &fchs, 1829 bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi, 1830 FC_MAX_PDUSZ, FC_FCCT_TOV); 1831 1832 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT); 1833 } 1834 1835 /* 1836 * This routine builds Port Attribute Block that used in RPA, RPRT commands. 1837 */ 1838 static u16 1839 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi, 1840 u8 *pyld) 1841 { 1842 struct bfa_fcs_fdmi_port_attr_s fcs_port_attr; 1843 struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld; 1844 struct fdmi_attr_s *attr; 1845 u8 *curr_ptr; 1846 u16 len; 1847 u8 count = 0; 1848 1849 /* 1850 * get port attributes 1851 */ 1852 bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); 1853 1854 len = sizeof(port_attrib->attr_count); 1855 1856 /* 1857 * fill out the invididual entries 1858 */ 1859 curr_ptr = (u8 *) &port_attrib->port_attr; 1860 1861 /* 1862 * FC4 Types 1863 */ 1864 attr = (struct fdmi_attr_s *) curr_ptr; 1865 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES); 1866 attr->len = sizeof(fcs_port_attr.supp_fc4_types); 1867 memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len); 1868 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1869 len += attr->len; 1870 ++count; 1871 attr->len = 1872 cpu_to_be16(attr->len + sizeof(attr->type) + 1873 sizeof(attr->len)); 1874 1875 /* 1876 * Supported Speed 1877 */ 1878 attr = (struct fdmi_attr_s *) curr_ptr; 1879 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED); 1880 attr->len = sizeof(fcs_port_attr.supp_speed); 1881 memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len); 1882 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1883 len += attr->len; 1884 ++count; 1885 attr->len = 1886 cpu_to_be16(attr->len + sizeof(attr->type) + 1887 sizeof(attr->len)); 1888 1889 /* 1890 * current Port Speed 1891 */ 1892 attr = (struct fdmi_attr_s *) curr_ptr; 1893 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED); 1894 attr->len = sizeof(fcs_port_attr.curr_speed); 1895 memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len); 1896 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1897 len += attr->len; 1898 ++count; 1899 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1900 sizeof(attr->len)); 1901 1902 /* 1903 * max frame size 1904 */ 1905 attr = (struct fdmi_attr_s *) curr_ptr; 1906 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE); 1907 attr->len = sizeof(fcs_port_attr.max_frm_size); 1908 memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len); 1909 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1910 len += attr->len; 1911 ++count; 1912 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1913 sizeof(attr->len)); 1914 1915 /* 1916 * OS Device Name 1917 */ 1918 if (fcs_port_attr.os_device_name[0] != '\0') { 1919 attr = (struct fdmi_attr_s *) curr_ptr; 1920 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME); 1921 attr->len = (u16) strlen(fcs_port_attr.os_device_name); 1922 memcpy(attr->value, fcs_port_attr.os_device_name, attr->len); 1923 attr->len = fc_roundup(attr->len, sizeof(u32)); 1924 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1925 len += attr->len; 1926 ++count; 1927 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1928 sizeof(attr->len)); 1929 } 1930 /* 1931 * Host Name 1932 */ 1933 if (fcs_port_attr.host_name[0] != '\0') { 1934 attr = (struct fdmi_attr_s *) curr_ptr; 1935 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME); 1936 attr->len = (u16) strlen(fcs_port_attr.host_name); 1937 memcpy(attr->value, fcs_port_attr.host_name, attr->len); 1938 attr->len = fc_roundup(attr->len, sizeof(u32)); 1939 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; 1940 len += attr->len; 1941 ++count; 1942 attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + 1943 sizeof(attr->len)); 1944 } 1945 1946 /* 1947 * Update size of payload 1948 */ 1949 port_attrib->attr_count = cpu_to_be32(count); 1950 len += ((sizeof(attr->type) + sizeof(attr->len)) * count); 1951 return len; 1952 } 1953 1954 static u16 1955 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) 1956 { 1957 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1958 struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld; 1959 u16 len; 1960 1961 rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs)); 1962 rprt->port_name = bfa_fcs_lport_get_pwwn(port); 1963 1964 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi, 1965 (u8 *) &rprt->port_attr_blk); 1966 1967 len += sizeof(rprt->hba_id) + sizeof(rprt->port_name); 1968 1969 return len; 1970 } 1971 1972 static void 1973 bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 1974 void *cbarg, bfa_status_t req_status, 1975 u32 rsp_len, u32 resid_len, 1976 struct fchs_s *rsp_fchs) 1977 { 1978 struct bfa_fcs_lport_fdmi_s *fdmi = 1979 (struct bfa_fcs_lport_fdmi_s *) cbarg; 1980 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1981 struct ct_hdr_s *cthdr = NULL; 1982 1983 bfa_trc(port->fcs, port->port_cfg.pwwn); 1984 1985 /* 1986 * Sanity Checks 1987 */ 1988 if (req_status != BFA_STATUS_OK) { 1989 bfa_trc(port->fcs, req_status); 1990 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); 1991 return; 1992 } 1993 1994 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 1995 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 1996 1997 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 1998 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); 1999 return; 2000 } 2001 2002 bfa_trc(port->fcs, cthdr->reason_code); 2003 bfa_trc(port->fcs, cthdr->exp_code); 2004 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); 2005 } 2006 2007 /* 2008 * RPA : Register Port Attributes. 2009 */ 2010 static void 2011 bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) 2012 { 2013 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg; 2014 struct bfa_fcs_lport_s *port = fdmi->ms->port; 2015 struct fchs_s fchs; 2016 u16 len, attr_len; 2017 struct bfa_fcxp_s *fcxp; 2018 u8 *pyld; 2019 2020 bfa_trc(port->fcs, port->port_cfg.pwwn); 2021 2022 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 2023 if (!fcxp) { 2024 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, 2025 bfa_fcs_lport_fdmi_send_rpa, fdmi); 2026 return; 2027 } 2028 fdmi->fcxp = fcxp; 2029 2030 pyld = bfa_fcxp_get_reqbuf(fcxp); 2031 memset(pyld, 0, FC_MAX_PDUSZ); 2032 2033 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port), 2034 FDMI_RPA); 2035 2036 attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi, 2037 (u8 *) ((struct ct_hdr_s *) pyld + 1)); 2038 2039 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 2040 FC_CLASS_3, len + attr_len, &fchs, 2041 bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi, 2042 FC_MAX_PDUSZ, FC_FCCT_TOV); 2043 2044 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT); 2045 } 2046 2047 static u16 2048 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) 2049 { 2050 struct bfa_fcs_lport_s *port = fdmi->ms->port; 2051 struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld; 2052 u16 len; 2053 2054 rpa->port_name = bfa_fcs_lport_get_pwwn(port); 2055 2056 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi, 2057 (u8 *) &rpa->port_attr_blk); 2058 2059 len += sizeof(rpa->port_name); 2060 2061 return len; 2062 } 2063 2064 static void 2065 bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 2066 void *cbarg, bfa_status_t req_status, u32 rsp_len, 2067 u32 resid_len, struct fchs_s *rsp_fchs) 2068 { 2069 struct bfa_fcs_lport_fdmi_s *fdmi = 2070 (struct bfa_fcs_lport_fdmi_s *) cbarg; 2071 struct bfa_fcs_lport_s *port = fdmi->ms->port; 2072 struct ct_hdr_s *cthdr = NULL; 2073 2074 bfa_trc(port->fcs, port->port_cfg.pwwn); 2075 2076 /* 2077 * Sanity Checks 2078 */ 2079 if (req_status != BFA_STATUS_OK) { 2080 bfa_trc(port->fcs, req_status); 2081 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); 2082 return; 2083 } 2084 2085 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 2086 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 2087 2088 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 2089 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); 2090 return; 2091 } 2092 2093 bfa_trc(port->fcs, cthdr->reason_code); 2094 bfa_trc(port->fcs, cthdr->exp_code); 2095 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); 2096 } 2097 2098 static void 2099 bfa_fcs_lport_fdmi_timeout(void *arg) 2100 { 2101 struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg; 2102 2103 bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT); 2104 } 2105 2106 void 2107 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, 2108 struct bfa_fcs_fdmi_hba_attr_s *hba_attr) 2109 { 2110 struct bfa_fcs_lport_s *port = fdmi->ms->port; 2111 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info; 2112 2113 memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s)); 2114 2115 bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc, 2116 hba_attr->manufacturer); 2117 bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc, 2118 hba_attr->serial_num); 2119 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, 2120 hba_attr->model); 2121 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, 2122 hba_attr->model_desc); 2123 bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc, 2124 hba_attr->hw_version); 2125 bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc, 2126 hba_attr->option_rom_ver); 2127 bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc, 2128 hba_attr->fw_version); 2129 2130 strncpy(hba_attr->driver_version, (char *)driver_info->version, 2131 sizeof(hba_attr->driver_version)); 2132 2133 strncpy(hba_attr->os_name, driver_info->host_os_name, 2134 sizeof(hba_attr->os_name)); 2135 2136 /* 2137 * If there is a patch level, append it 2138 * to the os name along with a separator 2139 */ 2140 if (driver_info->host_os_patch[0] != '\0') { 2141 strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, 2142 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); 2143 strncat(hba_attr->os_name, driver_info->host_os_patch, 2144 sizeof(driver_info->host_os_patch)); 2145 } 2146 2147 hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ); 2148 } 2149 2150 void 2151 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, 2152 struct bfa_fcs_fdmi_port_attr_s *port_attr) 2153 { 2154 struct bfa_fcs_lport_s *port = fdmi->ms->port; 2155 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info; 2156 struct bfa_port_attr_s pport_attr; 2157 2158 memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s)); 2159 2160 /* 2161 * get pport attributes from hal 2162 */ 2163 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr); 2164 2165 /* 2166 * get FC4 type Bitmask 2167 */ 2168 fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types); 2169 2170 /* 2171 * Supported Speeds 2172 */ 2173 port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS); 2174 2175 /* 2176 * Current Speed 2177 */ 2178 port_attr->curr_speed = cpu_to_be32(pport_attr.speed); 2179 2180 /* 2181 * Max PDU Size. 2182 */ 2183 port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ); 2184 2185 /* 2186 * OS device Name 2187 */ 2188 strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name, 2189 sizeof(port_attr->os_device_name)); 2190 2191 /* 2192 * Host name 2193 */ 2194 strncpy(port_attr->host_name, (char *)driver_info->host_machine_name, 2195 sizeof(port_attr->host_name)); 2196 2197 } 2198 2199 2200 void 2201 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms) 2202 { 2203 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi; 2204 2205 fdmi->ms = ms; 2206 if (ms->port->fcs->fdmi_enabled) 2207 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 2208 else 2209 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled); 2210 } 2211 2212 void 2213 bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms) 2214 { 2215 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi; 2216 2217 fdmi->ms = ms; 2218 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE); 2219 } 2220 2221 void 2222 bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms) 2223 { 2224 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi; 2225 2226 fdmi->ms = ms; 2227 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE); 2228 } 2229 2230 #define BFA_FCS_MS_CMD_MAX_RETRIES 2 2231 2232 /* 2233 * forward declarations 2234 */ 2235 static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, 2236 struct bfa_fcxp_s *fcxp_alloced); 2237 static void bfa_fcs_lport_ms_timeout(void *arg); 2238 static void bfa_fcs_lport_ms_plogi_response(void *fcsarg, 2239 struct bfa_fcxp_s *fcxp, 2240 void *cbarg, 2241 bfa_status_t req_status, 2242 u32 rsp_len, 2243 u32 resid_len, 2244 struct fchs_s *rsp_fchs); 2245 2246 static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, 2247 struct bfa_fcxp_s *fcxp_alloced); 2248 static void bfa_fcs_lport_ms_gmal_response(void *fcsarg, 2249 struct bfa_fcxp_s *fcxp, 2250 void *cbarg, 2251 bfa_status_t req_status, 2252 u32 rsp_len, 2253 u32 resid_len, 2254 struct fchs_s *rsp_fchs); 2255 static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, 2256 struct bfa_fcxp_s *fcxp_alloced); 2257 static void bfa_fcs_lport_ms_gfn_response(void *fcsarg, 2258 struct bfa_fcxp_s *fcxp, 2259 void *cbarg, 2260 bfa_status_t req_status, 2261 u32 rsp_len, 2262 u32 resid_len, 2263 struct fchs_s *rsp_fchs); 2264 /* 2265 * fcs_ms_sm FCS MS state machine 2266 */ 2267 2268 /* 2269 * MS State Machine events 2270 */ 2271 enum port_ms_event { 2272 MSSM_EVENT_PORT_ONLINE = 1, 2273 MSSM_EVENT_PORT_OFFLINE = 2, 2274 MSSM_EVENT_RSP_OK = 3, 2275 MSSM_EVENT_RSP_ERROR = 4, 2276 MSSM_EVENT_TIMEOUT = 5, 2277 MSSM_EVENT_FCXP_SENT = 6, 2278 MSSM_EVENT_PORT_FABRIC_RSCN = 7 2279 }; 2280 2281 static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms, 2282 enum port_ms_event event); 2283 static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms, 2284 enum port_ms_event event); 2285 static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms, 2286 enum port_ms_event event); 2287 static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms, 2288 enum port_ms_event event); 2289 static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms, 2290 enum port_ms_event event); 2291 static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms, 2292 enum port_ms_event event); 2293 static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms, 2294 enum port_ms_event event); 2295 static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms, 2296 enum port_ms_event event); 2297 static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms, 2298 enum port_ms_event event); 2299 static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms, 2300 enum port_ms_event event); 2301 static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms, 2302 enum port_ms_event event); 2303 /* 2304 * Start in offline state - awaiting NS to send start. 2305 */ 2306 static void 2307 bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms, 2308 enum port_ms_event event) 2309 { 2310 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2311 bfa_trc(ms->port->fcs, event); 2312 2313 switch (event) { 2314 case MSSM_EVENT_PORT_ONLINE: 2315 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending); 2316 bfa_fcs_lport_ms_send_plogi(ms, NULL); 2317 break; 2318 2319 case MSSM_EVENT_PORT_OFFLINE: 2320 break; 2321 2322 default: 2323 bfa_sm_fault(ms->port->fcs, event); 2324 } 2325 } 2326 2327 static void 2328 bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms, 2329 enum port_ms_event event) 2330 { 2331 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2332 bfa_trc(ms->port->fcs, event); 2333 2334 switch (event) { 2335 case MSSM_EVENT_FCXP_SENT: 2336 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi); 2337 break; 2338 2339 case MSSM_EVENT_PORT_OFFLINE: 2340 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2341 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port), 2342 &ms->fcxp_wqe); 2343 break; 2344 2345 default: 2346 bfa_sm_fault(ms->port->fcs, event); 2347 } 2348 } 2349 2350 static void 2351 bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms, 2352 enum port_ms_event event) 2353 { 2354 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2355 bfa_trc(ms->port->fcs, event); 2356 2357 switch (event) { 2358 case MSSM_EVENT_RSP_ERROR: 2359 /* 2360 * Start timer for a delayed retry 2361 */ 2362 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry); 2363 ms->port->stats.ms_retries++; 2364 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), 2365 &ms->timer, bfa_fcs_lport_ms_timeout, ms, 2366 BFA_FCS_RETRY_TIMEOUT); 2367 break; 2368 2369 case MSSM_EVENT_RSP_OK: 2370 /* 2371 * since plogi is done, now invoke MS related sub-modules 2372 */ 2373 bfa_fcs_lport_fdmi_online(ms); 2374 2375 /* 2376 * if this is a Vport, go to online state. 2377 */ 2378 if (ms->port->vport) { 2379 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online); 2380 break; 2381 } 2382 2383 /* 2384 * For a base port we need to get the 2385 * switch's IP address. 2386 */ 2387 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending); 2388 bfa_fcs_lport_ms_send_gmal(ms, NULL); 2389 break; 2390 2391 case MSSM_EVENT_PORT_OFFLINE: 2392 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2393 bfa_fcxp_discard(ms->fcxp); 2394 break; 2395 2396 default: 2397 bfa_sm_fault(ms->port->fcs, event); 2398 } 2399 } 2400 2401 static void 2402 bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms, 2403 enum port_ms_event event) 2404 { 2405 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2406 bfa_trc(ms->port->fcs, event); 2407 2408 switch (event) { 2409 case MSSM_EVENT_TIMEOUT: 2410 /* 2411 * Retry Timer Expired. Re-send 2412 */ 2413 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending); 2414 bfa_fcs_lport_ms_send_plogi(ms, NULL); 2415 break; 2416 2417 case MSSM_EVENT_PORT_OFFLINE: 2418 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2419 bfa_timer_stop(&ms->timer); 2420 break; 2421 2422 default: 2423 bfa_sm_fault(ms->port->fcs, event); 2424 } 2425 } 2426 2427 static void 2428 bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms, 2429 enum port_ms_event event) 2430 { 2431 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2432 bfa_trc(ms->port->fcs, event); 2433 2434 switch (event) { 2435 case MSSM_EVENT_PORT_OFFLINE: 2436 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2437 break; 2438 2439 case MSSM_EVENT_PORT_FABRIC_RSCN: 2440 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending); 2441 ms->retry_cnt = 0; 2442 bfa_fcs_lport_ms_send_gfn(ms, NULL); 2443 break; 2444 2445 default: 2446 bfa_sm_fault(ms->port->fcs, event); 2447 } 2448 } 2449 2450 static void 2451 bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms, 2452 enum port_ms_event event) 2453 { 2454 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2455 bfa_trc(ms->port->fcs, event); 2456 2457 switch (event) { 2458 case MSSM_EVENT_FCXP_SENT: 2459 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal); 2460 break; 2461 2462 case MSSM_EVENT_PORT_OFFLINE: 2463 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2464 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port), 2465 &ms->fcxp_wqe); 2466 break; 2467 2468 default: 2469 bfa_sm_fault(ms->port->fcs, event); 2470 } 2471 } 2472 2473 static void 2474 bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms, 2475 enum port_ms_event event) 2476 { 2477 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2478 bfa_trc(ms->port->fcs, event); 2479 2480 switch (event) { 2481 case MSSM_EVENT_RSP_ERROR: 2482 /* 2483 * Start timer for a delayed retry 2484 */ 2485 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) { 2486 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry); 2487 ms->port->stats.ms_retries++; 2488 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), 2489 &ms->timer, bfa_fcs_lport_ms_timeout, ms, 2490 BFA_FCS_RETRY_TIMEOUT); 2491 } else { 2492 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending); 2493 bfa_fcs_lport_ms_send_gfn(ms, NULL); 2494 ms->retry_cnt = 0; 2495 } 2496 break; 2497 2498 case MSSM_EVENT_RSP_OK: 2499 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending); 2500 bfa_fcs_lport_ms_send_gfn(ms, NULL); 2501 break; 2502 2503 case MSSM_EVENT_PORT_OFFLINE: 2504 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2505 bfa_fcxp_discard(ms->fcxp); 2506 break; 2507 2508 default: 2509 bfa_sm_fault(ms->port->fcs, event); 2510 } 2511 } 2512 2513 static void 2514 bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms, 2515 enum port_ms_event event) 2516 { 2517 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2518 bfa_trc(ms->port->fcs, event); 2519 2520 switch (event) { 2521 case MSSM_EVENT_TIMEOUT: 2522 /* 2523 * Retry Timer Expired. Re-send 2524 */ 2525 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending); 2526 bfa_fcs_lport_ms_send_gmal(ms, NULL); 2527 break; 2528 2529 case MSSM_EVENT_PORT_OFFLINE: 2530 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2531 bfa_timer_stop(&ms->timer); 2532 break; 2533 2534 default: 2535 bfa_sm_fault(ms->port->fcs, event); 2536 } 2537 } 2538 /* 2539 * ms_pvt MS local functions 2540 */ 2541 2542 static void 2543 bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) 2544 { 2545 struct bfa_fcs_lport_ms_s *ms = ms_cbarg; 2546 bfa_fcs_lport_t *port = ms->port; 2547 struct fchs_s fchs; 2548 int len; 2549 struct bfa_fcxp_s *fcxp; 2550 2551 bfa_trc(port->fcs, port->pid); 2552 2553 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 2554 if (!fcxp) { 2555 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, 2556 bfa_fcs_lport_ms_send_gmal, ms); 2557 return; 2558 } 2559 ms->fcxp = fcxp; 2560 2561 len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 2562 bfa_fcs_lport_get_fcid(port), 2563 bfa_lps_get_peer_nwwn(port->fabric->lps)); 2564 2565 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 2566 FC_CLASS_3, len, &fchs, 2567 bfa_fcs_lport_ms_gmal_response, (void *)ms, 2568 FC_MAX_PDUSZ, FC_FCCT_TOV); 2569 2570 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); 2571 } 2572 2573 static void 2574 bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 2575 void *cbarg, bfa_status_t req_status, 2576 u32 rsp_len, u32 resid_len, 2577 struct fchs_s *rsp_fchs) 2578 { 2579 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg; 2580 bfa_fcs_lport_t *port = ms->port; 2581 struct ct_hdr_s *cthdr = NULL; 2582 struct fcgs_gmal_resp_s *gmal_resp; 2583 struct fcgs_gmal_entry_s *gmal_entry; 2584 u32 num_entries; 2585 u8 *rsp_str; 2586 2587 bfa_trc(port->fcs, req_status); 2588 bfa_trc(port->fcs, port->port_cfg.pwwn); 2589 2590 /* 2591 * Sanity Checks 2592 */ 2593 if (req_status != BFA_STATUS_OK) { 2594 bfa_trc(port->fcs, req_status); 2595 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); 2596 return; 2597 } 2598 2599 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 2600 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 2601 2602 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 2603 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1); 2604 2605 num_entries = be32_to_cpu(gmal_resp->ms_len); 2606 if (num_entries == 0) { 2607 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); 2608 return; 2609 } 2610 /* 2611 * The response could contain multiple Entries. 2612 * Entries for SNMP interface, etc. 2613 * We look for the entry with a telnet prefix. 2614 * First "http://" entry refers to IP addr 2615 */ 2616 2617 gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma; 2618 while (num_entries > 0) { 2619 if (strncmp(gmal_entry->prefix, 2620 CT_GMAL_RESP_PREFIX_HTTP, 2621 sizeof(gmal_entry->prefix)) == 0) { 2622 2623 /* 2624 * if the IP address is terminating with a '/', 2625 * remove it. 2626 * Byte 0 consists of the length of the string. 2627 */ 2628 rsp_str = &(gmal_entry->prefix[0]); 2629 if (rsp_str[gmal_entry->len-1] == '/') 2630 rsp_str[gmal_entry->len-1] = 0; 2631 2632 /* copy IP Address to fabric */ 2633 strncpy(bfa_fcs_lport_get_fabric_ipaddr(port), 2634 gmal_entry->ip_addr, 2635 BFA_FCS_FABRIC_IPADDR_SZ); 2636 break; 2637 } else { 2638 --num_entries; 2639 ++gmal_entry; 2640 } 2641 } 2642 2643 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK); 2644 return; 2645 } 2646 2647 bfa_trc(port->fcs, cthdr->reason_code); 2648 bfa_trc(port->fcs, cthdr->exp_code); 2649 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); 2650 } 2651 2652 static void 2653 bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms, 2654 enum port_ms_event event) 2655 { 2656 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2657 bfa_trc(ms->port->fcs, event); 2658 2659 switch (event) { 2660 case MSSM_EVENT_FCXP_SENT: 2661 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn); 2662 break; 2663 2664 case MSSM_EVENT_PORT_OFFLINE: 2665 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2666 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port), 2667 &ms->fcxp_wqe); 2668 break; 2669 2670 default: 2671 bfa_sm_fault(ms->port->fcs, event); 2672 } 2673 } 2674 2675 static void 2676 bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms, 2677 enum port_ms_event event) 2678 { 2679 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2680 bfa_trc(ms->port->fcs, event); 2681 2682 switch (event) { 2683 case MSSM_EVENT_RSP_ERROR: 2684 /* 2685 * Start timer for a delayed retry 2686 */ 2687 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) { 2688 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry); 2689 ms->port->stats.ms_retries++; 2690 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), 2691 &ms->timer, bfa_fcs_lport_ms_timeout, ms, 2692 BFA_FCS_RETRY_TIMEOUT); 2693 } else { 2694 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online); 2695 ms->retry_cnt = 0; 2696 } 2697 break; 2698 2699 case MSSM_EVENT_RSP_OK: 2700 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online); 2701 break; 2702 2703 case MSSM_EVENT_PORT_OFFLINE: 2704 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2705 bfa_fcxp_discard(ms->fcxp); 2706 break; 2707 2708 default: 2709 bfa_sm_fault(ms->port->fcs, event); 2710 } 2711 } 2712 2713 static void 2714 bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms, 2715 enum port_ms_event event) 2716 { 2717 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); 2718 bfa_trc(ms->port->fcs, event); 2719 2720 switch (event) { 2721 case MSSM_EVENT_TIMEOUT: 2722 /* 2723 * Retry Timer Expired. Re-send 2724 */ 2725 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending); 2726 bfa_fcs_lport_ms_send_gfn(ms, NULL); 2727 break; 2728 2729 case MSSM_EVENT_PORT_OFFLINE: 2730 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2731 bfa_timer_stop(&ms->timer); 2732 break; 2733 2734 default: 2735 bfa_sm_fault(ms->port->fcs, event); 2736 } 2737 } 2738 /* 2739 * ms_pvt MS local functions 2740 */ 2741 2742 static void 2743 bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) 2744 { 2745 struct bfa_fcs_lport_ms_s *ms = ms_cbarg; 2746 bfa_fcs_lport_t *port = ms->port; 2747 struct fchs_s fchs; 2748 int len; 2749 struct bfa_fcxp_s *fcxp; 2750 2751 bfa_trc(port->fcs, port->pid); 2752 2753 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 2754 if (!fcxp) { 2755 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, 2756 bfa_fcs_lport_ms_send_gfn, ms); 2757 return; 2758 } 2759 ms->fcxp = fcxp; 2760 2761 len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 2762 bfa_fcs_lport_get_fcid(port), 2763 bfa_lps_get_peer_nwwn(port->fabric->lps)); 2764 2765 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 2766 FC_CLASS_3, len, &fchs, 2767 bfa_fcs_lport_ms_gfn_response, (void *)ms, 2768 FC_MAX_PDUSZ, FC_FCCT_TOV); 2769 2770 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); 2771 } 2772 2773 static void 2774 bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 2775 void *cbarg, bfa_status_t req_status, u32 rsp_len, 2776 u32 resid_len, struct fchs_s *rsp_fchs) 2777 { 2778 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg; 2779 bfa_fcs_lport_t *port = ms->port; 2780 struct ct_hdr_s *cthdr = NULL; 2781 wwn_t *gfn_resp; 2782 2783 bfa_trc(port->fcs, req_status); 2784 bfa_trc(port->fcs, port->port_cfg.pwwn); 2785 2786 /* 2787 * Sanity Checks 2788 */ 2789 if (req_status != BFA_STATUS_OK) { 2790 bfa_trc(port->fcs, req_status); 2791 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); 2792 return; 2793 } 2794 2795 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 2796 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 2797 2798 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 2799 gfn_resp = (wwn_t *)(cthdr + 1); 2800 /* check if it has actually changed */ 2801 if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port), 2802 gfn_resp, sizeof(wwn_t)) != 0)) { 2803 bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp); 2804 } 2805 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK); 2806 return; 2807 } 2808 2809 bfa_trc(port->fcs, cthdr->reason_code); 2810 bfa_trc(port->fcs, cthdr->exp_code); 2811 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); 2812 } 2813 2814 /* 2815 * ms_pvt MS local functions 2816 */ 2817 2818 static void 2819 bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) 2820 { 2821 struct bfa_fcs_lport_ms_s *ms = ms_cbarg; 2822 struct bfa_fcs_lport_s *port = ms->port; 2823 struct fchs_s fchs; 2824 int len; 2825 struct bfa_fcxp_s *fcxp; 2826 2827 bfa_trc(port->fcs, port->pid); 2828 2829 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 2830 if (!fcxp) { 2831 port->stats.ms_plogi_alloc_wait++; 2832 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, 2833 bfa_fcs_lport_ms_send_plogi, ms); 2834 return; 2835 } 2836 ms->fcxp = fcxp; 2837 2838 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 2839 bfa_os_hton3b(FC_MGMT_SERVER), 2840 bfa_fcs_lport_get_fcid(port), 0, 2841 port->port_cfg.pwwn, port->port_cfg.nwwn, 2842 bfa_fcport_get_maxfrsize(port->fcs->bfa)); 2843 2844 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 2845 FC_CLASS_3, len, &fchs, 2846 bfa_fcs_lport_ms_plogi_response, (void *)ms, 2847 FC_MAX_PDUSZ, FC_ELS_TOV); 2848 2849 port->stats.ms_plogi_sent++; 2850 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); 2851 } 2852 2853 static void 2854 bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 2855 void *cbarg, bfa_status_t req_status, 2856 u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs) 2857 { 2858 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg; 2859 struct bfa_fcs_lport_s *port = ms->port; 2860 struct fc_els_cmd_s *els_cmd; 2861 struct fc_ls_rjt_s *ls_rjt; 2862 2863 bfa_trc(port->fcs, req_status); 2864 bfa_trc(port->fcs, port->port_cfg.pwwn); 2865 2866 /* 2867 * Sanity Checks 2868 */ 2869 if (req_status != BFA_STATUS_OK) { 2870 port->stats.ms_plogi_rsp_err++; 2871 bfa_trc(port->fcs, req_status); 2872 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); 2873 return; 2874 } 2875 2876 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); 2877 2878 switch (els_cmd->els_code) { 2879 2880 case FC_ELS_ACC: 2881 if (rsp_len < sizeof(struct fc_logi_s)) { 2882 bfa_trc(port->fcs, rsp_len); 2883 port->stats.ms_plogi_acc_err++; 2884 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); 2885 break; 2886 } 2887 port->stats.ms_plogi_accepts++; 2888 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK); 2889 break; 2890 2891 case FC_ELS_LS_RJT: 2892 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); 2893 2894 bfa_trc(port->fcs, ls_rjt->reason_code); 2895 bfa_trc(port->fcs, ls_rjt->reason_code_expl); 2896 2897 port->stats.ms_rejects++; 2898 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); 2899 break; 2900 2901 default: 2902 port->stats.ms_plogi_unknown_rsp++; 2903 bfa_trc(port->fcs, els_cmd->els_code); 2904 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); 2905 } 2906 } 2907 2908 static void 2909 bfa_fcs_lport_ms_timeout(void *arg) 2910 { 2911 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg; 2912 2913 ms->port->stats.ms_timeouts++; 2914 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT); 2915 } 2916 2917 2918 void 2919 bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port) 2920 { 2921 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); 2922 2923 ms->port = port; 2924 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline); 2925 2926 /* 2927 * Invoke init routines of sub modules. 2928 */ 2929 bfa_fcs_lport_fdmi_init(ms); 2930 } 2931 2932 void 2933 bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port) 2934 { 2935 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); 2936 2937 ms->port = port; 2938 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE); 2939 bfa_fcs_lport_fdmi_offline(ms); 2940 } 2941 2942 void 2943 bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port) 2944 { 2945 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); 2946 2947 ms->port = port; 2948 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE); 2949 } 2950 void 2951 bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port) 2952 { 2953 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); 2954 2955 /* todo. Handle this only when in Online state */ 2956 if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online)) 2957 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN); 2958 } 2959 2960 /* 2961 * @page ns_sm_info VPORT NS State Machine 2962 * 2963 * @section ns_sm_interactions VPORT NS State Machine Interactions 2964 * 2965 * @section ns_sm VPORT NS State Machine 2966 * img ns_sm.jpg 2967 */ 2968 2969 /* 2970 * forward declarations 2971 */ 2972 static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, 2973 struct bfa_fcxp_s *fcxp_alloced); 2974 static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, 2975 struct bfa_fcxp_s *fcxp_alloced); 2976 static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, 2977 struct bfa_fcxp_s *fcxp_alloced); 2978 static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, 2979 struct bfa_fcxp_s *fcxp_alloced); 2980 static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, 2981 struct bfa_fcxp_s *fcxp_alloced); 2982 static void bfa_fcs_lport_ns_timeout(void *arg); 2983 static void bfa_fcs_lport_ns_plogi_response(void *fcsarg, 2984 struct bfa_fcxp_s *fcxp, 2985 void *cbarg, 2986 bfa_status_t req_status, 2987 u32 rsp_len, 2988 u32 resid_len, 2989 struct fchs_s *rsp_fchs); 2990 static void bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, 2991 struct bfa_fcxp_s *fcxp, 2992 void *cbarg, 2993 bfa_status_t req_status, 2994 u32 rsp_len, 2995 u32 resid_len, 2996 struct fchs_s *rsp_fchs); 2997 static void bfa_fcs_lport_ns_rft_id_response(void *fcsarg, 2998 struct bfa_fcxp_s *fcxp, 2999 void *cbarg, 3000 bfa_status_t req_status, 3001 u32 rsp_len, 3002 u32 resid_len, 3003 struct fchs_s *rsp_fchs); 3004 static void bfa_fcs_lport_ns_rff_id_response(void *fcsarg, 3005 struct bfa_fcxp_s *fcxp, 3006 void *cbarg, 3007 bfa_status_t req_status, 3008 u32 rsp_len, 3009 u32 resid_len, 3010 struct fchs_s *rsp_fchs); 3011 static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, 3012 struct bfa_fcxp_s *fcxp, 3013 void *cbarg, 3014 bfa_status_t req_status, 3015 u32 rsp_len, 3016 u32 resid_len, 3017 struct fchs_s *rsp_fchs); 3018 static void bfa_fcs_lport_ns_process_gidft_pids( 3019 struct bfa_fcs_lport_s *port, 3020 u32 *pid_buf, u32 n_pids); 3021 3022 static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port); 3023 /* 3024 * fcs_ns_sm FCS nameserver interface state machine 3025 */ 3026 3027 /* 3028 * VPort NS State Machine events 3029 */ 3030 enum vport_ns_event { 3031 NSSM_EVENT_PORT_ONLINE = 1, 3032 NSSM_EVENT_PORT_OFFLINE = 2, 3033 NSSM_EVENT_PLOGI_SENT = 3, 3034 NSSM_EVENT_RSP_OK = 4, 3035 NSSM_EVENT_RSP_ERROR = 5, 3036 NSSM_EVENT_TIMEOUT = 6, 3037 NSSM_EVENT_NS_QUERY = 7, 3038 NSSM_EVENT_RSPNID_SENT = 8, 3039 NSSM_EVENT_RFTID_SENT = 9, 3040 NSSM_EVENT_RFFID_SENT = 10, 3041 NSSM_EVENT_GIDFT_SENT = 11, 3042 }; 3043 3044 static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns, 3045 enum vport_ns_event event); 3046 static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns, 3047 enum vport_ns_event event); 3048 static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns, 3049 enum vport_ns_event event); 3050 static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns, 3051 enum vport_ns_event event); 3052 static void bfa_fcs_lport_ns_sm_sending_rspn_id( 3053 struct bfa_fcs_lport_ns_s *ns, 3054 enum vport_ns_event event); 3055 static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns, 3056 enum vport_ns_event event); 3057 static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns, 3058 enum vport_ns_event event); 3059 static void bfa_fcs_lport_ns_sm_sending_rft_id( 3060 struct bfa_fcs_lport_ns_s *ns, 3061 enum vport_ns_event event); 3062 static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns, 3063 enum vport_ns_event event); 3064 static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns, 3065 enum vport_ns_event event); 3066 static void bfa_fcs_lport_ns_sm_sending_rff_id( 3067 struct bfa_fcs_lport_ns_s *ns, 3068 enum vport_ns_event event); 3069 static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns, 3070 enum vport_ns_event event); 3071 static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns, 3072 enum vport_ns_event event); 3073 static void bfa_fcs_lport_ns_sm_sending_gid_ft( 3074 struct bfa_fcs_lport_ns_s *ns, 3075 enum vport_ns_event event); 3076 static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns, 3077 enum vport_ns_event event); 3078 static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns, 3079 enum vport_ns_event event); 3080 static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns, 3081 enum vport_ns_event event); 3082 /* 3083 * Start in offline state - awaiting linkup 3084 */ 3085 static void 3086 bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns, 3087 enum vport_ns_event event) 3088 { 3089 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3090 bfa_trc(ns->port->fcs, event); 3091 3092 switch (event) { 3093 case NSSM_EVENT_PORT_ONLINE: 3094 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending); 3095 bfa_fcs_lport_ns_send_plogi(ns, NULL); 3096 break; 3097 3098 case NSSM_EVENT_PORT_OFFLINE: 3099 break; 3100 3101 default: 3102 bfa_sm_fault(ns->port->fcs, event); 3103 } 3104 } 3105 3106 static void 3107 bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns, 3108 enum vport_ns_event event) 3109 { 3110 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3111 bfa_trc(ns->port->fcs, event); 3112 3113 switch (event) { 3114 case NSSM_EVENT_PLOGI_SENT: 3115 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi); 3116 break; 3117 3118 case NSSM_EVENT_PORT_OFFLINE: 3119 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3120 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3121 &ns->fcxp_wqe); 3122 break; 3123 3124 default: 3125 bfa_sm_fault(ns->port->fcs, event); 3126 } 3127 } 3128 3129 static void 3130 bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns, 3131 enum vport_ns_event event) 3132 { 3133 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3134 bfa_trc(ns->port->fcs, event); 3135 3136 switch (event) { 3137 case NSSM_EVENT_RSP_ERROR: 3138 /* 3139 * Start timer for a delayed retry 3140 */ 3141 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry); 3142 ns->port->stats.ns_retries++; 3143 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3144 &ns->timer, bfa_fcs_lport_ns_timeout, ns, 3145 BFA_FCS_RETRY_TIMEOUT); 3146 break; 3147 3148 case NSSM_EVENT_RSP_OK: 3149 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id); 3150 bfa_fcs_lport_ns_send_rspn_id(ns, NULL); 3151 break; 3152 3153 case NSSM_EVENT_PORT_OFFLINE: 3154 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3155 bfa_fcxp_discard(ns->fcxp); 3156 break; 3157 3158 default: 3159 bfa_sm_fault(ns->port->fcs, event); 3160 } 3161 } 3162 3163 static void 3164 bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns, 3165 enum vport_ns_event event) 3166 { 3167 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3168 bfa_trc(ns->port->fcs, event); 3169 3170 switch (event) { 3171 case NSSM_EVENT_TIMEOUT: 3172 /* 3173 * Retry Timer Expired. Re-send 3174 */ 3175 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending); 3176 bfa_fcs_lport_ns_send_plogi(ns, NULL); 3177 break; 3178 3179 case NSSM_EVENT_PORT_OFFLINE: 3180 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3181 bfa_timer_stop(&ns->timer); 3182 break; 3183 3184 default: 3185 bfa_sm_fault(ns->port->fcs, event); 3186 } 3187 } 3188 3189 static void 3190 bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns, 3191 enum vport_ns_event event) 3192 { 3193 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3194 bfa_trc(ns->port->fcs, event); 3195 3196 switch (event) { 3197 case NSSM_EVENT_RSPNID_SENT: 3198 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id); 3199 break; 3200 3201 case NSSM_EVENT_PORT_OFFLINE: 3202 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3203 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3204 &ns->fcxp_wqe); 3205 break; 3206 3207 default: 3208 bfa_sm_fault(ns->port->fcs, event); 3209 } 3210 } 3211 3212 static void 3213 bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns, 3214 enum vport_ns_event event) 3215 { 3216 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3217 bfa_trc(ns->port->fcs, event); 3218 3219 switch (event) { 3220 case NSSM_EVENT_RSP_ERROR: 3221 /* 3222 * Start timer for a delayed retry 3223 */ 3224 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry); 3225 ns->port->stats.ns_retries++; 3226 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3227 &ns->timer, bfa_fcs_lport_ns_timeout, ns, 3228 BFA_FCS_RETRY_TIMEOUT); 3229 break; 3230 3231 case NSSM_EVENT_RSP_OK: 3232 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id); 3233 bfa_fcs_lport_ns_send_rft_id(ns, NULL); 3234 break; 3235 3236 case NSSM_EVENT_PORT_OFFLINE: 3237 bfa_fcxp_discard(ns->fcxp); 3238 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3239 break; 3240 3241 default: 3242 bfa_sm_fault(ns->port->fcs, event); 3243 } 3244 } 3245 3246 static void 3247 bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns, 3248 enum vport_ns_event event) 3249 { 3250 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3251 bfa_trc(ns->port->fcs, event); 3252 3253 switch (event) { 3254 case NSSM_EVENT_TIMEOUT: 3255 /* 3256 * Retry Timer Expired. Re-send 3257 */ 3258 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id); 3259 bfa_fcs_lport_ns_send_rspn_id(ns, NULL); 3260 break; 3261 3262 case NSSM_EVENT_PORT_OFFLINE: 3263 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3264 bfa_timer_stop(&ns->timer); 3265 break; 3266 3267 default: 3268 bfa_sm_fault(ns->port->fcs, event); 3269 } 3270 } 3271 3272 static void 3273 bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns, 3274 enum vport_ns_event event) 3275 { 3276 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3277 bfa_trc(ns->port->fcs, event); 3278 3279 switch (event) { 3280 case NSSM_EVENT_RFTID_SENT: 3281 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id); 3282 break; 3283 3284 case NSSM_EVENT_PORT_OFFLINE: 3285 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3286 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3287 &ns->fcxp_wqe); 3288 break; 3289 3290 default: 3291 bfa_sm_fault(ns->port->fcs, event); 3292 } 3293 } 3294 3295 static void 3296 bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns, 3297 enum vport_ns_event event) 3298 { 3299 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3300 bfa_trc(ns->port->fcs, event); 3301 3302 switch (event) { 3303 case NSSM_EVENT_RSP_OK: 3304 /* Now move to register FC4 Features */ 3305 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id); 3306 bfa_fcs_lport_ns_send_rff_id(ns, NULL); 3307 break; 3308 3309 case NSSM_EVENT_RSP_ERROR: 3310 /* 3311 * Start timer for a delayed retry 3312 */ 3313 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry); 3314 ns->port->stats.ns_retries++; 3315 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3316 &ns->timer, bfa_fcs_lport_ns_timeout, ns, 3317 BFA_FCS_RETRY_TIMEOUT); 3318 break; 3319 3320 case NSSM_EVENT_PORT_OFFLINE: 3321 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3322 bfa_fcxp_discard(ns->fcxp); 3323 break; 3324 3325 default: 3326 bfa_sm_fault(ns->port->fcs, event); 3327 } 3328 } 3329 3330 static void 3331 bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns, 3332 enum vport_ns_event event) 3333 { 3334 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3335 bfa_trc(ns->port->fcs, event); 3336 3337 switch (event) { 3338 case NSSM_EVENT_TIMEOUT: 3339 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id); 3340 bfa_fcs_lport_ns_send_rft_id(ns, NULL); 3341 break; 3342 3343 case NSSM_EVENT_PORT_OFFLINE: 3344 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3345 bfa_timer_stop(&ns->timer); 3346 break; 3347 3348 default: 3349 bfa_sm_fault(ns->port->fcs, event); 3350 } 3351 } 3352 3353 static void 3354 bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns, 3355 enum vport_ns_event event) 3356 { 3357 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3358 bfa_trc(ns->port->fcs, event); 3359 3360 switch (event) { 3361 case NSSM_EVENT_RFFID_SENT: 3362 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id); 3363 break; 3364 3365 case NSSM_EVENT_PORT_OFFLINE: 3366 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3367 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3368 &ns->fcxp_wqe); 3369 break; 3370 3371 default: 3372 bfa_sm_fault(ns->port->fcs, event); 3373 } 3374 } 3375 3376 static void 3377 bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns, 3378 enum vport_ns_event event) 3379 { 3380 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3381 bfa_trc(ns->port->fcs, event); 3382 3383 switch (event) { 3384 case NSSM_EVENT_RSP_OK: 3385 3386 /* 3387 * If min cfg mode is enabled, we donot initiate rport 3388 * discovery with the fabric. Instead, we will retrieve the 3389 * boot targets from HAL/FW. 3390 */ 3391 if (__fcs_min_cfg(ns->port->fcs)) { 3392 bfa_fcs_lport_ns_boot_target_disc(ns->port); 3393 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online); 3394 return; 3395 } 3396 3397 /* 3398 * If the port role is Initiator Mode issue NS query. 3399 * If it is Target Mode, skip this and go to online. 3400 */ 3401 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) { 3402 bfa_sm_set_state(ns, 3403 bfa_fcs_lport_ns_sm_sending_gid_ft); 3404 bfa_fcs_lport_ns_send_gid_ft(ns, NULL); 3405 } 3406 /* 3407 * kick off mgmt srvr state machine 3408 */ 3409 bfa_fcs_lport_ms_online(ns->port); 3410 break; 3411 3412 case NSSM_EVENT_RSP_ERROR: 3413 /* 3414 * Start timer for a delayed retry 3415 */ 3416 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry); 3417 ns->port->stats.ns_retries++; 3418 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3419 &ns->timer, bfa_fcs_lport_ns_timeout, ns, 3420 BFA_FCS_RETRY_TIMEOUT); 3421 break; 3422 3423 case NSSM_EVENT_PORT_OFFLINE: 3424 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3425 bfa_fcxp_discard(ns->fcxp); 3426 break; 3427 3428 default: 3429 bfa_sm_fault(ns->port->fcs, event); 3430 } 3431 } 3432 3433 static void 3434 bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns, 3435 enum vport_ns_event event) 3436 { 3437 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3438 bfa_trc(ns->port->fcs, event); 3439 3440 switch (event) { 3441 case NSSM_EVENT_TIMEOUT: 3442 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id); 3443 bfa_fcs_lport_ns_send_rff_id(ns, NULL); 3444 break; 3445 3446 case NSSM_EVENT_PORT_OFFLINE: 3447 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3448 bfa_timer_stop(&ns->timer); 3449 break; 3450 3451 default: 3452 bfa_sm_fault(ns->port->fcs, event); 3453 } 3454 } 3455 static void 3456 bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns, 3457 enum vport_ns_event event) 3458 { 3459 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3460 bfa_trc(ns->port->fcs, event); 3461 3462 switch (event) { 3463 case NSSM_EVENT_GIDFT_SENT: 3464 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft); 3465 break; 3466 3467 case NSSM_EVENT_PORT_OFFLINE: 3468 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3469 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3470 &ns->fcxp_wqe); 3471 break; 3472 3473 default: 3474 bfa_sm_fault(ns->port->fcs, event); 3475 } 3476 } 3477 3478 static void 3479 bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns, 3480 enum vport_ns_event event) 3481 { 3482 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3483 bfa_trc(ns->port->fcs, event); 3484 3485 switch (event) { 3486 case NSSM_EVENT_RSP_OK: 3487 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online); 3488 break; 3489 3490 case NSSM_EVENT_RSP_ERROR: 3491 /* 3492 * TBD: for certain reject codes, we don't need to retry 3493 */ 3494 /* 3495 * Start timer for a delayed retry 3496 */ 3497 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry); 3498 ns->port->stats.ns_retries++; 3499 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), 3500 &ns->timer, bfa_fcs_lport_ns_timeout, ns, 3501 BFA_FCS_RETRY_TIMEOUT); 3502 break; 3503 3504 case NSSM_EVENT_PORT_OFFLINE: 3505 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3506 bfa_fcxp_discard(ns->fcxp); 3507 break; 3508 3509 case NSSM_EVENT_NS_QUERY: 3510 break; 3511 3512 default: 3513 bfa_sm_fault(ns->port->fcs, event); 3514 } 3515 } 3516 3517 static void 3518 bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns, 3519 enum vport_ns_event event) 3520 { 3521 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3522 bfa_trc(ns->port->fcs, event); 3523 3524 switch (event) { 3525 case NSSM_EVENT_TIMEOUT: 3526 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft); 3527 bfa_fcs_lport_ns_send_gid_ft(ns, NULL); 3528 break; 3529 3530 case NSSM_EVENT_PORT_OFFLINE: 3531 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3532 bfa_timer_stop(&ns->timer); 3533 break; 3534 3535 default: 3536 bfa_sm_fault(ns->port->fcs, event); 3537 } 3538 } 3539 3540 static void 3541 bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns, 3542 enum vport_ns_event event) 3543 { 3544 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); 3545 bfa_trc(ns->port->fcs, event); 3546 3547 switch (event) { 3548 case NSSM_EVENT_PORT_OFFLINE: 3549 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 3550 break; 3551 3552 case NSSM_EVENT_NS_QUERY: 3553 /* 3554 * If the port role is Initiator Mode issue NS query. 3555 * If it is Target Mode, skip this and go to online. 3556 */ 3557 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) { 3558 bfa_sm_set_state(ns, 3559 bfa_fcs_lport_ns_sm_sending_gid_ft); 3560 bfa_fcs_lport_ns_send_gid_ft(ns, NULL); 3561 }; 3562 break; 3563 3564 default: 3565 bfa_sm_fault(ns->port->fcs, event); 3566 } 3567 } 3568 3569 3570 3571 /* 3572 * ns_pvt Nameserver local functions 3573 */ 3574 3575 static void 3576 bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) 3577 { 3578 struct bfa_fcs_lport_ns_s *ns = ns_cbarg; 3579 struct bfa_fcs_lport_s *port = ns->port; 3580 struct fchs_s fchs; 3581 int len; 3582 struct bfa_fcxp_s *fcxp; 3583 3584 bfa_trc(port->fcs, port->pid); 3585 3586 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 3587 if (!fcxp) { 3588 port->stats.ns_plogi_alloc_wait++; 3589 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 3590 bfa_fcs_lport_ns_send_plogi, ns); 3591 return; 3592 } 3593 ns->fcxp = fcxp; 3594 3595 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 3596 bfa_os_hton3b(FC_NAME_SERVER), 3597 bfa_fcs_lport_get_fcid(port), 0, 3598 port->port_cfg.pwwn, port->port_cfg.nwwn, 3599 bfa_fcport_get_maxfrsize(port->fcs->bfa)); 3600 3601 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 3602 FC_CLASS_3, len, &fchs, 3603 bfa_fcs_lport_ns_plogi_response, (void *)ns, 3604 FC_MAX_PDUSZ, FC_ELS_TOV); 3605 port->stats.ns_plogi_sent++; 3606 3607 bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT); 3608 } 3609 3610 static void 3611 bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 3612 void *cbarg, bfa_status_t req_status, u32 rsp_len, 3613 u32 resid_len, struct fchs_s *rsp_fchs) 3614 { 3615 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; 3616 struct bfa_fcs_lport_s *port = ns->port; 3617 /* struct fc_logi_s *plogi_resp; */ 3618 struct fc_els_cmd_s *els_cmd; 3619 struct fc_ls_rjt_s *ls_rjt; 3620 3621 bfa_trc(port->fcs, req_status); 3622 bfa_trc(port->fcs, port->port_cfg.pwwn); 3623 3624 /* 3625 * Sanity Checks 3626 */ 3627 if (req_status != BFA_STATUS_OK) { 3628 bfa_trc(port->fcs, req_status); 3629 port->stats.ns_plogi_rsp_err++; 3630 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3631 return; 3632 } 3633 3634 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); 3635 3636 switch (els_cmd->els_code) { 3637 3638 case FC_ELS_ACC: 3639 if (rsp_len < sizeof(struct fc_logi_s)) { 3640 bfa_trc(port->fcs, rsp_len); 3641 port->stats.ns_plogi_acc_err++; 3642 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3643 break; 3644 } 3645 port->stats.ns_plogi_accepts++; 3646 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 3647 break; 3648 3649 case FC_ELS_LS_RJT: 3650 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); 3651 3652 bfa_trc(port->fcs, ls_rjt->reason_code); 3653 bfa_trc(port->fcs, ls_rjt->reason_code_expl); 3654 3655 port->stats.ns_rejects++; 3656 3657 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3658 break; 3659 3660 default: 3661 port->stats.ns_plogi_unknown_rsp++; 3662 bfa_trc(port->fcs, els_cmd->els_code); 3663 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3664 } 3665 } 3666 3667 /* 3668 * Register the symbolic port name. 3669 */ 3670 static void 3671 bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) 3672 { 3673 struct bfa_fcs_lport_ns_s *ns = ns_cbarg; 3674 struct bfa_fcs_lport_s *port = ns->port; 3675 struct fchs_s fchs; 3676 int len; 3677 struct bfa_fcxp_s *fcxp; 3678 u8 symbl[256]; 3679 u8 *psymbl = &symbl[0]; 3680 3681 memset(symbl, 0, sizeof(symbl)); 3682 3683 bfa_trc(port->fcs, port->port_cfg.pwwn); 3684 3685 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 3686 if (!fcxp) { 3687 port->stats.ns_rspnid_alloc_wait++; 3688 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 3689 bfa_fcs_lport_ns_send_rspn_id, ns); 3690 return; 3691 } 3692 ns->fcxp = fcxp; 3693 3694 /* 3695 * for V-Port, form a Port Symbolic Name 3696 */ 3697 if (port->vport) { 3698 /* 3699 * For Vports, we append the vport's port symbolic name 3700 * to that of the base port. 3701 */ 3702 3703 strncpy((char *)psymbl, 3704 (char *) & 3705 (bfa_fcs_lport_get_psym_name 3706 (bfa_fcs_get_base_port(port->fcs))), 3707 strlen((char *) & 3708 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port 3709 (port->fcs)))); 3710 3711 /* Ensure we have a null terminating string. */ 3712 ((char *)psymbl)[strlen((char *) & 3713 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port 3714 (port->fcs)))] = 0; 3715 strncat((char *)psymbl, 3716 (char *) &(bfa_fcs_lport_get_psym_name(port)), 3717 strlen((char *) &bfa_fcs_lport_get_psym_name(port))); 3718 } else { 3719 psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port)); 3720 } 3721 3722 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 3723 bfa_fcs_lport_get_fcid(port), 0, psymbl); 3724 3725 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 3726 FC_CLASS_3, len, &fchs, 3727 bfa_fcs_lport_ns_rspn_id_response, (void *)ns, 3728 FC_MAX_PDUSZ, FC_FCCT_TOV); 3729 3730 port->stats.ns_rspnid_sent++; 3731 3732 bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT); 3733 } 3734 3735 static void 3736 bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 3737 void *cbarg, bfa_status_t req_status, 3738 u32 rsp_len, u32 resid_len, 3739 struct fchs_s *rsp_fchs) 3740 { 3741 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; 3742 struct bfa_fcs_lport_s *port = ns->port; 3743 struct ct_hdr_s *cthdr = NULL; 3744 3745 bfa_trc(port->fcs, port->port_cfg.pwwn); 3746 3747 /* 3748 * Sanity Checks 3749 */ 3750 if (req_status != BFA_STATUS_OK) { 3751 bfa_trc(port->fcs, req_status); 3752 port->stats.ns_rspnid_rsp_err++; 3753 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3754 return; 3755 } 3756 3757 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 3758 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 3759 3760 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 3761 port->stats.ns_rspnid_accepts++; 3762 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 3763 return; 3764 } 3765 3766 port->stats.ns_rspnid_rejects++; 3767 bfa_trc(port->fcs, cthdr->reason_code); 3768 bfa_trc(port->fcs, cthdr->exp_code); 3769 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3770 } 3771 3772 /* 3773 * Register FC4-Types 3774 */ 3775 static void 3776 bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) 3777 { 3778 struct bfa_fcs_lport_ns_s *ns = ns_cbarg; 3779 struct bfa_fcs_lport_s *port = ns->port; 3780 struct fchs_s fchs; 3781 int len; 3782 struct bfa_fcxp_s *fcxp; 3783 3784 bfa_trc(port->fcs, port->port_cfg.pwwn); 3785 3786 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 3787 if (!fcxp) { 3788 port->stats.ns_rftid_alloc_wait++; 3789 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 3790 bfa_fcs_lport_ns_send_rft_id, ns); 3791 return; 3792 } 3793 ns->fcxp = fcxp; 3794 3795 len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 3796 bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles); 3797 3798 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 3799 FC_CLASS_3, len, &fchs, 3800 bfa_fcs_lport_ns_rft_id_response, (void *)ns, 3801 FC_MAX_PDUSZ, FC_FCCT_TOV); 3802 3803 port->stats.ns_rftid_sent++; 3804 bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT); 3805 } 3806 3807 static void 3808 bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 3809 void *cbarg, bfa_status_t req_status, 3810 u32 rsp_len, u32 resid_len, 3811 struct fchs_s *rsp_fchs) 3812 { 3813 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; 3814 struct bfa_fcs_lport_s *port = ns->port; 3815 struct ct_hdr_s *cthdr = NULL; 3816 3817 bfa_trc(port->fcs, port->port_cfg.pwwn); 3818 3819 /* 3820 * Sanity Checks 3821 */ 3822 if (req_status != BFA_STATUS_OK) { 3823 bfa_trc(port->fcs, req_status); 3824 port->stats.ns_rftid_rsp_err++; 3825 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3826 return; 3827 } 3828 3829 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 3830 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 3831 3832 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 3833 port->stats.ns_rftid_accepts++; 3834 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 3835 return; 3836 } 3837 3838 port->stats.ns_rftid_rejects++; 3839 bfa_trc(port->fcs, cthdr->reason_code); 3840 bfa_trc(port->fcs, cthdr->exp_code); 3841 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3842 } 3843 3844 /* 3845 * Register FC4-Features : Should be done after RFT_ID 3846 */ 3847 static void 3848 bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) 3849 { 3850 struct bfa_fcs_lport_ns_s *ns = ns_cbarg; 3851 struct bfa_fcs_lport_s *port = ns->port; 3852 struct fchs_s fchs; 3853 int len; 3854 struct bfa_fcxp_s *fcxp; 3855 u8 fc4_ftrs = 0; 3856 3857 bfa_trc(port->fcs, port->port_cfg.pwwn); 3858 3859 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 3860 if (!fcxp) { 3861 port->stats.ns_rffid_alloc_wait++; 3862 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 3863 bfa_fcs_lport_ns_send_rff_id, ns); 3864 return; 3865 } 3866 ns->fcxp = fcxp; 3867 3868 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) 3869 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR; 3870 3871 len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 3872 bfa_fcs_lport_get_fcid(port), 0, 3873 FC_TYPE_FCP, fc4_ftrs); 3874 3875 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 3876 FC_CLASS_3, len, &fchs, 3877 bfa_fcs_lport_ns_rff_id_response, (void *)ns, 3878 FC_MAX_PDUSZ, FC_FCCT_TOV); 3879 3880 port->stats.ns_rffid_sent++; 3881 bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT); 3882 } 3883 3884 static void 3885 bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 3886 void *cbarg, bfa_status_t req_status, 3887 u32 rsp_len, u32 resid_len, 3888 struct fchs_s *rsp_fchs) 3889 { 3890 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; 3891 struct bfa_fcs_lport_s *port = ns->port; 3892 struct ct_hdr_s *cthdr = NULL; 3893 3894 bfa_trc(port->fcs, port->port_cfg.pwwn); 3895 3896 /* 3897 * Sanity Checks 3898 */ 3899 if (req_status != BFA_STATUS_OK) { 3900 bfa_trc(port->fcs, req_status); 3901 port->stats.ns_rffid_rsp_err++; 3902 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3903 return; 3904 } 3905 3906 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 3907 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 3908 3909 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 3910 port->stats.ns_rffid_accepts++; 3911 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 3912 return; 3913 } 3914 3915 port->stats.ns_rffid_rejects++; 3916 bfa_trc(port->fcs, cthdr->reason_code); 3917 bfa_trc(port->fcs, cthdr->exp_code); 3918 3919 if (cthdr->reason_code == CT_RSN_NOT_SUPP) { 3920 /* if this command is not supported, we don't retry */ 3921 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 3922 } else 3923 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3924 } 3925 /* 3926 * Query Fabric for FC4-Types Devices. 3927 * 3928 * TBD : Need to use a local (FCS private) response buffer, since the response 3929 * can be larger than 2K. 3930 */ 3931 static void 3932 bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) 3933 { 3934 struct bfa_fcs_lport_ns_s *ns = ns_cbarg; 3935 struct bfa_fcs_lport_s *port = ns->port; 3936 struct fchs_s fchs; 3937 int len; 3938 struct bfa_fcxp_s *fcxp; 3939 3940 bfa_trc(port->fcs, port->pid); 3941 3942 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 3943 if (!fcxp) { 3944 port->stats.ns_gidft_alloc_wait++; 3945 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 3946 bfa_fcs_lport_ns_send_gid_ft, ns); 3947 return; 3948 } 3949 ns->fcxp = fcxp; 3950 3951 /* 3952 * This query is only initiated for FCP initiator mode. 3953 */ 3954 len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 3955 ns->port->pid, FC_TYPE_FCP); 3956 3957 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 3958 FC_CLASS_3, len, &fchs, 3959 bfa_fcs_lport_ns_gid_ft_response, (void *)ns, 3960 bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV); 3961 3962 port->stats.ns_gidft_sent++; 3963 3964 bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT); 3965 } 3966 3967 static void 3968 bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 3969 void *cbarg, bfa_status_t req_status, 3970 u32 rsp_len, u32 resid_len, 3971 struct fchs_s *rsp_fchs) 3972 { 3973 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; 3974 struct bfa_fcs_lport_s *port = ns->port; 3975 struct ct_hdr_s *cthdr = NULL; 3976 u32 n_pids; 3977 3978 bfa_trc(port->fcs, port->port_cfg.pwwn); 3979 3980 /* 3981 * Sanity Checks 3982 */ 3983 if (req_status != BFA_STATUS_OK) { 3984 bfa_trc(port->fcs, req_status); 3985 port->stats.ns_gidft_rsp_err++; 3986 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 3987 return; 3988 } 3989 3990 if (resid_len != 0) { 3991 /* 3992 * TBD : we will need to allocate a larger buffer & retry the 3993 * command 3994 */ 3995 bfa_trc(port->fcs, rsp_len); 3996 bfa_trc(port->fcs, resid_len); 3997 return; 3998 } 3999 4000 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 4001 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 4002 4003 switch (cthdr->cmd_rsp_code) { 4004 4005 case CT_RSP_ACCEPT: 4006 4007 port->stats.ns_gidft_accepts++; 4008 n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32)); 4009 bfa_trc(port->fcs, n_pids); 4010 bfa_fcs_lport_ns_process_gidft_pids(port, 4011 (u32 *) (cthdr + 1), 4012 n_pids); 4013 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 4014 break; 4015 4016 case CT_RSP_REJECT: 4017 4018 /* 4019 * Check the reason code & explanation. 4020 * There may not have been any FC4 devices in the fabric 4021 */ 4022 port->stats.ns_gidft_rejects++; 4023 bfa_trc(port->fcs, cthdr->reason_code); 4024 bfa_trc(port->fcs, cthdr->exp_code); 4025 4026 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF) 4027 && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) { 4028 4029 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 4030 } else { 4031 /* 4032 * for all other errors, retry 4033 */ 4034 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 4035 } 4036 break; 4037 4038 default: 4039 port->stats.ns_gidft_unknown_rsp++; 4040 bfa_trc(port->fcs, cthdr->cmd_rsp_code); 4041 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 4042 } 4043 } 4044 4045 /* 4046 * This routine will be called by bfa_timer on timer timeouts. 4047 * 4048 * param[in] port - pointer to bfa_fcs_lport_t. 4049 * 4050 * return 4051 * void 4052 * 4053 * Special Considerations: 4054 * 4055 * note 4056 */ 4057 static void 4058 bfa_fcs_lport_ns_timeout(void *arg) 4059 { 4060 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg; 4061 4062 ns->port->stats.ns_timeouts++; 4063 bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT); 4064 } 4065 4066 /* 4067 * Process the PID list in GID_FT response 4068 */ 4069 static void 4070 bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf, 4071 u32 n_pids) 4072 { 4073 struct fcgs_gidft_resp_s *gidft_entry; 4074 struct bfa_fcs_rport_s *rport; 4075 u32 ii; 4076 4077 for (ii = 0; ii < n_pids; ii++) { 4078 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii]; 4079 4080 if (gidft_entry->pid == port->pid) 4081 continue; 4082 4083 /* 4084 * Check if this rport already exists 4085 */ 4086 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid); 4087 if (rport == NULL) { 4088 /* 4089 * this is a new device. create rport 4090 */ 4091 rport = bfa_fcs_rport_create(port, gidft_entry->pid); 4092 } else { 4093 /* 4094 * this rport already exists 4095 */ 4096 bfa_fcs_rport_scn(rport); 4097 } 4098 4099 bfa_trc(port->fcs, gidft_entry->pid); 4100 4101 /* 4102 * if the last entry bit is set, bail out. 4103 */ 4104 if (gidft_entry->last) 4105 return; 4106 } 4107 } 4108 4109 /* 4110 * fcs_ns_public FCS nameserver public interfaces 4111 */ 4112 4113 /* 4114 * Functions called by port/fab. 4115 * These will send relevant Events to the ns state machine. 4116 */ 4117 void 4118 bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port) 4119 { 4120 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); 4121 4122 ns->port = port; 4123 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 4124 } 4125 4126 void 4127 bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port) 4128 { 4129 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); 4130 4131 ns->port = port; 4132 bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE); 4133 } 4134 4135 void 4136 bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port) 4137 { 4138 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); 4139 4140 ns->port = port; 4141 bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE); 4142 } 4143 4144 void 4145 bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port) 4146 { 4147 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); 4148 4149 bfa_trc(port->fcs, port->pid); 4150 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY); 4151 } 4152 4153 void 4154 bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port) 4155 { 4156 4157 struct bfa_fcs_rport_s *rport; 4158 u8 nwwns; 4159 wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX]; 4160 int ii; 4161 4162 bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns); 4163 4164 for (ii = 0 ; ii < nwwns; ++ii) { 4165 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]); 4166 bfa_assert(rport); 4167 } 4168 } 4169 4170 /* 4171 * FCS SCN 4172 */ 4173 4174 #define FC_QOS_RSCN_EVENT 0x0c 4175 #define FC_FABRIC_NAME_RSCN_EVENT 0x0d 4176 4177 /* 4178 * forward declarations 4179 */ 4180 static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg, 4181 struct bfa_fcxp_s *fcxp_alloced); 4182 static void bfa_fcs_lport_scn_scr_response(void *fcsarg, 4183 struct bfa_fcxp_s *fcxp, 4184 void *cbarg, 4185 bfa_status_t req_status, 4186 u32 rsp_len, 4187 u32 resid_len, 4188 struct fchs_s *rsp_fchs); 4189 static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port, 4190 struct fchs_s *rx_fchs); 4191 static void bfa_fcs_lport_scn_timeout(void *arg); 4192 4193 /* 4194 * fcs_scm_sm FCS SCN state machine 4195 */ 4196 4197 /* 4198 * VPort SCN State Machine events 4199 */ 4200 enum port_scn_event { 4201 SCNSM_EVENT_PORT_ONLINE = 1, 4202 SCNSM_EVENT_PORT_OFFLINE = 2, 4203 SCNSM_EVENT_RSP_OK = 3, 4204 SCNSM_EVENT_RSP_ERROR = 4, 4205 SCNSM_EVENT_TIMEOUT = 5, 4206 SCNSM_EVENT_SCR_SENT = 6, 4207 }; 4208 4209 static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn, 4210 enum port_scn_event event); 4211 static void bfa_fcs_lport_scn_sm_sending_scr( 4212 struct bfa_fcs_lport_scn_s *scn, 4213 enum port_scn_event event); 4214 static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn, 4215 enum port_scn_event event); 4216 static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn, 4217 enum port_scn_event event); 4218 static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn, 4219 enum port_scn_event event); 4220 4221 /* 4222 * Starting state - awaiting link up. 4223 */ 4224 static void 4225 bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn, 4226 enum port_scn_event event) 4227 { 4228 switch (event) { 4229 case SCNSM_EVENT_PORT_ONLINE: 4230 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr); 4231 bfa_fcs_lport_scn_send_scr(scn, NULL); 4232 break; 4233 4234 case SCNSM_EVENT_PORT_OFFLINE: 4235 break; 4236 4237 default: 4238 bfa_sm_fault(scn->port->fcs, event); 4239 } 4240 } 4241 4242 static void 4243 bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn, 4244 enum port_scn_event event) 4245 { 4246 switch (event) { 4247 case SCNSM_EVENT_SCR_SENT: 4248 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr); 4249 break; 4250 4251 case SCNSM_EVENT_PORT_OFFLINE: 4252 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 4253 bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe); 4254 break; 4255 4256 default: 4257 bfa_sm_fault(scn->port->fcs, event); 4258 } 4259 } 4260 4261 static void 4262 bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn, 4263 enum port_scn_event event) 4264 { 4265 struct bfa_fcs_lport_s *port = scn->port; 4266 4267 switch (event) { 4268 case SCNSM_EVENT_RSP_OK: 4269 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online); 4270 break; 4271 4272 case SCNSM_EVENT_RSP_ERROR: 4273 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry); 4274 bfa_timer_start(port->fcs->bfa, &scn->timer, 4275 bfa_fcs_lport_scn_timeout, scn, 4276 BFA_FCS_RETRY_TIMEOUT); 4277 break; 4278 4279 case SCNSM_EVENT_PORT_OFFLINE: 4280 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 4281 bfa_fcxp_discard(scn->fcxp); 4282 break; 4283 4284 default: 4285 bfa_sm_fault(port->fcs, event); 4286 } 4287 } 4288 4289 static void 4290 bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn, 4291 enum port_scn_event event) 4292 { 4293 switch (event) { 4294 case SCNSM_EVENT_TIMEOUT: 4295 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr); 4296 bfa_fcs_lport_scn_send_scr(scn, NULL); 4297 break; 4298 4299 case SCNSM_EVENT_PORT_OFFLINE: 4300 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 4301 bfa_timer_stop(&scn->timer); 4302 break; 4303 4304 default: 4305 bfa_sm_fault(scn->port->fcs, event); 4306 } 4307 } 4308 4309 static void 4310 bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn, 4311 enum port_scn_event event) 4312 { 4313 switch (event) { 4314 case SCNSM_EVENT_PORT_OFFLINE: 4315 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 4316 break; 4317 4318 default: 4319 bfa_sm_fault(scn->port->fcs, event); 4320 } 4321 } 4322 4323 4324 4325 /* 4326 * fcs_scn_private FCS SCN private functions 4327 */ 4328 4329 /* 4330 * This routine will be called to send a SCR command. 4331 */ 4332 static void 4333 bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced) 4334 { 4335 struct bfa_fcs_lport_scn_s *scn = scn_cbarg; 4336 struct bfa_fcs_lport_s *port = scn->port; 4337 struct fchs_s fchs; 4338 int len; 4339 struct bfa_fcxp_s *fcxp; 4340 4341 bfa_trc(port->fcs, port->pid); 4342 bfa_trc(port->fcs, port->port_cfg.pwwn); 4343 4344 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 4345 if (!fcxp) { 4346 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe, 4347 bfa_fcs_lport_scn_send_scr, scn); 4348 return; 4349 } 4350 scn->fcxp = fcxp; 4351 4352 /* Handle VU registrations for Base port only */ 4353 if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) { 4354 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 4355 bfa_lps_is_brcd_fabric(port->fabric->lps), 4356 port->pid, 0); 4357 } else { 4358 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 4359 BFA_FALSE, 4360 port->pid, 0); 4361 } 4362 4363 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 4364 FC_CLASS_3, len, &fchs, 4365 bfa_fcs_lport_scn_scr_response, 4366 (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV); 4367 4368 bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT); 4369 } 4370 4371 static void 4372 bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 4373 void *cbarg, bfa_status_t req_status, u32 rsp_len, 4374 u32 resid_len, struct fchs_s *rsp_fchs) 4375 { 4376 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg; 4377 struct bfa_fcs_lport_s *port = scn->port; 4378 struct fc_els_cmd_s *els_cmd; 4379 struct fc_ls_rjt_s *ls_rjt; 4380 4381 bfa_trc(port->fcs, port->port_cfg.pwwn); 4382 4383 /* 4384 * Sanity Checks 4385 */ 4386 if (req_status != BFA_STATUS_OK) { 4387 bfa_trc(port->fcs, req_status); 4388 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); 4389 return; 4390 } 4391 4392 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); 4393 4394 switch (els_cmd->els_code) { 4395 4396 case FC_ELS_ACC: 4397 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK); 4398 break; 4399 4400 case FC_ELS_LS_RJT: 4401 4402 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); 4403 4404 bfa_trc(port->fcs, ls_rjt->reason_code); 4405 bfa_trc(port->fcs, ls_rjt->reason_code_expl); 4406 4407 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); 4408 break; 4409 4410 default: 4411 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); 4412 } 4413 } 4414 4415 /* 4416 * Send a LS Accept 4417 */ 4418 static void 4419 bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port, 4420 struct fchs_s *rx_fchs) 4421 { 4422 struct fchs_s fchs; 4423 struct bfa_fcxp_s *fcxp; 4424 struct bfa_rport_s *bfa_rport = NULL; 4425 int len; 4426 4427 bfa_trc(port->fcs, rx_fchs->s_id); 4428 4429 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 4430 if (!fcxp) 4431 return; 4432 4433 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 4434 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 4435 rx_fchs->ox_id); 4436 4437 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 4438 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 4439 FC_MAX_PDUSZ, 0); 4440 } 4441 4442 /* 4443 * This routine will be called by bfa_timer on timer timeouts. 4444 * 4445 * param[in] vport - pointer to bfa_fcs_lport_t. 4446 * param[out] vport_status - pointer to return vport status in 4447 * 4448 * return 4449 * void 4450 * 4451 * Special Considerations: 4452 * 4453 * note 4454 */ 4455 static void 4456 bfa_fcs_lport_scn_timeout(void *arg) 4457 { 4458 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg; 4459 4460 bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT); 4461 } 4462 4463 4464 4465 /* 4466 * fcs_scn_public FCS state change notification public interfaces 4467 */ 4468 4469 /* 4470 * Functions called by port/fab 4471 */ 4472 void 4473 bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port) 4474 { 4475 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); 4476 4477 scn->port = port; 4478 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 4479 } 4480 4481 void 4482 bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port) 4483 { 4484 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); 4485 4486 scn->port = port; 4487 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE); 4488 } 4489 4490 void 4491 bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port) 4492 { 4493 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); 4494 4495 scn->port = port; 4496 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE); 4497 } 4498 4499 static void 4500 bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid) 4501 { 4502 struct bfa_fcs_rport_s *rport; 4503 4504 bfa_trc(port->fcs, rpid); 4505 4506 /* 4507 * If this is an unknown device, then it just came online. 4508 * Otherwise let rport handle the RSCN event. 4509 */ 4510 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid); 4511 if (rport == NULL) { 4512 /* 4513 * If min cfg mode is enabled, we donot need to 4514 * discover any new rports. 4515 */ 4516 if (!__fcs_min_cfg(port->fcs)) 4517 rport = bfa_fcs_rport_create(port, rpid); 4518 } else 4519 bfa_fcs_rport_scn(rport); 4520 } 4521 4522 /* 4523 * rscn format based PID comparison 4524 */ 4525 #define __fc_pid_match(__c0, __c1, __fmt) \ 4526 (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \ 4527 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \ 4528 ((__c0)[0] == (__c1)[0])) || \ 4529 (((__fmt) == FC_RSCN_FORMAT_AREA) && \ 4530 ((__c0)[0] == (__c1)[0]) && \ 4531 ((__c0)[1] == (__c1)[1]))) 4532 4533 static void 4534 bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port, 4535 enum fc_rscn_format format, 4536 u32 rscn_pid) 4537 { 4538 struct bfa_fcs_rport_s *rport; 4539 struct list_head *qe, *qe_next; 4540 u8 *c0, *c1; 4541 4542 bfa_trc(port->fcs, format); 4543 bfa_trc(port->fcs, rscn_pid); 4544 4545 c0 = (u8 *) &rscn_pid; 4546 4547 list_for_each_safe(qe, qe_next, &port->rport_q) { 4548 rport = (struct bfa_fcs_rport_s *) qe; 4549 c1 = (u8 *) &rport->pid; 4550 if (__fc_pid_match(c0, c1, format)) 4551 bfa_fcs_rport_scn(rport); 4552 } 4553 } 4554 4555 4556 void 4557 bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port, 4558 struct fchs_s *fchs, u32 len) 4559 { 4560 struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1); 4561 int num_entries; 4562 u32 rscn_pid; 4563 bfa_boolean_t nsquery = BFA_FALSE, found; 4564 int i = 0, j; 4565 4566 num_entries = 4567 (be16_to_cpu(rscn->payldlen) - 4568 sizeof(u32)) / sizeof(rscn->event[0]); 4569 4570 bfa_trc(port->fcs, num_entries); 4571 4572 port->stats.num_rscn++; 4573 4574 bfa_fcs_lport_scn_send_ls_acc(port, fchs); 4575 4576 for (i = 0; i < num_entries; i++) { 4577 rscn_pid = rscn->event[i].portid; 4578 4579 bfa_trc(port->fcs, rscn->event[i].format); 4580 bfa_trc(port->fcs, rscn_pid); 4581 4582 /* check for duplicate entries in the list */ 4583 found = BFA_FALSE; 4584 for (j = 0; j < i; j++) { 4585 if (rscn->event[j].portid == rscn_pid) { 4586 found = BFA_TRUE; 4587 break; 4588 } 4589 } 4590 4591 /* if found in down the list, pid has been already processed */ 4592 if (found) { 4593 bfa_trc(port->fcs, rscn_pid); 4594 continue; 4595 } 4596 4597 switch (rscn->event[i].format) { 4598 case FC_RSCN_FORMAT_PORTID: 4599 if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) { 4600 /* 4601 * Ignore this event. 4602 * f/w would have processed it 4603 */ 4604 bfa_trc(port->fcs, rscn_pid); 4605 } else { 4606 port->stats.num_portid_rscn++; 4607 bfa_fcs_lport_scn_portid_rscn(port, rscn_pid); 4608 } 4609 break; 4610 4611 case FC_RSCN_FORMAT_FABRIC: 4612 if (rscn->event[i].qualifier == 4613 FC_FABRIC_NAME_RSCN_EVENT) { 4614 bfa_fcs_lport_ms_fabric_rscn(port); 4615 break; 4616 } 4617 /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */ 4618 4619 case FC_RSCN_FORMAT_AREA: 4620 case FC_RSCN_FORMAT_DOMAIN: 4621 nsquery = BFA_TRUE; 4622 bfa_fcs_lport_scn_multiport_rscn(port, 4623 rscn->event[i].format, 4624 rscn_pid); 4625 break; 4626 4627 4628 default: 4629 bfa_assert(0); 4630 nsquery = BFA_TRUE; 4631 } 4632 } 4633 4634 /* 4635 * If any of area, domain or fabric RSCN is received, do a fresh 4636 * discovery to find new devices. 4637 */ 4638 if (nsquery) 4639 bfa_fcs_lport_ns_query(port); 4640 } 4641 4642 /* 4643 * BFA FCS port 4644 */ 4645 /* 4646 * fcs_port_api BFA FCS port API 4647 */ 4648 struct bfa_fcs_lport_s * 4649 bfa_fcs_get_base_port(struct bfa_fcs_s *fcs) 4650 { 4651 return &fcs->fabric.bport; 4652 } 4653 4654 wwn_t 4655 bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index, 4656 int nrports, bfa_boolean_t bwwn) 4657 { 4658 struct list_head *qh, *qe; 4659 struct bfa_fcs_rport_s *rport = NULL; 4660 int i; 4661 struct bfa_fcs_s *fcs; 4662 4663 if (port == NULL || nrports == 0) 4664 return (wwn_t) 0; 4665 4666 fcs = port->fcs; 4667 bfa_trc(fcs, (u32) nrports); 4668 4669 i = 0; 4670 qh = &port->rport_q; 4671 qe = bfa_q_first(qh); 4672 4673 while ((qe != qh) && (i < nrports)) { 4674 rport = (struct bfa_fcs_rport_s *) qe; 4675 if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) { 4676 qe = bfa_q_next(qe); 4677 bfa_trc(fcs, (u32) rport->pwwn); 4678 bfa_trc(fcs, rport->pid); 4679 bfa_trc(fcs, i); 4680 continue; 4681 } 4682 4683 if (bwwn) { 4684 if (!memcmp(&wwn, &rport->pwwn, 8)) 4685 break; 4686 } else { 4687 if (i == index) 4688 break; 4689 } 4690 4691 i++; 4692 qe = bfa_q_next(qe); 4693 } 4694 4695 bfa_trc(fcs, i); 4696 if (rport) 4697 return rport->pwwn; 4698 else 4699 return (wwn_t) 0; 4700 } 4701 4702 void 4703 bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port, 4704 wwn_t rport_wwns[], int *nrports) 4705 { 4706 struct list_head *qh, *qe; 4707 struct bfa_fcs_rport_s *rport = NULL; 4708 int i; 4709 struct bfa_fcs_s *fcs; 4710 4711 if (port == NULL || rport_wwns == NULL || *nrports == 0) 4712 return; 4713 4714 fcs = port->fcs; 4715 bfa_trc(fcs, (u32) *nrports); 4716 4717 i = 0; 4718 qh = &port->rport_q; 4719 qe = bfa_q_first(qh); 4720 4721 while ((qe != qh) && (i < *nrports)) { 4722 rport = (struct bfa_fcs_rport_s *) qe; 4723 if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) { 4724 qe = bfa_q_next(qe); 4725 bfa_trc(fcs, (u32) rport->pwwn); 4726 bfa_trc(fcs, rport->pid); 4727 bfa_trc(fcs, i); 4728 continue; 4729 } 4730 4731 rport_wwns[i] = rport->pwwn; 4732 4733 i++; 4734 qe = bfa_q_next(qe); 4735 } 4736 4737 bfa_trc(fcs, i); 4738 *nrports = i; 4739 } 4740 4741 /* 4742 * Iterate's through all the rport's in the given port to 4743 * determine the maximum operating speed. 4744 * 4745 * !!!! To be used in TRL Functionality only !!!! 4746 */ 4747 bfa_port_speed_t 4748 bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port) 4749 { 4750 struct list_head *qh, *qe; 4751 struct bfa_fcs_rport_s *rport = NULL; 4752 struct bfa_fcs_s *fcs; 4753 bfa_port_speed_t max_speed = 0; 4754 struct bfa_port_attr_s port_attr; 4755 bfa_port_speed_t port_speed, rport_speed; 4756 bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa); 4757 4758 4759 if (port == NULL) 4760 return 0; 4761 4762 fcs = port->fcs; 4763 4764 /* Get Physical port's current speed */ 4765 bfa_fcport_get_attr(port->fcs->bfa, &port_attr); 4766 port_speed = port_attr.speed; 4767 bfa_trc(fcs, port_speed); 4768 4769 qh = &port->rport_q; 4770 qe = bfa_q_first(qh); 4771 4772 while (qe != qh) { 4773 rport = (struct bfa_fcs_rport_s *) qe; 4774 if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) || 4775 (bfa_fcs_rport_get_state(rport) == 4776 BFA_RPORT_OFFLINE)) { 4777 qe = bfa_q_next(qe); 4778 continue; 4779 } 4780 4781 rport_speed = rport->rpf.rpsc_speed; 4782 if ((trl_enabled) && (rport_speed == 4783 BFA_PORT_SPEED_UNKNOWN)) { 4784 /* Use default ratelim speed setting */ 4785 rport_speed = 4786 bfa_fcport_get_ratelim_speed(port->fcs->bfa); 4787 } 4788 4789 if ((rport_speed == BFA_PORT_SPEED_8GBPS) || 4790 (rport_speed > port_speed)) { 4791 max_speed = rport_speed; 4792 break; 4793 } else if (rport_speed > max_speed) { 4794 max_speed = rport_speed; 4795 } 4796 4797 qe = bfa_q_next(qe); 4798 } 4799 4800 bfa_trc(fcs, max_speed); 4801 return max_speed; 4802 } 4803 4804 struct bfa_fcs_lport_s * 4805 bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn) 4806 { 4807 struct bfa_fcs_vport_s *vport; 4808 bfa_fcs_vf_t *vf; 4809 4810 bfa_assert(fcs != NULL); 4811 4812 vf = bfa_fcs_vf_lookup(fcs, vf_id); 4813 if (vf == NULL) { 4814 bfa_trc(fcs, vf_id); 4815 return NULL; 4816 } 4817 4818 if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn)) 4819 return &vf->bport; 4820 4821 vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn); 4822 if (vport) 4823 return &vport->lport; 4824 4825 return NULL; 4826 } 4827 4828 /* 4829 * API corresponding to NPIV_VPORT_GETINFO. 4830 */ 4831 void 4832 bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port, 4833 struct bfa_lport_info_s *port_info) 4834 { 4835 4836 bfa_trc(port->fcs, port->fabric->fabric_name); 4837 4838 if (port->vport == NULL) { 4839 /* 4840 * This is a Physical port 4841 */ 4842 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL; 4843 4844 /* 4845 * @todo : need to fix the state & reason 4846 */ 4847 port_info->port_state = 0; 4848 port_info->offline_reason = 0; 4849 4850 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port); 4851 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port); 4852 4853 port_info->max_vports_supp = 4854 bfa_lps_get_max_vport(port->fcs->bfa); 4855 port_info->num_vports_inuse = 4856 bfa_fcs_fabric_vport_count(port->fabric); 4857 port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP; 4858 port_info->num_rports_inuse = port->num_rports; 4859 } else { 4860 /* 4861 * This is a virtual port 4862 */ 4863 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL; 4864 4865 /* 4866 * @todo : need to fix the state & reason 4867 */ 4868 port_info->port_state = 0; 4869 port_info->offline_reason = 0; 4870 4871 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port); 4872 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port); 4873 } 4874 } 4875 4876 void 4877 bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port, 4878 struct bfa_lport_stats_s *port_stats) 4879 { 4880 *port_stats = fcs_port->stats; 4881 } 4882 4883 void 4884 bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port) 4885 { 4886 memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s)); 4887 } 4888 4889 /* 4890 * FCS virtual port state machine 4891 */ 4892 4893 #define __vport_fcs(__vp) ((__vp)->lport.fcs) 4894 #define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn) 4895 #define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn) 4896 #define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa) 4897 #define __vport_fcid(__vp) ((__vp)->lport.pid) 4898 #define __vport_fabric(__vp) ((__vp)->lport.fabric) 4899 #define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id) 4900 4901 #define BFA_FCS_VPORT_MAX_RETRIES 5 4902 /* 4903 * Forward declarations 4904 */ 4905 static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport); 4906 static void bfa_fcs_vport_timeout(void *vport_arg); 4907 static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport); 4908 static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport); 4909 4910 /* 4911 * fcs_vport_sm FCS virtual port state machine 4912 */ 4913 4914 /* 4915 * VPort State Machine events 4916 */ 4917 enum bfa_fcs_vport_event { 4918 BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */ 4919 BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */ 4920 BFA_FCS_VPORT_SM_START = 3, /* vport start request */ 4921 BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */ 4922 BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */ 4923 BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */ 4924 BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */ 4925 BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */ 4926 BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */ 4927 BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */ 4928 BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */ 4929 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/ 4930 BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */ 4931 }; 4932 4933 static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, 4934 enum bfa_fcs_vport_event event); 4935 static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, 4936 enum bfa_fcs_vport_event event); 4937 static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, 4938 enum bfa_fcs_vport_event event); 4939 static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, 4940 enum bfa_fcs_vport_event event); 4941 static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, 4942 enum bfa_fcs_vport_event event); 4943 static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, 4944 enum bfa_fcs_vport_event event); 4945 static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, 4946 enum bfa_fcs_vport_event event); 4947 static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, 4948 enum bfa_fcs_vport_event event); 4949 static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, 4950 enum bfa_fcs_vport_event event); 4951 static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, 4952 enum bfa_fcs_vport_event event); 4953 4954 static struct bfa_sm_table_s vport_sm_table[] = { 4955 {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT}, 4956 {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED}, 4957 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE}, 4958 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC}, 4959 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY}, 4960 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE}, 4961 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING}, 4962 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP}, 4963 {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO}, 4964 {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR} 4965 }; 4966 4967 /* 4968 * Beginning state. 4969 */ 4970 static void 4971 bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, 4972 enum bfa_fcs_vport_event event) 4973 { 4974 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 4975 bfa_trc(__vport_fcs(vport), event); 4976 4977 switch (event) { 4978 case BFA_FCS_VPORT_SM_CREATE: 4979 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); 4980 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport); 4981 break; 4982 4983 default: 4984 bfa_sm_fault(__vport_fcs(vport), event); 4985 } 4986 } 4987 4988 /* 4989 * Created state - a start event is required to start up the state machine. 4990 */ 4991 static void 4992 bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, 4993 enum bfa_fcs_vport_event event) 4994 { 4995 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 4996 bfa_trc(__vport_fcs(vport), event); 4997 4998 switch (event) { 4999 case BFA_FCS_VPORT_SM_START: 5000 if (bfa_fcs_fabric_is_online(__vport_fabric(vport)) 5001 && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) { 5002 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); 5003 bfa_fcs_vport_do_fdisc(vport); 5004 } else { 5005 /* 5006 * Fabric is offline or not NPIV capable, stay in 5007 * offline state. 5008 */ 5009 vport->vport_stats.fab_no_npiv++; 5010 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 5011 } 5012 break; 5013 5014 case BFA_FCS_VPORT_SM_DELETE: 5015 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 5016 bfa_fcs_lport_delete(&vport->lport); 5017 break; 5018 5019 case BFA_FCS_VPORT_SM_ONLINE: 5020 case BFA_FCS_VPORT_SM_OFFLINE: 5021 /* 5022 * Ignore ONLINE/OFFLINE events from fabric 5023 * till vport is started. 5024 */ 5025 break; 5026 5027 default: 5028 bfa_sm_fault(__vport_fcs(vport), event); 5029 } 5030 } 5031 5032 /* 5033 * Offline state - awaiting ONLINE event from fabric SM. 5034 */ 5035 static void 5036 bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, 5037 enum bfa_fcs_vport_event event) 5038 { 5039 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5040 bfa_trc(__vport_fcs(vport), event); 5041 5042 switch (event) { 5043 case BFA_FCS_VPORT_SM_DELETE: 5044 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 5045 bfa_fcs_lport_delete(&vport->lport); 5046 break; 5047 5048 case BFA_FCS_VPORT_SM_ONLINE: 5049 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); 5050 vport->fdisc_retries = 0; 5051 bfa_fcs_vport_do_fdisc(vport); 5052 break; 5053 5054 case BFA_FCS_VPORT_SM_OFFLINE: 5055 /* 5056 * This can happen if the vport couldn't be initialzied 5057 * due the fact that the npiv was not enabled on the switch. 5058 * In that case we will put the vport in offline state. 5059 * However, the link can go down and cause the this event to 5060 * be sent when we are already offline. Ignore it. 5061 */ 5062 break; 5063 5064 default: 5065 bfa_sm_fault(__vport_fcs(vport), event); 5066 } 5067 } 5068 5069 5070 /* 5071 * FDISC is sent and awaiting reply from fabric. 5072 */ 5073 static void 5074 bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, 5075 enum bfa_fcs_vport_event event) 5076 { 5077 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5078 bfa_trc(__vport_fcs(vport), event); 5079 5080 switch (event) { 5081 case BFA_FCS_VPORT_SM_DELETE: 5082 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 5083 bfa_lps_discard(vport->lps); 5084 bfa_fcs_lport_delete(&vport->lport); 5085 break; 5086 5087 case BFA_FCS_VPORT_SM_OFFLINE: 5088 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 5089 bfa_lps_discard(vport->lps); 5090 break; 5091 5092 case BFA_FCS_VPORT_SM_RSP_OK: 5093 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online); 5094 bfa_fcs_lport_online(&vport->lport); 5095 break; 5096 5097 case BFA_FCS_VPORT_SM_RSP_ERROR: 5098 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry); 5099 bfa_timer_start(__vport_bfa(vport), &vport->timer, 5100 bfa_fcs_vport_timeout, vport, 5101 BFA_FCS_RETRY_TIMEOUT); 5102 break; 5103 5104 case BFA_FCS_VPORT_SM_RSP_FAILED: 5105 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 5106 break; 5107 5108 case BFA_FCS_VPORT_SM_RSP_DUP_WWN: 5109 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error); 5110 break; 5111 5112 default: 5113 bfa_sm_fault(__vport_fcs(vport), event); 5114 } 5115 } 5116 5117 /* 5118 * FDISC attempt failed - a timer is active to retry FDISC. 5119 */ 5120 static void 5121 bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, 5122 enum bfa_fcs_vport_event event) 5123 { 5124 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5125 bfa_trc(__vport_fcs(vport), event); 5126 5127 switch (event) { 5128 case BFA_FCS_VPORT_SM_DELETE: 5129 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 5130 bfa_timer_stop(&vport->timer); 5131 bfa_fcs_lport_delete(&vport->lport); 5132 break; 5133 5134 case BFA_FCS_VPORT_SM_OFFLINE: 5135 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 5136 bfa_timer_stop(&vport->timer); 5137 break; 5138 5139 case BFA_FCS_VPORT_SM_TIMEOUT: 5140 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); 5141 vport->vport_stats.fdisc_retries++; 5142 vport->fdisc_retries++; 5143 bfa_fcs_vport_do_fdisc(vport); 5144 break; 5145 5146 default: 5147 bfa_sm_fault(__vport_fcs(vport), event); 5148 } 5149 } 5150 5151 /* 5152 * Vport is online (FDISC is complete). 5153 */ 5154 static void 5155 bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, 5156 enum bfa_fcs_vport_event event) 5157 { 5158 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5159 bfa_trc(__vport_fcs(vport), event); 5160 5161 switch (event) { 5162 case BFA_FCS_VPORT_SM_DELETE: 5163 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting); 5164 bfa_fcs_lport_delete(&vport->lport); 5165 break; 5166 5167 case BFA_FCS_VPORT_SM_OFFLINE: 5168 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 5169 bfa_lps_discard(vport->lps); 5170 bfa_fcs_lport_offline(&vport->lport); 5171 break; 5172 5173 default: 5174 bfa_sm_fault(__vport_fcs(vport), event); 5175 } 5176 } 5177 5178 /* 5179 * Vport is being deleted - awaiting lport delete completion to send 5180 * LOGO to fabric. 5181 */ 5182 static void 5183 bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, 5184 enum bfa_fcs_vport_event event) 5185 { 5186 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5187 bfa_trc(__vport_fcs(vport), event); 5188 5189 switch (event) { 5190 case BFA_FCS_VPORT_SM_DELETE: 5191 break; 5192 5193 case BFA_FCS_VPORT_SM_DELCOMP: 5194 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo); 5195 bfa_fcs_vport_do_logo(vport); 5196 break; 5197 5198 case BFA_FCS_VPORT_SM_OFFLINE: 5199 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 5200 break; 5201 5202 default: 5203 bfa_sm_fault(__vport_fcs(vport), event); 5204 } 5205 } 5206 5207 /* 5208 * Error State. 5209 * This state will be set when the Vport Creation fails due 5210 * to errors like Dup WWN. In this state only operation allowed 5211 * is a Vport Delete. 5212 */ 5213 static void 5214 bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, 5215 enum bfa_fcs_vport_event event) 5216 { 5217 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5218 bfa_trc(__vport_fcs(vport), event); 5219 5220 switch (event) { 5221 case BFA_FCS_VPORT_SM_DELETE: 5222 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 5223 bfa_fcs_lport_delete(&vport->lport); 5224 break; 5225 5226 default: 5227 bfa_trc(__vport_fcs(vport), event); 5228 } 5229 } 5230 5231 /* 5232 * Lport cleanup is in progress since vport is being deleted. Fabric is 5233 * offline, so no LOGO is needed to complete vport deletion. 5234 */ 5235 static void 5236 bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, 5237 enum bfa_fcs_vport_event event) 5238 { 5239 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5240 bfa_trc(__vport_fcs(vport), event); 5241 5242 switch (event) { 5243 case BFA_FCS_VPORT_SM_DELCOMP: 5244 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); 5245 bfa_fcs_vport_free(vport); 5246 break; 5247 5248 case BFA_FCS_VPORT_SM_DELETE: 5249 break; 5250 5251 default: 5252 bfa_sm_fault(__vport_fcs(vport), event); 5253 } 5254 } 5255 5256 /* 5257 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup 5258 * is done. 5259 */ 5260 static void 5261 bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, 5262 enum bfa_fcs_vport_event event) 5263 { 5264 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5265 bfa_trc(__vport_fcs(vport), event); 5266 5267 switch (event) { 5268 case BFA_FCS_VPORT_SM_OFFLINE: 5269 bfa_lps_discard(vport->lps); 5270 /* 5271 * !!! fall through !!! 5272 */ 5273 5274 case BFA_FCS_VPORT_SM_RSP_OK: 5275 case BFA_FCS_VPORT_SM_RSP_ERROR: 5276 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); 5277 bfa_fcs_vport_free(vport); 5278 break; 5279 5280 case BFA_FCS_VPORT_SM_DELETE: 5281 break; 5282 5283 default: 5284 bfa_sm_fault(__vport_fcs(vport), event); 5285 } 5286 } 5287 5288 5289 5290 /* 5291 * fcs_vport_private FCS virtual port private functions 5292 */ 5293 /* 5294 * This routine will be called to send a FDISC command. 5295 */ 5296 static void 5297 bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport) 5298 { 5299 bfa_lps_fdisc(vport->lps, vport, 5300 bfa_fcport_get_maxfrsize(__vport_bfa(vport)), 5301 __vport_pwwn(vport), __vport_nwwn(vport)); 5302 vport->vport_stats.fdisc_sent++; 5303 } 5304 5305 static void 5306 bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport) 5307 { 5308 u8 lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps); 5309 u8 lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps); 5310 5311 bfa_trc(__vport_fcs(vport), lsrjt_rsn); 5312 bfa_trc(__vport_fcs(vport), lsrjt_expl); 5313 5314 /* For certain reason codes, we don't want to retry. */ 5315 switch (bfa_lps_get_lsrjt_expl(vport->lps)) { 5316 case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */ 5317 case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */ 5318 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) 5319 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 5320 else 5321 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN); 5322 break; 5323 5324 case FC_LS_RJT_EXP_INSUFF_RES: 5325 /* 5326 * This means max logins per port/switch setting on the 5327 * switch was exceeded. 5328 */ 5329 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) 5330 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 5331 else 5332 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); 5333 break; 5334 5335 default: 5336 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 5337 } 5338 } 5339 5340 /* 5341 * Called to send a logout to the fabric. Used when a V-Port is 5342 * deleted/stopped. 5343 */ 5344 static void 5345 bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport) 5346 { 5347 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5348 5349 vport->vport_stats.logo_sent++; 5350 bfa_lps_fdisclogo(vport->lps); 5351 } 5352 5353 5354 /* 5355 * This routine will be called by bfa_timer on timer timeouts. 5356 * 5357 * param[in] vport - pointer to bfa_fcs_vport_t. 5358 * param[out] vport_status - pointer to return vport status in 5359 * 5360 * return 5361 * void 5362 * 5363 * Special Considerations: 5364 * 5365 * note 5366 */ 5367 static void 5368 bfa_fcs_vport_timeout(void *vport_arg) 5369 { 5370 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg; 5371 5372 vport->vport_stats.fdisc_timeouts++; 5373 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT); 5374 } 5375 5376 static void 5377 bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport) 5378 { 5379 struct bfad_vport_s *vport_drv = 5380 (struct bfad_vport_s *)vport->vport_drv; 5381 5382 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport); 5383 5384 if (vport_drv->comp_del) 5385 complete(vport_drv->comp_del); 5386 5387 bfa_lps_delete(vport->lps); 5388 } 5389 5390 5391 5392 /* 5393 * fcs_vport_public FCS virtual port public interfaces 5394 */ 5395 5396 /* 5397 * Online notification from fabric SM. 5398 */ 5399 void 5400 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport) 5401 { 5402 vport->vport_stats.fab_online++; 5403 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); 5404 } 5405 5406 /* 5407 * Offline notification from fabric SM. 5408 */ 5409 void 5410 bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport) 5411 { 5412 vport->vport_stats.fab_offline++; 5413 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE); 5414 } 5415 5416 /* 5417 * Cleanup notification from fabric SM on link timer expiry. 5418 */ 5419 void 5420 bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport) 5421 { 5422 vport->vport_stats.fab_cleanup++; 5423 } 5424 /* 5425 * delete notification from fabric SM. To be invoked from within FCS. 5426 */ 5427 void 5428 bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport) 5429 { 5430 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); 5431 } 5432 5433 /* 5434 * Delete completion callback from associated lport 5435 */ 5436 void 5437 bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport) 5438 { 5439 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP); 5440 } 5441 5442 5443 5444 /* 5445 * fcs_vport_api Virtual port API 5446 */ 5447 5448 /* 5449 * Use this function to instantiate a new FCS vport object. This 5450 * function will not trigger any HW initialization process (which will be 5451 * done in vport_start() call) 5452 * 5453 * param[in] vport - pointer to bfa_fcs_vport_t. This space 5454 * needs to be allocated by the driver. 5455 * param[in] fcs - FCS instance 5456 * param[in] vport_cfg - vport configuration 5457 * param[in] vf_id - VF_ID if vport is created within a VF. 5458 * FC_VF_ID_NULL to specify base fabric. 5459 * param[in] vport_drv - Opaque handle back to the driver's vport 5460 * structure 5461 * 5462 * retval BFA_STATUS_OK - on success. 5463 * retval BFA_STATUS_FAILED - on failure. 5464 */ 5465 bfa_status_t 5466 bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, 5467 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg, 5468 struct bfad_vport_s *vport_drv) 5469 { 5470 if (vport_cfg->pwwn == 0) 5471 return BFA_STATUS_INVALID_WWN; 5472 5473 if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn) 5474 return BFA_STATUS_VPORT_WWN_BP; 5475 5476 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL) 5477 return BFA_STATUS_VPORT_EXISTS; 5478 5479 if (bfa_fcs_fabric_vport_count(&fcs->fabric) == 5480 bfa_lps_get_max_vport(fcs->bfa)) 5481 return BFA_STATUS_VPORT_MAX; 5482 5483 vport->lps = bfa_lps_alloc(fcs->bfa); 5484 if (!vport->lps) 5485 return BFA_STATUS_VPORT_MAX; 5486 5487 vport->vport_drv = vport_drv; 5488 vport_cfg->preboot_vp = BFA_FALSE; 5489 5490 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); 5491 bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport); 5492 bfa_fcs_lport_init(&vport->lport, vport_cfg); 5493 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE); 5494 5495 return BFA_STATUS_OK; 5496 } 5497 5498 /* 5499 * Use this function to instantiate a new FCS PBC vport object. This 5500 * function will not trigger any HW initialization process (which will be 5501 * done in vport_start() call) 5502 * 5503 * param[in] vport - pointer to bfa_fcs_vport_t. This space 5504 * needs to be allocated by the driver. 5505 * param[in] fcs - FCS instance 5506 * param[in] vport_cfg - vport configuration 5507 * param[in] vf_id - VF_ID if vport is created within a VF. 5508 * FC_VF_ID_NULL to specify base fabric. 5509 * param[in] vport_drv - Opaque handle back to the driver's vport 5510 * structure 5511 * 5512 * retval BFA_STATUS_OK - on success. 5513 * retval BFA_STATUS_FAILED - on failure. 5514 */ 5515 bfa_status_t 5516 bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, 5517 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg, 5518 struct bfad_vport_s *vport_drv) 5519 { 5520 bfa_status_t rc; 5521 5522 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv); 5523 vport->lport.port_cfg.preboot_vp = BFA_TRUE; 5524 5525 return rc; 5526 } 5527 5528 /* 5529 * Use this function to findout if this is a pbc vport or not. 5530 * 5531 * @param[in] vport - pointer to bfa_fcs_vport_t. 5532 * 5533 * @returns None 5534 */ 5535 bfa_boolean_t 5536 bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport) 5537 { 5538 5539 if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE)) 5540 return BFA_TRUE; 5541 else 5542 return BFA_FALSE; 5543 5544 } 5545 5546 /* 5547 * Use this function initialize the vport. 5548 * 5549 * @param[in] vport - pointer to bfa_fcs_vport_t. 5550 * 5551 * @returns None 5552 */ 5553 bfa_status_t 5554 bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport) 5555 { 5556 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START); 5557 5558 return BFA_STATUS_OK; 5559 } 5560 5561 /* 5562 * Use this function quiese the vport object. This function will return 5563 * immediately, when the vport is actually stopped, the 5564 * bfa_drv_vport_stop_cb() will be called. 5565 * 5566 * param[in] vport - pointer to bfa_fcs_vport_t. 5567 * 5568 * return None 5569 */ 5570 bfa_status_t 5571 bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport) 5572 { 5573 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP); 5574 5575 return BFA_STATUS_OK; 5576 } 5577 5578 /* 5579 * Use this function to delete a vport object. Fabric object should 5580 * be stopped before this function call. 5581 * 5582 * !!!!!!! Donot invoke this from within FCS !!!!!!! 5583 * 5584 * param[in] vport - pointer to bfa_fcs_vport_t. 5585 * 5586 * return None 5587 */ 5588 bfa_status_t 5589 bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport) 5590 { 5591 5592 if (vport->lport.port_cfg.preboot_vp) 5593 return BFA_STATUS_PBC; 5594 5595 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); 5596 5597 return BFA_STATUS_OK; 5598 } 5599 5600 /* 5601 * Use this function to get vport's current status info. 5602 * 5603 * param[in] vport pointer to bfa_fcs_vport_t. 5604 * param[out] attr pointer to return vport attributes 5605 * 5606 * return None 5607 */ 5608 void 5609 bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport, 5610 struct bfa_vport_attr_s *attr) 5611 { 5612 if (vport == NULL || attr == NULL) 5613 return; 5614 5615 memset(attr, 0, sizeof(struct bfa_vport_attr_s)); 5616 5617 bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr); 5618 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm); 5619 } 5620 5621 /* 5622 * Use this function to get vport's statistics. 5623 * 5624 * param[in] vport pointer to bfa_fcs_vport_t. 5625 * param[out] stats pointer to return vport statistics in 5626 * 5627 * return None 5628 */ 5629 void 5630 bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport, 5631 struct bfa_vport_stats_s *stats) 5632 { 5633 *stats = vport->vport_stats; 5634 } 5635 5636 /* 5637 * Use this function to clear vport's statistics. 5638 * 5639 * param[in] vport pointer to bfa_fcs_vport_t. 5640 * 5641 * return None 5642 */ 5643 void 5644 bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport) 5645 { 5646 memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s)); 5647 } 5648 5649 /* 5650 * Lookup a virtual port. Excludes base port from lookup. 5651 */ 5652 struct bfa_fcs_vport_s * 5653 bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn) 5654 { 5655 struct bfa_fcs_vport_s *vport; 5656 struct bfa_fcs_fabric_s *fabric; 5657 5658 bfa_trc(fcs, vf_id); 5659 bfa_trc(fcs, vpwwn); 5660 5661 fabric = bfa_fcs_vf_lookup(fcs, vf_id); 5662 if (!fabric) { 5663 bfa_trc(fcs, vf_id); 5664 return NULL; 5665 } 5666 5667 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn); 5668 return vport; 5669 } 5670 5671 /* 5672 * FDISC Response 5673 */ 5674 void 5675 bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) 5676 { 5677 struct bfa_fcs_vport_s *vport = uarg; 5678 5679 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 5680 bfa_trc(__vport_fcs(vport), status); 5681 5682 switch (status) { 5683 case BFA_STATUS_OK: 5684 /* 5685 * Initialiaze the V-Port fields 5686 */ 5687 __vport_fcid(vport) = bfa_lps_get_pid(vport->lps); 5688 vport->vport_stats.fdisc_accepts++; 5689 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); 5690 break; 5691 5692 case BFA_STATUS_INVALID_MAC: 5693 /* Only for CNA */ 5694 vport->vport_stats.fdisc_acc_bad++; 5695 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 5696 5697 break; 5698 5699 case BFA_STATUS_EPROTOCOL: 5700 switch (bfa_lps_get_extstatus(vport->lps)) { 5701 case BFA_EPROTO_BAD_ACCEPT: 5702 vport->vport_stats.fdisc_acc_bad++; 5703 break; 5704 5705 case BFA_EPROTO_UNKNOWN_RSP: 5706 vport->vport_stats.fdisc_unknown_rsp++; 5707 break; 5708 5709 default: 5710 break; 5711 } 5712 5713 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 5714 break; 5715 5716 case BFA_STATUS_FABRIC_RJT: 5717 vport->vport_stats.fdisc_rejects++; 5718 bfa_fcs_vport_fdisc_rejected(vport); 5719 break; 5720 5721 default: 5722 vport->vport_stats.fdisc_rsp_err++; 5723 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 5724 } 5725 } 5726 5727 /* 5728 * LOGO response 5729 */ 5730 void 5731 bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg) 5732 { 5733 struct bfa_fcs_vport_s *vport = uarg; 5734 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); 5735 } 5736 5737 /* 5738 * Received clear virtual link 5739 */ 5740 void 5741 bfa_cb_lps_cvl_event(void *bfad, void *uarg) 5742 { 5743 struct bfa_fcs_vport_s *vport = uarg; 5744 5745 /* Send an Offline followed by an ONLINE */ 5746 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE); 5747 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); 5748 } 5749