diff --git a/clock.c b/clock.c index 56bc79bf..9c493c3d 100644 --- a/clock.c +++ b/clock.c @@ -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; @@ -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; diff --git a/clockadj.c b/clockadj.c index 86c7b331..0485d8ca 100644 --- a/clockadj.c +++ b/clockadj.c @@ -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; @@ -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) diff --git a/clockadj.h b/clockadj.h index 492418e9..4ea98c13 100644 --- a/clockadj.h +++ b/clockadj.h @@ -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, diff --git a/phc.c b/phc.c index 40fa6a15..a90d13e6 100644 --- a/phc.c +++ b/phc.c @@ -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 #include +#include #include -#include #include -#include +#include #include #include @@ -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; } diff --git a/phc.h b/phc.h index 154e35ec..c0c59966 100644 --- a/phc.h +++ b/phc.h @@ -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. diff --git a/ptp4l.c b/ptp4l.c index 3a9f0849..17db31f7 100644 --- a/ptp4l.c +++ b/ptp4l.c @@ -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"