aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/bfa/rport.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/bfa/rport.c')
-rw-r--r--drivers/scsi/bfa/rport.c88
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);
+}