Message ID | 20190816163157.25314-2-h.feurstein@gmail.com |
---|---|
State | Changes Requested |
Delegated to: | David Miller |
Headers | show |
Series | Improve phc2sys precision for mv88e6xxx switch in combination with imx6-fec | expand |
On Fri, Aug 16, 2019 at 06:31:55PM +0200, Hubert Feurstein wrote: > > int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); > int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); > +int __mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val, > + struct ptp_system_timestamp *sts); > > int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); > int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum); > int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); > int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val); > +int mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val, > + struct ptp_system_timestamp *sts); > +int mdiobus_write_sts_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val, > + struct ptp_system_timestamp *sts); Following the pattern, you have made three new global mdiobus_write_sts() functions. However, your patch set only uses mdiobus_write_sts_nested(). Please don't add global functions with no users. Let the first user add them, if and when the need arises. Thanks, Richard
On Fri, Aug 16, 2019 at 06:31:55PM +0200, Hubert Feurstein wrote: > In order to improve the synchronisation precision of phc2sys (from > the linuxptp project) for devices like switches which are attached > to the MDIO bus, it is necessary the get the system timestamps as > close as possible to the access which causes the PTP timestamp > register to be snapshotted in the switch hardware. Usually this is > triggered by an MDIO write access, the snapshotted timestamp is then > transferred by several MDIO reads. > > This patch adds the required infrastructure to solve the problem described > above. > > Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com> > --- > drivers/net/phy/mdio_bus.c | 105 +++++++++++++++++++++++++++++++++++++ > include/linux/mdio.h | 7 +++ > include/linux/phy.h | 25 +++++++++ > 3 files changed, 137 insertions(+) > > diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c > index bd04fe762056..167a21f267fa 100644 > --- a/drivers/net/phy/mdio_bus.c > +++ b/drivers/net/phy/mdio_bus.c > @@ -34,6 +34,7 @@ > #include <linux/phy.h> > #include <linux/io.h> > #include <linux/uaccess.h> > +#include <linux/ptp_clock_kernel.h> > > #define CREATE_TRACE_POINTS > #include <trace/events/mdio.h> > @@ -697,6 +698,110 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) > } > EXPORT_SYMBOL(mdiobus_write); > > +/** > + * __mdiobus_write_sts - Unlocked version of the mdiobus_write_sts function > + * @bus: the mii_bus struct > + * @addr: the phy address > + * @regnum: register number to write > + * @val: value to write to @regnum > + * @sts: the ptp system timestamp > + * > + * Write a MDIO bus register and request the MDIO bus driver to take the > + * system timestamps when sts-pointer is valid. When the bus driver doesn't > + * support this, the timestamps are taken in this function instead. > + * > + * In order to improve the synchronisation precision of phc2sys (from > + * the linuxptp project) for devices like switches which are attached > + * to the MDIO bus, it is necessary the get the system timestamps as > + * close as possible to the access which causes the PTP timestamp > + * register to be snapshotted in the switch hardware. Usually this is > + * triggered by an MDIO write access, the snapshotted timestamp is then > + * transferred by several MDIO reads. > + * > + * Caller must hold the mdio bus lock. > + * > + * NOTE: MUST NOT be called from interrupt context. > + */ > +int __mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val, > + struct ptp_system_timestamp *sts) > +{ > + int retval; > + > + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); > + > + if (!bus->ptp_sts_supported) > + ptp_read_system_prets(sts); How expensive is ptp_read_system_prets()? My original suggestion was to unconditionally call it here, and then let the driver overwrite it if it supports finer grained time stamping. MDIO is slow, so as long as ptp_read_system_prets() is not too expensive, i prefer KISS. Andrew
Hi Andrew, On Mon, 19 Aug 2019 at 16:17, Andrew Lunn <andrew@lunn.ch> wrote: > > On Fri, Aug 16, 2019 at 06:31:55PM +0200, Hubert Feurstein wrote: > > In order to improve the synchronisation precision of phc2sys (from > > the linuxptp project) for devices like switches which are attached > > to the MDIO bus, it is necessary the get the system timestamps as > > close as possible to the access which causes the PTP timestamp > > register to be snapshotted in the switch hardware. Usually this is > > triggered by an MDIO write access, the snapshotted timestamp is then > > transferred by several MDIO reads. > > > > This patch adds the required infrastructure to solve the problem described > > above. > > > > Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com> > > --- > > drivers/net/phy/mdio_bus.c | 105 +++++++++++++++++++++++++++++++++++++ > > include/linux/mdio.h | 7 +++ > > include/linux/phy.h | 25 +++++++++ > > 3 files changed, 137 insertions(+) > > > > diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c > > index bd04fe762056..167a21f267fa 100644 > > --- a/drivers/net/phy/mdio_bus.c > > +++ b/drivers/net/phy/mdio_bus.c > > @@ -34,6 +34,7 @@ > > #include <linux/phy.h> > > #include <linux/io.h> > > #include <linux/uaccess.h> > > +#include <linux/ptp_clock_kernel.h> > > > > #define CREATE_TRACE_POINTS > > #include <trace/events/mdio.h> > > @@ -697,6 +698,110 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) > > } > > EXPORT_SYMBOL(mdiobus_write); > > > > +/** > > + * __mdiobus_write_sts - Unlocked version of the mdiobus_write_sts function > > + * @bus: the mii_bus struct > > + * @addr: the phy address > > + * @regnum: register number to write > > + * @val: value to write to @regnum > > + * @sts: the ptp system timestamp > > + * > > + * Write a MDIO bus register and request the MDIO bus driver to take the > > + * system timestamps when sts-pointer is valid. When the bus driver doesn't > > + * support this, the timestamps are taken in this function instead. > > + * > > + * In order to improve the synchronisation precision of phc2sys (from > > + * the linuxptp project) for devices like switches which are attached > > + * to the MDIO bus, it is necessary the get the system timestamps as > > + * close as possible to the access which causes the PTP timestamp > > + * register to be snapshotted in the switch hardware. Usually this is > > + * triggered by an MDIO write access, the snapshotted timestamp is then > > + * transferred by several MDIO reads. > > + * > > + * Caller must hold the mdio bus lock. > > + * > > + * NOTE: MUST NOT be called from interrupt context. > > + */ > > +int __mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val, > > + struct ptp_system_timestamp *sts) > > +{ > > + int retval; > > + > > + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); > > + > > + if (!bus->ptp_sts_supported) > > + ptp_read_system_prets(sts); > > How expensive is ptp_read_system_prets()? My original suggestion was > to unconditionally call it here, and then let the driver overwrite it > if it supports finer grained time stamping. MDIO is slow, so as long > as ptp_read_system_prets() is not too expensive, i prefer KISS. > > Andrew While that works for the pre_ts, it doesn't work for the post_ts (the MDIO bus core will unconditionally overwrite the system timestamp from the driver). Unless you're suggesting to keep the pre_ts unconditional and the post_ts under the "if" condition, which is a bit odd. According to my tests with a scope (measuring the width between SPI transfers with and without the ptp_read_system_*ts calls), two calls to ktime_get_real_ts64 amount to around 750 ns on a 1200 MHz Cortex A7 core, or around 90 clock cycles. Regards, -Vladimir
On Mon, 19 Aug 2019 at 16:34, Vladimir Oltean <olteanv@gmail.com> wrote: > > Hi Andrew, > > On Mon, 19 Aug 2019 at 16:17, Andrew Lunn <andrew@lunn.ch> wrote: > > > > On Fri, Aug 16, 2019 at 06:31:55PM +0200, Hubert Feurstein wrote: > > > In order to improve the synchronisation precision of phc2sys (from > > > the linuxptp project) for devices like switches which are attached > > > to the MDIO bus, it is necessary the get the system timestamps as > > > close as possible to the access which causes the PTP timestamp > > > register to be snapshotted in the switch hardware. Usually this is > > > triggered by an MDIO write access, the snapshotted timestamp is then > > > transferred by several MDIO reads. > > > > > > This patch adds the required infrastructure to solve the problem described > > > above. > > > > > > Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com> > > > --- > > > drivers/net/phy/mdio_bus.c | 105 +++++++++++++++++++++++++++++++++++++ > > > include/linux/mdio.h | 7 +++ > > > include/linux/phy.h | 25 +++++++++ > > > 3 files changed, 137 insertions(+) > > > > > > diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c > > > index bd04fe762056..167a21f267fa 100644 > > > --- a/drivers/net/phy/mdio_bus.c > > > +++ b/drivers/net/phy/mdio_bus.c > > > @@ -34,6 +34,7 @@ > > > #include <linux/phy.h> > > > #include <linux/io.h> > > > #include <linux/uaccess.h> > > > +#include <linux/ptp_clock_kernel.h> > > > > > > #define CREATE_TRACE_POINTS > > > #include <trace/events/mdio.h> > > > @@ -697,6 +698,110 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) > > > } > > > EXPORT_SYMBOL(mdiobus_write); > > > > > > +/** > > > + * __mdiobus_write_sts - Unlocked version of the mdiobus_write_sts function > > > + * @bus: the mii_bus struct > > > + * @addr: the phy address > > > + * @regnum: register number to write > > > + * @val: value to write to @regnum > > > + * @sts: the ptp system timestamp > > > + * > > > + * Write a MDIO bus register and request the MDIO bus driver to take the > > > + * system timestamps when sts-pointer is valid. When the bus driver doesn't > > > + * support this, the timestamps are taken in this function instead. > > > + * > > > + * In order to improve the synchronisation precision of phc2sys (from > > > + * the linuxptp project) for devices like switches which are attached > > > + * to the MDIO bus, it is necessary the get the system timestamps as > > > + * close as possible to the access which causes the PTP timestamp > > > + * register to be snapshotted in the switch hardware. Usually this is > > > + * triggered by an MDIO write access, the snapshotted timestamp is then > > > + * transferred by several MDIO reads. > > > + * > > > + * Caller must hold the mdio bus lock. > > > + * > > > + * NOTE: MUST NOT be called from interrupt context. > > > + */ > > > +int __mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val, > > > + struct ptp_system_timestamp *sts) > > > +{ > > > + int retval; > > > + > > > + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); > > > + > > > + if (!bus->ptp_sts_supported) > > > + ptp_read_system_prets(sts); > > > > How expensive is ptp_read_system_prets()? My original suggestion was > > to unconditionally call it here, and then let the driver overwrite it > > if it supports finer grained time stamping. MDIO is slow, so as long > > as ptp_read_system_prets() is not too expensive, i prefer KISS. > > > > Andrew > > While that works for the pre_ts, it doesn't work for the post_ts (the > MDIO bus core will unconditionally overwrite the system timestamp from > the driver). > Unless you're suggesting to keep the pre_ts unconditional and the > post_ts under the "if" condition, which is a bit odd. > According to my tests with a scope (measuring the width between SPI > transfers with and without the ptp_read_system_*ts calls), two calls > to ktime_get_real_ts64 amount to around 750 ns on a 1200 MHz Cortex A7 > core, or around 90 clock cycles. 900 clock cycles, my bad. > > Regards, > -Vladimir
> > > How expensive is ptp_read_system_prets()? My original suggestion was > > > to unconditionally call it here, and then let the driver overwrite it > > > if it supports finer grained time stamping. MDIO is slow, so as long > > > as ptp_read_system_prets() is not too expensive, i prefer KISS. > > > > > > Andrew > > > > While that works for the pre_ts, it doesn't work for the post_ts (the > > MDIO bus core will unconditionally overwrite the system timestamp from > > the driver). > > Unless you're suggesting to keep the pre_ts unconditional and the > > post_ts under the "if" condition, which is a bit odd. > > According to my tests with a scope (measuring the width between SPI > > transfers with and without the ptp_read_system_*ts calls), two calls > > to ktime_get_real_ts64 amount to around 750 ns on a 1200 MHz Cortex A7 > > core, or around 90 clock cycles. > > 900 clock cycles, my bad. That is quite a lot. I was just expecting it to read a free running clock and maybe do some unit conversions. 900 cycles suggests it is doing a lot more. So please keep with the idea of the bus driver indicating if it supports the time stamping. But please make it a generic bus->flags, and bit 0 indicating time stamping. At some point in the future, it would be useful to indicate if the bus supports c45, which would be another use of flags. Thanks Andrew
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index bd04fe762056..167a21f267fa 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -34,6 +34,7 @@ #include <linux/phy.h> #include <linux/io.h> #include <linux/uaccess.h> +#include <linux/ptp_clock_kernel.h> #define CREATE_TRACE_POINTS #include <trace/events/mdio.h> @@ -697,6 +698,110 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) } EXPORT_SYMBOL(mdiobus_write); +/** + * __mdiobus_write_sts - Unlocked version of the mdiobus_write_sts function + * @bus: the mii_bus struct + * @addr: the phy address + * @regnum: register number to write + * @val: value to write to @regnum + * @sts: the ptp system timestamp + * + * Write a MDIO bus register and request the MDIO bus driver to take the + * system timestamps when sts-pointer is valid. When the bus driver doesn't + * support this, the timestamps are taken in this function instead. + * + * In order to improve the synchronisation precision of phc2sys (from + * the linuxptp project) for devices like switches which are attached + * to the MDIO bus, it is necessary the get the system timestamps as + * close as possible to the access which causes the PTP timestamp + * register to be snapshotted in the switch hardware. Usually this is + * triggered by an MDIO write access, the snapshotted timestamp is then + * transferred by several MDIO reads. + * + * Caller must hold the mdio bus lock. + * + * NOTE: MUST NOT be called from interrupt context. + */ +int __mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val, + struct ptp_system_timestamp *sts) +{ + int retval; + + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); + + if (!bus->ptp_sts_supported) + ptp_read_system_prets(sts); + + bus->ptp_sts = sts; + retval = __mdiobus_write(bus, addr, regnum, val); + bus->ptp_sts = NULL; + + if (!bus->ptp_sts_supported) + ptp_read_system_postts(sts); + + return retval; +} +EXPORT_SYMBOL(__mdiobus_write_sts); + +/** + * mdiobus_write_sts - Convenience function for writing a given MII mgmt + * register + * + * @bus: the mii_bus struct + * @addr: the phy address + * @regnum: register number to write + * @val: value to write to @regnum + * @sts: the ptp system timestamp + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val, + struct ptp_system_timestamp *sts) +{ + int retval; + + BUG_ON(in_interrupt()); + + mutex_lock(&bus->mdio_lock); + retval = __mdiobus_write_sts(bus, addr, regnum, val, sts); + mutex_unlock(&bus->mdio_lock); + + return retval; +} +EXPORT_SYMBOL(mdiobus_write_sts); + +/** + * mdiobus_write_sts_nested - Nested version of the mdiobus_write_sts function + * @bus: the mii_bus struct + * @addr: the phy address + * @regnum: register number to write + * @val: value to write to @regnum + * @sts: the ptp system timestamp + * + * In case of nested MDIO bus access avoid lockdep false positives by + * using mutex_lock_nested(). + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int mdiobus_write_sts_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val, + struct ptp_system_timestamp *sts) +{ + int retval; + + BUG_ON(in_interrupt()); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + retval = __mdiobus_write_sts(bus, addr, regnum, val, sts); + mutex_unlock(&bus->mdio_lock); + + return retval; +} +EXPORT_SYMBOL(mdiobus_write_sts_nested); + /** * mdio_bus_match - determine if given MDIO driver supports the given * MDIO device diff --git a/include/linux/mdio.h b/include/linux/mdio.h index e8242ad88c81..d65625c75b15 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -9,6 +9,7 @@ #include <uapi/linux/mdio.h> #include <linux/mod_devicetable.h> +struct ptp_system_timestamp; struct gpio_desc; struct mii_bus; @@ -305,11 +306,17 @@ static inline void mii_10gbt_stat_mod_linkmode_lpa_t(unsigned long *advertising, int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); +int __mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val, + struct ptp_system_timestamp *sts); int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum); int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val); +int mdiobus_write_sts(struct mii_bus *bus, int addr, u32 regnum, u16 val, + struct ptp_system_timestamp *sts); +int mdiobus_write_sts_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val, + struct ptp_system_timestamp *sts); int mdiobus_register_device(struct mdio_device *mdiodev); int mdiobus_unregister_device(struct mdio_device *mdiodev); diff --git a/include/linux/phy.h b/include/linux/phy.h index 462b90b73f93..15afe9c5256b 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -252,6 +252,31 @@ struct mii_bus { int reset_delay_us; /* RESET GPIO descriptor pointer */ struct gpio_desc *reset_gpiod; + + /* PTP system timestamping support + * + * In order to improve the synchronisation precision of phc2sys (from + * the linuxptp project) for devices like switches which are attached + * to the MDIO bus, it is necessary the get the system timestamps as + * close as possible to the access which causes the PTP timestamp + * register to be snapshotted in the switch hardware. Usually this is + * triggered by an MDIO write access, the snapshotted timestamp is then + * transferred by several MDIO reads. + * + * The switch driver can use mdio_write_sts*() to pass through the + * system timestamp pointer @ptp_sts to the MDIO bus driver. The bus + * driver simply has to do the following calls in its write handler: + * ptp_read_system_prets(bus->ptp_sts); + * writel(value, mdio-register) + * ptp_read_system_postts(bus->ptp_sts); + * + * The ptp_read_system_*ts functions already check the ptp_sts pointer. + * + * @ptp_sts_supported: Must be set to true when the MDIO bus driver + * takes the timestamps as described above. + */ + struct ptp_system_timestamp *ptp_sts; + bool ptp_sts_supported; }; #define to_mii_bus(d) container_of(d, struct mii_bus, dev)
In order to improve the synchronisation precision of phc2sys (from the linuxptp project) for devices like switches which are attached to the MDIO bus, it is necessary the get the system timestamps as close as possible to the access which causes the PTP timestamp register to be snapshotted in the switch hardware. Usually this is triggered by an MDIO write access, the snapshotted timestamp is then transferred by several MDIO reads. This patch adds the required infrastructure to solve the problem described above. Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com> --- drivers/net/phy/mdio_bus.c | 105 +++++++++++++++++++++++++++++++++++++ include/linux/mdio.h | 7 +++ include/linux/phy.h | 25 +++++++++ 3 files changed, 137 insertions(+)