/* * PLOGI is being sent. */ static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport, enum rport_event event) { bfa_trc(rport->fcs, rport->pwwn); bfa_trc(rport->fcs, rport->pid); bfa_trc(rport->fcs, event); switch (event) { case RPSM_EVENT_FCXP_SENT: bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi); break; case RPSM_EVENT_DELETE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_fcs_rport_free(rport); break; case RPSM_EVENT_PLOGI_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_fcs_rport_send_plogiacc(rport, NULL); break; case RPSM_EVENT_SCN_OFFLINE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; case RPSM_EVENT_ADDRESS_CHANGE: case RPSM_EVENT_FAB_SCN: /* query the NS */ bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) != BFA_PORT_TOPOLOGY_LOOP)); bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); rport->ns_retries = 0; bfa_fcs_rport_send_nsdisc(rport, NULL); break; case RPSM_EVENT_LOGO_IMP: rport->pid = 0; bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; default: bfa_sm_fault(rport->fcs, event); } }
static void bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns, enum vport_ns_event event) { bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); bfa_trc(ns->port->fcs, event); switch (event) { case NSSM_EVENT_RSP_ERROR: /* * Start timer for a delayed retry */ bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id_retry); ns->port->stats.ns_retries++; bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer, bfa_fcs_port_ns_timeout, ns, BFA_FCS_RETRY_TIMEOUT); break; case NSSM_EVENT_RSP_OK: bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id); bfa_fcs_port_ns_send_rft_id(ns, NULL); break; case NSSM_EVENT_PORT_OFFLINE: bfa_fcxp_discard(ns->fcxp); bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); break; default: bfa_assert(0); } }
static void bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event) { bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); bfa_trc(ms->port->fcs, event); switch (event) { case MSSM_EVENT_RSP_ERROR: /* * Start timer for a delayed retry */ if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) { bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry); bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer, bfa_fcs_port_ms_timeout, ms, BFA_FCS_RETRY_TIMEOUT); } else { bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online); ms->retry_cnt = 0; } break; case MSSM_EVENT_RSP_OK: bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online); break; case MSSM_EVENT_PORT_OFFLINE: bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); bfa_fcxp_discard(ms->fcxp); break; default: bfa_assert(0); } }
static void bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns, enum vport_ns_event event) { bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); bfa_trc(ns->port->fcs, event); switch (event) { case NSSM_EVENT_RSP_OK: bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online); break; case NSSM_EVENT_RSP_ERROR: /* * TBD: for certain reject codes, we don't need to retry */ /* * Start timer for a delayed retry */ bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft_retry); ns->port->stats.ns_retries++; bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer, bfa_fcs_port_ns_timeout, ns, BFA_FCS_RETRY_TIMEOUT); break; case NSSM_EVENT_PORT_OFFLINE: bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); bfa_fcxp_discard(ns->fcxp); break; default: bfa_assert(0); } }
static void bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns, enum vport_ns_event event) { bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); bfa_trc(ns->port->fcs, event); switch (event) { case NSSM_EVENT_RSP_OK: /* * If min cfg mode is enabled, we donot initiate rport * discovery with the fabric. Instead, we will retrieve the * boot targets from HAL/FW. */ if (__fcs_min_cfg(ns->port->fcs)) { bfa_fcs_port_ns_boot_target_disc(ns->port); bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online); return; } /* * If the port role is Initiator Mode issue NS query. * If it is Target Mode, skip this and go to online. */ if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) { bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft); bfa_fcs_port_ns_send_gid_ft(ns, NULL); } else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port)) { bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online); } /* * kick off mgmt srvr state machine */ bfa_fcs_port_ms_online(ns->port); break; case NSSM_EVENT_RSP_ERROR: /* * Start timer for a delayed retry */ bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id_retry); ns->port->stats.ns_retries++; bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer, bfa_fcs_port_ns_timeout, ns, BFA_FCS_RETRY_TIMEOUT); break; case NSSM_EVENT_PORT_OFFLINE: bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); bfa_fcxp_discard(ns->fcxp); break; default: bfa_assert(0); } }
/* * ADISC to rport * Already did offline actions */ static void bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport, enum rport_event event) { bfa_trc(rport->fcs, rport->pwwn); bfa_trc(rport->fcs, rport->pid); bfa_trc(rport->fcs, event); switch (event) { case RPSM_EVENT_ACCEPTED: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); bfa_fcs_rport_hal_online(rport); break; case RPSM_EVENT_PLOGI_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); bfa_fcxp_discard(rport->fcxp); bfa_fcs_rport_send_plogiacc(rport, NULL); break; case RPSM_EVENT_FAILED: bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; case RPSM_EVENT_DELETE: case RPSM_EVENT_SCN_OFFLINE: case RPSM_EVENT_LOGO_IMP: case RPSM_EVENT_LOGO_RCVD: case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_fcxp_discard(rport->fcxp); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; default: bfa_sm_fault(rport->fcs, event); } }
static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim, enum bfa_fcs_itnim_event event) { bfa_trc(itnim->fcs, itnim->rport->pwwn); bfa_trc(itnim->fcs, event); switch (event) { case BFA_FCS_ITNIM_SM_RSP_OK: if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); else bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hal_rport_online); bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE); break; case BFA_FCS_ITNIM_SM_RSP_ERROR: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry); bfa_timer_start(itnim->fcs->bfa, &itnim->timer, bfa_fcs_itnim_timeout, itnim, BFA_FCS_RETRY_TIMEOUT); break; case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); break; case BFA_FCS_ITNIM_SM_OFFLINE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); bfa_fcxp_discard(itnim->fcxp); bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); break; case BFA_FCS_ITNIM_SM_INITIATOR: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); bfa_fcxp_discard(itnim->fcxp); bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE); break; case BFA_FCS_ITNIM_SM_DELETE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); bfa_fcxp_discard(itnim->fcxp); bfa_fcs_itnim_free(itnim); break; default: bfa_sm_fault(itnim->fcs, event); } }
static void bfa_iocfc_stats_query(struct bfa_s *bfa) { struct bfa_iocfc_s *iocfc = &bfa->iocfc; struct bfi_iocfc_stats_req_s stats_req; bfa_timer_start(bfa, &iocfc->stats_timer, bfa_iocfc_stats_timeout, bfa, BFA_IOCFC_TOV); bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_GET_STATS_REQ, bfa_lpuid(bfa)); bfa_ioc_mbox_send(&bfa->ioc, &stats_req, sizeof(struct bfi_iocfc_stats_req_s)); }
static void bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event) { bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); bfa_trc(ms->port->fcs, event); switch (event) { case MSSM_EVENT_RSP_ERROR: /* * Start timer for a delayed retry */ bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_retry); ms->port->stats.ms_retries++; bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer, bfa_fcs_port_ms_timeout, ms, BFA_FCS_RETRY_TIMEOUT); break; case MSSM_EVENT_RSP_OK: /* * since plogi is done, now invoke MS related sub-modules */ bfa_fcs_port_fdmi_online(ms); /** * if this is a Vport, go to online state. */ if (ms->port->vport) { bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online); break; } /* * For a base port we need to get the * switch's IP address. */ bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending); bfa_fcs_port_ms_send_gmal(ms, NULL); break; case MSSM_EVENT_PORT_OFFLINE: bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); bfa_fcxp_discard(ms->fcxp); break; default: bfa_sm_fault(ms->port->fcs, event); } }
static void bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) { struct bfa_fcs_rport_s *rport = rpf->rport; bfa_trc(rport->fcs, rport->pid); bfa_trc(rport->fcs, event); switch (event) { case RPFSM_EVENT_RPSC_COMP: bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN) { bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed); } else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN) { bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed); } break; case RPFSM_EVENT_RPSC_FAIL: bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); break; case RPFSM_EVENT_RPSC_ERROR: if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) { bfa_timer_start(rport->fcs->bfa, &rpf->timer, bfa_fcs_rpf_timeout, rpf, BFA_FCS_RPF_RETRY_TIMEOUT); bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry); } else { bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); } break; case RPFSM_EVENT_RPORT_OFFLINE : bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); bfa_fcxp_discard(rpf->fcxp); rpf->rpsc_retries = 0; break; default: bfa_assert(0); } }
static void bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) { struct bfa_fcs_rport_s *rport = rpf->rport; bfa_trc(rport->fcs, rport->pid); bfa_trc(rport->fcs, event); switch (event) { case RPFSM_EVENT_RPSC_COMP: bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); /* Update speed info in f/w via BFA */ if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN) bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed); else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN) bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed); break; case RPFSM_EVENT_RPSC_FAIL: /* RPSC not supported by rport */ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); break; case RPFSM_EVENT_RPSC_ERROR: /* need to retry...delayed a bit. */ if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) { bfa_timer_start(rport->fcs->bfa, &rpf->timer, bfa_fcs_rpf_timeout, rpf, BFA_FCS_RPF_RETRY_TIMEOUT); bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry); } else { bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); } break; case RPFSM_EVENT_RPORT_OFFLINE: bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); bfa_fcxp_discard(rpf->fcxp); rpf->rpsc_retries = 0; break; default: bfa_sm_fault(rport->fcs, event); } }
static void bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi, enum port_fdmi_event event) { struct bfa_fcs_port_s *port = fdmi->ms->port; bfa_trc(port->fcs, port->port_cfg.pwwn); bfa_trc(port->fcs, event); switch (event) { case FDMISM_EVENT_RSP_ERROR: /* * if max retries have not been reached, start timer for a * delayed retry */ if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba_retry); bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), &fdmi->timer, bfa_fcs_port_fdmi_timeout, fdmi, BFA_FCS_RETRY_TIMEOUT); } else { /* * set state to offline */ bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); } break; case FDMISM_EVENT_RSP_OK: /* * Initiate Register Port Attributes */ bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa); fdmi->retry_cnt = 0; bfa_fcs_port_fdmi_send_rpa(fdmi, NULL); break; case FDMISM_EVENT_PORT_OFFLINE: bfa_fcxp_discard(fdmi->fcxp); bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); break; default: bfa_sm_fault(port->fcs, event); } }
static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim, enum bfa_fcs_itnim_event event) { bfa_trc(itnim->fcs, itnim->rport->pwwn); bfa_trc(itnim->fcs, event); switch (event) { case BFA_FCS_ITNIM_SM_RSP_OK: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online); bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec); break; case BFA_FCS_ITNIM_SM_RSP_ERROR: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry); bfa_timer_start(itnim->fcs->bfa, &itnim->timer, bfa_fcs_itnim_timeout, itnim, BFA_FCS_RETRY_TIMEOUT); break; case BFA_FCS_ITNIM_SM_OFFLINE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); bfa_fcxp_discard(itnim->fcxp); bfa_fcs_rport_itnim_ack(itnim->rport); break; case BFA_FCS_ITNIM_SM_INITIATOR: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); /* * dont discard fcxp. accept will reach same state */ break; case BFA_FCS_ITNIM_SM_DELETE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); bfa_fcxp_discard(itnim->fcxp); bfa_fcs_itnim_free(itnim); break; default: bfa_assert(0); } }
/** * 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); } }
/** * Reset port statistics (FCQoS or FCoE). */ bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg) { struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); if (fcport->stats_busy) { bfa_trc(bfa, fcport->stats_busy); return BFA_STATUS_DEVBUSY; } fcport->stats_busy = BFA_TRUE; fcport->stats_cbfn = cbfn; fcport->stats_cbarg = cbarg; bfa_fcport_send_stats_clear(fcport); bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout, fcport, BFA_FCPORT_STATS_TOV); return BFA_STATUS_OK; }
bfa_status_t bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg) { struct bfa_pport_s *port = BFA_PORT_MOD(bfa); if (port->stats_busy) { bfa_trc(bfa, port->stats_busy); return (BFA_STATUS_DEVBUSY); } port->stats_busy = BFA_TRUE; port->stats_cbfn = cbfn; port->stats_cbarg = cbarg; bfa_port_qos_stats_clear(port); bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port, BFA_PORT_STATS_TOV); return (BFA_STATUS_OK); }
/** * Fetch port attributes. */ bfa_status_t bfa_pport_get_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats, bfa_cb_pport_t cbfn, void *cbarg) { struct bfa_pport_s *port = BFA_PORT_MOD(bfa); if (port->stats_busy) { bfa_trc(bfa, port->stats_busy); return (BFA_STATUS_DEVBUSY); } port->stats_busy = BFA_TRUE; port->stats_ret = stats; port->stats_cbfn = cbfn; port->stats_cbarg = cbarg; bfa_port_stats_query(port); bfa_timer_start(bfa, &port->timer, bfa_port_stats_timeout, port, BFA_PORT_STATS_TOV); return (BFA_STATUS_OK); }
/* * Rport is offline. FC-4s are offline. Awaiting BFA rport offline * callback. */ static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, enum rport_event event) { bfa_trc(rport->fcs, rport->pwwn); bfa_trc(rport->fcs, rport->pid); bfa_trc(rport->fcs, event); switch (event) { case RPSM_EVENT_HCB_OFFLINE: if (bfa_fcs_lport_is_online(rport->port) && (rport->plogi_pending)) { rport->plogi_pending = BFA_FALSE; bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); bfa_fcs_rport_send_plogiacc(rport, NULL); break; } /* * !! fall through !! */ case RPSM_EVENT_ADDRESS_CHANGE: if (!bfa_fcs_lport_is_online(rport->port)) { rport->pid = 0; bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; } if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); rport->ns_retries = 0; bfa_fcs_rport_send_nsdisc(rport, NULL); } else if (bfa_fcport_get_topology(rport->port->fcs->bfa) == BFA_PORT_TOPOLOGY_LOOP) { if (rport->scn_online) { bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline_sending); bfa_fcs_rport_send_adisc(rport, NULL); } else { bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); } } else { bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); rport->plogi_retries = 0; bfa_fcs_rport_send_plogi(rport, NULL); } break; case RPSM_EVENT_DELETE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); bfa_fcs_rport_free(rport); break; case RPSM_EVENT_SCN_ONLINE: case RPSM_EVENT_SCN_OFFLINE: case RPSM_EVENT_FAB_SCN: case RPSM_EVENT_LOGO_RCVD: case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_PLOGI_RCVD: case RPSM_EVENT_LOGO_IMP: /* * Ignore, already offline. */ break; default: bfa_sm_fault(rport->fcs, event); } }
/* * Rport is offline. FC-4s are offline. Awaiting BFA rport offline * callback to send LOGO accept. */ static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, enum rport_event event) { bfa_trc(rport->fcs, rport->pwwn); bfa_trc(rport->fcs, rport->pid); bfa_trc(rport->fcs, event); switch (event) { case RPSM_EVENT_HCB_OFFLINE: case RPSM_EVENT_ADDRESS_CHANGE: if (rport->pid && (rport->prlo == BFA_TRUE)) bfa_fcs_rport_send_prlo_acc(rport); if (rport->pid && (rport->prlo == BFA_FALSE)) bfa_fcs_rport_send_logo_acc(rport); /* * If the lport is online and if the rport is not a well * known address port, * we try to re-discover the r-port. */ if (bfa_fcs_lport_is_online(rport->port) && (!BFA_FCS_PID_IS_WKA(rport->pid))) { if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); rport->ns_retries = 0; bfa_fcs_rport_send_nsdisc(rport, NULL); } else { /* For N2N Direct Attach, try to re-login */ bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); rport->plogi_retries = 0; bfa_fcs_rport_send_plogi(rport, NULL); } } else { /* * if it is not a well known address, reset the * pid to 0. */ if (!BFA_FCS_PID_IS_WKA(rport->pid)) rport->pid = 0; bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); } break; case RPSM_EVENT_DELETE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending); if (rport->pid && (rport->prlo == BFA_TRUE)) bfa_fcs_rport_send_prlo_acc(rport); if (rport->pid && (rport->prlo == BFA_FALSE)) bfa_fcs_rport_send_logo_acc(rport); break; case RPSM_EVENT_LOGO_IMP: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); break; case RPSM_EVENT_SCN_ONLINE: case RPSM_EVENT_SCN_OFFLINE: case RPSM_EVENT_LOGO_RCVD: case RPSM_EVENT_PRLO_RCVD: /* * Ignore - already processing a LOGO. */ break; default: bfa_sm_fault(rport->fcs, event); } }
/* * PLOGI is being sent. */ static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport, enum rport_event event) { bfa_trc(rport->fcs, rport->pwwn); bfa_trc(rport->fcs, rport->pid); bfa_trc(rport->fcs, event); switch (event) { case RPSM_EVENT_FCXP_SENT: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online); bfa_fcs_rport_fcs_online_action(rport); break; case RPSM_EVENT_DELETE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_fcs_rport_free(rport); break; case RPSM_EVENT_PLOGI_RCVD: case RPSM_EVENT_PLOGI_COMP: case RPSM_EVENT_FAB_SCN: /* * Ignore, SCN is possibly online notification. */ break; case RPSM_EVENT_SCN_OFFLINE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; case RPSM_EVENT_ADDRESS_CHANGE: bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); rport->ns_retries = 0; bfa_fcs_rport_send_nsdisc(rport, NULL); break; case RPSM_EVENT_LOGO_IMP: rport->pid = 0; bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; case RPSM_EVENT_HCB_OFFLINE: /* * Ignore BFA callback, on a PLOGI receive we call bfa offline. */ break; default: bfa_sm_fault(rport->fcs, event); } }
/* * PLOGI is sent. */ static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport, enum rport_event event) { bfa_trc(rport->fcs, rport->pwwn); bfa_trc(rport->fcs, rport->pid); bfa_trc(rport->fcs, event); switch (event) { case RPSM_EVENT_TIMEOUT: bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); bfa_fcs_rport_send_plogi(rport, NULL); break; case RPSM_EVENT_DELETE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); bfa_timer_stop(&rport->timer); bfa_fcs_rport_free(rport); break; case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_LOGO_RCVD: break; case RPSM_EVENT_PLOGI_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); bfa_timer_stop(&rport->timer); bfa_fcs_rport_send_plogiacc(rport, NULL); break; case RPSM_EVENT_SCN_OFFLINE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_timer_stop(&rport->timer); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; case RPSM_EVENT_ADDRESS_CHANGE: case RPSM_EVENT_FAB_SCN: bfa_timer_stop(&rport->timer); WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) != BFA_PORT_TOPOLOGY_LOOP)); bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); rport->ns_retries = 0; bfa_fcs_rport_send_nsdisc(rport, NULL); break; case RPSM_EVENT_LOGO_IMP: rport->pid = 0; bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_timer_stop(&rport->timer); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; case RPSM_EVENT_PLOGI_COMP: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online); bfa_timer_stop(&rport->timer); bfa_fcs_rport_fcs_online_action(rport); break; default: bfa_sm_fault(rport->fcs, event); } }
/* * PLOGI is sent. */ static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event) { bfa_trc(rport->fcs, rport->pwwn); bfa_trc(rport->fcs, rport->pid); bfa_trc(rport->fcs, event); switch (event) { case RPSM_EVENT_ACCEPTED: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online); rport->plogi_retries = 0; bfa_fcs_rport_fcs_online_action(rport); break; case RPSM_EVENT_LOGO_RCVD: bfa_fcs_rport_send_logo_acc(rport); /* * !! fall through !! */ case RPSM_EVENT_PRLO_RCVD: if (rport->prlo == BFA_TRUE) bfa_fcs_rport_send_prlo_acc(rport); bfa_fcxp_discard(rport->fcxp); /* * !! fall through !! */ case RPSM_EVENT_FAILED: if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) { rport->plogi_retries++; bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, BFA_FCS_RETRY_TIMEOUT); } else { bfa_stats(rport->port, rport_del_max_plogi_retry); rport->old_pid = rport->pid; rport->pid = 0; bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); } break; case RPSM_EVENT_SCN_ONLINE: break; case RPSM_EVENT_SCN_OFFLINE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_fcxp_discard(rport->fcxp); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; case RPSM_EVENT_PLOGI_RETRY: rport->plogi_retries = 0; bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, (FC_RA_TOV * 1000)); break; case RPSM_EVENT_LOGO_IMP: rport->pid = 0; bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); bfa_fcxp_discard(rport->fcxp); bfa_timer_start(rport->fcs->bfa, &rport->timer, bfa_fcs_rport_timeout, rport, bfa_fcs_rport_del_timeout); break; case RPSM_EVENT_ADDRESS_CHANGE: case RPSM_EVENT_FAB_SCN: bfa_fcxp_discard(rport->fcxp); WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) != BFA_PORT_TOPOLOGY_LOOP)); bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); rport->ns_retries = 0; bfa_fcs_rport_send_nsdisc(rport, NULL); break; case RPSM_EVENT_PLOGI_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); bfa_fcxp_discard(rport->fcxp); bfa_fcs_rport_send_plogiacc(rport, NULL); break; case RPSM_EVENT_DELETE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); bfa_fcxp_discard(rport->fcxp); bfa_fcs_rport_free(rport); break; case RPSM_EVENT_PLOGI_COMP: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online); bfa_fcxp_discard(rport->fcxp); bfa_fcs_rport_fcs_online_action(rport); break; default: bfa_sm_fault(rport->fcs, event); } }