lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 14 May 2020 12:28:06 +0200
From:   Olivier Dautricourt <olivier.dautricourt@...lia.com>
To:     Giuseppe Cavallaro <peppe.cavallaro@...com>,
        Alexandre Torgue <alexandre.torgue@...com>,
        Jose Abreu <joabreu@...opsys.com>,
        "David S . Miller" <davem@...emloft.net>
Cc:     Richard Cochran <richardcochran@...il.com>, netdev@...r.kernel.org,
        Artem Panfilov <panfilov.artyom@...il.com>,
        Olivier Dautricourt <olivier.dautricourt@...lia.com>
Subject: [PATCH 1/3] net: stmmac: gmac3: add auxiliary snapshot support

From: Artem Panfilov <panfilov.artyom@...il.com>

This patch adds support for time stamping external inputs for GMAC3.

The documentation defines 4 auxiliary snapshots ATSEN0 to ATSEN3 which
can be toggled by writing the Timestamp Control Register.

When the gmac detects a pps rising edge on one of it's auxiliary inputs,
an isr of type GMAC_INT_STATUS_TSTAMP will be triggered.
We use this isr to generate a ptp clock event of type PTP_CLOCK_EXTTS
with the following content:

  - Time of which the event occurred in ns.
  - All the extts for which the event was generated (0000 - 1111)

Note from the documentation:
"When more than one bit is set at the same time, it means
that corresponding auxiliary triggers were sampled at the same clock"

When the GMAC writes it's auxiliary snapshots on it's fifo
and that fifo is full, it will discard any new auxiliary snapshot until
we read the fifo. By reading on each isr, it is unlikely that
we will loose the 1pps external timestamps.

Events for one auxiliary input can be requested through the
PTP_EXTTS_REQUEST ioctl and read as already implemented in the uapi.

This patch introduces 2 functions:

    stmmac_set_hw_tstamping and stmmac_get_hw_tstamping

Each time we initialize the timestamping, we read the current
value of PTP_TCR and patch with new configuration without setting
the ATSENX flags again, which are set independently by the user
through the ioctl.
This allows to not loose the activated external events between each
initialization of the timestamping, and not force the user to redo
ioctl.

Signed-off-by: Olivier Dautricourt <olivier.dautricourt@...lia.com>
Signed-off-by: Artem Panfilov <panfilov.artyom@...il.com>
---
 .../net/ethernet/stmicro/stmmac/dwmac1000.h   |  3 +-
 .../ethernet/stmicro/stmmac/dwmac1000_core.c  | 24 ++++++++++
 drivers/net/ethernet/stmicro/stmmac/hwif.h    |  9 ++--
 .../ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 10 ++++-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  7 +--
 .../net/ethernet/stmicro/stmmac/stmmac_ptp.c  | 44 +++++++++++++++++++
 .../net/ethernet/stmicro/stmmac/stmmac_ptp.h  | 20 +++++++++
 7 files changed, 107 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index b70d44ac0990..5cff6c100258 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -41,8 +41,7 @@
 #define	GMAC_INT_DISABLE_PCS	(GMAC_INT_DISABLE_RGMII | \
 				 GMAC_INT_DISABLE_PCSLINK | \
 				 GMAC_INT_DISABLE_PCSAN)
-#define	GMAC_INT_DEFAULT_MASK	(GMAC_INT_DISABLE_TIMESTAMP | \
-				 GMAC_INT_DISABLE_PCS)
+#define	GMAC_INT_DEFAULT_MASK	GMAC_INT_DISABLE_PCS
 
 /* PMT Control and Status */
 #define GMAC_PMT		0x0000002c
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index efc6ec1b8027..3895fe9396e5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -20,6 +20,7 @@
 #include "stmmac.h"
 #include "stmmac_pcs.h"
 #include "dwmac1000.h"
+#include "stmmac_ptp.h"
 
 static void dwmac1000_core_init(struct mac_device_info *hw,
 				struct net_device *dev)
@@ -300,9 +301,29 @@ static void dwmac1000_rgsmii(void __iomem *ioaddr, struct stmmac_extra_stats *x)
 	}
 }
 
+static void dwmac1000_ptp_isr(struct stmmac_priv *priv)
+{
+	struct ptp_clock_event event;
+	u32 reg_value;
+	u64 ns;
+
+	reg_value = readl(priv->ioaddr + PTP_GMAC3_TSR);
+
+	ns = readl(priv->ioaddr + PTP_GMAC3_AUXTSLO);
+	ns += readl(priv->ioaddr + PTP_GMAC3_AUXTSHI) * 1000000000ULL;
+
+	event.timestamp = ns;
+	event.type = PTP_CLOCK_EXTTS;
+	event.index = (reg_value & PTP_GMAC3_ATSSTN_MASK) >>
+			PTP_GMAC3_ATSSTN_SHIFT;
+	ptp_clock_event(priv->ptp_clock, &event);
+}
+
 static int dwmac1000_irq_status(struct mac_device_info *hw,
 				struct stmmac_extra_stats *x)
 {
+	struct stmmac_priv *priv =
+		container_of(x, struct stmmac_priv, xstats);
 	void __iomem *ioaddr = hw->pcsr;
 	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
 	u32 intr_mask = readl(ioaddr + GMAC_INT_MASK);
@@ -324,6 +345,9 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
 		x->irq_receive_pmt_irq_n++;
 	}
 
+	if (intr_status & GMAC_INT_STATUS_TSTAMP)
+		dwmac1000_ptp_isr(priv);
+
 	/* MAC tx/rx EEE LPI entry/exit interrupts */
 	if (intr_status & GMAC_INT_STATUS_LPIIS) {
 		/* Clean LPI interrupt by reading the Reg 12 */
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index ffe2d63389b8..8fa63d059231 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -492,7 +492,8 @@ struct stmmac_ops {
 
 /* PTP and HW Timer helpers */
 struct stmmac_hwtimestamp {
-	void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
+	void (*get_hw_tstamping)(void __iomem *ioaddr, u32 *data);
+	void (*set_hw_tstamping)(void __iomem *ioaddr, u32 data);
 	void (*config_sub_second_increment)(void __iomem *ioaddr, u32 ptp_clock,
 					   int gmac4, u32 *ssinc);
 	int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
@@ -502,8 +503,10 @@ struct stmmac_hwtimestamp {
 	void (*get_systime) (void __iomem *ioaddr, u64 *systime);
 };
 
-#define stmmac_config_hw_tstamping(__priv, __args...) \
-	stmmac_do_void_callback(__priv, ptp, config_hw_tstamping, __args)
+#define stmmac_get_hw_tstamping(__priv, __args...) \
+	stmmac_do_void_callback(__priv, ptp, get_hw_tstamping, __args)
+#define stmmac_set_hw_tstamping(__priv, __args...) \
+	stmmac_do_void_callback(__priv, ptp, set_hw_tstamping, __args)
 #define stmmac_config_sub_second_increment(__priv, __args...) \
 	stmmac_do_void_callback(__priv, ptp, config_sub_second_increment, __args)
 #define stmmac_init_systime(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
index d291612eeafb..b974d83afe67 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
@@ -15,7 +15,12 @@
 #include "common.h"
 #include "stmmac_ptp.h"
 
-static void config_hw_tstamping(void __iomem *ioaddr, u32 data)
+static void get_hw_tstamping(void __iomem *ioaddr, u32 *data)
+{
+	*data = readl(ioaddr + PTP_TCR);
+}
+
+static void set_hw_tstamping(void __iomem *ioaddr, u32 data)
 {
 	writel(data, ioaddr + PTP_TCR);
 }
@@ -154,7 +159,8 @@ static void get_systime(void __iomem *ioaddr, u64 *systime)
 }
 
 const struct stmmac_hwtimestamp stmmac_ptp = {
-	.config_hw_tstamping = config_hw_tstamping,
+	.get_hw_tstamping = get_hw_tstamping,
+	.set_hw_tstamping = set_hw_tstamping,
 	.init_systime = init_systime,
 	.config_sub_second_increment = config_sub_second_increment,
 	.config_addend = config_addend,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a999d6b33a64..c39fafe69b12 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -686,13 +686,14 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
 	priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
 
 	if (!priv->hwts_tx_en && !priv->hwts_rx_en)
-		stmmac_config_hw_tstamping(priv, priv->ptpaddr, 0);
+		stmmac_set_hw_tstamping(priv, priv->ptpaddr, 0);
 	else {
-		value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
+		stmmac_get_hw_tstamping(priv, priv->ptpaddr, &value);
+		value |= (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
 			 ts_master_en | snap_type_sel);
-		stmmac_config_hw_tstamping(priv, priv->ptpaddr, value);
+		stmmac_set_hw_tstamping(priv, priv->ptpaddr, value);
 
 		/* program Sub Second Increment reg */
 		stmmac_config_sub_second_increment(priv,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
index 0989e2bb6ee3..920f0f3ebbca 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -45,6 +45,43 @@ static int stmmac_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
 	return 0;
 }
 
+static int stmmac_extts_configure(struct stmmac_priv *priv,
+				  struct ptp_clock_request *rq,
+				  int on)
+{
+	u32 tsauxc, tsauxc_mask;
+
+	if (priv->ptp_clock_ops.n_ext_ts <= rq->extts.index)
+		return -ERANGE;
+
+	switch (rq->extts.index) {
+	case 0:
+		tsauxc_mask = PTP_TCR_ATSEN0;
+		break;
+	case 1:
+		tsauxc_mask = PTP_TCR_ATSEN1;
+		break;
+	case 2:
+		tsauxc_mask = PTP_TCR_ATSEN2;
+		break;
+	case 3:
+		tsauxc_mask = PTP_TCR_ATSEN3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	tsauxc = readl(priv->ptpaddr);
+
+	if (on)
+		tsauxc |= tsauxc_mask;
+	else
+		tsauxc &= ~tsauxc_mask;
+
+	writel(tsauxc, priv->ptpaddr);
+	return 0;
+}
+
 /**
  * stmmac_adjust_time
  *
@@ -158,6 +195,11 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
 					     priv->systime_flags);
 		spin_unlock_irqrestore(&priv->ptp_lock, flags);
 		break;
+	case PTP_CLK_REQ_EXTTS:
+		spin_lock_irqsave(&priv->ptp_lock, flags);
+		ret = stmmac_extts_configure(priv, rq, on);
+		spin_unlock_irqrestore(&priv->ptp_lock, flags);
+		break;
 	default:
 		break;
 	}
@@ -202,6 +244,8 @@ void stmmac_ptp_register(struct stmmac_priv *priv)
 		stmmac_ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;
 
 	stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
+	if (priv->plat->has_gmac)
+		stmmac_ptp_clock_ops.n_ext_ts = 4;
 
 	spin_lock_init(&priv->ptp_lock);
 	priv->ptp_clock_ops = stmmac_ptp_clock_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
index 7abb1d47e7da..26bea23f04ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -59,9 +59,29 @@
 #define	PTP_TCR_SNAPTYPSEL_1	BIT(16)
 /* Enable MAC address for PTP Frame Filtering */
 #define	PTP_TCR_TSENMACADDR	BIT(18)
+/* Clear Auxiliary Snapshot FIFO */
+#define PTP_TCR_ATSFC		BIT(24)
+/* Enable Auxiliary Snapshot 0 */
+#define PTP_TCR_ATSEN0		BIT(25)
+/* Enable Auxiliary Snapshot 1 */
+#define PTP_TCR_ATSEN1		BIT(26)
+/* Enable Auxiliary Snapshot 2 */
+#define PTP_TCR_ATSEN2		BIT(27)
+/* Enable Auxiliary Snapshot 3 */
+#define PTP_TCR_ATSEN3		BIT(28)
 
 /* SSIR defines */
 #define	PTP_SSIR_SSINC_MASK		0xff
 #define	GMAC4_PTP_SSIR_SSINC_SHIFT	16
 
+/* Auxiliary Timestamp Snapshot defines */
+
+#define PTP_GMAC3_TSR		0x0728	/* Timestamp Status */
+#define PTP_GMAC3_AUXTSLO	0x0730	/* Aux Timestamp - Nanoseconds Reg */
+#define PTP_GMAC3_AUXTSHI	0x0734	/* Aux Timestamp - Seconds Reg */
+
+#define PTP_GMAC3_TSR		0x0728	/* Timestamp Status */
+#define PTP_GMAC3_ATSSTN_MASK	GENMASK(19, 16)
+#define PTP_GMAC3_ATSSTN_SHIFT	16
+
 #endif	/* __STMMAC_PTP_H__ */
-- 
2.17.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ