Commit 34074639 authored by Sergey Organov's avatar Sergey Organov Committed by Jakub Kicinski

net: fec: fix hardware time stamping by external devices

Fix support for external PTP-aware devices such as DSA or PTP PHY:

Make sure we never time stamp tx packets when hardware time stamping
is disabled.

Check for PTP PHY being in use and then pass ioctls related to time
stamping of Ethernet packets to the PTP PHY rather than handle them
ourselves. In addition, disable our own hardware time stamping in this
case.

Fixes: 6605b730 ("FEC: Add time stamping code and a PTP hardware clock")
Signed-off-by: default avatarSergey Organov <sorganov@gmail.com>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Acked-by: default avatarVladimir Oltean <olteanv@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent c28d9a28
...@@ -590,6 +590,7 @@ struct fec_enet_private { ...@@ -590,6 +590,7 @@ struct fec_enet_private {
void fec_ptp_init(struct platform_device *pdev, int irq_idx); void fec_ptp_init(struct platform_device *pdev, int irq_idx);
void fec_ptp_stop(struct platform_device *pdev); void fec_ptp_stop(struct platform_device *pdev);
void fec_ptp_start_cyclecounter(struct net_device *ndev); void fec_ptp_start_cyclecounter(struct net_device *ndev);
void fec_ptp_disable_hwts(struct net_device *ndev);
int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr); int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
......
...@@ -1294,7 +1294,12 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) ...@@ -1294,7 +1294,12 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
ndev->stats.tx_bytes += skb->len; ndev->stats.tx_bytes += skb->len;
} }
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) && /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who
* are to time stamp the packet, so we still need to check time
* stamping enabled flag.
*/
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
fep->hwts_tx_en) &&
fep->bufdesc_ex) { fep->bufdesc_ex) {
struct skb_shared_hwtstamps shhwtstamps; struct skb_shared_hwtstamps shhwtstamps;
struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
...@@ -2723,11 +2728,17 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) ...@@ -2723,11 +2728,17 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
return -ENODEV; return -ENODEV;
if (fep->bufdesc_ex) { if (fep->bufdesc_ex) {
if (cmd == SIOCSHWTSTAMP) bool use_fec_hwts = !phy_has_hwtstamp(phydev);
if (cmd == SIOCSHWTSTAMP) {
if (use_fec_hwts)
return fec_ptp_set(ndev, rq); return fec_ptp_set(ndev, rq);
if (cmd == SIOCGHWTSTAMP) fec_ptp_disable_hwts(ndev);
} else if (cmd == SIOCGHWTSTAMP) {
if (use_fec_hwts)
return fec_ptp_get(ndev, rq); return fec_ptp_get(ndev, rq);
} }
}
return phy_mii_ioctl(phydev, rq, cmd); return phy_mii_ioctl(phydev, rq, cmd);
} }
......
...@@ -452,6 +452,18 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, ...@@ -452,6 +452,18 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
/**
* fec_ptp_disable_hwts - disable hardware time stamping
* @ndev: pointer to net_device
*/
void fec_ptp_disable_hwts(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
fep->hwts_tx_en = 0;
fep->hwts_rx_en = 0;
}
int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr) int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr)
{ {
struct fec_enet_private *fep = netdev_priv(ndev); struct fec_enet_private *fep = netdev_priv(ndev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment