Re: [PATCH net-next v17 04/14] net: Change the API of PHY default timestamp to MAC

From: Jacob Keller
Date: Mon Jul 15 2024 - 19:37:26 EST




On 7/9/2024 6:53 AM, Kory Maincent wrote:
> Change the API to select MAC default time stamping instead of the PHY.
> Indeed the PHY is closer to the wire therefore theoretically it has less
> delay than the MAC timestamping but the reality is different. Due to lower
> time stamping clock frequency, latency in the MDIO bus and no PHC hardware
> synchronization between different PHY, the PHY PTP is often less precise
> than the MAC. The exception is for PHY designed specially for PTP case but
> these devices are not very widespread. For not breaking the compatibility
> default_timestamp flag has been introduced in phy_device that is set by
> the phy driver to know we are using the old API behavior.
>

This description feels like it is making a pretty broad generalization
about devices. The specifics of whether MAC or PHY timestamping is
better will be device dependent.

It looks like you introduce a default_timestamp flag to ensure existing
devices default to PHY? I assume your goal here is to discourage this
and not allow setting it for new devices? Or do we want to let device
driver authors decide which is a better default?

> Reviewed-by: Rahul Rameshbabu <rrameshbabu@xxxxxxxxxx>
> Signed-off-by: Kory Maincent <kory.maincent@xxxxxxxxxxx>

Overall this makes sense, with a couple questions I had during review.

Reviewed-by: Jacob Keller <jacob.e.keller@xxxxxxxxx>

> ---
> diff --git a/include/linux/phy.h b/include/linux/phy.h
> index bd68f9d8e74f..e7a38137211c 100644
> --- a/include/linux/phy.h
> +++ b/include/linux/phy.h
> @@ -616,6 +616,8 @@ struct macsec_ops;
> * handling shall be postponed until PHY has resumed
> * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
> * requiring a rerun of the interrupt handler after resume
> + * @default_timestamp: Flag indicating whether we are using the phy
> + * timestamp as the default one

This is clearly intended to ensure existing drivers maintain legacy
behavior. But what is our policy going forward for new devices? Do we
want to leave it up to PHY driver authors?

> * @interface: enum phy_interface_t value
> * @possible_interfaces: bitmap if interface modes that the attached PHY
> * will switch between depending on media speed.
> @@ -681,6 +683,8 @@ struct phy_device {
> unsigned irq_suspended:1;
> unsigned irq_rerun:1;
>
> + unsigned default_timestamp:1;
> +
> int rate_matching;
>
> enum phy_state state;
> @@ -1625,6 +1629,21 @@ static inline void phy_txtstamp(struct phy_device *phydev, struct sk_buff *skb,
> phydev->mii_ts->txtstamp(phydev->mii_ts, skb, type);
> }
>
> +/**
> + * phy_is_default_hwtstamp - Is the PHY hwtstamp the default timestamp
> + * @phydev: Pointer to phy_device
> + *
> + * This is used to get default timestamping device taking into account
> + * the new API choice, which is selecting the timestamping from MAC by
> + * default if the phydev does not have default_timestamp flag enabled.
> + *
> + * Return: True if phy is the default hw timestamp, false otherwise.
> + */
> +static inline bool phy_is_default_hwtstamp(struct phy_device *phydev)
> +{
> + return phy_has_hwtstamp(phydev) && phydev->default_timestamp;
> +}
> +
> /**
> * phy_is_internal - Convenience function for testing if a PHY is internal
> * @phydev: the phy_device struct
> diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
> index 6aaa8326bf8f..36cea843381f 100644
> --- a/net/core/dev_ioctl.c
> +++ b/net/core/dev_ioctl.c
> @@ -259,9 +259,7 @@ static int dev_eth_ioctl(struct net_device *dev,
> * @dev: Network device
> * @cfg: Timestamping configuration structure
> *
> - * Helper for enforcing a common policy that phylib timestamping, if available,
> - * should take precedence in front of hardware timestamping provided by the
> - * netdev.
> + * Helper for calling the default hardware provider timestamping.
> *
> * Note: phy_mii_ioctl() only handles SIOCSHWTSTAMP (not SIOCGHWTSTAMP), and
> * there only exists a phydev->mii_ts->hwtstamp() method. So this will return
> @@ -271,7 +269,7 @@ static int dev_eth_ioctl(struct net_device *dev,
> int dev_get_hwtstamp_phylib(struct net_device *dev,
> struct kernel_hwtstamp_config *cfg)
> {
> - if (phy_has_hwtstamp(dev->phydev))
> + if (phy_is_default_hwtstamp(dev->phydev))
> return phy_hwtstamp_get(dev->phydev, cfg);
>
> return dev->netdev_ops->ndo_hwtstamp_get(dev, cfg);
> @@ -327,7 +325,7 @@ int dev_set_hwtstamp_phylib(struct net_device *dev,
> struct netlink_ext_ack *extack)
> {
> const struct net_device_ops *ops = dev->netdev_ops;
> - bool phy_ts = phy_has_hwtstamp(dev->phydev);
> + bool phy_ts = phy_is_default_hwtstamp(dev->phydev);
> struct kernel_hwtstamp_config old_cfg = {};
> bool changed = false;
> int err;
> diff --git a/net/core/timestamping.c b/net/core/timestamping.c
> index 04840697fe79..3717fb152ecc 100644
> --- a/net/core/timestamping.c
> +++ b/net/core/timestamping.c
> @@ -25,7 +25,8 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)
> struct sk_buff *clone;
> unsigned int type;
>
> - if (!skb->sk)
> + if (!skb->sk || !skb->dev ||
> + !phy_is_default_hwtstamp(skb->dev->phydev))

I don't follow why this check is added and its not calling something
like "phy_is_current_hwtstamp"? I guess because we don't yet have a way
to select between MAC/PHY at this point in the series? Ok.

> return;
>
> type = classify(skb);
> @@ -47,7 +48,7 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)
> struct mii_timestamper *mii_ts;
> unsigned int type;
>
> - if (!skb->dev || !skb->dev->phydev || !skb->dev->phydev->mii_ts)
> + if (!skb->dev || !phy_is_default_hwtstamp(skb->dev->phydev))
> return false;
>
> if (skb_headroom(skb) < ETH_HLEN)
> diff --git a/net/ethtool/common.c b/net/ethtool/common.c
> index 6b2a360dcdf0..01b7550f12c6 100644
> --- a/net/ethtool/common.c
> +++ b/net/ethtool/common.c
> @@ -637,7 +637,7 @@ int __ethtool_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
> memset(info, 0, sizeof(*info));
> info->cmd = ETHTOOL_GET_TS_INFO;
>
> - if (phy_has_tsinfo(phydev))
> + if (phy_is_default_hwtstamp(phydev) && phy_has_tsinfo(phydev))
> return phy_ts_info(phydev, info);
> if (ops->get_ts_info)
> return ops->get_ts_info(dev, info);
>