Commit 8633ced3 authored by Sven Meier's avatar Sven Meier

bmc & cleanup: fixes after the audit portings

The audit portings changed the timely behaviour of the ppsi which cause wrong behaviours,
the timeout scheme was changed to only reset timeouts where needed and in all non PTP
states. UTC offset is now fetched from the system where supported, link up/down is now
considered in the BMC, also some state changes where cleaned up to be out of the BMC, e.g.
state changes based on timeouts between PreMaster and Master or between Uncalibrated and Slave.
parent 6295769e
......@@ -51,6 +51,8 @@ void sim_main_loop(struct pp_globals *ppg)
for (j = 0; j < ppg->nlinks; j++) {
ppi = INST(ppg, j);
ppi->is_new_state = 1;
/* just tell that the links are up */
ppi->linkUp = TRUE;
}
delay_ns = run_all_state_machines(ppg) * 1000LL * 1000LL;
......
......@@ -48,6 +48,8 @@ void unix_main_loop(struct pp_globals *ppg)
for (j = 0; j < ppg->nlinks; j++) {
ppi = INST(ppg, j);
/* just tell that the links are up */
ppi->linkUp = TRUE;
/*
* The main loop here is based on select. While we are not
......
......@@ -225,7 +225,8 @@ int wrc_ptp_start()
delay_ms = pp_state_machine(ppi, NULL, 0);
start_tics = timer_get_tics();
WR_DSPOR(ppi)->linkUP = FALSE;
/* just tell that the link is up, if not it will anyhow not receive anything */
ppi->linkUP = TRUE;
wr_servo_reset(ppi);
ptp_enabled = 1;
......@@ -244,6 +245,8 @@ int wrc_ptp_stop()
memset(ppi->frgn_master, 0, sizeof(ppi->frgn_master));
ppi->frgn_rec_num = 0; /* no known master */
/* just tell that the link is down now */
ppi->linkUP = FALSE;
ptp_enabled = 0;
wr_servo_reset(ppi);
pp_close_globals(&ppg_static);
......
......@@ -29,7 +29,7 @@ static int run_all_state_machines(struct pp_globals *ppg)
for (j = 0; j < ppg->nlinks; j++) {
struct pp_instance *ppi = INST(ppg, j);
int old_lu = WR_DSPOR(ppi)->linkUP;
int old_lu = ppi->linkUP;
struct hal_port_state *p;
/* FIXME: we should save this pointer in the ppi itself */
......@@ -40,16 +40,16 @@ static int run_all_state_machines(struct pp_globals *ppg)
continue;
}
WR_DSPOR(ppi)->linkUP =
ppi->linkUP =
(p->state != HAL_PORT_STATE_LINK_DOWN &&
p->state != HAL_PORT_STATE_DISABLED);
if (old_lu != WR_DSPOR(ppi)->linkUP) {
if (old_lu != ppi->linkUP) {
pp_diag(ppi, fsm, 1, "iface %s went %s\n",
ppi->iface_name, WR_DSPOR(ppi)->linkUP ? "up":"down");
ppi->iface_name, ppi->linkUP ? "up":"down");
if (WR_DSPOR(ppi)->linkUP) {
if (ppi->linkUP) {
ppi->state = PPS_INITIALIZING;
}
else {
......@@ -62,7 +62,7 @@ static int run_all_state_machines(struct pp_globals *ppg)
}
/* Do not call state machine if link is down */
if (WR_DSPOR(ppi)->linkUP)
if (ppi->linkUP)
delay_ms_j = pp_state_machine(ppi, NULL, 0);
else
delay_ms_j = PP_DEFAULT_NEXT_DELAY_MS;
......
......@@ -87,8 +87,11 @@ get_current_state_table_item(struct pp_instance *ppi)
*/
static int leave_current_state(struct pp_instance *ppi)
{
/* if the next or old state is non standard PTP reset all timeouts */
if ((ppi->state > PPS_SLAVE) || (ppi->next_state > PPS_SLAVE))
pp_timeout_setall(ppi);
ppi->state = ppi->next_state;
pp_timeout_setall(ppi);
ppi->flags &= ~PPI_FLAGS_WAITING;
pp_diag_fsm(ppi, ppi->current_state_item->name, STATE_LEAVE, 0);
/* next_delay unused: go to new state now */
......
......@@ -28,6 +28,7 @@
#define PP_DEFAULT_SYNC_INTERVAL 0 /* -7 in 802.1AS */
#define PP_DEFAULT_SYNC_RECEIPT_TIMEOUT 3
#define PP_DEFAULT_ANNOUNCE_RECEIPT_TIMEOUT 3 /* 3 by default */
#define PP_DEFAULT_UTC_OFFSET 37
/* Clock classes (pag 55, PTP-2008). See ppsi-manual for an explanation */
#define PP_CLASS_SLAVE_ONLY 255
......
......@@ -180,6 +180,7 @@ struct pp_instance {
UInteger16 sent_seq[__PP_NR_MESSAGES_TYPES]; /* last sent this type */
MsgHeader received_ptp_header;
Boolean linkUP;
char *iface_name; /* for direct actions on hardware */
char *port_name; /* for diagnostics, mainly */
int port_idx;
......
......@@ -197,6 +197,7 @@ extern struct pp_network_operations unix_net_ops;
* If "set" receives a NULL time value, it should update the TAI offset.
*/
struct pp_time_operations {
int (*get_utc_offset)(struct pp_instance *ppi, int *offset);
int (*get)(struct pp_instance *ppi, struct pp_time *t);
int (*set)(struct pp_instance *ppi, const struct pp_time *t);
/* freq_ppb is parts per billion */
......
......@@ -24,6 +24,8 @@ void bare_main_loop(struct pp_instance *ppi)
{
int delay_ms;
/* just tell that the links are up */
ppi->linkUp = TRUE;
/*
* The main loop here is based on select. While we are not
* doing anything else but the protocol, this allows extra stuff
......
......@@ -307,9 +307,11 @@ static int wr_state_decision(struct pp_instance *ppi, int next_state)
wrp->parentWrModeOn = FALSE;
wrp->calibrated = !WR_DEFAULT_PHY_CALIBRATION_REQUIRED;
/* if we are leaving the slave state reset the servo */
if ((ppi->state == PPS_SLAVE) &&
(ppg->ebest_idx == ppi->port_idx))
(ppg->ebest_idx == ppi->port_idx)) {
wr_servo_reset(ppi);
}
}
/* else do the normal statemachine */
......
......@@ -11,7 +11,7 @@
/* Please increment WRS_PPSI_SHMEM_VERSION if you change any exported data
* structure */
#define WRS_PPSI_SHMEM_VERSION 23 /* Changed struct pp_frgn_master */
#define WRS_PPSI_SHMEM_VERSION 25 /* linkUp added to pp_instance */
/* Don't include the Following when this file is included in assembler. */
#ifndef __ASSEMBLY__
......@@ -51,7 +51,6 @@ struct wr_dsport {
FixedDelta otherNodeDeltaTx;
FixedDelta otherNodeDeltaRx;
Boolean doRestart;
Boolean linkUP;
};
/* This uppercase name matches "DSPOR(ppi)" used by standard protocol */
......
......@@ -22,6 +22,8 @@ void bmc_m1(struct pp_instance *ppi)
struct DSParent *parent = DSPAR(ppi);
struct DSDefault *defds = DSDEF(ppi);
struct DSTimeProperties *prop = DSPRO(ppi);
int ret = 0;
int offset;
/* Current data set update */
DSCUR(ppi)->stepsRemoved = 0;
......@@ -38,16 +40,31 @@ void bmc_m1(struct pp_instance *ppi)
parent->grandmasterClockQuality = defds->clockQuality;
parent->grandmasterPriority1 = defds->priority1;
parent->grandmasterPriority2 = defds->priority2;
ret = ppi->t_ops->get_utc_offset(ppi, &offset);
if (ret)
offset = PP_DEFAULT_UTC_OFFSET;
/* Time Properties data set */
/* TODO get the time properties from somewhere,
* these are the default according to 9.4
*/
prop->currentUtcOffset = 37;
prop->currentUtcOffsetValid = FALSE;
if (prop->currentUtcOffset != offset) {
pp_diag(ppi, bmc, 1, "New UTC offset: %i\n",
offset);
prop->currentUtcOffset = offset;
ppi->t_ops->set(ppi, NULL);
}
if (ret)
{
prop->timeTraceable = FALSE;
prop->currentUtcOffsetValid = FALSE;
}
else
{
prop->timeTraceable = TRUE;
prop->currentUtcOffsetValid = TRUE;
}
/* these are the default according to 9.4 */
prop->leap59 = FALSE;
prop->leap61 = FALSE;
prop->timeTraceable = FALSE;
prop->frequencyTraceable = FALSE;
prop->ptpTimescale = TRUE;
prop->timeSource = INTERNAL_OSCILLATOR;
......@@ -59,6 +76,8 @@ void bmc_m2(struct pp_instance *ppi)
struct DSParent *parent = DSPAR(ppi);
struct DSDefault *defds = DSDEF(ppi);
struct DSTimeProperties *prop = DSPRO(ppi);
int ret = 0;
int offset;
/* Current data set update */
DSCUR(ppi)->stepsRemoved = 0;
......@@ -75,16 +94,31 @@ void bmc_m2(struct pp_instance *ppi)
parent->grandmasterClockQuality = defds->clockQuality;
parent->grandmasterPriority1 = defds->priority1;
parent->grandmasterPriority2 = defds->priority2;
ret = ppi->t_ops->get_utc_offset(ppi, &offset);
if (ret)
offset = PP_DEFAULT_UTC_OFFSET;
/* Time Properties data set */
/* TODO get the time properties from somewhere,
* these are the default according to 9.4
*/
prop->currentUtcOffset = 37;
prop->currentUtcOffsetValid = FALSE;
if (prop->currentUtcOffset != offset) {
pp_diag(ppi, bmc, 1, "New UTC offset: %i\n",
offset);
prop->currentUtcOffset = offset;
ppi->t_ops->set(ppi, NULL);
}
if (ret)
{
prop->timeTraceable = FALSE;
prop->currentUtcOffsetValid = FALSE;
}
else
{
prop->timeTraceable = TRUE;
prop->currentUtcOffsetValid = TRUE;
}
/* these are the default according to 9.4 */
prop->leap59 = FALSE;
prop->leap61 = FALSE;
prop->timeTraceable = FALSE;
prop->frequencyTraceable = FALSE;
prop->ptpTimescale = TRUE;
prop->timeSource = INTERNAL_OSCILLATOR;
......@@ -559,15 +593,16 @@ master_m1:
return PPS_LISTENING;
}
bmc_m1(ppi);
if (ppi->state != PPS_MASTER) {
/* if not already in pre master state start qualification */
if (ppi->state != PPS_PRE_MASTER) {
/* 9.2.6.10 a) timeout 0 */
pp_timeout_clear(ppi, PP_TO_QUALIFICATION);
}
if ((ppi->state != PPS_MASTER) &&
(ppi->state != PPS_PRE_MASTER)) {
/* 9.2.6.10 a) timeout 0 */
pp_timeout_clear(ppi, PP_TO_QUALIFICATION);
return PPS_PRE_MASTER;
} else
return PPS_MASTER;
} else {
/* the decision to go from PPS_PRE_MASTER to PPS_MASTER is
* done outside the BMC, so just return the current state */
return ppi->state;
}
master_m2:
pp_diag(ppi, bmc, 1, "%s: master m2\n", __func__);
......@@ -578,15 +613,16 @@ master_m2:
return PPS_LISTENING;
}
bmc_m2(ppi);
if (ppi->state != PPS_MASTER) {
/* if not already in pre master state start qualification */
if (ppi->state != PPS_PRE_MASTER) {
/* 9.2.6.10 a) timeout 0 */
pp_timeout_clear(ppi, PP_TO_QUALIFICATION);
}
if ((ppi->state != PPS_MASTER) &&
(ppi->state != PPS_PRE_MASTER)) {
/* 9.2.6.10 a) timeout 0 */
pp_timeout_clear(ppi, PP_TO_QUALIFICATION);
return PPS_PRE_MASTER;
} else
return PPS_MASTER;
} else {
/* the decision to go from PPS_PRE_MASTER to PPS_MASTER is
* done outside the BMC, so just return the current state */
return ppi->state;
}
master_m3:
pp_diag(ppi, bmc, 1, "%s: master m3\n", __func__);
......@@ -597,17 +633,18 @@ master_m3:
return PPS_LISTENING;
}
bmc_m3(ppi);
if (ppi->state != PPS_MASTER) {
/* if not already in pre master state start qualification */
if (ppi->state != PPS_PRE_MASTER) {
/* timeout reinit */
pp_timeout_init(ppi);
/* 9.2.6.11 b) timeout steps removed+1*/
pp_timeout_set(ppi, PP_TO_QUALIFICATION);
}
if ((ppi->state != PPS_MASTER) &&
(ppi->state != PPS_PRE_MASTER)) {
/* timeout reinit */
pp_timeout_init(ppi);
/* 9.2.6.11 b) timeout steps removed+1*/
pp_timeout_set(ppi, PP_TO_QUALIFICATION);
return PPS_PRE_MASTER;
} else
return PPS_MASTER;
} else {
/* the decision to go from PPS_PRE_MASTER to PPS_MASTER is
* done outside the BMC, so just return the current state */
return ppi->state;
}
slave_s1:
pp_diag(ppi, bmc, 1, "%s: slave s1\n", __func__);
......@@ -642,7 +679,9 @@ slave_s1:
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_SLAVE)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
return PPS_SLAVE;
/* the decision to go from UNCALIBRATED to SLAVEW is
* done outside the BMC, so just return the current state */
return ppi->state;
}
}
}
......@@ -811,6 +850,14 @@ void bmc_add_frgn_master(struct pp_instance *ppi, void *buf,
pp_diag(ppi, bmc, 1, "New foreign Master %i added\n", sel);
}
static void bmc_flush_frgn_master(struct pp_instance *ppi)
{
pp_diag(ppi, bmc, 2, "%s\n", __func__);
memset(ppi->frgn_master, 0, sizeof(ppi->frgn_master));
ppi->frgn_rec_num = 0;
}
static void bmc_age_frgn_master(struct pp_instance *ppi)
{
int i, j;
......@@ -877,8 +924,7 @@ static int bmc_any_port_initializing(struct pp_globals *ppg)
ppi = INST(ppg, i);
if ((WR_DSPOR(ppi)->linkUP)
&& (ppi->state == PPS_INITIALIZING)) {
if (ppi->linkUP && (ppi->state == PPS_INITIALIZING)) {
pp_diag(ppi, bmc, 2, "The first port in INITIALIZING "
"state is %i\n", i);
return 1;
......@@ -904,6 +950,10 @@ static void bmc_update_erbest(struct pp_globals *ppg)
ppi = INST(ppg, i);
frgn_master = ppi->frgn_master;
/* if link is down clear foreign master table */
if (!ppi->linkUP)
bmc_flush_frgn_master(ppi);
if (ppi->frgn_rec_num > 0) {
/* Only if port is not in the FAULTY or DISABLED
* state 9.2.6.8 */
......@@ -1020,8 +1070,13 @@ int bmc(struct pp_instance *ppi)
/* Calulate Ebest Figure 25 */
bmc_update_ebest(ppg);
/* Make state decision */
next_state = bmc_state_decision(ppi);
if (ppi->linkUP) {
/* Make state decision */
next_state = bmc_state_decision(ppi);
} else {
/* Set it back to initializing */
next_state = PPS_INITIALIZING;
}
/* Extra states handled here */
if (pp_hooks.state_decision)
......
......@@ -91,6 +91,7 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
port->logSyncInterval = opt->sync_intvl;
port->versionNumber = PP_VERSION_PTP;
pp_timeout_init(ppi);
pp_timeout_setall(ppi);
if (pp_hooks.init)
ret = pp_hooks.init(ppi, buf, len);
......@@ -105,7 +106,7 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
DSDEF(ppi)->clockQuality.clockAccuracy);
msg_init_header(ppi, ppi->tx_ptp); /* This is used for all tx */
if (ppi->role != PPSI_ROLE_MASTER)
ppi->next_state = PPS_LISTENING;
else
......
......@@ -8,6 +8,22 @@
#include <ppsi/ppsi.h>
#include "bare-linux.h"
static int bare_time_get_utc_offset(struct pp_instance *ppi, int *offset)
{
struct bare_timex t;
/*
* Get the UTC/TAI difference
*/
memset(&t, 0, sizeof(t));
if (adjtimex(&t) >= 0) {
*offset = (int)t.tai;
return 0;
} else {
*offset = 0;
return -1;
}
}
static int bare_time_get(struct pp_instance *ppi, struct pp_time *t)
{
struct bare_timeval tv;
......@@ -100,6 +116,7 @@ static unsigned long bare_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations bare_time_ops = {
.get_utc_offset = bare_time_get_utc_offset,
.get = bare_time_get,
.set = bare_time_set,
.adjust = bare_time_adjust,
......
......@@ -46,6 +46,13 @@ int sim_fast_forward_ns(struct pp_globals *ppg, int64_t ff_ns)
return 0;
}
static int sim_time_get_utc_offset(struct pp_instance *ppi, int *offset)
{
/* no UTC offset */
*offset = 0;
return -1;
}
static int sim_time_get(struct pp_instance *ppi, struct pp_time *t)
{
t->scaled_nsecs = (SIM_PPI_ARCH(ppi)->time.current_ns %
......@@ -113,6 +120,7 @@ static unsigned long sim_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations sim_time_ops = {
.get_utc_offset = sim_time_get_utc_offset,
.get = sim_time_get,
.set = sim_time_set,
.adjust = sim_time_adjust,
......
......@@ -23,6 +23,27 @@ static void clock_fatal_error(char *context)
exit(1);
}
static int unix_time_get_utc_offset(struct pp_instance *ppi, int *offset)
{
struct timex t;
/*
* Get the UTC/TAI difference
*/
memset(&t, 0, sizeof(t));
if (adjtimex(&t) >= 0) {
/*
* Our WRS kernel has tai support, but our compiler does not.
* We are 32-bit only, and we know for sure that tai is
* exactly after stbcnt. It's a bad hack, but it works
*/
*offset = *((int *)(&t.stbcnt) + 1);
return 0;
} else {
*offset = 0;
return -1;
}
}
static int unix_time_get(struct pp_instance *ppi, struct pp_time *t)
{
struct timespec tp;
......@@ -124,6 +145,7 @@ static unsigned long unix_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations unix_time_ops = {
.get_utc_offset = unix_time_get_utc_offset,
.get = unix_time_get,
.set = unix_time_set,
.adjust = unix_time_adjust,
......
......@@ -9,6 +9,13 @@
#include "pps_gen.h" /* in wrpc-sw */
#include "syscon.h" /* in wrpc-sw */
static int wrpc_time_get_utc_offset(struct pp_instance *ppi, int *offset)
{
/* no UTC offset */
*offset = 0;
return -1;
}
static int wrpc_time_get(struct pp_instance *ppi, struct pp_time *t)
{
uint64_t sec;
......@@ -65,6 +72,7 @@ static unsigned long wrpc_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations wrpc_time_ops = {
.get_utc_offset = wrpc_time_get_utc_offset,
.get = wrpc_time_get,
.set = wrpc_time_set,
.adjust = wrpc_time_adjust,
......
......@@ -187,6 +187,27 @@ static int wrdate_get(struct pp_time *t)
return 0;
}
static int wrs_time_get_utc_offset(struct pp_instance *ppi, int *offset)
{
struct timex t;
/*
* Get the UTC/TAI difference
*/
memset(&t, 0, sizeof(t));
if (adjtimex(&t) >= 0) {
/*
* Our WRS kernel has tai support, but our compiler does not.
* We are 32-bit only, and we know for sure that tai is
* exactly after stbcnt. It's a bad hack, but it works
*/
*offset = *((int *)(&t.stbcnt) + 1);
return 0;
} else {
*offset = 0;
return -1;
}
}
/* This is only used when the wrs is slave to a non-WR master */
static int wrs_time_get(struct pp_instance *ppi, struct pp_time *t)
{
......@@ -371,6 +392,7 @@ static unsigned long wrs_calc_timeout(struct pp_instance *ppi,
}
struct pp_time_operations wrs_time_ops = {
.get_utc_offset = wrs_time_get_utc_offset,
.get = wrs_time_get,
.set = wrs_time_set,
.adjust = wrs_time_adjust,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment