1/* 2 * Copyright (c) 2005-2009 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/** 19 * bfa_fcs_vport.c FCS virtual port state machine 20 */ 21 22#include <bfa.h> 23#include <bfa_svc.h> 24#include <fcbuild.h> 25#include "fcs_fabric.h" 26#include "fcs_lport.h" 27#include "fcs_vport.h" 28#include "fcs_trcmod.h" 29#include "fcs.h" 30#include <aen/bfa_aen_lport.h> 31 32BFA_TRC_FILE(FCS, VPORT); 33 34#define __vport_fcs(__vp) ((__vp)->lport.fcs) 35#define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn) 36#define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn) 37#define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa) 38#define __vport_fcid(__vp) ((__vp)->lport.pid) 39#define __vport_fabric(__vp) ((__vp)->lport.fabric) 40#define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id) 41 42#define BFA_FCS_VPORT_MAX_RETRIES 5 43/* 44 * Forward declarations 45 */ 46static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport); 47static void bfa_fcs_vport_timeout(void *vport_arg); 48static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport); 49static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport); 50 51/** 52 * fcs_vport_sm FCS virtual port state machine 53 */ 54 55/** 56 * VPort State Machine events 57 */ 58enum bfa_fcs_vport_event { 59 BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */ 60 BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */ 61 BFA_FCS_VPORT_SM_START = 3, /* vport start request */ 62 BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */ 63 BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */ 64 BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */ 65 BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */ 66 BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */ 67 BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */ 68 BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */ 69 BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */ 70 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error */ 71 BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */ 72}; 73 74static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, 75 enum bfa_fcs_vport_event event); 76static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, 77 enum bfa_fcs_vport_event event); 78static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, 79 enum bfa_fcs_vport_event event); 80static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, 81 enum bfa_fcs_vport_event event); 82static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, 83 enum bfa_fcs_vport_event event); 84static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, 85 enum bfa_fcs_vport_event event); 86static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, 87 enum bfa_fcs_vport_event event); 88static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, 89 enum bfa_fcs_vport_event event); 90static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, 91 enum bfa_fcs_vport_event event); 92static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, 93 enum bfa_fcs_vport_event event); 94 95static struct bfa_sm_table_s vport_sm_table[] = { 96 {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT}, 97 {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED}, 98 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE}, 99 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC}, 100 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY}, 101 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE}, 102 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING}, 103 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP}, 104 {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO}, 105 {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR} 106}; 107 108/** 109 * Beginning state. 110 */ 111static void 112bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, 113 enum bfa_fcs_vport_event event) 114{ 115 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 116 bfa_trc(__vport_fcs(vport), event); 117 118 switch (event) { 119 case BFA_FCS_VPORT_SM_CREATE: 120 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); 121 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport); 122 break; 123 124 default: 125 bfa_sm_fault(__vport_fcs(vport), event); 126 } 127} 128 129/** 130 * Created state - a start event is required to start up the state machine. 131 */ 132static void 133bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, 134 enum bfa_fcs_vport_event event) 135{ 136 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 137 bfa_trc(__vport_fcs(vport), event); 138 139 switch (event) { 140 case BFA_FCS_VPORT_SM_START: 141 if (bfa_fcs_fabric_is_online(__vport_fabric(vport)) 142 && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) { 143 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); 144 bfa_fcs_vport_do_fdisc(vport); 145 } else { 146 /** 147 * Fabric is offline or not NPIV capable, stay in 148 * offline state. 149 */ 150 vport->vport_stats.fab_no_npiv++; 151 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 152 } 153 break; 154 155 case BFA_FCS_VPORT_SM_DELETE: 156 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 157 bfa_fcs_port_delete(&vport->lport); 158 break; 159 160 case BFA_FCS_VPORT_SM_ONLINE: 161 case BFA_FCS_VPORT_SM_OFFLINE: 162 /** 163 * Ignore ONLINE/OFFLINE events from fabric till vport is started. 164 */ 165 break; 166 167 default: 168 bfa_sm_fault(__vport_fcs(vport), event); 169 } 170} 171 172/** 173 * Offline state - awaiting ONLINE event from fabric SM. 174 */ 175static void 176bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, 177 enum bfa_fcs_vport_event event) 178{ 179 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 180 bfa_trc(__vport_fcs(vport), event); 181 182 switch (event) { 183 case BFA_FCS_VPORT_SM_DELETE: 184 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 185 bfa_fcs_port_delete(&vport->lport); 186 break; 187 188 case BFA_FCS_VPORT_SM_ONLINE: 189 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); 190 vport->fdisc_retries = 0; 191 bfa_fcs_vport_do_fdisc(vport); 192 break; 193 194 case BFA_FCS_VPORT_SM_OFFLINE: 195 /* 196 * This can happen if the vport couldn't be initialzied due 197 * the fact that the npiv was not enabled on the switch. In 198 * that case we will put the vport in offline state. However, 199 * the link can go down and cause the this event to be sent when 200 * we are already offline. Ignore it. 201 */ 202 break; 203 204 default: 205 bfa_sm_fault(__vport_fcs(vport), event); 206 } 207} 208 209/** 210 * FDISC is sent and awaiting reply from fabric. 211 */ 212static void 213bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, 214 enum bfa_fcs_vport_event event) 215{ 216 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 217 bfa_trc(__vport_fcs(vport), event); 218 219 switch (event) { 220 case BFA_FCS_VPORT_SM_DELETE: 221 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 222 bfa_lps_discard(vport->lps); 223 bfa_fcs_port_delete(&vport->lport); 224 break; 225 226 case BFA_FCS_VPORT_SM_OFFLINE: 227 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 228 bfa_lps_discard(vport->lps); 229 break; 230 231 case BFA_FCS_VPORT_SM_RSP_OK: 232 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online); 233 bfa_fcs_port_online(&vport->lport); 234 break; 235 236 case BFA_FCS_VPORT_SM_RSP_ERROR: 237 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry); 238 bfa_timer_start(__vport_bfa(vport), &vport->timer, 239 bfa_fcs_vport_timeout, vport, 240 BFA_FCS_RETRY_TIMEOUT); 241 break; 242 243 case BFA_FCS_VPORT_SM_RSP_FAILED: 244 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 245 break; 246 247 case BFA_FCS_VPORT_SM_RSP_DUP_WWN: 248 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error); 249 break; 250 251 default: 252 bfa_sm_fault(__vport_fcs(vport), event); 253 } 254} 255 256/** 257 * FDISC attempt failed - a timer is active to retry FDISC. 258 */ 259static void 260bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, 261 enum bfa_fcs_vport_event event) 262{ 263 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 264 bfa_trc(__vport_fcs(vport), event); 265 266 switch (event) { 267 case BFA_FCS_VPORT_SM_DELETE: 268 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 269 bfa_timer_stop(&vport->timer); 270 bfa_fcs_port_delete(&vport->lport); 271 break; 272 273 case BFA_FCS_VPORT_SM_OFFLINE: 274 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 275 bfa_timer_stop(&vport->timer); 276 break; 277 278 case BFA_FCS_VPORT_SM_TIMEOUT: 279 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); 280 vport->vport_stats.fdisc_retries++; 281 vport->fdisc_retries++; 282 bfa_fcs_vport_do_fdisc(vport); 283 break; 284 285 default: 286 bfa_sm_fault(__vport_fcs(vport), event); 287 } 288} 289 290/** 291 * Vport is online (FDISC is complete). 292 */ 293static void 294bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, 295 enum bfa_fcs_vport_event event) 296{ 297 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 298 bfa_trc(__vport_fcs(vport), event); 299 300 switch (event) { 301 case BFA_FCS_VPORT_SM_DELETE: 302 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting); 303 bfa_fcs_port_delete(&vport->lport); 304 break; 305 306 case BFA_FCS_VPORT_SM_OFFLINE: 307 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); 308 bfa_lps_discard(vport->lps); 309 bfa_fcs_port_offline(&vport->lport); 310 break; 311 312 default: 313 bfa_sm_fault(__vport_fcs(vport), event); 314 } 315} 316 317/** 318 * Vport is being deleted - awaiting lport delete completion to send 319 * LOGO to fabric. 320 */ 321static void 322bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, 323 enum bfa_fcs_vport_event event) 324{ 325 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 326 bfa_trc(__vport_fcs(vport), event); 327 328 switch (event) { 329 case BFA_FCS_VPORT_SM_DELETE: 330 break; 331 332 case BFA_FCS_VPORT_SM_DELCOMP: 333 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo); 334 bfa_fcs_vport_do_logo(vport); 335 break; 336 337 case BFA_FCS_VPORT_SM_OFFLINE: 338 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 339 break; 340 341 default: 342 bfa_sm_fault(__vport_fcs(vport), event); 343 } 344} 345 346/** 347 * Error State. 348 * This state will be set when the Vport Creation fails due to errors like 349 * Dup WWN. In this state only operation allowed is a Vport Delete. 350 */ 351static void 352bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, 353 enum bfa_fcs_vport_event event) 354{ 355 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 356 bfa_trc(__vport_fcs(vport), event); 357 358 switch (event) { 359 case BFA_FCS_VPORT_SM_DELETE: 360 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 361 bfa_fcs_port_delete(&vport->lport); 362 363 break; 364 365 default: 366 bfa_trc(__vport_fcs(vport), event); 367 } 368} 369 370/** 371 * Lport cleanup is in progress since vport is being deleted. Fabric is 372 * offline, so no LOGO is needed to complete vport deletion. 373 */ 374static void 375bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, 376 enum bfa_fcs_vport_event event) 377{ 378 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 379 bfa_trc(__vport_fcs(vport), event); 380 381 switch (event) { 382 case BFA_FCS_VPORT_SM_DELCOMP: 383 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); 384 bfa_fcs_vport_free(vport); 385 break; 386 387 case BFA_FCS_VPORT_SM_DELETE: 388 break; 389 390 default: 391 bfa_sm_fault(__vport_fcs(vport), event); 392 } 393} 394 395/** 396 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup 397 * is done. 398 */ 399static void 400bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, 401 enum bfa_fcs_vport_event event) 402{ 403 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 404 bfa_trc(__vport_fcs(vport), event); 405 406 switch (event) { 407 case BFA_FCS_VPORT_SM_OFFLINE: 408 bfa_lps_discard(vport->lps); 409 /* 410 * !!! fall through !!! 411 */ 412 413 case BFA_FCS_VPORT_SM_RSP_OK: 414 case BFA_FCS_VPORT_SM_RSP_ERROR: 415 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); 416 bfa_fcs_vport_free(vport); 417 break; 418 419 case BFA_FCS_VPORT_SM_DELETE: 420 break; 421 422 default: 423 bfa_sm_fault(__vport_fcs(vport), event); 424 } 425} 426 427 428 429/** 430 * fcs_vport_private FCS virtual port private functions 431 */ 432 433/** 434 * Send AEN notification 435 */ 436static void 437bfa_fcs_vport_aen_post(bfa_fcs_lport_t *port, enum bfa_lport_aen_event event) 438{ 439 union bfa_aen_data_u aen_data; 440 struct bfa_log_mod_s *logmod = port->fcs->logm; 441 enum bfa_port_role role = port->port_cfg.roles; 442 wwn_t lpwwn = bfa_fcs_port_get_pwwn(port); 443 char lpwwn_ptr[BFA_STRING_32]; 444 char *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] = 445 { "Initiator", "Target", "IPFC" }; 446 447 wwn2str(lpwwn_ptr, lpwwn); 448 449 bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX); 450 451 bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, event), lpwwn_ptr, 452 role_str[role/2]); 453 454 aen_data.lport.vf_id = port->fabric->vf_id; 455 aen_data.lport.roles = role; 456 aen_data.lport.ppwwn = 457 bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs)); 458 aen_data.lport.lpwwn = lpwwn; 459} 460 461/** 462 * This routine will be called to send a FDISC command. 463 */ 464static void 465bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport) 466{ 467 bfa_lps_fdisc(vport->lps, vport, 468 bfa_fcport_get_maxfrsize(__vport_bfa(vport)), 469 __vport_pwwn(vport), __vport_nwwn(vport)); 470 vport->vport_stats.fdisc_sent++; 471} 472 473static void 474bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport) 475{ 476 u8 lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps); 477 u8 lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps); 478 479 bfa_trc(__vport_fcs(vport), lsrjt_rsn); 480 bfa_trc(__vport_fcs(vport), lsrjt_expl); 481 482 /* 483 * For certain reason codes, we don't want to retry. 484 */ 485 switch (bfa_lps_get_lsrjt_expl(vport->lps)) { 486 case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */ 487 case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */ 488 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) 489 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 490 else { 491 bfa_fcs_vport_aen_post(&vport->lport, 492 BFA_LPORT_AEN_NPIV_DUP_WWN); 493 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN); 494 } 495 break; 496 497 case FC_LS_RJT_EXP_INSUFF_RES: 498 /* 499 * This means max logins per port/switch setting on the 500 * switch was exceeded. 501 */ 502 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) 503 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 504 else { 505 bfa_fcs_vport_aen_post(&vport->lport, 506 BFA_LPORT_AEN_NPIV_FABRIC_MAX); 507 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); 508 } 509 break; 510 511 default: 512 if (vport->fdisc_retries == 0) /* Print only once */ 513 bfa_fcs_vport_aen_post(&vport->lport, 514 BFA_LPORT_AEN_NPIV_UNKNOWN); 515 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 516 } 517} 518 519/** 520 * Called to send a logout to the fabric. Used when a V-Port is 521 * deleted/stopped. 522 */ 523static void 524bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport) 525{ 526 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 527 528 vport->vport_stats.logo_sent++; 529 bfa_lps_fdisclogo(vport->lps); 530} 531 532/** 533 * This routine will be called by bfa_timer on timer timeouts. 534 * 535 * param[in] vport - pointer to bfa_fcs_vport_t. 536 * param[out] vport_status - pointer to return vport status in 537 * 538 * return 539 * void 540 * 541* Special Considerations: 542 * 543 * note 544 */ 545static void 546bfa_fcs_vport_timeout(void *vport_arg) 547{ 548 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *)vport_arg; 549 550 vport->vport_stats.fdisc_timeouts++; 551 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT); 552} 553 554static void 555bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport) 556{ 557 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport); 558 bfa_fcb_vport_delete(vport->vport_drv); 559 bfa_lps_delete(vport->lps); 560} 561 562 563 564/** 565 * fcs_vport_public FCS virtual port public interfaces 566 */ 567 568/** 569 * Online notification from fabric SM. 570 */ 571void 572bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport) 573{ 574 vport->vport_stats.fab_online++; 575 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); 576} 577 578/** 579 * Offline notification from fabric SM. 580 */ 581void 582bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport) 583{ 584 vport->vport_stats.fab_offline++; 585 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE); 586} 587 588/** 589 * Cleanup notification from fabric SM on link timer expiry. 590 */ 591void 592bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport) 593{ 594 vport->vport_stats.fab_cleanup++; 595} 596 597/** 598 * delete notification from fabric SM. To be invoked from within FCS. 599 */ 600void 601bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport) 602{ 603 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); 604} 605 606/** 607 * Delete completion callback from associated lport 608 */ 609void 610bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport) 611{ 612 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP); 613} 614 615/** 616 * fcs_vport_api Virtual port API 617 */ 618 619/** 620 * Use this function to instantiate a new FCS vport object. This 621 * function will not trigger any HW initialization process (which will be 622 * done in vport_start() call) 623 * 624 * param[in] vport - pointer to bfa_fcs_vport_t. This space 625 * needs to be allocated by the driver. 626 * param[in] fcs - FCS instance 627 * param[in] vport_cfg - vport configuration 628 * param[in] vf_id - VF_ID if vport is created within a VF. 629 * FC_VF_ID_NULL to specify base fabric. 630 * param[in] vport_drv - Opaque handle back to the driver's vport 631 * structure 632 * 633 * retval BFA_STATUS_OK - on success. 634 * retval BFA_STATUS_FAILED - on failure. 635 */ 636bfa_status_t 637bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, 638 u16 vf_id, struct bfa_port_cfg_s *vport_cfg, 639 struct bfad_vport_s *vport_drv) 640{ 641 if (vport_cfg->pwwn == 0) 642 return BFA_STATUS_INVALID_WWN; 643 644 if (bfa_fcs_port_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn) 645 return BFA_STATUS_VPORT_WWN_BP; 646 647 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL) 648 return BFA_STATUS_VPORT_EXISTS; 649 650 if (bfa_fcs_fabric_vport_count(&fcs->fabric) == 651 bfa_lps_get_max_vport(fcs->bfa)) 652 return BFA_STATUS_VPORT_MAX; 653 654 vport->lps = bfa_lps_alloc(fcs->bfa); 655 if (!vport->lps) 656 return BFA_STATUS_VPORT_MAX; 657 658 vport->vport_drv = vport_drv; 659 vport_cfg->preboot_vp = BFA_FALSE; 660 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); 661 662 bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport); 663 bfa_fcs_lport_init(&vport->lport, vport_cfg); 664 665 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE); 666 667 return BFA_STATUS_OK; 668} 669 670/** 671 * Use this function to instantiate a new FCS PBC vport object. This 672 * function will not trigger any HW initialization process (which will be 673 * done in vport_start() call) 674 * 675 * param[in] vport - pointer to bfa_fcs_vport_t. This space 676 * needs to be allocated by the driver. 677 * param[in] fcs - FCS instance 678 * param[in] vport_cfg - vport configuration 679 * param[in] vf_id - VF_ID if vport is created within a VF. 680 * FC_VF_ID_NULL to specify base fabric. 681 * param[in] vport_drv - Opaque handle back to the driver's vport 682 * structure 683 * 684 * retval BFA_STATUS_OK - on success. 685 * retval BFA_STATUS_FAILED - on failure. 686 */ 687bfa_status_t 688bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, 689 uint16_t vf_id, struct bfa_port_cfg_s *vport_cfg, 690 struct bfad_vport_s *vport_drv) 691{ 692 bfa_status_t rc; 693 694 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv); 695 vport->lport.port_cfg.preboot_vp = BFA_TRUE; 696 697 return rc; 698} 699 700/** 701 * Use this function initialize the vport. 702 * 703 * @param[in] vport - pointer to bfa_fcs_vport_t. 704 * 705 * @returns None 706 */ 707bfa_status_t 708bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport) 709{ 710 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START); 711 712 return BFA_STATUS_OK; 713} 714 715/** 716 * Use this function quiese the vport object. This function will return 717 * immediately, when the vport is actually stopped, the 718 * bfa_drv_vport_stop_cb() will be called. 719 * 720 * param[in] vport - pointer to bfa_fcs_vport_t. 721 * 722 * return None 723 */ 724bfa_status_t 725bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport) 726{ 727 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP); 728 729 return BFA_STATUS_OK; 730} 731 732/** 733 * Use this function to delete a vport object. Fabric object should 734 * be stopped before this function call. 735 * 736 * Donot invoke this from within FCS 737 * 738 * param[in] vport - pointer to bfa_fcs_vport_t. 739 * 740 * return None 741 */ 742bfa_status_t 743bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport) 744{ 745 if (vport->lport.port_cfg.preboot_vp) 746 return BFA_STATUS_PBC; 747 748 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); 749 750 return BFA_STATUS_OK; 751} 752 753/** 754 * Use this function to get vport's current status info. 755 * 756 * param[in] vport pointer to bfa_fcs_vport_t. 757 * param[out] attr pointer to return vport attributes 758 * 759 * return None 760 */ 761void 762bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport, 763 struct bfa_vport_attr_s *attr) 764{ 765 if (vport == NULL || attr == NULL) 766 return; 767 768 bfa_os_memset(attr, 0, sizeof(struct bfa_vport_attr_s)); 769 770 bfa_fcs_port_get_attr(&vport->lport, &attr->port_attr); 771 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm); 772} 773 774/** 775 * Use this function to get vport's statistics. 776 * 777 * param[in] vport pointer to bfa_fcs_vport_t. 778 * param[out] stats pointer to return vport statistics in 779 * 780 * return None 781 */ 782void 783bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport, 784 struct bfa_vport_stats_s *stats) 785{ 786 *stats = vport->vport_stats; 787} 788 789/** 790 * Use this function to clear vport's statistics. 791 * 792 * param[in] vport pointer to bfa_fcs_vport_t. 793 * 794 * return None 795 */ 796void 797bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport) 798{ 799 bfa_os_memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s)); 800} 801 802/** 803 * Lookup a virtual port. Excludes base port from lookup. 804 */ 805struct bfa_fcs_vport_s * 806bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn) 807{ 808 struct bfa_fcs_vport_s *vport; 809 struct bfa_fcs_fabric_s *fabric; 810 811 bfa_trc(fcs, vf_id); 812 bfa_trc(fcs, vpwwn); 813 814 fabric = bfa_fcs_vf_lookup(fcs, vf_id); 815 if (!fabric) { 816 bfa_trc(fcs, vf_id); 817 return NULL; 818 } 819 820 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn); 821 return vport; 822} 823 824/** 825 * FDISC Response 826 */ 827void 828bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) 829{ 830 struct bfa_fcs_vport_s *vport = uarg; 831 832 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); 833 bfa_trc(__vport_fcs(vport), status); 834 835 switch (status) { 836 case BFA_STATUS_OK: 837 /* 838 * Initialize the V-Port fields 839 */ 840 __vport_fcid(vport) = bfa_lps_get_pid(vport->lps); 841 vport->vport_stats.fdisc_accepts++; 842 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); 843 break; 844 845 case BFA_STATUS_INVALID_MAC: 846 /* 847 * Only for CNA 848 */ 849 vport->vport_stats.fdisc_acc_bad++; 850 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 851 852 break; 853 854 case BFA_STATUS_EPROTOCOL: 855 switch (bfa_lps_get_extstatus(vport->lps)) { 856 case BFA_EPROTO_BAD_ACCEPT: 857 vport->vport_stats.fdisc_acc_bad++; 858 break; 859 860 case BFA_EPROTO_UNKNOWN_RSP: 861 vport->vport_stats.fdisc_unknown_rsp++; 862 break; 863 864 default: 865 break; 866 } 867 868 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 869 break; 870 871 case BFA_STATUS_FABRIC_RJT: 872 vport->vport_stats.fdisc_rejects++; 873 bfa_fcs_vport_fdisc_rejected(vport); 874 break; 875 876 default: 877 vport->vport_stats.fdisc_rsp_err++; 878 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); 879 } 880} 881 882/** 883 * LOGO response 884 */ 885void 886bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg) 887{ 888 struct bfa_fcs_vport_s *vport = uarg; 889 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); 890} 891 892/** 893 * Received clear virtual link 894 */ 895void 896bfa_cb_lps_cvl_event(void *bfad, void *uarg) 897{ 898 struct bfa_fcs_vport_s *vport = uarg; 899 900 /* Send an Offline followed by an ONLINE */ 901 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE); 902 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); 903} 904