2018-06-07 03:29:15

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 00/10] Support DPAA PTP clock and timestamping

This patchset is to support DPAA FMAN PTP clock and HW timestamping.
- The patch #1 to patch #5 are to support DPAA FMAN 1588 timer in
ptp_qoriq driver.
- The patch #6 to patch #10 are to add HW timestamping support in
DPAA ethernet driver.

Yangbo Lu (10):
fsl/fman: share the event interrupt
ptp: support DPAA FMan 1588 timer in ptp_qoriq
dt-binding: ptp_qoriq: add DPAA FMan support
powerpc/mpc85xx: move ptp timer out of fman in dts
arm64: dts: fsl: move ptp timer out of fman
fsl/fman: add set_tstamp interface
fsl/fman_port: support getting timestamp field
fsl/fman: define frame description command UPD
dpaa_eth: add support for hardware timestamping
dpaa_eth: add the get_ts_info interface for ethtool

Documentation/devicetree/bindings/net/fsl-fman.txt | 25 +-----
.../devicetree/bindings/ptp/ptp-qoriq.txt | 15 +++-
arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi | 14 ++-
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 101 ++++++++++++++++++-
drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 3 +
drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 39 ++++++++
drivers/net/ethernet/freescale/fman/fman.c | 3 +-
drivers/net/ethernet/freescale/fman/fman.h | 1 +
drivers/net/ethernet/freescale/fman/fman_dtsec.c | 27 +++++
drivers/net/ethernet/freescale/fman/fman_dtsec.h | 1 +
drivers/net/ethernet/freescale/fman/fman_memac.c | 5 +
drivers/net/ethernet/freescale/fman/fman_memac.h | 1 +
drivers/net/ethernet/freescale/fman/fman_port.c | 12 +++
drivers/net/ethernet/freescale/fman/fman_port.h | 3 +
drivers/net/ethernet/freescale/fman/fman_tgec.c | 21 ++++
drivers/net/ethernet/freescale/fman/fman_tgec.h | 1 +
drivers/net/ethernet/freescale/fman/mac.c | 3 +
drivers/net/ethernet/freescale/fman/mac.h | 1 +
drivers/ptp/Kconfig | 2 +-
drivers/ptp/ptp_qoriq.c | 104 ++++++++++++-------
include/linux/fsl/ptp_qoriq.h | 38 ++++++--
26 files changed, 375 insertions(+), 115 deletions(-)



2018-06-07 03:26:30

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 05/10] arm64: dts: fsl: move ptp timer out of fman

This patch is to move ptp timer node out of fman.
Because ptp timer will be probed by ptp_qoriq driver,
it should be an independent device in case of conflict
memory mapping.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- Fixed address-cells for ptp-timer.
---
arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
index 4dd0676..a56a408 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
@@ -11,13 +11,14 @@ fman0: fman@1a00000 {
#size-cells = <1>;
cell-index = <0>;
compatible = "fsl,fman";
- ranges = <0x0 0x0 0x1a00000 0x100000>;
- reg = <0x0 0x1a00000 0x0 0x100000>;
+ ranges = <0x0 0x0 0x1a00000 0xfe000>;
+ reg = <0x0 0x1a00000 0x0 0xfe000>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen 3 0>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x800 0x10>;
+ ptimer-handle = <&ptp_timer0>;

muram@0 {
compatible = "fsl,fman-muram";
@@ -73,9 +74,10 @@ fman0: fman@1a00000 {
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfd000 0x1000>;
};
+};

- ptp_timer0: ptp-timer@fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer0: ptp-timer@1afe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x0 0x1afe000 0x0 0x1000>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
};
--
1.7.1


2018-06-07 03:26:33

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 10/10] dpaa_eth: add the get_ts_info interface for ethtool

Added the get_ts_info interface for ethtool to check
the timestamping capability.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- Removed ifdef for hw timestamp.
---
drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 39 ++++++++++++++++++++
1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
index 2f933b6..3184c8f 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
@@ -32,6 +32,9 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/string.h>
+#include <linux/of_platform.h>
+#include <linux/net_tstamp.h>
+#include <linux/fsl/ptp_qoriq.h>

#include "dpaa_eth.h"
#include "mac.h"
@@ -515,6 +518,41 @@ static int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
return ret;
}

+static int dpaa_get_ts_info(struct net_device *net_dev,
+ struct ethtool_ts_info *info)
+{
+ struct device *dev = net_dev->dev.parent;
+ struct device_node *mac_node = dev->of_node;
+ struct device_node *fman_node = NULL, *ptp_node = NULL;
+ struct platform_device *ptp_dev = NULL;
+ struct qoriq_ptp *ptp = NULL;
+
+ info->phc_index = -1;
+
+ fman_node = of_get_parent(mac_node);
+ if (fman_node)
+ ptp_node = of_parse_phandle(fman_node, "ptimer-handle", 0);
+
+ if (ptp_node)
+ ptp_dev = of_find_device_by_node(ptp_node);
+
+ if (ptp_dev)
+ ptp = platform_get_drvdata(ptp_dev);
+
+ if (ptp)
+ info->phc_index = ptp->phc_index;
+
+ info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->tx_types = (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+ info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_ALL);
+
+ return 0;
+}
+
const struct ethtool_ops dpaa_ethtool_ops = {
.get_drvinfo = dpaa_get_drvinfo,
.get_msglevel = dpaa_get_msglevel,
@@ -530,4 +568,5 @@ static int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
.set_link_ksettings = dpaa_set_link_ksettings,
.get_rxnfc = dpaa_get_rxnfc,
.set_rxnfc = dpaa_set_rxnfc,
+ .get_ts_info = dpaa_get_ts_info,
};
--
1.7.1


2018-06-07 03:26:42

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 06/10] fsl/fman: add set_tstamp interface

This patch is to add set_tstamp interface for memac,
dtsec, and 10GEC controllers to configure HW timestamping.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- None.
---
drivers/net/ethernet/freescale/fman/fman_dtsec.c | 27 ++++++++++++++++++++++
drivers/net/ethernet/freescale/fman/fman_dtsec.h | 1 +
drivers/net/ethernet/freescale/fman/fman_memac.c | 5 ++++
drivers/net/ethernet/freescale/fman/fman_memac.h | 1 +
drivers/net/ethernet/freescale/fman/fman_tgec.c | 21 +++++++++++++++++
drivers/net/ethernet/freescale/fman/fman_tgec.h | 1 +
drivers/net/ethernet/freescale/fman/mac.c | 3 ++
drivers/net/ethernet/freescale/fman/mac.h | 1 +
8 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 57b1e2b..1ca543a 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -123,11 +123,13 @@
#define DTSEC_ECNTRL_R100M 0x00000008
#define DTSEC_ECNTRL_QSGMIIM 0x00000001

+#define TCTRL_TTSE 0x00000040
#define TCTRL_GTS 0x00000020

#define RCTRL_PAL_MASK 0x001f0000
#define RCTRL_PAL_SHIFT 16
#define RCTRL_GHTX 0x00000400
+#define RCTRL_RTSE 0x00000040
#define RCTRL_GRS 0x00000020
#define RCTRL_MPROM 0x00000008
#define RCTRL_RSF 0x00000004
@@ -1136,6 +1138,31 @@ int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable)
return 0;
}

+int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable)
+{
+ struct dtsec_regs __iomem *regs = dtsec->regs;
+ u32 rctrl, tctrl;
+
+ if (!is_init_done(dtsec->dtsec_drv_param))
+ return -EINVAL;
+
+ rctrl = ioread32be(&regs->rctrl);
+ tctrl = ioread32be(&regs->tctrl);
+
+ if (enable) {
+ rctrl |= RCTRL_RTSE;
+ tctrl |= TCTRL_TTSE;
+ } else {
+ rctrl &= ~RCTRL_RTSE;
+ tctrl &= ~TCTRL_TTSE;
+ }
+
+ iowrite32be(rctrl, &regs->rctrl);
+ iowrite32be(tctrl, &regs->tctrl);
+
+ return 0;
+}
+
int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr)
{
struct dtsec_regs __iomem *regs = dtsec->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.h b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
index 1a689ad..5149d96 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
@@ -56,5 +56,6 @@ int dtsec_set_exception(struct fman_mac *dtsec,
int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr);
int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version);
int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable);
+int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable);

#endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 446a97b..bc6eb30 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -964,6 +964,11 @@ int memac_set_allmulti(struct fman_mac *memac, bool enable)
return 0;
}

+int memac_set_tstamp(struct fman_mac *memac, bool enable)
+{
+ return 0; /* Always enabled. */
+}
+
int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr)
{
struct memac_regs __iomem *regs = memac->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h b/drivers/net/ethernet/freescale/fman/fman_memac.h
index b5a5033..b2c671e 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.h
@@ -58,5 +58,6 @@ int memac_set_exception(struct fman_mac *memac,
int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
int memac_set_allmulti(struct fman_mac *memac, bool enable);
+int memac_set_tstamp(struct fman_mac *memac, bool enable);

#endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 284735d..4070593 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -44,6 +44,7 @@
#define TGEC_TX_IPG_LENGTH_MASK 0x000003ff

/* Command and Configuration Register (COMMAND_CONFIG) */
+#define CMD_CFG_EN_TIMESTAMP 0x00100000
#define CMD_CFG_NO_LEN_CHK 0x00020000
#define CMD_CFG_PAUSE_IGNORE 0x00000100
#define CMF_CFG_CRC_FWD 0x00000040
@@ -588,6 +589,26 @@ int tgec_set_allmulti(struct fman_mac *tgec, bool enable)
return 0;
}

+int tgec_set_tstamp(struct fman_mac *tgec, bool enable)
+{
+ struct tgec_regs __iomem *regs = tgec->regs;
+ u32 tmp;
+
+ if (!is_init_done(tgec->cfg))
+ return -EINVAL;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (enable)
+ tmp |= CMD_CFG_EN_TIMESTAMP;
+ else
+ tmp &= ~CMD_CFG_EN_TIMESTAMP;
+
+ iowrite32be(tmp, &regs->command_config);
+
+ return 0;
+}
+
int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr)
{
struct tgec_regs __iomem *regs = tgec->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h b/drivers/net/ethernet/freescale/fman/fman_tgec.h
index cbbd3b4..3bfd106 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.h
@@ -52,5 +52,6 @@ int tgec_set_exception(struct fman_mac *tgec,
int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr);
int tgec_get_version(struct fman_mac *tgec, u32 *mac_version);
int tgec_set_allmulti(struct fman_mac *tgec, bool enable);
+int tgec_set_tstamp(struct fman_mac *tgec, bool enable);

#endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 7b5b95f..a847b9c 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -471,6 +471,7 @@ static void setup_dtsec(struct mac_device *mac_dev)
mac_dev->set_rx_pause = dtsec_accept_rx_pause_frames;
mac_dev->set_exception = dtsec_set_exception;
mac_dev->set_allmulti = dtsec_set_allmulti;
+ mac_dev->set_tstamp = dtsec_set_tstamp;
mac_dev->set_multi = set_multi;
mac_dev->start = start;
mac_dev->stop = stop;
@@ -490,6 +491,7 @@ static void setup_tgec(struct mac_device *mac_dev)
mac_dev->set_rx_pause = tgec_accept_rx_pause_frames;
mac_dev->set_exception = tgec_set_exception;
mac_dev->set_allmulti = tgec_set_allmulti;
+ mac_dev->set_tstamp = tgec_set_tstamp;
mac_dev->set_multi = set_multi;
mac_dev->start = start;
mac_dev->stop = stop;
@@ -509,6 +511,7 @@ static void setup_memac(struct mac_device *mac_dev)
mac_dev->set_rx_pause = memac_accept_rx_pause_frames;
mac_dev->set_exception = memac_set_exception;
mac_dev->set_allmulti = memac_set_allmulti;
+ mac_dev->set_tstamp = memac_set_tstamp;
mac_dev->set_multi = set_multi;
mac_dev->start = start;
mac_dev->stop = stop;
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index b520cec..824a81a 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -68,6 +68,7 @@ struct mac_device {
int (*set_promisc)(struct fman_mac *mac_dev, bool enable);
int (*change_addr)(struct fman_mac *mac_dev, enet_addr_t *enet_addr);
int (*set_allmulti)(struct fman_mac *mac_dev, bool enable);
+ int (*set_tstamp)(struct fman_mac *mac_dev, bool enable);
int (*set_multi)(struct net_device *net_dev,
struct mac_device *mac_dev);
int (*set_rx_pause)(struct fman_mac *mac_dev, bool en);
--
1.7.1


2018-06-07 03:28:05

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 04/10] powerpc/mpc85xx: move ptp timer out of fman in dts

This patch is to move ptp timer node out of fman.
Because ptp timer will be probed by ptp_qoriq driver,
it should be an independent device in case of conflict
memory mapping.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- None.
---
arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi | 14 ++++++++------
arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi | 14 ++++++++------
arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi | 14 ++++++++------
arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi | 14 ++++++++------
arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi | 14 ++++++++------
5 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi
index abd01d4..6b124f7 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi
@@ -37,12 +37,13 @@ fman0: fman@400000 {
#size-cells = <1>;
cell-index = <0>;
compatible = "fsl,fman";
- ranges = <0 0x400000 0x100000>;
- reg = <0x400000 0x100000>;
+ ranges = <0 0x400000 0xfe000>;
+ reg = <0x400000 0xfe000>;
interrupts = <96 2 0 0>, <16 2 1 1>;
clocks = <&clockgen 3 0>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x40 0xc>;
+ ptimer-handle = <&ptp_timer0>;

muram@0 {
compatible = "fsl,fman-muram";
@@ -93,9 +94,10 @@ fman0: fman@400000 {
reg = <0x87000 0x1000>;
status = "disabled";
};
+};

- ptp_timer0: ptp-timer@fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer0: ptp-timer@4fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x4fe000 0x1000>;
+ interrupts = <96 2 0 0>;
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi
index debea75..b80aaf5 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi
@@ -37,12 +37,13 @@ fman1: fman@500000 {
#size-cells = <1>;
cell-index = <1>;
compatible = "fsl,fman";
- ranges = <0 0x500000 0x100000>;
- reg = <0x500000 0x100000>;
+ ranges = <0 0x500000 0xfe000>;
+ reg = <0x500000 0xfe000>;
interrupts = <97 2 0 0>, <16 2 1 0>;
clocks = <&clockgen 3 1>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x60 0xc>;
+ ptimer-handle = <&ptp_timer1>;

muram@0 {
compatible = "fsl,fman-muram";
@@ -93,9 +94,10 @@ fman1: fman@500000 {
reg = <0x87000 0x1000>;
status = "disabled";
};
+};

- ptp_timer1: ptp-timer@fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer1: ptp-timer@5fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x5fe000 0x1000>;
+ interrupts = <97 2 0 0>;
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi
index 3a20e0d..d3720fd 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi
@@ -37,12 +37,13 @@ fman0: fman@400000 {
#size-cells = <1>;
cell-index = <0>;
compatible = "fsl,fman";
- ranges = <0 0x400000 0x100000>;
- reg = <0x400000 0x100000>;
+ ranges = <0 0x400000 0xfe000>;
+ reg = <0x400000 0xfe000>;
interrupts = <96 2 0 0>, <16 2 1 1>;
clocks = <&clockgen 3 0>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x800 0x10>;
+ ptimer-handle = <&ptp_timer0>;

muram@0 {
compatible = "fsl,fman-muram";
@@ -98,9 +99,10 @@ fman0: fman@400000 {
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfd000 0x1000>;
};
+};

- ptp_timer0: ptp-timer@fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer0: ptp-timer@4fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x4fe000 0x1000>;
+ interrupts = <96 2 0 0>;
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi
index 82750ac..ae34c20 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi
@@ -37,12 +37,13 @@ fman1: fman@500000 {
#size-cells = <1>;
cell-index = <1>;
compatible = "fsl,fman";
- ranges = <0 0x500000 0x100000>;
- reg = <0x500000 0x100000>;
+ ranges = <0 0x500000 0xfe000>;
+ reg = <0x500000 0xfe000>;
interrupts = <97 2 0 0>, <16 2 1 0>;
clocks = <&clockgen 3 1>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x820 0x10>;
+ ptimer-handle = <&ptp_timer1>;

muram@0 {
compatible = "fsl,fman-muram";
@@ -98,9 +99,10 @@ fman1: fman@500000 {
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfd000 0x1000>;
};
+};

- ptp_timer1: ptp-timer@fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer1: ptp-timer@5fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x5fe000 0x1000>;
+ interrupts = <97 2 0 0>;
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
index 7f60b60..02f2755 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
@@ -37,12 +37,13 @@ fman0: fman@400000 {
#size-cells = <1>;
cell-index = <0>;
compatible = "fsl,fman";
- ranges = <0 0x400000 0x100000>;
- reg = <0x400000 0x100000>;
+ ranges = <0 0x400000 0xfe000>;
+ reg = <0x400000 0xfe000>;
interrupts = <96 2 0 0>, <16 2 1 1>;
clocks = <&clockgen 3 0>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x800 0x10>;
+ ptimer-handle = <&ptp_timer0>;

muram@0 {
compatible = "fsl,fman-muram";
@@ -86,9 +87,10 @@ fman0: fman@400000 {
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfd000 0x1000>;
};
+};

- ptp_timer0: ptp-timer@fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer0: ptp-timer@4fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x4fe000 0x1000>;
+ interrupts = <96 2 0 0>;
};
--
1.7.1


2018-06-07 03:28:08

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 08/10] fsl/fman: define frame description command UPD

Defined frame description command FM_FD_CMD_UPD for
prepended data updating.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- None.
---
drivers/net/ethernet/freescale/fman/fman.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman.h b/drivers/net/ethernet/freescale/fman/fman.h
index bfa02e0..935c317 100644
--- a/drivers/net/ethernet/freescale/fman/fman.h
+++ b/drivers/net/ethernet/freescale/fman/fman.h
@@ -41,6 +41,7 @@
/* Frame queue Context Override */
#define FM_FD_CMD_FCO 0x80000000
#define FM_FD_CMD_RPD 0x40000000 /* Read Prepended Data */
+#define FM_FD_CMD_UPD 0x20000000 /* Update Prepended Data */
#define FM_FD_CMD_DTC 0x10000000 /* Do L4 Checksum */

/* TX-Port: Unsupported Format */
--
1.7.1


2018-06-07 03:28:17

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 09/10] dpaa_eth: add support for hardware timestamping

This patch is to add hardware timestamping support
for dpaa_eth. On Rx, timestamping is enabled for
all frames. On Tx, we only instruct the hardware
to timestamp the frames marked accordingly by the
stack.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- Removed ifdef for timestamp code.
- Minor fixes for code style.
---
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 101 ++++++++++++++++++++++-
drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 3 +
2 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index fd43f98..bd589ac 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -1168,7 +1168,7 @@ static int dpaa_eth_init_tx_port(struct fman_port *port, struct dpaa_fq *errq,
buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
buf_prefix_content.pass_prs_result = true;
buf_prefix_content.pass_hash_result = true;
- buf_prefix_content.pass_time_stamp = false;
+ buf_prefix_content.pass_time_stamp = true;
buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;

params.specific_params.non_rx_params.err_fqid = errq->fqid;
@@ -1210,7 +1210,7 @@ static int dpaa_eth_init_rx_port(struct fman_port *port, struct dpaa_bp **bps,
buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
buf_prefix_content.pass_prs_result = true;
buf_prefix_content.pass_hash_result = true;
- buf_prefix_content.pass_time_stamp = false;
+ buf_prefix_content.pass_time_stamp = true;
buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;

rx_p = &params.specific_params.rx_params;
@@ -1592,6 +1592,16 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
return 0;
}

+static int dpaa_get_tstamp_ns(struct net_device *net_dev, u64 *ns,
+ struct fman_port *port, const void *data)
+{
+ if (!fman_port_get_tstamp_field(port, data, ns)) {
+ be64_to_cpus(ns);
+ return 0;
+ }
+ return -EINVAL;
+}
+
/* Cleanup function for outgoing frame descriptors that were built on Tx path,
* either contiguous frames or scatter/gather ones.
* Skb freeing is not handled here.
@@ -1607,14 +1617,29 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
{
const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
struct device *dev = priv->net_dev->dev.parent;
+ struct skb_shared_hwtstamps shhwtstamps;
dma_addr_t addr = qm_fd_addr(fd);
const struct qm_sg_entry *sgt;
struct sk_buff **skbh, *skb;
int nr_frags, i;
+ u64 ns;

skbh = (struct sk_buff **)phys_to_virt(addr);
skb = *skbh;

+ if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+
+ if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
+ priv->mac_dev->port[TX],
+ (void *)skbh)) {
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+ skb_tstamp_tx(skb, &shhwtstamps);
+ } else {
+ dev_warn(dev, "dpaa_get_tstamp_ns failed!\n");
+ }
+ }
+
if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
nr_frags = skb_shinfo(skb)->nr_frags;
dma_unmap_single(dev, addr, qm_fd_get_offset(fd) +
@@ -2086,6 +2111,11 @@ static int dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
if (unlikely(err < 0))
goto skb_to_fd_failed;

+ if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+ fd.cmd |= FM_FD_CMD_UPD;
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ }
+
if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
return NETDEV_TX_OK;

@@ -2227,6 +2257,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
struct qman_fq *fq,
const struct qm_dqrr_entry *dq)
{
+ struct skb_shared_hwtstamps *shhwtstamps;
struct rtnl_link_stats64 *percpu_stats;
struct dpaa_percpu_priv *percpu_priv;
const struct qm_fd *fd = &dq->fd;
@@ -2240,6 +2271,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
struct sk_buff *skb;
int *count_ptr;
void *vaddr;
+ u64 ns;

fd_status = be32_to_cpu(fd->status);
fd_format = qm_fd_get_format(fd);
@@ -2304,6 +2336,18 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
if (!skb)
return qman_cb_dqrr_consume;

+ if (priv->rx_tstamp) {
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+ if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
+ priv->mac_dev->port[RX],
+ vaddr))
+ shhwtstamps->hwtstamp = ns_to_ktime(ns);
+ else
+ dev_warn(net_dev->dev.parent, "dpaa_get_tstamp_ns failed!\n");
+ }
+
skb->protocol = eth_type_trans(skb, net_dev);

if (net_dev->features & NETIF_F_RXHASH && priv->keygen_in_use &&
@@ -2523,11 +2567,58 @@ static int dpaa_eth_stop(struct net_device *net_dev)
return err;
}

+static int dpaa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct dpaa_priv *priv = netdev_priv(dev);
+ struct hwtstamp_config config;
+
+ if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ /* Couldn't disable rx/tx timestamping separately.
+ * Do nothing here.
+ */
+ priv->tx_tstamp = false;
+ break;
+ case HWTSTAMP_TX_ON:
+ priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac, true);
+ priv->tx_tstamp = true;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ if (config.rx_filter == HWTSTAMP_FILTER_NONE) {
+ /* Couldn't disable rx/tx timestamping separately.
+ * Do nothing here.
+ */
+ priv->rx_tstamp = false;
+ } else {
+ priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac, true);
+ priv->rx_tstamp = true;
+ /* TS is set for all frame types, not only those requested */
+ config.rx_filter = HWTSTAMP_FILTER_ALL;
+ }
+
+ return copy_to_user(rq->ifr_data, &config, sizeof(config)) ?
+ -EFAULT : 0;
+}
+
static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
{
- if (!net_dev->phydev)
- return -EINVAL;
- return phy_mii_ioctl(net_dev->phydev, rq, cmd);
+ int ret = -EINVAL;
+
+ if (cmd == SIOCGMIIREG) {
+ if (net_dev->phydev)
+ return phy_mii_ioctl(net_dev->phydev, rq, cmd);
+ }
+
+ if (cmd == SIOCSHWTSTAMP)
+ return dpaa_ts_ioctl(net_dev, rq, cmd);
+
+ return ret;
}

static const struct net_device_ops dpaa_ops = {
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
index bd94220..af320f8 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
@@ -182,6 +182,9 @@ struct dpaa_priv {

struct dpaa_buffer_layout buf_layout[2];
u16 rx_headroom;
+
+ bool tx_tstamp; /* Tx timestamping enabled */
+ bool rx_tstamp; /* Rx timestamping enabled */
};

/* from dpaa_ethtool.c */
--
1.7.1


2018-06-07 03:28:25

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 02/10] ptp: support DPAA FMan 1588 timer in ptp_qoriq

This patch is to support DPAA (Data Path Acceleration Architecture)
1588 timer by adding "fsl,fman-ptp-timer" compatible, sharing
interrupt with FMan, adding FSL_DPAA_ETH dependency, and fixing
up register offset.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- None.
---
drivers/ptp/Kconfig | 2 +-
drivers/ptp/ptp_qoriq.c | 104 ++++++++++++++++++++++++++---------------
include/linux/fsl/ptp_qoriq.h | 38 ++++++++++++---
3 files changed, 98 insertions(+), 46 deletions(-)

diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 474c988..d137c48 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -43,7 +43,7 @@ config PTP_1588_CLOCK_DTE

config PTP_1588_CLOCK_QORIQ
tristate "Freescale QorIQ 1588 timer as PTP clock"
- depends on GIANFAR
+ depends on GIANFAR || FSL_DPAA_ETH
depends on PTP_1588_CLOCK
default y
help
diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c
index 1468a16..c4e3545 100644
--- a/drivers/ptp/ptp_qoriq.c
+++ b/drivers/ptp/ptp_qoriq.c
@@ -39,11 +39,12 @@
/* Caller must hold qoriq_ptp->lock. */
static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
{
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u64 ns;
u32 lo, hi;

- lo = qoriq_read(&qoriq_ptp->regs->tmr_cnt_l);
- hi = qoriq_read(&qoriq_ptp->regs->tmr_cnt_h);
+ lo = qoriq_read(&regs->ctrl_regs->tmr_cnt_l);
+ hi = qoriq_read(&regs->ctrl_regs->tmr_cnt_h);
ns = ((u64) hi) << 32;
ns |= lo;
return ns;
@@ -52,16 +53,18 @@ static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
/* Caller must hold qoriq_ptp->lock. */
static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns)
{
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u32 hi = ns >> 32;
u32 lo = ns & 0xffffffff;

- qoriq_write(&qoriq_ptp->regs->tmr_cnt_l, lo);
- qoriq_write(&qoriq_ptp->regs->tmr_cnt_h, hi);
+ qoriq_write(&regs->ctrl_regs->tmr_cnt_l, lo);
+ qoriq_write(&regs->ctrl_regs->tmr_cnt_h, hi);
}

/* Caller must hold qoriq_ptp->lock. */
static void set_alarm(struct qoriq_ptp *qoriq_ptp)
{
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u64 ns;
u32 lo, hi;

@@ -70,16 +73,18 @@ static void set_alarm(struct qoriq_ptp *qoriq_ptp)
ns -= qoriq_ptp->tclk_period;
hi = ns >> 32;
lo = ns & 0xffffffff;
- qoriq_write(&qoriq_ptp->regs->tmr_alarm1_l, lo);
- qoriq_write(&qoriq_ptp->regs->tmr_alarm1_h, hi);
+ qoriq_write(&regs->alarm_regs->tmr_alarm1_l, lo);
+ qoriq_write(&regs->alarm_regs->tmr_alarm1_h, hi);
}

/* Caller must hold qoriq_ptp->lock. */
static void set_fipers(struct qoriq_ptp *qoriq_ptp)
{
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
+
set_alarm(qoriq_ptp);
- qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
- qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
+ qoriq_write(&regs->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
+ qoriq_write(&regs->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
}

/*
@@ -89,16 +94,17 @@ static void set_fipers(struct qoriq_ptp *qoriq_ptp)
static irqreturn_t isr(int irq, void *priv)
{
struct qoriq_ptp *qoriq_ptp = priv;
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
struct ptp_clock_event event;
u64 ns;
u32 ack = 0, lo, hi, mask, val;

- val = qoriq_read(&qoriq_ptp->regs->tmr_tevent);
+ val = qoriq_read(&regs->ctrl_regs->tmr_tevent);

if (val & ETS1) {
ack |= ETS1;
- hi = qoriq_read(&qoriq_ptp->regs->tmr_etts1_h);
- lo = qoriq_read(&qoriq_ptp->regs->tmr_etts1_l);
+ hi = qoriq_read(&regs->etts_regs->tmr_etts1_h);
+ lo = qoriq_read(&regs->etts_regs->tmr_etts1_l);
event.type = PTP_CLOCK_EXTTS;
event.index = 0;
event.timestamp = ((u64) hi) << 32;
@@ -108,8 +114,8 @@ static irqreturn_t isr(int irq, void *priv)

if (val & ETS2) {
ack |= ETS2;
- hi = qoriq_read(&qoriq_ptp->regs->tmr_etts2_h);
- lo = qoriq_read(&qoriq_ptp->regs->tmr_etts2_l);
+ hi = qoriq_read(&regs->etts_regs->tmr_etts2_h);
+ lo = qoriq_read(&regs->etts_regs->tmr_etts2_l);
event.type = PTP_CLOCK_EXTTS;
event.index = 1;
event.timestamp = ((u64) hi) << 32;
@@ -130,16 +136,16 @@ static irqreturn_t isr(int irq, void *priv)
hi = ns >> 32;
lo = ns & 0xffffffff;
spin_lock(&qoriq_ptp->lock);
- qoriq_write(&qoriq_ptp->regs->tmr_alarm2_l, lo);
- qoriq_write(&qoriq_ptp->regs->tmr_alarm2_h, hi);
+ qoriq_write(&regs->alarm_regs->tmr_alarm2_l, lo);
+ qoriq_write(&regs->alarm_regs->tmr_alarm2_h, hi);
spin_unlock(&qoriq_ptp->lock);
qoriq_ptp->alarm_value = ns;
} else {
- qoriq_write(&qoriq_ptp->regs->tmr_tevent, ALM2);
+ qoriq_write(&regs->ctrl_regs->tmr_tevent, ALM2);
spin_lock(&qoriq_ptp->lock);
- mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
+ mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
mask &= ~ALM2EN;
- qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
+ qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
spin_unlock(&qoriq_ptp->lock);
qoriq_ptp->alarm_value = 0;
qoriq_ptp->alarm_interval = 0;
@@ -153,7 +159,7 @@ static irqreturn_t isr(int irq, void *priv)
}

if (ack) {
- qoriq_write(&qoriq_ptp->regs->tmr_tevent, ack);
+ qoriq_write(&regs->ctrl_regs->tmr_tevent, ack);
return IRQ_HANDLED;
} else
return IRQ_NONE;
@@ -169,6 +175,7 @@ static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
u32 tmr_add;
int neg_adj = 0;
struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;

if (scaled_ppm < 0) {
neg_adj = 1;
@@ -186,7 +193,7 @@ static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)

tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;

- qoriq_write(&qoriq_ptp->regs->tmr_add, tmr_add);
+ qoriq_write(&regs->ctrl_regs->tmr_add, tmr_add);

return 0;
}
@@ -250,6 +257,7 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on)
{
struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
unsigned long flags;
u32 bit, mask;

@@ -266,23 +274,23 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
return -EINVAL;
}
spin_lock_irqsave(&qoriq_ptp->lock, flags);
- mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
+ mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
if (on)
mask |= bit;
else
mask &= ~bit;
- qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
+ qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0;

case PTP_CLK_REQ_PPS:
spin_lock_irqsave(&qoriq_ptp->lock, flags);
- mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
+ mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
if (on)
mask |= PP1EN;
else
mask &= ~PP1EN;
- qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
+ qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0;

@@ -313,10 +321,12 @@ static int qoriq_ptp_probe(struct platform_device *dev)
{
struct device_node *node = dev->dev.of_node;
struct qoriq_ptp *qoriq_ptp;
+ struct qoriq_ptp_registers *regs;
struct timespec64 now;
int err = -ENOMEM;
u32 tmr_ctrl;
unsigned long flags;
+ void __iomem *base;

qoriq_ptp = kzalloc(sizeof(*qoriq_ptp), GFP_KERNEL);
if (!qoriq_ptp)
@@ -351,7 +361,7 @@ static int qoriq_ptp_probe(struct platform_device *dev)
pr_err("irq not in device tree\n");
goto no_node;
}
- if (request_irq(qoriq_ptp->irq, isr, 0, DRIVER, qoriq_ptp)) {
+ if (request_irq(qoriq_ptp->irq, isr, IRQF_SHARED, DRIVER, qoriq_ptp)) {
pr_err("request_irq failed\n");
goto no_node;
}
@@ -368,12 +378,27 @@ static int qoriq_ptp_probe(struct platform_device *dev)

spin_lock_init(&qoriq_ptp->lock);

- qoriq_ptp->regs = ioremap(qoriq_ptp->rsrc->start,
- resource_size(qoriq_ptp->rsrc));
- if (!qoriq_ptp->regs) {
+ base = ioremap(qoriq_ptp->rsrc->start,
+ resource_size(qoriq_ptp->rsrc));
+ if (!base) {
pr_err("ioremap ptp registers failed\n");
goto no_ioremap;
}
+
+ qoriq_ptp->base = base;
+
+ if (of_device_is_compatible(node, "fsl,fman-ptp-timer")) {
+ qoriq_ptp->regs.ctrl_regs = base + FMAN_CTRL_REGS_OFFSET;
+ qoriq_ptp->regs.alarm_regs = base + FMAN_ALARM_REGS_OFFSET;
+ qoriq_ptp->regs.fiper_regs = base + FMAN_FIPER_REGS_OFFSET;
+ qoriq_ptp->regs.etts_regs = base + FMAN_ETTS_REGS_OFFSET;
+ } else {
+ qoriq_ptp->regs.ctrl_regs = base + CTRL_REGS_OFFSET;
+ qoriq_ptp->regs.alarm_regs = base + ALARM_REGS_OFFSET;
+ qoriq_ptp->regs.fiper_regs = base + FIPER_REGS_OFFSET;
+ qoriq_ptp->regs.etts_regs = base + ETTS_REGS_OFFSET;
+ }
+
getnstimeofday64(&now);
ptp_qoriq_settime(&qoriq_ptp->caps, &now);

@@ -383,13 +408,14 @@ static int qoriq_ptp_probe(struct platform_device *dev)

spin_lock_irqsave(&qoriq_ptp->lock, flags);

- qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl);
- qoriq_write(&qoriq_ptp->regs->tmr_add, qoriq_ptp->tmr_add);
- qoriq_write(&qoriq_ptp->regs->tmr_prsc, qoriq_ptp->tmr_prsc);
- qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
- qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
+ regs = &qoriq_ptp->regs;
+ qoriq_write(&regs->ctrl_regs->tmr_ctrl, tmr_ctrl);
+ qoriq_write(&regs->ctrl_regs->tmr_add, qoriq_ptp->tmr_add);
+ qoriq_write(&regs->ctrl_regs->tmr_prsc, qoriq_ptp->tmr_prsc);
+ qoriq_write(&regs->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
+ qoriq_write(&regs->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
set_alarm(qoriq_ptp);
- qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD);
+ qoriq_write(&regs->ctrl_regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD);

spin_unlock_irqrestore(&qoriq_ptp->lock, flags);

@@ -405,7 +431,7 @@ static int qoriq_ptp_probe(struct platform_device *dev)
return 0;

no_clock:
- iounmap(qoriq_ptp->regs);
+ iounmap(qoriq_ptp->base);
no_ioremap:
release_resource(qoriq_ptp->rsrc);
no_resource:
@@ -419,12 +445,13 @@ static int qoriq_ptp_probe(struct platform_device *dev)
static int qoriq_ptp_remove(struct platform_device *dev)
{
struct qoriq_ptp *qoriq_ptp = platform_get_drvdata(dev);
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;

- qoriq_write(&qoriq_ptp->regs->tmr_temask, 0);
- qoriq_write(&qoriq_ptp->regs->tmr_ctrl, 0);
+ qoriq_write(&regs->ctrl_regs->tmr_temask, 0);
+ qoriq_write(&regs->ctrl_regs->tmr_ctrl, 0);

ptp_clock_unregister(qoriq_ptp->clock);
- iounmap(qoriq_ptp->regs);
+ iounmap(qoriq_ptp->base);
release_resource(qoriq_ptp->rsrc);
free_irq(qoriq_ptp->irq, qoriq_ptp);
kfree(qoriq_ptp);
@@ -434,6 +461,7 @@ static int qoriq_ptp_remove(struct platform_device *dev)

static const struct of_device_id match_table[] = {
{ .compatible = "fsl,etsec-ptp" },
+ { .compatible = "fsl,fman-ptp-timer" },
{},
};
MODULE_DEVICE_TABLE(of, match_table);
diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h
index b462d9e..dc3dac4 100644
--- a/include/linux/fsl/ptp_qoriq.h
+++ b/include/linux/fsl/ptp_qoriq.h
@@ -11,9 +11,8 @@

/*
* qoriq ptp registers
- * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010
*/
-struct qoriq_ptp_registers {
+struct ctrl_regs {
u32 tmr_ctrl; /* Timer control register */
u32 tmr_tevent; /* Timestamp event register */
u32 tmr_temask; /* Timer event mask register */
@@ -28,22 +27,47 @@ struct qoriq_ptp_registers {
u8 res1[4];
u32 tmroff_h; /* Timer offset high */
u32 tmroff_l; /* Timer offset low */
- u8 res2[8];
+};
+
+struct alarm_regs {
u32 tmr_alarm1_h; /* Timer alarm 1 high register */
u32 tmr_alarm1_l; /* Timer alarm 1 high register */
u32 tmr_alarm2_h; /* Timer alarm 2 high register */
u32 tmr_alarm2_l; /* Timer alarm 2 high register */
- u8 res3[48];
+};
+
+struct fiper_regs {
u32 tmr_fiper1; /* Timer fixed period interval */
u32 tmr_fiper2; /* Timer fixed period interval */
u32 tmr_fiper3; /* Timer fixed period interval */
- u8 res4[20];
+};
+
+struct etts_regs {
u32 tmr_etts1_h; /* Timestamp of general purpose external trigger */
u32 tmr_etts1_l; /* Timestamp of general purpose external trigger */
u32 tmr_etts2_h; /* Timestamp of general purpose external trigger */
u32 tmr_etts2_l; /* Timestamp of general purpose external trigger */
};

+struct qoriq_ptp_registers {
+ struct ctrl_regs __iomem *ctrl_regs;
+ struct alarm_regs __iomem *alarm_regs;
+ struct fiper_regs __iomem *fiper_regs;
+ struct etts_regs __iomem *etts_regs;
+};
+
+/* Offset definitions for the four register groups */
+#define CTRL_REGS_OFFSET 0x0
+#define ALARM_REGS_OFFSET 0x40
+#define FIPER_REGS_OFFSET 0x80
+#define ETTS_REGS_OFFSET 0xa0
+
+#define FMAN_CTRL_REGS_OFFSET 0x80
+#define FMAN_ALARM_REGS_OFFSET 0xb8
+#define FMAN_FIPER_REGS_OFFSET 0xd0
+#define FMAN_ETTS_REGS_OFFSET 0xe0
+
+
/* Bit definitions for the TMR_CTRL register */
#define ALM1P (1<<31) /* Alarm1 output polarity */
#define ALM2P (1<<30) /* Alarm2 output polarity */
@@ -105,10 +129,10 @@ struct qoriq_ptp_registers {
#define DRIVER "ptp_qoriq"
#define DEFAULT_CKSEL 1
#define N_EXT_TS 2
-#define REG_SIZE sizeof(struct qoriq_ptp_registers)

struct qoriq_ptp {
- struct qoriq_ptp_registers __iomem *regs;
+ void __iomem *base;
+ struct qoriq_ptp_registers regs;
spinlock_t lock; /* protects regs */
struct ptp_clock *clock;
struct ptp_clock_info caps;
--
1.7.1


2018-06-07 03:30:05

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 01/10] fsl/fman: share the event interrupt

This patch is to share fman event interrupt because
the 1588 timer driver will also use this interrupt.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- None.
---
drivers/net/ethernet/freescale/fman/fman.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c
index 9530405..c415ac6 100644
--- a/drivers/net/ethernet/freescale/fman/fman.c
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -2801,7 +2801,8 @@ static irqreturn_t fman_irq(int irq, void *handle)
of_node_put(muram_node);
of_node_put(fm_node);

- err = devm_request_irq(&of_dev->dev, irq, fman_irq, 0, "fman", fman);
+ err = devm_request_irq(&of_dev->dev, irq, fman_irq, IRQF_SHARED,
+ "fman", fman);
if (err < 0) {
dev_err(&of_dev->dev, "%s: irq %d allocation failed (error = %d)\n",
__func__, irq, err);
--
1.7.1


2018-06-07 03:48:49

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 03/10] dt-binding: ptp_qoriq: add DPAA FMan support

This patch is to add bindings description for DPAA
FMan 1588 timer, and also remove its description in
fsl-fman dt-bindings document.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- None.
---
Documentation/devicetree/bindings/net/fsl-fman.txt | 25 +-------------------
.../devicetree/bindings/ptp/ptp-qoriq.txt | 15 +++++++++--
2 files changed, 13 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/fsl-fman.txt b/Documentation/devicetree/bindings/net/fsl-fman.txt
index df873d1..74603dd 100644
--- a/Documentation/devicetree/bindings/net/fsl-fman.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fman.txt
@@ -356,30 +356,7 @@ ethernet@e0000 {
============================================================================
FMan IEEE 1588 Node

-DESCRIPTION
-
-The FMan interface to support IEEE 1588
-
-
-PROPERTIES
-
-- compatible
- Usage: required
- Value type: <stringlist>
- Definition: A standard property.
- Must include "fsl,fman-ptp-timer".
-
-- reg
- Usage: required
- Value type: <prop-encoded-array>
- Definition: A standard property.
-
-EXAMPLE
-
-ptp-timer@fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
-};
+Refer to Documentation/devicetree/bindings/ptp/ptp-qoriq.txt

=============================================================================
FMan MDIO Node
diff --git a/Documentation/devicetree/bindings/ptp/ptp-qoriq.txt b/Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
index 0f569d8..c5d0e79 100644
--- a/Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
+++ b/Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
@@ -2,7 +2,8 @@

General Properties:

- - compatible Should be "fsl,etsec-ptp"
+ - compatible Should be "fsl,etsec-ptp" for eTSEC
+ Should be "fsl,fman-ptp-timer" for DPAA FMan
- reg Offset and length of the register set for the device
- interrupts There should be at least two interrupts. Some devices
have as many as four PTP related interrupts.
@@ -43,14 +44,22 @@ Clock Properties:
value, which will be directly written in those bits, that is why,
according to reference manual, the next clock sources can be used:

+ For eTSEC,
<0> - external high precision timer reference clock (TSEC_TMR_CLK
input is used for this purpose);
<1> - eTSEC system clock;
<2> - eTSEC1 transmit clock;
<3> - RTC clock input.

- When this attribute is not used, eTSEC system clock will serve as
- IEEE 1588 timer reference clock.
+ For DPAA FMan,
+ <0> - external high precision timer reference clock (TMR_1588_CLK)
+ <1> - MAC system clock (1/2 FMan clock)
+ <2> - reserved
+ <3> - RTC clock oscillator
+
+ When this attribute is not used, the IEEE 1588 timer reference clock
+ will use the eTSEC system clock (for Gianfar) or the MAC system
+ clock (for DPAA).

Example:

--
1.7.1


2018-06-07 03:49:45

by Yangbo Lu

[permalink] [raw]
Subject: [v2, 07/10] fsl/fman_port: support getting timestamp field

This patch is to add fman_port_get_tstamp_field() interface
to get timestamp field data.

Signed-off-by: Yangbo Lu <[email protected]>
---
Changes for v2:
- None.
---
drivers/net/ethernet/freescale/fman/fman_port.c | 12 ++++++++++++
drivers/net/ethernet/freescale/fman/fman_port.h | 3 +++
2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c
index ce6e24c..86f0094 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.c
+++ b/drivers/net/ethernet/freescale/fman/fman_port.c
@@ -1731,6 +1731,18 @@ int fman_port_get_hash_result_offset(struct fman_port *port, u32 *offset)
}
EXPORT_SYMBOL(fman_port_get_hash_result_offset);

+int fman_port_get_tstamp_field(struct fman_port *port, const void *data,
+ u64 *tstamp)
+{
+ if (port->buffer_offsets.time_stamp_offset == ILLEGAL_BASE)
+ return -EINVAL;
+
+ *tstamp = *(u64 *)(data + port->buffer_offsets.time_stamp_offset);
+
+ return 0;
+}
+EXPORT_SYMBOL(fman_port_get_tstamp_field);
+
static int fman_port_probe(struct platform_device *of_dev)
{
struct fman_port *port;
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.h b/drivers/net/ethernet/freescale/fman/fman_port.h
index e86ca6a..d10e48d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.h
+++ b/drivers/net/ethernet/freescale/fman/fman_port.h
@@ -153,6 +153,9 @@ int fman_port_cfg_buf_prefix_content(struct fman_port *port,

int fman_port_get_hash_result_offset(struct fman_port *port, u32 *offset);

+int fman_port_get_tstamp_field(struct fman_port *port, const void *data,
+ u64 *tstamp);
+
struct fman_port *fman_port_bind(struct device *dev);

#endif /* __FMAN_PORT_H */
--
1.7.1


2018-06-07 08:25:45

by Madalin-cristian Bucur

[permalink] [raw]
Subject: RE: [v2, 09/10] dpaa_eth: add support for hardware timestamping

> -----Original Message-----
> From: Yangbo Lu [mailto:[email protected]]
> Sent: Thursday, June 7, 2018 6:23 AM
> Subject: [v2, 09/10] dpaa_eth: add support for hardware timestamping
>
> This patch is to add hardware timestamping support
> for dpaa_eth. On Rx, timestamping is enabled for
> all frames. On Tx, we only instruct the hardware
> to timestamp the frames marked accordingly by the
> stack.
>
> Signed-off-by: Yangbo Lu <[email protected]>
> ---
> Changes for v2:
> - Removed ifdef for timestamp code.
> - Minor fixes for code style.
> ---
> drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 101
> ++++++++++++++++++++++-
> drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 3 +
> 2 files changed, 99 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> index fd43f98..bd589ac 100644
> --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> @@ -1168,7 +1168,7 @@ static int dpaa_eth_init_tx_port(struct fman_port
> *port, struct dpaa_fq *errq,
> buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
> buf_prefix_content.pass_prs_result = true;
> buf_prefix_content.pass_hash_result = true;
> - buf_prefix_content.pass_time_stamp = false;
> + buf_prefix_content.pass_time_stamp = true;
> buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
>
> params.specific_params.non_rx_params.err_fqid = errq->fqid;
> @@ -1210,7 +1210,7 @@ static int dpaa_eth_init_rx_port(struct fman_port
> *port, struct dpaa_bp **bps,
> buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
> buf_prefix_content.pass_prs_result = true;
> buf_prefix_content.pass_hash_result = true;
> - buf_prefix_content.pass_time_stamp = false;
> + buf_prefix_content.pass_time_stamp = true;
> buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
>
> rx_p = &params.specific_params.rx_params;
> @@ -1592,6 +1592,16 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv
> *priv)
> return 0;
> }
>
> +static int dpaa_get_tstamp_ns(struct net_device *net_dev, u64 *ns,
> + struct fman_port *port, const void *data)
> +{
> + if (!fman_port_get_tstamp_field(port, data, ns)) {
> + be64_to_cpus(ns);

Please move this endianness conversion in the fman API.

> + return 0;
> + }
> + return -EINVAL;
> +}
> +
> /* Cleanup function for outgoing frame descriptors that were built on Tx
> path,
> * either contiguous frames or scatter/gather ones.
> * Skb freeing is not handled here.
> @@ -1607,14 +1617,29 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv
> *priv)
> {
> const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
> struct device *dev = priv->net_dev->dev.parent;
> + struct skb_shared_hwtstamps shhwtstamps;
> dma_addr_t addr = qm_fd_addr(fd);
> const struct qm_sg_entry *sgt;
> struct sk_buff **skbh, *skb;
> int nr_frags, i;
> + u64 ns;
>
> skbh = (struct sk_buff **)phys_to_virt(addr);
> skb = *skbh;
>
> + if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags &
> SKBTX_HW_TSTAMP) {
> + memset(&shhwtstamps, 0, sizeof(shhwtstamps));
> +
> + if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
> + priv->mac_dev->port[TX],
> + (void *)skbh)) {
> + shhwtstamps.hwtstamp = ns_to_ktime(ns);
> + skb_tstamp_tx(skb, &shhwtstamps);
> + } else {
> + dev_warn(dev, "dpaa_get_tstamp_ns failed!\n");
> + }
> + }
> +
> if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
> nr_frags = skb_shinfo(skb)->nr_frags;
> dma_unmap_single(dev, addr, qm_fd_get_offset(fd) +
> @@ -2086,6 +2111,11 @@ static int dpaa_start_xmit(struct sk_buff *skb,
> struct net_device *net_dev)
> if (unlikely(err < 0))
> goto skb_to_fd_failed;
>
> + if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags &
> SKBTX_HW_TSTAMP) {
> + fd.cmd |= FM_FD_CMD_UPD;

The fd.cmd field is big endian, please use this:

+ fd.cmd |= cpu_to_be32(FM_FD_CMD_UPD);

> + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
> + }
> +
> if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
> return NETDEV_TX_OK;
>
> @@ -2227,6 +2257,7 @@ static enum qman_cb_dqrr_result
> rx_default_dqrr(struct qman_portal *portal,
> struct qman_fq *fq,
> const struct qm_dqrr_entry
> *dq)
> {
> + struct skb_shared_hwtstamps *shhwtstamps;
> struct rtnl_link_stats64 *percpu_stats;
> struct dpaa_percpu_priv *percpu_priv;
> const struct qm_fd *fd = &dq->fd;
> @@ -2240,6 +2271,7 @@ static enum qman_cb_dqrr_result
> rx_default_dqrr(struct qman_portal *portal,
> struct sk_buff *skb;
> int *count_ptr;
> void *vaddr;
> + u64 ns;
>
> fd_status = be32_to_cpu(fd->status);
> fd_format = qm_fd_get_format(fd);
> @@ -2304,6 +2336,18 @@ static enum qman_cb_dqrr_result
> rx_default_dqrr(struct qman_portal *portal,
> if (!skb)
> return qman_cb_dqrr_consume;
>
> + if (priv->rx_tstamp) {
> + shhwtstamps = skb_hwtstamps(skb);
> + memset(shhwtstamps, 0, sizeof(*shhwtstamps));
> +
> + if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
> + priv->mac_dev->port[RX],
> + vaddr))
> + shhwtstamps->hwtstamp = ns_to_ktime(ns);
> + else
> + dev_warn(net_dev->dev.parent,
> "dpaa_get_tstamp_ns failed!\n");
> + }
> +
> skb->protocol = eth_type_trans(skb, net_dev);
>
> if (net_dev->features & NETIF_F_RXHASH && priv->keygen_in_use
> &&
> @@ -2523,11 +2567,58 @@ static int dpaa_eth_stop(struct net_device
> *net_dev)
> return err;
> }
>
> +static int dpaa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
> +{
> + struct dpaa_priv *priv = netdev_priv(dev);
> + struct hwtstamp_config config;
> +
> + if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
> + return -EFAULT;
> +
> + switch (config.tx_type) {
> + case HWTSTAMP_TX_OFF:
> + /* Couldn't disable rx/tx timestamping separately.
> + * Do nothing here.
> + */
> + priv->tx_tstamp = false;
> + break;
> + case HWTSTAMP_TX_ON:
> + priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac,
> true);
> + priv->tx_tstamp = true;
> + break;
> + default:
> + return -ERANGE;
> + }
> +
> + if (config.rx_filter == HWTSTAMP_FILTER_NONE) {
> + /* Couldn't disable rx/tx timestamping separately.
> + * Do nothing here.
> + */
> + priv->rx_tstamp = false;
> + } else {
> + priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac,
> true);
> + priv->rx_tstamp = true;
> + /* TS is set for all frame types, not only those requested */
> + config.rx_filter = HWTSTAMP_FILTER_ALL;
> + }
> +
> + return copy_to_user(rq->ifr_data, &config, sizeof(config)) ?
> + -EFAULT : 0;
> +}
> +
> static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
> {
> - if (!net_dev->phydev)
> - return -EINVAL;
> - return phy_mii_ioctl(net_dev->phydev, rq, cmd);
> + int ret = -EINVAL;
> +
> + if (cmd == SIOCGMIIREG) {
> + if (net_dev->phydev)
> + return phy_mii_ioctl(net_dev->phydev, rq, cmd);
> + }
> +
> + if (cmd == SIOCSHWTSTAMP)
> + return dpaa_ts_ioctl(net_dev, rq, cmd);
> +
> + return ret;
> }
>
> static const struct net_device_ops dpaa_ops = {
> diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> index bd94220..af320f8 100644
> --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> @@ -182,6 +182,9 @@ struct dpaa_priv {
>
> struct dpaa_buffer_layout buf_layout[2];
> u16 rx_headroom;
> +
> + bool tx_tstamp; /* Tx timestamping enabled */
> + bool rx_tstamp; /* Rx timestamping enabled */
> };
>
> /* from dpaa_ethtool.c */
> --
> 1.7.1


2018-06-07 09:28:32

by Yangbo Lu

[permalink] [raw]
Subject: RE: [v2, 09/10] dpaa_eth: add support for hardware timestamping

Hi Madalin,

> -----Original Message-----
> From: Madalin-cristian Bucur
> Sent: Thursday, June 7, 2018 4:24 PM
> To: Y.b. Lu <[email protected]>; [email protected]; Richard Cochran
> <[email protected]>; Rob Herring <[email protected]>; Shawn
> Guo <[email protected]>; David S . Miller <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected]; Y.b. Lu
> <[email protected]>
> Subject: RE: [v2, 09/10] dpaa_eth: add support for hardware timestamping
>
> > -----Original Message-----
> > From: Yangbo Lu [mailto:[email protected]]
> > Sent: Thursday, June 7, 2018 6:23 AM
> > Subject: [v2, 09/10] dpaa_eth: add support for hardware timestamping
> >
> > This patch is to add hardware timestamping support for dpaa_eth. On
> > Rx, timestamping is enabled for all frames. On Tx, we only instruct
> > the hardware to timestamp the frames marked accordingly by the stack.
> >
> > Signed-off-by: Yangbo Lu <[email protected]>
> > ---
> > Changes for v2:
> > - Removed ifdef for timestamp code.
> > - Minor fixes for code style.
> > ---
> > drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 101
> > ++++++++++++++++++++++-
> > drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 3 +
> > 2 files changed, 99 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > index fd43f98..bd589ac 100644
> > --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > @@ -1168,7 +1168,7 @@ static int dpaa_eth_init_tx_port(struct
> > fman_port *port, struct dpaa_fq *errq,
> > buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
> > buf_prefix_content.pass_prs_result = true;
> > buf_prefix_content.pass_hash_result = true;
> > - buf_prefix_content.pass_time_stamp = false;
> > + buf_prefix_content.pass_time_stamp = true;
> > buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
> >
> > params.specific_params.non_rx_params.err_fqid = errq->fqid; @@
> > -1210,7 +1210,7 @@ static int dpaa_eth_init_rx_port(struct fman_port
> > *port, struct dpaa_bp **bps,
> > buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
> > buf_prefix_content.pass_prs_result = true;
> > buf_prefix_content.pass_hash_result = true;
> > - buf_prefix_content.pass_time_stamp = false;
> > + buf_prefix_content.pass_time_stamp = true;
> > buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
> >
> > rx_p = &params.specific_params.rx_params;
> > @@ -1592,6 +1592,16 @@ static int dpaa_eth_refill_bpools(struct
> > dpaa_priv
> > *priv)
> > return 0;
> > }
> >
> > +static int dpaa_get_tstamp_ns(struct net_device *net_dev, u64 *ns,
> > + struct fman_port *port, const void *data) {
> > + if (!fman_port_get_tstamp_field(port, data, ns)) {
> > + be64_to_cpus(ns);
>
> Please move this endianness conversion in the fman API.

[Y.b. Lu] Ok. Will move to fman API in next version.

>
> > + return 0;
> > + }
> > + return -EINVAL;
> > +}
> > +
> > /* Cleanup function for outgoing frame descriptors that were built on
> > Tx path,
> > * either contiguous frames or scatter/gather ones.
> > * Skb freeing is not handled here.
> > @@ -1607,14 +1617,29 @@ static int dpaa_eth_refill_bpools(struct
> > dpaa_priv
> > *priv)
> > {
> > const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
> > struct device *dev = priv->net_dev->dev.parent;
> > + struct skb_shared_hwtstamps shhwtstamps;
> > dma_addr_t addr = qm_fd_addr(fd);
> > const struct qm_sg_entry *sgt;
> > struct sk_buff **skbh, *skb;
> > int nr_frags, i;
> > + u64 ns;
> >
> > skbh = (struct sk_buff **)phys_to_virt(addr);
> > skb = *skbh;
> >
> > + if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags &
> > SKBTX_HW_TSTAMP) {
> > + memset(&shhwtstamps, 0, sizeof(shhwtstamps));
> > +
> > + if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
> > + priv->mac_dev->port[TX],
> > + (void *)skbh)) {
> > + shhwtstamps.hwtstamp = ns_to_ktime(ns);
> > + skb_tstamp_tx(skb, &shhwtstamps);
> > + } else {
> > + dev_warn(dev, "dpaa_get_tstamp_ns failed!\n");
> > + }
> > + }
> > +
> > if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
> > nr_frags = skb_shinfo(skb)->nr_frags;
> > dma_unmap_single(dev, addr, qm_fd_get_offset(fd) + @@ -2086,6
> > +2111,11 @@ static int dpaa_start_xmit(struct sk_buff *skb, struct
> > net_device *net_dev)
> > if (unlikely(err < 0))
> > goto skb_to_fd_failed;
> >
> > + if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags &
> > SKBTX_HW_TSTAMP) {
> > + fd.cmd |= FM_FD_CMD_UPD;
>
> The fd.cmd field is big endian, please use this:
>
> + fd.cmd |= cpu_to_be32(FM_FD_CMD_UPD);
>

[Y.b. Lu] Thanks a lot for pointing out this issue. This fixes TX timestamp issue on ARM platform.
By now, I have verified both PowerPC platform and ARM platform. The PTP clock driver and timestamping worked fine.
I will send out v3 patch-set for reviewing.

> > + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
> > + }
> > +
> > if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
> > return NETDEV_TX_OK;
> >
> > @@ -2227,6 +2257,7 @@ static enum qman_cb_dqrr_result
> > rx_default_dqrr(struct qman_portal *portal,
> > struct qman_fq *fq,
> > const struct qm_dqrr_entry
> > *dq)
> > {
> > + struct skb_shared_hwtstamps *shhwtstamps;
> > struct rtnl_link_stats64 *percpu_stats;
> > struct dpaa_percpu_priv *percpu_priv;
> > const struct qm_fd *fd = &dq->fd;
> > @@ -2240,6 +2271,7 @@ static enum qman_cb_dqrr_result
> > rx_default_dqrr(struct qman_portal *portal,
> > struct sk_buff *skb;
> > int *count_ptr;
> > void *vaddr;
> > + u64 ns;
> >
> > fd_status = be32_to_cpu(fd->status);
> > fd_format = qm_fd_get_format(fd);
> > @@ -2304,6 +2336,18 @@ static enum qman_cb_dqrr_result
> > rx_default_dqrr(struct qman_portal *portal,
> > if (!skb)
> > return qman_cb_dqrr_consume;
> >
> > + if (priv->rx_tstamp) {
> > + shhwtstamps = skb_hwtstamps(skb);
> > + memset(shhwtstamps, 0, sizeof(*shhwtstamps));
> > +
> > + if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
> > + priv->mac_dev->port[RX],
> > + vaddr))
> > + shhwtstamps->hwtstamp = ns_to_ktime(ns);
> > + else
> > + dev_warn(net_dev->dev.parent,
> > "dpaa_get_tstamp_ns failed!\n");
> > + }
> > +
> > skb->protocol = eth_type_trans(skb, net_dev);
> >
> > if (net_dev->features & NETIF_F_RXHASH && priv->keygen_in_use &&
> @@
> > -2523,11 +2567,58 @@ static int dpaa_eth_stop(struct net_device
> > *net_dev)
> > return err;
> > }
> >
> > +static int dpaa_ts_ioctl(struct net_device *dev, struct ifreq *rq,
> > +int cmd) {
> > + struct dpaa_priv *priv = netdev_priv(dev);
> > + struct hwtstamp_config config;
> > +
> > + if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
> > + return -EFAULT;
> > +
> > + switch (config.tx_type) {
> > + case HWTSTAMP_TX_OFF:
> > + /* Couldn't disable rx/tx timestamping separately.
> > + * Do nothing here.
> > + */
> > + priv->tx_tstamp = false;
> > + break;
> > + case HWTSTAMP_TX_ON:
> > + priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac,
> > true);
> > + priv->tx_tstamp = true;
> > + break;
> > + default:
> > + return -ERANGE;
> > + }
> > +
> > + if (config.rx_filter == HWTSTAMP_FILTER_NONE) {
> > + /* Couldn't disable rx/tx timestamping separately.
> > + * Do nothing here.
> > + */
> > + priv->rx_tstamp = false;
> > + } else {
> > + priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac,
> > true);
> > + priv->rx_tstamp = true;
> > + /* TS is set for all frame types, not only those requested */
> > + config.rx_filter = HWTSTAMP_FILTER_ALL;
> > + }
> > +
> > + return copy_to_user(rq->ifr_data, &config, sizeof(config)) ?
> > + -EFAULT : 0;
> > +}
> > +
> > static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq,
> > int cmd) {
> > - if (!net_dev->phydev)
> > - return -EINVAL;
> > - return phy_mii_ioctl(net_dev->phydev, rq, cmd);
> > + int ret = -EINVAL;
> > +
> > + if (cmd == SIOCGMIIREG) {
> > + if (net_dev->phydev)
> > + return phy_mii_ioctl(net_dev->phydev, rq, cmd);
> > + }
> > +
> > + if (cmd == SIOCSHWTSTAMP)
> > + return dpaa_ts_ioctl(net_dev, rq, cmd);
> > +
> > + return ret;
> > }
> >
> > static const struct net_device_ops dpaa_ops = { diff --git
> > a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> > b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> > index bd94220..af320f8 100644
> > --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> > +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> > @@ -182,6 +182,9 @@ struct dpaa_priv {
> >
> > struct dpaa_buffer_layout buf_layout[2];
> > u16 rx_headroom;
> > +
> > + bool tx_tstamp; /* Tx timestamping enabled */
> > + bool rx_tstamp; /* Rx timestamping enabled */
> > };
> >
> > /* from dpaa_ethtool.c */
> > --
> > 1.7.1