Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[SCSI] bfa: Defined a new LPS event to clear virtual link on a vport



Clear virtual links was not propagated upwards to bfa from fw.
This resulted in HBA and switch being in an inconsistent state.

So defined a new LPS event for clear virtual link on a vport,
and also now clear virtual link on a baseport, is sent as a
link down event from the fw.

Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 4c147dd8
Loading
Loading
Loading
Loading
+70 −1
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ static void bfa_lps_send_login(struct bfa_lps_s *lps);
static void bfa_lps_send_logout(struct bfa_lps_s *lps);
static void bfa_lps_login_comp(struct bfa_lps_s *lps);
static void bfa_lps_logout_comp(struct bfa_lps_s *lps);

static void bfa_lps_cvl_event(struct bfa_lps_s *lps);

/**
 *  lps_pvt BFA LPS private functions
@@ -62,6 +62,7 @@ enum bfa_lps_event {
	BFA_LPS_SM_RESUME	= 4,	/* space present in reqq queue	*/
	BFA_LPS_SM_DELETE	= 5,	/* lps delete from user		*/
	BFA_LPS_SM_OFFLINE	= 6,	/* Link is offline		*/
	BFA_LPS_SM_RX_CVL       = 7,	/* Rx clear virtual link        */
};

static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
@@ -101,6 +102,7 @@ bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
		bfa_lps_free(lps);
		break;

	case BFA_LPS_SM_RX_CVL:
	case BFA_LPS_SM_OFFLINE:
		break;

@@ -162,6 +164,14 @@ bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
		bfa_reqq_wcancel(&lps->wqe);
		break;

	case BFA_LPS_SM_RX_CVL:
		/*
		 * Login was not even sent out; so when getting out
		 * of this state, it will appear like a login retry
		 * after Clear virtual link
		 */
		break;

	default:
		bfa_assert(0);
	}
@@ -187,6 +197,15 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
		}
		break;

	case BFA_LPS_SM_RX_CVL:
		bfa_sm_set_state(lps, bfa_lps_sm_init);

		/* Let the vport module know about this event */
		bfa_lps_cvl_event(lps);
		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
		break;

	case BFA_LPS_SM_OFFLINE:
	case BFA_LPS_SM_DELETE:
		bfa_sm_set_state(lps, bfa_lps_sm_init);
@@ -395,6 +414,20 @@ bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
}

/**
 * Firmware received a Clear virtual link request (for FCoE)
 */
static void
bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
{
	struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
	struct bfa_lps_s        *lps;

	lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);

	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
}

/**
 * Space is available in request queue, resume queueing request to firmware.
 */
@@ -531,7 +564,39 @@ bfa_lps_logout_comp(struct bfa_lps_s *lps)
		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
}

/**
 * Clear virtual link completion handler for non-fcs
 */
static void
bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
{
	struct bfa_lps_s *lps   = arg;

	if (!complete)
		return;

	/* Clear virtual link to base port will result in link down */
	if (lps->fdisc)
		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
}

/**
 * Received Clear virtual link event --direct call for fcs,
 * queue for others
 */
static void
bfa_lps_cvl_event(struct bfa_lps_s *lps)
{
	if (!lps->bfa->fcs) {
		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
				lps);
		return;
	}

	/* Clear virtual link to base port will result in link down */
	if (lps->fdisc)
		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
}

/**
 *  lps_public BFA LPS public functions
@@ -773,6 +838,10 @@ bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
		bfa_lps_logout_rsp(bfa, msg.logout_rsp);
		break;

	case BFI_LPS_H2I_CVL_EVENT:
		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
		break;

	default:
		bfa_trc(bfa, m->mhdr.msg_id);
		bfa_assert(0);
+1 −0
Original line number Diff line number Diff line
@@ -319,6 +319,7 @@ void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
void bfa_cb_lps_flogo_comp(void *bfad, void *uarg);
void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
void bfa_cb_lps_cvl_event(void *bfad, void *uarg);

#endif /* __BFA_SVC_H__ */
+8 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ enum bfi_lps_h2i_msgs {
enum bfi_lps_i2h_msgs {
	BFI_LPS_H2I_LOGIN_RSP	= BFA_I2HM(1),
	BFI_LPS_H2I_LOGOUT_RSP	= BFA_I2HM(2),
	BFI_LPS_H2I_CVL_EVENT   = BFA_I2HM(3),
};

struct bfi_lps_login_req_s {
@@ -77,6 +78,12 @@ struct bfi_lps_logout_rsp_s {
	u8		rsvd[2];
};

struct bfi_lps_cvl_event_s {
	struct bfi_mhdr_s  mh;      /* common msg header      */
	u8		lp_tag;
	u8		rsvd[3];
};

union bfi_lps_h2i_msg_u {
	struct bfi_mhdr_s		*msg;
	struct bfi_lps_login_req_s	*login_req;
@@ -87,6 +94,7 @@ union bfi_lps_i2h_msg_u {
	struct bfi_msg_s		*msg;
	struct bfi_lps_login_rsp_s	*login_rsp;
	struct bfi_lps_logout_rsp_s	*logout_rsp;
	struct bfi_lps_cvl_event_s	*cvl_event;
};

#pragma pack()
+7 −2
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@ enum bfa_plog_mid {
	BFA_PL_MID_HAL_FCXP 	= 4,
	BFA_PL_MID_HAL_UF 	= 5,
	BFA_PL_MID_FCS 		= 6,
	BFA_PL_MID_MAX 		= 7
	BFA_PL_MID_LPS		= 7,
	BFA_PL_MID_MAX 		= 8
};

#define BFA_PL_MID_STRLEN    8
@@ -118,7 +119,11 @@ enum bfa_plog_eid {
	BFA_PL_EID_RSCN 		= 17,
	BFA_PL_EID_DEBUG 		= 18,
	BFA_PL_EID_MISC 		= 19,
	BFA_PL_EID_MAX 			= 20
	BFA_PL_EID_FIP_FCF_DISC		= 20,
	BFA_PL_EID_FIP_FCF_CVL		= 21,
	BFA_PL_EID_LOGIN		= 22,
	BFA_PL_EID_LOGO			= 23,
	BFA_PL_EID_MAX			= 24
};

#define BFA_PL_ENAME_STRLEN    	8
+11 −0
Original line number Diff line number Diff line
@@ -888,4 +888,15 @@ bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
}

/**
 * Received clear virtual link
 */
void
bfa_cb_lps_cvl_event(void *bfad, void *uarg)
{
	struct bfa_fcs_vport_s *vport = uarg;

	/* Send an Offline followed by an ONLINE */
	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
}