[Linuxptp-devel] [PATCH 1/2] phc_ctl: display all capability information

2019-09-26 Thread Jacob Keller
The capability command for phc_ctl does not display the number of pins
or the cross timestamping support. Add this as output so that the user
can see the complete device capabilities.

Signed-off-by: Jacob Keller 
---
 phc_ctl.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/phc_ctl.c b/phc_ctl.c
index e55af593471a..5a01e9d69b0f 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -320,12 +320,16 @@ static int do_caps(clockid_t clkid, int cmdc, char 
*cmdv[])
"  %d programable alarms\n"
"  %d external time stamp channels\n"
"  %d programmable periodic signals\n"
-   "  %s pulse per second support",
+   "  %d configurable input/output pins\n"
+   "  %s pulse per second support\n"
+   "  %s cross timestamping support\n",
caps.max_adj,
caps.n_alarm,
caps.n_ext_ts,
caps.n_per_out,
-   caps.pps ? "has" : "doesn't have");
+   caps.n_pins,
+   caps.pps ? "has" : "doesn't have",
+   caps.cross_timestamping ? "has" : "doesn't have");
return 0;
 }
 
-- 
2.23.0.245.gf157bbb9169d



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 0/2] additions to phc_ctl

2019-09-26 Thread Jacob Keller
This series provides a couple of updates to the phc_ctl utility. First, we
display additional capabillity information such as the cross timestamping
support as well as the number of pins.

The second patch adds a new  command, "pin_cfg", which will query the pin
configuration for all of the supported pins. Suggestions on how to format
this this output is appreciated. I would almost think it's better to combine the
printing into a single pr_* buffer.. but the only way I can think to do that
would be using a local buffer to build up the longer string.

Jacob Keller (2):
  phc_ctl: display all capability information
  phc_ctl: add pin_cfg command to display pin functions

 phc_ctl.c | 81 +--
 1 file changed, 79 insertions(+), 2 deletions(-)

-- 
2.23.0.245.gf157bbb9169d



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 2/2] phc_ctl: add pin_cfg command to display pin functions

2019-09-26 Thread Jacob Keller
Add a new function to phc_ctl to display the devices pin configuration
data. First, obtain the device capabilities to determine the number of
pins. Then, for each pin, print the name, function, and channel
information.

Signed-off-by: Jacob Keller 
---
 phc_ctl.c | 73 +++
 1 file changed, 73 insertions(+)

diff --git a/phc_ctl.c b/phc_ctl.c
index 5a01e9d69b0f..a619d9203472 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -134,6 +134,7 @@ static void usage(const char *progname)
"  freq [ppb]  adjust PHC frequency (default returns 
current offset)\n"
"  cmp compare PHC offset to CLOCK_REALTIME\n"
"  capsdisplay device capabilities (default if no 
command given)\n"
+   "  pin_cfg display device pin configuration\n"
"  wait   pause between commands\n"
"\n",
progname);
@@ -333,6 +334,77 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
return 0;
 }
 
+static const char *pin_func_string(unsigned int func)
+{
+   switch (func) {
+   case PTP_PF_NONE:
+   return "no function";
+   case PTP_PF_EXTTS:
+   return "external timestamping";
+   case PTP_PF_PEROUT:
+   return "periodic output";
+   case PTP_PF_PHYSYNC:
+   return "phy sync";
+   default:
+   return "unknown function";
+   }
+}
+
+static int do_pin_cfg(clockid_t clkid, int cmdc, char *cmdv[])
+{
+   struct ptp_clock_caps caps;
+   struct ptp_pin_desc pin_desc;
+   unsigned int index;
+
+   if (clkid == CLOCK_REALTIME) {
+   pr_warning("CLOCK_REALTIME is not a PHC device.");
+   return 0;
+   }
+
+   /* Get device capabilities first */
+   if (ioctl(CLOCKID_TO_FD(clkid), PTP_CLOCK_GETCAPS, )) {
+   pr_err("get capabilities failed: %s",
+   strerror(errno));
+   return -1;
+   }
+
+   if (caps.n_pins == 0) {
+   pr_notice("device has no configurable pins");
+   return (0);
+   }
+
+   pr_notice("device has %d configurable input/output pins",
+   caps.n_pins);
+
+   /* For each pin, read its configuration */
+   for (index = 0; index < caps.n_pins; index++) {
+   memset(_desc, 0, sizeof(pin_desc));
+   pin_desc.index = index;
+
+   if (ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_GETFUNC, _desc)) {
+   pr_warning("get pin configuration for pin %d failed: 
%s",
+   index,
+   strerror(errno));
+   /* keep going */
+   continue;
+   }
+
+   if (pin_desc.func == PTP_PF_NONE) {
+   pr_notice("pin %d [%s] is not configured",
+   pin_desc.index,
+   pin_desc.name);
+   } else {
+   pr_notice("pin %d [%s] performing %s using channel %d",
+   pin_desc.index,
+   pin_desc.name,
+   pin_func_string(pin_desc.func),
+   pin_desc.chan);
+   }
+   }
+
+   return 0;
+}
+
 static int do_cmp(clockid_t clkid, int cmdc, char *cmdv[])
 {
struct timespec ts, rta, rtb;
@@ -418,6 +490,7 @@ static const struct cmd_t all_commands[] = {
{ "freq", _freq },
{ "cmp", _cmp },
{ "caps", _caps },
+   { "pin_cfg", _pin_cfg },
{ "wait", _wait },
{ 0, 0 }
 };
-- 
2.23.0.245.gf157bbb9169d



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [Linuxptp-users] How do I implement Sync message receive timeout according to Automotive and 802.1 AS profiles?

2019-09-26 Thread Erik Hons


Hi Yangbo,

> > > May I have your suggestion here? To maintain gPTP time in software, 
> > > I just copied kernel timecounter code into linuxptp for usage.
> > 
> > Why?  That sounds wrong.
>
> Regarding to physical clock adjustment, that's confusing. This will changes
> neighbor rate ratio frequently, so the cumulative rate ratio and corrected 
> residence time/path delay in follow_up and TLV will be not correct for the
> receiver.

I have some experience with this. With appropriate filtering and servo 
implementation, the necessary PHC adjustments do not introduce instability. The 
worst case synchronization error will scale with the number of bridges, and the 
offset will oscillate slowly, but the error does not "whip crack" to large 
unpredictable errors.

Whether that's acceptable for your application is up to you. But you *can* 
build a system with a deep clock tree that stays within a narrow 
synchronization band while adjusting PHCs on all the bridges.

As Richard mentioned in the other thread, you must do this if you are building 
systems that use Qbv queuing. You do not need to do it if your system requires 
end-station time synchronization only.



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 2/3] port: Avoid calling freed servo after switching PHC.

2019-09-26 Thread Miroslav Lichvar
In port_synchronize(), when the clock returned SERVO_UNLOCKED and
port_dispatch() triggered a switch of the PHC, the variable "s" would
point to a servo which was already freed and the following call of
servo_offset_threshold() would read invalid memory.

Don't save the servo before dispatching the port.

Signed-off-by: Miroslav Lichvar 
Fixes: 3f5f5653d796 ("port: Add interval update mechanism.")
---
 port.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/port.c b/port.c
index d051403..add5205 100644
--- a/port.c
+++ b/port.c
@@ -1137,7 +1137,6 @@ static void port_synchronize(struct port *p,
 {
enum servo_state state, last_state;
tmv_t t1, t1c, t2, c1, c2;
-   struct servo *s;
 
port_set_sync_rx_tmo(p);
 
@@ -1147,13 +1146,12 @@ static void port_synchronize(struct port *p,
c2 = correction_to_tmv(correction2);
t1c = tmv_add(t1, tmv_add(c1, c2));
 
-   s = clock_servo(p->clock);
last_state = clock_servo_state(p->clock);
state = clock_synchronize(p->clock, t2, t1c);
switch (state) {
case SERVO_UNLOCKED:
port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0);
-   if (servo_offset_threshold(s) != 0 &&
+   if (servo_offset_threshold(clock_servo(p->clock)) != 0 &&
sync_interval != p->initialLogSyncInterval) {
p->logPdelayReqInterval = p->logMinPdelayReqInterval;
p->logSyncInterval = p->initialLogSyncInterval;
@@ -1186,7 +1184,7 @@ static void port_synchronize(struct port *p,
 * The most likely reason for this to happen is the
 * master daemon re-initialized due to some fault.
 */
-   servo_reset(s);
+   servo_reset(clock_servo(p->clock));
port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0);
}
break;
-- 
2.21.0



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 1/3] port: Don't leak transport when unicast initialization fails.

2019-09-26 Thread Miroslav Lichvar
Signed-off-by: Miroslav Lichvar 
---
 port.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/port.c b/port.c
index 07ad3f0..d051403 100644
--- a/port.c
+++ b/port.c
@@ -3036,14 +3036,14 @@ struct port *port_open(int phc_index,
p->versionNumber = PTP_VERSION;
 
if (number && unicast_client_claim_table(p)) {
-   goto err_port;
+   goto err_transport;
}
if (unicast_client_enabled(p) &&
config_set_section_int(cfg, p->name, "hybrid_e2e", 1)) {
-   goto err_port;
+   goto err_transport;
}
if (number && unicast_service_initialize(p)) {
-   goto err_port;
+   goto err_transport;
}
p->hybrid_e2e = config_get_int(cfg, p->name, "hybrid_e2e");
 
-- 
2.21.0



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 0/3] Port fixes and sharing unicast master table

2019-09-26 Thread Miroslav Lichvar
The first two patches fix bugs I came across when developing and testing
the third patch, but are not really related to it.

The third patch allows a unicast master table in the config to be used
by multiple ports, which should simplify ptp4l configuration in some
cases and make it usable with timemaster.

Miroslav Lichvar (3):
  port: Don't leak transport when unicast initialization fails.
  port: Avoid calling freed servo after switching PHC.
  unicast: Enable sharing master tables between ports.

 port.c   | 15 ++---
 ptp4l.8  |  4 +---
 unicast_client.c | 55 
 unicast_client.h |  8 ++-
 4 files changed, 66 insertions(+), 16 deletions(-)

-- 
2.21.0



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 3/3] unicast: Enable sharing master tables between ports.

2019-09-26 Thread Miroslav Lichvar
Don't require each port to have its own master table specified in the
config. Instead of ports claming configured tables, clone the table in
each port, so different ports don't interfere with each other.

Signed-off-by: Miroslav Lichvar 
---
 port.c   |  3 ++-
 ptp4l.8  |  4 +---
 unicast_client.c | 55 
 unicast_client.h |  8 ++-
 4 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/port.c b/port.c
index add5205..202c088 100644
--- a/port.c
+++ b/port.c
@@ -2311,6 +2311,7 @@ void port_close(struct port *p)
rtnl_close(p->fda.fd[FD_RTNL]);
}
 
+   unicast_client_cleanup(p);
unicast_service_cleanup(p);
transport_destroy(p->trp);
tsproc_destroy(p->tsproc);
@@ -3033,7 +3034,7 @@ struct port *port_open(int phc_index,
p->delayMechanism = config_get_int(cfg, p->name, "delay_mechanism");
p->versionNumber = PTP_VERSION;
 
-   if (number && unicast_client_claim_table(p)) {
+   if (number && unicast_client_initialize(p)) {
goto err_transport;
}
if (unicast_client_enabled(p) &&
diff --git a/ptp4l.8 b/ptp4l.8
index 9890839..d1db27a 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -282,9 +282,7 @@ using the default announce and sync intervals.
 When set to a positive integer, this option specifies the table id to
 be used for unicast discovery.  Each table lives in its own section
 and has a unique, positive numerical ID.  Entries in the table are a
-pair of transport type and protocol address.  Tables may not be shared
-between ports, but nothing prevents table entries from appearing in
-more than table.
+pair of transport type and protocol address.
 The default is 0 (unicast discovery disabled).
 .TP
 .B unicast_req_duration
diff --git a/unicast_client.c b/unicast_client.c
index 6495d6f..f41e59b 100644
--- a/unicast_client.c
+++ b/unicast_client.c
@@ -17,6 +17,8 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
  */
+#include 
+
 #include "port.h"
 #include "port_private.h"
 #include "print.h"
@@ -250,6 +252,45 @@ out:
return err;
 }
 
+static void free_master_table(struct unicast_master_table *table)
+{
+   struct unicast_master_address *address;
+
+   while ((address = STAILQ_FIRST(>addrs))) {
+   STAILQ_REMOVE_HEAD(>addrs, list);
+   free(address);
+   }
+   free(table->peer_name);
+   free(table);
+}
+
+static struct unicast_master_table *
+clone_master_table(struct unicast_master_table *table)
+{
+   struct unicast_master_address *address, *cloned_address;
+   struct unicast_master_table *cloned_table;
+
+   cloned_table = malloc(sizeof(*cloned_table));
+   if (!cloned_table)
+   return NULL;
+   *cloned_table = *table;
+   STAILQ_INIT(_table->addrs);
+   memset(_table->list, 0, sizeof(cloned_table->list));
+   if (table->peer_name)
+   cloned_table->peer_name = strdup(table->peer_name);
+
+   STAILQ_FOREACH(address, >addrs, list) {
+   cloned_address = malloc(sizeof(*cloned_address));
+   if (!cloned_address) {
+   free_master_table(cloned_table);
+   return NULL;
+   }
+   *cloned_address = *address;
+   STAILQ_INSERT_TAIL(_table->addrs, cloned_address, list);
+   }
+   return cloned_table;
+}
+
 /* public methods */
 
 int unicast_client_cancel(struct port *p, struct ptp_message *m,
@@ -302,7 +343,7 @@ out:
return err;
 }
 
-int unicast_client_claim_table(struct port *p)
+int unicast_client_initialize(struct port *p)
 {
struct unicast_master_address *master, *peer;
struct config *cfg = clock_config(p->clock);
@@ -322,9 +363,9 @@ int unicast_client_claim_table(struct port *p)
pr_err("port %d: no table with id %d", portnum(p), table_id);
return -1;
}
-   if (table->port) {
-   pr_err("port %d: table %d already claimed by port %d",
-  portnum(p), table_id, table->port);
+   table = clone_master_table(table);
+   if (!table) {
+   pr_err("low memory");
return -1;
}
peer = >peer_addr;
@@ -352,6 +393,12 @@ int unicast_client_claim_table(struct port *p)
return 0;
 }
 
+void unicast_client_cleanup(struct port *p)
+{
+   if (p->unicast_master_table)
+   free_master_table(p->unicast_master_table);
+}
+
 int unicast_client_enabled(struct port *p)
 {
return p->unicast_master_table ? 1 : 0;
diff --git a/unicast_client.h b/unicast_client.h
index fc8dc6f..16e291f 100644
--- a/unicast_client.h
+++ b/unicast_client.h
@@ -37,7 +37,13 @@ int unicast_client_cancel(struct port *p, struct ptp_message 
*m,
  * @param port   The port in question.
  * @return   Zero on