Commit 91794555 authored by Sven Meier's avatar Sven Meier

clock class: handling of changing clock classes in gm mode changed

The clock class is now decreased and increased based on the servo state,
this only has an effect for wrs and wrpc since the contain a servo loop.
parent 3f97bf92
......@@ -12,7 +12,7 @@
static struct pp_runtime_opts sim_master_rt_opts = {
.clock_quality = {
.clockClass = PP_CLASS_WR_GM_LOCKED,
.clockClass = PP_PTP_CLASS_GM_LOCKED,
.clockAccuracy = PP_DEFAULT_CLOCK_ACCURACY,
.offsetScaledLogVariance = PP_DEFAULT_CLOCK_VARIANCE,
},
......
......@@ -135,22 +135,22 @@ int wrc_ptp_set_mode(int mode)
case WRC_MODE_ABSCAL: /* absolute calibration, gm-lookalike */
wrp->wrConfig = WR_M_ONLY;
ppi->role = PPSI_ROLE_MASTER;
*class_ptr = PP_CLASS_WR_GM_LOCKED;
*class_ptr = PP_PTP_CLASS_GM_LOCKED;
spll_init(SPLL_MODE_GRAND_MASTER, 0, 1);
shw_pps_gen_unmask_output(1);
lock_timeout = LOCK_TIMEOUT_GM;
DSDEF(ppi)->clockQuality.clockClass = PP_CLASS_WR_GM_LOCKED;
DSDEF(ppi)->clockQuality.clockClass = PP_PTP_CLASS_GM_LOCKED;
bmc_m1(ppi);
break;
case WRC_MODE_MASTER:
wrp->wrConfig = WR_M_ONLY;
ppi->role = PPSI_ROLE_MASTER;
*class_ptr = PP_CLASS_DEFAULT;
*class_ptr = PP_PTP_CLASS_GM_UNLOCKED;
spll_init(SPLL_MODE_FREE_RUNNING_MASTER, 0, 1);
shw_pps_gen_unmask_output(1);
lock_timeout = LOCK_TIMEOUT_FM;
DSDEF(ppi)->clockQuality.clockClass = PP_CLASS_DEFAULT;
DSDEF(ppi)->clockQuality.clockClass = PP_PTP_CLASS_GM_UNLOCKED;
bmc_m1(ppi);
break;
......@@ -182,7 +182,7 @@ int wrc_ptp_set_mode(int mode)
/* If we can't lock to the atomic/gps, we say it in the class */
if (error && mode == WRC_MODE_GM)
*class_ptr = PP_CLASS_WR_GM_UNLOCKED;
*class_ptr = PP_PTP_CLASS_GM_UNLOCKED;
ptp_mode = mode;
return error;
......
......@@ -28,21 +28,30 @@
#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
#define PP_DEFAULT_UTC_OFFSET 37
/* Clock classes (pag 55, PTP-2008). See ppsi-manual for an explanation */
#define PP_CLASS_SLAVE_ONLY 255
#define PP_CLASS_DEFAULT 187
#define PP_CLASS_WR_GM_LOCKED 6
#define PP_CLASS_WR_GM_UNLOCKED 52
#define PP_CLASS_DEFAULT 248
#define PP_PTP_CLASS_GM_LOCKED 6
#define PP_PTP_CLASS_GM_HOLDOVER 7
#define PP_PTP_CLASS_GM_UNLOCKED 52
#define PP_ARB_CLASS_GM_LOCKED 13
#define PP_ARB_CLASS_GM_HOLDOVER 14
#define PP_ARB_CLASS_GM_UNLOCKED 58
#define PP_DEFAULT_CLOCK_ACCURACY 0xFE
#define PP_DEFAULT_PRIORITY1 128
#define PP_DEFAULT_PRIORITY2 128
#define PP_DEFAULT_CLOCK_VARIANCE 0x8000 /* FIXME shall be set to
* 0xFFFF once getting calculated,
* defining it is not yet calculated
*/
* 0xFFFF once getting calculated,
* defining it is not yet calculated
*/
#define PP_SERVO_UNKNOWN 0
#define PP_SERVO_LOCKED 1
#define PP_SERVO_HOLDOVER 2
#define PP_SERVO_UNLOCKED 3
#define PP_NR_FOREIGN_RECORDS 5
#define PP_FOREIGN_MASTER_TIME_WINDOW 4
......
......@@ -200,7 +200,6 @@ typedef struct DSDefault { /* page 65 */
UInteger8 priority2;
UInteger8 domainNumber;
Boolean slaveOnly;
unsigned long ext_specific; /* used by extension */
} DSDefault;
/* Current Data Set */
......
......@@ -206,6 +206,7 @@ struct pp_time_operations {
int (*adjust_offset)(struct pp_instance *ppi, long offset_ns);
int (*adjust_freq)(struct pp_instance *ppi, long freq_ppb);
int (*init_servo)(struct pp_instance *ppi);
int (*get_servo_state)(struct pp_instance *ppi, int *state);
unsigned long (*calc_timeout)(struct pp_instance *ppi, int millisec);
};
......
......@@ -40,11 +40,7 @@ static int wr_open(struct pp_globals *ppg, struct pp_runtime_opts *rt_opts)
/* FIXME check if correct: assign to each instance the same
* wr_data. May I move it to pp_globals? */
INST(ppg, i)->ext_data = ppg->global_ext_data;
/* store clock class */
DSDEF(INST(ppg, i))->ext_specific =
DSDEF(INST(ppg, i))->clockQuality.clockClass;
INST(ppg, i)->ext_data = ppg->global_ext_data;
if (ppi->cfg.ext == PPSI_EXT_WR) {
switch (ppi->role) {
case PPSI_ROLE_MASTER:
......@@ -302,10 +298,6 @@ static int wr_state_decision(struct pp_instance *ppi, int next_state)
static void wr_state_change(struct pp_instance *ppi)
{
int i;
int nr_of_ports = 0;
int is_gm = 1;
struct pp_globals *ppg = GLBS(ppi);
struct wr_dsport *wrp = WR_DSPOR(ppi);
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
......@@ -335,28 +327,6 @@ static void wr_state_change(struct pp_instance *ppi)
if (ppi->state == PPS_SLAVE)
wrp->ops->locking_reset(ppi);
if (DSDEF(ppi)->clockQuality.clockClass <= 127) {
if (ppi->state == PPS_MASTER) {
if (DSDEF(ppi)->numberPorts > 1) {
for (i = 0; i < ppg->defaultDS->numberPorts; i++) {
if (INST(ppg, i)->link_up == TRUE) {
nr_of_ports++;
if (INST(ppg, i)->state != PPS_MASTER)
is_gm = 0;
}
}
} else
nr_of_ports = 1;
/* if we change the state reset the clock class if we are not GM anymore */
if ((!is_gm) || (nr_of_ports == 0) ||
(DSDEF(ppi)->numberPorts == 1))
DSDEF(ppi)->clockQuality.clockClass =
DSDEF(ppi)->ext_specific;
}
}
}
}
......
......@@ -11,7 +11,7 @@
/* Please increment WRS_PPSI_SHMEM_VERSION if you change any exported data
* structure */
#define WRS_PPSI_SHMEM_VERSION 28 /* added extension to default dataset */
#define WRS_PPSI_SHMEM_VERSION 29 /* added get_servo_state to time ops */
/* Don't include the Following when this file is included in assembler. */
#ifndef __ASSEMBLY__
......
......@@ -56,48 +56,10 @@ static inline UInteger16 get_be16(void *ptr)
void msg_pack_announce_wr_tlv(struct pp_instance *ppi)
{
void *buf;
int i;
UInteger16 wr_flags = 0;
int locked, class = DSDEF(ppi)->clockQuality.clockClass;
struct wr_dsport *wrp = WR_DSPOR(ppi);
struct pp_globals *ppg = GLBS(ppi);
int is_gm = 1;
buf = ppi->tx_ptp;
/* GM: update clock Class, according to whether we are locked or not
* but only for grandmaster clocks in specific clocks that can anyhow
* be only master
*/
if (class <= 127) {
if (DSDEF(ppi)->numberPorts > 1) {
for (i = 0; i < ppg->defaultDS->numberPorts; i++) {
if ((INST(ppg, i)->link_up == TRUE) &&
(INST(ppg, i)->state != PPS_MASTER))
is_gm = 0;
}
}
if (is_gm) {
locked = wrp->ops->locking_poll(ppi, 1);
if (locked == WR_SPLL_READY)
class = PP_CLASS_WR_GM_LOCKED;
else
class = PP_CLASS_WR_GM_UNLOCKED;
bmc_m1(ppi);
if (class != DSDEF(ppi)->clockQuality.clockClass) {
pp_error("New class %i\n", class);
DSDEF(ppi)->clockQuality.clockClass = class;
*(UInteger8 *) (buf + 48) = class;
if (DSDEF(ppi)->numberPorts > 1)
pp_error("Configuring GM clock class while in BC mode\n");
}
}
}
/* Change length */
*(UInteger16 *)(buf + 2) = htons(WR_ANNOUNCE_LENGTH);
......
......@@ -1105,6 +1105,107 @@ static void bmc_update_ebest(struct pp_globals *ppg)
}
}
static void bmc_update_clock_quality(struct pp_instance *ppi)
{
struct pp_globals *ppg = GLBS(ppi);
struct pp_runtime_opts *rt_opts = ppi->glbs->rt_opts;
int ret = 0;
int state;
if (rt_opts->clock_quality.clockClass < 128) {
if ((rt_opts->clock_quality.clockClass == PP_PTP_CLASS_GM_LOCKED) ||
(rt_opts->clock_quality.clockClass == PP_ARB_CLASS_GM_LOCKED)) {
pp_diag(ppi, bmc, 2,
"GM locked class configured, checking servo state\n");
} else if ((rt_opts->clock_quality.clockClass == PP_PTP_CLASS_GM_UNLOCKED) ||
(rt_opts->clock_quality.clockClass == PP_ARB_CLASS_GM_UNLOCKED)) {
pp_diag(ppi, bmc, 2,
"GM unlocked class configured, skipping checking servo state\n");
return;
} else {
pp_diag(ppi, bmc, 2,
" GM unknown clock class configured, skipping checking servo state\n");
return;
}
ret = ppi->t_ops->get_servo_state(ppi, &state);
if (ret) {
pp_diag(ppi, bmc, 1,
"Could not get servo state, taking old clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
return;
}
switch (state) {
case PP_SERVO_LOCKED:
if (rt_opts->clock_quality.clockClass == PP_PTP_CLASS_GM_LOCKED) {
if (ppg->defaultDS->clockQuality.clockClass != PP_PTP_CLASS_GM_LOCKED) {
ppg->defaultDS->clockQuality.clockClass = PP_PTP_CLASS_GM_LOCKED;
pp_diag(ppi, bmc, 1,
"Servo locked, new clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
}
} else if (rt_opts->clock_quality.clockClass == PP_ARB_CLASS_GM_LOCKED) {
if (ppg->defaultDS->clockQuality.clockClass != PP_ARB_CLASS_GM_LOCKED) {
ppg->defaultDS->clockQuality.clockClass = PP_ARB_CLASS_GM_LOCKED;
pp_diag(ppi, bmc, 1,
"Servo locked, new clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
}
}
break;
case PP_SERVO_HOLDOVER:
if (rt_opts->clock_quality.clockClass == PP_PTP_CLASS_GM_LOCKED) {
if (ppg->defaultDS->clockQuality.clockClass != PP_PTP_CLASS_GM_HOLDOVER) {
ppg->defaultDS->clockQuality.clockClass = PP_PTP_CLASS_GM_HOLDOVER;
pp_diag(ppi, bmc, 1,
"Servo in holdover, new clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
}
} else if (rt_opts->clock_quality.clockClass == PP_ARB_CLASS_GM_LOCKED) {
if (ppg->defaultDS->clockQuality.clockClass != PP_ARB_CLASS_GM_HOLDOVER) {
ppg->defaultDS->clockQuality.clockClass = PP_ARB_CLASS_GM_HOLDOVER;
pp_diag(ppi, bmc, 1,
"Servo in holdover, new clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
}
}
break;
case PP_SERVO_UNLOCKED:
if (rt_opts->clock_quality.clockClass == PP_PTP_CLASS_GM_LOCKED) {
if (ppg->defaultDS->clockQuality.clockClass != PP_PTP_CLASS_GM_UNLOCKED) {
ppg->defaultDS->clockQuality.clockClass = PP_PTP_CLASS_GM_UNLOCKED;
pp_diag(ppi, bmc, 1,
"Servo unlocked, new clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
}
} else if (rt_opts->clock_quality.clockClass == PP_ARB_CLASS_GM_LOCKED) {
if (ppg->defaultDS->clockQuality.clockClass != PP_ARB_CLASS_GM_UNLOCKED) {
ppg->defaultDS->clockQuality.clockClass = PP_ARB_CLASS_GM_UNLOCKED;
pp_diag(ppi, bmc, 1,
"Servo unlocked, new clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
}
}
break;
case PP_SERVO_UNKNOWN:
default:
pp_diag(ppi, bmc, 2,
"Unknown servo state, taking old clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
break;
}
}
}
int bmc(struct pp_instance *ppi)
{
struct pp_globals *ppg = GLBS(ppi);
......@@ -1113,6 +1214,9 @@ int bmc(struct pp_instance *ppi)
/* bmc is called several times, so report only at level 2 */
pp_diag(ppi, bmc, 2, "%s\n", __func__);
/* check if we shall update the clock qualities */
bmc_update_clock_quality(ppi);
/* Age table only based on timeouts*/
if (pp_timeout(ppi, PP_TO_BMC)) {
......
......@@ -36,6 +36,12 @@ static int bare_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *l
}
}
static int bare_time_get_servo_state(struct pp_instance *ppi, int *state)
{
*state = PP_SERVO_UNKNOWN;
return 0;
}
static int bare_time_get(struct pp_instance *ppi, struct pp_time *t)
{
struct bare_timeval tv;
......@@ -129,6 +135,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_servo_state = bare_time_get_servo_state,
.get = bare_time_get,
.set = bare_time_set,
.adjust = bare_time_adjust,
......
......@@ -55,6 +55,12 @@ static int sim_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *le
return -1;
}
static int sim_time_get_servo_state(struct pp_instance *ppi, int *state)
{
*state = PP_SERVO_UNKNOWN;
return 0;
}
static int sim_time_get(struct pp_instance *ppi, struct pp_time *t)
{
t->scaled_nsecs = (SIM_PPI_ARCH(ppi)->time.current_ns %
......@@ -122,6 +128,7 @@ static unsigned long sim_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations sim_time_ops = {
.get_servo_state = sim_time_get_servo_state,
.get_utc_offset = sim_time_get_utc_offset,
.get = sim_time_get,
.set = sim_time_set,
......
......@@ -56,6 +56,12 @@ static int unix_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *l
}
}
static int unix_time_get_servo_state(struct pp_instance *ppi, int *state)
{
*state = PP_SERVO_UNKNOWN;
return 0;
}
static int unix_time_get(struct pp_instance *ppi, struct pp_time *t)
{
struct timespec tp;
......@@ -157,6 +163,7 @@ static unsigned long unix_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations unix_time_ops = {
.get_servo_state = unix_time_get_servo_state,
.get_utc_offset = unix_time_get_utc_offset,
.get = unix_time_get,
.set = unix_time_set,
......
......@@ -18,6 +18,19 @@ static int wrpc_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *l
return -1;
}
static int wrpc_time_get_servo_state(struct pp_instance *ppi, int *state)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
int locked;
locked = wrp->ops->locking_poll(ppi, 1);
if (locked == WR_SPLL_READY)
*state = PP_SERVO_LOCKED;
else
*state = PP_SERVO_UNLOCKED;
return 0;
}
static int wrpc_time_get(struct pp_instance *ppi, struct pp_time *t)
{
uint64_t sec;
......@@ -74,6 +87,7 @@ static unsigned long wrpc_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations wrpc_time_ops = {
.get_servo_state = wrpc_time_get_servo_state,
.get_utc_offset = wrpc_time_get_utc_offset,
.get = wrpc_time_get,
.set = wrpc_time_set,
......
......@@ -235,6 +235,19 @@ static int wrs_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *le
}
}
static int wrs_time_get_servo_state(struct pp_instance *ppi, int *state)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
int locked;
locked = wrp->ops->locking_poll(ppi, 1);
if (locked == WR_SPLL_READY)
*state = PP_SERVO_LOCKED;
else
*state = PP_SERVO_UNLOCKED;
return 0;
}
/* 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)
{
......@@ -419,6 +432,7 @@ static unsigned long wrs_calc_timeout(struct pp_instance *ppi,
}
struct pp_time_operations wrs_time_ops = {
.get_servo_state = wrs_time_get_servo_state,
.get_utc_offset = wrs_time_get_utc_offset,
.get = wrs_time_get,
.set = wrs_time_set,
......
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