43ff50
commit 10d4e7f8b0525bbf72981e3e5fcf0c10833a7631
43ff50
Author: Richard Cochran <richardcochran@gmail.com>
43ff50
Date:   Tue Jan 3 20:55:18 2017 +0100
43ff50
43ff50
    port: Make the finite state machine into a function variable.
43ff50
    
43ff50
    This allows adding new FSM flavors in the future.
43ff50
    
43ff50
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
43ff50
43ff50
diff --git a/port.c b/port.c
43ff50
index a1ad6f6..afe0057 100644
43ff50
--- a/port.c
43ff50
+++ b/port.c
43ff50
@@ -94,6 +94,8 @@ struct port {
43ff50
 	unsigned int pdr_missing;
43ff50
 	unsigned int multiple_seq_pdr_count;
43ff50
 	unsigned int multiple_pdr_detected;
43ff50
+	enum port_state (*state_machine)(enum port_state state,
43ff50
+					 enum fsm_event event, int mdiff);
43ff50
 	/* portDS */
43ff50
 	struct PortIdentity portIdentity;
43ff50
 	enum port_state     state; /*portState*/
43ff50
@@ -2142,10 +2144,8 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 		if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
43ff50
 			port_slave_priority_warning(p);
43ff50
 		}
43ff50
-		next = ptp_slave_fsm(p->state, event, mdiff);
43ff50
-	} else {
43ff50
-		next = ptp_fsm(p->state, event, mdiff);
43ff50
 	}
43ff50
+	next = p->state_machine(p->state, event, mdiff);
43ff50
 
43ff50
 	if (!fault_interval(p, last_fault_type(p), &i) &&
43ff50
 	    ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) ||
43ff50
@@ -2555,6 +2555,7 @@ struct port *port_open(int phc_index,
43ff50
 
43ff50
 	memset(p, 0, sizeof(*p));
43ff50
 
43ff50
+	p->state_machine = clock_slave_only(clock) ? ptp_slave_fsm : ptp_fsm;
43ff50
 	p->phc_index = phc_index;
43ff50
 	p->jbod = config_get_int(cfg, interface->name, "boundary_clock_jbod");
43ff50
 	transport = config_get_int(cfg, interface->name, "network_transport");
43ff50
43ff50
commit 80a28a9dc322f28b991effc44ec1c5362a598281
43ff50
Author: Richard Cochran <richardcochran@gmail.com>
43ff50
Date:   Tue Jan 3 20:55:33 2017 +0100
43ff50
43ff50
    Change a misleading fault handling function signature.
43ff50
    
43ff50
    Looking at the fault logic in port_dispatch(), you might think that
43ff50
    the function, fault_interval(), checks whether a fault is active, but
43ff50
    you would be wrong, since that function always returns zero.
43ff50
    
43ff50
    This patch removes the superfluous input error checking inside of
43ff50
    fault_interval() and changes the return type to void, making the
43ff50
    actual behavior explicit.  Dropping the input check is safe because
43ff50
    that function has exactly two callers, both of whom always provide
43ff50
    valid inputs.
43ff50
    
43ff50
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
43ff50
43ff50
diff --git a/port.c b/port.c
43ff50
index afe0057..6c9aa72 100644
43ff50
--- a/port.c
43ff50
+++ b/port.c
43ff50
@@ -205,16 +205,11 @@ enum fault_type last_fault_type(struct port *port)
43ff50
 	return port->last_fault_type;
43ff50
 }
43ff50
 
43ff50
-int fault_interval(struct port *port, enum fault_type ft,
43ff50
-	struct fault_interval *i)
43ff50
+void fault_interval(struct port *port, enum fault_type ft,
43ff50
+		    struct fault_interval *i)
43ff50
 {
43ff50
-	if (!port || !i)
43ff50
-		return -EINVAL;
43ff50
-	if (ft < 0 || ft >= FT_CNT)
43ff50
-		return -EINVAL;
43ff50
 	i->type = port->flt_interval_pertype[ft].type;
43ff50
 	i->val = port->flt_interval_pertype[ft].val;
43ff50
-	return 0;
43ff50
 }
43ff50
 
43ff50
 int port_fault_fd(struct port *port)
43ff50
@@ -2147,9 +2142,9 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 	}
43ff50
 	next = p->state_machine(p->state, event, mdiff);
43ff50
 
43ff50
-	if (!fault_interval(p, last_fault_type(p), &i) &&
43ff50
-	    ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) ||
43ff50
-	     (i.val == 0 && i.type == FTMO_LINEAR_SECONDS)))
43ff50
+	fault_interval(p, last_fault_type(p), &i);
43ff50
+	if ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) ||
43ff50
+	     (i.val == 0 && i.type == FTMO_LINEAR_SECONDS))
43ff50
 		fri_asap = 1;
43ff50
 	if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) {
43ff50
 		/*
43ff50
diff --git a/port.h b/port.h
43ff50
index 19dec4a..d2e0865 100644
43ff50
--- a/port.h
43ff50
+++ b/port.h
43ff50
@@ -318,9 +318,8 @@ enum fault_type last_fault_type(struct port *port);
43ff50
  * @param port        A port instance.
43ff50
  * @param ft          Fault type.
43ff50
  * @param i           Pointer to the struct which will be filled in.
43ff50
- * @return Zero on success, non-zero otherwise.
43ff50
  */
43ff50
-int fault_interval(struct port *port, enum fault_type ft,
43ff50
-	struct fault_interval *i);
43ff50
+void fault_interval(struct port *port, enum fault_type ft,
43ff50
+		    struct fault_interval *i);
43ff50
 
43ff50
 #endif
43ff50
43ff50
commit 1f66948d3853c8b08c7f52c9c8daecb361164a43
43ff50
Author: Richard Cochran <richardcochran@gmail.com>
43ff50
Date:   Tue Jan 3 20:55:42 2017 +0100
43ff50
43ff50
    Make the fault handling code more readable.
43ff50
    
43ff50
    The code that decides whether a fault qualifies for ASAP treatment is
43ff50
    a tangle of logical operators.  This patch replaces the open coded
43ff50
    logic with a helper function whose name makes the intent clear.  This
43ff50
    is a cosmetic change only.
43ff50
    
43ff50
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
43ff50
43ff50
diff --git a/port.c b/port.c
43ff50
index 6c9aa72..02dbabb 100644
43ff50
--- a/port.c
43ff50
+++ b/port.c
43ff50
@@ -161,6 +161,19 @@ static void announce_to_dataset(struct ptp_message *m, struct port *p,
43ff50
 	out->receiver     = p->portIdentity;
43ff50
 }
43ff50
 
43ff50
+static int clear_fault_asap(struct fault_interval *faint)
43ff50
+{
43ff50
+	switch (faint->type) {
43ff50
+	case FTMO_LINEAR_SECONDS:
43ff50
+		return faint->val == 0 ? 1 : 0;
43ff50
+	case FTMO_LOG2_SECONDS:
43ff50
+		return faint->val == FRI_ASAP ? 1 : 0;
43ff50
+	case FTMO_CNT:
43ff50
+		return 0;
43ff50
+	}
43ff50
+	return 0;
43ff50
+}
43ff50
+
43ff50
 static int msg_current(struct ptp_message *m, struct timespec now)
43ff50
 {
43ff50
 	int64_t t1, t2, tmo;
43ff50
@@ -2143,9 +2156,9 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 	next = p->state_machine(p->state, event, mdiff);
43ff50
 
43ff50
 	fault_interval(p, last_fault_type(p), &i);
43ff50
-	if ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) ||
43ff50
-	     (i.val == 0 && i.type == FTMO_LINEAR_SECONDS))
43ff50
+	if (clear_fault_asap(&i)) {
43ff50
 		fri_asap = 1;
43ff50
+	}
43ff50
 	if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) {
43ff50
 		/*
43ff50
 		 * This is a special case. Since we initialize the
43ff50
43ff50
commit 01ee947457813078f63d606c310818d6dedb4ca3
43ff50
Author: Richard Cochran <richardcochran@gmail.com>
43ff50
Date:   Tue Jan 3 20:55:50 2017 +0100
43ff50
43ff50
    Disentangle initialization from fault clearing.
43ff50
    
43ff50
    Although leaving the INITIALIZING state and clearing the FAULTY state
43ff50
    ASAP both result in a port entering the LISTENING state, still there
43ff50
    is no benefit from conflating the two.  In the FAULTY case, the
43ff50
    current code actually skips the INITIALIZING state altogether.
43ff50
    
43ff50
    This patch separates the two cases resulting in two benefits.  First,
43ff50
    the check for ASAP fault status is only made when a fault is actually
43ff50
    present, unlike the present unconditional check.  Second, this change
43ff50
    will allow us to cleanly support alternative state machines later on.
43ff50
    
43ff50
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
43ff50
43ff50
diff --git a/port.c b/port.c
43ff50
index 02dbabb..ebe7342 100644
43ff50
--- a/port.c
43ff50
+++ b/port.c
43ff50
@@ -2145,8 +2145,6 @@ static void port_p2p_transition(struct port *p, enum port_state next)
43ff50
 int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 {
43ff50
 	enum port_state next;
43ff50
-	struct fault_interval i;
43ff50
-	int fri_asap = 0;
43ff50
 
43ff50
 	if (clock_slave_only(p->clock)) {
43ff50
 		if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
43ff50
@@ -2155,11 +2153,15 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 	}
43ff50
 	next = p->state_machine(p->state, event, mdiff);
43ff50
 
43ff50
-	fault_interval(p, last_fault_type(p), &i);
43ff50
-	if (clear_fault_asap(&i)) {
43ff50
-		fri_asap = 1;
43ff50
+	if (PS_FAULTY == next) {
43ff50
+		struct fault_interval i;
43ff50
+		fault_interval(p, last_fault_type(p), &i);
43ff50
+		if (clear_fault_asap(&i)) {
43ff50
+			pr_notice("port %hu: clearing fault immediately", portnum(p));
43ff50
+			next = PS_INITIALIZING;
43ff50
+		}
43ff50
 	}
43ff50
-	if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) {
43ff50
+	if (PS_INITIALIZING == next) {
43ff50
 		/*
43ff50
 		 * This is a special case. Since we initialize the
43ff50
 		 * port immediately, we can skip right to listening
43ff50
43ff50
commit b738afb6044a8c59310fc13f646c8f5c4dcf2963
43ff50
Author: Richard Cochran <richardcochran@gmail.com>
43ff50
Date:   Thu Oct 27 15:20:36 2016 +0200
43ff50
43ff50
    fsm: Make the transition out of INITIALIZING part of the FSM code.
43ff50
    
43ff50
    The state machines in 1588 do not specify an event that causes a transition
43ff50
    out of the initializing state.  This was left as a local issue.  For this
43ff50
    transition, the current code assigns the next state outside of the FSM.  But
43ff50
    doing so prevents an alternative FSM to handle this transition differently.
43ff50
    
43ff50
    By introducing a new event, this patch places this transition where it
43ff50
    belongs, namely under the control of the FSM code,
43ff50
    
43ff50
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
43ff50
43ff50
diff --git a/fsm.c b/fsm.c
43ff50
index d1423e7..ce6efad 100644
43ff50
--- a/fsm.c
43ff50
+++ b/fsm.c
43ff50
@@ -27,7 +27,16 @@ enum port_state ptp_fsm(enum port_state state, enum fsm_event event, int mdiff)
43ff50
 
43ff50
 	switch (state) {
43ff50
 	case PS_INITIALIZING:
43ff50
-		next = PS_LISTENING;
43ff50
+		switch (event) {
43ff50
+		case EV_FAULT_DETECTED:
43ff50
+			next = PS_FAULTY;
43ff50
+			break;
43ff50
+		case EV_INIT_COMPLETE:
43ff50
+			next = PS_LISTENING;
43ff50
+			break;
43ff50
+		default:
43ff50
+			break;
43ff50
+		}
43ff50
 		break;
43ff50
 
43ff50
 	case PS_FAULTY:
43ff50
@@ -220,7 +229,16 @@ enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event,
43ff50
 
43ff50
 	switch (state) {
43ff50
 	case PS_INITIALIZING:
43ff50
-		next = PS_LISTENING;
43ff50
+		switch (event) {
43ff50
+		case EV_FAULT_DETECTED:
43ff50
+			next = PS_FAULTY;
43ff50
+			break;
43ff50
+		case EV_INIT_COMPLETE:
43ff50
+			next = PS_LISTENING;
43ff50
+			break;
43ff50
+		default:
43ff50
+			break;
43ff50
+		}
43ff50
 		break;
43ff50
 
43ff50
 	case PS_FAULTY:
43ff50
diff --git a/fsm.h b/fsm.h
43ff50
index 5d4ae91..0616daa 100644
43ff50
--- a/fsm.h
43ff50
+++ b/fsm.h
43ff50
@@ -48,6 +48,7 @@ enum fsm_event {
43ff50
 	EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES,
43ff50
 	EV_SYNCHRONIZATION_FAULT,
43ff50
 	EV_MASTER_CLOCK_SELECTED,
43ff50
+	EV_INIT_COMPLETE,
43ff50
 	EV_RS_MASTER,
43ff50
 	EV_RS_GRAND_MASTER,
43ff50
 	EV_RS_SLAVE,
43ff50
diff --git a/port.c b/port.c
43ff50
index ebe7342..5f1646b 100644
43ff50
--- a/port.c
43ff50
+++ b/port.c
43ff50
@@ -2120,6 +2120,7 @@ static void port_p2p_transition(struct port *p, enum port_state next)
43ff50
 		break;
43ff50
 	case PS_LISTENING:
43ff50
 		port_set_announce_tmo(p);
43ff50
+		port_set_delay_tmo(p);
43ff50
 		break;
43ff50
 	case PS_PRE_MASTER:
43ff50
 		port_set_qualification_tmo(p);
43ff50
@@ -2158,7 +2159,7 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 		fault_interval(p, last_fault_type(p), &i);
43ff50
 		if (clear_fault_asap(&i)) {
43ff50
 			pr_notice("port %hu: clearing fault immediately", portnum(p));
43ff50
-			next = PS_INITIALIZING;
43ff50
+			next = p->state_machine(next, EV_FAULT_CLEARED, 0);
43ff50
 		}
43ff50
 	}
43ff50
 	if (PS_INITIALIZING == next) {
43ff50
@@ -2170,14 +2171,12 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 		if (port_is_enabled(p)) {
43ff50
 			port_disable(p);
43ff50
 		}
43ff50
-		next = port_initialize(p) ? PS_FAULTY : PS_LISTENING;
43ff50
-		port_show_transition(p, next, event);
43ff50
-		p->state = next;
43ff50
-		if (next == PS_LISTENING && p->delayMechanism == DM_P2P) {
43ff50
-			port_set_delay_tmo(p);
43ff50
+		if (port_initialize(p)) {
43ff50
+			event = EV_FAULT_DETECTED;
43ff50
+		} else {
43ff50
+			event = EV_INIT_COMPLETE;
43ff50
 		}
43ff50
-		port_notify_event(p, NOTIFY_PORT_STATE);
43ff50
-		return 1;
43ff50
+		next = p->state_machine(next, event, 0);
43ff50
 	}
43ff50
 
43ff50
 	if (next == p->state)
43ff50
diff --git a/util.c b/util.c
43ff50
index 594b49f..2b880ff 100644
43ff50
--- a/util.c
43ff50
+++ b/util.c
43ff50
@@ -61,6 +61,7 @@ const char *ev_str[] = {
43ff50
 	"ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES",
43ff50
 	"SYNCHRONIZATION_FAULT",
43ff50
 	"MASTER_CLOCK_SELECTED",
43ff50
+	"INIT_COMPLETE",
43ff50
 	"RS_MASTER",
43ff50
 	"RS_GRAND_MASTER",
43ff50
 	"RS_SLAVE",
43ff50
43ff50
commit 6b471d45edfdfa835a9115ce4be96d92f100e2ac
43ff50
Author: Richard Cochran <richardcochran@gmail.com>
43ff50
Date:   Sun Feb 5 18:25:18 2017 +0100
43ff50
43ff50
    port: Change port_dispatch() into a void function.
43ff50
    
43ff50
    This global function used to return an error code, but now it always
43ff50
    returns zero.  This patch converts the function signature to return void
43ff50
    and simplifies the main clock loop by removing the useless test.
43ff50
    
43ff50
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
43ff50
43ff50
diff --git a/clock.c b/clock.c
43ff50
index a6a1a1a..f027305 100644
43ff50
--- a/clock.c
43ff50
+++ b/clock.c
43ff50
@@ -1463,7 +1463,7 @@ struct PortIdentity clock_parent_identity(struct clock *c)
43ff50
 
43ff50
 int clock_poll(struct clock *c)
43ff50
 {
43ff50
-	int cnt, err, i, sde = 0;
43ff50
+	int cnt, i, sde = 0;
43ff50
 	enum fsm_event event;
43ff50
 	struct pollfd *cur;
43ff50
 	struct port *p;
43ff50
@@ -1490,14 +1490,14 @@ int clock_poll(struct clock *c)
43ff50
 	cur++;
43ff50
 	LIST_FOREACH(p, &c->ports, list) {
43ff50
 		/* Let the ports handle their events. */
43ff50
-		for (i = err = 0; i < N_POLLFD && !err; i++) {
43ff50
+		for (i = 0; i < N_POLLFD; i++) {
43ff50
 			if (cur[i].revents & (POLLIN|POLLPRI)) {
43ff50
 				event = port_event(p, i);
43ff50
 				if (EV_STATE_DECISION_EVENT == event)
43ff50
 					sde = 1;
43ff50
 				if (EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES == event)
43ff50
 					sde = 1;
43ff50
-				err = port_dispatch(p, event, 0);
43ff50
+				port_dispatch(p, event, 0);
43ff50
 				/* Clear any fault after a little while. */
43ff50
 				if (PS_FAULTY == port_state(p)) {
43ff50
 					clock_fault_timeout(p, 1);
43ff50
diff --git a/port.c b/port.c
43ff50
index 5f1646b..0f99b1b 100644
43ff50
--- a/port.c
43ff50
+++ b/port.c
43ff50
@@ -2143,7 +2143,7 @@ static void port_p2p_transition(struct port *p, enum port_state next)
43ff50
 	};
43ff50
 }
43ff50
 
43ff50
-int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
+void port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 {
43ff50
 	enum port_state next;
43ff50
 
43ff50
@@ -2180,7 +2180,7 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 	}
43ff50
 
43ff50
 	if (next == p->state)
43ff50
-		return 0;
43ff50
+		return;
43ff50
 
43ff50
 	port_show_transition(p, next, event);
43ff50
 
43ff50
@@ -2196,12 +2196,11 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
43ff50
 	if (p->jbod && next == PS_UNCALIBRATED) {
43ff50
 		if (clock_switch_phc(p->clock, p->phc_index)) {
43ff50
 			p->last_fault_type = FT_SWITCH_PHC;
43ff50
-			return port_dispatch(p, EV_FAULT_DETECTED, 0);
43ff50
+			port_dispatch(p, EV_FAULT_DETECTED, 0);
43ff50
+			return;
43ff50
 		}
43ff50
 		clock_sync_interval(p->clock, p->log_sync_interval);
43ff50
 	}
43ff50
-
43ff50
-	return 0;
43ff50
 }
43ff50
 
43ff50
 enum fsm_event port_event(struct port *p, int fd_index)
43ff50
diff --git a/port.h b/port.h
43ff50
index d2e0865..b00bc64 100644
43ff50
--- a/port.h
43ff50
+++ b/port.h
43ff50
@@ -69,10 +69,8 @@ struct foreign_clock *port_compute_best(struct port *port);
43ff50
  * @param port A pointer previously obtained via port_open().
43ff50
  * @param event One of the @a fsm_event codes.
43ff50
  * @param mdiff Whether a new master has been selected.
43ff50
- * @return Zero if the port's file descriptor array is still valid,
43ff50
- *         and non-zero if it has become invalid.
43ff50
  */
43ff50
-int port_dispatch(struct port *p, enum fsm_event event, int mdiff);
43ff50
+void port_dispatch(struct port *p, enum fsm_event event, int mdiff);
43ff50
 
43ff50
 /**
43ff50
  * Generates state machine events based on activity on a port's file