net: Change the API of PHY default timestamp to MAC
authorKory Maincent <kory.maincent@bootlin.com>
Tue, 9 Jul 2024 13:53:36 +0000 (15:53 +0200)
committerJakub Kicinski <kuba@kernel.org>
Mon, 15 Jul 2024 15:02:26 +0000 (08:02 -0700)
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.

Reviewed-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Link: https://patch.msgid.link/20240709-feature_ptp_netnext-v17-4-b5317f50df2a@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/bcm-phy-ptp.c
drivers/net/phy/dp83640.c
drivers/net/phy/micrel.c
drivers/net/phy/mscc/mscc_ptp.c
drivers/net/phy/nxp-c45-tja11xx.c
include/linux/phy.h
net/core/dev_ioctl.c
net/core/timestamping.c
net/ethtool/common.c

index 617d384d4551ac31dd8a7752b24c9087883e70d2..d3e825c951eef1b74068cb90c9970d379698b559 100644 (file)
@@ -931,6 +931,9 @@ struct bcm_ptp_private *bcm_ptp_probe(struct phy_device *phydev)
                return ERR_CAST(clock);
        priv->ptp_clock = clock;
 
+       /* Timestamp selected by default to keep legacy API */
+       phydev->default_timestamp = true;
+
        priv->phydev = phydev;
        bcm_ptp_init(priv);
 
index 5c42c47dc56469349a0162e35e928812d339746e..d3e72d5c1472fda60358b575efd7c7be27cb5816 100644 (file)
@@ -1447,6 +1447,8 @@ static int dp83640_probe(struct phy_device *phydev)
        for (i = 0; i < MAX_RXTS; i++)
                list_add(&dp83640->rx_pool_data[i].list, &dp83640->rxpool);
 
+       /* Timestamp selected by default to keep legacy API */
+       phydev->default_timestamp = true;
        phydev->mii_ts = &dp83640->mii_ts;
        phydev->priv = dp83640;
 
index ebafedde0ab745467a130225a1620ac47d0cd7df..8d57225d85757d59534740a5bc8e12b7bd528a15 100644 (file)
@@ -3781,6 +3781,9 @@ static void lan8814_ptp_init(struct phy_device *phydev)
        ptp_priv->mii_ts.ts_info  = lan8814_ts_info;
 
        phydev->mii_ts = &ptp_priv->mii_ts;
+
+       /* Timestamp selected by default to keep legacy API */
+       phydev->default_timestamp = true;
 }
 
 static int lan8814_ptp_probe_once(struct phy_device *phydev)
@@ -5279,6 +5282,9 @@ static int lan8841_probe(struct phy_device *phydev)
 
        phydev->mii_ts = &ptp_priv->mii_ts;
 
+       /* Timestamp selected by default to keep legacy API */
+       phydev->default_timestamp = true;
+
        return 0;
 }
 
index eb0b032cb613d1c91c798323664918707a3dd0a3..e66d20eff7c458f36cee95b35184ef84fa7067e1 100644 (file)
@@ -1570,6 +1570,9 @@ int vsc8584_ptp_probe(struct phy_device *phydev)
                return PTR_ERR(vsc8531->load_save);
        }
 
+       /* Timestamp selected by default to keep legacy API */
+       phydev->default_timestamp = true;
+
        vsc8531->ptp->phydev = phydev;
 
        return 0;
index 3cf614b4cd5205c821375020e5962f3d97fa7eef..d18c133e6013db7fd19f62a62697c174d946b46a 100644 (file)
@@ -1660,6 +1660,9 @@ static int nxp_c45_probe(struct phy_device *phydev)
                priv->mii_ts.ts_info = nxp_c45_ts_info;
                phydev->mii_ts = &priv->mii_ts;
                ret = nxp_c45_init_ptp_clock(priv);
+
+               /* Timestamp selected by default to keep legacy API */
+               phydev->default_timestamp = true;
        } else {
                phydev_dbg(phydev, "PTP support not enabled even if the phy supports it");
        }
index bd68f9d8e74f19ec5e461b4761ef275b10ec9066..e7a38137211cdd99a334786422555150623217a8 100644 (file)
@@ -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
  * @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
index b9719ed3c3fd5648bd46c3e9c4d50d487dae795f..8592c052c0f4f37c102777a68e44d52860288493 100644 (file)
@@ -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,
 static 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;
index 04840697fe79fa5e1f4e2908cac8cb8ad13ffc40..3717fb152ecc4f8b81aeb6252b9f4d8a2242da69 100644 (file)
@@ -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))
                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)
index 6b2a360dcdf069218becaf8cbd79ad3faefbcf90..01b7550f12c60683b0d4453457ddccfe0c9d131f 100644 (file)
@@ -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);