When computing the next port state based on a FSM event, much of the logic
will stay the same for OC, BC, and TC nodes.

- handling a fault ASAP
- INITIALIZING state handling
- showing the transition in the log
- sending notifications

This patch moves this common code into a global port method, making it
available to future TC implementations.

Signed-off-by: Richard Cochran <richardcoch...@gmail.com>
---
 port.c | 82 ++++++++++++++++++++++++++++++++++++------------------------------
 port.h |  9 ++++++++
 2 files changed, 54 insertions(+), 37 deletions(-)

diff --git a/port.c b/port.c
index 9c7f695..bc44017 100644
--- a/port.c
+++ b/port.c
@@ -2382,55 +2382,23 @@ void port_dispatch(struct port *p, enum fsm_event 
event, int mdiff)
 
 static void bc_dispatch(struct port *p, enum fsm_event event, int mdiff)
 {
-       enum port_state next;
-
        if (clock_slave_only(p->clock)) {
                if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
                        port_slave_priority_warning(p);
                }
        }
-       next = p->state_machine(p->state, event, mdiff);
-
-       if (PS_FAULTY == next) {
-               struct fault_interval i;
-               fault_interval(p, last_fault_type(p), &i);
-               if (clear_fault_asap(&i)) {
-                       pr_notice("port %hu: clearing fault immediately", 
portnum(p));
-                       next = p->state_machine(next, EV_FAULT_CLEARED, 0);
-               }
-       }
-       if (PS_INITIALIZING == next) {
-               /*
-                * This is a special case. Since we initialize the
-                * port immediately, we can skip right to listening
-                * state if all goes well.
-                */
-               if (port_is_enabled(p)) {
-                       port_disable(p);
-               }
-               if (port_initialize(p)) {
-                       event = EV_FAULT_DETECTED;
-               } else {
-                       event = EV_INIT_COMPLETE;
-               }
-               next = p->state_machine(next, event, 0);
-       }
 
-       if (next == p->state)
+       if (!port_state_update(p, event, mdiff)) {
                return;
-
-       port_show_transition(p, next, event);
+       }
 
        if (p->delayMechanism == DM_P2P) {
-               port_p2p_transition(p, next);
+               port_p2p_transition(p, p->state);
        } else {
-               port_e2e_transition(p, next);
+               port_e2e_transition(p, p->state);
        }
 
-       p->state = next;
-       port_notify_event(p, NOTIFY_PORT_STATE);
-
-       if (p->jbod && next == PS_UNCALIBRATED) {
+       if (p->jbod && p->state == PS_UNCALIBRATED) {
                if (clock_switch_phc(p->clock, p->phc_index)) {
                        p->last_fault_type = FT_SWITCH_PHC;
                        port_dispatch(p, EV_FAULT_DETECTED, 0);
@@ -2987,3 +2955,43 @@ enum port_state port_state(struct port *port)
 {
        return port->state;
 }
+
+int port_state_update(struct port *p, enum fsm_event event, int mdiff)
+{
+       enum port_state next = p->state_machine(p->state, event, mdiff);
+
+       if (PS_FAULTY == next) {
+               struct fault_interval i;
+               fault_interval(p, last_fault_type(p), &i);
+               if (clear_fault_asap(&i)) {
+                       pr_notice("port %hu: clearing fault immediately", 
portnum(p));
+                       next = p->state_machine(next, EV_FAULT_CLEARED, 0);
+               }
+       }
+
+       if (PS_INITIALIZING == next) {
+               /*
+                * This is a special case. Since we initialize the
+                * port immediately, we can skip right to listening
+                * state if all goes well.
+                */
+               if (port_is_enabled(p)) {
+                       port_disable(p);
+               }
+               if (port_initialize(p)) {
+                       event = EV_FAULT_DETECTED;
+               } else {
+                       event = EV_INIT_COMPLETE;
+               }
+               next = p->state_machine(next, event, 0);
+       }
+
+       if (next != p->state) {
+               port_show_transition(p, next, event);
+               p->state = next;
+               port_notify_event(p, NOTIFY_PORT_STATE);
+               return 1;
+       }
+
+       return 0;
+}
diff --git a/port.h b/port.h
index 60fd0a4..a76b2bd 100644
--- a/port.h
+++ b/port.h
@@ -213,6 +213,15 @@ struct port *port_open(int phc_index,
 enum port_state port_state(struct port *port);
 
 /**
+ * Update a port's current state based on a given event.
+ * @param p        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.
+ * @return         One (1) if the port state has changed, zero otherwise.
+ */
+int port_state_update(struct port *p, enum fsm_event event, int mdiff);
+
+/**
  * Return array of file descriptors for this port. The fault fd is not
  * included.
  * @param port A port instance
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to