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

Configure Feed

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

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