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