diff options
author | 2023-11-14 12:28:41 +0100 | |
---|---|---|
committer | 2023-11-18 14:52:57 +0000 | |
commit | 0f7f463d4821a4f52fa5c0a961389e651d50c384 (patch) | |
tree | 76d682494226939dac8adba05bf57ae34b827357 /drivers | |
parent | net: Replace hwtstamp_source by timestamping layer (diff) | |
download | linux-0f7f463d4821a4f52fa5c0a961389e651d50c384.tar.gz linux-0f7f463d4821a4f52fa5c0a961389e651d50c384.tar.bz2 linux-0f7f463d4821a4f52fa5c0a961389e651d50c384.zip |
net: Change the API of PHY default timestamp to MAC
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 I
introduce a default_timestamp flag in phy_device that is set by the phy
driver to know we are using the old API behavior.
The phy_set_timestamp function is called at each call of phy_attach_direct.
In case of MAC driver using phylink this function is called when the
interface is turned up. Then if the interface goes down and up again the
last choice of timestamp will be overwritten by the default choice.
A solution could be to cache the timestamp status but it can bring other
issues. In case of SFP, if we change the module, it doesn't make sense to
blindly re-set the timestamp back to PHY, if the new module has a PHY with
mediocre timestamping capabilities.
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/phy/bcm-phy-ptp.c | 3 | ||||
-rw-r--r-- | drivers/net/phy/dp83640.c | 3 | ||||
-rw-r--r-- | drivers/net/phy/micrel.c | 6 | ||||
-rw-r--r-- | drivers/net/phy/mscc/mscc_ptp.c | 2 | ||||
-rw-r--r-- | drivers/net/phy/nxp-c45-tja11xx.c | 3 | ||||
-rw-r--r-- | drivers/net/phy/phy_device.c | 37 |
6 files changed, 54 insertions, 0 deletions
diff --git a/drivers/net/phy/bcm-phy-ptp.c b/drivers/net/phy/bcm-phy-ptp.c index 617d384d4551..d3e825c951ee 100644 --- a/drivers/net/phy/bcm-phy-ptp.c +++ b/drivers/net/phy/bcm-phy-ptp.c @@ -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); diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 5c42c47dc564..64fd1a109c0f 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1450,6 +1450,9 @@ static int dp83640_probe(struct phy_device *phydev) phydev->mii_ts = &dp83640->mii_ts; phydev->priv = dp83640; + /* Timestamp selected by default to keep legacy API */ + phydev->default_timestamp = true; + spin_lock_init(&dp83640->rx_lock); skb_queue_head_init(&dp83640->rx_queue); skb_queue_head_init(&dp83640->tx_queue); diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index bd4cd082662f..2b8dd0131926 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -3158,6 +3158,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) @@ -4586,6 +4589,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; } diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c index eb0b032cb613..fd174eb06d4a 100644 --- a/drivers/net/phy/mscc/mscc_ptp.c +++ b/drivers/net/phy/mscc/mscc_ptp.c @@ -1570,6 +1570,8 @@ 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; diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 780ad353cf55..0515c7b979db 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -1658,6 +1658,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"); } diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2ce74593d6e4..8c4794631daa 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1412,6 +1412,26 @@ int phy_sfp_probe(struct phy_device *phydev, EXPORT_SYMBOL(phy_sfp_probe); /** + * phy_set_timestamp - set the default selected timestamping device + * @dev: Pointer to net_device + * @phydev: Pointer to phy_device + * + * This is used to set 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. + */ +static void phy_set_timestamp(struct net_device *dev, struct phy_device *phydev) +{ + const struct ethtool_ops *ops = dev->ethtool_ops; + + if (!phy_has_tsinfo(phydev)) + return; + + if (!ops->get_ts_info || phydev->default_timestamp) + dev->ts_layer = PHY_TIMESTAMPING; +} + +/** * phy_attach_direct - attach a network device to a given PHY device pointer * @dev: network device to attach * @phydev: Pointer to phy_device to attach @@ -1484,6 +1504,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, phydev->phy_link_change = phy_link_change; if (dev) { + phy_set_timestamp(dev, phydev); phydev->attached_dev = dev; dev->phydev = phydev; @@ -1812,6 +1833,22 @@ void phy_detach(struct phy_device *phydev) phy_suspend(phydev); if (dev) { + const struct ethtool_ops *ops = dev->ethtool_ops; + struct ethtool_ts_info ts_info = {0}; + + if (ops->get_ts_info) { + ops->get_ts_info(dev, &ts_info); + if ((ts_info.so_timestamping & + SOF_TIMESTAMPING_HARDWARE_MASK) == + SOF_TIMESTAMPING_HARDWARE_MASK) + dev->ts_layer = MAC_TIMESTAMPING; + else if ((ts_info.so_timestamping & + SOF_TIMESTAMPING_SOFTWARE_MASK) == + SOF_TIMESTAMPING_SOFTWARE_MASK) + dev->ts_layer = SOFTWARE_TIMESTAMPING; + } else { + dev->ts_layer = NO_TIMESTAMPING; + } phydev->attached_dev->phydev = NULL; phydev->attached_dev = NULL; } |