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

[SCSI] bfa: Add support for FC Arbitrated Loop topology.



- Add private loop topology support at 2G/4G/8G speeds with following
  limitations
  1. No support for multiple initiators in the loop
  2. No public loop support. If attached to a loop with an FL_Port,
     device continues to work as a private NL_Port in the loop
  3. No auto topology detection. User has to manually set the
     configured topology to loop if attaching to loop.
- When loop topology is configured, enabling FC port features
  QoS/Trunk/TRL are not allowed and vice versa.

Signed-off-by: default avatarVijaya Mohan Guvva <vmohan@brocade.com>
Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 56d92aa5
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -159,6 +159,8 @@ enum bfa_status {
	BFA_STATUS_BEACON_ON    = 72,   /* Port Beacon already on */
	BFA_STATUS_ENOFSAVE	= 78,	/*  No saved firmware trace */
	BFA_STATUS_IOC_DISABLED = 82,   /* IOC is already disabled */
	BFA_STATUS_ERROR_TRL_ENABLED  = 87,   /* TRL is enabled */
	BFA_STATUS_ERROR_QOS_ENABLED  = 88,   /* QoS is enabled */
	BFA_STATUS_NO_SFP_DEV = 89,	/* No SFP device check or replace SFP */
	BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */
	BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
@@ -184,6 +186,9 @@ enum bfa_status {
	BFA_STATUS_FAA_ACQ_ADDR = 200,	/* Acquiring addr */
	BFA_STATUS_ERROR_TRUNK_ENABLED = 203,	/* Trunk enabled on adapter */
	BFA_STATUS_MAX_ENTRY_REACHED = 212,	/* MAX entry reached */
	BFA_STATUS_TOPOLOGY_LOOP = 230, /* Topology is set to Loop */
	BFA_STATUS_LOOP_UNSUPP_MEZZ = 231, /* Loop topology is not supported
					    * on mezz cards */
	BFA_STATUS_MAX_VAL		/* Unknown error code */
};
#define bfa_status_t enum bfa_status
+69 −18
Original line number Diff line number Diff line
@@ -324,12 +324,46 @@ struct bfa_fw_fcoe_port_stats_s {
	struct bfa_fw_fip_stats_s		fip_stats;
};

/**
 * @brief LPSM statistics
 */
struct bfa_fw_lpsm_stats_s {
	u32	cls_rx;		/* LPSM cls_rx			*/
	u32	cls_tx;		/* LPSM cls_tx			*/
	u32	arbf0_rx;	/* LPSM abrf0 rcvd		*/
	u32	arbf0_tx;	/* LPSM abrf0 xmit		*/
	u32	init_rx;	/* LPSM loop init start		*/
	u32	unexp_hwst;	/* LPSM unknown hw state	*/
	u32	unexp_frame;	/* LPSM unknown_frame		*/
	u32	unexp_prim;	/* LPSM unexpected primitive	*/
	u32	prev_alpa_unavail; /* LPSM prev alpa unavailable */
	u32	alpa_unavail;	/* LPSM alpa not available	*/
	u32	lip_rx;		/* LPSM lip rcvd		*/
	u32	lip_f7f7_rx;	/* LPSM lip f7f7 rcvd		*/
	u32	lip_f8_rx;	/* LPSM lip f8 rcvd		*/
	u32	lip_f8f7_rx;	/* LPSM lip f8f7 rcvd		*/
	u32	lip_other_rx;	/* LPSM lip other rcvd		*/
	u32	lip_tx;		/* LPSM lip xmit		*/
	u32	retry_tov;	/* LPSM retry TOV		*/
	u32	lip_tov;	/* LPSM LIP wait TOV		*/
	u32	idle_tov;	/* LPSM idle wait TOV		*/
	u32	arbf0_tov;	/* LPSM arbfo wait TOV		*/
	u32	stop_loop_tov;	/* LPSM stop loop wait TOV	*/
	u32	lixa_tov;	/* LPSM lisa wait TOV		*/
	u32	lixx_tov;	/* LPSM lilp/lirp wait TOV	*/
	u32	cls_tov;	/* LPSM cls wait TOV		*/
	u32	sler;		/* LPSM SLER recvd		*/
	u32	failed;		/* LPSM failed			*/
	u32	success;	/* LPSM online			*/
};

/*
 * IOC firmware FC uport stats
 */
struct bfa_fw_fc_uport_stats_s {
	struct bfa_fw_port_snsm_stats_s		snsm_stats;
	struct bfa_fw_port_lksm_stats_s		lksm_stats;
	struct bfa_fw_lpsm_stats_s		lpsm_stats;
};

/*
@@ -357,11 +391,6 @@ struct bfa_fw_fcxchg_stats_s {
	u32	ua_state_inv;
};

struct bfa_fw_lpsm_stats_s {
	u32	cls_rx;
	u32	cls_tx;
};

/*
 *  Trunk statistics
 */
@@ -454,7 +483,6 @@ struct bfa_fw_stats_s {
	struct bfa_fw_io_stats_s	io_stats;
	struct bfa_fw_port_stats_s	port_stats;
	struct bfa_fw_fcxchg_stats_s	fcxchg_stats;
	struct bfa_fw_lpsm_stats_s	lpsm_stats;
	struct bfa_fw_lps_stats_s	lps_stats;
	struct bfa_fw_trunk_stats_s	trunk_stats;
	struct bfa_fw_advsm_stats_s	advsm_stats;
@@ -499,8 +527,9 @@ enum bfa_qos_bw_alloc {
 */
struct bfa_qos_attr_s {
	u8	state;		/*  QoS current state */
	u8		rsvd[3];
	u8	rsvd1[3];
	u32	total_bb_cr;	/*  Total BB Credits */
	u32	rsvd2[2];
};

/*
@@ -714,9 +743,11 @@ enum bfa_port_type {
 */
enum bfa_port_topology {
	BFA_PORT_TOPOLOGY_NONE = 0,	/*  No valid topology */
	BFA_PORT_TOPOLOGY_P2P  = 1,	/*  P2P only */
	BFA_PORT_TOPOLOGY_P2P_OLD_VER = 1, /* P2P def for older ver */
	BFA_PORT_TOPOLOGY_LOOP = 2,	/* LOOP topology */
	BFA_PORT_TOPOLOGY_AUTO = 3,	/*  auto topology selection */
	BFA_PORT_TOPOLOGY_AUTO_OLD_VER = 3, /* auto def for older ver */
	BFA_PORT_TOPOLOGY_AUTO = 4,	/* auto topology selection */
	BFA_PORT_TOPOLOGY_P2P = 5,	/* P2P only */
};

/*
@@ -851,9 +882,10 @@ struct bfa_port_cfg_s {
	u8	 bb_scn;	/*  BB_SCN value from FLOGI Exchg */
	u8	 bb_scn_state;	/*  Config state of BB_SCN */
	u8	 faa_state;	/*  FAA enabled/disabled        */
	u8	 rsvd[1];
	u8	 rsvd1;
	u16	 path_tov;	/*  device path timeout	*/
	u16	 q_depth;	/*  SCSI Queue depth		*/
	u32	 rsvd2;
};
#pragma pack()

@@ -971,6 +1003,13 @@ struct bfa_trunk_vc_attr_s {
	u16 vc_credits[8];
};

struct bfa_fcport_loop_info_s {
	u8	myalpa;		/* alpa claimed */
	u8	alpabm_val;	/* alpa bitmap valid or not (1 or 0) */
	u8	resvd[6];
	struct fc_alpabm_s alpabm;	/* alpa bitmap */
};

/*
 *	Link state information
 */
@@ -981,13 +1020,18 @@ struct bfa_port_link_s {
	u8	 speed;		/*  Link speed (1/2/4/8 G) */
	u32	 linkstate_opt; /*  Linkstate optional data (debug) */
	u8	 trunked;	/*  Trunked or not (1 or 0) */
	u8	 resvd[3];
	u8	 resvd[7];
	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
	union {
		struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
		struct bfa_fcport_loop_info_s loop_info;
		union {
			struct bfa_qos_vc_attr_s qos_vc_attr;
					/*  VC info from ELP */
			struct bfa_trunk_vc_attr_s trunk_vc_attr;
		struct bfa_fcport_fcf_s fcf; /*  FCF information (for FCoE) */
			struct bfa_fcport_fcf_s fcf;
					/*  FCF information (for FCoE) */
		} vc_fcf;
	} attr;
};
#pragma pack()

@@ -1112,6 +1156,9 @@ struct bfa_port_fc_stats_s {
	u64     tx_frames;      /*  Tx frames                   */
	u64     tx_words;       /*  Tx words                    */
	u64     tx_lip;         /*  Tx LIP                      */
	u64	tx_lip_f7f7;	/*  Tx LIP_F7F7		*/
	u64	tx_lip_f8f7;	/*  Tx LIP_F8F7		*/
	u64	tx_arbf0;	/*  Tx ARB F0			*/
	u64     tx_nos;         /*  Tx NOS                      */
	u64     tx_ols;         /*  Tx OLS                      */
	u64     tx_lr;          /*  Tx LR                       */
@@ -1119,6 +1166,9 @@ struct bfa_port_fc_stats_s {
	u64     rx_frames;      /*  Rx frames                   */
	u64     rx_words;       /*  Rx words                    */
	u64     lip_count;      /*  Rx LIP                      */
	u64	rx_lip_f7f7;	/*  Rx LIP_F7F7		*/
	u64	rx_lip_f8f7;	/*  Rx LIP_F8F7		*/
	u64	rx_arbf0;	/*  Rx ARB F0			*/
	u64     nos_count;      /*  Rx NOS                      */
	u64     ols_count;      /*  Rx OLS                      */
	u64     lr_count;       /*  Rx LR                       */
@@ -1140,6 +1190,7 @@ struct bfa_port_fc_stats_s {
	u64	bbsc_frames_lost; /* Credit Recovery-Frames Lost  */
	u64	bbsc_credits_lost; /* Credit Recovery-Credits Lost */
	u64	bbsc_link_resets; /* Credit Recovery-Link Resets   */
	u64	loop_timeouts;	/*  Loop timeouts		*/
};

/*
+5 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ typedef u64 wwn_t;

#define WWN_NULL	(0)
#define FC_SYMNAME_MAX	256	/*  max name server symbolic name size */
#define FC_ALPA_MAX	128

#pragma pack(1)

@@ -1015,6 +1016,10 @@ struct fc_symname_s {
	u8         symname[FC_SYMNAME_MAX];
};

struct fc_alpabm_s {
	u8	alpa_bm[FC_ALPA_MAX / 8];
};

/*
 * protocol default timeout values
 */
+4 −0
Original line number Diff line number Diff line
@@ -228,6 +228,10 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,

	memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));

	/* For FC AL bb_cr is 0 and altbbcred is 1 */
	if (!bb_cr)
		plogi->csp.altbbcred = 1;

	plogi->els_cmd.els_code = els_code;
	if (els_code == FC_ELS_PLOGI)
		fc_els_req_build(fchs, d_id, s_id, ox_id);
+51 −13
Original line number Diff line number Diff line
@@ -303,16 +303,30 @@ static void
bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
			  enum bfa_fcs_fabric_event event)
{
	struct bfa_s	*bfa = fabric->fcs->bfa;

	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
	bfa_trc(fabric->fcs, event);

	switch (event) {
	case BFA_FCS_FABRIC_SM_START:
		if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
		if (!bfa_fcport_is_linkup(fabric->fcs->bfa)) {
			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
			break;
		}
		if (bfa_fcport_get_topology(bfa) ==
				BFA_PORT_TOPOLOGY_LOOP) {
			fabric->fab_type = BFA_FCS_FABRIC_LOOP;
			fabric->bport.pid = bfa_fcport_get_myalpa(bfa);
			fabric->bport.pid = bfa_hton3b(fabric->bport.pid);
			bfa_sm_set_state(fabric,
					bfa_fcs_fabric_sm_online);
			bfa_fcs_fabric_set_opertype(fabric);
			bfa_fcs_lport_online(&fabric->bport);
		} else {
			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
			bfa_fcs_fabric_login(fabric);
		} else
			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
		}
		break;

	case BFA_FCS_FABRIC_SM_LINK_UP:
@@ -337,16 +351,28 @@ static void
bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
			   enum bfa_fcs_fabric_event event)
{
	struct bfa_s	*bfa = fabric->fcs->bfa;

	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
	bfa_trc(fabric->fcs, event);

	switch (event) {
	case BFA_FCS_FABRIC_SM_LINK_UP:
		if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP) {
			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
			bfa_fcs_fabric_login(fabric);
			break;
		}
		fabric->fab_type = BFA_FCS_FABRIC_LOOP;
		fabric->bport.pid = bfa_fcport_get_myalpa(bfa);
		fabric->bport.pid = bfa_hton3b(fabric->bport.pid);
		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
		bfa_fcs_fabric_set_opertype(fabric);
		bfa_fcs_lport_online(&fabric->bport);
		break;

	case BFA_FCS_FABRIC_SM_RETRY_OP:
	case BFA_FCS_FABRIC_SM_LOOPBACK:
		break;

	case BFA_FCS_FABRIC_SM_DELETE:
@@ -595,14 +621,20 @@ void
bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
			 enum bfa_fcs_fabric_event event)
{
	struct bfa_s	*bfa = fabric->fcs->bfa;

	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
	bfa_trc(fabric->fcs, event);

	switch (event) {
	case BFA_FCS_FABRIC_SM_LINK_DOWN:
		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
		if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {
			bfa_fcs_lport_offline(&fabric->bport);
		} else {
			bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
			bfa_fcs_fabric_notify_offline(fabric);
		}
		break;

	case BFA_FCS_FABRIC_SM_DELETE:
@@ -719,19 +751,28 @@ static void
bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,
			   enum bfa_fcs_fabric_event event)
{
	struct bfa_s	*bfa = fabric->fcs->bfa;

	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
	bfa_trc(fabric->fcs, event);

	switch (event) {
	case BFA_FCS_FABRIC_SM_STOPCOMP:
		if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {
			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
		} else {
			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
			bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);
		}
		break;

	case BFA_FCS_FABRIC_SM_LINK_UP:
		break;

	case BFA_FCS_FABRIC_SM_LINK_DOWN:
		if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
		else
			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
		break;

@@ -975,9 +1016,6 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
	struct bfa_lport_cfg_s	*pcfg = &fabric->bport.port_cfg;
	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;
Loading