port: Provide a common method for updating the port state.
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 <richardcochran@gmail.com>master
parent
c170405822
commit
866da1044c
82
port.c
82
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)
|
static void bc_dispatch(struct port *p, enum fsm_event event, int mdiff)
|
||||||
{
|
{
|
||||||
enum port_state next;
|
|
||||||
|
|
||||||
if (clock_slave_only(p->clock)) {
|
if (clock_slave_only(p->clock)) {
|
||||||
if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
|
if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
|
||||||
port_slave_priority_warning(p);
|
port_slave_priority_warning(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next = p->state_machine(p->state, event, mdiff);
|
|
||||||
|
|
||||||
if (PS_FAULTY == next) {
|
if (!port_state_update(p, event, mdiff)) {
|
||||||
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)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
port_show_transition(p, next, event);
|
|
||||||
|
|
||||||
if (p->delayMechanism == DM_P2P) {
|
if (p->delayMechanism == DM_P2P) {
|
||||||
port_p2p_transition(p, next);
|
port_p2p_transition(p, p->state);
|
||||||
} else {
|
} else {
|
||||||
port_e2e_transition(p, next);
|
port_e2e_transition(p, p->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
p->state = next;
|
if (p->jbod && p->state == PS_UNCALIBRATED) {
|
||||||
port_notify_event(p, NOTIFY_PORT_STATE);
|
|
||||||
|
|
||||||
if (p->jbod && next == PS_UNCALIBRATED) {
|
|
||||||
if (clock_switch_phc(p->clock, p->phc_index)) {
|
if (clock_switch_phc(p->clock, p->phc_index)) {
|
||||||
p->last_fault_type = FT_SWITCH_PHC;
|
p->last_fault_type = FT_SWITCH_PHC;
|
||||||
port_dispatch(p, EV_FAULT_DETECTED, 0);
|
port_dispatch(p, EV_FAULT_DETECTED, 0);
|
||||||
|
@ -2987,3 +2955,43 @@ enum port_state port_state(struct port *port)
|
||||||
{
|
{
|
||||||
return port->state;
|
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;
|
||||||
|
}
|
||||||
|
|
9
port.h
9
port.h
|
@ -212,6 +212,15 @@ struct port *port_open(int phc_index,
|
||||||
*/
|
*/
|
||||||
enum port_state port_state(struct port *port);
|
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
|
* Return array of file descriptors for this port. The fault fd is not
|
||||||
* included.
|
* included.
|
||||||
|
|
Loading…
Reference in New Issue