Fix the port finite state machine.

The state machine needs to know whether a new master has just been
selected in order to choose between the slave and uncalibrated states.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
master
Richard Cochran 2012-01-06 21:12:50 +01:00
parent c2fad7bd51
commit 222c9bb62b
5 changed files with 26 additions and 16 deletions

12
clock.c
View File

@ -230,7 +230,7 @@ struct clock *clock_create(char *phc, struct interface *iface, int count,
c->dds.numberPorts = c->nports = count; c->dds.numberPorts = c->nports = count;
for (i = 0; i < c->nports; i++) for (i = 0; i < c->nports; i++)
port_dispatch(c->port[i], EV_INITIALIZE); port_dispatch(c->port[i], EV_INITIALIZE, 0);
return c; return c;
} }
@ -322,7 +322,7 @@ int clock_poll(struct clock *c)
if (EV_STATE_DECISION_EVENT == event) if (EV_STATE_DECISION_EVENT == event)
sde = 1; sde = 1;
else else
port_dispatch(c->port[i], event); port_dispatch(c->port[i], event, 0);
} }
} }
} }
@ -435,7 +435,7 @@ struct timePropertiesDS *clock_time_properties(struct clock *c)
static void handle_state_decision_event(struct clock *c) static void handle_state_decision_event(struct clock *c)
{ {
struct foreign_clock *best = NULL, *fc; struct foreign_clock *best = NULL, *fc;
int i; int fresh_best = 0, i;
for (i = 0; i < c->nports; i++) { for (i = 0; i < c->nports; i++) {
fc = port_compute_best(c->port[i]); fc = port_compute_best(c->port[i]);
@ -451,8 +451,10 @@ static void handle_state_decision_event(struct clock *c)
pr_notice("selected best master clock %s", pr_notice("selected best master clock %s",
cid2str(&best->dataset.identity)); cid2str(&best->dataset.identity));
if (c->best != best) if (c->best != best) {
mave_reset(c->avg_delay); mave_reset(c->avg_delay);
fresh_best = 1;
}
c->best = best; c->best = best;
@ -482,6 +484,6 @@ static void handle_state_decision_event(struct clock *c)
event = EV_INITIALIZE; event = EV_INITIALIZE;
break; break;
} }
port_dispatch(c->port[i], event); port_dispatch(c->port[i], event, fresh_best);
} }
} }

7
fsm.c
View File

@ -18,7 +18,7 @@
*/ */
#include "fsm.h" #include "fsm.h"
enum port_state ptp_fsm(enum port_state state, enum fsm_event event) enum port_state ptp_fsm(enum port_state state, enum fsm_event event, int mdiff)
{ {
enum port_state next = state; enum port_state next = state;
@ -195,6 +195,7 @@ enum port_state ptp_fsm(enum port_state state, enum fsm_event event)
next = PS_GRAND_MASTER; next = PS_GRAND_MASTER;
break; break;
case EV_RS_SLAVE: case EV_RS_SLAVE:
if (mdiff)
next = PS_UNCALIBRATED; next = PS_UNCALIBRATED;
break; break;
case EV_RS_PASSIVE: case EV_RS_PASSIVE:
@ -209,7 +210,8 @@ enum port_state ptp_fsm(enum port_state state, enum fsm_event event)
return next; return next;
} }
enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event) enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event,
int mdiff)
{ {
enum port_state next = state; enum port_state next = state;
@ -301,6 +303,7 @@ enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event)
next = PS_UNCALIBRATED; next = PS_UNCALIBRATED;
break; break;
case EV_RS_SLAVE: case EV_RS_SLAVE:
if (mdiff)
next = PS_UNCALIBRATED; next = PS_UNCALIBRATED;
break; break;
default: default:

7
fsm.h
View File

@ -58,16 +58,19 @@ enum fsm_event {
* Run the state machine for a BC or OC port. * Run the state machine for a BC or OC port.
* @param state The current state of the port. * @param state The current state of the port.
* @param event The event to be processed. * @param event The event to be processed.
* @param mdiff Whether a new master has been selected.
* @return The new state for the port. * @return The new state for the port.
*/ */
enum port_state ptp_fsm(enum port_state state, enum fsm_event event); enum port_state ptp_fsm(enum port_state state, enum fsm_event event, int mdiff);
/** /**
* Run the state machine for a slave only clock. * Run the state machine for a slave only clock.
* @param state The current state of the port. * @param state The current state of the port.
* @param event The event to be processed. * @param event The event to be processed.
* @param mdiff Whether a new master has been selected.
* @return The new state for the port. * @return The new state for the port.
*/ */
enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event); enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event,
int mdiff);
#endif #endif

9
port.c
View File

@ -311,10 +311,10 @@ static void port_synchronize(struct port *p,
switch (state) { switch (state) {
case SERVO_UNLOCKED: case SERVO_UNLOCKED:
case SERVO_JUMP: case SERVO_JUMP:
port_dispatch(p, EV_SYNCHRONIZATION_FAULT); port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0);
break; break;
case SERVO_LOCKED: case SERVO_LOCKED:
port_dispatch(p, EV_MASTER_CLOCK_SELECTED); port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0);
break; break;
} }
} }
@ -794,10 +794,11 @@ struct foreign_clock *port_compute_best(struct port *p)
return p->best; return p->best;
} }
void port_dispatch(struct port *p, enum fsm_event event) void port_dispatch(struct port *p, enum fsm_event event, int mdiff)
{ {
enum port_state next = clock_slave_only(p->clock) ? enum port_state next = clock_slave_only(p->clock) ?
ptp_slave_fsm(p->state, event) : ptp_fsm(p->state, event); ptp_slave_fsm(p->state, event, mdiff) :
ptp_fsm(p->state, event, mdiff);
if (PS_INITIALIZING == next) { if (PS_INITIALIZING == next) {
/* /*

3
port.h
View File

@ -69,8 +69,9 @@ struct foreign_clock *port_compute_best(struct port *port);
* *
* @param port A pointer previously obtained via port_open(). * @param port A pointer previously obtained via port_open().
* @param event One of the @a fsm_event codes. * @param event One of the @a fsm_event codes.
* @param mdiff Whether a new master has been selected.
*/ */
void port_dispatch(struct port *port, enum fsm_event event); void port_dispatch(struct port *p, enum fsm_event event, int mdiff);
/** /**
* Generates state machine events based on activity on a port's file * Generates state machine events based on activity on a port's file