In version 6.15 the Linux kernel started checking write access on the
PHC file descriptor in the PTP_PIN_SETFUNC and PTP_EXTTS_REQUEST ioctls.
chronyd opened the PHC device as readonly, which caused the PHC refclock
driver configured with the extpps option to fail with the
"Could not enable external PHC timestamping" error message.
To ensure compatibility with new kernel versions, add flags to the
SYS_Linux_OpenPHC() function and open the device with the O_RDWR flag
when the extpps option is enabled.
SCK_CloseSocket(sock_fd);
SCK_CloseSocket(sock_fd);
- phc_fd = SYS_Linux_OpenPHC(req.ifr_name);
+ phc_fd = SYS_Linux_OpenPHC(req.ifr_name, O_RDONLY);
if (phc_fd < 0)
return 0;
if (phc_fd < 0)
return 0;
{
const char *options[] = {"nocrossts", "extpps", "pin", "channel", "clear", NULL};
struct phc_instance *phc;
{
const char *options[] = {"nocrossts", "extpps", "pin", "channel", "clear", NULL};
struct phc_instance *phc;
- int phc_fd, rising_edge;
struct stat st;
char *path, *s;
struct stat st;
char *path, *s;
path = RCL_GetDriverParameter(instance);
path = RCL_GetDriverParameter(instance);
- phc_fd = SYS_Linux_OpenPHC(path);
- if (phc_fd < 0)
- LOG_FATAL("Could not open PHC");
-
phc = MallocNew(struct phc_instance);
phc = MallocNew(struct phc_instance);
- phc->fd = phc_fd;
- if (fstat(phc_fd, &st) < 0 || !S_ISCHR(st.st_mode))
- LOG_FATAL("Could not get PHC index");
- phc->dev_index = minor(st.st_rdev);
phc->mode = 0;
phc->nocrossts = RCL_GetDriverOption(instance, "nocrossts") ? 1 : 0;
phc->extpps = RCL_GetDriverOption(instance, "extpps") ? 1 : 0;
UTI_ZeroTimespec(&phc->last_extts);
phc->mode = 0;
phc->nocrossts = RCL_GetDriverOption(instance, "nocrossts") ? 1 : 0;
phc->extpps = RCL_GetDriverOption(instance, "extpps") ? 1 : 0;
UTI_ZeroTimespec(&phc->last_extts);
+
+ phc->fd = SYS_Linux_OpenPHC(path, phc->extpps ? O_RDWR : O_RDONLY);
+ if (phc->fd < 0)
+ LOG_FATAL("Could not open PHC");
+
+ if (fstat(phc->fd, &st) < 0 || !S_ISCHR(st.st_mode))
+ LOG_FATAL("Could not get PHC index");
+ phc->dev_index = minor(st.st_rdev);
+
phc->clock = HCL_CreateInstance(0, 16, UTI_Log2ToDouble(RCL_GetDriverPoll(instance)),
RCL_GetPrecision(instance));
phc->clock = HCL_CreateInstance(0, 16, UTI_Log2ToDouble(RCL_GetDriverPoll(instance)),
RCL_GetPrecision(instance));
/* ================================================== */
static int
/* ================================================== */
static int
-open_phc_by_iface_name(const char *iface)
+open_phc_by_iface_name(const char *iface, int flags)
{
#ifdef HAVE_LINUX_TIMESTAMPING
struct ethtool_ts_info ts_info;
{
#ifdef HAVE_LINUX_TIMESTAMPING
struct ethtool_ts_info ts_info;
"/dev/ptp%d", ts_info.phc_index) >= sizeof (phc_device))
return -1;
"/dev/ptp%d", ts_info.phc_index) >= sizeof (phc_device))
return -1;
- return open(phc_device, O_RDONLY);
+ return open(phc_device, flags);
/* ================================================== */
int
/* ================================================== */
int
-SYS_Linux_OpenPHC(const char *device)
+SYS_Linux_OpenPHC(const char *device, int flags)
{
int phc_fd = -1;
if (device[0] == '/') {
{
int phc_fd = -1;
if (device[0] == '/') {
- phc_fd = open(device, O_RDONLY);
+ phc_fd = open(device, flags);
if (phc_fd >= 0)
phc_fd = verify_fd_is_phc(phc_fd);
}
if (phc_fd < 0) {
if (phc_fd >= 0)
phc_fd = verify_fd_is_phc(phc_fd);
}
if (phc_fd < 0) {
- phc_fd = open_phc_by_iface_name(device);
+ phc_fd = open_phc_by_iface_name(device, flags);
if (phc_fd < 0) {
LOG(LOGS_ERR, "Could not open PHC of iface %s : %s",
device, strerror(errno));
if (phc_fd < 0) {
LOG(LOGS_ERR, "Could not open PHC of iface %s : %s",
device, strerror(errno));
extern int SYS_Linux_CheckKernelVersion(int req_major, int req_minor);
extern int SYS_Linux_CheckKernelVersion(int req_major, int req_minor);
-extern int SYS_Linux_OpenPHC(const char *device);
+extern int SYS_Linux_OpenPHC(const char *device, int flags);
extern int SYS_Linux_GetPHCReadings(int fd, int nocrossts, int *reading_mode, int max_readings,
struct timespec tss[][3]);
extern int SYS_Linux_GetPHCReadings(int fd, int nocrossts, int *reading_mode, int max_readings,
struct timespec tss[][3]);