diff options
Diffstat (limited to 'drivers/scsi/bfa/rport.c')
-rw-r--r-- | drivers/scsi/bfa/rport.c | 88 |
1 files changed, 79 insertions, 9 deletions
diff --git a/drivers/scsi/bfa/rport.c b/drivers/scsi/bfa/rport.c index 7b096f2e383..9b4c2c9a644 100644 --- a/drivers/scsi/bfa/rport.c +++ b/drivers/scsi/bfa/rport.c @@ -36,8 +36,6 @@ BFA_TRC_FILE(FCS, RPORT); -#define BFA_FCS_RPORT_MAX_RETRIES (5) - /* In millisecs */ static u32 bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000; @@ -95,6 +93,7 @@ static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, u8 reason_code_expl); static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs, u16 len); +static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport); /** * fcs_rport_sm FCS rport state machine events */ @@ -115,7 +114,8 @@ enum rport_event { RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */ RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */ RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */ - RPSM_EVENT_ADDRESS_DISC = 16 /* Need to Discover rport's PID */ + RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */ + RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */ }; static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, @@ -356,8 +356,8 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport, */ case RPSM_EVENT_TIMEOUT: - rport->plogi_retries++; if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) { + rport->plogi_retries++; bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); bfa_fcs_rport_send_plogi(rport, NULL); } else { @@ -375,6 +375,7 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport, bfa_fcs_rport_free(rport); break; + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_LOGO_RCVD: break; @@ -430,6 +431,13 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event) 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 !! @@ -504,6 +512,9 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, bfa_fcs_rport_online_action(rport); break; + case RPSM_EVENT_PRLO_RCVD: + break; + case RPSM_EVENT_LOGO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); bfa_rport_offline(rport->bfa_rport); @@ -582,6 +593,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event) break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcs_rport_offline_action(rport); break; @@ -624,6 +636,7 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_fcs_rport_offline_action(rport); @@ -690,6 +703,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event) break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcxp_discard(rport->fcxp); bfa_fcs_rport_offline_action(rport); @@ -740,6 +754,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_fcs_rport_offline_action(rport); @@ -811,6 +826,7 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event) break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcxp_discard(rport->fcxp); bfa_fcs_rport_offline_action(rport); @@ -843,6 +859,7 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_ADDRESS_CHANGE: break; @@ -894,6 +911,7 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_SCN: case RPSM_EVENT_LOGO_IMP: case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_ADDRESS_CHANGE: /** * rport is already going offline. @@ -953,6 +971,7 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_SCN: case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: /** * Ignore, already offline. */ @@ -978,8 +997,11 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, switch (event) { case RPSM_EVENT_HCB_OFFLINE: case RPSM_EVENT_ADDRESS_CHANGE: - if (rport->pid) + 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. @@ -1013,6 +1035,7 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: /** * Ignore - already processing a LOGO. */ @@ -1042,6 +1065,7 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_ADDRESS_CHANGE: break; @@ -1075,6 +1099,7 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: 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); @@ -1123,6 +1148,7 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event) break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_LOGO_IMP: break; @@ -1174,6 +1200,7 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_SCN: case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_PLOGI_SEND: break; @@ -1250,6 +1277,10 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport, bfa_fcs_rport_send_logo_acc(rport); break; + case RPSM_EVENT_PRLO_RCVD: + bfa_fcs_rport_send_prlo_acc(rport); + break; + case RPSM_EVENT_PLOGI_COMP: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); bfa_timer_stop(&rport->timer); @@ -1322,6 +1353,10 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, bfa_fcs_rport_del_timeout); break; + case RPSM_EVENT_PRLO_RCVD: + bfa_fcs_rport_send_prlo_acc(rport); + break; + case RPSM_EVENT_SCN: /** * ignore, wait for NS query response @@ -1378,7 +1413,7 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response, - (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV); rport->stats.plogis++; bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); @@ -1519,7 +1554,7 @@ bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response, - rport, FC_MAX_PDUSZ, FC_RA_TOV); + rport, FC_MAX_PDUSZ, FC_ELS_TOV); rport->stats.adisc_sent++; bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); @@ -1580,7 +1615,7 @@ bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response, - (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV); bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); } @@ -1692,7 +1727,7 @@ bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ, - FC_ED_TOV); + FC_ELS_TOV); rport->stats.logos++; bfa_fcxp_discard(rport->fcxp); @@ -2184,6 +2219,7 @@ bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs) rport->reply_oxid = fchs->ox_id; bfa_trc(rport->fcs, rport->reply_oxid); + rport->prlo = BFA_FALSE; rport->stats.logo_rcvd++; bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD); } @@ -2553,6 +2589,30 @@ bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, } } +/* Send best case acc to prlo */ +static void +bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport) +{ + struct bfa_fcs_port_s *port = rport->port; + struct fchs_s fchs; + struct bfa_fcxp_s *fcxp; + int len; + + bfa_trc(rport->fcs, rport->pid); + + fcxp = bfa_fcs_fcxp_alloc(port->fcs); + if (!fcxp) + return; + + len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), + rport->pid, bfa_fcs_port_get_fcid(port), + rport->reply_oxid, 0); + + bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, + port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, + NULL, NULL, FC_MAX_PDUSZ, 0); +} + /* * Send a LS reject */ @@ -2604,3 +2664,13 @@ bfa_fcs_rport_set_del_timeout(u8 rport_tmo) if (rport_tmo > 0) bfa_fcs_rport_del_timeout = rport_tmo * 1000; } + +void +bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id) +{ + bfa_trc(rport->fcs, rport->pid); + + rport->prlo = BFA_TRUE; + rport->reply_oxid = ox_id; + bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD); +} |