Skip to content

Commit

Permalink
Added support for opening POSIX clock devices
Browse files Browse the repository at this point in the history
I have reduced the requirements for the -p option to accept
any type of device. With this it should be possible to use
ptp4l to syncronize any clock device that implements the kernel
POSIX clock interface.

[ RC - Initialize struct timex. ]

Signed-off-by: Dimitrios Katsaros <[email protected]>
Signed-off-by: Richard Cochran <[email protected]>
  • Loading branch information
DmtKats authored and richardcochran committed Jan 7, 2019
1 parent d1ce07d commit a5da8c4
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 28 deletions.
11 changes: 9 additions & 2 deletions clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -979,8 +979,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
phc_index = -1;
} else if (phc_device) {
if (1 != sscanf(phc_device, "/dev/ptp%d", &phc_index)) {
pr_err("bad ptp device string");
return NULL;
phc_index = -1;
}
} else if (iface->ts_info.valid) {
phc_index = iface->ts_info.phc_index;
Expand Down Expand Up @@ -1053,6 +1052,14 @@ struct clock *clock_create(enum clock_type type, struct config *config,
return NULL;
}
clockadj_init(c->clkid);
} else if (phc_device) {
c->clkid = phc_open(phc_device);
if (c->clkid == CLOCK_INVALID) {
pr_err("Failed to open %s: %m", phc_device);
return NULL;
}
max_adj = clockadj_max_freq(c->clkid);
clockadj_init(c->clkid);
} else {
c->clkid = CLOCK_REALTIME;
c->utc_timescale = 1;
Expand Down
43 changes: 25 additions & 18 deletions clockadj.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,30 @@ void clockadj_step(clockid_t clkid, int64_t step)
pr_err("failed to step clock: %m");
}

int clockadj_max_freq(clockid_t clkid)
{
int f = 0;
struct timex tx;

memset(&tx, 0, sizeof(tx));
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to read out the clock maximum adjustment: %m");
else
f = tx.tolerance / 65.536;
if (!f)
f = 500000;

/* The kernel allows the tick length to be adjusted up to 10%. But use
* it only if the overall frequency of the clock can be adjusted
* continuously with the tick and freq fields (i.e. hz <= 1000).
*/
if (clkid == CLOCK_REALTIME && (realtime_nominal_tick && 2 * f >=
1000 * realtime_hz))
f = realtime_nominal_tick / 10 * 1000 * realtime_hz;

return f;
}

void sysclk_set_leap(int leap)
{
clockid_t clkid = CLOCK_REALTIME;
Expand Down Expand Up @@ -142,24 +166,7 @@ void sysclk_set_tai_offset(int offset)

int sysclk_max_freq(void)
{
clockid_t clkid = CLOCK_REALTIME;
int f = 0;
struct timex tx;
memset(&tx, 0, sizeof(tx));
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to read out the clock maximum adjustment: %m");
else
f = tx.tolerance / 65.536;
if (!f)
f = 500000;

/* The kernel allows the tick length to be adjusted up to 10%. But use
it only if the overall frequency of the clock can be adjusted
continuously with the tick and freq fields (i.e. hz <= 1000). */
if (realtime_nominal_tick && 2 * f >= 1000 * realtime_hz)
f = realtime_nominal_tick / 10 * 1000 * realtime_hz;

return f;
return clockadj_max_freq(CLOCK_REALTIME);
}

void sysclk_set_sync(void)
Expand Down
6 changes: 6 additions & 0 deletions clockadj.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ double clockadj_get_freq(clockid_t clkid);
*/
void clockadj_step(clockid_t clkid, int64_t step);

/**
* Read maximum frequency adjustment of the target clock.
* @return The maximum frequency adjustment in parts per billion (ppb).
*/
int clockadj_max_freq(clockid_t clkid);

/**
* Set the system clock to insert/delete leap second at midnight.
* @param leap +1 to insert leap second, -1 to delete leap second,
Expand Down
21 changes: 15 additions & 6 deletions phc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>

#include <linux/ptp_clock.h>
Expand All @@ -38,18 +39,26 @@

static int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps);

clockid_t phc_open(char *phc)
clockid_t phc_open(const char *phc)
{
clockid_t clkid;
struct ptp_clock_caps caps;
int fd = open(phc, O_RDWR);
struct timespec ts;
struct timex tx;
int fd;

memset(&tx, 0, sizeof(tx));

fd = open(phc, O_RDWR);
if (fd < 0)
return CLOCK_INVALID;

clkid = FD_TO_CLOCKID(fd);
/* check if clkid is valid */
if (phc_get_caps(clkid, &caps)) {
if (clock_gettime(clkid, &ts)) {
close(fd);
return CLOCK_INVALID;
}
if (clock_adjtime(clkid, &tx)) {
close(fd);
return CLOCK_INVALID;
}
Expand Down
2 changes: 1 addition & 1 deletion phc.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
*
* @return A valid clock ID on success, CLOCK_INVALID otherwise.
*/
clockid_t phc_open(char *phc);
clockid_t phc_open(const char *phc);

/**
* Closes a PTP hardware clock device.
Expand Down
2 changes: 1 addition & 1 deletion ptp4l.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ static void usage(char *progname)
" -f [file] read configuration from 'file'\n"
" -i [dev] interface device to use, for example 'eth0'\n"
" (may be specified multiple times)\n"
" -p [dev] PTP hardware clock device to use, default auto\n"
" -p [dev] Clock device to use, default auto\n"
" (ignored for SOFTWARE/LEGACY HW time stamping)\n"
" -s slave only mode (overrides configuration file)\n"
" -t transparent clock\n"
Expand Down

0 comments on commit a5da8c4

Please sign in to comment.