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