Add support for testing the new PTP_SYS_OFFSET_EXTENDED_ATTRS and
PTP_SYS_OFFSET_PRECISE_ATTRS ioctls in the testptp utility.

Add a "-a" modifier that requests clock quality attributes
(error_bound, status, timescale) alongside the existing extended (-x)
and precise (-X) offset requests:
  -x N -a: extended offset with attributes (N samples)
  -X -a:   precise cross-timestamp with attributes

When the device does not report a given attribute, print an explicit
"not reported" line so all attributes are always accounted for.

Also print the system counter value and its identifier (sys_counter,
sys_counter_id) returned in struct ptp_sys_time, so the counter source
is visible; a sys_counter_id of 0 (UNKNOWN) with sys_counter 0 indicates
an unavailable or unidentified counter source.

These options allow testing and validation of PHC devices that provide
clock quality information alongside timestamps.

Also display the new extended_attrs/precise_attrs capabilities in the -c
output, and update print_system_timestamp to print unrecognized clock
types instead of silently dropping them.

Co-developed-by: Amit Bernstein <[email protected]>
Signed-off-by: Amit Bernstein <[email protected]>
Signed-off-by: Arthur Kiyanovski <[email protected]>
---
 tools/testing/selftests/ptp/testptp.c | 124 +++++++++++++++++++++++++-
 1 file changed, 120 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/ptp/testptp.c 
b/tools/testing/selftests/ptp/testptp.c
index d603d9f82237..62b1d0340d71 100644
--- a/tools/testing/selftests/ptp/testptp.c
+++ b/tools/testing/selftests/ptp/testptp.c
@@ -148,6 +148,8 @@ static void usage(char *progname)
                " -T val     set the ptp clock time to 'val' seconds\n"
                " -x val     get an extended ptp clock time with the desired 
number of samples (up to %d)\n"
                " -X         get a ptp clock cross timestamp\n"
+               " -a         also report clock quality attributes 
(error_bound,\n"
+               "            status, timescale); use together with -x or -X\n"
                " -y val     pre/post tstamp timebase to use 
{realtime|monotonic|monotonic-raw}\n"
                " -z         test combinations of rising/falling external time 
stamp flags\n",
                progname, PTP_MAX_SAMPLES);
@@ -174,8 +176,10 @@ static void print_system_timestamp(int sample_num, 
__kernel_clockid_t clockid,
                break;
        }
 
-       if (!name)
+       if (!name) {
+               printf("sample #%2d: unknown clock %d\n", sample_num, clockid);
                return;
+       }
 
        printf("sample #%2d: %s time %s: %lld.%09u\n",
               sample_num, name, when, sec, nsec);
@@ -194,6 +198,7 @@ int main(int argc, char *argv[])
        struct ptp_sys_offset *sysoff;
        struct ptp_sys_offset_extended *soe;
        struct ptp_sys_offset_precise *xts;
+       struct ptp_sys_offset_attrs *attrs_data;
 
        char *progname;
        unsigned int i;
@@ -215,6 +220,7 @@ int main(int argc, char *argv[])
        int pct_offset = 0;
        int getextended = 0;
        int getcross = 0;
+       int use_attrs = 0;
        int n_samples = 0;
        int pin_index = -1, pin_func;
        int pps = -1;
@@ -232,7 +238,8 @@ int main(int argc, char *argv[])
 
        progname = strrchr(argv[0], '/');
        progname = progname ? 1+progname : argv[0];
-       while (EOF != (c = getopt(argc, argv, 
"cd:e:E:f:F:ghH:i:k:lL:n:o:p:P:rsSt:T:w:x:Xy:z"))) {
+       while (EOF != (c = getopt(argc, argv,
+                                 
"acd:e:E:f:F:ghH:i:k:lL:n:o:p:P:rsSt:T:w:x:Xy:z"))) {
                switch (c) {
                case 'c':
                        capabilities = 1;
@@ -317,6 +324,9 @@ int main(int argc, char *argv[])
                                return -1;
                        }
                        break;
+               case 'a':
+                       use_attrs = 1;
+                       break;
                case 'X':
                        getcross = 1;
                        break;
@@ -373,6 +383,8 @@ int main(int argc, char *argv[])
                               "  %d programmable pins\n"
                               "  %d cross timestamping\n"
                               "  %d adjust_phase\n"
+                              "  %d extended_attrs\n"
+                              "  %d precise_attrs\n"
                               "  %d maximum phase adjustment (ns)\n",
                               caps.max_adj,
                               caps.n_alarm,
@@ -382,6 +394,8 @@ int main(int argc, char *argv[])
                               caps.n_pins,
                               caps.cross_timestamping,
                               caps.adjust_phase,
+                              caps.extended_attrs,
+                              caps.precise_attrs,
                               caps.max_phase_adj);
                }
        }
@@ -619,7 +633,7 @@ int main(int argc, char *argv[])
                free(sysoff);
        }
 
-       if (getextended) {
+       if (getextended && !use_attrs) {
                soe = calloc(1, sizeof(*soe));
                if (!soe) {
                        perror("calloc");
@@ -654,7 +668,60 @@ int main(int argc, char *argv[])
                free(soe);
        }
 
-       if (getcross) {
+       if (getextended && use_attrs) {
+               attrs_data = calloc(1, sizeof(*attrs_data) +
+                                   getextended * sizeof(struct ptp_timestamp));
+               if (!attrs_data) {
+                       perror("calloc");
+                       return -1;
+               }
+
+               attrs_data->request.num_samples = getextended;
+               attrs_data->request.clock_id = ext_clockid;
+
+               if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED_ATTRS, attrs_data)) {
+                       perror("PTP_SYS_OFFSET_EXTENDED_ATTRS");
+               } else {
+                       printf("extended attrs timestamp request returned %d 
samples\n",
+                              getextended);
+
+                       for (i = 0; i < getextended; i++) {
+                               struct ptp_timestamp *ts = 
&attrs_data->timestamps[i];
+
+                               printf("  sample #%u:\n", i);
+                               printf("    sys before: %lld ns\n",
+                                      (long long)ts->pre_systime.sys_time);
+                               printf("    sys_counter_id: %u\n",
+                                      ts->pre_systime.sys_counter_id);
+                               printf("    sys_counter:    %llu\n",
+                                      (unsigned long 
long)ts->pre_systime.sys_counter);
+                               printf("    phc time:   %lld.%09u\n",
+                                      ts->devtime.device_time.sec,
+                                      ts->devtime.device_time.nsec);
+                               if (ts->devtime.attrs.valid & 
PTP_ATTRS_VALID_ERROR_BOUND)
+                                       printf("    error_bound: %u ns\n",
+                                              ts->devtime.attrs.error_bound);
+                               else
+                                       printf("    error_bound: not 
reported\n");
+                               if (ts->devtime.attrs.valid & 
PTP_ATTRS_VALID_STATUS)
+                                       printf("    status: %u\n",
+                                              ts->devtime.attrs.status);
+                               else
+                                       printf("    status: not reported\n");
+                               if (ts->devtime.attrs.valid & 
PTP_ATTRS_VALID_TIMESCALE)
+                                       printf("    timescale: %u\n",
+                                              ts->devtime.attrs.timescale);
+                               else
+                                       printf("    timescale: not reported\n");
+                               printf("    sys after:  %lld ns\n",
+                                      (long long)ts->post_systime.sys_time);
+                       }
+               }
+
+               free(attrs_data);
+       }
+
+       if (getcross && !use_attrs) {
                xts = calloc(1, sizeof(*xts));
                if (!xts) {
                        perror("calloc");
@@ -677,6 +744,55 @@ int main(int argc, char *argv[])
                free(xts);
        }
 
+       if (getcross && use_attrs) {
+               attrs_data = calloc(1, sizeof(*attrs_data) +
+                                   sizeof(struct ptp_timestamp));
+               if (!attrs_data) {
+                       perror("calloc");
+                       return -1;
+               }
+
+               attrs_data->request.num_samples = 1;
+               /* precise crosstimestamp supports only CLOCK_REALTIME/AUX */
+               attrs_data->request.clock_id = CLOCK_REALTIME;
+
+               if (ioctl(fd, PTP_SYS_OFFSET_PRECISE_ATTRS, attrs_data)) {
+                       perror("PTP_SYS_OFFSET_PRECISE_ATTRS");
+               } else {
+                       struct ptp_timestamp *ts = &attrs_data->timestamps[0];
+
+                       puts("precise attrs crosstimestamp request okay");
+                       printf("device time: %lld.%09u\n",
+                              ts->devtime.device_time.sec,
+                              ts->devtime.device_time.nsec);
+                       printf("system time: %lld ns\n",
+                              (long long)ts->systime.sys_time);
+                       printf("raw time:    %lld ns\n",
+                              (long long)ts->systime.sys_rawtime);
+                       printf("sys_counter_id: %u\n",
+                              ts->systime.sys_counter_id);
+                       printf("sys_counter:    %llu\n",
+                              (unsigned long long)ts->systime.sys_counter);
+                       if (ts->devtime.attrs.valid & 
PTP_ATTRS_VALID_ERROR_BOUND)
+                               printf("error_bound: %u ns\n",
+                                      ts->devtime.attrs.error_bound);
+                       else
+                               printf("error_bound: not reported\n");
+                       if (ts->devtime.attrs.valid & PTP_ATTRS_VALID_STATUS)
+                               printf("status: %u\n",
+                                      ts->devtime.attrs.status);
+                       else
+                               printf("status: not reported\n");
+                       if (ts->devtime.attrs.valid & PTP_ATTRS_VALID_TIMESCALE)
+                               printf("timescale: %u\n",
+                                      ts->devtime.attrs.timescale);
+                       else
+                               printf("timescale: not reported\n");
+               }
+
+               free(attrs_data);
+       }
+
        if (channel >= 0) {
                if (ioctl(fd, PTP_MASK_CLEAR_ALL)) {
                        perror("PTP_MASK_CLEAR_ALL");
-- 
2.47.3


Reply via email to