Commit c3b60ab7 authored by Rahul Rameshbabu's avatar Rahul Rameshbabu Committed by David S. Miller

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: default avatarRahul Rameshbabu <rrameshbabu@nvidia.com>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3a9a9a61
...@@ -136,7 +136,10 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg) ...@@ -136,7 +136,10 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
caps.pps = ptp->info->pps; caps.pps = ptp->info->pps;
caps.n_pins = ptp->info->n_pins; caps.n_pins = ptp->info->n_pins;
caps.cross_timestamping = ptp->info->getcrosststamp != NULL; caps.cross_timestamping = ptp->info->getcrosststamp != NULL;
caps.adjust_phase = ptp->info->adjphase != NULL; caps.adjust_phase = ptp->info->adjphase != NULL &&
ptp->info->getmaxphase != NULL;
if (caps.adjust_phase)
caps.max_phase_adj = ptp->info->getmaxphase(ptp->info);
if (copy_to_user((void __user *)arg, &caps, sizeof(caps))) if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
err = -EFAULT; err = -EFAULT;
break; break;
......
...@@ -135,11 +135,15 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx) ...@@ -135,11 +135,15 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
ptp->dialed_frequency = tx->freq; ptp->dialed_frequency = tx->freq;
} else if (tx->modes & ADJ_OFFSET) { } else if (tx->modes & ADJ_OFFSET) {
if (ops->adjphase) { if (ops->adjphase) {
s32 max_phase_adj = ops->getmaxphase(ops);
s32 offset = tx->offset; s32 offset = tx->offset;
if (!(tx->modes & ADJ_NANO)) if (!(tx->modes & ADJ_NANO))
offset *= NSEC_PER_USEC; offset *= NSEC_PER_USEC;
if (offset > max_phase_adj || offset < -max_phase_adj)
return -ERANGE;
err = ops->adjphase(ops, offset); err = ops->adjphase(ops, offset);
} }
} else if (tx->modes == 0) { } else if (tx->modes == 0) {
......
...@@ -18,6 +18,17 @@ static ssize_t clock_name_show(struct device *dev, ...@@ -18,6 +18,17 @@ static ssize_t clock_name_show(struct device *dev,
} }
static DEVICE_ATTR_RO(clock_name); static DEVICE_ATTR_RO(clock_name);
static ssize_t max_phase_adjustment_show(struct device *dev,
struct device_attribute *attr,
char *page)
{
struct ptp_clock *ptp = dev_get_drvdata(dev);
return snprintf(page, PAGE_SIZE - 1, "%d\n",
ptp->info->getmaxphase(ptp->info));
}
static DEVICE_ATTR_RO(max_phase_adjustment);
#define PTP_SHOW_INT(name, var) \ #define PTP_SHOW_INT(name, var) \
static ssize_t var##_show(struct device *dev, \ static ssize_t var##_show(struct device *dev, \
struct device_attribute *attr, char *page) \ struct device_attribute *attr, char *page) \
...@@ -309,6 +320,7 @@ static struct attribute *ptp_attrs[] = { ...@@ -309,6 +320,7 @@ static struct attribute *ptp_attrs[] = {
&dev_attr_clock_name.attr, &dev_attr_clock_name.attr,
&dev_attr_max_adjustment.attr, &dev_attr_max_adjustment.attr,
&dev_attr_max_phase_adjustment.attr,
&dev_attr_n_alarms.attr, &dev_attr_n_alarms.attr,
&dev_attr_n_external_timestamps.attr, &dev_attr_n_external_timestamps.attr,
&dev_attr_n_periodic_outputs.attr, &dev_attr_n_periodic_outputs.attr,
......
...@@ -82,6 +82,10 @@ struct ptp_system_timestamp { ...@@ -82,6 +82,10 @@ struct ptp_system_timestamp {
* parameter delta: PHC servo phase adjustment target * parameter delta: PHC servo phase adjustment target
* in nanoseconds. * in nanoseconds.
* *
* @getmaxphase: Advertises maximum offset that can be provided
* to the hardware clock's phase control functionality
* through adjphase.
*
* @adjtime: Shifts the time of the hardware clock. * @adjtime: Shifts the time of the hardware clock.
* parameter delta: Desired change in nanoseconds. * parameter delta: Desired change in nanoseconds.
* *
...@@ -171,6 +175,7 @@ struct ptp_clock_info { ...@@ -171,6 +175,7 @@ struct ptp_clock_info {
struct ptp_pin_desc *pin_config; struct ptp_pin_desc *pin_config;
int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm); int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm);
int (*adjphase)(struct ptp_clock_info *ptp, s32 phase); int (*adjphase)(struct ptp_clock_info *ptp, s32 phase);
s32 (*getmaxphase)(struct ptp_clock_info *ptp);
int (*adjtime)(struct ptp_clock_info *ptp, s64 delta); int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts); int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);
int (*gettimex64)(struct ptp_clock_info *ptp, struct timespec64 *ts, int (*gettimex64)(struct ptp_clock_info *ptp, struct timespec64 *ts,
......
...@@ -95,7 +95,8 @@ struct ptp_clock_caps { ...@@ -95,7 +95,8 @@ struct ptp_clock_caps {
int cross_timestamping; int cross_timestamping;
/* Whether the clock supports adjust phase */ /* Whether the clock supports adjust phase */
int adjust_phase; int adjust_phase;
int rsv[12]; /* Reserved for future use. */ int max_phase_adj; /* Maximum phase adjustment in nanoseconds. */
int rsv[11]; /* Reserved for future use. */
}; };
struct ptp_extts_request { struct ptp_extts_request {
......
...@@ -292,7 +292,8 @@ int main(int argc, char *argv[]) ...@@ -292,7 +292,8 @@ int main(int argc, char *argv[])
" %d pulse per second\n" " %d pulse per second\n"
" %d programmable pins\n" " %d programmable pins\n"
" %d cross timestamping\n" " %d cross timestamping\n"
" %d adjust_phase\n", " %d adjust_phase\n"
" %d maximum phase adjustment (ns)\n",
caps.max_adj, caps.max_adj,
caps.n_alarm, caps.n_alarm,
caps.n_ext_ts, caps.n_ext_ts,
...@@ -300,7 +301,8 @@ int main(int argc, char *argv[]) ...@@ -300,7 +301,8 @@ int main(int argc, char *argv[])
caps.pps, caps.pps,
caps.n_pins, caps.n_pins,
caps.cross_timestamping, caps.cross_timestamping,
caps.adjust_phase); caps.adjust_phase,
caps.max_phase_adj);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment