From 222c9bb62bef1c64aba8a954611146e309ed8add Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Fri, 6 Jan 2012 21:12:50 +0100 Subject: [PATCH] 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 --- clock.c | 12 +++++++----- fsm.c | 11 +++++++---- fsm.h | 7 +++++-- port.c | 9 +++++---- port.h | 3 ++- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/clock.c b/clock.c index 13ce73d..6e94dcb 100644 --- a/clock.c +++ b/clock.c @@ -230,7 +230,7 @@ struct clock *clock_create(char *phc, struct interface *iface, int count, c->dds.numberPorts = c->nports = count; for (i = 0; i < c->nports; i++) - port_dispatch(c->port[i], EV_INITIALIZE); + port_dispatch(c->port[i], EV_INITIALIZE, 0); return c; } @@ -322,7 +322,7 @@ int clock_poll(struct clock *c) if (EV_STATE_DECISION_EVENT == event) sde = 1; 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) { struct foreign_clock *best = NULL, *fc; - int i; + int fresh_best = 0, i; for (i = 0; i < c->nports; 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", cid2str(&best->dataset.identity)); - if (c->best != best) + if (c->best != best) { mave_reset(c->avg_delay); + fresh_best = 1; + } c->best = best; @@ -482,6 +484,6 @@ static void handle_state_decision_event(struct clock *c) event = EV_INITIALIZE; break; } - port_dispatch(c->port[i], event); + port_dispatch(c->port[i], event, fresh_best); } } diff --git a/fsm.c b/fsm.c index 476de45..d1423e7 100644 --- a/fsm.c +++ b/fsm.c @@ -18,7 +18,7 @@ */ #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; @@ -195,7 +195,8 @@ enum port_state ptp_fsm(enum port_state state, enum fsm_event event) next = PS_GRAND_MASTER; break; case EV_RS_SLAVE: - next = PS_UNCALIBRATED; + if (mdiff) + next = PS_UNCALIBRATED; break; case EV_RS_PASSIVE: next = PS_PASSIVE; @@ -209,7 +210,8 @@ enum port_state ptp_fsm(enum port_state state, enum fsm_event event) 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; @@ -301,7 +303,8 @@ enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event) next = PS_UNCALIBRATED; break; case EV_RS_SLAVE: - next = PS_UNCALIBRATED; + if (mdiff) + next = PS_UNCALIBRATED; break; default: break; diff --git a/fsm.h b/fsm.h index b4b2eff..90c7a4d 100644 --- a/fsm.h +++ b/fsm.h @@ -58,16 +58,19 @@ enum fsm_event { * Run the state machine for a BC or OC port. * @param state The current state of the port. * @param event The event to be processed. + * @param mdiff Whether a new master has been selected. * @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. * @param state The current state of the port. * @param event The event to be processed. + * @param mdiff Whether a new master has been selected. * @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 diff --git a/port.c b/port.c index 512d242..243322c 100644 --- a/port.c +++ b/port.c @@ -311,10 +311,10 @@ static void port_synchronize(struct port *p, switch (state) { case SERVO_UNLOCKED: case SERVO_JUMP: - port_dispatch(p, EV_SYNCHRONIZATION_FAULT); + port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0); break; case SERVO_LOCKED: - port_dispatch(p, EV_MASTER_CLOCK_SELECTED); + port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0); break; } } @@ -794,10 +794,11 @@ struct foreign_clock *port_compute_best(struct port *p) 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) ? - 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) { /* diff --git a/port.h b/port.h index b575a3d..6e8da71 100644 --- a/port.h +++ b/port.h @@ -69,8 +69,9 @@ struct foreign_clock *port_compute_best(struct port *port); * * @param port A pointer previously obtained via port_open(). * @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