Skip to content

Commit c3b60ab

Browse files
Binary-Eaterdavem330
authored andcommitted
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 <[email protected]> Cc: Shuah Khan <[email protected]> Cc: Richard Cochran <[email protected]> Cc: Maciek Machnikowski <[email protected]> Signed-off-by: Rahul Rameshbabu <[email protected]> Acked-by: Richard Cochran <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3a9a9a6 commit c3b60ab

File tree

6 files changed

+31
-4
lines changed

6 files changed

+31
-4
lines changed

drivers/ptp/ptp_chardev.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,10 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
136136
caps.pps = ptp->info->pps;
137137
caps.n_pins = ptp->info->n_pins;
138138
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);
140143
if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
141144
err = -EFAULT;
142145
break;

drivers/ptp/ptp_clock.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,15 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
135135
ptp->dialed_frequency = tx->freq;
136136
} else if (tx->modes & ADJ_OFFSET) {
137137
if (ops->adjphase) {
138+
s32 max_phase_adj = ops->getmaxphase(ops);
138139
s32 offset = tx->offset;
139140

140141
if (!(tx->modes & ADJ_NANO))
141142
offset *= NSEC_PER_USEC;
142143

144+
if (offset > max_phase_adj || offset < -max_phase_adj)
145+
return -ERANGE;
146+
143147
err = ops->adjphase(ops, offset);
144148
}
145149
} else if (tx->modes == 0) {

drivers/ptp/ptp_sysfs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ static ssize_t clock_name_show(struct device *dev,
1818
}
1919
static DEVICE_ATTR_RO(clock_name);
2020

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+
2132
#define PTP_SHOW_INT(name, var) \
2233
static ssize_t var##_show(struct device *dev, \
2334
struct device_attribute *attr, char *page) \
@@ -309,6 +320,7 @@ static struct attribute *ptp_attrs[] = {
309320
&dev_attr_clock_name.attr,
310321

311322
&dev_attr_max_adjustment.attr,
323+
&dev_attr_max_phase_adjustment.attr,
312324
&dev_attr_n_alarms.attr,
313325
&dev_attr_n_external_timestamps.attr,
314326
&dev_attr_n_periodic_outputs.attr,

include/linux/ptp_clock_kernel.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ struct ptp_system_timestamp {
8282
* parameter delta: PHC servo phase adjustment target
8383
* in nanoseconds.
8484
*
85+
* @getmaxphase: Advertises maximum offset that can be provided
86+
* to the hardware clock's phase control functionality
87+
* through adjphase.
88+
*
8589
* @adjtime: Shifts the time of the hardware clock.
8690
* parameter delta: Desired change in nanoseconds.
8791
*
@@ -171,6 +175,7 @@ struct ptp_clock_info {
171175
struct ptp_pin_desc *pin_config;
172176
int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm);
173177
int (*adjphase)(struct ptp_clock_info *ptp, s32 phase);
178+
s32 (*getmaxphase)(struct ptp_clock_info *ptp);
174179
int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
175180
int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);
176181
int (*gettimex64)(struct ptp_clock_info *ptp, struct timespec64 *ts,

include/uapi/linux/ptp_clock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ struct ptp_clock_caps {
9595
int cross_timestamping;
9696
/* Whether the clock supports adjust phase */
9797
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. */
99100
};
100101

101102
struct ptp_extts_request {

tools/testing/selftests/ptp/testptp.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,15 +292,17 @@ int main(int argc, char *argv[])
292292
" %d pulse per second\n"
293293
" %d programmable pins\n"
294294
" %d cross timestamping\n"
295-
" %d adjust_phase\n",
295+
" %d adjust_phase\n"
296+
" %d maximum phase adjustment (ns)\n",
296297
caps.max_adj,
297298
caps.n_alarm,
298299
caps.n_ext_ts,
299300
caps.n_per_out,
300301
caps.pps,
301302
caps.n_pins,
302303
caps.cross_timestamping,
303-
caps.adjust_phase);
304+
caps.adjust_phase,
305+
caps.max_phase_adj);
304306
}
305307
}
306308

0 commit comments

Comments
 (0)