1 /* 2 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. 3 * Copyright (c) 2014- QLogic Corporation. 4 * All rights reserved 5 * www.qlogic.com 6 * 7 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter. 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License (GPL) Version 2 as 11 * published by the Free Software Foundation 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 */ 18 19 #include "bfad_drv.h" 20 #include "bfad_im.h" 21 #include "bfa_fcs.h" 22 #include "bfa_fcbuild.h" 23 #include "bfa_fc.h" 24 25 BFA_TRC_FILE(FCS, PORT); 26 27 /* 28 * ALPA to LIXA bitmap mapping 29 * 30 * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31 31 * is for L_bit (login required) and is filled as ALPA 0x00 here. 32 */ 33 static const u8 loop_alpa_map[] = { 34 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, /* Word 0 Bits 31..24 */ 35 0x17, 0x18, 0x1B, 0x1D, 0x1E, 0x1F, 0x23, 0x25, /* Word 0 Bits 23..16 */ 36 0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, /* Word 0 Bits 15..08 */ 37 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, /* Word 0 Bits 07..00 */ 38 39 0x3C, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, /* Word 1 Bits 31..24 */ 40 0x4C, 0x4D, 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, /* Word 1 Bits 23..16 */ 41 0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x67, /* Word 1 Bits 15..08 */ 42 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, /* Word 1 Bits 07..00 */ 43 44 0x73, 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, /* Word 2 Bits 31..24 */ 45 0x81, 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, /* Word 2 Bits 23..16 */ 46 0x9B, 0x9D, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, /* Word 2 Bits 15..08 */ 47 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, /* Word 2 Bits 07..00 */ 48 49 0xB3, 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xC3, /* Word 3 Bits 31..24 */ 50 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, /* Word 3 Bits 23..16 */ 51 0xCE, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, /* Word 3 Bits 15..08 */ 52 0xDA, 0xDC, 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF, /* Word 3 Bits 07..00 */ 53 }; 54 55 static void bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, 56 struct fchs_s *rx_fchs, u8 reason_code, 57 u8 reason_code_expl); 58 static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, 59 struct fchs_s *rx_fchs, struct fc_logi_s *plogi); 60 static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port); 61 static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port); 62 static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port); 63 static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port); 64 static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port); 65 static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port); 66 static void bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, 67 struct fchs_s *rx_fchs, 68 struct fc_echo_s *echo, u16 len); 69 static void bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, 70 struct fchs_s *rx_fchs, 71 struct fc_rnid_cmd_s *rnid, u16 len); 72 static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port, 73 struct fc_rnid_general_topology_data_s *gen_topo_data); 74 75 static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port); 76 static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port); 77 static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port); 78 79 static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port); 80 static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port); 81 static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port); 82 83 static void bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port); 84 static void bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port); 85 static void bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port); 86 87 static struct { 88 void (*init) (struct bfa_fcs_lport_s *port); 89 void (*online) (struct bfa_fcs_lport_s *port); 90 void (*offline) (struct bfa_fcs_lport_s *port); 91 } __port_action[] = { 92 [BFA_FCS_FABRIC_UNKNOWN] = { 93 .init = bfa_fcs_lport_unknown_init, 94 .online = bfa_fcs_lport_unknown_online, 95 .offline = bfa_fcs_lport_unknown_offline 96 }, 97 [BFA_FCS_FABRIC_SWITCHED] = { 98 .init = bfa_fcs_lport_fab_init, 99 .online = bfa_fcs_lport_fab_online, 100 .offline = bfa_fcs_lport_fab_offline 101 }, 102 [BFA_FCS_FABRIC_N2N] = { 103 .init = bfa_fcs_lport_n2n_init, 104 .online = bfa_fcs_lport_n2n_online, 105 .offline = bfa_fcs_lport_n2n_offline 106 }, 107 [BFA_FCS_FABRIC_LOOP] = { 108 .init = bfa_fcs_lport_loop_init, 109 .online = bfa_fcs_lport_loop_online, 110 .offline = bfa_fcs_lport_loop_offline 111 }, 112 }; 113 114 /* 115 * fcs_port_sm FCS logical port state machine 116 */ 117 118 enum bfa_fcs_lport_event { 119 BFA_FCS_PORT_SM_CREATE = 1, 120 BFA_FCS_PORT_SM_ONLINE = 2, 121 BFA_FCS_PORT_SM_OFFLINE = 3, 122 BFA_FCS_PORT_SM_DELETE = 4, 123 BFA_FCS_PORT_SM_DELRPORT = 5, 124 BFA_FCS_PORT_SM_STOP = 6, 125 }; 126 127 static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port, 128 enum bfa_fcs_lport_event event); 129 static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port, 130 enum bfa_fcs_lport_event event); 131 static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port, 132 enum bfa_fcs_lport_event event); 133 static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port, 134 enum bfa_fcs_lport_event event); 135 static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port, 136 enum bfa_fcs_lport_event event); 137 static void bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port, 138 enum bfa_fcs_lport_event event); 139 140 static void 141 bfa_fcs_lport_sm_uninit( 142 struct bfa_fcs_lport_s *port, 143 enum bfa_fcs_lport_event event) 144 { 145 bfa_trc(port->fcs, port->port_cfg.pwwn); 146 bfa_trc(port->fcs, event); 147 148 switch (event) { 149 case BFA_FCS_PORT_SM_CREATE: 150 bfa_sm_set_state(port, bfa_fcs_lport_sm_init); 151 break; 152 153 default: 154 bfa_sm_fault(port->fcs, event); 155 } 156 } 157 158 static void 159 bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port, 160 enum bfa_fcs_lport_event event) 161 { 162 bfa_trc(port->fcs, port->port_cfg.pwwn); 163 bfa_trc(port->fcs, event); 164 165 switch (event) { 166 case BFA_FCS_PORT_SM_ONLINE: 167 bfa_sm_set_state(port, bfa_fcs_lport_sm_online); 168 bfa_fcs_lport_online_actions(port); 169 break; 170 171 case BFA_FCS_PORT_SM_DELETE: 172 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); 173 bfa_fcs_lport_deleted(port); 174 break; 175 176 case BFA_FCS_PORT_SM_STOP: 177 /* If vport - send completion call back */ 178 if (port->vport) 179 bfa_fcs_vport_stop_comp(port->vport); 180 else 181 bfa_wc_down(&(port->fabric->stop_wc)); 182 break; 183 184 case BFA_FCS_PORT_SM_OFFLINE: 185 break; 186 187 default: 188 bfa_sm_fault(port->fcs, event); 189 } 190 } 191 192 static void 193 bfa_fcs_lport_sm_online( 194 struct bfa_fcs_lport_s *port, 195 enum bfa_fcs_lport_event event) 196 { 197 struct bfa_fcs_rport_s *rport; 198 struct list_head *qe, *qen; 199 200 bfa_trc(port->fcs, port->port_cfg.pwwn); 201 bfa_trc(port->fcs, event); 202 203 switch (event) { 204 case BFA_FCS_PORT_SM_OFFLINE: 205 bfa_sm_set_state(port, bfa_fcs_lport_sm_offline); 206 bfa_fcs_lport_offline_actions(port); 207 break; 208 209 case BFA_FCS_PORT_SM_STOP: 210 __port_action[port->fabric->fab_type].offline(port); 211 212 if (port->num_rports == 0) { 213 bfa_sm_set_state(port, bfa_fcs_lport_sm_init); 214 /* If vport - send completion call back */ 215 if (port->vport) 216 bfa_fcs_vport_stop_comp(port->vport); 217 else 218 bfa_wc_down(&(port->fabric->stop_wc)); 219 } else { 220 bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping); 221 list_for_each_safe(qe, qen, &port->rport_q) { 222 rport = (struct bfa_fcs_rport_s *) qe; 223 bfa_sm_send_event(rport, RPSM_EVENT_DELETE); 224 } 225 } 226 break; 227 228 case BFA_FCS_PORT_SM_DELETE: 229 230 __port_action[port->fabric->fab_type].offline(port); 231 232 if (port->num_rports == 0) { 233 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); 234 bfa_fcs_lport_deleted(port); 235 } else { 236 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting); 237 list_for_each_safe(qe, qen, &port->rport_q) { 238 rport = (struct bfa_fcs_rport_s *) qe; 239 bfa_sm_send_event(rport, RPSM_EVENT_DELETE); 240 } 241 } 242 break; 243 244 case BFA_FCS_PORT_SM_DELRPORT: 245 break; 246 247 default: 248 bfa_sm_fault(port->fcs, event); 249 } 250 } 251 252 static void 253 bfa_fcs_lport_sm_offline( 254 struct bfa_fcs_lport_s *port, 255 enum bfa_fcs_lport_event event) 256 { 257 struct bfa_fcs_rport_s *rport; 258 struct list_head *qe, *qen; 259 260 bfa_trc(port->fcs, port->port_cfg.pwwn); 261 bfa_trc(port->fcs, event); 262 263 switch (event) { 264 case BFA_FCS_PORT_SM_ONLINE: 265 bfa_sm_set_state(port, bfa_fcs_lport_sm_online); 266 bfa_fcs_lport_online_actions(port); 267 break; 268 269 case BFA_FCS_PORT_SM_STOP: 270 if (port->num_rports == 0) { 271 bfa_sm_set_state(port, bfa_fcs_lport_sm_init); 272 /* If vport - send completion call back */ 273 if (port->vport) 274 bfa_fcs_vport_stop_comp(port->vport); 275 else 276 bfa_wc_down(&(port->fabric->stop_wc)); 277 } else { 278 bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping); 279 list_for_each_safe(qe, qen, &port->rport_q) { 280 rport = (struct bfa_fcs_rport_s *) qe; 281 bfa_sm_send_event(rport, RPSM_EVENT_DELETE); 282 } 283 } 284 break; 285 286 case BFA_FCS_PORT_SM_DELETE: 287 if (port->num_rports == 0) { 288 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); 289 bfa_fcs_lport_deleted(port); 290 } else { 291 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting); 292 list_for_each_safe(qe, qen, &port->rport_q) { 293 rport = (struct bfa_fcs_rport_s *) qe; 294 bfa_sm_send_event(rport, RPSM_EVENT_DELETE); 295 } 296 } 297 break; 298 299 case BFA_FCS_PORT_SM_DELRPORT: 300 case BFA_FCS_PORT_SM_OFFLINE: 301 break; 302 303 default: 304 bfa_sm_fault(port->fcs, event); 305 } 306 } 307 308 static void 309 bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port, 310 enum bfa_fcs_lport_event event) 311 { 312 bfa_trc(port->fcs, port->port_cfg.pwwn); 313 bfa_trc(port->fcs, event); 314 315 switch (event) { 316 case BFA_FCS_PORT_SM_DELRPORT: 317 if (port->num_rports == 0) { 318 bfa_sm_set_state(port, bfa_fcs_lport_sm_init); 319 /* If vport - send completion call back */ 320 if (port->vport) 321 bfa_fcs_vport_stop_comp(port->vport); 322 else 323 bfa_wc_down(&(port->fabric->stop_wc)); 324 } 325 break; 326 327 default: 328 bfa_sm_fault(port->fcs, event); 329 } 330 } 331 332 static void 333 bfa_fcs_lport_sm_deleting( 334 struct bfa_fcs_lport_s *port, 335 enum bfa_fcs_lport_event event) 336 { 337 bfa_trc(port->fcs, port->port_cfg.pwwn); 338 bfa_trc(port->fcs, event); 339 340 switch (event) { 341 case BFA_FCS_PORT_SM_DELRPORT: 342 if (port->num_rports == 0) { 343 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); 344 bfa_fcs_lport_deleted(port); 345 } 346 break; 347 348 default: 349 bfa_sm_fault(port->fcs, event); 350 } 351 } 352 353 /* 354 * fcs_port_pvt 355 */ 356 357 /* 358 * Send AEN notification 359 */ 360 static void 361 bfa_fcs_lport_aen_post(struct bfa_fcs_lport_s *port, 362 enum bfa_lport_aen_event event) 363 { 364 struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad; 365 struct bfa_aen_entry_s *aen_entry; 366 367 bfad_get_aen_entry(bfad, aen_entry); 368 if (!aen_entry) 369 return; 370 371 aen_entry->aen_data.lport.vf_id = port->fabric->vf_id; 372 aen_entry->aen_data.lport.roles = port->port_cfg.roles; 373 aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn( 374 bfa_fcs_get_base_port(port->fcs)); 375 aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port); 376 377 /* Send the AEN notification */ 378 bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq, 379 BFA_AEN_CAT_LPORT, event); 380 } 381 382 /* 383 * Send a LS reject 384 */ 385 static void 386 bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, 387 u8 reason_code, u8 reason_code_expl) 388 { 389 struct fchs_s fchs; 390 struct bfa_fcxp_s *fcxp; 391 struct bfa_rport_s *bfa_rport = NULL; 392 int len; 393 394 bfa_trc(port->fcs, rx_fchs->d_id); 395 bfa_trc(port->fcs, rx_fchs->s_id); 396 397 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); 398 if (!fcxp) 399 return; 400 401 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 402 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 403 rx_fchs->ox_id, reason_code, reason_code_expl); 404 405 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 406 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 407 FC_MAX_PDUSZ, 0); 408 } 409 410 /* 411 * Send a FCCT Reject 412 */ 413 static void 414 bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port, 415 struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl) 416 { 417 struct fchs_s fchs; 418 struct bfa_fcxp_s *fcxp; 419 struct bfa_rport_s *bfa_rport = NULL; 420 int len; 421 struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1); 422 struct ct_hdr_s *ct_hdr; 423 424 bfa_trc(port->fcs, rx_fchs->d_id); 425 bfa_trc(port->fcs, rx_fchs->s_id); 426 427 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); 428 if (!fcxp) 429 return; 430 431 ct_hdr = bfa_fcxp_get_reqbuf(fcxp); 432 ct_hdr->gs_type = rx_cthdr->gs_type; 433 ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type; 434 435 len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id, 436 bfa_fcs_lport_get_fcid(port), 437 rx_fchs->ox_id, reason_code, reason_code_expl); 438 439 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 440 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 441 FC_MAX_PDUSZ, 0); 442 } 443 444 /* 445 * Process incoming plogi from a remote port. 446 */ 447 static void 448 bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, 449 struct fchs_s *rx_fchs, struct fc_logi_s *plogi) 450 { 451 struct bfa_fcs_rport_s *rport; 452 453 bfa_trc(port->fcs, rx_fchs->d_id); 454 bfa_trc(port->fcs, rx_fchs->s_id); 455 456 /* 457 * If min cfg mode is enabled, drop any incoming PLOGIs 458 */ 459 if (__fcs_min_cfg(port->fcs)) { 460 bfa_trc(port->fcs, rx_fchs->s_id); 461 return; 462 } 463 464 if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) { 465 bfa_trc(port->fcs, rx_fchs->s_id); 466 /* 467 * send a LS reject 468 */ 469 bfa_fcs_lport_send_ls_rjt(port, rx_fchs, 470 FC_LS_RJT_RSN_PROTOCOL_ERROR, 471 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS); 472 return; 473 } 474 475 /* 476 * Direct Attach P2P mode : verify address assigned by the r-port. 477 */ 478 if ((!bfa_fcs_fabric_is_switched(port->fabric)) && 479 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port), 480 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) { 481 if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) { 482 /* Address assigned to us cannot be a WKA */ 483 bfa_fcs_lport_send_ls_rjt(port, rx_fchs, 484 FC_LS_RJT_RSN_PROTOCOL_ERROR, 485 FC_LS_RJT_EXP_INVALID_NPORT_ID); 486 return; 487 } 488 port->pid = rx_fchs->d_id; 489 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id); 490 } 491 492 /* 493 * First, check if we know the device by pwwn. 494 */ 495 rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name); 496 if (rport) { 497 /* 498 * Direct Attach P2P mode : handle address assigned by r-port. 499 */ 500 if ((!bfa_fcs_fabric_is_switched(port->fabric)) && 501 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port), 502 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) { 503 port->pid = rx_fchs->d_id; 504 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id); 505 rport->pid = rx_fchs->s_id; 506 } 507 bfa_fcs_rport_plogi(rport, rx_fchs, plogi); 508 return; 509 } 510 511 /* 512 * Next, lookup rport by PID. 513 */ 514 rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id); 515 if (!rport) { 516 /* 517 * Inbound PLOGI from a new device. 518 */ 519 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); 520 return; 521 } 522 523 /* 524 * Rport is known only by PID. 525 */ 526 if (rport->pwwn) { 527 /* 528 * This is a different device with the same pid. Old device 529 * disappeared. Send implicit LOGO to old device. 530 */ 531 WARN_ON(rport->pwwn == plogi->port_name); 532 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); 533 534 /* 535 * Inbound PLOGI from a new device (with old PID). 536 */ 537 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); 538 return; 539 } 540 541 /* 542 * PLOGI crossing each other. 543 */ 544 WARN_ON(rport->pwwn != WWN_NULL); 545 bfa_fcs_rport_plogi(rport, rx_fchs, plogi); 546 } 547 548 /* 549 * Process incoming ECHO. 550 * Since it does not require a login, it is processed here. 551 */ 552 static void 553 bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, 554 struct fc_echo_s *echo, u16 rx_len) 555 { 556 struct fchs_s fchs; 557 struct bfa_fcxp_s *fcxp; 558 struct bfa_rport_s *bfa_rport = NULL; 559 int len, pyld_len; 560 561 bfa_trc(port->fcs, rx_fchs->s_id); 562 bfa_trc(port->fcs, rx_fchs->d_id); 563 564 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); 565 if (!fcxp) 566 return; 567 568 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 569 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 570 rx_fchs->ox_id); 571 572 /* 573 * Copy the payload (if any) from the echo frame 574 */ 575 pyld_len = rx_len - sizeof(struct fchs_s); 576 bfa_trc(port->fcs, rx_len); 577 bfa_trc(port->fcs, pyld_len); 578 579 if (pyld_len > len) 580 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) + 581 sizeof(struct fc_echo_s), (echo + 1), 582 (pyld_len - sizeof(struct fc_echo_s))); 583 584 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 585 BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL, 586 FC_MAX_PDUSZ, 0); 587 } 588 589 /* 590 * Process incoming RNID. 591 * Since it does not require a login, it is processed here. 592 */ 593 static void 594 bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, 595 struct fc_rnid_cmd_s *rnid, u16 rx_len) 596 { 597 struct fc_rnid_common_id_data_s common_id_data; 598 struct fc_rnid_general_topology_data_s gen_topo_data; 599 struct fchs_s fchs; 600 struct bfa_fcxp_s *fcxp; 601 struct bfa_rport_s *bfa_rport = NULL; 602 u16 len; 603 u32 data_format; 604 605 bfa_trc(port->fcs, rx_fchs->s_id); 606 bfa_trc(port->fcs, rx_fchs->d_id); 607 bfa_trc(port->fcs, rx_len); 608 609 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); 610 if (!fcxp) 611 return; 612 613 /* 614 * Check Node Indentification Data Format 615 * We only support General Topology Discovery Format. 616 * For any other requested Data Formats, we return Common Node Id Data 617 * only, as per FC-LS. 618 */ 619 bfa_trc(port->fcs, rnid->node_id_data_format); 620 if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) { 621 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY; 622 /* 623 * Get General topology data for this port 624 */ 625 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data); 626 } else { 627 data_format = RNID_NODEID_DATA_FORMAT_COMMON; 628 } 629 630 /* 631 * Copy the Node Id Info 632 */ 633 common_id_data.port_name = bfa_fcs_lport_get_pwwn(port); 634 common_id_data.node_name = bfa_fcs_lport_get_nwwn(port); 635 636 len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 637 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 638 rx_fchs->ox_id, data_format, &common_id_data, 639 &gen_topo_data); 640 641 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 642 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 643 FC_MAX_PDUSZ, 0); 644 } 645 646 /* 647 * Fill out General Topolpgy Discovery Data for RNID ELS. 648 */ 649 static void 650 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port, 651 struct fc_rnid_general_topology_data_s *gen_topo_data) 652 { 653 memset(gen_topo_data, 0, 654 sizeof(struct fc_rnid_general_topology_data_s)); 655 656 gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST); 657 gen_topo_data->phy_port_num = 0; /* @todo */ 658 gen_topo_data->num_attached_nodes = cpu_to_be32(1); 659 } 660 661 static void 662 bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port) 663 { 664 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; 665 char lpwwn_buf[BFA_STRING_32]; 666 667 bfa_trc(port->fcs, port->fabric->oper_type); 668 669 __port_action[port->fabric->fab_type].init(port); 670 __port_action[port->fabric->fab_type].online(port); 671 672 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); 673 BFA_LOG(KERN_WARNING, bfad, bfa_log_level, 674 "Logical port online: WWN = %s Role = %s\n", 675 lpwwn_buf, "Initiator"); 676 bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_ONLINE); 677 678 bfad->bfad_flags |= BFAD_PORT_ONLINE; 679 } 680 681 static void 682 bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port) 683 { 684 struct list_head *qe, *qen; 685 struct bfa_fcs_rport_s *rport; 686 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; 687 char lpwwn_buf[BFA_STRING_32]; 688 689 bfa_trc(port->fcs, port->fabric->oper_type); 690 691 __port_action[port->fabric->fab_type].offline(port); 692 693 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); 694 if (bfa_sm_cmp_state(port->fabric, 695 bfa_fcs_fabric_sm_online) == BFA_TRUE) { 696 BFA_LOG(KERN_WARNING, bfad, bfa_log_level, 697 "Logical port lost fabric connectivity: WWN = %s Role = %s\n", 698 lpwwn_buf, "Initiator"); 699 bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DISCONNECT); 700 } else { 701 BFA_LOG(KERN_WARNING, bfad, bfa_log_level, 702 "Logical port taken offline: WWN = %s Role = %s\n", 703 lpwwn_buf, "Initiator"); 704 bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_OFFLINE); 705 } 706 707 list_for_each_safe(qe, qen, &port->rport_q) { 708 rport = (struct bfa_fcs_rport_s *) qe; 709 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); 710 } 711 } 712 713 static void 714 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port) 715 { 716 WARN_ON(1); 717 } 718 719 static void 720 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port) 721 { 722 WARN_ON(1); 723 } 724 725 static void 726 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port) 727 { 728 WARN_ON(1); 729 } 730 731 static void 732 bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs) 733 { 734 struct fchs_s fchs; 735 struct bfa_fcxp_s *fcxp; 736 int len; 737 738 bfa_trc(port->fcs, rx_fchs->d_id); 739 bfa_trc(port->fcs, rx_fchs->s_id); 740 741 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); 742 if (!fcxp) 743 return; 744 745 len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 746 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 747 rx_fchs->ox_id, 0); 748 749 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, 750 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 751 FC_MAX_PDUSZ, 0); 752 } 753 static void 754 bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port) 755 { 756 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; 757 char lpwwn_buf[BFA_STRING_32]; 758 759 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); 760 BFA_LOG(KERN_INFO, bfad, bfa_log_level, 761 "Logical port deleted: WWN = %s Role = %s\n", 762 lpwwn_buf, "Initiator"); 763 bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DELETE); 764 765 /* Base port will be deleted by the OS driver */ 766 if (port->vport) 767 bfa_fcs_vport_delete_comp(port->vport); 768 else 769 bfa_wc_down(&port->fabric->wc); 770 } 771 772 773 /* 774 * Unsolicited frame receive handling. 775 */ 776 void 777 bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport, 778 struct fchs_s *fchs, u16 len) 779 { 780 u32 pid = fchs->s_id; 781 struct bfa_fcs_rport_s *rport = NULL; 782 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); 783 784 bfa_stats(lport, uf_recvs); 785 bfa_trc(lport->fcs, fchs->type); 786 787 if (!bfa_fcs_lport_is_online(lport)) { 788 /* 789 * In direct attach topology, it is possible to get a PLOGI 790 * before the lport is online due to port feature 791 * (QoS/Trunk/FEC/CR), so send a rjt 792 */ 793 if ((fchs->type == FC_TYPE_ELS) && 794 (els_cmd->els_code == FC_ELS_PLOGI)) { 795 bfa_fcs_lport_send_ls_rjt(lport, fchs, 796 FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD, 797 FC_LS_RJT_EXP_NO_ADDL_INFO); 798 bfa_stats(lport, plogi_rcvd); 799 } else 800 bfa_stats(lport, uf_recv_drops); 801 802 return; 803 } 804 805 /* 806 * First, handle ELSs that donot require a login. 807 */ 808 /* 809 * Handle PLOGI first 810 */ 811 if ((fchs->type == FC_TYPE_ELS) && 812 (els_cmd->els_code == FC_ELS_PLOGI)) { 813 bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd); 814 return; 815 } 816 817 /* 818 * Handle ECHO separately. 819 */ 820 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) { 821 bfa_fcs_lport_echo(lport, fchs, 822 (struct fc_echo_s *)els_cmd, len); 823 return; 824 } 825 826 /* 827 * Handle RNID separately. 828 */ 829 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) { 830 bfa_fcs_lport_rnid(lport, fchs, 831 (struct fc_rnid_cmd_s *) els_cmd, len); 832 return; 833 } 834 835 if (fchs->type == FC_TYPE_BLS) { 836 if ((fchs->routing == FC_RTG_BASIC_LINK) && 837 (fchs->cat_info == FC_CAT_ABTS)) 838 bfa_fcs_lport_abts_acc(lport, fchs); 839 return; 840 } 841 842 if (fchs->type == FC_TYPE_SERVICES) { 843 /* 844 * Unhandled FC-GS frames. Send a FC-CT Reject 845 */ 846 bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP, 847 CT_NS_EXP_NOADDITIONAL); 848 return; 849 } 850 851 /* 852 * look for a matching remote port ID 853 */ 854 rport = bfa_fcs_lport_get_rport_by_pid(lport, pid); 855 if (rport) { 856 bfa_trc(rport->fcs, fchs->s_id); 857 bfa_trc(rport->fcs, fchs->d_id); 858 bfa_trc(rport->fcs, fchs->type); 859 860 bfa_fcs_rport_uf_recv(rport, fchs, len); 861 return; 862 } 863 864 /* 865 * Only handles ELS frames for now. 866 */ 867 if (fchs->type != FC_TYPE_ELS) { 868 bfa_trc(lport->fcs, fchs->s_id); 869 bfa_trc(lport->fcs, fchs->d_id); 870 /* ignore type FC_TYPE_FC_FSS */ 871 if (fchs->type != FC_TYPE_FC_FSS) 872 bfa_sm_fault(lport->fcs, fchs->type); 873 return; 874 } 875 876 bfa_trc(lport->fcs, els_cmd->els_code); 877 if (els_cmd->els_code == FC_ELS_RSCN) { 878 bfa_fcs_lport_scn_process_rscn(lport, fchs, len); 879 return; 880 } 881 882 if (els_cmd->els_code == FC_ELS_LOGO) { 883 /* 884 * @todo Handle LOGO frames received. 885 */ 886 return; 887 } 888 889 if (els_cmd->els_code == FC_ELS_PRLI) { 890 /* 891 * @todo Handle PRLI frames received. 892 */ 893 return; 894 } 895 896 /* 897 * Unhandled ELS frames. Send a LS_RJT. 898 */ 899 bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP, 900 FC_LS_RJT_EXP_NO_ADDL_INFO); 901 902 } 903 904 /* 905 * PID based Lookup for a R-Port in the Port R-Port Queue 906 */ 907 struct bfa_fcs_rport_s * 908 bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid) 909 { 910 struct bfa_fcs_rport_s *rport; 911 struct list_head *qe; 912 913 list_for_each(qe, &port->rport_q) { 914 rport = (struct bfa_fcs_rport_s *) qe; 915 if (rport->pid == pid) 916 return rport; 917 } 918 919 bfa_trc(port->fcs, pid); 920 return NULL; 921 } 922 923 /* 924 * OLD_PID based Lookup for a R-Port in the Port R-Port Queue 925 */ 926 struct bfa_fcs_rport_s * 927 bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid) 928 { 929 struct bfa_fcs_rport_s *rport; 930 struct list_head *qe; 931 932 list_for_each(qe, &port->rport_q) { 933 rport = (struct bfa_fcs_rport_s *) qe; 934 if (rport->old_pid == pid) 935 return rport; 936 } 937 938 bfa_trc(port->fcs, pid); 939 return NULL; 940 } 941 942 /* 943 * PWWN based Lookup for a R-Port in the Port R-Port Queue 944 */ 945 struct bfa_fcs_rport_s * 946 bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn) 947 { 948 struct bfa_fcs_rport_s *rport; 949 struct list_head *qe; 950 951 list_for_each(qe, &port->rport_q) { 952 rport = (struct bfa_fcs_rport_s *) qe; 953 if (wwn_is_equal(rport->pwwn, pwwn)) 954 return rport; 955 } 956 957 bfa_trc(port->fcs, pwwn); 958 return NULL; 959 } 960 961 /* 962 * NWWN based Lookup for a R-Port in the Port R-Port Queue 963 */ 964 struct bfa_fcs_rport_s * 965 bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn) 966 { 967 struct bfa_fcs_rport_s *rport; 968 struct list_head *qe; 969 970 list_for_each(qe, &port->rport_q) { 971 rport = (struct bfa_fcs_rport_s *) qe; 972 if (wwn_is_equal(rport->nwwn, nwwn)) 973 return rport; 974 } 975 976 bfa_trc(port->fcs, nwwn); 977 return NULL; 978 } 979 980 /* 981 * PWWN & PID based Lookup for a R-Port in the Port R-Port Queue 982 */ 983 struct bfa_fcs_rport_s * 984 bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port, 985 wwn_t pwwn, u32 pid) 986 { 987 struct bfa_fcs_rport_s *rport; 988 struct list_head *qe; 989 990 list_for_each(qe, &port->rport_q) { 991 rport = (struct bfa_fcs_rport_s *) qe; 992 if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid) 993 return rport; 994 } 995 996 bfa_trc(port->fcs, pwwn); 997 return NULL; 998 } 999 1000 /* 1001 * Called by rport module when new rports are discovered. 1002 */ 1003 void 1004 bfa_fcs_lport_add_rport( 1005 struct bfa_fcs_lport_s *port, 1006 struct bfa_fcs_rport_s *rport) 1007 { 1008 list_add_tail(&rport->qe, &port->rport_q); 1009 port->num_rports++; 1010 } 1011 1012 /* 1013 * Called by rport module to when rports are deleted. 1014 */ 1015 void 1016 bfa_fcs_lport_del_rport( 1017 struct bfa_fcs_lport_s *port, 1018 struct bfa_fcs_rport_s *rport) 1019 { 1020 WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport)); 1021 list_del(&rport->qe); 1022 port->num_rports--; 1023 1024 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT); 1025 } 1026 1027 /* 1028 * Called by fabric for base port when fabric login is complete. 1029 * Called by vport for virtual ports when FDISC is complete. 1030 */ 1031 void 1032 bfa_fcs_lport_online(struct bfa_fcs_lport_s *port) 1033 { 1034 bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE); 1035 } 1036 1037 /* 1038 * Called by fabric for base port when fabric goes offline. 1039 * Called by vport for virtual ports when virtual port becomes offline. 1040 */ 1041 void 1042 bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port) 1043 { 1044 bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE); 1045 } 1046 1047 /* 1048 * Called by fabric for base port and by vport for virtual ports 1049 * when target mode driver is unloaded. 1050 */ 1051 void 1052 bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port) 1053 { 1054 bfa_sm_send_event(port, BFA_FCS_PORT_SM_STOP); 1055 } 1056 1057 /* 1058 * Called by fabric to delete base lport and associated resources. 1059 * 1060 * Called by vport to delete lport and associated resources. Should call 1061 * bfa_fcs_vport_delete_comp() for vports on completion. 1062 */ 1063 void 1064 bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port) 1065 { 1066 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE); 1067 } 1068 1069 /* 1070 * Return TRUE if port is online, else return FALSE 1071 */ 1072 bfa_boolean_t 1073 bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port) 1074 { 1075 return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online); 1076 } 1077 1078 /* 1079 * Attach time initialization of logical ports. 1080 */ 1081 void 1082 bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs, 1083 u16 vf_id, struct bfa_fcs_vport_s *vport) 1084 { 1085 lport->fcs = fcs; 1086 lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id); 1087 lport->vport = vport; 1088 lport->lp_tag = (vport) ? vport->lps->bfa_tag : 1089 lport->fabric->lps->bfa_tag; 1090 1091 INIT_LIST_HEAD(&lport->rport_q); 1092 lport->num_rports = 0; 1093 } 1094 1095 /* 1096 * Logical port initialization of base or virtual port. 1097 * Called by fabric for base port or by vport for virtual ports. 1098 */ 1099 1100 void 1101 bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport, 1102 struct bfa_lport_cfg_s *port_cfg) 1103 { 1104 struct bfa_fcs_vport_s *vport = lport->vport; 1105 struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad; 1106 char lpwwn_buf[BFA_STRING_32]; 1107 1108 lport->port_cfg = *port_cfg; 1109 1110 lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport, 1111 lport->port_cfg.roles, 1112 lport->fabric->vf_drv, 1113 vport ? vport->vport_drv : NULL); 1114 1115 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport)); 1116 BFA_LOG(KERN_INFO, bfad, bfa_log_level, 1117 "New logical port created: WWN = %s Role = %s\n", 1118 lpwwn_buf, "Initiator"); 1119 bfa_fcs_lport_aen_post(lport, BFA_LPORT_AEN_NEW); 1120 1121 bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit); 1122 bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE); 1123 } 1124 1125 void 1126 bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, 1127 char *symname) 1128 { 1129 strcpy(port->port_cfg.sym_name.symname, symname); 1130 1131 if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online)) 1132 bfa_fcs_lport_ns_util_send_rspn_id( 1133 BFA_FCS_GET_NS_FROM_PORT(port), NULL); 1134 } 1135 1136 /* 1137 * fcs_lport_api 1138 */ 1139 1140 void 1141 bfa_fcs_lport_get_attr( 1142 struct bfa_fcs_lport_s *port, 1143 struct bfa_lport_attr_s *port_attr) 1144 { 1145 if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online)) 1146 port_attr->pid = port->pid; 1147 else 1148 port_attr->pid = 0; 1149 1150 port_attr->port_cfg = port->port_cfg; 1151 1152 if (port->fabric) { 1153 port_attr->port_type = port->fabric->oper_type; 1154 port_attr->loopback = bfa_sm_cmp_state(port->fabric, 1155 bfa_fcs_fabric_sm_loopback); 1156 port_attr->authfail = 1157 bfa_sm_cmp_state(port->fabric, 1158 bfa_fcs_fabric_sm_auth_failed); 1159 port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port); 1160 memcpy(port_attr->fabric_ip_addr, 1161 bfa_fcs_lport_get_fabric_ipaddr(port), 1162 BFA_FCS_FABRIC_IPADDR_SZ); 1163 1164 if (port->vport != NULL) { 1165 port_attr->port_type = BFA_PORT_TYPE_VPORT; 1166 port_attr->fpma_mac = 1167 port->vport->lps->lp_mac; 1168 } else { 1169 port_attr->fpma_mac = 1170 port->fabric->lps->lp_mac; 1171 } 1172 } else { 1173 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN; 1174 port_attr->state = BFA_LPORT_UNINIT; 1175 } 1176 } 1177 1178 /* 1179 * bfa_fcs_lport_fab port fab functions 1180 */ 1181 1182 /* 1183 * Called by port to initialize fabric services of the base port. 1184 */ 1185 static void 1186 bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port) 1187 { 1188 bfa_fcs_lport_ns_init(port); 1189 bfa_fcs_lport_scn_init(port); 1190 bfa_fcs_lport_ms_init(port); 1191 } 1192 1193 /* 1194 * Called by port to notify transition to online state. 1195 */ 1196 static void 1197 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port) 1198 { 1199 bfa_fcs_lport_ns_online(port); 1200 bfa_fcs_lport_fab_scn_online(port); 1201 } 1202 1203 /* 1204 * Called by port to notify transition to offline state. 1205 */ 1206 static void 1207 bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port) 1208 { 1209 bfa_fcs_lport_ns_offline(port); 1210 bfa_fcs_lport_scn_offline(port); 1211 bfa_fcs_lport_ms_offline(port); 1212 } 1213 1214 /* 1215 * bfa_fcs_lport_n2n functions 1216 */ 1217 1218 /* 1219 * Called by fcs/port to initialize N2N topology. 1220 */ 1221 static void 1222 bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port) 1223 { 1224 } 1225 1226 /* 1227 * Called by fcs/port to notify transition to online state. 1228 */ 1229 static void 1230 bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port) 1231 { 1232 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n; 1233 struct bfa_lport_cfg_s *pcfg = &port->port_cfg; 1234 struct bfa_fcs_rport_s *rport; 1235 1236 bfa_trc(port->fcs, pcfg->pwwn); 1237 1238 /* 1239 * If our PWWN is > than that of the r-port, we have to initiate PLOGI 1240 * and assign an Address. if not, we need to wait for its PLOGI. 1241 * 1242 * If our PWWN is < than that of the remote port, it will send a PLOGI 1243 * with the PIDs assigned. The rport state machine take care of this 1244 * incoming PLOGI. 1245 */ 1246 if (memcmp 1247 ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn, 1248 sizeof(wwn_t)) > 0) { 1249 port->pid = N2N_LOCAL_PID; 1250 bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID); 1251 /* 1252 * First, check if we know the device by pwwn. 1253 */ 1254 rport = bfa_fcs_lport_get_rport_by_pwwn(port, 1255 n2n_port->rem_port_wwn); 1256 if (rport) { 1257 bfa_trc(port->fcs, rport->pid); 1258 bfa_trc(port->fcs, rport->pwwn); 1259 rport->pid = N2N_REMOTE_PID; 1260 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND); 1261 return; 1262 } 1263 1264 /* 1265 * In n2n there can be only one rport. Delete the old one 1266 * whose pid should be zero, because it is offline. 1267 */ 1268 if (port->num_rports > 0) { 1269 rport = bfa_fcs_lport_get_rport_by_pid(port, 0); 1270 WARN_ON(rport == NULL); 1271 if (rport) { 1272 bfa_trc(port->fcs, rport->pwwn); 1273 bfa_sm_send_event(rport, RPSM_EVENT_DELETE); 1274 } 1275 } 1276 bfa_fcs_rport_create(port, N2N_REMOTE_PID); 1277 } 1278 } 1279 1280 /* 1281 * Called by fcs/port to notify transition to offline state. 1282 */ 1283 static void 1284 bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port) 1285 { 1286 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n; 1287 1288 bfa_trc(port->fcs, port->pid); 1289 port->pid = 0; 1290 n2n_port->rem_port_wwn = 0; 1291 n2n_port->reply_oxid = 0; 1292 } 1293 1294 void 1295 bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s *port) 1296 { 1297 int i = 0, j = 0, bit = 0, alpa_bit = 0; 1298 u8 k = 0; 1299 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(port->fcs->bfa); 1300 1301 port->port_topo.ploop.alpabm_valid = fcport->alpabm_valid; 1302 port->pid = fcport->myalpa; 1303 port->pid = bfa_hton3b(port->pid); 1304 1305 for (i = 0; i < (FC_ALPA_MAX / 8); i++) { 1306 for (j = 0, alpa_bit = 0; j < 8; j++, alpa_bit++) { 1307 bfa_trc(port->fcs->bfa, fcport->alpabm.alpa_bm[i]); 1308 bit = (fcport->alpabm.alpa_bm[i] & (1 << (7 - j))); 1309 if (bit) { 1310 port->port_topo.ploop.alpa_pos_map[k] = 1311 loop_alpa_map[(i * 8) + alpa_bit]; 1312 k++; 1313 bfa_trc(port->fcs->bfa, k); 1314 bfa_trc(port->fcs->bfa, 1315 port->port_topo.ploop.alpa_pos_map[k]); 1316 } 1317 } 1318 } 1319 port->port_topo.ploop.num_alpa = k; 1320 } 1321 1322 /* 1323 * Called by fcs/port to initialize Loop topology. 1324 */ 1325 static void 1326 bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port) 1327 { 1328 } 1329 1330 /* 1331 * Called by fcs/port to notify transition to online state. 1332 */ 1333 static void 1334 bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port) 1335 { 1336 u8 num_alpa = 0, alpabm_valid = 0; 1337 struct bfa_fcs_rport_s *rport; 1338 u8 *alpa_map = NULL; 1339 int i = 0; 1340 u32 pid; 1341 1342 bfa_fcport_get_loop_attr(port); 1343 1344 num_alpa = port->port_topo.ploop.num_alpa; 1345 alpabm_valid = port->port_topo.ploop.alpabm_valid; 1346 alpa_map = port->port_topo.ploop.alpa_pos_map; 1347 1348 bfa_trc(port->fcs->bfa, port->pid); 1349 bfa_trc(port->fcs->bfa, num_alpa); 1350 if (alpabm_valid == 1) { 1351 for (i = 0; i < num_alpa; i++) { 1352 bfa_trc(port->fcs->bfa, alpa_map[i]); 1353 if (alpa_map[i] != bfa_hton3b(port->pid)) { 1354 pid = alpa_map[i]; 1355 bfa_trc(port->fcs->bfa, pid); 1356 rport = bfa_fcs_lport_get_rport_by_pid(port, 1357 bfa_hton3b(pid)); 1358 if (!rport) 1359 rport = bfa_fcs_rport_create(port, 1360 bfa_hton3b(pid)); 1361 } 1362 } 1363 } else { 1364 for (i = 0; i < MAX_ALPA_COUNT; i++) { 1365 if (alpa_map[i] != port->pid) { 1366 pid = loop_alpa_map[i]; 1367 bfa_trc(port->fcs->bfa, pid); 1368 rport = bfa_fcs_lport_get_rport_by_pid(port, 1369 bfa_hton3b(pid)); 1370 if (!rport) 1371 rport = bfa_fcs_rport_create(port, 1372 bfa_hton3b(pid)); 1373 } 1374 } 1375 } 1376 } 1377 1378 /* 1379 * Called by fcs/port to notify transition to offline state. 1380 */ 1381 static void 1382 bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port) 1383 { 1384 } 1385 1386 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2 1387 1388 /* 1389 * forward declarations 1390 */ 1391 static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, 1392 struct bfa_fcxp_s *fcxp_alloced); 1393 static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, 1394 struct bfa_fcxp_s *fcxp_alloced); 1395 static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, 1396 struct bfa_fcxp_s *fcxp_alloced); 1397 static void bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, 1398 struct bfa_fcxp_s *fcxp, 1399 void *cbarg, 1400 bfa_status_t req_status, 1401 u32 rsp_len, 1402 u32 resid_len, 1403 struct fchs_s *rsp_fchs); 1404 static void bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, 1405 struct bfa_fcxp_s *fcxp, 1406 void *cbarg, 1407 bfa_status_t req_status, 1408 u32 rsp_len, 1409 u32 resid_len, 1410 struct fchs_s *rsp_fchs); 1411 static void bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, 1412 struct bfa_fcxp_s *fcxp, 1413 void *cbarg, 1414 bfa_status_t req_status, 1415 u32 rsp_len, 1416 u32 resid_len, 1417 struct fchs_s *rsp_fchs); 1418 static void bfa_fcs_lport_fdmi_timeout(void *arg); 1419 static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, 1420 u8 *pyld); 1421 static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, 1422 u8 *pyld); 1423 static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, 1424 u8 *pyld); 1425 static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s * 1426 fdmi, u8 *pyld); 1427 static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, 1428 struct bfa_fcs_fdmi_hba_attr_s *hba_attr); 1429 static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, 1430 struct bfa_fcs_fdmi_port_attr_s *port_attr); 1431 u32 bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed); 1432 1433 /* 1434 * fcs_fdmi_sm FCS FDMI state machine 1435 */ 1436 1437 /* 1438 * FDMI State Machine events 1439 */ 1440 enum port_fdmi_event { 1441 FDMISM_EVENT_PORT_ONLINE = 1, 1442 FDMISM_EVENT_PORT_OFFLINE = 2, 1443 FDMISM_EVENT_RSP_OK = 4, 1444 FDMISM_EVENT_RSP_ERROR = 5, 1445 FDMISM_EVENT_TIMEOUT = 6, 1446 FDMISM_EVENT_RHBA_SENT = 7, 1447 FDMISM_EVENT_RPRT_SENT = 8, 1448 FDMISM_EVENT_RPA_SENT = 9, 1449 }; 1450 1451 static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi, 1452 enum port_fdmi_event event); 1453 static void bfa_fcs_lport_fdmi_sm_sending_rhba( 1454 struct bfa_fcs_lport_fdmi_s *fdmi, 1455 enum port_fdmi_event event); 1456 static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi, 1457 enum port_fdmi_event event); 1458 static void bfa_fcs_lport_fdmi_sm_rhba_retry( 1459 struct bfa_fcs_lport_fdmi_s *fdmi, 1460 enum port_fdmi_event event); 1461 static void bfa_fcs_lport_fdmi_sm_sending_rprt( 1462 struct bfa_fcs_lport_fdmi_s *fdmi, 1463 enum port_fdmi_event event); 1464 static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi, 1465 enum port_fdmi_event event); 1466 static void bfa_fcs_lport_fdmi_sm_rprt_retry( 1467 struct bfa_fcs_lport_fdmi_s *fdmi, 1468 enum port_fdmi_event event); 1469 static void bfa_fcs_lport_fdmi_sm_sending_rpa( 1470 struct bfa_fcs_lport_fdmi_s *fdmi, 1471 enum port_fdmi_event event); 1472 static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi, 1473 enum port_fdmi_event event); 1474 static void bfa_fcs_lport_fdmi_sm_rpa_retry( 1475 struct bfa_fcs_lport_fdmi_s *fdmi, 1476 enum port_fdmi_event event); 1477 static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi, 1478 enum port_fdmi_event event); 1479 static void bfa_fcs_lport_fdmi_sm_disabled( 1480 struct bfa_fcs_lport_fdmi_s *fdmi, 1481 enum port_fdmi_event event); 1482 /* 1483 * Start in offline state - awaiting MS to send start. 1484 */ 1485 static void 1486 bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi, 1487 enum port_fdmi_event event) 1488 { 1489 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1490 1491 bfa_trc(port->fcs, port->port_cfg.pwwn); 1492 bfa_trc(port->fcs, event); 1493 1494 fdmi->retry_cnt = 0; 1495 1496 switch (event) { 1497 case FDMISM_EVENT_PORT_ONLINE: 1498 if (port->vport) { 1499 /* 1500 * For Vports, register a new port. 1501 */ 1502 bfa_sm_set_state(fdmi, 1503 bfa_fcs_lport_fdmi_sm_sending_rprt); 1504 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL); 1505 } else { 1506 /* 1507 * For a base port, we should first register the HBA 1508 * attribute. The HBA attribute also contains the base 1509 * port registration. 1510 */ 1511 bfa_sm_set_state(fdmi, 1512 bfa_fcs_lport_fdmi_sm_sending_rhba); 1513 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL); 1514 } 1515 break; 1516 1517 case FDMISM_EVENT_PORT_OFFLINE: 1518 break; 1519 1520 default: 1521 bfa_sm_fault(port->fcs, event); 1522 } 1523 } 1524 1525 static void 1526 bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi, 1527 enum port_fdmi_event event) 1528 { 1529 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1530 1531 bfa_trc(port->fcs, port->port_cfg.pwwn); 1532 bfa_trc(port->fcs, event); 1533 1534 switch (event) { 1535 case FDMISM_EVENT_RHBA_SENT: 1536 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba); 1537 break; 1538 1539 case FDMISM_EVENT_PORT_OFFLINE: 1540 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1541 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), 1542 &fdmi->fcxp_wqe); 1543 break; 1544 1545 default: 1546 bfa_sm_fault(port->fcs, event); 1547 } 1548 } 1549 1550 static void 1551 bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi, 1552 enum port_fdmi_event event) 1553 { 1554 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1555 1556 bfa_trc(port->fcs, port->port_cfg.pwwn); 1557 bfa_trc(port->fcs, event); 1558 1559 switch (event) { 1560 case FDMISM_EVENT_RSP_ERROR: 1561 /* 1562 * if max retries have not been reached, start timer for a 1563 * delayed retry 1564 */ 1565 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { 1566 bfa_sm_set_state(fdmi, 1567 bfa_fcs_lport_fdmi_sm_rhba_retry); 1568 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), 1569 &fdmi->timer, 1570 bfa_fcs_lport_fdmi_timeout, fdmi, 1571 BFA_FCS_RETRY_TIMEOUT); 1572 } else { 1573 /* 1574 * set state to offline 1575 */ 1576 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1577 } 1578 break; 1579 1580 case FDMISM_EVENT_RSP_OK: 1581 /* 1582 * Initiate Register Port Attributes 1583 */ 1584 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa); 1585 fdmi->retry_cnt = 0; 1586 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL); 1587 break; 1588 1589 case FDMISM_EVENT_PORT_OFFLINE: 1590 bfa_fcxp_discard(fdmi->fcxp); 1591 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1592 break; 1593 1594 default: 1595 bfa_sm_fault(port->fcs, event); 1596 } 1597 } 1598 1599 static void 1600 bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi, 1601 enum port_fdmi_event event) 1602 { 1603 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1604 1605 bfa_trc(port->fcs, port->port_cfg.pwwn); 1606 bfa_trc(port->fcs, event); 1607 1608 switch (event) { 1609 case FDMISM_EVENT_TIMEOUT: 1610 /* 1611 * Retry Timer Expired. Re-send 1612 */ 1613 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba); 1614 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL); 1615 break; 1616 1617 case FDMISM_EVENT_PORT_OFFLINE: 1618 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1619 bfa_timer_stop(&fdmi->timer); 1620 break; 1621 1622 default: 1623 bfa_sm_fault(port->fcs, event); 1624 } 1625 } 1626 1627 /* 1628 * RPRT : Register Port 1629 */ 1630 static void 1631 bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi, 1632 enum port_fdmi_event event) 1633 { 1634 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1635 1636 bfa_trc(port->fcs, port->port_cfg.pwwn); 1637 bfa_trc(port->fcs, event); 1638 1639 switch (event) { 1640 case FDMISM_EVENT_RPRT_SENT: 1641 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt); 1642 break; 1643 1644 case FDMISM_EVENT_PORT_OFFLINE: 1645 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1646 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), 1647 &fdmi->fcxp_wqe); 1648 break; 1649 1650 default: 1651 bfa_sm_fault(port->fcs, event); 1652 } 1653 } 1654 1655 static void 1656 bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi, 1657 enum port_fdmi_event event) 1658 { 1659 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1660 1661 bfa_trc(port->fcs, port->port_cfg.pwwn); 1662 bfa_trc(port->fcs, event); 1663 1664 switch (event) { 1665 case FDMISM_EVENT_RSP_ERROR: 1666 /* 1667 * if max retries have not been reached, start timer for a 1668 * delayed retry 1669 */ 1670 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { 1671 bfa_sm_set_state(fdmi, 1672 bfa_fcs_lport_fdmi_sm_rprt_retry); 1673 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), 1674 &fdmi->timer, 1675 bfa_fcs_lport_fdmi_timeout, fdmi, 1676 BFA_FCS_RETRY_TIMEOUT); 1677 1678 } else { 1679 /* 1680 * set state to offline 1681 */ 1682 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1683 fdmi->retry_cnt = 0; 1684 } 1685 break; 1686 1687 case FDMISM_EVENT_RSP_OK: 1688 fdmi->retry_cnt = 0; 1689 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online); 1690 break; 1691 1692 case FDMISM_EVENT_PORT_OFFLINE: 1693 bfa_fcxp_discard(fdmi->fcxp); 1694 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1695 break; 1696 1697 default: 1698 bfa_sm_fault(port->fcs, event); 1699 } 1700 } 1701 1702 static void 1703 bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi, 1704 enum port_fdmi_event event) 1705 { 1706 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1707 1708 bfa_trc(port->fcs, port->port_cfg.pwwn); 1709 bfa_trc(port->fcs, event); 1710 1711 switch (event) { 1712 case FDMISM_EVENT_TIMEOUT: 1713 /* 1714 * Retry Timer Expired. Re-send 1715 */ 1716 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt); 1717 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL); 1718 break; 1719 1720 case FDMISM_EVENT_PORT_OFFLINE: 1721 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1722 bfa_timer_stop(&fdmi->timer); 1723 break; 1724 1725 default: 1726 bfa_sm_fault(port->fcs, event); 1727 } 1728 } 1729 1730 /* 1731 * Register Port Attributes 1732 */ 1733 static void 1734 bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi, 1735 enum port_fdmi_event event) 1736 { 1737 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1738 1739 bfa_trc(port->fcs, port->port_cfg.pwwn); 1740 bfa_trc(port->fcs, event); 1741 1742 switch (event) { 1743 case FDMISM_EVENT_RPA_SENT: 1744 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa); 1745 break; 1746 1747 case FDMISM_EVENT_PORT_OFFLINE: 1748 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1749 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), 1750 &fdmi->fcxp_wqe); 1751 break; 1752 1753 default: 1754 bfa_sm_fault(port->fcs, event); 1755 } 1756 } 1757 1758 static void 1759 bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi, 1760 enum port_fdmi_event event) 1761 { 1762 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1763 1764 bfa_trc(port->fcs, port->port_cfg.pwwn); 1765 bfa_trc(port->fcs, event); 1766 1767 switch (event) { 1768 case FDMISM_EVENT_RSP_ERROR: 1769 /* 1770 * if max retries have not been reached, start timer for a 1771 * delayed retry 1772 */ 1773 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { 1774 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry); 1775 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), 1776 &fdmi->timer, 1777 bfa_fcs_lport_fdmi_timeout, fdmi, 1778 BFA_FCS_RETRY_TIMEOUT); 1779 } else { 1780 /* 1781 * set state to offline 1782 */ 1783 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1784 fdmi->retry_cnt = 0; 1785 } 1786 break; 1787 1788 case FDMISM_EVENT_RSP_OK: 1789 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online); 1790 fdmi->retry_cnt = 0; 1791 break; 1792 1793 case FDMISM_EVENT_PORT_OFFLINE: 1794 bfa_fcxp_discard(fdmi->fcxp); 1795 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1796 break; 1797 1798 default: 1799 bfa_sm_fault(port->fcs, event); 1800 } 1801 } 1802 1803 static void 1804 bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi, 1805 enum port_fdmi_event event) 1806 { 1807 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1808 1809 bfa_trc(port->fcs, port->port_cfg.pwwn); 1810 bfa_trc(port->fcs, event); 1811 1812 switch (event) { 1813 case FDMISM_EVENT_TIMEOUT: 1814 /* 1815 * Retry Timer Expired. Re-send 1816 */ 1817 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa); 1818 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL); 1819 break; 1820 1821 case FDMISM_EVENT_PORT_OFFLINE: 1822 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1823 bfa_timer_stop(&fdmi->timer); 1824 break; 1825 1826 default: 1827 bfa_sm_fault(port->fcs, event); 1828 } 1829 } 1830 1831 static void 1832 bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi, 1833 enum port_fdmi_event event) 1834 { 1835 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1836 1837 bfa_trc(port->fcs, port->port_cfg.pwwn); 1838 bfa_trc(port->fcs, event); 1839 1840 switch (event) { 1841 case FDMISM_EVENT_PORT_OFFLINE: 1842 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline); 1843 break; 1844 1845 default: 1846 bfa_sm_fault(port->fcs, event); 1847 } 1848 } 1849 /* 1850 * FDMI is disabled state. 1851 */ 1852 static void 1853 bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi, 1854 enum port_fdmi_event event) 1855 { 1856 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1857 1858 bfa_trc(port->fcs, port->port_cfg.pwwn); 1859 bfa_trc(port->fcs, event); 1860 1861 /* No op State. It can only be enabled at Driver Init. */ 1862 } 1863 1864 /* 1865 * RHBA : Register HBA Attributes. 1866 */ 1867 static void 1868 bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) 1869 { 1870 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg; 1871 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1872 struct fchs_s fchs; 1873 int len, attr_len; 1874 struct bfa_fcxp_s *fcxp; 1875 u8 *pyld; 1876 1877 bfa_trc(port->fcs, port->port_cfg.pwwn); 1878 1879 fcxp = fcxp_alloced ? fcxp_alloced : 1880 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); 1881 if (!fcxp) { 1882 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, 1883 bfa_fcs_lport_fdmi_send_rhba, fdmi, BFA_TRUE); 1884 return; 1885 } 1886 fdmi->fcxp = fcxp; 1887 1888 pyld = bfa_fcxp_get_reqbuf(fcxp); 1889 memset(pyld, 0, FC_MAX_PDUSZ); 1890 1891 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port), 1892 FDMI_RHBA); 1893 1894 attr_len = 1895 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi, 1896 (u8 *) ((struct ct_hdr_s *) pyld 1897 + 1)); 1898 1899 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1900 FC_CLASS_3, (len + attr_len), &fchs, 1901 bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi, 1902 FC_MAX_PDUSZ, FC_FCCT_TOV); 1903 1904 bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT); 1905 } 1906 1907 static u16 1908 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) 1909 { 1910 struct bfa_fcs_lport_s *port = fdmi->ms->port; 1911 struct bfa_fcs_fdmi_hba_attr_s hba_attr; 1912 struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr; 1913 struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld; 1914 struct fdmi_attr_s *attr; 1915 u8 *curr_ptr; 1916 u16 len, count; 1917 u16 templen; 1918 1919 /* 1920 * get hba attributes 1921 */ 1922 bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr); 1923 1924 rhba->hba_id = bfa_fcs_lport_get_pwwn(port); 1925 rhba->port_list.num_ports = cpu_to_be32(1); 1926 rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port); 1927 1928 len = sizeof(rhba->hba_id) + sizeof(rhba->port_list); 1929 1930 count = 0; 1931 len += sizeof(rhba->hba_attr_blk.attr_count); 1932 1933 /* 1934 * fill out the invididual entries of the HBA attrib Block 1935 */ 1936 curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr; 1937 1938 /* 1939 * Node Name 1940 */ 1941 attr = (struct fdmi_attr_s *) curr_ptr; 1942 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME); 1943 templen = sizeof(wwn_t); 1944 memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen); 1945 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 1946 len += templen; 1947 count++; 1948 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 1949 sizeof(templen)); 1950 1951 /* 1952 * Manufacturer 1953 */ 1954 attr = (struct fdmi_attr_s *) curr_ptr; 1955 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER); 1956 templen = (u16) strlen(fcs_hba_attr->manufacturer); 1957 memcpy(attr->value, fcs_hba_attr->manufacturer, templen); 1958 templen = fc_roundup(templen, sizeof(u32)); 1959 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 1960 len += templen; 1961 count++; 1962 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 1963 sizeof(templen)); 1964 1965 /* 1966 * Serial Number 1967 */ 1968 attr = (struct fdmi_attr_s *) curr_ptr; 1969 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM); 1970 templen = (u16) strlen(fcs_hba_attr->serial_num); 1971 memcpy(attr->value, fcs_hba_attr->serial_num, templen); 1972 templen = fc_roundup(templen, sizeof(u32)); 1973 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 1974 len += templen; 1975 count++; 1976 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 1977 sizeof(templen)); 1978 1979 /* 1980 * Model 1981 */ 1982 attr = (struct fdmi_attr_s *) curr_ptr; 1983 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL); 1984 templen = (u16) strlen(fcs_hba_attr->model); 1985 memcpy(attr->value, fcs_hba_attr->model, templen); 1986 templen = fc_roundup(templen, sizeof(u32)); 1987 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 1988 len += templen; 1989 count++; 1990 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 1991 sizeof(templen)); 1992 1993 /* 1994 * Model Desc 1995 */ 1996 attr = (struct fdmi_attr_s *) curr_ptr; 1997 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC); 1998 templen = (u16) strlen(fcs_hba_attr->model_desc); 1999 memcpy(attr->value, fcs_hba_attr->model_desc, templen); 2000 templen = fc_roundup(templen, sizeof(u32)); 2001 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2002 len += templen; 2003 count++; 2004 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2005 sizeof(templen)); 2006 2007 /* 2008 * H/W Version 2009 */ 2010 if (fcs_hba_attr->hw_version[0] != '\0') { 2011 attr = (struct fdmi_attr_s *) curr_ptr; 2012 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION); 2013 templen = (u16) strlen(fcs_hba_attr->hw_version); 2014 memcpy(attr->value, fcs_hba_attr->hw_version, templen); 2015 templen = fc_roundup(templen, sizeof(u32)); 2016 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2017 len += templen; 2018 count++; 2019 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2020 sizeof(templen)); 2021 } 2022 2023 /* 2024 * Driver Version 2025 */ 2026 attr = (struct fdmi_attr_s *) curr_ptr; 2027 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION); 2028 templen = (u16) strlen(fcs_hba_attr->driver_version); 2029 memcpy(attr->value, fcs_hba_attr->driver_version, templen); 2030 templen = fc_roundup(templen, sizeof(u32)); 2031 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2032 len += templen; 2033 count++; 2034 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2035 sizeof(templen)); 2036 2037 /* 2038 * Option Rom Version 2039 */ 2040 if (fcs_hba_attr->option_rom_ver[0] != '\0') { 2041 attr = (struct fdmi_attr_s *) curr_ptr; 2042 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION); 2043 templen = (u16) strlen(fcs_hba_attr->option_rom_ver); 2044 memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen); 2045 templen = fc_roundup(templen, sizeof(u32)); 2046 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2047 len += templen; 2048 count++; 2049 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2050 sizeof(templen)); 2051 } 2052 2053 attr = (struct fdmi_attr_s *) curr_ptr; 2054 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION); 2055 templen = (u16) strlen(fcs_hba_attr->fw_version); 2056 memcpy(attr->value, fcs_hba_attr->fw_version, templen); 2057 templen = fc_roundup(templen, sizeof(u32)); 2058 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2059 len += templen; 2060 count++; 2061 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2062 sizeof(templen)); 2063 2064 /* 2065 * OS Name 2066 */ 2067 if (fcs_hba_attr->os_name[0] != '\0') { 2068 attr = (struct fdmi_attr_s *) curr_ptr; 2069 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME); 2070 templen = (u16) strlen(fcs_hba_attr->os_name); 2071 memcpy(attr->value, fcs_hba_attr->os_name, templen); 2072 templen = fc_roundup(templen, sizeof(u32)); 2073 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2074 len += templen; 2075 count++; 2076 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2077 sizeof(templen)); 2078 } 2079 2080 /* 2081 * MAX_CT_PAYLOAD 2082 */ 2083 attr = (struct fdmi_attr_s *) curr_ptr; 2084 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT); 2085 templen = sizeof(fcs_hba_attr->max_ct_pyld); 2086 memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen); 2087 templen = fc_roundup(templen, sizeof(u32)); 2088 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2089 len += templen; 2090 count++; 2091 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2092 sizeof(templen)); 2093 /* 2094 * Send extended attributes ( FOS 7.1 support ) 2095 */ 2096 if (fdmi->retry_cnt == 0) { 2097 attr = (struct fdmi_attr_s *) curr_ptr; 2098 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODE_SYM_NAME); 2099 templen = sizeof(fcs_hba_attr->node_sym_name); 2100 memcpy(attr->value, &fcs_hba_attr->node_sym_name, templen); 2101 templen = fc_roundup(templen, sizeof(u32)); 2102 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2103 len += templen; 2104 count++; 2105 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2106 sizeof(templen)); 2107 2108 attr = (struct fdmi_attr_s *) curr_ptr; 2109 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_VENDOR_ID); 2110 templen = sizeof(fcs_hba_attr->vendor_info); 2111 memcpy(attr->value, &fcs_hba_attr->vendor_info, templen); 2112 templen = fc_roundup(templen, sizeof(u32)); 2113 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2114 len += templen; 2115 count++; 2116 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2117 sizeof(templen)); 2118 2119 attr = (struct fdmi_attr_s *) curr_ptr; 2120 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NUM_PORTS); 2121 templen = sizeof(fcs_hba_attr->num_ports); 2122 memcpy(attr->value, &fcs_hba_attr->num_ports, templen); 2123 templen = fc_roundup(templen, sizeof(u32)); 2124 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2125 len += templen; 2126 count++; 2127 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2128 sizeof(templen)); 2129 2130 attr = (struct fdmi_attr_s *) curr_ptr; 2131 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FABRIC_NAME); 2132 templen = sizeof(fcs_hba_attr->fabric_name); 2133 memcpy(attr->value, &fcs_hba_attr->fabric_name, templen); 2134 templen = fc_roundup(templen, sizeof(u32)); 2135 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2136 len += templen; 2137 count++; 2138 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2139 sizeof(templen)); 2140 2141 attr = (struct fdmi_attr_s *) curr_ptr; 2142 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_BIOS_VER); 2143 templen = sizeof(fcs_hba_attr->bios_ver); 2144 memcpy(attr->value, &fcs_hba_attr->bios_ver, templen); 2145 templen = fc_roundup(attr->len, sizeof(u32)); 2146 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; 2147 len += templen; 2148 count++; 2149 attr->len = cpu_to_be16(templen + sizeof(attr->type) + 2150 sizeof(templen)); 2151 } 2152 2153 /* 2154 * Update size of payload 2155 */ 2156 len += ((sizeof(attr->type) + sizeof(attr->len)) * count); 2157 2158 rhba->hba_attr_blk.attr_count = cpu_to_be32(count); 2159 return len; 2160 } 2161 2162 static void 2163 bfa_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 */ 2200 static void 2201 bfa_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 */ 2243 static u16 2244 bfa_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 2467 static u16 2468 bfa_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 2485 static void 2486 bfa_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 */ 2523 static void 2524 bfa_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 2561 static u16 2562 bfa_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 2578 static void 2579 bfa_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 2612 static void 2613 bfa_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 2620 static void 2621 bfa_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 strncpy(hba_attr->driver_version, (char *)driver_info->version, 2646 sizeof(hba_attr->driver_version)); 2647 2648 strncpy(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 strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, 2657 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); 2658 strncat(hba_attr->os_name, driver_info->host_os_patch, 2659 sizeof(driver_info->host_os_patch)); 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 strncpy(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 strncpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); 2673 2674 } 2675 2676 static void 2677 bfa_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 strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name, 2740 sizeof(port_attr->os_device_name)); 2741 2742 /* 2743 * Host name 2744 */ 2745 strncpy(port_attr->host_name, (char *)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 strncpy(port_attr->port_sym_name.symname, 2752 (char *)&bfa_fcs_lport_get_psym_name(port), 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 */ 2765 u32 2766 bfa_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 2798 void 2799 bfa_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 2810 void 2811 bfa_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 2819 void 2820 bfa_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 */ 2833 static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, 2834 struct bfa_fcxp_s *fcxp_alloced); 2835 static void bfa_fcs_lport_ms_timeout(void *arg); 2836 static 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 2844 static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, 2845 struct bfa_fcxp_s *fcxp_alloced); 2846 static 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); 2853 static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, 2854 struct bfa_fcxp_s *fcxp_alloced); 2855 static 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 */ 2869 enum 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 2879 static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms, 2880 enum port_ms_event event); 2881 static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms, 2882 enum port_ms_event event); 2883 static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms, 2884 enum port_ms_event event); 2885 static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms, 2886 enum port_ms_event event); 2887 static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms, 2888 enum port_ms_event event); 2889 static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms, 2890 enum port_ms_event event); 2891 static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms, 2892 enum port_ms_event event); 2893 static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms, 2894 enum port_ms_event event); 2895 static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms, 2896 enum port_ms_event event); 2897 static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms, 2898 enum port_ms_event event); 2899 static 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 */ 2904 static void 2905 bfa_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 2925 static void 2926 bfa_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 2948 static void 2949 bfa_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 2999 static void 3000 bfa_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 3025 static void 3026 bfa_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 3048 static void 3049 bfa_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 3071 static void 3072 bfa_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 3111 static void 3112 bfa_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 3140 static void 3141 bfa_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 3172 static void 3173 bfa_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 strncpy(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 3251 static void 3252 bfa_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 3274 static void 3275 bfa_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 3312 static void 3313 bfa_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 3341 static void 3342 bfa_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 3373 static void 3374 bfa_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 3418 static void 3419 bfa_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 3455 static void 3456 bfa_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 3510 static void 3511 bfa_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 3520 void 3521 bfa_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 3534 void 3535 bfa_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 3544 void 3545 bfa_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 } 3552 void 3553 bfa_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 */ 3574 static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, 3575 struct bfa_fcxp_s *fcxp_alloced); 3576 static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, 3577 struct bfa_fcxp_s *fcxp_alloced); 3578 static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, 3579 struct bfa_fcxp_s *fcxp_alloced); 3580 static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, 3581 struct bfa_fcxp_s *fcxp_alloced); 3582 static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, 3583 struct bfa_fcxp_s *fcxp_alloced); 3584 static void bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, 3585 struct bfa_fcxp_s *fcxp_alloced); 3586 static void bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, 3587 struct bfa_fcxp_s *fcxp_alloced); 3588 static void bfa_fcs_lport_ns_timeout(void *arg); 3589 static 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); 3596 static 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); 3603 static 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); 3610 static 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); 3617 static 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); 3624 static 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); 3631 static 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); 3638 static void bfa_fcs_lport_ns_process_gidft_pids( 3639 struct bfa_fcs_lport_s *port, 3640 u32 *pid_buf, u32 n_pids); 3641 3642 static 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 */ 3650 enum 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 3666 static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns, 3667 enum vport_ns_event event); 3668 static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns, 3669 enum vport_ns_event event); 3670 static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns, 3671 enum vport_ns_event event); 3672 static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns, 3673 enum vport_ns_event event); 3674 static void bfa_fcs_lport_ns_sm_sending_rspn_id( 3675 struct bfa_fcs_lport_ns_s *ns, 3676 enum vport_ns_event event); 3677 static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns, 3678 enum vport_ns_event event); 3679 static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns, 3680 enum vport_ns_event event); 3681 static void bfa_fcs_lport_ns_sm_sending_rft_id( 3682 struct bfa_fcs_lport_ns_s *ns, 3683 enum vport_ns_event event); 3684 static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns, 3685 enum vport_ns_event event); 3686 static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns, 3687 enum vport_ns_event event); 3688 static void bfa_fcs_lport_ns_sm_sending_rff_id( 3689 struct bfa_fcs_lport_ns_s *ns, 3690 enum vport_ns_event event); 3691 static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns, 3692 enum vport_ns_event event); 3693 static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns, 3694 enum vport_ns_event event); 3695 static void bfa_fcs_lport_ns_sm_sending_gid_ft( 3696 struct bfa_fcs_lport_ns_s *ns, 3697 enum vport_ns_event event); 3698 static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns, 3699 enum vport_ns_event event); 3700 static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns, 3701 enum vport_ns_event event); 3702 static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns, 3703 enum vport_ns_event event); 3704 static void bfa_fcs_lport_ns_sm_sending_rnn_id( 3705 struct bfa_fcs_lport_ns_s *ns, 3706 enum vport_ns_event event); 3707 static void bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns, 3708 enum vport_ns_event event); 3709 static void bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns, 3710 enum vport_ns_event event); 3711 static void bfa_fcs_lport_ns_sm_sending_rsnn_nn( 3712 struct bfa_fcs_lport_ns_s *ns, 3713 enum vport_ns_event event); 3714 static void bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns, 3715 enum vport_ns_event event); 3716 static 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 */ 3722 static void 3723 bfa_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 3743 static void 3744 bfa_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 3766 static void 3767 bfa_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 3801 static void 3802 bfa_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 3827 static void 3828 bfa_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 3849 static void 3850 bfa_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 3889 static void 3890 bfa_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 3912 static void 3913 bfa_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 3935 static void 3936 bfa_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 3974 static void 3975 bfa_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 3997 static void 3998 bfa_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 4020 static void 4021 bfa_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 4054 static void 4055 bfa_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 4080 static void 4081 bfa_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 4103 static void 4104 bfa_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 4138 static void 4139 bfa_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 4161 static void 4162 bfa_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 4184 static void 4185 bfa_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 4241 static void 4242 bfa_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 } 4263 static void 4264 bfa_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 4286 static void 4287 bfa_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 4325 static void 4326 bfa_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 4348 static void 4349 bfa_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 4383 static void 4384 bfa_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 4420 static void 4421 bfa_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 */ 4480 static void 4481 bfa_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 4516 static void 4517 bfa_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 */ 4557 static void 4558 bfa_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 4596 static void 4597 bfa_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 */ 4636 static void 4637 bfa_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 strncpy((char *)psymbl, 4671 (char *) & 4672 (bfa_fcs_lport_get_psym_name 4673 (bfa_fcs_get_base_port(port->fcs))), 4674 strlen((char *) & 4675 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port 4676 (port->fcs)))); 4677 4678 /* Ensure we have a null terminating string. */ 4679 ((char *)psymbl)[strlen((char *) & 4680 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port 4681 (port->fcs)))] = 0; 4682 strncat((char *)psymbl, 4683 (char *) &(bfa_fcs_lport_get_psym_name(port)), 4684 strlen((char *) &bfa_fcs_lport_get_psym_name(port))); 4685 } else { 4686 psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port)); 4687 } 4688 4689 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 4690 bfa_fcs_lport_get_fcid(port), 0, psymbl); 4691 4692 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 4693 FC_CLASS_3, len, &fchs, 4694 bfa_fcs_lport_ns_rspn_id_response, (void *)ns, 4695 FC_MAX_PDUSZ, FC_FCCT_TOV); 4696 4697 port->stats.ns_rspnid_sent++; 4698 4699 bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT); 4700 } 4701 4702 static void 4703 bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 4704 void *cbarg, bfa_status_t req_status, 4705 u32 rsp_len, u32 resid_len, 4706 struct fchs_s *rsp_fchs) 4707 { 4708 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; 4709 struct bfa_fcs_lport_s *port = ns->port; 4710 struct ct_hdr_s *cthdr = NULL; 4711 4712 bfa_trc(port->fcs, port->port_cfg.pwwn); 4713 4714 /* 4715 * Sanity Checks 4716 */ 4717 if (req_status != BFA_STATUS_OK) { 4718 bfa_trc(port->fcs, req_status); 4719 port->stats.ns_rspnid_rsp_err++; 4720 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 4721 return; 4722 } 4723 4724 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 4725 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 4726 4727 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 4728 port->stats.ns_rspnid_accepts++; 4729 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 4730 return; 4731 } 4732 4733 port->stats.ns_rspnid_rejects++; 4734 bfa_trc(port->fcs, cthdr->reason_code); 4735 bfa_trc(port->fcs, cthdr->exp_code); 4736 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 4737 } 4738 4739 /* 4740 * Register FC4-Types 4741 */ 4742 static void 4743 bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) 4744 { 4745 struct bfa_fcs_lport_ns_s *ns = ns_cbarg; 4746 struct bfa_fcs_lport_s *port = ns->port; 4747 struct fchs_s fchs; 4748 int len; 4749 struct bfa_fcxp_s *fcxp; 4750 4751 bfa_trc(port->fcs, port->port_cfg.pwwn); 4752 4753 fcxp = fcxp_alloced ? fcxp_alloced : 4754 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); 4755 if (!fcxp) { 4756 port->stats.ns_rftid_alloc_wait++; 4757 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 4758 bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE); 4759 return; 4760 } 4761 ns->fcxp = fcxp; 4762 4763 len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 4764 bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles); 4765 4766 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 4767 FC_CLASS_3, len, &fchs, 4768 bfa_fcs_lport_ns_rft_id_response, (void *)ns, 4769 FC_MAX_PDUSZ, FC_FCCT_TOV); 4770 4771 port->stats.ns_rftid_sent++; 4772 bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT); 4773 } 4774 4775 static void 4776 bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 4777 void *cbarg, bfa_status_t req_status, 4778 u32 rsp_len, u32 resid_len, 4779 struct fchs_s *rsp_fchs) 4780 { 4781 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; 4782 struct bfa_fcs_lport_s *port = ns->port; 4783 struct ct_hdr_s *cthdr = NULL; 4784 4785 bfa_trc(port->fcs, port->port_cfg.pwwn); 4786 4787 /* 4788 * Sanity Checks 4789 */ 4790 if (req_status != BFA_STATUS_OK) { 4791 bfa_trc(port->fcs, req_status); 4792 port->stats.ns_rftid_rsp_err++; 4793 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 4794 return; 4795 } 4796 4797 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 4798 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 4799 4800 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 4801 port->stats.ns_rftid_accepts++; 4802 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 4803 return; 4804 } 4805 4806 port->stats.ns_rftid_rejects++; 4807 bfa_trc(port->fcs, cthdr->reason_code); 4808 bfa_trc(port->fcs, cthdr->exp_code); 4809 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 4810 } 4811 4812 /* 4813 * Register FC4-Features : Should be done after RFT_ID 4814 */ 4815 static void 4816 bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) 4817 { 4818 struct bfa_fcs_lport_ns_s *ns = ns_cbarg; 4819 struct bfa_fcs_lport_s *port = ns->port; 4820 struct fchs_s fchs; 4821 int len; 4822 struct bfa_fcxp_s *fcxp; 4823 u8 fc4_ftrs = 0; 4824 4825 bfa_trc(port->fcs, port->port_cfg.pwwn); 4826 4827 fcxp = fcxp_alloced ? fcxp_alloced : 4828 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); 4829 if (!fcxp) { 4830 port->stats.ns_rffid_alloc_wait++; 4831 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 4832 bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE); 4833 return; 4834 } 4835 ns->fcxp = fcxp; 4836 4837 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) 4838 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR; 4839 4840 len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 4841 bfa_fcs_lport_get_fcid(port), 0, 4842 FC_TYPE_FCP, fc4_ftrs); 4843 4844 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 4845 FC_CLASS_3, len, &fchs, 4846 bfa_fcs_lport_ns_rff_id_response, (void *)ns, 4847 FC_MAX_PDUSZ, FC_FCCT_TOV); 4848 4849 port->stats.ns_rffid_sent++; 4850 bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT); 4851 } 4852 4853 static void 4854 bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 4855 void *cbarg, bfa_status_t req_status, 4856 u32 rsp_len, u32 resid_len, 4857 struct fchs_s *rsp_fchs) 4858 { 4859 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; 4860 struct bfa_fcs_lport_s *port = ns->port; 4861 struct ct_hdr_s *cthdr = NULL; 4862 4863 bfa_trc(port->fcs, port->port_cfg.pwwn); 4864 4865 /* 4866 * Sanity Checks 4867 */ 4868 if (req_status != BFA_STATUS_OK) { 4869 bfa_trc(port->fcs, req_status); 4870 port->stats.ns_rffid_rsp_err++; 4871 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 4872 return; 4873 } 4874 4875 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 4876 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 4877 4878 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 4879 port->stats.ns_rffid_accepts++; 4880 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 4881 return; 4882 } 4883 4884 port->stats.ns_rffid_rejects++; 4885 bfa_trc(port->fcs, cthdr->reason_code); 4886 bfa_trc(port->fcs, cthdr->exp_code); 4887 4888 if (cthdr->reason_code == CT_RSN_NOT_SUPP) { 4889 /* if this command is not supported, we don't retry */ 4890 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 4891 } else 4892 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 4893 } 4894 /* 4895 * Query Fabric for FC4-Types Devices. 4896 * 4897 * TBD : Need to use a local (FCS private) response buffer, since the response 4898 * can be larger than 2K. 4899 */ 4900 static void 4901 bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) 4902 { 4903 struct bfa_fcs_lport_ns_s *ns = ns_cbarg; 4904 struct bfa_fcs_lport_s *port = ns->port; 4905 struct fchs_s fchs; 4906 int len; 4907 struct bfa_fcxp_s *fcxp; 4908 4909 bfa_trc(port->fcs, port->pid); 4910 4911 fcxp = fcxp_alloced ? fcxp_alloced : 4912 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); 4913 if (!fcxp) { 4914 port->stats.ns_gidft_alloc_wait++; 4915 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 4916 bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE); 4917 return; 4918 } 4919 ns->fcxp = fcxp; 4920 4921 /* 4922 * This query is only initiated for FCP initiator mode. 4923 */ 4924 len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 4925 ns->port->pid, FC_TYPE_FCP); 4926 4927 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 4928 FC_CLASS_3, len, &fchs, 4929 bfa_fcs_lport_ns_gid_ft_response, (void *)ns, 4930 bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV); 4931 4932 port->stats.ns_gidft_sent++; 4933 4934 bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT); 4935 } 4936 4937 static void 4938 bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 4939 void *cbarg, bfa_status_t req_status, 4940 u32 rsp_len, u32 resid_len, 4941 struct fchs_s *rsp_fchs) 4942 { 4943 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; 4944 struct bfa_fcs_lport_s *port = ns->port; 4945 struct ct_hdr_s *cthdr = NULL; 4946 u32 n_pids; 4947 4948 bfa_trc(port->fcs, port->port_cfg.pwwn); 4949 4950 /* 4951 * Sanity Checks 4952 */ 4953 if (req_status != BFA_STATUS_OK) { 4954 bfa_trc(port->fcs, req_status); 4955 port->stats.ns_gidft_rsp_err++; 4956 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 4957 return; 4958 } 4959 4960 if (resid_len != 0) { 4961 /* 4962 * TBD : we will need to allocate a larger buffer & retry the 4963 * command 4964 */ 4965 bfa_trc(port->fcs, rsp_len); 4966 bfa_trc(port->fcs, resid_len); 4967 return; 4968 } 4969 4970 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 4971 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); 4972 4973 switch (cthdr->cmd_rsp_code) { 4974 4975 case CT_RSP_ACCEPT: 4976 4977 port->stats.ns_gidft_accepts++; 4978 n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32)); 4979 bfa_trc(port->fcs, n_pids); 4980 bfa_fcs_lport_ns_process_gidft_pids(port, 4981 (u32 *) (cthdr + 1), 4982 n_pids); 4983 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 4984 break; 4985 4986 case CT_RSP_REJECT: 4987 4988 /* 4989 * Check the reason code & explanation. 4990 * There may not have been any FC4 devices in the fabric 4991 */ 4992 port->stats.ns_gidft_rejects++; 4993 bfa_trc(port->fcs, cthdr->reason_code); 4994 bfa_trc(port->fcs, cthdr->exp_code); 4995 4996 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF) 4997 && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) { 4998 4999 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); 5000 } else { 5001 /* 5002 * for all other errors, retry 5003 */ 5004 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 5005 } 5006 break; 5007 5008 default: 5009 port->stats.ns_gidft_unknown_rsp++; 5010 bfa_trc(port->fcs, cthdr->cmd_rsp_code); 5011 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); 5012 } 5013 } 5014 5015 /* 5016 * This routine will be called by bfa_timer on timer timeouts. 5017 * 5018 * param[in] port - pointer to bfa_fcs_lport_t. 5019 * 5020 * return 5021 * void 5022 * 5023 * Special Considerations: 5024 * 5025 * note 5026 */ 5027 static void 5028 bfa_fcs_lport_ns_timeout(void *arg) 5029 { 5030 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg; 5031 5032 ns->port->stats.ns_timeouts++; 5033 bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT); 5034 } 5035 5036 /* 5037 * Process the PID list in GID_FT response 5038 */ 5039 static void 5040 bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf, 5041 u32 n_pids) 5042 { 5043 struct fcgs_gidft_resp_s *gidft_entry; 5044 struct bfa_fcs_rport_s *rport; 5045 u32 ii; 5046 struct bfa_fcs_fabric_s *fabric = port->fabric; 5047 struct bfa_fcs_vport_s *vport; 5048 struct list_head *qe; 5049 u8 found = 0; 5050 5051 for (ii = 0; ii < n_pids; ii++) { 5052 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii]; 5053 5054 if (gidft_entry->pid == port->pid) 5055 continue; 5056 5057 /* 5058 * Ignore PID if it is of base port 5059 * (Avoid vports discovering base port as remote port) 5060 */ 5061 if (gidft_entry->pid == fabric->bport.pid) 5062 continue; 5063 5064 /* 5065 * Ignore PID if it is of vport created on the same base port 5066 * (Avoid vport discovering every other vport created on the 5067 * same port as remote port) 5068 */ 5069 list_for_each(qe, &fabric->vport_q) { 5070 vport = (struct bfa_fcs_vport_s *) qe; 5071 if (vport->lport.pid == gidft_entry->pid) 5072 found = 1; 5073 } 5074 5075 if (found) { 5076 found = 0; 5077 continue; 5078 } 5079 5080 /* 5081 * Check if this rport already exists 5082 */ 5083 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid); 5084 if (rport == NULL) { 5085 /* 5086 * this is a new device. create rport 5087 */ 5088 rport = bfa_fcs_rport_create(port, gidft_entry->pid); 5089 } else { 5090 /* 5091 * this rport already exists 5092 */ 5093 bfa_fcs_rport_scn(rport); 5094 } 5095 5096 bfa_trc(port->fcs, gidft_entry->pid); 5097 5098 /* 5099 * if the last entry bit is set, bail out. 5100 */ 5101 if (gidft_entry->last) 5102 return; 5103 } 5104 } 5105 5106 /* 5107 * fcs_ns_public FCS nameserver public interfaces 5108 */ 5109 5110 /* 5111 * Functions called by port/fab. 5112 * These will send relevant Events to the ns state machine. 5113 */ 5114 void 5115 bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port) 5116 { 5117 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); 5118 5119 ns->port = port; 5120 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); 5121 } 5122 5123 void 5124 bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port) 5125 { 5126 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); 5127 5128 ns->port = port; 5129 bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE); 5130 } 5131 5132 void 5133 bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port) 5134 { 5135 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); 5136 5137 ns->port = port; 5138 bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE); 5139 } 5140 5141 void 5142 bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port) 5143 { 5144 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); 5145 5146 bfa_trc(port->fcs, port->pid); 5147 if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online)) 5148 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY); 5149 } 5150 5151 static void 5152 bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port) 5153 { 5154 5155 struct bfa_fcs_rport_s *rport; 5156 u8 nwwns; 5157 wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX]; 5158 int ii; 5159 5160 bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns); 5161 5162 for (ii = 0 ; ii < nwwns; ++ii) { 5163 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]); 5164 WARN_ON(!rport); 5165 } 5166 } 5167 5168 void 5169 bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced) 5170 { 5171 struct bfa_fcs_lport_ns_s *ns = cbarg; 5172 struct bfa_fcs_lport_s *port = ns->port; 5173 struct fchs_s fchs; 5174 struct bfa_fcxp_s *fcxp; 5175 u8 symbl[256]; 5176 u8 *psymbl = &symbl[0]; 5177 int len; 5178 5179 /* Avoid sending RSPN in the following states. */ 5180 if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) || 5181 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) || 5182 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) || 5183 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) || 5184 bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry)) 5185 return; 5186 5187 memset(symbl, 0, sizeof(symbl)); 5188 bfa_trc(port->fcs, port->port_cfg.pwwn); 5189 5190 fcxp = fcxp_alloced ? fcxp_alloced : 5191 bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); 5192 if (!fcxp) { 5193 port->stats.ns_rspnid_alloc_wait++; 5194 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 5195 bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE); 5196 return; 5197 } 5198 5199 ns->fcxp = fcxp; 5200 5201 if (port->vport) { 5202 /* 5203 * For Vports, we append the vport's port symbolic name 5204 * to that of the base port. 5205 */ 5206 strncpy((char *)psymbl, (char *)&(bfa_fcs_lport_get_psym_name 5207 (bfa_fcs_get_base_port(port->fcs))), 5208 strlen((char *)&bfa_fcs_lport_get_psym_name( 5209 bfa_fcs_get_base_port(port->fcs)))); 5210 5211 /* Ensure we have a null terminating string. */ 5212 ((char *)psymbl)[strlen((char *)&bfa_fcs_lport_get_psym_name( 5213 bfa_fcs_get_base_port(port->fcs)))] = 0; 5214 5215 strncat((char *)psymbl, 5216 (char *)&(bfa_fcs_lport_get_psym_name(port)), 5217 strlen((char *)&bfa_fcs_lport_get_psym_name(port))); 5218 } 5219 5220 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 5221 bfa_fcs_lport_get_fcid(port), 0, psymbl); 5222 5223 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 5224 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); 5225 5226 port->stats.ns_rspnid_sent++; 5227 } 5228 5229 /* 5230 * FCS SCN 5231 */ 5232 5233 #define FC_QOS_RSCN_EVENT 0x0c 5234 #define FC_FABRIC_NAME_RSCN_EVENT 0x0d 5235 5236 /* 5237 * forward declarations 5238 */ 5239 static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg, 5240 struct bfa_fcxp_s *fcxp_alloced); 5241 static void bfa_fcs_lport_scn_scr_response(void *fcsarg, 5242 struct bfa_fcxp_s *fcxp, 5243 void *cbarg, 5244 bfa_status_t req_status, 5245 u32 rsp_len, 5246 u32 resid_len, 5247 struct fchs_s *rsp_fchs); 5248 static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port, 5249 struct fchs_s *rx_fchs); 5250 static void bfa_fcs_lport_scn_timeout(void *arg); 5251 5252 /* 5253 * fcs_scm_sm FCS SCN state machine 5254 */ 5255 5256 /* 5257 * VPort SCN State Machine events 5258 */ 5259 enum port_scn_event { 5260 SCNSM_EVENT_PORT_ONLINE = 1, 5261 SCNSM_EVENT_PORT_OFFLINE = 2, 5262 SCNSM_EVENT_RSP_OK = 3, 5263 SCNSM_EVENT_RSP_ERROR = 4, 5264 SCNSM_EVENT_TIMEOUT = 5, 5265 SCNSM_EVENT_SCR_SENT = 6, 5266 }; 5267 5268 static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn, 5269 enum port_scn_event event); 5270 static void bfa_fcs_lport_scn_sm_sending_scr( 5271 struct bfa_fcs_lport_scn_s *scn, 5272 enum port_scn_event event); 5273 static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn, 5274 enum port_scn_event event); 5275 static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn, 5276 enum port_scn_event event); 5277 static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn, 5278 enum port_scn_event event); 5279 5280 /* 5281 * Starting state - awaiting link up. 5282 */ 5283 static void 5284 bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn, 5285 enum port_scn_event event) 5286 { 5287 switch (event) { 5288 case SCNSM_EVENT_PORT_ONLINE: 5289 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr); 5290 bfa_fcs_lport_scn_send_scr(scn, NULL); 5291 break; 5292 5293 case SCNSM_EVENT_PORT_OFFLINE: 5294 break; 5295 5296 default: 5297 bfa_sm_fault(scn->port->fcs, event); 5298 } 5299 } 5300 5301 static void 5302 bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn, 5303 enum port_scn_event event) 5304 { 5305 switch (event) { 5306 case SCNSM_EVENT_SCR_SENT: 5307 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr); 5308 break; 5309 5310 case SCNSM_EVENT_PORT_OFFLINE: 5311 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 5312 bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe); 5313 break; 5314 5315 default: 5316 bfa_sm_fault(scn->port->fcs, event); 5317 } 5318 } 5319 5320 static void 5321 bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn, 5322 enum port_scn_event event) 5323 { 5324 struct bfa_fcs_lport_s *port = scn->port; 5325 5326 switch (event) { 5327 case SCNSM_EVENT_RSP_OK: 5328 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online); 5329 break; 5330 5331 case SCNSM_EVENT_RSP_ERROR: 5332 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry); 5333 bfa_timer_start(port->fcs->bfa, &scn->timer, 5334 bfa_fcs_lport_scn_timeout, scn, 5335 BFA_FCS_RETRY_TIMEOUT); 5336 break; 5337 5338 case SCNSM_EVENT_PORT_OFFLINE: 5339 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 5340 bfa_fcxp_discard(scn->fcxp); 5341 break; 5342 5343 default: 5344 bfa_sm_fault(port->fcs, event); 5345 } 5346 } 5347 5348 static void 5349 bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn, 5350 enum port_scn_event event) 5351 { 5352 switch (event) { 5353 case SCNSM_EVENT_TIMEOUT: 5354 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr); 5355 bfa_fcs_lport_scn_send_scr(scn, NULL); 5356 break; 5357 5358 case SCNSM_EVENT_PORT_OFFLINE: 5359 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 5360 bfa_timer_stop(&scn->timer); 5361 break; 5362 5363 default: 5364 bfa_sm_fault(scn->port->fcs, event); 5365 } 5366 } 5367 5368 static void 5369 bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn, 5370 enum port_scn_event event) 5371 { 5372 switch (event) { 5373 case SCNSM_EVENT_PORT_OFFLINE: 5374 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 5375 break; 5376 5377 default: 5378 bfa_sm_fault(scn->port->fcs, event); 5379 } 5380 } 5381 5382 5383 5384 /* 5385 * fcs_scn_private FCS SCN private functions 5386 */ 5387 5388 /* 5389 * This routine will be called to send a SCR command. 5390 */ 5391 static void 5392 bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced) 5393 { 5394 struct bfa_fcs_lport_scn_s *scn = scn_cbarg; 5395 struct bfa_fcs_lport_s *port = scn->port; 5396 struct fchs_s fchs; 5397 int len; 5398 struct bfa_fcxp_s *fcxp; 5399 5400 bfa_trc(port->fcs, port->pid); 5401 bfa_trc(port->fcs, port->port_cfg.pwwn); 5402 5403 fcxp = fcxp_alloced ? fcxp_alloced : 5404 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); 5405 if (!fcxp) { 5406 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe, 5407 bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE); 5408 return; 5409 } 5410 scn->fcxp = fcxp; 5411 5412 /* Handle VU registrations for Base port only */ 5413 if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) { 5414 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 5415 port->fabric->lps->brcd_switch, 5416 port->pid, 0); 5417 } else { 5418 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 5419 BFA_FALSE, 5420 port->pid, 0); 5421 } 5422 5423 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 5424 FC_CLASS_3, len, &fchs, 5425 bfa_fcs_lport_scn_scr_response, 5426 (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV); 5427 5428 bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT); 5429 } 5430 5431 static void 5432 bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp, 5433 void *cbarg, bfa_status_t req_status, u32 rsp_len, 5434 u32 resid_len, struct fchs_s *rsp_fchs) 5435 { 5436 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg; 5437 struct bfa_fcs_lport_s *port = scn->port; 5438 struct fc_els_cmd_s *els_cmd; 5439 struct fc_ls_rjt_s *ls_rjt; 5440 5441 bfa_trc(port->fcs, port->port_cfg.pwwn); 5442 5443 /* 5444 * Sanity Checks 5445 */ 5446 if (req_status != BFA_STATUS_OK) { 5447 bfa_trc(port->fcs, req_status); 5448 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); 5449 return; 5450 } 5451 5452 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); 5453 5454 switch (els_cmd->els_code) { 5455 5456 case FC_ELS_ACC: 5457 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK); 5458 break; 5459 5460 case FC_ELS_LS_RJT: 5461 5462 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); 5463 5464 bfa_trc(port->fcs, ls_rjt->reason_code); 5465 bfa_trc(port->fcs, ls_rjt->reason_code_expl); 5466 5467 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); 5468 break; 5469 5470 default: 5471 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); 5472 } 5473 } 5474 5475 /* 5476 * Send a LS Accept 5477 */ 5478 static void 5479 bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port, 5480 struct fchs_s *rx_fchs) 5481 { 5482 struct fchs_s fchs; 5483 struct bfa_fcxp_s *fcxp; 5484 struct bfa_rport_s *bfa_rport = NULL; 5485 int len; 5486 5487 bfa_trc(port->fcs, rx_fchs->s_id); 5488 5489 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); 5490 if (!fcxp) 5491 return; 5492 5493 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 5494 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port), 5495 rx_fchs->ox_id); 5496 5497 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, 5498 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 5499 FC_MAX_PDUSZ, 0); 5500 } 5501 5502 /* 5503 * This routine will be called by bfa_timer on timer timeouts. 5504 * 5505 * param[in] vport - pointer to bfa_fcs_lport_t. 5506 * param[out] vport_status - pointer to return vport status in 5507 * 5508 * return 5509 * void 5510 * 5511 * Special Considerations: 5512 * 5513 * note 5514 */ 5515 static void 5516 bfa_fcs_lport_scn_timeout(void *arg) 5517 { 5518 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg; 5519 5520 bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT); 5521 } 5522 5523 5524 5525 /* 5526 * fcs_scn_public FCS state change notification public interfaces 5527 */ 5528 5529 /* 5530 * Functions called by port/fab 5531 */ 5532 void 5533 bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port) 5534 { 5535 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); 5536 5537 scn->port = port; 5538 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline); 5539 } 5540 5541 void 5542 bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port) 5543 { 5544 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); 5545 5546 scn->port = port; 5547 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE); 5548 } 5549 5550 void 5551 bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port) 5552 { 5553 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); 5554 5555 scn->port = port; 5556 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE); 5557 } 5558 5559 static void 5560 bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid) 5561 { 5562 struct bfa_fcs_rport_s *rport; 5563 struct bfa_fcs_fabric_s *fabric = port->fabric; 5564 struct bfa_fcs_vport_s *vport; 5565 struct list_head *qe; 5566 5567 bfa_trc(port->fcs, rpid); 5568 5569 /* 5570 * Ignore PID if it is of base port or of vports created on the 5571 * same base port. It is to avoid vports discovering base port or 5572 * other vports created on same base port as remote port 5573 */ 5574 if (rpid == fabric->bport.pid) 5575 return; 5576 5577 list_for_each(qe, &fabric->vport_q) { 5578 vport = (struct bfa_fcs_vport_s *) qe; 5579 if (vport->lport.pid == rpid) 5580 return; 5581 } 5582 /* 5583 * If this is an unknown device, then it just came online. 5584 * Otherwise let rport handle the RSCN event. 5585 */ 5586 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid); 5587 if (!rport) 5588 rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid); 5589 5590 if (rport == NULL) { 5591 /* 5592 * If min cfg mode is enabled, we donot need to 5593 * discover any new rports. 5594 */ 5595 if (!__fcs_min_cfg(port->fcs)) 5596 rport = bfa_fcs_rport_create(port, rpid); 5597 } else 5598 bfa_fcs_rport_scn(rport); 5599 } 5600 5601 /* 5602 * rscn format based PID comparison 5603 */ 5604 #define __fc_pid_match(__c0, __c1, __fmt) \ 5605 (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \ 5606 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \ 5607 ((__c0)[0] == (__c1)[0])) || \ 5608 (((__fmt) == FC_RSCN_FORMAT_AREA) && \ 5609 ((__c0)[0] == (__c1)[0]) && \ 5610 ((__c0)[1] == (__c1)[1]))) 5611 5612 static void 5613 bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port, 5614 enum fc_rscn_format format, 5615 u32 rscn_pid) 5616 { 5617 struct bfa_fcs_rport_s *rport; 5618 struct list_head *qe, *qe_next; 5619 u8 *c0, *c1; 5620 5621 bfa_trc(port->fcs, format); 5622 bfa_trc(port->fcs, rscn_pid); 5623 5624 c0 = (u8 *) &rscn_pid; 5625 5626 list_for_each_safe(qe, qe_next, &port->rport_q) { 5627 rport = (struct bfa_fcs_rport_s *) qe; 5628 c1 = (u8 *) &rport->pid; 5629 if (__fc_pid_match(c0, c1, format)) 5630 bfa_fcs_rport_scn(rport); 5631 } 5632 } 5633 5634 5635 void 5636 bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port, 5637 struct fchs_s *fchs, u32 len) 5638 { 5639 struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1); 5640 int num_entries; 5641 u32 rscn_pid; 5642 bfa_boolean_t nsquery = BFA_FALSE, found; 5643 int i = 0, j; 5644 5645 num_entries = 5646 (be16_to_cpu(rscn->payldlen) - 5647 sizeof(u32)) / sizeof(rscn->event[0]); 5648 5649 bfa_trc(port->fcs, num_entries); 5650 5651 port->stats.num_rscn++; 5652 5653 bfa_fcs_lport_scn_send_ls_acc(port, fchs); 5654 5655 for (i = 0; i < num_entries; i++) { 5656 rscn_pid = rscn->event[i].portid; 5657 5658 bfa_trc(port->fcs, rscn->event[i].format); 5659 bfa_trc(port->fcs, rscn_pid); 5660 5661 /* check for duplicate entries in the list */ 5662 found = BFA_FALSE; 5663 for (j = 0; j < i; j++) { 5664 if (rscn->event[j].portid == rscn_pid) { 5665 found = BFA_TRUE; 5666 break; 5667 } 5668 } 5669 5670 /* if found in down the list, pid has been already processed */ 5671 if (found) { 5672 bfa_trc(port->fcs, rscn_pid); 5673 continue; 5674 } 5675 5676 switch (rscn->event[i].format) { 5677 case FC_RSCN_FORMAT_PORTID: 5678 if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) { 5679 /* 5680 * Ignore this event. 5681 * f/w would have processed it 5682 */ 5683 bfa_trc(port->fcs, rscn_pid); 5684 } else { 5685 port->stats.num_portid_rscn++; 5686 bfa_fcs_lport_scn_portid_rscn(port, rscn_pid); 5687 } 5688 break; 5689 5690 case FC_RSCN_FORMAT_FABRIC: 5691 if (rscn->event[i].qualifier == 5692 FC_FABRIC_NAME_RSCN_EVENT) { 5693 bfa_fcs_lport_ms_fabric_rscn(port); 5694 break; 5695 } 5696 /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */ 5697 5698 case FC_RSCN_FORMAT_AREA: 5699 case FC_RSCN_FORMAT_DOMAIN: 5700 nsquery = BFA_TRUE; 5701 bfa_fcs_lport_scn_multiport_rscn(port, 5702 rscn->event[i].format, 5703 rscn_pid); 5704 break; 5705 5706 5707 default: 5708 WARN_ON(1); 5709 nsquery = BFA_TRUE; 5710 } 5711 } 5712 5713 /* 5714 * If any of area, domain or fabric RSCN is received, do a fresh 5715 * discovery to find new devices. 5716 */ 5717 if (nsquery) 5718 bfa_fcs_lport_ns_query(port); 5719 } 5720 5721 /* 5722 * BFA FCS port 5723 */ 5724 /* 5725 * fcs_port_api BFA FCS port API 5726 */ 5727 struct bfa_fcs_lport_s * 5728 bfa_fcs_get_base_port(struct bfa_fcs_s *fcs) 5729 { 5730 return &fcs->fabric.bport; 5731 } 5732 5733 wwn_t 5734 bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index, 5735 int nrports, bfa_boolean_t bwwn) 5736 { 5737 struct list_head *qh, *qe; 5738 struct bfa_fcs_rport_s *rport = NULL; 5739 int i; 5740 struct bfa_fcs_s *fcs; 5741 5742 if (port == NULL || nrports == 0) 5743 return (wwn_t) 0; 5744 5745 fcs = port->fcs; 5746 bfa_trc(fcs, (u32) nrports); 5747 5748 i = 0; 5749 qh = &port->rport_q; 5750 qe = bfa_q_first(qh); 5751 5752 while ((qe != qh) && (i < nrports)) { 5753 rport = (struct bfa_fcs_rport_s *) qe; 5754 if (bfa_ntoh3b(rport->pid) > 0xFFF000) { 5755 qe = bfa_q_next(qe); 5756 bfa_trc(fcs, (u32) rport->pwwn); 5757 bfa_trc(fcs, rport->pid); 5758 bfa_trc(fcs, i); 5759 continue; 5760 } 5761 5762 if (bwwn) { 5763 if (!memcmp(&wwn, &rport->pwwn, 8)) 5764 break; 5765 } else { 5766 if (i == index) 5767 break; 5768 } 5769 5770 i++; 5771 qe = bfa_q_next(qe); 5772 } 5773 5774 bfa_trc(fcs, i); 5775 if (rport) 5776 return rport->pwwn; 5777 else 5778 return (wwn_t) 0; 5779 } 5780 5781 void 5782 bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port, 5783 struct bfa_rport_qualifier_s rports[], int *nrports) 5784 { 5785 struct list_head *qh, *qe; 5786 struct bfa_fcs_rport_s *rport = NULL; 5787 int i; 5788 struct bfa_fcs_s *fcs; 5789 5790 if (port == NULL || rports == NULL || *nrports == 0) 5791 return; 5792 5793 fcs = port->fcs; 5794 bfa_trc(fcs, (u32) *nrports); 5795 5796 i = 0; 5797 qh = &port->rport_q; 5798 qe = bfa_q_first(qh); 5799 5800 while ((qe != qh) && (i < *nrports)) { 5801 rport = (struct bfa_fcs_rport_s *) qe; 5802 if (bfa_ntoh3b(rport->pid) > 0xFFF000) { 5803 qe = bfa_q_next(qe); 5804 bfa_trc(fcs, (u32) rport->pwwn); 5805 bfa_trc(fcs, rport->pid); 5806 bfa_trc(fcs, i); 5807 continue; 5808 } 5809 5810 if (!rport->pwwn && !rport->pid) { 5811 qe = bfa_q_next(qe); 5812 continue; 5813 } 5814 5815 rports[i].pwwn = rport->pwwn; 5816 rports[i].pid = rport->pid; 5817 5818 i++; 5819 qe = bfa_q_next(qe); 5820 } 5821 5822 bfa_trc(fcs, i); 5823 *nrports = i; 5824 } 5825 5826 /* 5827 * Iterate's through all the rport's in the given port to 5828 * determine the maximum operating speed. 5829 * 5830 * !!!! To be used in TRL Functionality only !!!! 5831 */ 5832 bfa_port_speed_t 5833 bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port) 5834 { 5835 struct list_head *qh, *qe; 5836 struct bfa_fcs_rport_s *rport = NULL; 5837 struct bfa_fcs_s *fcs; 5838 bfa_port_speed_t max_speed = 0; 5839 struct bfa_port_attr_s port_attr; 5840 bfa_port_speed_t port_speed, rport_speed; 5841 bfa_boolean_t trl_enabled; 5842 5843 if (port == NULL) 5844 return 0; 5845 5846 fcs = port->fcs; 5847 trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa); 5848 5849 /* Get Physical port's current speed */ 5850 bfa_fcport_get_attr(port->fcs->bfa, &port_attr); 5851 port_speed = port_attr.speed; 5852 bfa_trc(fcs, port_speed); 5853 5854 qh = &port->rport_q; 5855 qe = bfa_q_first(qh); 5856 5857 while (qe != qh) { 5858 rport = (struct bfa_fcs_rport_s *) qe; 5859 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) || 5860 (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) || 5861 (rport->scsi_function != BFA_RPORT_TARGET)) { 5862 qe = bfa_q_next(qe); 5863 continue; 5864 } 5865 5866 rport_speed = rport->rpf.rpsc_speed; 5867 if ((trl_enabled) && (rport_speed == 5868 BFA_PORT_SPEED_UNKNOWN)) { 5869 /* Use default ratelim speed setting */ 5870 rport_speed = 5871 bfa_fcport_get_ratelim_speed(port->fcs->bfa); 5872 } 5873 5874 if (rport_speed > max_speed) 5875 max_speed = rport_speed; 5876 5877 qe = bfa_q_next(qe); 5878 } 5879 5880 if (max_speed > port_speed) 5881 max_speed = port_speed; 5882 5883 bfa_trc(fcs, max_speed); 5884 return max_speed; 5885 } 5886 5887 struct bfa_fcs_lport_s * 5888 bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn) 5889 { 5890 struct bfa_fcs_vport_s *vport; 5891 bfa_fcs_vf_t *vf; 5892 5893 WARN_ON(fcs == NULL); 5894 5895 vf = bfa_fcs_vf_lookup(fcs, vf_id); 5896 if (vf == NULL) { 5897 bfa_trc(fcs, vf_id); 5898 return NULL; 5899 } 5900 5901 if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn)) 5902 return &vf->bport; 5903 5904 vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn); 5905 if (vport) 5906 return &vport->lport; 5907 5908 return NULL; 5909 } 5910 5911 /* 5912 * API corresponding to NPIV_VPORT_GETINFO. 5913 */ 5914 void 5915 bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port, 5916 struct bfa_lport_info_s *port_info) 5917 { 5918 5919 bfa_trc(port->fcs, port->fabric->fabric_name); 5920 5921 if (port->vport == NULL) { 5922 /* 5923 * This is a Physical port 5924 */ 5925 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL; 5926 5927 /* 5928 * @todo : need to fix the state & reason 5929 */ 5930 port_info->port_state = 0; 5931 port_info->offline_reason = 0; 5932 5933 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port); 5934 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port); 5935 5936 port_info->max_vports_supp = 5937 bfa_lps_get_max_vport(port->fcs->bfa); 5938 port_info->num_vports_inuse = 5939 port->fabric->num_vports; 5940 port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP; 5941 port_info->num_rports_inuse = port->num_rports; 5942 } else { 5943 /* 5944 * This is a virtual port 5945 */ 5946 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL; 5947 5948 /* 5949 * @todo : need to fix the state & reason 5950 */ 5951 port_info->port_state = 0; 5952 port_info->offline_reason = 0; 5953 5954 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port); 5955 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port); 5956 } 5957 } 5958 5959 void 5960 bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port, 5961 struct bfa_lport_stats_s *port_stats) 5962 { 5963 *port_stats = fcs_port->stats; 5964 } 5965 5966 void 5967 bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port) 5968 { 5969 memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s)); 5970 } 5971 5972 /* 5973 * Let new loop map create missing rports 5974 */ 5975 void 5976 bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port) 5977 { 5978 bfa_fcs_lport_loop_online(port); 5979 } 5980 5981 /* 5982 * FCS virtual port state machine 5983 */ 5984 5985 #define __vport_fcs(__vp) ((__vp)->lport.fcs) 5986 #define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn) 5987 #define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn) 5988 #define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa) 5989 #define __vport_fcid(__vp) ((__vp)->lport.pid) 5990 #define __vport_fabric(__vp) ((__vp)->lport.fabric) 5991 #define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id) 5992 5993 #define BFA_FCS_VPORT_MAX_RETRIES 5 5994 /* 5995 * Forward declarations 5996 */ 5997 static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport); 5998 static void bfa_fcs_vport_timeout(void *vport_arg); 5999 static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport); 6000 static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport); 6001 6002 /* 6003 * fcs_vport_sm FCS virtual port state machine 6004 */ 6005 6006 /* 6007 * VPort State Machine events 6008 */ 6009 enum bfa_fcs_vport_event { 6010 BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */ 6011 BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */ 6012 BFA_FCS_VPORT_SM_START = 3, /* vport start request */ 6013 BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */ 6014 BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */ 6015 BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */ 6016 BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */ 6017 BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */ 6018 BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */ 6019 BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */ 6020 BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */ 6021 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/ 6022 BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */ 6023 BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */ 6024 BFA_FCS_VPORT_SM_FABRIC_MAX = 15, /* max vports on fabric */ 6025 }; 6026 6027 static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, 6028 enum bfa_fcs_vport_event event); 6029 static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, 6030 enum bfa_fcs_vport_event event); 6031 static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, 6032 enum bfa_fcs_vport_event event); 6033 static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, 6034 enum bfa_fcs_vport_event event); 6035 static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, 6036 enum bfa_fcs_vport_event event); 6037 static void bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport, 6038 enum bfa_fcs_vport_event event); 6039 static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, 6040 enum bfa_fcs_vport_event event); 6041 static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, 6042 enum bfa_fcs_vport_event event); 6043 static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, 6044 enum bfa_fcs_vport_event event); 6045 static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, 6046 enum bfa_fcs_vport_event event); 6047 static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, 6048 enum bfa_fcs_vport_event event); 6049 static void bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport, 6050 enum bfa_fcs_vport_event event); 6051 static void bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport, 6052 enum bfa_fcs_vport_event event); 6053 6054 static struct bfa_sm_table_s vport_sm_table[] = { 6055 {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT}, 6056 {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED}, 6057 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE}, 6058 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC}, 6059 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY}, 6060 {BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT}, 6061 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE}, 6062 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING}, 6063 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP}, 6064 {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO}, 6065 {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR} 6066 }; 6067 6068 /* 6069 * Beginning state. 6070 */ 6071 static void 6072 bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, 6073 enum bfa_fcs_vport_event event) 6074 { 6075 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6076 bfa_trc(__vport_fcs(vport), event); 6077 6078 switch (event) { 6079 case BFA_FCS_VPORT_SM_CREATE: 6080 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); 6081 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport); 6082 break; 6083 6084 default: 6085 bfa_sm_fault(__vport_fcs(vport), event); 6086 } 6087 } 6088 6089 /* 6090 * Created state - a start event is required to start up the state machine. 6091 */ 6092 static void 6093 bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, 6094 enum bfa_fcs_vport_event event) 6095 { 6096 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6097 bfa_trc(__vport_fcs(vport), event); 6098 6099 switch (event) { 6100 case BFA_FCS_VPORT_SM_START: 6101 if (bfa_sm_cmp_state(__vport_fabric(vport), 6102 bfa_fcs_fabric_sm_online) 6103 && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) { 6104 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); 6105 bfa_fcs_vport_do_fdisc(vport); 6106 } else { 6107 /* 6108 * Fabric is offline or not NPIV capable, stay in 6109 * offline state. 6110 */ 6111 vport->vport_stats.fab_no_npiv++; 6112 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 6113 } 6114 break; 6115 6116 case BFA_FCS_VPORT_SM_DELETE: 6117 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 6118 bfa_fcs_lport_delete(&vport->lport); 6119 break; 6120 6121 case BFA_FCS_VPORT_SM_ONLINE: 6122 case BFA_FCS_VPORT_SM_OFFLINE: 6123 /* 6124 * Ignore ONLINE/OFFLINE events from fabric 6125 * till vport is started. 6126 */ 6127 break; 6128 6129 default: 6130 bfa_sm_fault(__vport_fcs(vport), event); 6131 } 6132 } 6133 6134 /* 6135 * Offline state - awaiting ONLINE event from fabric SM. 6136 */ 6137 static void 6138 bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, 6139 enum bfa_fcs_vport_event event) 6140 { 6141 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6142 bfa_trc(__vport_fcs(vport), event); 6143 6144 switch (event) { 6145 case BFA_FCS_VPORT_SM_DELETE: 6146 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 6147 bfa_fcs_lport_delete(&vport->lport); 6148 break; 6149 6150 case BFA_FCS_VPORT_SM_ONLINE: 6151 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); 6152 vport->fdisc_retries = 0; 6153 bfa_fcs_vport_do_fdisc(vport); 6154 break; 6155 6156 case BFA_FCS_VPORT_SM_STOP: 6157 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 6158 bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP); 6159 break; 6160 6161 case BFA_FCS_VPORT_SM_OFFLINE: 6162 /* 6163 * This can happen if the vport couldn't be initialzied 6164 * due the fact that the npiv was not enabled on the switch. 6165 * In that case we will put the vport in offline state. 6166 * However, the link can go down and cause the this event to 6167 * be sent when we are already offline. Ignore it. 6168 */ 6169 break; 6170 6171 default: 6172 bfa_sm_fault(__vport_fcs(vport), event); 6173 } 6174 } 6175 6176 6177 /* 6178 * FDISC is sent and awaiting reply from fabric. 6179 */ 6180 static void 6181 bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, 6182 enum bfa_fcs_vport_event event) 6183 { 6184 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6185 bfa_trc(__vport_fcs(vport), event); 6186 6187 switch (event) { 6188 case BFA_FCS_VPORT_SM_DELETE: 6189 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait); 6190 break; 6191 6192 case BFA_FCS_VPORT_SM_OFFLINE: 6193 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 6194 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); 6195 break; 6196 6197 case BFA_FCS_VPORT_SM_RSP_OK: 6198 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online); 6199 bfa_fcs_lport_online(&vport->lport); 6200 break; 6201 6202 case BFA_FCS_VPORT_SM_RSP_ERROR: 6203 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry); 6204 bfa_timer_start(__vport_bfa(vport), &vport->timer, 6205 bfa_fcs_vport_timeout, vport, 6206 BFA_FCS_RETRY_TIMEOUT); 6207 break; 6208 6209 case BFA_FCS_VPORT_SM_RSP_FAILED: 6210 case BFA_FCS_VPORT_SM_FABRIC_MAX: 6211 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 6212 break; 6213 6214 case BFA_FCS_VPORT_SM_RSP_DUP_WWN: 6215 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error); 6216 break; 6217 6218 default: 6219 bfa_sm_fault(__vport_fcs(vport), event); 6220 } 6221 } 6222 6223 /* 6224 * FDISC attempt failed - a timer is active to retry FDISC. 6225 */ 6226 static void 6227 bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, 6228 enum bfa_fcs_vport_event event) 6229 { 6230 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6231 bfa_trc(__vport_fcs(vport), event); 6232 6233 switch (event) { 6234 case BFA_FCS_VPORT_SM_DELETE: 6235 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 6236 bfa_timer_stop(&vport->timer); 6237 bfa_fcs_lport_delete(&vport->lport); 6238 break; 6239 6240 case BFA_FCS_VPORT_SM_OFFLINE: 6241 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 6242 bfa_timer_stop(&vport->timer); 6243 break; 6244 6245 case BFA_FCS_VPORT_SM_TIMEOUT: 6246 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); 6247 vport->vport_stats.fdisc_retries++; 6248 vport->fdisc_retries++; 6249 bfa_fcs_vport_do_fdisc(vport); 6250 break; 6251 6252 default: 6253 bfa_sm_fault(__vport_fcs(vport), event); 6254 } 6255 } 6256 6257 /* 6258 * FDISC is in progress and we got a vport delete request - 6259 * this is a wait state while we wait for fdisc response and 6260 * we will transition to the appropriate state - on rsp status. 6261 */ 6262 static void 6263 bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport, 6264 enum bfa_fcs_vport_event event) 6265 { 6266 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6267 bfa_trc(__vport_fcs(vport), event); 6268 6269 switch (event) { 6270 case BFA_FCS_VPORT_SM_RSP_OK: 6271 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting); 6272 bfa_fcs_lport_delete(&vport->lport); 6273 break; 6274 6275 case BFA_FCS_VPORT_SM_DELETE: 6276 break; 6277 6278 case BFA_FCS_VPORT_SM_OFFLINE: 6279 case BFA_FCS_VPORT_SM_RSP_ERROR: 6280 case BFA_FCS_VPORT_SM_RSP_FAILED: 6281 case BFA_FCS_VPORT_SM_FABRIC_MAX: 6282 case BFA_FCS_VPORT_SM_RSP_DUP_WWN: 6283 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 6284 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); 6285 bfa_fcs_lport_delete(&vport->lport); 6286 break; 6287 6288 default: 6289 bfa_sm_fault(__vport_fcs(vport), event); 6290 } 6291 } 6292 6293 /* 6294 * Vport is online (FDISC is complete). 6295 */ 6296 static void 6297 bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, 6298 enum bfa_fcs_vport_event event) 6299 { 6300 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6301 bfa_trc(__vport_fcs(vport), event); 6302 6303 switch (event) { 6304 case BFA_FCS_VPORT_SM_DELETE: 6305 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting); 6306 bfa_fcs_lport_delete(&vport->lport); 6307 break; 6308 6309 case BFA_FCS_VPORT_SM_STOP: 6310 bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping); 6311 bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP); 6312 break; 6313 6314 case BFA_FCS_VPORT_SM_OFFLINE: 6315 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 6316 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); 6317 bfa_fcs_lport_offline(&vport->lport); 6318 break; 6319 6320 default: 6321 bfa_sm_fault(__vport_fcs(vport), event); 6322 } 6323 } 6324 6325 /* 6326 * Vport is being stopped - awaiting lport stop completion to send 6327 * LOGO to fabric. 6328 */ 6329 static void 6330 bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport, 6331 enum bfa_fcs_vport_event event) 6332 { 6333 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6334 bfa_trc(__vport_fcs(vport), event); 6335 6336 switch (event) { 6337 case BFA_FCS_VPORT_SM_STOPCOMP: 6338 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop); 6339 bfa_fcs_vport_do_logo(vport); 6340 break; 6341 6342 case BFA_FCS_VPORT_SM_OFFLINE: 6343 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 6344 break; 6345 6346 default: 6347 bfa_sm_fault(__vport_fcs(vport), event); 6348 } 6349 } 6350 6351 /* 6352 * Vport is being deleted - awaiting lport delete completion to send 6353 * LOGO to fabric. 6354 */ 6355 static void 6356 bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, 6357 enum bfa_fcs_vport_event event) 6358 { 6359 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6360 bfa_trc(__vport_fcs(vport), event); 6361 6362 switch (event) { 6363 case BFA_FCS_VPORT_SM_DELETE: 6364 break; 6365 6366 case BFA_FCS_VPORT_SM_DELCOMP: 6367 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo); 6368 bfa_fcs_vport_do_logo(vport); 6369 break; 6370 6371 case BFA_FCS_VPORT_SM_OFFLINE: 6372 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 6373 break; 6374 6375 default: 6376 bfa_sm_fault(__vport_fcs(vport), event); 6377 } 6378 } 6379 6380 /* 6381 * Error State. 6382 * This state will be set when the Vport Creation fails due 6383 * to errors like Dup WWN. In this state only operation allowed 6384 * is a Vport Delete. 6385 */ 6386 static void 6387 bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, 6388 enum bfa_fcs_vport_event event) 6389 { 6390 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6391 bfa_trc(__vport_fcs(vport), event); 6392 6393 switch (event) { 6394 case BFA_FCS_VPORT_SM_DELETE: 6395 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 6396 bfa_fcs_lport_delete(&vport->lport); 6397 break; 6398 6399 default: 6400 bfa_trc(__vport_fcs(vport), event); 6401 } 6402 } 6403 6404 /* 6405 * Lport cleanup is in progress since vport is being deleted. Fabric is 6406 * offline, so no LOGO is needed to complete vport deletion. 6407 */ 6408 static void 6409 bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, 6410 enum bfa_fcs_vport_event event) 6411 { 6412 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6413 bfa_trc(__vport_fcs(vport), event); 6414 6415 switch (event) { 6416 case BFA_FCS_VPORT_SM_DELCOMP: 6417 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); 6418 bfa_fcs_vport_free(vport); 6419 break; 6420 6421 case BFA_FCS_VPORT_SM_STOPCOMP: 6422 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); 6423 break; 6424 6425 case BFA_FCS_VPORT_SM_DELETE: 6426 break; 6427 6428 default: 6429 bfa_sm_fault(__vport_fcs(vport), event); 6430 } 6431 } 6432 6433 /* 6434 * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup 6435 * is done. 6436 */ 6437 static void 6438 bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport, 6439 enum bfa_fcs_vport_event event) 6440 { 6441 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6442 bfa_trc(__vport_fcs(vport), event); 6443 6444 switch (event) { 6445 case BFA_FCS_VPORT_SM_OFFLINE: 6446 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); 6447 /* 6448 * !!! fall through !!! 6449 */ 6450 6451 case BFA_FCS_VPORT_SM_RSP_OK: 6452 case BFA_FCS_VPORT_SM_RSP_ERROR: 6453 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); 6454 break; 6455 6456 default: 6457 bfa_sm_fault(__vport_fcs(vport), event); 6458 } 6459 } 6460 6461 /* 6462 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup 6463 * is done. 6464 */ 6465 static void 6466 bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, 6467 enum bfa_fcs_vport_event event) 6468 { 6469 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6470 bfa_trc(__vport_fcs(vport), event); 6471 6472 switch (event) { 6473 case BFA_FCS_VPORT_SM_OFFLINE: 6474 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); 6475 /* 6476 * !!! fall through !!! 6477 */ 6478 6479 case BFA_FCS_VPORT_SM_RSP_OK: 6480 case BFA_FCS_VPORT_SM_RSP_ERROR: 6481 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); 6482 bfa_fcs_vport_free(vport); 6483 break; 6484 6485 case BFA_FCS_VPORT_SM_DELETE: 6486 break; 6487 6488 default: 6489 bfa_sm_fault(__vport_fcs(vport), event); 6490 } 6491 } 6492 6493 6494 6495 /* 6496 * fcs_vport_private FCS virtual port private functions 6497 */ 6498 /* 6499 * Send AEN notification 6500 */ 6501 static void 6502 bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s *port, 6503 enum bfa_lport_aen_event event) 6504 { 6505 struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad; 6506 struct bfa_aen_entry_s *aen_entry; 6507 6508 bfad_get_aen_entry(bfad, aen_entry); 6509 if (!aen_entry) 6510 return; 6511 6512 aen_entry->aen_data.lport.vf_id = port->fabric->vf_id; 6513 aen_entry->aen_data.lport.roles = port->port_cfg.roles; 6514 aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn( 6515 bfa_fcs_get_base_port(port->fcs)); 6516 aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port); 6517 6518 /* Send the AEN notification */ 6519 bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq, 6520 BFA_AEN_CAT_LPORT, event); 6521 } 6522 6523 /* 6524 * This routine will be called to send a FDISC command. 6525 */ 6526 static void 6527 bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport) 6528 { 6529 bfa_lps_fdisc(vport->lps, vport, 6530 bfa_fcport_get_maxfrsize(__vport_bfa(vport)), 6531 __vport_pwwn(vport), __vport_nwwn(vport)); 6532 vport->vport_stats.fdisc_sent++; 6533 } 6534 6535 static void 6536 bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport) 6537 { 6538 u8 lsrjt_rsn = vport->lps->lsrjt_rsn; 6539 u8 lsrjt_expl = vport->lps->lsrjt_expl; 6540 6541 bfa_trc(__vport_fcs(vport), lsrjt_rsn); 6542 bfa_trc(__vport_fcs(vport), lsrjt_expl); 6543 6544 /* For certain reason codes, we don't want to retry. */ 6545 switch (vport->lps->lsrjt_expl) { 6546 case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */ 6547 case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */ 6548 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) 6549 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 6550 else { 6551 bfa_fcs_vport_aen_post(&vport->lport, 6552 BFA_LPORT_AEN_NPIV_DUP_WWN); 6553 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN); 6554 } 6555 break; 6556 6557 case FC_LS_RJT_EXP_INSUFF_RES: 6558 /* 6559 * This means max logins per port/switch setting on the 6560 * switch was exceeded. 6561 */ 6562 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) 6563 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 6564 else { 6565 bfa_fcs_vport_aen_post(&vport->lport, 6566 BFA_LPORT_AEN_NPIV_FABRIC_MAX); 6567 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_FABRIC_MAX); 6568 } 6569 break; 6570 6571 default: 6572 if (vport->fdisc_retries == 0) 6573 bfa_fcs_vport_aen_post(&vport->lport, 6574 BFA_LPORT_AEN_NPIV_UNKNOWN); 6575 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 6576 } 6577 } 6578 6579 /* 6580 * Called to send a logout to the fabric. Used when a V-Port is 6581 * deleted/stopped. 6582 */ 6583 static void 6584 bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport) 6585 { 6586 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6587 6588 vport->vport_stats.logo_sent++; 6589 bfa_lps_fdisclogo(vport->lps); 6590 } 6591 6592 6593 /* 6594 * This routine will be called by bfa_timer on timer timeouts. 6595 * 6596 * param[in] vport - pointer to bfa_fcs_vport_t. 6597 * param[out] vport_status - pointer to return vport status in 6598 * 6599 * return 6600 * void 6601 * 6602 * Special Considerations: 6603 * 6604 * note 6605 */ 6606 static void 6607 bfa_fcs_vport_timeout(void *vport_arg) 6608 { 6609 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg; 6610 6611 vport->vport_stats.fdisc_timeouts++; 6612 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT); 6613 } 6614 6615 static void 6616 bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport) 6617 { 6618 struct bfad_vport_s *vport_drv = 6619 (struct bfad_vport_s *)vport->vport_drv; 6620 6621 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport); 6622 bfa_lps_delete(vport->lps); 6623 6624 if (vport_drv->comp_del) { 6625 complete(vport_drv->comp_del); 6626 return; 6627 } 6628 6629 /* 6630 * We queue the vport delete work to the IM work_q from here. 6631 * The memory for the bfad_vport_s is freed from the FC function 6632 * template vport_delete entry point. 6633 */ 6634 bfad_im_port_delete(vport_drv->drv_port.bfad, &vport_drv->drv_port); 6635 } 6636 6637 /* 6638 * fcs_vport_public FCS virtual port public interfaces 6639 */ 6640 6641 /* 6642 * Online notification from fabric SM. 6643 */ 6644 void 6645 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport) 6646 { 6647 vport->vport_stats.fab_online++; 6648 if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) 6649 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); 6650 else 6651 vport->vport_stats.fab_no_npiv++; 6652 } 6653 6654 /* 6655 * Offline notification from fabric SM. 6656 */ 6657 void 6658 bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport) 6659 { 6660 vport->vport_stats.fab_offline++; 6661 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE); 6662 } 6663 6664 /* 6665 * Cleanup notification from fabric SM on link timer expiry. 6666 */ 6667 void 6668 bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport) 6669 { 6670 vport->vport_stats.fab_cleanup++; 6671 } 6672 6673 /* 6674 * Stop notification from fabric SM. To be invoked from within FCS. 6675 */ 6676 void 6677 bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport) 6678 { 6679 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP); 6680 } 6681 6682 /* 6683 * delete notification from fabric SM. To be invoked from within FCS. 6684 */ 6685 void 6686 bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport) 6687 { 6688 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); 6689 } 6690 6691 /* 6692 * Stop completion callback from associated lport 6693 */ 6694 void 6695 bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport) 6696 { 6697 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP); 6698 } 6699 6700 /* 6701 * Delete completion callback from associated lport 6702 */ 6703 void 6704 bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport) 6705 { 6706 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP); 6707 } 6708 6709 6710 6711 /* 6712 * fcs_vport_api Virtual port API 6713 */ 6714 6715 /* 6716 * Use this function to instantiate a new FCS vport object. This 6717 * function will not trigger any HW initialization process (which will be 6718 * done in vport_start() call) 6719 * 6720 * param[in] vport - pointer to bfa_fcs_vport_t. This space 6721 * needs to be allocated by the driver. 6722 * param[in] fcs - FCS instance 6723 * param[in] vport_cfg - vport configuration 6724 * param[in] vf_id - VF_ID if vport is created within a VF. 6725 * FC_VF_ID_NULL to specify base fabric. 6726 * param[in] vport_drv - Opaque handle back to the driver's vport 6727 * structure 6728 * 6729 * retval BFA_STATUS_OK - on success. 6730 * retval BFA_STATUS_FAILED - on failure. 6731 */ 6732 bfa_status_t 6733 bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, 6734 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg, 6735 struct bfad_vport_s *vport_drv) 6736 { 6737 if (vport_cfg->pwwn == 0) 6738 return BFA_STATUS_INVALID_WWN; 6739 6740 if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn) 6741 return BFA_STATUS_VPORT_WWN_BP; 6742 6743 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL) 6744 return BFA_STATUS_VPORT_EXISTS; 6745 6746 if (fcs->fabric.num_vports == 6747 bfa_lps_get_max_vport(fcs->bfa)) 6748 return BFA_STATUS_VPORT_MAX; 6749 6750 vport->lps = bfa_lps_alloc(fcs->bfa); 6751 if (!vport->lps) 6752 return BFA_STATUS_VPORT_MAX; 6753 6754 vport->vport_drv = vport_drv; 6755 vport_cfg->preboot_vp = BFA_FALSE; 6756 6757 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); 6758 bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport); 6759 bfa_fcs_lport_init(&vport->lport, vport_cfg); 6760 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE); 6761 6762 return BFA_STATUS_OK; 6763 } 6764 6765 /* 6766 * Use this function to instantiate a new FCS PBC vport object. This 6767 * function will not trigger any HW initialization process (which will be 6768 * done in vport_start() call) 6769 * 6770 * param[in] vport - pointer to bfa_fcs_vport_t. This space 6771 * needs to be allocated by the driver. 6772 * param[in] fcs - FCS instance 6773 * param[in] vport_cfg - vport configuration 6774 * param[in] vf_id - VF_ID if vport is created within a VF. 6775 * FC_VF_ID_NULL to specify base fabric. 6776 * param[in] vport_drv - Opaque handle back to the driver's vport 6777 * structure 6778 * 6779 * retval BFA_STATUS_OK - on success. 6780 * retval BFA_STATUS_FAILED - on failure. 6781 */ 6782 bfa_status_t 6783 bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, 6784 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg, 6785 struct bfad_vport_s *vport_drv) 6786 { 6787 bfa_status_t rc; 6788 6789 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv); 6790 vport->lport.port_cfg.preboot_vp = BFA_TRUE; 6791 6792 return rc; 6793 } 6794 6795 /* 6796 * Use this function to findout if this is a pbc vport or not. 6797 * 6798 * @param[in] vport - pointer to bfa_fcs_vport_t. 6799 * 6800 * @returns None 6801 */ 6802 bfa_boolean_t 6803 bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport) 6804 { 6805 6806 if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE)) 6807 return BFA_TRUE; 6808 else 6809 return BFA_FALSE; 6810 6811 } 6812 6813 /* 6814 * Use this function initialize the vport. 6815 * 6816 * @param[in] vport - pointer to bfa_fcs_vport_t. 6817 * 6818 * @returns None 6819 */ 6820 bfa_status_t 6821 bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport) 6822 { 6823 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START); 6824 6825 return BFA_STATUS_OK; 6826 } 6827 6828 /* 6829 * Use this function quiese the vport object. This function will return 6830 * immediately, when the vport is actually stopped, the 6831 * bfa_drv_vport_stop_cb() will be called. 6832 * 6833 * param[in] vport - pointer to bfa_fcs_vport_t. 6834 * 6835 * return None 6836 */ 6837 bfa_status_t 6838 bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport) 6839 { 6840 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP); 6841 6842 return BFA_STATUS_OK; 6843 } 6844 6845 /* 6846 * Use this function to delete a vport object. Fabric object should 6847 * be stopped before this function call. 6848 * 6849 * !!!!!!! Donot invoke this from within FCS !!!!!!! 6850 * 6851 * param[in] vport - pointer to bfa_fcs_vport_t. 6852 * 6853 * return None 6854 */ 6855 bfa_status_t 6856 bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport) 6857 { 6858 6859 if (vport->lport.port_cfg.preboot_vp) 6860 return BFA_STATUS_PBC; 6861 6862 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); 6863 6864 return BFA_STATUS_OK; 6865 } 6866 6867 /* 6868 * Use this function to get vport's current status info. 6869 * 6870 * param[in] vport pointer to bfa_fcs_vport_t. 6871 * param[out] attr pointer to return vport attributes 6872 * 6873 * return None 6874 */ 6875 void 6876 bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport, 6877 struct bfa_vport_attr_s *attr) 6878 { 6879 if (vport == NULL || attr == NULL) 6880 return; 6881 6882 memset(attr, 0, sizeof(struct bfa_vport_attr_s)); 6883 6884 bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr); 6885 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm); 6886 } 6887 6888 6889 /* 6890 * Lookup a virtual port. Excludes base port from lookup. 6891 */ 6892 struct bfa_fcs_vport_s * 6893 bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn) 6894 { 6895 struct bfa_fcs_vport_s *vport; 6896 struct bfa_fcs_fabric_s *fabric; 6897 6898 bfa_trc(fcs, vf_id); 6899 bfa_trc(fcs, vpwwn); 6900 6901 fabric = bfa_fcs_vf_lookup(fcs, vf_id); 6902 if (!fabric) { 6903 bfa_trc(fcs, vf_id); 6904 return NULL; 6905 } 6906 6907 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn); 6908 return vport; 6909 } 6910 6911 /* 6912 * FDISC Response 6913 */ 6914 void 6915 bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) 6916 { 6917 struct bfa_fcs_vport_s *vport = uarg; 6918 6919 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 6920 bfa_trc(__vport_fcs(vport), status); 6921 6922 switch (status) { 6923 case BFA_STATUS_OK: 6924 /* 6925 * Initialize the V-Port fields 6926 */ 6927 __vport_fcid(vport) = vport->lps->lp_pid; 6928 vport->vport_stats.fdisc_accepts++; 6929 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); 6930 break; 6931 6932 case BFA_STATUS_INVALID_MAC: 6933 /* Only for CNA */ 6934 vport->vport_stats.fdisc_acc_bad++; 6935 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 6936 6937 break; 6938 6939 case BFA_STATUS_EPROTOCOL: 6940 switch (vport->lps->ext_status) { 6941 case BFA_EPROTO_BAD_ACCEPT: 6942 vport->vport_stats.fdisc_acc_bad++; 6943 break; 6944 6945 case BFA_EPROTO_UNKNOWN_RSP: 6946 vport->vport_stats.fdisc_unknown_rsp++; 6947 break; 6948 6949 default: 6950 break; 6951 } 6952 6953 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) 6954 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 6955 else 6956 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); 6957 6958 break; 6959 6960 case BFA_STATUS_ETIMER: 6961 vport->vport_stats.fdisc_timeouts++; 6962 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) 6963 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 6964 else 6965 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); 6966 break; 6967 6968 case BFA_STATUS_FABRIC_RJT: 6969 vport->vport_stats.fdisc_rejects++; 6970 bfa_fcs_vport_fdisc_rejected(vport); 6971 break; 6972 6973 default: 6974 vport->vport_stats.fdisc_rsp_err++; 6975 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 6976 } 6977 } 6978 6979 /* 6980 * LOGO response 6981 */ 6982 void 6983 bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg) 6984 { 6985 struct bfa_fcs_vport_s *vport = uarg; 6986 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); 6987 } 6988 6989 /* 6990 * Received clear virtual link 6991 */ 6992 void 6993 bfa_cb_lps_cvl_event(void *bfad, void *uarg) 6994 { 6995 struct bfa_fcs_vport_s *vport = uarg; 6996 6997 /* Send an Offline followed by an ONLINE */ 6998 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE); 6999 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); 7000 } 7001