aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2011-06-13 18:53:04 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-06-29 16:52:21 -0400
commitbe540a991e2097c313d7304e0daaf89d68011bb9 (patch)
treea44685889c9989546ffac1ee7ad1da7dd641c20c /drivers/scsi/bfa
parent8b070b4a022f86dd5098308e36426ce29b6b8960 (diff)
[SCSI] bfa: FC credit recovery and misc bug fixes.
- Introduce FC credit recovery. - Added module parameter to enable/disable credit recovery. Bug Fixes: - Removed check for ignoring plogi from initiator in switched fabric mode. - The ABTS for PLOGI is going out few millisecs earlier due to FW timer calibration (around 300 miilisecs earlier). So there is a window if an accept comes during this time HBA would have initiated an ABORT. - Added 1 to FC_ELS_TOV for compensating for FW timer. Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r--drivers/scsi/bfa/bfa_defs_svc.h6
-rw-r--r--drivers/scsi/bfa/bfa_fc.h2
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.c18
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.h6
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c60
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h5
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c8
-rw-r--r--drivers/scsi/bfa/bfa_fcs_rport.c38
-rw-r--r--drivers/scsi/bfa/bfa_svc.c25
-rw-r--r--drivers/scsi/bfa/bfa_svc.h8
-rw-r--r--drivers/scsi/bfa/bfad.c5
-rw-r--r--drivers/scsi/bfa/bfad_drv.h1
-rw-r--r--drivers/scsi/bfa/bfi_ms.h7
13 files changed, 129 insertions, 60 deletions
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index bcc919c4a503..6934b2d8d857 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -746,6 +746,8 @@ struct bfa_port_cfg_s {
746 u8 tx_bbcredit; /* transmit buffer credits */ 746 u8 tx_bbcredit; /* transmit buffer credits */
747 u8 ratelimit; /* ratelimit enabled or not */ 747 u8 ratelimit; /* ratelimit enabled or not */
748 u8 trl_def_speed; /* ratelimit default speed */ 748 u8 trl_def_speed; /* ratelimit default speed */
749 u8 bb_scn;
750 u8 rsvd[3];
749 u16 path_tov; /* device path timeout */ 751 u16 path_tov; /* device path timeout */
750 u16 q_depth; /* SCSI Queue depth */ 752 u16 q_depth; /* SCSI Queue depth */
751}; 753};
@@ -782,6 +784,7 @@ struct bfa_port_attr_s {
782 bfa_boolean_t beacon; /* current beacon status */ 784 bfa_boolean_t beacon; /* current beacon status */
783 bfa_boolean_t link_e2e_beacon; /* link beacon is on */ 785 bfa_boolean_t link_e2e_beacon; /* link beacon is on */
784 bfa_boolean_t plog_enabled; /* portlog is enabled */ 786 bfa_boolean_t plog_enabled; /* portlog is enabled */
787 bfa_boolean_t bbsc_op_status; /* fc credit recovery oper state */
785 788
786 /* 789 /*
787 * Dynamic field - info from FCS 790 * Dynamic field - info from FCS
@@ -1018,6 +1021,9 @@ struct bfa_port_fc_stats_s {
1018 u64 bad_os_count; /* Invalid ordered sets */ 1021 u64 bad_os_count; /* Invalid ordered sets */
1019 u64 err_enc_out; /* Encoding err nonframe_8b10b */ 1022 u64 err_enc_out; /* Encoding err nonframe_8b10b */
1020 u64 err_enc; /* Encoding err frame_8b10b */ 1023 u64 err_enc; /* Encoding err frame_8b10b */
1024 u64 bbsc_frames_lost; /* Credit Recovery-Frames Lost */
1025 u64 bbsc_credits_lost; /* Credit Recovery-Credits Lost */
1026 u64 bbsc_link_resets; /* Credit Recovery-Link Resets */
1021}; 1027};
1022 1028
1023/* 1029/*
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index 7bc020855be0..8d0b88f67a38 100644
--- a/drivers/scsi/bfa/bfa_fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -1021,7 +1021,7 @@ struct fc_symname_s {
1021#define FC_ED_TOV 2 1021#define FC_ED_TOV 2
1022#define FC_REC_TOV (FC_ED_TOV + 1) 1022#define FC_REC_TOV (FC_ED_TOV + 1)
1023#define FC_RA_TOV 10 1023#define FC_RA_TOV 10
1024#define FC_ELS_TOV (2 * FC_RA_TOV) 1024#define FC_ELS_TOV ((2 * FC_RA_TOV) + 1)
1025#define FC_FCCT_TOV (3 * FC_RA_TOV) 1025#define FC_FCCT_TOV (3 * FC_RA_TOV)
1026 1026
1027/* 1027/*
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index b7e253451654..08fba370cf4f 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -94,7 +94,6 @@ fcbuild_init(void)
94 */ 94 */
95 plogi_tmpl.csp.verhi = FC_PH_VER_PH_3; 95 plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
96 plogi_tmpl.csp.verlo = FC_PH_VER_4_3; 96 plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
97 plogi_tmpl.csp.bbcred = cpu_to_be16(0x0004);
98 plogi_tmpl.csp.ciro = 0x1; 97 plogi_tmpl.csp.ciro = 0x1;
99 plogi_tmpl.csp.cisc = 0x0; 98 plogi_tmpl.csp.cisc = 0x0;
100 plogi_tmpl.csp.altbbcred = 0x0; 99 plogi_tmpl.csp.altbbcred = 0x0;
@@ -207,7 +206,7 @@ fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
207static u16 206static u16
208fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 207fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
209 __be16 ox_id, wwn_t port_name, wwn_t node_name, 208 __be16 ox_id, wwn_t port_name, wwn_t node_name,
210 u16 pdu_size, u8 els_code) 209 u16 pdu_size, u16 bb_cr, u8 els_code)
211{ 210{
212 struct fc_logi_s *plogi = (struct fc_logi_s *) (pld); 211 struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
213 212
@@ -220,6 +219,7 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
220 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 219 fc_els_rsp_build(fchs, d_id, s_id, ox_id);
221 220
222 plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size); 221 plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
222 plogi->csp.bbcred = cpu_to_be16(bb_cr);
223 223
224 memcpy(&plogi->port_name, &port_name, sizeof(wwn_t)); 224 memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
225 memcpy(&plogi->node_name, &node_name, sizeof(wwn_t)); 225 memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
@@ -268,15 +268,17 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
268u16 268u16
269fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, 269fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
270 __be16 ox_id, wwn_t port_name, wwn_t node_name, 270 __be16 ox_id, wwn_t port_name, wwn_t node_name,
271 u16 pdu_size, u16 local_bb_credits) 271 u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
272{ 272{
273 u32 d_id = 0; 273 u32 d_id = 0;
274 u16 bbscn_rxsz = (bb_scn << 12) | pdu_size;
274 275
275 memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); 276 memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
276 fc_els_rsp_build(fchs, d_id, s_id, ox_id); 277 fc_els_rsp_build(fchs, d_id, s_id, ox_id);
277 278
278 flogi->els_cmd.els_code = FC_ELS_ACC; 279 flogi->els_cmd.els_code = FC_ELS_ACC;
279 flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size); 280 flogi->class3.rxsz = cpu_to_be16(pdu_size);
281 flogi->csp.rxsz = cpu_to_be16(bbscn_rxsz); /* bb_scn/rxsz */
280 flogi->port_name = port_name; 282 flogi->port_name = port_name;
281 flogi->node_name = node_name; 283 flogi->node_name = node_name;
282 284
@@ -306,19 +308,19 @@ fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
306u16 308u16
307fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 309fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
308 u16 ox_id, wwn_t port_name, wwn_t node_name, 310 u16 ox_id, wwn_t port_name, wwn_t node_name,
309 u16 pdu_size) 311 u16 pdu_size, u16 bb_cr)
310{ 312{
311 return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, 313 return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
312 node_name, pdu_size, FC_ELS_PLOGI); 314 node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
313} 315}
314 316
315u16 317u16
316fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, 318fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
317 u16 ox_id, wwn_t port_name, wwn_t node_name, 319 u16 ox_id, wwn_t port_name, wwn_t node_name,
318 u16 pdu_size) 320 u16 pdu_size, u16 bb_cr)
319{ 321{
320 return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, 322 return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
321 node_name, pdu_size, FC_ELS_ACC); 323 node_name, pdu_size, bb_cr, FC_ELS_ACC);
322} 324}
323 325
324enum fc_parse_status 326enum fc_parse_status
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
index 24c4cfb30098..9ba24c724f4c 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.h
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -147,11 +147,11 @@ u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
147 u32 s_id, __be16 ox_id, 147 u32 s_id, __be16 ox_id,
148 wwn_t port_name, wwn_t node_name, 148 wwn_t port_name, wwn_t node_name,
149 u16 pdu_size, 149 u16 pdu_size,
150 u16 local_bb_credits); 150 u16 local_bb_credits, u8 bb_scn);
151 151
152u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, 152u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
153 u32 s_id, u16 ox_id, wwn_t port_name, 153 u32 s_id, u16 ox_id, wwn_t port_name,
154 wwn_t node_name, u16 pdu_size); 154 wwn_t node_name, u16 pdu_size, u16 bb_cr);
155 155
156enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs); 156enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
157 157
@@ -189,7 +189,7 @@ u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
189u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, 189u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
190 u32 s_id, u16 ox_id, 190 u32 s_id, u16 ox_id,
191 wwn_t port_name, wwn_t node_name, 191 wwn_t port_name, wwn_t node_name,
192 u16 pdu_size); 192 u16 pdu_size, u16 bb_cr);
193 193
194u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, 194u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
195 u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name, 195 u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name,
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index eb42e74ed423..6c8a27e78974 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -196,6 +196,9 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
196 u32 rsp_len, 196 u32 rsp_len,
197 u32 resid_len, 197 u32 resid_len,
198 struct fchs_s *rspfchs); 198 struct fchs_s *rspfchs);
199static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric);
200static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled(
201 struct bfa_fcs_fabric_s *fabric);
199 202
200static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, 203static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
201 enum bfa_fcs_fabric_event event); 204 enum bfa_fcs_fabric_event event);
@@ -322,7 +325,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
322 case BFA_FCS_FABRIC_SM_CONT_OP: 325 case BFA_FCS_FABRIC_SM_CONT_OP:
323 326
324 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, 327 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
325 fabric->bb_credit); 328 fabric->bb_credit,
329 bfa_fcs_fabric_oper_bbscn(fabric));
326 fabric->fab_type = BFA_FCS_FABRIC_SWITCHED; 330 fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
327 331
328 if (fabric->auth_reqd && fabric->is_auth) { 332 if (fabric->auth_reqd && fabric->is_auth) {
@@ -350,7 +354,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
350 case BFA_FCS_FABRIC_SM_NO_FABRIC: 354 case BFA_FCS_FABRIC_SM_NO_FABRIC:
351 fabric->fab_type = BFA_FCS_FABRIC_N2N; 355 fabric->fab_type = BFA_FCS_FABRIC_N2N;
352 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, 356 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
353 fabric->bb_credit); 357 fabric->bb_credit,
358 bfa_fcs_fabric_oper_bbscn(fabric));
354 bfa_fcs_fabric_notify_online(fabric); 359 bfa_fcs_fabric_notify_online(fabric);
355 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric); 360 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
356 break; 361 break;
@@ -518,7 +523,8 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
518 case BFA_FCS_FABRIC_SM_NO_FABRIC: 523 case BFA_FCS_FABRIC_SM_NO_FABRIC:
519 bfa_trc(fabric->fcs, fabric->bb_credit); 524 bfa_trc(fabric->fcs, fabric->bb_credit);
520 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, 525 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
521 fabric->bb_credit); 526 fabric->bb_credit,
527 bfa_fcs_fabric_oper_bbscn(fabric));
522 break; 528 break;
523 529
524 default: 530 default:
@@ -764,6 +770,10 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
764 770
765 case BFA_STATUS_FABRIC_RJT: 771 case BFA_STATUS_FABRIC_RJT:
766 fabric->stats.flogi_rejects++; 772 fabric->stats.flogi_rejects++;
773 if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR &&
774 fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO)
775 fabric->fcs->bbscn_flogi_rjt = BFA_TRUE;
776
767 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); 777 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
768 return; 778 return;
769 779
@@ -808,13 +818,17 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
808{ 818{
809 struct bfa_s *bfa = fabric->fcs->bfa; 819 struct bfa_s *bfa = fabric->fcs->bfa;
810 struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg; 820 struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
811 u8 alpa = 0; 821 u8 alpa = 0, bb_scn = 0;
812 822
813 if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) 823 if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
814 alpa = bfa_fcport_get_myalpa(bfa); 824 alpa = bfa_fcport_get_myalpa(bfa);
815 825
826 if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
827 (!fabric->fcs->bbscn_flogi_rjt))
828 bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
829
816 bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa), 830 bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
817 pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd); 831 pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn);
818 832
819 fabric->stats.flogi_sent++; 833 fabric->stats.flogi_sent++;
820} 834}
@@ -873,6 +887,37 @@ bfa_fcs_fabric_delay(void *cbarg)
873} 887}
874 888
875/* 889/*
890 * Computes operating BB_SCN value
891 */
892static u8
893bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric)
894{
895 u8 pr_bbscn = fabric->lps->pr_bbscn;
896
897 if (!(fabric->fcs->bbscn_enabled && pr_bbscn))
898 return 0;
899
900 /* return max of local/remote bb_scn values */
901 return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ?
902 pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN);
903}
904
905/*
906 * Check if BB_SCN can be enabled.
907 */
908static bfa_boolean_t
909bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric)
910{
911 if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) &&
912 fabric->fcs->bbscn_enabled &&
913 !bfa_fcport_is_qos_enabled(fabric->fcs->bfa) &&
914 !bfa_fcport_is_trunk_enabled(fabric->fcs->bfa))
915 return BFA_TRUE;
916 else
917 return BFA_FALSE;
918}
919
920/*
876 * Delete all vports and wait for vport delete completions. 921 * Delete all vports and wait for vport delete completions.
877 */ 922 */
878static void 923static void
@@ -989,6 +1034,7 @@ void
989bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric) 1034bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
990{ 1035{
991 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); 1036 bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
1037 fabric->fcs->bbscn_flogi_rjt = BFA_FALSE;
992 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN); 1038 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
993} 1039}
994 1040
@@ -1192,6 +1238,7 @@ bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
1192 } 1238 }
1193 1239
1194 fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred); 1240 fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
1241 fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12);
1195 bport->port_topo.pn2n.rem_port_wwn = flogi->port_name; 1242 bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
1196 bport->port_topo.pn2n.reply_oxid = fchs->ox_id; 1243 bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
1197 1244
@@ -1224,7 +1271,8 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
1224 n2n_port->reply_oxid, pcfg->pwwn, 1271 n2n_port->reply_oxid, pcfg->pwwn,
1225 pcfg->nwwn, 1272 pcfg->nwwn,
1226 bfa_fcport_get_maxfrsize(bfa), 1273 bfa_fcport_get_maxfrsize(bfa),
1227 bfa_fcport_get_rx_bbcredit(bfa)); 1274 bfa_fcport_get_rx_bbcredit(bfa),
1275 bfa_fcs_fabric_oper_bbscn(fabric));
1228 1276
1229 bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag, 1277 bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
1230 BFA_FALSE, FC_CLASS_3, 1278 BFA_FALSE, FC_CLASS_3,
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index a9942b46b508..4cfd2e949ce2 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -254,6 +254,9 @@ struct bfa_fcs_fabric_s;
254#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48 254#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48
255#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16 255#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16
256 256
257/* bb_scn value in 2^bb_scn */
258#define BFA_FCS_PORT_DEF_BB_SCN 3
259
257/* 260/*
258 * Get FC port ID for a logical port. 261 * Get FC port ID for a logical port.
259 */ 262 */
@@ -650,6 +653,8 @@ struct bfa_fcs_s {
650 struct bfa_trc_mod_s *trcmod; /* tracing module */ 653 struct bfa_trc_mod_s *trcmod; /* tracing module */
651 bfa_boolean_t vf_enabled; /* VF mode is enabled */ 654 bfa_boolean_t vf_enabled; /* VF mode is enabled */
652 bfa_boolean_t fdmi_enabled; /* FDMI is enabled */ 655 bfa_boolean_t fdmi_enabled; /* FDMI is enabled */
656 bfa_boolean_t bbscn_enabled; /* Driver Config Parameter */
657 bfa_boolean_t bbscn_flogi_rjt;/* FLOGI reject due to BB_SCN */
653 bfa_boolean_t min_cfg; /* min cfg enabled/disabled */ 658 bfa_boolean_t min_cfg; /* min cfg enabled/disabled */
654 u16 port_vfid; /* port default VF ID */ 659 u16 port_vfid; /* port default VF ID */
655 struct bfa_fcs_driver_info_s driver_info; 660 struct bfa_fcs_driver_info_s driver_info;
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index a0c6f960b992..479ccbe901b5 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -2892,7 +2892,8 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2892 bfa_hton3b(FC_MGMT_SERVER), 2892 bfa_hton3b(FC_MGMT_SERVER),
2893 bfa_fcs_lport_get_fcid(port), 0, 2893 bfa_fcs_lport_get_fcid(port), 0,
2894 port->port_cfg.pwwn, port->port_cfg.nwwn, 2894 port->port_cfg.pwwn, port->port_cfg.nwwn,
2895 bfa_fcport_get_maxfrsize(port->fcs->bfa)); 2895 bfa_fcport_get_maxfrsize(port->fcs->bfa),
2896 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
2896 2897
2897 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 2898 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2898 FC_CLASS_3, len, &fchs, 2899 FC_CLASS_3, len, &fchs,
@@ -3636,7 +3637,7 @@ bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3636 3637
3637 bfa_trc(port->fcs, port->pid); 3638 bfa_trc(port->fcs, port->pid);
3638 3639
3639fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 3640 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3640 if (!fcxp) { 3641 if (!fcxp) {
3641 port->stats.ns_plogi_alloc_wait++; 3642 port->stats.ns_plogi_alloc_wait++;
3642 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, 3643 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
@@ -3649,7 +3650,8 @@ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3649 bfa_hton3b(FC_NAME_SERVER), 3650 bfa_hton3b(FC_NAME_SERVER),
3650 bfa_fcs_lport_get_fcid(port), 0, 3651 bfa_fcs_lport_get_fcid(port), 0,
3651 port->port_cfg.pwwn, port->port_cfg.nwwn, 3652 port->port_cfg.pwwn, port->port_cfg.nwwn,
3652 bfa_fcport_get_maxfrsize(port->fcs->bfa)); 3653 bfa_fcport_get_maxfrsize(port->fcs->bfa),
3654 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
3653 3655
3654 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 3656 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3655 FC_CLASS_3, len, &fchs, 3657 FC_CLASS_3, len, &fchs,
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index caaee6f06937..2ec5719b654d 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -1356,7 +1356,8 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1356 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, 1356 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1357 bfa_fcs_lport_get_fcid(port), 0, 1357 bfa_fcs_lport_get_fcid(port), 0,
1358 port->port_cfg.pwwn, port->port_cfg.nwwn, 1358 port->port_cfg.pwwn, port->port_cfg.nwwn,
1359 bfa_fcport_get_maxfrsize(port->fcs->bfa)); 1359 bfa_fcport_get_maxfrsize(port->fcs->bfa),
1360 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
1360 1361
1361 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1362 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1362 FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response, 1363 FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
@@ -1476,7 +1477,8 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1476 rport->pid, bfa_fcs_lport_get_fcid(port), 1477 rport->pid, bfa_fcs_lport_get_fcid(port),
1477 rport->reply_oxid, port->port_cfg.pwwn, 1478 rport->reply_oxid, port->port_cfg.pwwn,
1478 port->port_cfg.nwwn, 1479 port->port_cfg.nwwn,
1479 bfa_fcport_get_maxfrsize(port->fcs->bfa)); 1480 bfa_fcport_get_maxfrsize(port->fcs->bfa),
1481 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
1480 1482
1481 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1483 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1482 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); 1484 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
@@ -2120,7 +2122,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
2120 2122
2121 port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred); 2123 port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
2122 bfa_fcport_set_tx_bbcredit(port->fcs->bfa, 2124 bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
2123 port->fabric->bb_credit); 2125 port->fabric->bb_credit, 0);
2124 } 2126 }
2125 2127
2126} 2128}
@@ -2233,22 +2235,6 @@ bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
2233 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD); 2235 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2234} 2236}
2235 2237
2236static int
2237wwn_compare(wwn_t wwn1, wwn_t wwn2)
2238{
2239 u8 *b1 = (u8 *) &wwn1;
2240 u8 *b2 = (u8 *) &wwn2;
2241 int i;
2242
2243 for (i = 0; i < sizeof(wwn_t); i++) {
2244 if (b1[i] < b2[i])
2245 return -1;
2246 if (b1[i] > b2[i])
2247 return 1;
2248 }
2249 return 0;
2250}
2251
2252/* 2238/*
2253 * Called by bport/vport to handle PLOGI received from an existing 2239 * Called by bport/vport to handle PLOGI received from an existing
2254 * remote port. 2240 * remote port.
@@ -2266,20 +2252,6 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2266 rport->reply_oxid = rx_fchs->ox_id; 2252 rport->reply_oxid = rx_fchs->ox_id;
2267 bfa_trc(rport->fcs, rport->reply_oxid); 2253 bfa_trc(rport->fcs, rport->reply_oxid);
2268 2254
2269 /*
2270 * In Switched fabric topology,
2271 * PLOGI to each other. If our pwwn is smaller, ignore it,
2272 * if it is not a well known address.
2273 * If the link topology is N2N,
2274 * this Plogi should be accepted.
2275 */
2276 if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) &&
2277 (bfa_fcs_fabric_is_switched(rport->port->fabric)) &&
2278 (!BFA_FCS_PID_IS_WKA(rport->pid))) {
2279 bfa_trc(rport->fcs, rport->pid);
2280 return;
2281 }
2282
2283 rport->stats.plogi_rcvd++; 2255 rport->stats.plogi_rcvd++;
2284 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD); 2256 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2285} 2257}
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 46e8cdd31db9..5373e5ddd4ad 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -1257,6 +1257,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
1257 break; 1257 break;
1258 1258
1259 case BFA_LPS_SM_OFFLINE: 1259 case BFA_LPS_SM_OFFLINE:
1260 case BFA_LPS_SM_DELETE:
1260 bfa_sm_set_state(lps, bfa_lps_sm_init); 1261 bfa_sm_set_state(lps, bfa_lps_sm_init);
1261 break; 1262 break;
1262 1263
@@ -1285,6 +1286,7 @@ bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1285 break; 1286 break;
1286 1287
1287 case BFA_LPS_SM_OFFLINE: 1288 case BFA_LPS_SM_OFFLINE:
1289 case BFA_LPS_SM_DELETE:
1288 bfa_sm_set_state(lps, bfa_lps_sm_init); 1290 bfa_sm_set_state(lps, bfa_lps_sm_init);
1289 bfa_reqq_wcancel(&lps->wqe); 1291 bfa_reqq_wcancel(&lps->wqe);
1290 break; 1292 break;
@@ -1409,6 +1411,7 @@ bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1409 break; 1411 break;
1410 1412
1411 case BFA_LPS_SM_OFFLINE: 1413 case BFA_LPS_SM_OFFLINE:
1414 case BFA_LPS_SM_DELETE:
1412 bfa_sm_set_state(lps, bfa_lps_sm_init); 1415 bfa_sm_set_state(lps, bfa_lps_sm_init);
1413 break; 1416 break;
1414 1417
@@ -1433,6 +1436,7 @@ bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1433 break; 1436 break;
1434 1437
1435 case BFA_LPS_SM_OFFLINE: 1438 case BFA_LPS_SM_OFFLINE:
1439 case BFA_LPS_SM_DELETE:
1436 bfa_sm_set_state(lps, bfa_lps_sm_init); 1440 bfa_sm_set_state(lps, bfa_lps_sm_init);
1437 bfa_reqq_wcancel(&lps->wqe); 1441 bfa_reqq_wcancel(&lps->wqe);
1438 break; 1442 break;
@@ -1551,6 +1555,7 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
1551 lps->lp_mac = rsp->lp_mac; 1555 lps->lp_mac = rsp->lp_mac;
1552 lps->brcd_switch = rsp->brcd_switch; 1556 lps->brcd_switch = rsp->brcd_switch;
1553 lps->fcf_mac = rsp->fcf_mac; 1557 lps->fcf_mac = rsp->fcf_mac;
1558 lps->pr_bbscn = rsp->bb_scn;
1554 1559
1555 break; 1560 break;
1556 1561
@@ -1647,6 +1652,7 @@ bfa_lps_send_login(struct bfa_lps_s *lps)
1647 m->nwwn = lps->nwwn; 1652 m->nwwn = lps->nwwn;
1648 m->fdisc = lps->fdisc; 1653 m->fdisc = lps->fdisc;
1649 m->auth_en = lps->auth_en; 1654 m->auth_en = lps->auth_en;
1655 m->bb_scn = lps->bb_scn;
1650 1656
1651 bfa_reqq_produce(lps->bfa, lps->reqq); 1657 bfa_reqq_produce(lps->bfa, lps->reqq);
1652} 1658}
@@ -1838,7 +1844,7 @@ bfa_lps_delete(struct bfa_lps_s *lps)
1838 */ 1844 */
1839void 1845void
1840bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz, 1846bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
1841 wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en) 1847 wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en, uint8_t bb_scn)
1842{ 1848{
1843 lps->uarg = uarg; 1849 lps->uarg = uarg;
1844 lps->alpa = alpa; 1850 lps->alpa = alpa;
@@ -1847,6 +1853,7 @@ bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
1847 lps->nwwn = nwwn; 1853 lps->nwwn = nwwn;
1848 lps->fdisc = BFA_FALSE; 1854 lps->fdisc = BFA_FALSE;
1849 lps->auth_en = auth_en; 1855 lps->auth_en = auth_en;
1856 lps->bb_scn = bb_scn;
1850 bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN); 1857 bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1851} 1858}
1852 1859
@@ -2900,6 +2907,7 @@ bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
2900{ 2907{
2901 fcport->speed = BFA_PORT_SPEED_UNKNOWN; 2908 fcport->speed = BFA_PORT_SPEED_UNKNOWN;
2902 fcport->topology = BFA_PORT_TOPOLOGY_NONE; 2909 fcport->topology = BFA_PORT_TOPOLOGY_NONE;
2910 fcport->bbsc_op_state = BFA_FALSE;
2903} 2911}
2904 2912
2905/* 2913/*
@@ -3010,6 +3018,7 @@ bfa_fcport_send_txcredit(void *port_cbarg)
3010 bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ, 3018 bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
3011 bfa_lpuid(fcport->bfa)); 3019 bfa_lpuid(fcport->bfa));
3012 m->tx_bbcredit = cpu_to_be16((u16)fcport->cfg.tx_bbcredit); 3020 m->tx_bbcredit = cpu_to_be16((u16)fcport->cfg.tx_bbcredit);
3021 m->bb_scn = fcport->cfg.bb_scn;
3013 3022
3014 /* 3023 /*
3015 * queue I/O message to firmware 3024 * queue I/O message to firmware
@@ -3626,11 +3635,14 @@ bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
3626} 3635}
3627 3636
3628void 3637void
3629bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit) 3638bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn)
3630{ 3639{
3631 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); 3640 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3632 3641
3633 fcport->cfg.tx_bbcredit = (u8)tx_bbcredit; 3642 fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
3643 fcport->cfg.bb_scn = bb_scn;
3644 if (bb_scn)
3645 fcport->bbsc_op_state = BFA_TRUE;
3634 bfa_fcport_send_txcredit(fcport); 3646 bfa_fcport_send_txcredit(fcport);
3635} 3647}
3636 3648
@@ -3683,6 +3695,7 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
3683 attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa); 3695 attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
3684 attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa); 3696 attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
3685 attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm); 3697 attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
3698 attr->bbsc_op_status = fcport->bbsc_op_state;
3686 3699
3687 /* PBC Disabled State */ 3700 /* PBC Disabled State */
3688 if (bfa_fcport_is_pbcdisabled(bfa)) 3701 if (bfa_fcport_is_pbcdisabled(bfa))
@@ -3805,6 +3818,14 @@ bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
3805 return fcport->cfg.qos_enabled; 3818 return fcport->cfg.qos_enabled;
3806} 3819}
3807 3820
3821bfa_boolean_t
3822bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
3823{
3824 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3825
3826 return fcport->cfg.trunked;
3827}
3828
3808/* 3829/*
3809 * Rport State machine functions 3830 * Rport State machine functions
3810 */ 3831 */
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index c5927a5cbac9..c81cf5cb856f 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -377,6 +377,8 @@ struct bfa_lps_s {
377 bfa_status_t status; /* login status */ 377 bfa_status_t status; /* login status */
378 u16 pdusz; /* max receive PDU size */ 378 u16 pdusz; /* max receive PDU size */
379 u16 pr_bbcred; /* BB_CREDIT from peer */ 379 u16 pr_bbcred; /* BB_CREDIT from peer */
380 u8 pr_bbscn; /* BB_SCN from peer */
381 u8 bb_scn; /* local BB_SCN */
380 u8 lsrjt_rsn; /* LSRJT reason */ 382 u8 lsrjt_rsn; /* LSRJT reason */
381 u8 lsrjt_expl; /* LSRJT explanation */ 383 u8 lsrjt_expl; /* LSRJT explanation */
382 wwn_t pwwn; /* port wwn of lport */ 384 wwn_t pwwn; /* port wwn of lport */
@@ -477,6 +479,7 @@ struct bfa_fcport_s {
477 bfa_boolean_t diag_busy; /* diag busy status */ 479 bfa_boolean_t diag_busy; /* diag busy status */
478 bfa_boolean_t beacon; /* port beacon status */ 480 bfa_boolean_t beacon; /* port beacon status */
479 bfa_boolean_t link_e2e_beacon; /* link beacon status */ 481 bfa_boolean_t link_e2e_beacon; /* link beacon status */
482 bfa_boolean_t bbsc_op_state; /* Cred recov Oper State */
480 struct bfa_fcport_trunk_s trunk; 483 struct bfa_fcport_trunk_s trunk;
481 u16 fcoe_vlan; 484 u16 fcoe_vlan;
482}; 485};
@@ -515,7 +518,7 @@ void bfa_fcport_event_register(struct bfa_s *bfa,
515bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa); 518bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
516enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa); 519enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
517 520
518void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit); 521void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn);
519bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa); 522bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa);
520bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa); 523bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa);
521bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa, 524bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
@@ -524,6 +527,7 @@ bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
524bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, 527bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
525 void *cbarg); 528 void *cbarg);
526bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa); 529bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
530bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa);
527bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa); 531bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
528 532
529/* 533/*
@@ -607,7 +611,7 @@ struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
607void bfa_lps_delete(struct bfa_lps_s *lps); 611void bfa_lps_delete(struct bfa_lps_s *lps);
608void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, 612void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
609 u16 pdusz, wwn_t pwwn, wwn_t nwwn, 613 u16 pdusz, wwn_t pwwn, wwn_t nwwn,
610 bfa_boolean_t auth_en); 614 bfa_boolean_t auth_en, u8 bb_scn);
611void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, 615void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
612 wwn_t pwwn, wwn_t nwwn); 616 wwn_t pwwn, wwn_t nwwn);
613void bfa_lps_fdisclogo(struct bfa_lps_s *lps); 617void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 57cc50eacb0f..cdf84f67f0c2 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -53,6 +53,7 @@ int bfa_log_level = 3; /* WARNING log level */
53int ioc_auto_recover = BFA_TRUE; 53int ioc_auto_recover = BFA_TRUE;
54int bfa_linkup_delay = -1; 54int bfa_linkup_delay = -1;
55int fdmi_enable = BFA_TRUE; 55int fdmi_enable = BFA_TRUE;
56int fc_credit_recovery = BFA_TRUE;
56int pcie_max_read_reqsz; 57int pcie_max_read_reqsz;
57int bfa_debugfs_enable = 1; 58int bfa_debugfs_enable = 1;
58int msix_disable_cb = 0, msix_disable_ct = 0; 59int msix_disable_cb = 0, msix_disable_ct = 0;
@@ -138,6 +139,9 @@ MODULE_PARM_DESC(msix_disable_ct, "Disable Message Signaled Interrupts "
138module_param(fdmi_enable, int, S_IRUGO | S_IWUSR); 139module_param(fdmi_enable, int, S_IRUGO | S_IWUSR);
139MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1, " 140MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1, "
140 "Range[false:0|true:1]"); 141 "Range[false:0|true:1]");
142module_param(fc_credit_recovery, int, S_IRUGO | S_IWUSR);
143MODULE_PARM_DESC(fc_credit_recovery, "Enables FC Credit Recovery, default=1, "
144 "Range[false:0|true:1]");
141module_param(pcie_max_read_reqsz, int, S_IRUGO | S_IWUSR); 145module_param(pcie_max_read_reqsz, int, S_IRUGO | S_IWUSR);
142MODULE_PARM_DESC(pcie_max_read_reqsz, "PCIe max read request size, default=0 " 146MODULE_PARM_DESC(pcie_max_read_reqsz, "PCIe max read request size, default=0 "
143 "(use system setting), Range[128|256|512|1024|2048|4096]"); 147 "(use system setting), Range[128|256|512|1024|2048|4096]");
@@ -910,6 +914,7 @@ bfad_drv_init(struct bfad_s *bfad)
910 bfad->bfa_fcs.trcmod = bfad->trcmod; 914 bfad->bfa_fcs.trcmod = bfad->trcmod;
911 bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE); 915 bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
912 bfad->bfa_fcs.fdmi_enabled = fdmi_enable; 916 bfad->bfa_fcs.fdmi_enabled = fdmi_enable;
917 bfad->bfa_fcs.bbscn_enabled = fc_credit_recovery;
913 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 918 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
914 919
915 bfad->bfad_flags |= BFAD_DRV_INIT_DONE; 920 bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 4af1b02e2dbb..dcb112c8e203 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -353,6 +353,7 @@ extern int bfa_linkup_delay;
353extern int msix_disable_cb; 353extern int msix_disable_cb;
354extern int msix_disable_ct; 354extern int msix_disable_ct;
355extern int fdmi_enable; 355extern int fdmi_enable;
356extern int fc_credit_recovery;
356extern int supported_fc4s; 357extern int supported_fc4s;
357extern int pcie_max_read_reqsz; 358extern int pcie_max_read_reqsz;
358extern int bfa_debugfs_enable; 359extern int bfa_debugfs_enable;
diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
index d43bf6a08a66..edb92561dde9 100644
--- a/drivers/scsi/bfa/bfi_ms.h
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -226,7 +226,8 @@ struct bfi_fcport_enable_req_s {
226struct bfi_fcport_set_svc_params_req_s { 226struct bfi_fcport_set_svc_params_req_s {
227 struct bfi_mhdr_s mh; /* msg header */ 227 struct bfi_mhdr_s mh; /* msg header */
228 __be16 tx_bbcredit; /* Tx credits */ 228 __be16 tx_bbcredit; /* Tx credits */
229 u16 rsvd; 229 u8 bb_scn; /* BB_SC FC credit recovery */
230 u8 rsvd;
230}; 231};
231 232
232/* 233/*
@@ -374,7 +375,7 @@ struct bfi_lps_login_req_s {
374 u8 fdisc; 375 u8 fdisc;
375 u8 auth_en; 376 u8 auth_en;
376 u8 lps_role; 377 u8 lps_role;
377 u8 rsvd[1]; 378 u8 bb_scn;
378}; 379};
379 380
380struct bfi_lps_login_rsp_s { 381struct bfi_lps_login_rsp_s {
@@ -394,6 +395,8 @@ struct bfi_lps_login_rsp_s {
394 mac_t fcf_mac; 395 mac_t fcf_mac;
395 u8 ext_status; 396 u8 ext_status;
396 u8 brcd_switch; /* attached peer is brcd switch */ 397 u8 brcd_switch; /* attached peer is brcd switch */
398 u8 bb_scn; /* atatched port's bb_scn */
399 u8 resvd;
397}; 400};
398 401
399struct bfi_lps_logout_req_s { 402struct bfi_lps_logout_req_s {