[PATCH 18/32] bfa: Introduce a link notification state machine.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Change details:

	- Introduce a link notification state machine to handle next incoming link events
	  while the current event is being delivered to the driver.

	- When the event has been processed by the driver, the link notification state machine
	  will queue the next event (if there is any) to the driver.
---
 drivers/scsi/bfa/bfa_fcport.c    |  232 +++++++++++++++++++++++++++++++++++--
 drivers/scsi/bfa/bfa_port_priv.h |   13 ++-
 2 files changed, 230 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c
index aef648b..29c8a6a 100644
--- a/drivers/scsi/bfa/bfa_fcport.c
+++ b/drivers/scsi/bfa/bfa_fcport.c
@@ -26,16 +26,6 @@
 BFA_TRC_FILE(HAL, PPORT);
 BFA_MODULE(pport);
 
-#define bfa_pport_callback(__pport, __event) do {			\
-	if ((__pport)->bfa->fcs) {      \
-		(__pport)->event_cbfn((__pport)->event_cbarg, (__event));      \
-	} else {							\
-		(__pport)->hcb_event = (__event);      \
-		bfa_cb_queue((__pport)->bfa, &(__pport)->hcb_qe,	\
-		__bfa_cb_port_event, (__pport));      \
-	}								\
-} while (0)
-
 /*
  * The port is considered disabled if corresponding physical port or IOC are
  * disabled explicitly
@@ -57,7 +47,10 @@ static void     __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete);
 static void     __bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete);
 static void     bfa_port_stats_timeout(void *cbarg);
 static void     bfa_port_stats_clr_timeout(void *cbarg);
-
+static void	bfa_pport_callback(struct bfa_pport_s *pport,
+				enum bfa_pport_linkstate event);
+static void	bfa_pport_queue_cb(struct bfa_pport_ln_s *ln,
+				enum bfa_pport_linkstate event);
 /**
  *  bfa_pport_private
  */
@@ -77,6 +70,16 @@ enum bfa_pport_sm_event {
 	BFA_PPORT_SM_HWFAIL = 9,	/*  IOC h/w failure */
 };
 
+/**
+ * BFA port link notification state machine events
+ */
+
+enum bfa_pport_ln_sm_event {
+	BFA_PPORT_LN_SM_LINKUP         = 1,    /*  linkup event */
+	BFA_PPORT_LN_SM_LINKDOWN       = 2,    /*  linkdown event */
+	BFA_PPORT_LN_SM_NOTIFICATION   = 3     /*  done notification */
+};
+
 static void     bfa_pport_sm_uninit(struct bfa_pport_s *pport,
 				    enum bfa_pport_sm_event event);
 static void     bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport,
@@ -100,6 +103,21 @@ static void     bfa_pport_sm_iocdown(struct bfa_pport_s *pport,
 static void     bfa_pport_sm_iocfail(struct bfa_pport_s *pport,
 				     enum bfa_pport_sm_event event);
 
+static void	bfa_pport_ln_sm_dn(struct bfa_pport_ln_s *ln,
+					enum bfa_pport_ln_sm_event event);
+static void	bfa_pport_ln_sm_dn_nf(struct bfa_pport_ln_s *ln,
+					enum bfa_pport_ln_sm_event event);
+static void	bfa_pport_ln_sm_dn_up_nf(struct bfa_pport_ln_s *ln,
+					enum bfa_pport_ln_sm_event event);
+static void     bfa_pport_ln_sm_up(struct bfa_pport_ln_s *ln,
+					enum bfa_pport_ln_sm_event event);
+static void	bfa_pport_ln_sm_up_nf(struct bfa_pport_ln_s *ln,
+					enum bfa_pport_ln_sm_event event);
+static void	bfa_pport_ln_sm_up_dn_nf(struct bfa_pport_ln_s *ln,
+					enum bfa_pport_ln_sm_event event);
+static void	bfa_pport_ln_sm_up_dn_up_nf(struct bfa_pport_ln_s *ln,
+					enum bfa_pport_ln_sm_event event);
+
 static struct bfa_sm_table_s hal_pport_sm_table[] = {
 	{BFA_SM(bfa_pport_sm_uninit), BFA_PPORT_ST_UNINIT},
 	{BFA_SM(bfa_pport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT},
@@ -619,7 +637,163 @@ bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 	}
 }
 
+/**
+ * Link state is down
+ */
+static void
+bfa_pport_ln_sm_dn(struct bfa_pport_ln_s *ln,
+		enum bfa_pport_ln_sm_event event)
+{
+	bfa_trc(ln->pport->bfa, event);
+
+	switch (event) {
+	case BFA_PPORT_LN_SM_LINKUP:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_up_nf);
+		bfa_pport_queue_cb(ln, BFA_PPORT_LINKUP);
+		break;
+
+	default:
+		bfa_sm_fault(ln->pport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for down notification
+ */
+static void
+bfa_pport_ln_sm_dn_nf(struct bfa_pport_ln_s *ln,
+		enum bfa_pport_ln_sm_event event)
+{
+	bfa_trc(ln->pport->bfa, event);
+
+	switch (event) {
+	case BFA_PPORT_LN_SM_LINKUP:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_up_nf);
+		break;
+
+	case BFA_PPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_dn);
+		break;
+
+	default:
+		bfa_sm_fault(ln->pport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for down notification and there is a pending up
+ */
+static void
+bfa_pport_ln_sm_dn_up_nf(struct bfa_pport_ln_s *ln,
+		enum bfa_pport_ln_sm_event event)
+{
+	bfa_trc(ln->pport->bfa, event);
+
+	switch (event) {
+	case BFA_PPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_nf);
+		break;
+
+	case BFA_PPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_up_nf);
+		bfa_pport_queue_cb(ln, BFA_PPORT_LINKUP);
+		break;
+
+	default:
+		bfa_sm_fault(ln->pport->bfa, event);
+	}
+}
+
+/**
+ * Link state is up
+ */
+static void
+bfa_pport_ln_sm_up(struct bfa_pport_ln_s *ln,
+                enum bfa_pport_ln_sm_event event)
+{
+	bfa_trc(ln->pport->bfa, event);
+
+	switch (event) {
+	case BFA_PPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_nf);
+		bfa_pport_queue_cb(ln, BFA_PPORT_LINKDOWN);
+		break;
+
+	default:
+		bfa_sm_fault(ln->pport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for up notification
+ */
+static void
+bfa_pport_ln_sm_up_nf(struct bfa_pport_ln_s *ln,
+		enum bfa_pport_ln_sm_event event)
+{
+	bfa_trc(ln->pport->bfa, event);
+
+	switch (event) {
+	case BFA_PPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_up_dn_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_up);
+		break;
+
+	default:
+		bfa_sm_fault(ln->pport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for up notification and there is a pending down
+ */
+static void
+bfa_pport_ln_sm_up_dn_nf(struct bfa_pport_ln_s *ln,
+		enum bfa_pport_ln_sm_event event)
+{
+	bfa_trc(ln->pport->bfa, event);
 
+	switch (event) {
+	case BFA_PPORT_LN_SM_LINKUP:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_up_dn_up_nf);
+		break;
+
+	case BFA_PPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_nf);
+		bfa_pport_queue_cb(ln, BFA_PPORT_LINKDOWN);
+		break;
+
+	default:
+		bfa_sm_fault(ln->pport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for up notification and there are pending down and up
+ */
+static void
+bfa_pport_ln_sm_up_dn_up_nf(struct bfa_pport_ln_s *ln,
+			enum bfa_pport_ln_sm_event event)
+{
+	bfa_trc(ln->pport->bfa, event);
+
+	switch (event) {
+	case BFA_PPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_up_dn_nf);
+		break;
+
+	case BFA_PPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_pport_ln_sm_dn_up_nf);
+		bfa_pport_queue_cb(ln, BFA_PPORT_LINKDOWN);
+		break;
+
+	default:
+		bfa_sm_fault(ln->pport->bfa, event);
+	}
+}
 
 /**
  *  bfa_pport_private
@@ -628,10 +802,12 @@ bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 static void
 __bfa_cb_port_event(void *cbarg, bfa_boolean_t complete)
 {
-	struct bfa_pport_s *pport = cbarg;
+	struct bfa_pport_ln_s *ln = cbarg;
 
 	if (complete)
-		pport->event_cbfn(pport->event_cbarg, pport->hcb_event);
+		ln->pport->event_cbfn(ln->pport->event_cbarg, ln->ln_event);
+	else
+		bfa_sm_send_event(ln, BFA_PPORT_LN_SM_NOTIFICATION);
 }
 
 #define PPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), \
@@ -681,13 +857,16 @@ bfa_pport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 {
 	struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
 	struct bfa_pport_cfg_s *port_cfg = &pport->cfg;
+	struct bfa_pport_ln_s *ln = &pport->ln;
 
 	bfa_os_memset(pport, 0, sizeof(struct bfa_pport_s));
 	pport->bfa = bfa;
+	ln->pport = pport;
 
 	bfa_pport_mem_claim(pport, meminfo);
 
 	bfa_sm_set_state(pport, bfa_pport_sm_uninit);
+	bfa_sm_set_state(ln, bfa_pport_ln_sm_dn);
 
 	/**
 	 * initialize and set default configuration
@@ -1369,6 +1548,33 @@ bfa_port_stats_clr_timeout(void *cbarg)
 }
 
 static void
+bfa_pport_callback(struct bfa_pport_s *pport, enum bfa_pport_linkstate event)
+{
+	if (pport->bfa->fcs) {
+		pport->event_cbfn(pport->event_cbarg, event);
+		return;
+	}
+
+	switch (event) {
+	case BFA_PPORT_LINKUP:
+		bfa_sm_send_event(&pport->ln, BFA_PPORT_LN_SM_LINKUP);
+		break;
+	case BFA_PPORT_LINKDOWN:
+		bfa_sm_send_event(&pport->ln, BFA_PPORT_LN_SM_LINKDOWN);
+		break;
+	default:
+		bfa_assert(0);
+	}
+}
+
+static void
+bfa_pport_queue_cb(struct bfa_pport_ln_s *ln, enum bfa_pport_linkstate event)
+{
+	ln->ln_event = event;
+	bfa_cb_queue(ln->pport->bfa, &ln->ln_qe, __bfa_cb_port_event, ln);
+}
+
+static void
 __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete)
 {
 	struct bfa_pport_s *port = cbarg;
diff --git a/drivers/scsi/bfa/bfa_port_priv.h b/drivers/scsi/bfa/bfa_port_priv.h
index 51f698a..f29701b 100644
--- a/drivers/scsi/bfa/bfa_port_priv.h
+++ b/drivers/scsi/bfa/bfa_port_priv.h
@@ -23,6 +23,16 @@
 #include "bfa_intr_priv.h"
 
 /**
+ * Link notification data structure
+ */
+struct bfa_pport_ln_s {
+	struct bfa_pport_s     *pport;
+	bfa_sm_t                sm;
+	struct bfa_cb_qe_s      ln_qe;  /*  BFA callback queue elem for ln */
+	enum bfa_pport_linkstate ln_event; /*  ln event for callback */
+};
+
+/**
  * BFA physical port data structure
  */
 struct bfa_pport_s {
@@ -52,9 +62,8 @@ struct bfa_pport_s {
 		union bfi_pport_i2h_msg_u i2hmsg;
 	} event_arg;
 	void			*bfad;	/*  BFA driver handle */
+	struct bfa_pport_ln_s   ln; /* Link Notification */
 	struct bfa_cb_qe_s		hcb_qe;	/*  BFA callback queue elem */
-	enum bfa_pport_linkstate	hcb_event;
-					/*  link event for callback */
 	u32		msgtag;	/*  fimrware msg tag for reply */
 	u8			*stats_kva;
 	u64		stats_pa;
-- 
1.6.5.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux