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