/** * Offline state - awaiting ONLINE event from fabric SM. */ static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_DELETE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); bfa_fcs_port_delete(&vport->lport); break; case BFA_FCS_VPORT_SM_ONLINE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); vport->fdisc_retries = 0; bfa_fcs_vport_do_fdisc(vport); break; case BFA_FCS_VPORT_SM_OFFLINE: /* * This can happen if the vport couldn't be initialzied due * the fact that the npiv was not enabled on the switch. In * that case we will put the vport in offline state. However, * the link can go down and cause the this event to be sent when * we are already offline. Ignore it. */ break; default: bfa_assert(0); } }
/** * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup * is done. */ static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_OFFLINE: bfa_lps_discard(vport->lps); /* * !!! fall through !!! */ case BFA_FCS_VPORT_SM_RSP_OK: case BFA_FCS_VPORT_SM_RSP_ERROR: bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); bfa_fcs_vport_free(vport); break; case BFA_FCS_VPORT_SM_DELETE: break; default: bfa_assert(0); } }
/** * FDISC attempt failed - a timer is active to retry FDISC. */ static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_DELETE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); bfa_timer_stop(&vport->timer); bfa_fcs_port_delete(&vport->lport); break; case BFA_FCS_VPORT_SM_OFFLINE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); bfa_timer_stop(&vport->timer); break; case BFA_FCS_VPORT_SM_TIMEOUT: bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); vport->vport_stats.fdisc_retries++; vport->fdisc_retries++; bfa_fcs_vport_do_fdisc(vport); break; default: bfa_assert(0); } }
static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_START: if (bfa_fcs_fabric_is_online(__vport_fabric(vport)) && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) { bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); bfa_fcs_vport_do_fdisc(vport); } else { vport->vport_stats.fab_no_npiv++; bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); } break; case BFA_FCS_VPORT_SM_DELETE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); bfa_fcs_port_delete(&vport->lport); break; case BFA_FCS_VPORT_SM_ONLINE: case BFA_FCS_VPORT_SM_OFFLINE: break; default: bfa_assert(0); } }
/** * FDISC Response */ void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) { struct bfa_fcs_vport_s *vport = uarg; bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), status); switch (status) { case BFA_STATUS_OK: /* * Initialiaze the V-Port fields */ __vport_fcid(vport) = bfa_lps_get_pid(vport->lps); vport->vport_stats.fdisc_accepts++; bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); break; case BFA_STATUS_INVALID_MAC: /* * Only for CNA */ vport->vport_stats.fdisc_acc_bad++; bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); break; case BFA_STATUS_EPROTOCOL: switch (bfa_lps_get_extstatus(vport->lps)) { case BFA_EPROTO_BAD_ACCEPT: vport->vport_stats.fdisc_acc_bad++; break; case BFA_EPROTO_UNKNOWN_RSP: vport->vport_stats.fdisc_unknown_rsp++; break; default: break; } bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); break; case BFA_STATUS_FABRIC_RJT: vport->vport_stats.fdisc_rejects++; bfa_fcs_vport_fdisc_rejected(vport); break; default: vport->vport_stats.fdisc_rsp_err++; bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); } }
/** * Called to send a logout to the fabric. Used when a V-Port is * deleted/stopped. */ static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); vport->vport_stats.logo_sent++; bfa_lps_fdisclogo(vport->lps); }
/** * Error State. * This state will be set when the Vport Creation fails due to errors like * Dup WWN. In this state only operation allowed is a Vport Delete. */ static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_DELETE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); bfa_fcs_vport_free(vport); break; default: bfa_trc(__vport_fcs(vport), event); } }
/** * Beginning state. */ static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_CREATE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); bfa_fcs_fabric_addvport(__vport_fabric(vport), vport); break; default: bfa_assert(0); } }
static void bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport) { u8 lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps); u8 lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps); bfa_trc(__vport_fcs(vport), lsrjt_rsn); bfa_trc(__vport_fcs(vport), lsrjt_expl); /* * For certain reason codes, we don't want to retry. */ switch (bfa_lps_get_lsrjt_expl(vport->lps)) { case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */ case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */ if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); else { bfa_fcs_vport_aen_post(&vport->lport, BFA_LPORT_AEN_NPIV_DUP_WWN); bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN); } break; case FC_LS_RJT_EXP_INSUFF_RES: /* * This means max logins per port/switch setting on the * switch was exceeded. */ if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); else { bfa_fcs_vport_aen_post(&vport->lport, BFA_LPORT_AEN_NPIV_FABRIC_MAX); bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); } break; default: if (vport->fdisc_retries == 0) /* Print only once */ bfa_fcs_vport_aen_post(&vport->lport, BFA_LPORT_AEN_NPIV_UNKNOWN); bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); } }
/** * FDISC is sent and awaiting reply from fabric. */ static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_DELETE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo); bfa_lps_discard(vport->lps); bfa_fcs_vport_do_logo(vport); break; case BFA_FCS_VPORT_SM_OFFLINE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); bfa_lps_discard(vport->lps); break; case BFA_FCS_VPORT_SM_RSP_OK: bfa_sm_set_state(vport, bfa_fcs_vport_sm_online); bfa_fcs_port_online(&vport->lport); break; case BFA_FCS_VPORT_SM_RSP_ERROR: bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry); bfa_timer_start(__vport_bfa(vport), &vport->timer, bfa_fcs_vport_timeout, vport, BFA_FCS_RETRY_TIMEOUT); break; case BFA_FCS_VPORT_SM_RSP_FAILED: bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); break; case BFA_FCS_VPORT_SM_RSP_DUP_WWN: bfa_sm_set_state(vport, bfa_fcs_vport_sm_error); break; default: bfa_assert(0); } }
static void bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport) { u8 lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps); u8 lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps); bfa_trc(__vport_fcs(vport), lsrjt_rsn); bfa_trc(__vport_fcs(vport), lsrjt_expl); switch (bfa_lps_get_lsrjt_expl(vport->lps)) { case FC_LS_RJT_EXP_INV_PORT_NAME: case FC_LS_RJT_EXP_INVALID_NPORT_ID: if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); else { bfa_fcs_vport_aen_post(&vport->lport, BFA_LPORT_AEN_NPIV_DUP_WWN); bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN); } break; case FC_LS_RJT_EXP_INSUFF_RES: if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); else { bfa_fcs_vport_aen_post(&vport->lport, BFA_LPORT_AEN_NPIV_FABRIC_MAX); bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); } break; default: if (vport->fdisc_retries == 0) bfa_fcs_vport_aen_post(&vport->lport, BFA_LPORT_AEN_NPIV_UNKNOWN); bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); } }
/** * Created state - a start event is required to start up the state machine. */ static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_START: if (bfa_fcs_fabric_is_online(__vport_fabric(vport)) && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) { bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); bfa_fcs_vport_do_fdisc(vport); } else { /** * Fabric is offline or not NPIV capable, stay in * offline state. */ vport->vport_stats.fab_no_npiv++; bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); } break; case BFA_FCS_VPORT_SM_DELETE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); bfa_fcs_port_delete(&vport->lport); break; case BFA_FCS_VPORT_SM_ONLINE: case BFA_FCS_VPORT_SM_OFFLINE: /** * Ignore ONLINE/OFFLINE events from fabric till vport is started. */ break; default: bfa_assert(0); } }
/** * Vport is online (FDISC is complete). */ static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_DELETE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting); bfa_fcs_port_delete(&vport->lport); break; case BFA_FCS_VPORT_SM_OFFLINE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); bfa_lps_discard(vport->lps); bfa_fcs_port_offline(&vport->lport); break; default: bfa_assert(0); } }
/** * Vport is being deleted - awaiting lport delete completion to send * LOGO to fabric. */ static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, enum bfa_fcs_vport_event event) { bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); bfa_trc(__vport_fcs(vport), event); switch (event) { case BFA_FCS_VPORT_SM_DELETE: break; case BFA_FCS_VPORT_SM_DELCOMP: bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo); bfa_fcs_vport_do_logo(vport); break; case BFA_FCS_VPORT_SM_OFFLINE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); break; default: bfa_assert(0); } }