Commit be540a99 authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley
Browse files

[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: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 8b070b4a
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -746,6 +746,8 @@ struct bfa_port_cfg_s {
	u8	 tx_bbcredit;	/*  transmit buffer credits	*/
	u8	 ratelimit;	/*  ratelimit enabled or not	*/
	u8	 trl_def_speed;	/*  ratelimit default speed	*/
	u8	bb_scn;
	u8	rsvd[3];
	u16 path_tov;	/*  device path timeout	*/
	u16 q_depth;	/*  SCSI Queue depth		*/
};
@@ -782,6 +784,7 @@ struct bfa_port_attr_s {
	bfa_boolean_t		beacon;		/*  current beacon status */
	bfa_boolean_t		link_e2e_beacon; /*  link beacon is on */
	bfa_boolean_t		plog_enabled;	/*  portlog is enabled */
	bfa_boolean_t	bbsc_op_status;	/* fc credit recovery oper state */

	/*
	 * Dynamic field - info from FCS
@@ -1018,6 +1021,9 @@ struct bfa_port_fc_stats_s {
	u64     bad_os_count;   /*  Invalid ordered sets        */
	u64     err_enc_out;    /*  Encoding err nonframe_8b10b */
	u64     err_enc;        /*  Encoding err frame_8b10b    */
	u64	bbsc_frames_lost; /* Credit Recovery-Frames Lost  */
	u64	bbsc_credits_lost; /* Credit Recovery-Credits Lost */
	u64	bbsc_link_resets; /* Credit Recovery-Link Resets   */
};

/*
+1 −1
Original line number Diff line number Diff line
@@ -1021,7 +1021,7 @@ struct fc_symname_s {
#define FC_ED_TOV	2
#define FC_REC_TOV	(FC_ED_TOV + 1)
#define FC_RA_TOV	10
#define FC_ELS_TOV	(2 * FC_RA_TOV)
#define FC_ELS_TOV	((2 * FC_RA_TOV) + 1)
#define FC_FCCT_TOV	(3 * FC_RA_TOV)

/*
+10 −8
Original line number Diff line number Diff line
@@ -94,7 +94,6 @@ fcbuild_init(void)
	 */
	plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
	plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
	plogi_tmpl.csp.bbcred = cpu_to_be16(0x0004);
	plogi_tmpl.csp.ciro = 0x1;
	plogi_tmpl.csp.cisc = 0x0;
	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)
static          u16
fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
		 __be16 ox_id, wwn_t port_name, wwn_t node_name,
		 u16 pdu_size, u8 els_code)
		 u16 pdu_size, u16 bb_cr, u8 els_code)
{
	struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);

@@ -220,6 +219,7 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
		fc_els_rsp_build(fchs, d_id, s_id, ox_id);

	plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
	plogi->csp.bbcred  = cpu_to_be16(bb_cr);

	memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
	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,
u16
fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
		   __be16 ox_id, wwn_t port_name, wwn_t node_name,
		   u16 pdu_size, u16 local_bb_credits)
		   u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
{
	u32        d_id = 0;
	u16	   bbscn_rxsz = (bb_scn << 12) | pdu_size;

	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
	fc_els_rsp_build(fchs, d_id, s_id, ox_id);

	flogi->els_cmd.els_code = FC_ELS_ACC;
	flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
	flogi->class3.rxsz = cpu_to_be16(pdu_size);
	flogi->csp.rxsz  = cpu_to_be16(bbscn_rxsz);	/* bb_scn/rxsz */
	flogi->port_name = port_name;
	flogi->node_name = node_name;

@@ -306,19 +308,19 @@ fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
u16
fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
	       u16 ox_id, wwn_t port_name, wwn_t node_name,
	       u16 pdu_size)
	       u16 pdu_size, u16 bb_cr)
{
	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
				node_name, pdu_size, FC_ELS_PLOGI);
				node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
}

u16
fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
		   u16 ox_id, wwn_t port_name, wwn_t node_name,
		   u16 pdu_size)
		   u16 pdu_size, u16 bb_cr)
{
	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
				node_name, pdu_size, FC_ELS_ACC);
				node_name, pdu_size, bb_cr, FC_ELS_ACC);
}

enum fc_parse_status
+3 −3
Original line number Diff line number Diff line
@@ -147,11 +147,11 @@ u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
				   u32 s_id, __be16 ox_id,
				   wwn_t port_name, wwn_t node_name,
				   u16 pdu_size,
				   u16 local_bb_credits);
				   u16 local_bb_credits, u8 bb_scn);

u16        fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
			       u32 s_id, u16 ox_id, wwn_t port_name,
			       wwn_t node_name, u16 pdu_size);
			       wwn_t node_name, u16 pdu_size, u16 bb_cr);

enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);

@@ -189,7 +189,7 @@ u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
u16        fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
				   u32 s_id, u16 ox_id,
				   wwn_t port_name, wwn_t node_name,
				   u16 pdu_size);
				   u16 pdu_size, u16 bb_cr);

u16        fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
			u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name,
+54 −6
Original line number Diff line number Diff line
@@ -196,6 +196,9 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
					 u32 rsp_len,
					 u32 resid_len,
					 struct fchs_s *rspfchs);
static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric);
static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled(
				struct bfa_fcs_fabric_s *fabric);

static void	bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
					 enum bfa_fcs_fabric_event event);
@@ -322,7 +325,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
	case BFA_FCS_FABRIC_SM_CONT_OP:

		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
					   fabric->bb_credit);
					   fabric->bb_credit,
					   bfa_fcs_fabric_oper_bbscn(fabric));
		fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;

		if (fabric->auth_reqd && fabric->is_auth) {
@@ -350,7 +354,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
	case BFA_FCS_FABRIC_SM_NO_FABRIC:
		fabric->fab_type = BFA_FCS_FABRIC_N2N;
		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
					   fabric->bb_credit);
					   fabric->bb_credit,
					   bfa_fcs_fabric_oper_bbscn(fabric));
		bfa_fcs_fabric_notify_online(fabric);
		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
		break;
@@ -518,7 +523,8 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
	case BFA_FCS_FABRIC_SM_NO_FABRIC:
		bfa_trc(fabric->fcs, fabric->bb_credit);
		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
					   fabric->bb_credit);
					   fabric->bb_credit,
					   bfa_fcs_fabric_oper_bbscn(fabric));
		break;

	default:
@@ -764,6 +770,10 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)

	case BFA_STATUS_FABRIC_RJT:
		fabric->stats.flogi_rejects++;
		if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR &&
		    fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO)
			fabric->fcs->bbscn_flogi_rjt = BFA_TRUE;

		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
		return;

@@ -808,13 +818,17 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
{
	struct bfa_s		*bfa = fabric->fcs->bfa;
	struct bfa_lport_cfg_s	*pcfg = &fabric->bport.port_cfg;
	u8			alpa = 0;
	u8			alpa = 0, bb_scn = 0;

	if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
		alpa = bfa_fcport_get_myalpa(bfa);

	if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
	    (!fabric->fcs->bbscn_flogi_rjt))
		bb_scn = BFA_FCS_PORT_DEF_BB_SCN;

	bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn);

	fabric->stats.flogi_sent++;
}
@@ -872,6 +886,37 @@ bfa_fcs_fabric_delay(void *cbarg)
	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
}

/*
 * Computes operating BB_SCN value
 */
static u8
bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric)
{
	u8	pr_bbscn = fabric->lps->pr_bbscn;

	if (!(fabric->fcs->bbscn_enabled && pr_bbscn))
		return 0;

	/* return max of local/remote bb_scn values */
	return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ?
		pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN);
}

/*
 * Check if BB_SCN can be enabled.
 */
static bfa_boolean_t
bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric)
{
	if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) &&
			fabric->fcs->bbscn_enabled &&
			!bfa_fcport_is_qos_enabled(fabric->fcs->bfa) &&
			!bfa_fcport_is_trunk_enabled(fabric->fcs->bfa))
		return BFA_TRUE;
	else
		return BFA_FALSE;
}

/*
 * Delete all vports and wait for vport delete completions.
 */
@@ -989,6 +1034,7 @@ void
bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
{
	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
	fabric->fcs->bbscn_flogi_rjt = BFA_FALSE;
	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
}

@@ -1192,6 +1238,7 @@ bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
	}

	fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
	fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12);
	bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
	bport->port_topo.pn2n.reply_oxid = fchs->ox_id;

@@ -1224,7 +1271,8 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
				    n2n_port->reply_oxid, pcfg->pwwn,
				    pcfg->nwwn,
				    bfa_fcport_get_maxfrsize(bfa),
				    bfa_fcport_get_rx_bbcredit(bfa));
				    bfa_fcport_get_rx_bbcredit(bfa),
				    bfa_fcs_fabric_oper_bbscn(fabric));

	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
		      BFA_FALSE, FC_CLASS_3,
Loading