Message ID | 20241021141955.1466979-2-arkadiusz.kubalewski@intel.com |
---|---|
State | Changes Requested |
Headers | show |
Series | ptp: add control over HW timestamp latch point | expand |
Dear Arkadiusz, Thank you for your patch. Am 21.10.24 um 16:19 schrieb Arkadiusz Kubalewski: > Currently HW support of PTP/timesync solutions in network PHY chips can be > implemented with two different approaches, the timestamp maybe latched > either at the beginning or after the Start of Frame Delimiter (SFD) [1]. > > Allow ptp device drivers to provide user with control over the HW > timestamp latch point with ptp sysfs ABI. Please describe, that it’s done using `/sys` filesystem. How can this be tested? > [1] https://www.ieee802.org/3/cx/public/april20/tse_3cx_01_0420.pdf > > Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> > Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> > --- > Documentation/ABI/testing/sysfs-ptp | 12 ++++++++ > drivers/ptp/ptp_sysfs.c | 44 +++++++++++++++++++++++++++++ > include/linux/ptp_clock_kernel.h | 29 +++++++++++++++++++ > 3 files changed, 85 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-ptp b/Documentation/ABI/testing/sysfs-ptp > index 9c317ac7c47a..a0d89e0fd72e 100644 > --- a/Documentation/ABI/testing/sysfs-ptp > +++ b/Documentation/ABI/testing/sysfs-ptp > @@ -140,3 +140,15 @@ Description: > PPS events to the Linux PPS subsystem. To enable PPS > events, write a "1" into the file. To disable events, > write a "0" into the file. > + > +What: /sys/class/ptp/ptp<N>/ts_point > +Date: October 2024 > +Contact: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> > +Description: > + This file provides control over the point in time in > + which the HW timestamp is latched. As specified in IEEE > + 802.3cx, the latch point can be either at the beginning > + or after the end of Start of Frame Delimiter (SFD). > + Value "0" means the timestamp is latched at the > + beginning of the SFD. Value "1" means that timestamp is > + latched after the end of SFD. Would it make sense to let it be configured by strings, so it’s clear, what the values mean? 1. beginning_of_sfd 2. end_of_sfd > diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c > index 6b1b8f57cd95..7e9f6ef368b6 100644 > --- a/drivers/ptp/ptp_sysfs.c > +++ b/drivers/ptp/ptp_sysfs.c > @@ -28,6 +28,46 @@ static ssize_t max_phase_adjustment_show(struct device *dev, > } > static DEVICE_ATTR_RO(max_phase_adjustment); > > +static ssize_t ts_point_show(struct device *dev, struct device_attribute *attr, > + char *page) > +{ > + struct ptp_clock *ptp = dev_get_drvdata(dev); > + enum ptp_ts_point point; > + int err; > + > + if (!ptp->info->get_ts_point) > + return -EOPNOTSUPP; > + err = ptp->info->get_ts_point(ptp->info, &point); > + if (err) > + return err; > + > + return sysfs_emit(page, "%d\n", point); > +} > + > +static ssize_t ts_point_store(struct device *dev, struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + struct ptp_clock *ptp = dev_get_drvdata(dev); > + enum ptp_ts_point point; > + int err; > + u8 val; > + > + if (!ptp->info->set_ts_point) > + return -EOPNOTSUPP; > + if (kstrtou8(buf, 0, &val)) > + return -EINVAL; > + if (val > PTP_TS_POINT_MAX) > + return -EINVAL; > + point = val; > + > + err = ptp->info->set_ts_point(ptp->info, point); > + if (err) > + return err; > + > + return count; > +} > +static DEVICE_ATTR_RW(ts_point); > + > #define PTP_SHOW_INT(name, var) \ > static ssize_t var##_show(struct device *dev, \ > struct device_attribute *attr, char *page) \ > @@ -335,6 +375,7 @@ static struct attribute *ptp_attrs[] = { > &dev_attr_pps_enable.attr, > &dev_attr_n_vclocks.attr, > &dev_attr_max_vclocks.attr, > + &dev_attr_ts_point.attr, > NULL > }; > > @@ -363,6 +404,9 @@ static umode_t ptp_is_attribute_visible(struct kobject *kobj, > } else if (attr == &dev_attr_max_phase_adjustment.attr) { > if (!info->adjphase || !info->getmaxphase) > mode = 0; > + } else if (attr == &dev_attr_ts_point.attr) { > + if (!info->get_ts_point && !info->set_ts_point) > + mode = 0; > } > > return mode; > diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h > index c892d22ce0a7..921d6615bd39 100644 > --- a/include/linux/ptp_clock_kernel.h > +++ b/include/linux/ptp_clock_kernel.h > @@ -55,6 +55,23 @@ struct ptp_system_timestamp { > clockid_t clockid; > }; > > +/** > + * enum ptp_ts_point - possible timestamp latch points (IEEE 802.3cx) > + * @PTP_TS_POINT_SFD: timestamp latched at the beginning of sending Start The alignment of the start of the description looks strange with the second line being further right. > + * of Frame Delimiter (SFD) > + * @PTP_TS_POINT_POST_SFD: timestamp latched after the end of sending Start > + * of Frame Delimiter (SFD) > + */ > +enum ptp_ts_point { > + PTP_TS_POINT_SFD, > + PTP_TS_POINT_POST_SFD, > + > + /* private: */ > + __PTP_TS_POINT_MAX > +}; > + > +#define PTP_TS_POINT_MAX (__PTP_TS_POINT_MAX - 1) > + > /** > * struct ptp_clock_info - describes a PTP hardware clock > * > @@ -159,6 +176,14 @@ struct ptp_system_timestamp { > * scheduling time (>=0) or negative value in case further > * scheduling is not required. > * > + * @set_ts_point: Request change of timestamp latch point, as the timestamp > + * could be latched at the beginning or after the end of start > + * frame delimiter (SFD), as described in IEEE 802.3cx > + * specification. > + * > + * @get_ts_point: Obtain the timestamp measurement latch point, counterpart of > + * .set_ts_point() for getting currently configured value. > + * > * Drivers should embed their ptp_clock_info within a private > * structure, obtaining a reference to it using container_of(). > * > @@ -195,6 +220,10 @@ struct ptp_clock_info { > int (*verify)(struct ptp_clock_info *ptp, unsigned int pin, > enum ptp_pin_function func, unsigned int chan); > long (*do_aux_work)(struct ptp_clock_info *ptp); > + int (*set_ts_point)(struct ptp_clock_info *ptp, > + enum ptp_ts_point point); > + int (*get_ts_point)(struct ptp_clock_info *ptp, > + enum ptp_ts_point *point); > }; > > struct ptp_clock; Kind regards, Paul
On 10/21/2024 7:19 AM, Arkadiusz Kubalewski wrote: > Currently HW support of PTP/timesync solutions in network PHY chips can be > implemented with two different approaches, the timestamp maybe latched > either at the beginning or after the Start of Frame Delimiter (SFD) [1]. > > Allow ptp device drivers to provide user with control over the HW > timestamp latch point with ptp sysfs ABI. > > [1] https://www.ieee802.org/3/cx/public/april20/tse_3cx_01_0420.pdf > > Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> > Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> > --- > Documentation/ABI/testing/sysfs-ptp | 12 ++++++++ > drivers/ptp/ptp_sysfs.c | 44 +++++++++++++++++++++++++++++ > include/linux/ptp_clock_kernel.h | 29 +++++++++++++++++++ > 3 files changed, 85 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-ptp b/Documentation/ABI/testing/sysfs-ptp > index 9c317ac7c47a..a0d89e0fd72e 100644 > --- a/Documentation/ABI/testing/sysfs-ptp > +++ b/Documentation/ABI/testing/sysfs-ptp > @@ -140,3 +140,15 @@ Description: > PPS events to the Linux PPS subsystem. To enable PPS > events, write a "1" into the file. To disable events, > write a "0" into the file. > + > +What: /sys/class/ptp/ptp<N>/ts_point > +Date: October 2024 > +Contact: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> > +Description: > + This file provides control over the point in time in > + which the HW timestamp is latched. As specified in IEEE > + 802.3cx, the latch point can be either at the beginning > + or after the end of Start of Frame Delimiter (SFD). > + Value "0" means the timestamp is latched at the > + beginning of the SFD. Value "1" means that timestamp is > + latched after the end of SFD. > diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c > index 6b1b8f57cd95..7e9f6ef368b6 100644 > --- a/drivers/ptp/ptp_sysfs.c > +++ b/drivers/ptp/ptp_sysfs.c > @@ -28,6 +28,46 @@ static ssize_t max_phase_adjustment_show(struct device *dev, > } > static DEVICE_ATTR_RO(max_phase_adjustment); > > +static ssize_t ts_point_show(struct device *dev, struct device_attribute *attr, > + char *page) > +{ > + struct ptp_clock *ptp = dev_get_drvdata(dev); > + enum ptp_ts_point point; > + int err; > + > + if (!ptp->info->get_ts_point) > + return -EOPNOTSUPP; > + err = ptp->info->get_ts_point(ptp->info, &point); > + if (err) > + return err; > + > + return sysfs_emit(page, "%d\n", point); > +} > + Ok, so if the driver doesn't support this API, we just return EOPNOTSUPP and don't support the API then. Presumably hardware which doesn't timestamp according to this standard would then simply not support the API?
>From: Paul Menzel <pmenzel@molgen.mpg.de> >Sent: Monday, October 21, 2024 5:21 PM > >Dear Arkadiusz, > > >Thank you for your patch. Thank you for the review! > >Am 21.10.24 um 16:19 schrieb Arkadiusz Kubalewski: >> Currently HW support of PTP/timesync solutions in network PHY chips can >> be >> implemented with two different approaches, the timestamp maybe latched >> either at the beginning or after the Start of Frame Delimiter (SFD) [1]. >> >> Allow ptp device drivers to provide user with control over the HW >> timestamp latch point with ptp sysfs ABI. > >Please describe, that it’s done using `/sys` filesystem. > >How can this be tested? Sure, will add some example/description. > >> [1] https://www.ieee802.org/3/cx/public/april20/tse_3cx_01_0420.pdf >> >> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> >> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> >> --- >> Documentation/ABI/testing/sysfs-ptp | 12 ++++++++ >> drivers/ptp/ptp_sysfs.c | 44 +++++++++++++++++++++++++++++ >> include/linux/ptp_clock_kernel.h | 29 +++++++++++++++++++ >> 3 files changed, 85 insertions(+) >> >> diff --git a/Documentation/ABI/testing/sysfs-ptp >> b/Documentation/ABI/testing/sysfs-ptp >> index 9c317ac7c47a..a0d89e0fd72e 100644 >> --- a/Documentation/ABI/testing/sysfs-ptp >> +++ b/Documentation/ABI/testing/sysfs-ptp >> @@ -140,3 +140,15 @@ Description: >> PPS events to the Linux PPS subsystem. To enable PPS >> events, write a "1" into the file. To disable events, >> write a "0" into the file. >> + >> +What: /sys/class/ptp/ptp<N>/ts_point >> +Date: October 2024 >> +Contact: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> >> +Description: >> + This file provides control over the point in time in >> + which the HW timestamp is latched. As specified in IEEE >> + 802.3cx, the latch point can be either at the beginning >> + or after the end of Start of Frame Delimiter (SFD). >> + Value "0" means the timestamp is latched at the >> + beginning of the SFD. Value "1" means that timestamp is >> + latched after the end of SFD. > >Would it make sense to let it be configured by strings, so it’s clear, >what the values mean? > >1. beginning_of_sfd >2. end_of_sfd Actually I don't have strong opinion here. I don't know much sysfs files which take strings as arguments, thus started with numeric values. And from 'consistency' perspective it is much more common to use numeric enum values. But, as I said, I could change it, just not sure if that is actually better. Any other opinions? > >> diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c >> index 6b1b8f57cd95..7e9f6ef368b6 100644 >> --- a/drivers/ptp/ptp_sysfs.c >> +++ b/drivers/ptp/ptp_sysfs.c >> @@ -28,6 +28,46 @@ static ssize_t max_phase_adjustment_show(struct device >> *dev, >> } >> static DEVICE_ATTR_RO(max_phase_adjustment); >> >> +static ssize_t ts_point_show(struct device *dev, struct device_attribute >> *attr, >> + char *page) >> +{ >> + struct ptp_clock *ptp = dev_get_drvdata(dev); >> + enum ptp_ts_point point; >> + int err; >> + >> + if (!ptp->info->get_ts_point) >> + return -EOPNOTSUPP; >> + err = ptp->info->get_ts_point(ptp->info, &point); >> + if (err) >> + return err; >> + >> + return sysfs_emit(page, "%d\n", point); >> +} >> + >> +static ssize_t ts_point_store(struct device *dev, struct >> device_attribute *attr, >> + const char *buf, size_t count) >> +{ >> + struct ptp_clock *ptp = dev_get_drvdata(dev); >> + enum ptp_ts_point point; >> + int err; >> + u8 val; >> + >> + if (!ptp->info->set_ts_point) >> + return -EOPNOTSUPP; >> + if (kstrtou8(buf, 0, &val)) >> + return -EINVAL; >> + if (val > PTP_TS_POINT_MAX) >> + return -EINVAL; >> + point = val; >> + >> + err = ptp->info->set_ts_point(ptp->info, point); >> + if (err) >> + return err; >> + >> + return count; >> +} >> +static DEVICE_ATTR_RW(ts_point); >> + >> #define PTP_SHOW_INT(name, var) \ >> static ssize_t var##_show(struct device *dev, \ >> struct device_attribute *attr, char *page) \ >> @@ -335,6 +375,7 @@ static struct attribute *ptp_attrs[] = { >> &dev_attr_pps_enable.attr, >> &dev_attr_n_vclocks.attr, >> &dev_attr_max_vclocks.attr, >> + &dev_attr_ts_point.attr, >> NULL >> }; >> >> @@ -363,6 +404,9 @@ static umode_t ptp_is_attribute_visible(struct >> kobject *kobj, >> } else if (attr == &dev_attr_max_phase_adjustment.attr) { >> if (!info->adjphase || !info->getmaxphase) >> mode = 0; >> + } else if (attr == &dev_attr_ts_point.attr) { >> + if (!info->get_ts_point && !info->set_ts_point) >> + mode = 0; >> } >> >> return mode; >> diff --git a/include/linux/ptp_clock_kernel.h >> b/include/linux/ptp_clock_kernel.h >> index c892d22ce0a7..921d6615bd39 100644 >> --- a/include/linux/ptp_clock_kernel.h >> +++ b/include/linux/ptp_clock_kernel.h >> @@ -55,6 +55,23 @@ struct ptp_system_timestamp { >> clockid_t clockid; >> }; >> >> +/** >> + * enum ptp_ts_point - possible timestamp latch points (IEEE 802.3cx) >> + * @PTP_TS_POINT_SFD: timestamp latched at the beginning of sending >> Start > >The alignment of the start of the description looks strange with the >second line being further right. > True, will try to fix it. >> + * of Frame Delimiter (SFD) >> + * @PTP_TS_POINT_POST_SFD: timestamp latched after the end of sending >> Start >> + * of Frame Delimiter (SFD) >> + */ >> +enum ptp_ts_point { >> + PTP_TS_POINT_SFD, >> + PTP_TS_POINT_POST_SFD, >> + >> + /* private: */ >> + __PTP_TS_POINT_MAX >> +}; >> + >> +#define PTP_TS_POINT_MAX (__PTP_TS_POINT_MAX - 1) >> + >> /** >> * struct ptp_clock_info - describes a PTP hardware clock >> * >> @@ -159,6 +176,14 @@ struct ptp_system_timestamp { >> * scheduling time (>=0) or negative value in case >> further >> * scheduling is not required. >> * >> + * @set_ts_point: Request change of timestamp latch point, as the >> timestamp >> + * could be latched at the beginning or after the end of >> start >> + * frame delimiter (SFD), as described in IEEE 802.3cx >> + * specification. >> + * >> + * @get_ts_point: Obtain the timestamp measurement latch point, >> counterpart of >> + * .set_ts_point() for getting currently configured >> value. >> + * >> * Drivers should embed their ptp_clock_info within a private >> * structure, obtaining a reference to it using container_of(). >> * >> @@ -195,6 +220,10 @@ struct ptp_clock_info { >> int (*verify)(struct ptp_clock_info *ptp, unsigned int pin, >> enum ptp_pin_function func, unsigned int chan); >> long (*do_aux_work)(struct ptp_clock_info *ptp); >> + int (*set_ts_point)(struct ptp_clock_info *ptp, >> + enum ptp_ts_point point); >> + int (*get_ts_point)(struct ptp_clock_info *ptp, >> + enum ptp_ts_point *point); >> }; >> >> struct ptp_clock; > > >Kind regards, > >Paul Thank you! Arkadiusz
>From: Keller, Jacob E <jacob.e.keller@intel.com> >Sent: Tuesday, October 22, 2024 12:31 AM > > >On 10/21/2024 7:19 AM, Arkadiusz Kubalewski wrote: >> Currently HW support of PTP/timesync solutions in network PHY chips can >> be >> implemented with two different approaches, the timestamp maybe latched >> either at the beginning or after the Start of Frame Delimiter (SFD) [1]. >> >> Allow ptp device drivers to provide user with control over the HW >> timestamp latch point with ptp sysfs ABI. >> >> [1] https://www.ieee802.org/3/cx/public/april20/tse_3cx_01_0420.pdf >> >> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> >> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> >> --- >> Documentation/ABI/testing/sysfs-ptp | 12 ++++++++ >> drivers/ptp/ptp_sysfs.c | 44 +++++++++++++++++++++++++++++ >> include/linux/ptp_clock_kernel.h | 29 +++++++++++++++++++ >> 3 files changed, 85 insertions(+) >> >> diff --git a/Documentation/ABI/testing/sysfs-ptp >> b/Documentation/ABI/testing/sysfs-ptp >> index 9c317ac7c47a..a0d89e0fd72e 100644 >> --- a/Documentation/ABI/testing/sysfs-ptp >> +++ b/Documentation/ABI/testing/sysfs-ptp >> @@ -140,3 +140,15 @@ Description: >> PPS events to the Linux PPS subsystem. To enable PPS >> events, write a "1" into the file. To disable events, >> write a "0" into the file. >> + >> +What: /sys/class/ptp/ptp<N>/ts_point >> +Date: October 2024 >> +Contact: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> >> +Description: >> + This file provides control over the point in time in >> + which the HW timestamp is latched. As specified in IEEE >> + 802.3cx, the latch point can be either at the beginning >> + or after the end of Start of Frame Delimiter (SFD). >> + Value "0" means the timestamp is latched at the >> + beginning of the SFD. Value "1" means that timestamp is >> + latched after the end of SFD. >> diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c >> index 6b1b8f57cd95..7e9f6ef368b6 100644 >> --- a/drivers/ptp/ptp_sysfs.c >> +++ b/drivers/ptp/ptp_sysfs.c >> @@ -28,6 +28,46 @@ static ssize_t max_phase_adjustment_show(struct device >> *dev, >> } >> static DEVICE_ATTR_RO(max_phase_adjustment); >> >> +static ssize_t ts_point_show(struct device *dev, struct device_attribute >> *attr, >> + char *page) >> +{ >> + struct ptp_clock *ptp = dev_get_drvdata(dev); >> + enum ptp_ts_point point; >> + int err; >> + >> + if (!ptp->info->get_ts_point) >> + return -EOPNOTSUPP; >> + err = ptp->info->get_ts_point(ptp->info, &point); >> + if (err) >> + return err; >> + >> + return sysfs_emit(page, "%d\n", point); >> +} >> + > >Ok, so if the driver doesn't support this API, we just return EOPNOTSUPP >and don't support the API then. > >Presumably hardware which doesn't timestamp according to this standard >would then simply not support the API? This is tricky, I did it this way, since the driver can implement only get_ts_point for any given HW - just to give user idea what it shall expect (the timestamp is always latched at some point). Setting this, on the other hand depends on the PHY, which needs to allow control over it. If none of the callbacks are implemented then sysfs doesn't appear, if one of the callbacks is implemented then the sysfs will appear, but the check if callback is present is still required. Thank you! Arkadiusz
On Mon, Oct 21, 2024 at 04:19:54PM +0200, Arkadiusz Kubalewski wrote: > Currently HW support of PTP/timesync solutions in network PHY chips can be > implemented with two different approaches, the timestamp maybe latched > either at the beginning or after the Start of Frame Delimiter (SFD) [1]. Why did 802.3-2012 change the definition of the time stamp position? Thanks, Richard
>From: Richard Cochran <richardcochran@gmail.com> >Sent: Wednesday, October 23, 2024 4:13 AM > >On Mon, Oct 21, 2024 at 04:19:54PM +0200, Arkadiusz Kubalewski wrote: >> Currently HW support of PTP/timesync solutions in network PHY chips >> can be implemented with two different approaches, the timestamp maybe >> latched either at the beginning or after the Start of Frame Delimiter >(SFD) [1]. > >Why did 802.3-2012 change the definition of the time stamp position? > >Thanks, >Richard Good question! Although, I don't feel like I a right person to answer this, I believe This was the other way around and they just tried to react on the PHY chip vendors inconsistencies. Thank you! Arkadiusz
diff --git a/Documentation/ABI/testing/sysfs-ptp b/Documentation/ABI/testing/sysfs-ptp index 9c317ac7c47a..a0d89e0fd72e 100644 --- a/Documentation/ABI/testing/sysfs-ptp +++ b/Documentation/ABI/testing/sysfs-ptp @@ -140,3 +140,15 @@ Description: PPS events to the Linux PPS subsystem. To enable PPS events, write a "1" into the file. To disable events, write a "0" into the file. + +What: /sys/class/ptp/ptp<N>/ts_point +Date: October 2024 +Contact: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> +Description: + This file provides control over the point in time in + which the HW timestamp is latched. As specified in IEEE + 802.3cx, the latch point can be either at the beginning + or after the end of Start of Frame Delimiter (SFD). + Value "0" means the timestamp is latched at the + beginning of the SFD. Value "1" means that timestamp is + latched after the end of SFD. diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c index 6b1b8f57cd95..7e9f6ef368b6 100644 --- a/drivers/ptp/ptp_sysfs.c +++ b/drivers/ptp/ptp_sysfs.c @@ -28,6 +28,46 @@ static ssize_t max_phase_adjustment_show(struct device *dev, } static DEVICE_ATTR_RO(max_phase_adjustment); +static ssize_t ts_point_show(struct device *dev, struct device_attribute *attr, + char *page) +{ + struct ptp_clock *ptp = dev_get_drvdata(dev); + enum ptp_ts_point point; + int err; + + if (!ptp->info->get_ts_point) + return -EOPNOTSUPP; + err = ptp->info->get_ts_point(ptp->info, &point); + if (err) + return err; + + return sysfs_emit(page, "%d\n", point); +} + +static ssize_t ts_point_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ptp_clock *ptp = dev_get_drvdata(dev); + enum ptp_ts_point point; + int err; + u8 val; + + if (!ptp->info->set_ts_point) + return -EOPNOTSUPP; + if (kstrtou8(buf, 0, &val)) + return -EINVAL; + if (val > PTP_TS_POINT_MAX) + return -EINVAL; + point = val; + + err = ptp->info->set_ts_point(ptp->info, point); + if (err) + return err; + + return count; +} +static DEVICE_ATTR_RW(ts_point); + #define PTP_SHOW_INT(name, var) \ static ssize_t var##_show(struct device *dev, \ struct device_attribute *attr, char *page) \ @@ -335,6 +375,7 @@ static struct attribute *ptp_attrs[] = { &dev_attr_pps_enable.attr, &dev_attr_n_vclocks.attr, &dev_attr_max_vclocks.attr, + &dev_attr_ts_point.attr, NULL }; @@ -363,6 +404,9 @@ static umode_t ptp_is_attribute_visible(struct kobject *kobj, } else if (attr == &dev_attr_max_phase_adjustment.attr) { if (!info->adjphase || !info->getmaxphase) mode = 0; + } else if (attr == &dev_attr_ts_point.attr) { + if (!info->get_ts_point && !info->set_ts_point) + mode = 0; } return mode; diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h index c892d22ce0a7..921d6615bd39 100644 --- a/include/linux/ptp_clock_kernel.h +++ b/include/linux/ptp_clock_kernel.h @@ -55,6 +55,23 @@ struct ptp_system_timestamp { clockid_t clockid; }; +/** + * enum ptp_ts_point - possible timestamp latch points (IEEE 802.3cx) + * @PTP_TS_POINT_SFD: timestamp latched at the beginning of sending Start + * of Frame Delimiter (SFD) + * @PTP_TS_POINT_POST_SFD: timestamp latched after the end of sending Start + * of Frame Delimiter (SFD) + */ +enum ptp_ts_point { + PTP_TS_POINT_SFD, + PTP_TS_POINT_POST_SFD, + + /* private: */ + __PTP_TS_POINT_MAX +}; + +#define PTP_TS_POINT_MAX (__PTP_TS_POINT_MAX - 1) + /** * struct ptp_clock_info - describes a PTP hardware clock * @@ -159,6 +176,14 @@ struct ptp_system_timestamp { * scheduling time (>=0) or negative value in case further * scheduling is not required. * + * @set_ts_point: Request change of timestamp latch point, as the timestamp + * could be latched at the beginning or after the end of start + * frame delimiter (SFD), as described in IEEE 802.3cx + * specification. + * + * @get_ts_point: Obtain the timestamp measurement latch point, counterpart of + * .set_ts_point() for getting currently configured value. + * * Drivers should embed their ptp_clock_info within a private * structure, obtaining a reference to it using container_of(). * @@ -195,6 +220,10 @@ struct ptp_clock_info { int (*verify)(struct ptp_clock_info *ptp, unsigned int pin, enum ptp_pin_function func, unsigned int chan); long (*do_aux_work)(struct ptp_clock_info *ptp); + int (*set_ts_point)(struct ptp_clock_info *ptp, + enum ptp_ts_point point); + int (*get_ts_point)(struct ptp_clock_info *ptp, + enum ptp_ts_point *point); }; struct ptp_clock;