diff mbox series

[v3,net] net: fec: fix hardware time stamping by external devices

Message ID 20200714162802.11926-1-sorganov@gmail.com
State Accepted
Delegated to: David Miller
Headers show
Series [v3,net] net: fec: fix hardware time stamping by external devices | expand

Commit Message

Sergey Organov July 14, 2020, 4:28 p.m. UTC
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: 6605b730c061 ("FEC: Add time stamping code and a PTP hardware clock")
Signed-off-by: Sergey Organov <sorganov@gmail.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Acked-by: Vladimir Oltean <olteanv@gmail.com>
---

v3:
  - Fixed SHA1 length of Fixes: tag
  - Added Acked-by: tags

v2:
  - Extracted from larger patch series
  - Description/comments updated according to discussions
  - Added Fixes: tag

 drivers/net/ethernet/freescale/fec.h      |  1 +
 drivers/net/ethernet/freescale/fec_main.c | 23 +++++++++++++++++------
 drivers/net/ethernet/freescale/fec_ptp.c  | 12 ++++++++++++
 3 files changed, 30 insertions(+), 6 deletions(-)

Comments

Jakub Kicinski July 16, 2020, 6:24 p.m. UTC | #1
On Tue, 14 Jul 2020 19:28:02 +0300 Sergey Organov wrote:
> 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: 6605b730c061 ("FEC: Add time stamping code and a PTP hardware clock")
> Signed-off-by: Sergey Organov <sorganov@gmail.com>
> Acked-by: Richard Cochran <richardcochran@gmail.com>
> Acked-by: Vladimir Oltean <olteanv@gmail.com>
> ---
> 
> v3:
>   - Fixed SHA1 length of Fixes: tag
>   - Added Acked-by: tags
> 
> v2:
>   - Extracted from larger patch series
>   - Description/comments updated according to discussions
>   - Added Fixes: tag

FWIW in the networking subsystem we like the changelog to be part of the
commit.

Applied, and added to the stable queue, thanks!
Sergey Organov July 16, 2020, 8:38 p.m. UTC | #2
Jakub Kicinski <kuba@kernel.org> writes:

> On Tue, 14 Jul 2020 19:28:02 +0300 Sergey Organov wrote:
>> 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: 6605b730c061 ("FEC: Add time stamping code and a PTP hardware
>> clock")
>> Signed-off-by: Sergey Organov <sorganov@gmail.com>
>> Acked-by: Richard Cochran <richardcochran@gmail.com>
>> Acked-by: Vladimir Oltean <olteanv@gmail.com>
>> ---
>>
>> v3:
>>   - Fixed SHA1 length of Fixes: tag
>>   - Added Acked-by: tags
>>
>> v2:
>>   - Extracted from larger patch series
>>   - Description/comments updated according to discussions
>>   - Added Fixes: tag
>
> FWIW in the networking subsystem we like the changelog to be part of the
> commit.

Thanks, Jakub, I took a notice for myself!

>
> Applied, and added to the stable queue, thanks!

Thanks, and I've also got a no-brainer patch that lets this bug fix
compile as-is with older kernels, where there were no phy_has_hwtstamp()
function. Dunno how to properly handle this. Here is the patch (on
top of v4.9.146), just in case:

--- >8 ---

commit eee1f92bbc83ad59c83935a21f635e088cf7aa02
Author: Sergey Organov <sorganov@gmail.com>
Date:   Tue Jun 30 17:12:16 2020 +0300

    phy: add phy_has_hwtstamp() for compatibility with newer kernels

    Signed-off-by: Sergey Organov <sorganov@gmail.com>

diff --git a/include/linux/phy.h b/include/linux/phy.h
index 867110c9d707..aa01ed4e8e1f 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -595,6 +595,15 @@ struct phy_driver {
 #define PHY_ANY_ID "MATCH ANY PHY"
 #define PHY_ANY_UID 0xffffffff
 
+/**
+ * phy_has_hwtstamp - Tests whether a PHY supports time stamp configuration.
+ * @phydev: the phy_device struct
+ */
+static inline bool phy_has_hwtstamp(struct phy_device *phydev)
+{
+       return phydev && phydev->drv && phydev->drv->hwtstamp;
+}
+
 /* A Structure for boards to register fixups with the PHY Lib */
 struct phy_fixup {
        struct list_head list;


-- Sergey
Jakub Kicinski July 16, 2020, 9:06 p.m. UTC | #3
On Thu, 16 Jul 2020 23:38:13 +0300 Sergey Organov wrote:
> > Applied, and added to the stable queue, thanks!  
> 
> Thanks, and I've also got a no-brainer patch that lets this bug fix
> compile as-is with older kernels, where there were no phy_has_hwtstamp()
> function. Dunno how to properly handle this. Here is the patch (on
> top of v4.9.146), just in case:

I see, I'll only add it to 5.7. By default we backport net fixes to
the two most recent releases, anyway. Could you send a patch that will 
work on 4.4 or 4.9 - 5.4 to Greg yourself once this hits Linus's tree
in a week or two?
Sergey Organov July 16, 2020, 9:18 p.m. UTC | #4
Jakub Kicinski <kuba@kernel.org> writes:

> On Thu, 16 Jul 2020 23:38:13 +0300 Sergey Organov wrote:
>> > Applied, and added to the stable queue, thanks!  
>> 
>> Thanks, and I've also got a no-brainer patch that lets this bug fix
>> compile as-is with older kernels, where there were no phy_has_hwtstamp()
>> function. Dunno how to properly handle this. Here is the patch (on
>> top of v4.9.146), just in case:
>
> I see, I'll only add it to 5.7. By default we backport net fixes to
> the two most recent releases, anyway. Could you send a patch that will 
> work on 4.4 or 4.9 - 5.4 to Greg yourself once this hits Linus's tree
> in a week or two?

Sure. Hopefully I get it right that I'll need to send it to Greg as a
backport of this one to older kernel trees.

Thanks,
-- Sergey
diff mbox series

Patch

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index d8d76da..832a217 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -590,6 +590,7 @@  struct fec_enet_private {
 void fec_ptp_init(struct platform_device *pdev, int irq_idx);
 void fec_ptp_stop(struct platform_device *pdev);
 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_get(struct net_device *ndev, struct ifreq *ifr);
 
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 3982285..cc7fbfc 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1294,8 +1294,13 @@  fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 			ndev->stats.tx_bytes += skb->len;
 		}
 
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) &&
-			fep->bufdesc_ex) {
+		/* 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) {
 			struct skb_shared_hwtstamps shhwtstamps;
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 
@@ -2723,10 +2728,16 @@  static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 		return -ENODEV;
 
 	if (fep->bufdesc_ex) {
-		if (cmd == SIOCSHWTSTAMP)
-			return fec_ptp_set(ndev, rq);
-		if (cmd == SIOCGHWTSTAMP)
-			return fec_ptp_get(ndev, rq);
+		bool use_fec_hwts = !phy_has_hwtstamp(phydev);
+
+		if (cmd == SIOCSHWTSTAMP) {
+			if (use_fec_hwts)
+				return fec_ptp_set(ndev, rq);
+			fec_ptp_disable_hwts(ndev);
+		} else if (cmd == SIOCGHWTSTAMP) {
+			if (use_fec_hwts)
+				return fec_ptp_get(ndev, rq);
+		}
 	}
 
 	return phy_mii_ioctl(phydev, rq, cmd);
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index 945643c..f8a592c 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -452,6 +452,18 @@  static int fec_ptp_enable(struct ptp_clock_info *ptp,
 	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)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);