Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ptp: Add .getmaxphase callback to ptp_clock_info

Enables advertisement of the maximum offset supported by the phase control
functionality of PHCs. The callback is used to return an error if an offset
not supported by the PHC is used in ADJ_OFFSET. The ioctls
PTP_CLOCK_GETCAPS and PTP_CLOCK_GETCAPS2 now advertise the maximum offset a
PHC's phase control functionality is capable of supporting. Introduce new
sysfs node, max_phase_adjustment.

Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Maciek Machnikowski <maciek@machnikowski.net>
Signed-off-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Rahul Rameshbabu and committed by
David S. Miller
c3b60ab7 3a9a9a61

+31 -4
+4 -1
drivers/ptp/ptp_chardev.c
··· 136 136 caps.pps = ptp->info->pps; 137 137 caps.n_pins = ptp->info->n_pins; 138 138 caps.cross_timestamping = ptp->info->getcrosststamp != NULL; 139 - caps.adjust_phase = ptp->info->adjphase != NULL; 139 + caps.adjust_phase = ptp->info->adjphase != NULL && 140 + ptp->info->getmaxphase != NULL; 141 + if (caps.adjust_phase) 142 + caps.max_phase_adj = ptp->info->getmaxphase(ptp->info); 140 143 if (copy_to_user((void __user *)arg, &caps, sizeof(caps))) 141 144 err = -EFAULT; 142 145 break;
+4
drivers/ptp/ptp_clock.c
··· 135 135 ptp->dialed_frequency = tx->freq; 136 136 } else if (tx->modes & ADJ_OFFSET) { 137 137 if (ops->adjphase) { 138 + s32 max_phase_adj = ops->getmaxphase(ops); 138 139 s32 offset = tx->offset; 139 140 140 141 if (!(tx->modes & ADJ_NANO)) 141 142 offset *= NSEC_PER_USEC; 143 + 144 + if (offset > max_phase_adj || offset < -max_phase_adj) 145 + return -ERANGE; 142 146 143 147 err = ops->adjphase(ops, offset); 144 148 }
+12
drivers/ptp/ptp_sysfs.c
··· 18 18 } 19 19 static DEVICE_ATTR_RO(clock_name); 20 20 21 + static ssize_t max_phase_adjustment_show(struct device *dev, 22 + struct device_attribute *attr, 23 + char *page) 24 + { 25 + struct ptp_clock *ptp = dev_get_drvdata(dev); 26 + 27 + return snprintf(page, PAGE_SIZE - 1, "%d\n", 28 + ptp->info->getmaxphase(ptp->info)); 29 + } 30 + static DEVICE_ATTR_RO(max_phase_adjustment); 31 + 21 32 #define PTP_SHOW_INT(name, var) \ 22 33 static ssize_t var##_show(struct device *dev, \ 23 34 struct device_attribute *attr, char *page) \ ··· 320 309 &dev_attr_clock_name.attr, 321 310 322 311 &dev_attr_max_adjustment.attr, 312 + &dev_attr_max_phase_adjustment.attr, 323 313 &dev_attr_n_alarms.attr, 324 314 &dev_attr_n_external_timestamps.attr, 325 315 &dev_attr_n_periodic_outputs.attr,
+5
include/linux/ptp_clock_kernel.h
··· 82 82 * parameter delta: PHC servo phase adjustment target 83 83 * in nanoseconds. 84 84 * 85 + * @getmaxphase: Advertises maximum offset that can be provided 86 + * to the hardware clock's phase control functionality 87 + * through adjphase. 88 + * 85 89 * @adjtime: Shifts the time of the hardware clock. 86 90 * parameter delta: Desired change in nanoseconds. 87 91 * ··· 175 171 struct ptp_pin_desc *pin_config; 176 172 int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm); 177 173 int (*adjphase)(struct ptp_clock_info *ptp, s32 phase); 174 + s32 (*getmaxphase)(struct ptp_clock_info *ptp); 178 175 int (*adjtime)(struct ptp_clock_info *ptp, s64 delta); 179 176 int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts); 180 177 int (*gettimex64)(struct ptp_clock_info *ptp, struct timespec64 *ts,
+2 -1
include/uapi/linux/ptp_clock.h
··· 95 95 int cross_timestamping; 96 96 /* Whether the clock supports adjust phase */ 97 97 int adjust_phase; 98 - int rsv[12]; /* Reserved for future use. */ 98 + int max_phase_adj; /* Maximum phase adjustment in nanoseconds. */ 99 + int rsv[11]; /* Reserved for future use. */ 99 100 }; 100 101 101 102 struct ptp_extts_request {
+4 -2
tools/testing/selftests/ptp/testptp.c
··· 292 292 " %d pulse per second\n" 293 293 " %d programmable pins\n" 294 294 " %d cross timestamping\n" 295 - " %d adjust_phase\n", 295 + " %d adjust_phase\n" 296 + " %d maximum phase adjustment (ns)\n", 296 297 caps.max_adj, 297 298 caps.n_alarm, 298 299 caps.n_ext_ts, ··· 301 300 caps.pps, 302 301 caps.n_pins, 303 302 caps.cross_timestamping, 304 - caps.adjust_phase); 303 + caps.adjust_phase, 304 + caps.max_phase_adj); 305 305 } 306 306 } 307 307