* [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping
@ 2019-05-31 5:56 Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 1/6] net: Introduce peer to peer one step PTP " Richard Cochran
` (6 more replies)
0 siblings, 7 replies; 16+ messages in thread
From: Richard Cochran @ 2019-05-31 5:56 UTC (permalink / raw)
To: netdev
Cc: David Miller, devicetree, Andrew Lunn, Florian Fainelli,
Jacob Keller, Mark Rutland, Miroslav Lichvar, Rob Herring,
Willem de Bruijn
This series adds support for PTP (IEEE 1588) P2P one-step time
stamping along with a driver for a hardware device that supports this.
If the hardware supports p2p one-step, it subtracts the ingress time
stamp value from the Pdelay_Request correction field. The user space
software stack then simply copies the correction field into the
Pdelay_Response, and on transmission the hardware adds the egress time
stamp into the correction field.
This new functionality extends CONFIG_NETWORK_PHY_TIMESTAMPING to
cover MII snooping devices, but it still depends on phylib, just as
that option does. Expanding beyond phylib is not within the scope of
the this series.
User space support is available in the current linuxptp master branch.
- Patch 1 adds the new option.
- Patches 2-5 add support for MII time stamping in non-PHY devices.
- Patch 6 adds a driver implementing the new option.
Thanks,
Richard
Changed in v5:
~~~~~~~~~~~~~~
- Fixed build failure in macvlan.
- Fixed latent bug with its gcc warning in the driver.
Changed in v4:
~~~~~~~~~~~~~~
- Correct error paths and PTR_ERR return values in the framework.
- Expanded KernelDoc comments WRT PHY locking.
- Pick up Andrew's review tag.
Changed in v3:
~~~~~~~~~~~~~~
- Simplify the device tree binding and document the time stamping
phandle by itself.
Changed in v2:
~~~~~~~~~~~~~~
- Per the v1 review, changed the modeling of MII time stamping
devices. They are no longer a kind of mdio device.
Richard Cochran (6):
net: Introduce peer to peer one step PTP time stamping.
net: Introduce a new MII time stamping interface.
net: Add a layer for non-PHY MII time stamping drivers.
dt-bindings: ptp: Introduce MII time stamping devices.
net: mdio: of: Register discovered MII time stampers.
ptp: Add a driver for InES time stamping IP core.
Documentation/devicetree/bindings/ptp/ptp-ines.txt | 35 +
.../devicetree/bindings/ptp/timestamper.txt | 41 +
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 1 +
drivers/net/macvlan.c | 4 +-
drivers/net/phy/Makefile | 2 +
drivers/net/phy/dp83640.c | 47 +-
drivers/net/phy/mii_timestamper.c | 121 +++
drivers/net/phy/phy.c | 4 +-
drivers/net/phy/phy_device.c | 5 +
drivers/of/of_mdio.c | 30 +-
drivers/ptp/Kconfig | 10 +
drivers/ptp/Makefile | 1 +
drivers/ptp/ptp_ines.c | 859 +++++++++++++++++++++
include/linux/mii_timestamper.h | 120 +++
include/linux/phy.h | 25 +-
include/uapi/linux/net_tstamp.h | 8 +
net/8021q/vlan_dev.c | 4 +-
net/Kconfig | 7 +-
net/core/dev_ioctl.c | 1 +
net/core/ethtool.c | 4 +-
net/core/timestamping.c | 20 +-
21 files changed, 1289 insertions(+), 60 deletions(-)
create mode 100644 Documentation/devicetree/bindings/ptp/ptp-ines.txt
create mode 100644 Documentation/devicetree/bindings/ptp/timestamper.txt
create mode 100644 drivers/net/phy/mii_timestamper.c
create mode 100644 drivers/ptp/ptp_ines.c
create mode 100644 include/linux/mii_timestamper.h
--
2.11.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH V5 net-next 1/6] net: Introduce peer to peer one step PTP time stamping.
2019-05-31 5:56 [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping Richard Cochran
@ 2019-05-31 5:56 ` Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 2/6] net: Introduce a new MII time stamping interface Richard Cochran
` (5 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Richard Cochran @ 2019-05-31 5:56 UTC (permalink / raw)
To: netdev
Cc: David Miller, devicetree, Andrew Lunn, Florian Fainelli,
Jacob Keller, Mark Rutland, Miroslav Lichvar, Rob Herring,
Willem de Bruijn
The 1588 standard defines one step operation for both Sync and
PDelay_Resp messages. Up until now, hardware with P2P one step has
been rare, and kernel support was lacking. This patch adds support of
the mode in anticipation of new hardware developments.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 1 +
include/uapi/linux/net_tstamp.h | 8 ++++++++
net/core/dev_ioctl.c | 1 +
3 files changed, 10 insertions(+)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 03ac10b1cd1e..44a378f26bbd 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -15380,6 +15380,7 @@ int bnx2x_configure_ptp_filters(struct bnx2x *bp)
REG_WR(bp, rule, BNX2X_PTP_TX_ON_RULE_MASK);
break;
case HWTSTAMP_TX_ONESTEP_SYNC:
+ case HWTSTAMP_TX_ONESTEP_P2P:
BNX2X_ERR("One-step timestamping is not supported\n");
return -ERANGE;
}
diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h
index e5b39721c6e4..f96e650d0af9 100644
--- a/include/uapi/linux/net_tstamp.h
+++ b/include/uapi/linux/net_tstamp.h
@@ -90,6 +90,14 @@ enum hwtstamp_tx_types {
* queue.
*/
HWTSTAMP_TX_ONESTEP_SYNC,
+
+ /*
+ * Same as HWTSTAMP_TX_ONESTEP_SYNC, but also enables time
+ * stamp insertion directly into PDelay_Resp packets. In this
+ * case, neither transmitted Sync nor PDelay_Resp packets will
+ * receive a time stamp via the socket error queue.
+ */
+ HWTSTAMP_TX_ONESTEP_P2P,
};
/* possible values for hwtstamp_config->rx_filter */
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 5163d900bb4f..dbaebbe573f0 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -187,6 +187,7 @@ static int net_hwtstamp_validate(struct ifreq *ifr)
case HWTSTAMP_TX_OFF:
case HWTSTAMP_TX_ON:
case HWTSTAMP_TX_ONESTEP_SYNC:
+ case HWTSTAMP_TX_ONESTEP_P2P:
tx_type_valid = 1;
break;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V5 net-next 2/6] net: Introduce a new MII time stamping interface.
2019-05-31 5:56 [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 1/6] net: Introduce peer to peer one step PTP " Richard Cochran
@ 2019-05-31 5:56 ` Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 3/6] net: Add a layer for non-PHY MII time stamping drivers Richard Cochran
` (4 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Richard Cochran @ 2019-05-31 5:56 UTC (permalink / raw)
To: netdev
Cc: David Miller, devicetree, Andrew Lunn, Florian Fainelli,
Jacob Keller, Mark Rutland, Miroslav Lichvar, Rob Herring,
Willem de Bruijn
Currently the stack supports time stamping in PHY devices. However,
there are newer, non-PHY devices that can snoop an MII bus and provide
time stamps. In order to support such devices, this patch introduces
a new interface to be used by both PHY and non-PHY devices.
In addition, the one and only user of the old PHY time stamping API is
converted to the new interface.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/macvlan.c | 4 +--
drivers/net/phy/dp83640.c | 47 +++++++++++++++++++++++-----------
drivers/net/phy/phy.c | 4 +--
drivers/net/phy/phy_device.c | 2 ++
include/linux/mii_timestamper.h | 56 +++++++++++++++++++++++++++++++++++++++++
include/linux/phy.h | 25 ++----------------
net/8021q/vlan_dev.c | 4 +--
net/core/ethtool.c | 4 +--
net/core/timestamping.c | 20 +++++++--------
9 files changed, 110 insertions(+), 56 deletions(-)
create mode 100644 include/linux/mii_timestamper.h
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 0ccabde8e9c9..8f7868d31612 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1056,8 +1056,8 @@ static int macvlan_ethtool_get_ts_info(struct net_device *dev,
const struct ethtool_ops *ops = real_dev->ethtool_ops;
struct phy_device *phydev = real_dev->phydev;
- if (phydev && phydev->drv && phydev->drv->ts_info) {
- return phydev->drv->ts_info(phydev, info);
+ if (phydev && phydev->mii_ts && phydev->mii_ts->ts_info) {
+ return phydev->mii_ts->ts_info(phydev->mii_ts, info);
} else if (ops->get_ts_info) {
return ops->get_ts_info(real_dev, info);
} else {
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 6580094161a9..a87a72818e89 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -98,6 +98,7 @@ struct dp83640_private {
struct list_head list;
struct dp83640_clock *clock;
struct phy_device *phydev;
+ struct mii_timestamper mii_ts;
struct delayed_work ts_work;
int hwts_tx_en;
int hwts_rx_en;
@@ -201,6 +202,14 @@ static void dp83640_gpio_defaults(struct ptp_pin_desc *pd)
static LIST_HEAD(phyter_clocks);
static DEFINE_MUTEX(phyter_clocks_lock);
+static int dp83640_hwtstamp(struct mii_timestamper *mii_ts,
+ struct ifreq *ifr);
+static int dp83640_ts_info(struct mii_timestamper *mii_ts,
+ struct ethtool_ts_info *info);
+static bool dp83640_rxtstamp(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type);
+static void dp83640_txtstamp(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type);
static void rx_timestamp_work(struct work_struct *work);
/* extended register access functions */
@@ -1133,13 +1142,18 @@ static int dp83640_probe(struct phy_device *phydev)
goto no_memory;
dp83640->phydev = phydev;
- INIT_DELAYED_WORK(&dp83640->ts_work, rx_timestamp_work);
+ dp83640->mii_ts.rxtstamp = dp83640_rxtstamp;
+ dp83640->mii_ts.txtstamp = dp83640_txtstamp;
+ dp83640->mii_ts.hwtstamp = dp83640_hwtstamp;
+ dp83640->mii_ts.ts_info = dp83640_ts_info;
+ INIT_DELAYED_WORK(&dp83640->ts_work, rx_timestamp_work);
INIT_LIST_HEAD(&dp83640->rxts);
INIT_LIST_HEAD(&dp83640->rxpool);
for (i = 0; i < MAX_RXTS; i++)
list_add(&dp83640->rx_pool_data[i].list, &dp83640->rxpool);
+ phydev->mii_ts = &dp83640->mii_ts;
phydev->priv = dp83640;
spin_lock_init(&dp83640->rx_lock);
@@ -1180,6 +1194,8 @@ static void dp83640_remove(struct phy_device *phydev)
if (phydev->mdio.addr == BROADCAST_ADDR)
return;
+ phydev->mii_ts = NULL;
+
enable_status_frames(phydev, false);
cancel_delayed_work_sync(&dp83640->ts_work);
@@ -1303,9 +1319,10 @@ static int dp83640_config_intr(struct phy_device *phydev)
}
}
-static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
+static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
{
- struct dp83640_private *dp83640 = phydev->priv;
+ struct dp83640_private *dp83640 =
+ container_of(mii_ts, struct dp83640_private, mii_ts);
struct hwtstamp_config cfg;
u16 txcfg0, rxcfg0;
@@ -1381,8 +1398,8 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
mutex_lock(&dp83640->clock->extreg_lock);
- ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0);
- ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0);
+ ext_write(0, dp83640->phydev, PAGE5, PTP_TXCFG0, txcfg0);
+ ext_write(0, dp83640->phydev, PAGE5, PTP_RXCFG0, rxcfg0);
mutex_unlock(&dp83640->clock->extreg_lock);
@@ -1412,10 +1429,11 @@ static void rx_timestamp_work(struct work_struct *work)
schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
}
-static bool dp83640_rxtstamp(struct phy_device *phydev,
+static bool dp83640_rxtstamp(struct mii_timestamper *mii_ts,
struct sk_buff *skb, int type)
{
- struct dp83640_private *dp83640 = phydev->priv;
+ struct dp83640_private *dp83640 =
+ container_of(mii_ts, struct dp83640_private, mii_ts);
struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
struct list_head *this, *next;
struct rxts *rxts;
@@ -1461,11 +1479,12 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
return true;
}
-static void dp83640_txtstamp(struct phy_device *phydev,
+static void dp83640_txtstamp(struct mii_timestamper *mii_ts,
struct sk_buff *skb, int type)
{
struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
- struct dp83640_private *dp83640 = phydev->priv;
+ struct dp83640_private *dp83640 =
+ container_of(mii_ts, struct dp83640_private, mii_ts);
switch (dp83640->hwts_tx_en) {
@@ -1488,9 +1507,11 @@ static void dp83640_txtstamp(struct phy_device *phydev,
}
}
-static int dp83640_ts_info(struct phy_device *dev, struct ethtool_ts_info *info)
+static int dp83640_ts_info(struct mii_timestamper *mii_ts,
+ struct ethtool_ts_info *info)
{
- struct dp83640_private *dp83640 = dev->priv;
+ struct dp83640_private *dp83640 =
+ container_of(mii_ts, struct dp83640_private, mii_ts);
info->so_timestamping =
SOF_TIMESTAMPING_TX_HARDWARE |
@@ -1521,10 +1542,6 @@ static struct phy_driver dp83640_driver = {
.config_init = dp83640_config_init,
.ack_interrupt = dp83640_ack_interrupt,
.config_intr = dp83640_config_intr,
- .ts_info = dp83640_ts_info,
- .hwtstamp = dp83640_hwtstamp,
- .rxtstamp = dp83640_rxtstamp,
- .txtstamp = dp83640_txtstamp,
};
static int __init dp83640_init(void)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 84671d868a80..1137bef6a752 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -470,8 +470,8 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
return 0;
case SIOCSHWTSTAMP:
- if (phydev->drv && phydev->drv->hwtstamp)
- return phydev->drv->hwtstamp(phydev, ifr);
+ if (phydev->mii_ts && phydev->mii_ts->hwtstamp)
+ return phydev->mii_ts->hwtstamp(phydev->mii_ts, ifr);
/* fall through */
default:
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 2c879ba01f35..055087654b2c 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -915,6 +915,8 @@ static void phy_link_change(struct phy_device *phydev, bool up, bool do_carrier)
netif_carrier_off(netdev);
}
phydev->adjust_link(netdev);
+ if (phydev->mii_ts && phydev->mii_ts->link_state)
+ phydev->mii_ts->link_state(phydev->mii_ts, phydev);
}
/**
diff --git a/include/linux/mii_timestamper.h b/include/linux/mii_timestamper.h
new file mode 100644
index 000000000000..8586eed2f3b9
--- /dev/null
+++ b/include/linux/mii_timestamper.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Support for generic time stamping devices on MII buses.
+ * Copyright (C) 2018 Richard Cochran <richardcochran@gmail.com>
+ */
+#ifndef _LINUX_MII_TIMESTAMPER_H
+#define _LINUX_MII_TIMESTAMPER_H
+
+#include <linux/device.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+
+/**
+ * struct mii_timestamper - Callback interface to MII time stamping devices.
+ *
+ * @rxtstamp: Requests a Rx timestamp for 'skb'. If the skb is accepted,
+ * the MII time stamping device promises to deliver it using
+ * netif_rx() as soon as a timestamp becomes available. One of
+ * the PTP_CLASS_ values is passed in 'type'. The function
+ * must return true if the skb is accepted for delivery.
+ *
+ * @txtstamp: Requests a Tx timestamp for 'skb'. The MII time stamping
+ * device promises to deliver it using skb_complete_tx_timestamp()
+ * as soon as a timestamp becomes available. One of the PTP_CLASS_
+ * values is passed in 'type'.
+ *
+ * @hwtstamp: Handles SIOCSHWTSTAMP ioctl for hardware time stamping.
+ *
+ * @link_state: Allows the device to respond to changes in the link
+ * state. The caller invokes this function while holding
+ * the phy_device mutex.
+ *
+ * @ts_info: Handles ethtool queries for hardware time stamping.
+ *
+ * Drivers for PHY time stamping devices should embed their
+ * mii_timestamper within a private structure, obtaining a reference
+ * to it using container_of().
+ */
+struct mii_timestamper {
+ bool (*rxtstamp)(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type);
+
+ void (*txtstamp)(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type);
+
+ int (*hwtstamp)(struct mii_timestamper *mii_ts,
+ struct ifreq *ifreq);
+
+ void (*link_state)(struct mii_timestamper *mii_ts,
+ struct phy_device *phydev);
+
+ int (*ts_info)(struct mii_timestamper *mii_ts,
+ struct ethtool_ts_info *ts_info);
+};
+
+#endif
diff --git a/include/linux/phy.h b/include/linux/phy.h
index dc4b51060ebc..ad63820a89d2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -22,6 +22,7 @@
#include <linux/linkmode.h>
#include <linux/mdio.h>
#include <linux/mii.h>
+#include <linux/mii_timestamper.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
@@ -443,6 +444,7 @@ struct phy_device {
struct phylink *phylink;
struct net_device *attached_dev;
+ struct mii_timestamper *mii_ts;
u8 mdix;
u8 mdix_ctrl;
@@ -548,29 +550,6 @@ struct phy_driver {
*/
int (*match_phy_device)(struct phy_device *phydev);
- /* Handles ethtool queries for hardware time stamping. */
- int (*ts_info)(struct phy_device *phydev, struct ethtool_ts_info *ti);
-
- /* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */
- int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr);
-
- /*
- * Requests a Rx timestamp for 'skb'. If the skb is accepted,
- * the phy driver promises to deliver it using netif_rx() as
- * soon as a timestamp becomes available. One of the
- * PTP_CLASS_ values is passed in 'type'. The function must
- * return true if the skb is accepted for delivery.
- */
- bool (*rxtstamp)(struct phy_device *dev, struct sk_buff *skb, int type);
-
- /*
- * Requests a Tx timestamp for 'skb'. The phy driver promises
- * to deliver it using skb_complete_tx_timestamp() as soon as a
- * timestamp becomes available. One of the PTP_CLASS_ values
- * is passed in 'type'.
- */
- void (*txtstamp)(struct phy_device *dev, struct sk_buff *skb, int type);
-
/* Some devices (e.g. qnap TS-119P II) require PHY register changes to
* enable Wake on LAN, so set_wol is provided to be called in the
* ethernet driver's set_wol function. */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index c546c4228075..12b832d32c59 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -682,8 +682,8 @@ static int vlan_ethtool_get_ts_info(struct net_device *dev,
const struct ethtool_ops *ops = vlan->real_dev->ethtool_ops;
struct phy_device *phydev = vlan->real_dev->phydev;
- if (phydev && phydev->drv && phydev->drv->ts_info) {
- return phydev->drv->ts_info(phydev, info);
+ if (phydev && phydev->mii_ts && phydev->mii_ts->ts_info) {
+ return phydev->mii_ts->ts_info(phydev->mii_ts, info);
} else if (ops->get_ts_info) {
return ops->get_ts_info(vlan->real_dev, info);
} else {
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 4a593853cbf2..e6cb3c987677 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -2168,8 +2168,8 @@ static int ethtool_get_ts_info(struct net_device *dev, void __user *useraddr)
memset(&info, 0, sizeof(info));
info.cmd = ETHTOOL_GET_TS_INFO;
- if (phydev && phydev->drv && phydev->drv->ts_info) {
- err = phydev->drv->ts_info(phydev, &info);
+ if (phydev && phydev->mii_ts && phydev->mii_ts->ts_info) {
+ err = phydev->mii_ts->ts_info(phydev->mii_ts, &info);
} else if (ops->get_ts_info) {
err = ops->get_ts_info(dev, &info);
} else {
diff --git a/net/core/timestamping.c b/net/core/timestamping.c
index 42689d5c468c..95c45c4dc0f9 100644
--- a/net/core/timestamping.c
+++ b/net/core/timestamping.c
@@ -26,7 +26,7 @@
static unsigned int classify(const struct sk_buff *skb)
{
if (likely(skb->dev && skb->dev->phydev &&
- skb->dev->phydev->drv))
+ skb->dev->phydev->mii_ts))
return ptp_classify_raw(skb);
else
return PTP_CLASS_NONE;
@@ -34,7 +34,7 @@ static unsigned int classify(const struct sk_buff *skb)
void skb_clone_tx_timestamp(struct sk_buff *skb)
{
- struct phy_device *phydev;
+ struct mii_timestamper *mii_ts;
struct sk_buff *clone;
unsigned int type;
@@ -45,22 +45,22 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)
if (type == PTP_CLASS_NONE)
return;
- phydev = skb->dev->phydev;
- if (likely(phydev->drv->txtstamp)) {
+ mii_ts = skb->dev->phydev->mii_ts;
+ if (likely(mii_ts->txtstamp)) {
clone = skb_clone_sk(skb);
if (!clone)
return;
- phydev->drv->txtstamp(phydev, clone, type);
+ mii_ts->txtstamp(mii_ts, clone, type);
}
}
EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
bool skb_defer_rx_timestamp(struct sk_buff *skb)
{
- struct phy_device *phydev;
+ struct mii_timestamper *mii_ts;
unsigned int type;
- if (!skb->dev || !skb->dev->phydev || !skb->dev->phydev->drv)
+ if (!skb->dev || !skb->dev->phydev || !skb->dev->phydev->mii_ts)
return false;
if (skb_headroom(skb) < ETH_HLEN)
@@ -75,9 +75,9 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)
if (type == PTP_CLASS_NONE)
return false;
- phydev = skb->dev->phydev;
- if (likely(phydev->drv->rxtstamp))
- return phydev->drv->rxtstamp(phydev, skb, type);
+ mii_ts = skb->dev->phydev->mii_ts;
+ if (likely(mii_ts->rxtstamp))
+ return mii_ts->rxtstamp(mii_ts, skb, type);
return false;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V5 net-next 3/6] net: Add a layer for non-PHY MII time stamping drivers.
2019-05-31 5:56 [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 1/6] net: Introduce peer to peer one step PTP " Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 2/6] net: Introduce a new MII time stamping interface Richard Cochran
@ 2019-05-31 5:56 ` Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 4/6] dt-bindings: ptp: Introduce MII time stamping devices Richard Cochran
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Richard Cochran @ 2019-05-31 5:56 UTC (permalink / raw)
To: netdev
Cc: David Miller, devicetree, Andrew Lunn, Florian Fainelli,
Jacob Keller, Mark Rutland, Miroslav Lichvar, Rob Herring,
Willem de Bruijn
While PHY time stamping drivers can simply attach their interface
directly to the PHY instance, stand alone drivers require support in
order to manage their services. Non-PHY MII time stamping drivers
have a control interface over another bus like I2C, SPI, UART, or via
a memory mapped peripheral. The controller device will be associated
with one or more time stamping channels, each of which sits snoops in
on a MII bus.
This patch provides a glue layer that will enable time stamping
channels to find their controlling device.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/phy/Makefile | 2 +
drivers/net/phy/mii_timestamper.c | 121 ++++++++++++++++++++++++++++++++++++++
include/linux/mii_timestamper.h | 64 ++++++++++++++++++++
net/Kconfig | 7 ++-
4 files changed, 191 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/phy/mii_timestamper.c
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index bac339e09042..4f7db9e23456 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -42,6 +42,8 @@ obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
+obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += mii_timestamper.o
+
obj-$(CONFIG_SFP) += sfp.o
sfp-obj-$(CONFIG_SFP) += sfp-bus.o
obj-y += $(sfp-obj-y) $(sfp-obj-m)
diff --git a/drivers/net/phy/mii_timestamper.c b/drivers/net/phy/mii_timestamper.c
new file mode 100644
index 000000000000..bdc9bf8dfce2
--- /dev/null
+++ b/drivers/net/phy/mii_timestamper.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Support for generic time stamping devices on MII buses.
+// Copyright (C) 2018 Richard Cochran <richardcochran@gmail.com>
+//
+
+#include <linux/mii_timestamper.h>
+
+static LIST_HEAD(mii_timestamping_devices);
+static DEFINE_MUTEX(tstamping_devices_lock);
+
+struct mii_timestamping_desc {
+ struct list_head list;
+ struct mii_timestamping_ctrl *ctrl;
+ struct device *device;
+};
+
+/**
+ * register_mii_tstamp_controller() - registers an MII time stamping device.
+ *
+ * @device: The device to be registered.
+ * @ctrl: Pointer to device's control interface.
+ *
+ * Returns zero on success or non-zero on failure.
+ */
+int register_mii_tstamp_controller(struct device *device,
+ struct mii_timestamping_ctrl *ctrl)
+{
+ struct mii_timestamping_desc *desc;
+
+ desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&desc->list);
+ desc->ctrl = ctrl;
+ desc->device = device;
+
+ mutex_lock(&tstamping_devices_lock);
+ list_add_tail(&mii_timestamping_devices, &desc->list);
+ mutex_unlock(&tstamping_devices_lock);
+
+ return 0;
+}
+
+/**
+ * unregister_mii_tstamp_controller() - unregisters an MII time stamping device.
+ *
+ * @device: A device previously passed to register_mii_tstamp_controller().
+ */
+void unregister_mii_tstamp_controller(struct device *device)
+{
+ struct mii_timestamping_desc *desc;
+ struct list_head *this, *next;
+
+ mutex_lock(&tstamping_devices_lock);
+ list_for_each_safe(this, next, &mii_timestamping_devices) {
+ desc = list_entry(this, struct mii_timestamping_desc, list);
+ if (desc->device == device) {
+ list_del_init(&desc->list);
+ kfree(desc);
+ break;
+ }
+ }
+ mutex_unlock(&tstamping_devices_lock);
+}
+
+/**
+ * register_mii_timestamper - Enables a given port of an MII time stamper.
+ *
+ * @node: The device tree node of the MII time stamp controller.
+ * @port: The index of the port to be enabled.
+ *
+ * Returns a valid interface on success or ERR_PTR otherwise.
+ */
+struct mii_timestamper *register_mii_timestamper(struct device_node *node,
+ unsigned int port)
+{
+ struct mii_timestamper *mii_ts = NULL;
+ struct mii_timestamping_desc *desc;
+ struct list_head *this;
+
+ mutex_lock(&tstamping_devices_lock);
+ list_for_each(this, &mii_timestamping_devices) {
+ desc = list_entry(this, struct mii_timestamping_desc, list);
+ if (desc->device->of_node == node) {
+ mii_ts = desc->ctrl->probe_channel(desc->device, port);
+ if (!IS_ERR(mii_ts)) {
+ mii_ts->device = desc->device;
+ get_device(desc->device);
+ }
+ break;
+ }
+ }
+ mutex_unlock(&tstamping_devices_lock);
+
+ return mii_ts ? mii_ts : ERR_PTR(-EPROBE_DEFER);
+}
+
+/**
+ * unregister_mii_timestamper - Disables a given MII time stamper.
+ *
+ * @mii_ts: An interface obtained via register_mii_timestamper().
+ *
+ */
+void unregister_mii_timestamper(struct mii_timestamper *mii_ts)
+{
+ struct mii_timestamping_desc *desc;
+ struct list_head *this;
+
+ mutex_lock(&tstamping_devices_lock);
+ list_for_each(this, &mii_timestamping_devices) {
+ desc = list_entry(this, struct mii_timestamping_desc, list);
+ if (desc->device == mii_ts->device) {
+ desc->ctrl->release_channel(desc->device, mii_ts);
+ put_device(desc->device);
+ break;
+ }
+ }
+ mutex_unlock(&tstamping_devices_lock);
+}
diff --git a/include/linux/mii_timestamper.h b/include/linux/mii_timestamper.h
index 8586eed2f3b9..74524f494cb2 100644
--- a/include/linux/mii_timestamper.h
+++ b/include/linux/mii_timestamper.h
@@ -8,6 +8,7 @@
#include <linux/device.h>
#include <linux/ethtool.h>
+#include <linux/phy.h>
#include <linux/skbuff.h>
/**
@@ -31,10 +32,15 @@
* the phy_device mutex.
*
* @ts_info: Handles ethtool queries for hardware time stamping.
+ * @device: Remembers the device to which the instance belongs.
*
* Drivers for PHY time stamping devices should embed their
* mii_timestamper within a private structure, obtaining a reference
* to it using container_of().
+ *
+ * Drivers for non-PHY time stamping devices should return a pointer
+ * to a mii_timestamper from the probe_channel() callback of their
+ * mii_timestamping_ctrl interface.
*/
struct mii_timestamper {
bool (*rxtstamp)(struct mii_timestamper *mii_ts,
@@ -51,6 +57,64 @@ struct mii_timestamper {
int (*ts_info)(struct mii_timestamper *mii_ts,
struct ethtool_ts_info *ts_info);
+
+ struct device *device;
+};
+
+/**
+ * struct mii_timestamping_ctrl - MII time stamping controller interface.
+ *
+ * @probe_channel: Callback into the controller driver announcing the
+ * presence of the 'port' channel. The 'device' field
+ * had been passed to register_mii_tstamp_controller().
+ * The driver must return either a pointer to a valid
+ * MII timestamper instance or PTR_ERR.
+ *
+ * @release_channel: Releases an instance obtained via .probe_channel.
+ */
+struct mii_timestamping_ctrl {
+ struct mii_timestamper *(*probe_channel)(struct device *device,
+ unsigned int port);
+ void (*release_channel)(struct device *device,
+ struct mii_timestamper *mii_ts);
};
+#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
+
+int register_mii_tstamp_controller(struct device *device,
+ struct mii_timestamping_ctrl *ctrl);
+
+void unregister_mii_tstamp_controller(struct device *device);
+
+struct mii_timestamper *register_mii_timestamper(struct device_node *node,
+ unsigned int port);
+
+void unregister_mii_timestamper(struct mii_timestamper *mii_ts);
+
+#else
+
+static inline
+int register_mii_tstamp_controller(struct device *device,
+ struct mii_timestamping_ctrl *ctrl)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void unregister_mii_tstamp_controller(struct device *device)
+{
+}
+
+static inline
+struct mii_timestamper *register_mii_timestamper(struct device_node *node,
+ unsigned int port)
+{
+ return NULL;
+}
+
+static inline void unregister_mii_timestamper(struct mii_timestamper *mii_ts)
+{
+}
+
+#endif
+
#endif
diff --git a/net/Kconfig b/net/Kconfig
index d122f53c6fa2..203e6f5dafa7 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -110,9 +110,10 @@ config NETWORK_PHY_TIMESTAMPING
bool "Timestamping in PHY devices"
select NET_PTP_CLASSIFY
help
- This allows timestamping of network packets by PHYs with
- hardware timestamping capabilities. This option adds some
- overhead in the transmit and receive paths.
+ This allows timestamping of network packets by PHYs (or
+ other MII bus snooping devices) with hardware timestamping
+ capabilities. This option adds some overhead in the transmit
+ and receive paths.
If you are unsure how to answer this question, answer N.
--
2.11.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V5 net-next 4/6] dt-bindings: ptp: Introduce MII time stamping devices.
2019-05-31 5:56 [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping Richard Cochran
` (2 preceding siblings ...)
2019-05-31 5:56 ` [PATCH V5 net-next 3/6] net: Add a layer for non-PHY MII time stamping drivers Richard Cochran
@ 2019-05-31 5:56 ` Richard Cochran
2019-07-08 21:38 ` Rob Herring
2019-05-31 5:56 ` [PATCH V5 net-next 5/6] net: mdio: of: Register discovered MII time stampers Richard Cochran
` (2 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Richard Cochran @ 2019-05-31 5:56 UTC (permalink / raw)
To: netdev
Cc: David Miller, devicetree, Andrew Lunn, Florian Fainelli,
Jacob Keller, Mark Rutland, Miroslav Lichvar, Rob Herring,
Willem de Bruijn
This patch add a new binding that allows non-PHY MII time stamping
devices to find their buses. The new documentation covers both the
generic binding and one upcoming user.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
Documentation/devicetree/bindings/ptp/ptp-ines.txt | 35 ++++++++++++++++++
.../devicetree/bindings/ptp/timestamper.txt | 41 ++++++++++++++++++++++
2 files changed, 76 insertions(+)
create mode 100644 Documentation/devicetree/bindings/ptp/ptp-ines.txt
create mode 100644 Documentation/devicetree/bindings/ptp/timestamper.txt
diff --git a/Documentation/devicetree/bindings/ptp/ptp-ines.txt b/Documentation/devicetree/bindings/ptp/ptp-ines.txt
new file mode 100644
index 000000000000..4dee9eb89455
--- /dev/null
+++ b/Documentation/devicetree/bindings/ptp/ptp-ines.txt
@@ -0,0 +1,35 @@
+ZHAW InES PTP time stamping IP core
+
+The IP core needs two different kinds of nodes. The control node
+lives somewhere in the memory map and specifies the address of the
+control registers. There can be up to three port handles placed as
+attributes of PHY nodes. These associate a particular MII bus with a
+port index within the IP core.
+
+Required properties of the control node:
+
+- compatible: "ines,ptp-ctrl"
+- reg: physical address and size of the register bank
+
+Required format of the port handle within the PHY node:
+
+- timestamper: provides control node reference and
+ the port channel within the IP core
+
+Example:
+
+ tstamper: timestamper@60000000 {
+ compatible = "ines,ptp-ctrl";
+ reg = <0x60000000 0x80>;
+ };
+
+ ethernet@80000000 {
+ ...
+ mdio {
+ ...
+ phy@3 {
+ ...
+ timestamper = <&tstamper 0>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/ptp/timestamper.txt b/Documentation/devicetree/bindings/ptp/timestamper.txt
new file mode 100644
index 000000000000..88ea0bc7d662
--- /dev/null
+++ b/Documentation/devicetree/bindings/ptp/timestamper.txt
@@ -0,0 +1,41 @@
+Time stamps from MII bus snooping devices
+
+This binding supports non-PHY devices that snoop the MII bus and
+provide time stamps. In contrast to PHY time stamping drivers (which
+can simply attach their interface directly to the PHY instance), stand
+alone MII time stamping drivers use this binding to specify the
+connection between the snooping device and a given network interface.
+
+Non-PHY MII time stamping drivers typically talk to the control
+interface over another bus like I2C, SPI, UART, or via a memory mapped
+peripheral. This controller device is associated with one or more
+time stamping channels, each of which snoops on a MII bus.
+
+The "timestamper" property lives in a phy node and links a time
+stamping channel from the controller device to that phy's MII bus.
+
+Example:
+
+ tstamper: timestamper@10000000 {
+ compatible = "bigcorp,ts-ctrl";
+ };
+
+ ethernet@20000000 {
+ mdio {
+ phy@1 {
+ timestamper = <&tstamper 0>;
+ };
+ };
+ };
+
+ ethernet@30000000 {
+ mdio {
+ phy@2 {
+ timestamper = <&tstamper 1>;
+ };
+ };
+ };
+
+In this example, time stamps from the MII bus attached to phy@1 will
+appear on time stamp channel 0 (zero), and those from phy@2 appear on
+channel 1.
--
2.11.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V5 net-next 5/6] net: mdio: of: Register discovered MII time stampers.
2019-05-31 5:56 [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping Richard Cochran
` (3 preceding siblings ...)
2019-05-31 5:56 ` [PATCH V5 net-next 4/6] dt-bindings: ptp: Introduce MII time stamping devices Richard Cochran
@ 2019-05-31 5:56 ` Richard Cochran
2019-05-31 17:24 ` kbuild test robot
2019-05-31 17:24 ` [RFC PATCH] net: mdio: of: of_find_mii_timestamper() can be static kbuild test robot
2019-05-31 5:56 ` [PATCH V5 net-next 6/6] ptp: Add a driver for InES time stamping IP core Richard Cochran
2019-05-31 21:54 ` [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping David Miller
6 siblings, 2 replies; 16+ messages in thread
From: Richard Cochran @ 2019-05-31 5:56 UTC (permalink / raw)
To: netdev
Cc: David Miller, devicetree, Andrew Lunn, Florian Fainelli,
Jacob Keller, Mark Rutland, Miroslav Lichvar, Rob Herring,
Willem de Bruijn
When parsing a PHY node, register its time stamper, if any, and attach
the instance to the PHY device.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/phy/phy_device.c | 3 +++
drivers/of/of_mdio.c | 30 +++++++++++++++++++++++++++++-
2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 055087654b2c..aa06ef33df79 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -877,6 +877,9 @@ EXPORT_SYMBOL(phy_device_register);
*/
void phy_device_remove(struct phy_device *phydev)
{
+ if (phydev->mii_ts)
+ unregister_mii_timestamper(phydev->mii_ts);
+
device_del(&phydev->mdio.dev);
/* Assert the reset signal */
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index fcf25e32b1ed..98f2516ec3ba 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -43,14 +43,37 @@ static int of_get_phy_id(struct device_node *device, u32 *phy_id)
return -EINVAL;
}
+struct mii_timestamper *of_find_mii_timestamper(struct device_node *node)
+{
+ struct of_phandle_args arg;
+ int err;
+
+ err = of_parse_phandle_with_fixed_args(node, "timestamper", 1, 0, &arg);
+
+ if (err == -ENOENT)
+ return NULL;
+ else if (err)
+ return ERR_PTR(err);
+
+ if (arg.args_count != 1)
+ return ERR_PTR(-EINVAL);
+
+ return register_mii_timestamper(arg.np, arg.args[0]);
+}
+
static int of_mdiobus_register_phy(struct mii_bus *mdio,
struct device_node *child, u32 addr)
{
+ struct mii_timestamper *mii_ts;
struct phy_device *phy;
bool is_c45;
int rc;
u32 phy_id;
+ mii_ts = of_find_mii_timestamper(child);
+ if (IS_ERR(mii_ts))
+ return PTR_ERR(mii_ts);
+
is_c45 = of_device_is_compatible(child,
"ethernet-phy-ieee802.3-c45");
@@ -58,11 +81,14 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio,
phy = phy_device_create(mdio, addr, phy_id, 0, NULL);
else
phy = get_phy_device(mdio, addr, is_c45);
- if (IS_ERR(phy))
+ if (IS_ERR(phy)) {
+ unregister_mii_timestamper(mii_ts);
return PTR_ERR(phy);
+ }
rc = of_irq_get(child, 0);
if (rc == -EPROBE_DEFER) {
+ unregister_mii_timestamper(mii_ts);
phy_device_free(phy);
return rc;
}
@@ -91,10 +117,12 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio,
* register it */
rc = phy_device_register(phy);
if (rc) {
+ unregister_mii_timestamper(mii_ts);
phy_device_free(phy);
of_node_put(child);
return rc;
}
+ phy->mii_ts = mii_ts;
dev_dbg(&mdio->dev, "registered phy %pOFn at address %i\n",
child, addr);
--
2.11.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V5 net-next 6/6] ptp: Add a driver for InES time stamping IP core.
2019-05-31 5:56 [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping Richard Cochran
` (4 preceding siblings ...)
2019-05-31 5:56 ` [PATCH V5 net-next 5/6] net: mdio: of: Register discovered MII time stampers Richard Cochran
@ 2019-05-31 5:56 ` Richard Cochran
2019-05-31 20:22 ` kbuild test robot
2019-05-31 20:22 ` [RFC PATCH] ptp: ines_ptp_probe_channel() can be static kbuild test robot
2019-05-31 21:54 ` [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping David Miller
6 siblings, 2 replies; 16+ messages in thread
From: Richard Cochran @ 2019-05-31 5:56 UTC (permalink / raw)
To: netdev
Cc: David Miller, devicetree, Andrew Lunn, Florian Fainelli,
Jacob Keller, Mark Rutland, Miroslav Lichvar, Rob Herring,
Willem de Bruijn
The InES at the ZHAW offers a PTP time stamping IP core. The FPGA
logic recognizes and time stamps PTP frames on the MII bus. This
patch adds a driver for the core along with a device tree binding to
allow hooking the driver to MII buses.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/ptp/Kconfig | 10 +
drivers/ptp/Makefile | 1 +
drivers/ptp/ptp_ines.c | 859 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 870 insertions(+)
create mode 100644 drivers/ptp/ptp_ines.c
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 9b8fee5178e8..9824ea0467c8 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -89,6 +89,16 @@ config DP83640_PHY
In order for this to work, your MAC driver must also
implement the skb_tx_timestamp() function.
+config PTP_1588_CLOCK_INES
+ tristate "ZHAW InES PTP time stamping IP core"
+ depends on NETWORK_PHY_TIMESTAMPING
+ depends on PHYLIB
+ depends on PTP_1588_CLOCK
+ help
+ This driver adds support for using the ZHAW InES 1588 IP
+ core. This clock is only useful if the MII bus of your MAC
+ is wired up to the core.
+
config PTP_1588_CLOCK_PCH
tristate "Intel PCH EG20T as PTP clock"
depends on X86_32 || COMPILE_TEST
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
index 677d1d178a3e..3cdd33f93d35 100644
--- a/drivers/ptp/Makefile
+++ b/drivers/ptp/Makefile
@@ -6,6 +6,7 @@
ptp-y := ptp_clock.o ptp_chardev.o ptp_sysfs.o
obj-$(CONFIG_PTP_1588_CLOCK) += ptp.o
obj-$(CONFIG_PTP_1588_CLOCK_DTE) += ptp_dte.o
+obj-$(CONFIG_PTP_1588_CLOCK_INES) += ptp_ines.o
obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o
obj-$(CONFIG_PTP_1588_CLOCK_PCH) += ptp_pch.o
obj-$(CONFIG_PTP_1588_CLOCK_KVM) += ptp_kvm.o
diff --git a/drivers/ptp/ptp_ines.c b/drivers/ptp/ptp_ines.c
new file mode 100644
index 000000000000..59cb3f16d423
--- /dev/null
+++ b/drivers/ptp/ptp_ines.c
@@ -0,0 +1,859 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 MOSER-BAER AG
+//
+
+#define pr_fmt(fmt) "InES_PTP: " fmt
+
+#include <linux/ethtool.h>
+#include <linux/export.h>
+#include <linux/if_vlan.h>
+#include <linux/mii_timestamper.h>
+#include <linux/module.h>
+#include <linux/net_tstamp.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/ptp_classify.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/stddef.h>
+
+MODULE_DESCRIPTION("Driver for the ZHAW InES PTP time stamping IP core");
+MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
+
+/* GLOBAL register */
+#define MCAST_MAC_SELECT_SHIFT 2
+#define MCAST_MAC_SELECT_MASK 0x3
+#define IO_RESET BIT(1)
+#define PTP_RESET BIT(0)
+
+/* VERSION register */
+#define IF_MAJOR_VER_SHIFT 12
+#define IF_MAJOR_VER_MASK 0xf
+#define IF_MINOR_VER_SHIFT 8
+#define IF_MINOR_VER_MASK 0xf
+#define FPGA_MAJOR_VER_SHIFT 4
+#define FPGA_MAJOR_VER_MASK 0xf
+#define FPGA_MINOR_VER_SHIFT 0
+#define FPGA_MINOR_VER_MASK 0xf
+
+/* INT_STAT register */
+#define RX_INTR_STATUS_3 BIT(5)
+#define RX_INTR_STATUS_2 BIT(4)
+#define RX_INTR_STATUS_1 BIT(3)
+#define TX_INTR_STATUS_3 BIT(2)
+#define TX_INTR_STATUS_2 BIT(1)
+#define TX_INTR_STATUS_1 BIT(0)
+
+/* INT_MSK register */
+#define RX_INTR_MASK_3 BIT(5)
+#define RX_INTR_MASK_2 BIT(4)
+#define RX_INTR_MASK_1 BIT(3)
+#define TX_INTR_MASK_3 BIT(2)
+#define TX_INTR_MASK_2 BIT(1)
+#define TX_INTR_MASK_1 BIT(0)
+
+/* BUF_STAT register */
+#define RX_FIFO_NE_3 BIT(5)
+#define RX_FIFO_NE_2 BIT(4)
+#define RX_FIFO_NE_1 BIT(3)
+#define TX_FIFO_NE_3 BIT(2)
+#define TX_FIFO_NE_2 BIT(1)
+#define TX_FIFO_NE_1 BIT(0)
+
+/* PORT_CONF register */
+#define CM_ONE_STEP BIT(6)
+#define PHY_SPEED_SHIFT 4
+#define PHY_SPEED_MASK 0x3
+#define P2P_DELAY_WR_POS_SHIFT 2
+#define P2P_DELAY_WR_POS_MASK 0x3
+#define PTP_MODE_SHIFT 0
+#define PTP_MODE_MASK 0x3
+
+/* TS_STAT_TX register */
+#define TS_ENABLE BIT(15)
+#define DATA_READ_POS_SHIFT 8
+#define DATA_READ_POS_MASK 0x1f
+#define DISCARDED_EVENTS_SHIFT 4
+#define DISCARDED_EVENTS_MASK 0xf
+
+#define INES_N_PORTS 3
+#define INES_REGISTER_SIZE 0x80
+#define INES_PORT_OFFSET 0x20
+#define INES_PORT_SIZE 0x20
+#define INES_FIFO_DEPTH 90
+#define INES_MAX_EVENTS 100
+
+#define BC_PTP_V1 0
+#define BC_PTP_V2 1
+#define TC_E2E_PTP_V2 2
+#define TC_P2P_PTP_V2 3
+
+#define OFF_PTP_CLOCK_ID 20
+#define OFF_PTP_PORT_NUM 28
+
+#define PHY_SPEED_10 0
+#define PHY_SPEED_100 1
+#define PHY_SPEED_1000 2
+
+#define PORT_CONF \
+ ((PHY_SPEED_1000 << PHY_SPEED_SHIFT) | (BC_PTP_V2 << PTP_MODE_SHIFT))
+
+#define ines_read32(s, r) __raw_readl(&s->regs->r)
+#define ines_write32(s, v, r) __raw_writel(v, &s->regs->r)
+
+#define MESSAGE_TYPE_SYNC 1
+#define MESSAGE_TYPE_P_DELAY_REQ 2
+#define MESSAGE_TYPE_P_DELAY_RESP 3
+#define MESSAGE_TYPE_DELAY_REQ 4
+
+#define SYNC 0x0
+#define DELAY_REQ 0x1
+#define PDELAY_REQ 0x2
+#define PDELAY_RESP 0x3
+
+static LIST_HEAD(ines_clocks);
+static DEFINE_MUTEX(ines_clocks_lock);
+
+struct ines_global_registers {
+ u32 id;
+ u32 test;
+ u32 global;
+ u32 version;
+ u32 test2;
+ u32 int_stat;
+ u32 int_msk;
+ u32 buf_stat;
+};
+
+struct ines_port_registers {
+ u32 port_conf;
+ u32 p_delay;
+ u32 ts_stat_tx;
+ u32 ts_stat_rx;
+ u32 ts_tx;
+ u32 ts_rx;
+};
+
+struct ines_timestamp {
+ struct list_head list;
+ unsigned long tmo;
+ u16 tag;
+ u64 sec;
+ u64 nsec;
+ u64 clkid;
+ u16 portnum;
+ u16 seqid;
+};
+
+struct ines_port {
+ struct ines_port_registers *regs;
+ struct mii_timestamper mii_ts;
+ struct ines_clock *clock;
+ bool rxts_enabled;
+ bool txts_enabled;
+ unsigned int index;
+ struct delayed_work ts_work;
+ /* lock protects event list and tx_skb */
+ spinlock_t lock;
+ struct sk_buff *tx_skb;
+ struct list_head events;
+ struct list_head pool;
+ struct ines_timestamp pool_data[INES_MAX_EVENTS];
+};
+
+struct ines_clock {
+ struct ines_port port[INES_N_PORTS];
+ struct ines_global_registers *regs;
+ void __iomem *base;
+ struct device_node *node;
+ struct list_head list;
+};
+
+static bool ines_match(struct sk_buff *skb, unsigned int ptp_class,
+ struct ines_timestamp *ts);
+static int ines_rxfifo_read(struct ines_port *port);
+static u64 ines_rxts64(struct ines_port *port, unsigned int words);
+static bool ines_timestamp_expired(struct ines_timestamp *ts);
+static u64 ines_txts64(struct ines_port *port, unsigned int words);
+static void ines_txtstamp_work(struct work_struct *work);
+static bool is_sync_pdelay_resp(struct sk_buff *skb, int type);
+static u8 tag_to_msgtype(u8 tag);
+
+static void ines_clock_cleanup(struct ines_clock *clock)
+{
+ struct ines_port *port;
+ int i;
+
+ for (i = 0; i < INES_N_PORTS; i++) {
+ port = &clock->port[i];
+ cancel_delayed_work_sync(&port->ts_work);
+ }
+}
+
+static int ines_clock_init(struct ines_clock *clock, struct device_node *node,
+ void __iomem *addr)
+{
+ unsigned long port_addr;
+ struct ines_port *port;
+ int i, j;
+
+ INIT_LIST_HEAD(&clock->list);
+ clock->node = node;
+ clock->base = addr;
+ clock->regs = clock->base;
+
+ for (i = 0; i < INES_N_PORTS; i++) {
+ port = &clock->port[i];
+ port_addr = (unsigned long) clock->base +
+ INES_PORT_OFFSET + i * INES_PORT_SIZE;
+ port->regs = (struct ines_port_registers *) port_addr;
+ port->clock = clock;
+ port->index = i;
+ INIT_DELAYED_WORK(&port->ts_work, ines_txtstamp_work);
+ spin_lock_init(&port->lock);
+ INIT_LIST_HEAD(&port->events);
+ INIT_LIST_HEAD(&port->pool);
+ for (j = 0; j < INES_MAX_EVENTS; j++)
+ list_add(&port->pool_data[j].list, &port->pool);
+ }
+
+ ines_write32(clock, 0xBEEF, test);
+ ines_write32(clock, 0xBEEF, test2);
+
+ pr_debug("ID 0x%x\n", ines_read32(clock, id));
+ pr_debug("TEST 0x%x\n", ines_read32(clock, test));
+ pr_debug("VERSION 0x%x\n", ines_read32(clock, version));
+ pr_debug("TEST2 0x%x\n", ines_read32(clock, test2));
+
+ for (i = 0; i < INES_N_PORTS; i++) {
+ port = &clock->port[i];
+ ines_write32(port, PORT_CONF, port_conf);
+ }
+
+ return 0;
+}
+
+static void ines_dump_ts(char *label, struct ines_timestamp *ts)
+{
+#ifdef DEBUG
+ pr_err("%s timestamp, tag=0x%04hx t=%llu.%9llu c=0x%llx p=%hu s=%hu\n",
+ label, ts->tag, ts->sec, ts->nsec,
+ ts->clkid, ts->portnum, ts->seqid);
+#endif
+}
+
+static struct ines_port *ines_find_port(struct device_node *node, u32 index)
+{
+ struct ines_port *port = NULL;
+ struct ines_clock *clock;
+ struct list_head *this;
+
+ mutex_lock(&ines_clocks_lock);
+ list_for_each(this, &ines_clocks) {
+ clock = list_entry(this, struct ines_clock, list);
+ if (clock->node == node) {
+ port = &clock->port[index];
+ break;
+ }
+ }
+ mutex_unlock(&ines_clocks_lock);
+ return port;
+}
+
+static u64 ines_find_rxts(struct ines_port *port, struct sk_buff *skb, int type)
+{
+ struct list_head *this, *next;
+ struct ines_timestamp *ts;
+ unsigned long flags;
+ u64 ns = 0;
+
+ if (type == PTP_CLASS_NONE)
+ return 0;
+
+ spin_lock_irqsave(&port->lock, flags);
+ ines_rxfifo_read(port);
+ list_for_each_safe(this, next, &port->events) {
+ ts = list_entry(this, struct ines_timestamp, list);
+ if (ines_timestamp_expired(ts)) {
+ list_del_init(&ts->list);
+ list_add(&ts->list, &port->pool);
+ continue;
+ }
+ if (ines_match(skb, type, ts)) {
+ ns = ts->sec * 1000000000ULL + ts->nsec;
+ list_del_init(&ts->list);
+ list_add(&ts->list, &port->pool);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return ns;
+}
+
+static u64 ines_find_txts(struct ines_port *port, struct sk_buff *skb)
+{
+ unsigned int class = ptp_classify_raw(skb), i;
+ u32 data_rd_pos, buf_stat, mask, ts_stat_tx;
+ struct ines_timestamp ts;
+ unsigned long flags;
+ u64 ns = 0;
+
+ mask = TX_FIFO_NE_1 << port->index;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ for (i = 0; i < INES_FIFO_DEPTH; i++) {
+
+ buf_stat = ines_read32(port->clock, buf_stat);
+ if (!(buf_stat & mask)) {
+ pr_debug("Tx timestamp FIFO unexpectedly empty\n");
+ break;
+ }
+ ts_stat_tx = ines_read32(port, ts_stat_tx);
+ data_rd_pos = (ts_stat_tx >> DATA_READ_POS_SHIFT) &
+ DATA_READ_POS_MASK;
+ if (data_rd_pos) {
+ pr_err("unexpected Tx read pos %u\n", data_rd_pos);
+ break;
+ }
+
+ ts.tag = ines_read32(port, ts_tx);
+ ts.sec = ines_txts64(port, 3);
+ ts.nsec = ines_txts64(port, 2);
+ ts.clkid = ines_txts64(port, 4);
+ ts.portnum = ines_read32(port, ts_tx);
+ ts.seqid = ines_read32(port, ts_tx);
+
+ ines_dump_ts("Tx", &ts);
+
+ if (ines_match(skb, class, &ts)) {
+ ns = ts.sec * 1000000000ULL + ts.nsec;
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&port->lock, flags);
+ return ns;
+}
+
+static int ines_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
+{
+ struct ines_port *port = container_of(mii_ts, struct ines_port, mii_ts);
+ u32 cm_one_step = 0, port_conf, ts_stat_rx, ts_stat_tx;
+ struct hwtstamp_config cfg;
+ unsigned long flags;
+
+ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (cfg.flags)
+ return -EINVAL;
+
+ switch (cfg.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ ts_stat_tx = 0;
+ break;
+ case HWTSTAMP_TX_ON:
+ ts_stat_tx = TS_ENABLE;
+ break;
+ case HWTSTAMP_TX_ONESTEP_P2P:
+ ts_stat_tx = TS_ENABLE;
+ cm_one_step = CM_ONE_STEP;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (cfg.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ ts_stat_rx = 0;
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ return -ERANGE;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ ts_stat_rx = TS_ENABLE;
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ port_conf = ines_read32(port, port_conf);
+ port_conf &= ~CM_ONE_STEP;
+ port_conf |= cm_one_step;
+
+ ines_write32(port, port_conf, port_conf);
+ ines_write32(port, ts_stat_rx, ts_stat_rx);
+ ines_write32(port, ts_stat_tx, ts_stat_tx);
+
+ port->rxts_enabled = ts_stat_rx == TS_ENABLE ? true : false;
+ port->txts_enabled = ts_stat_tx == TS_ENABLE ? true : false;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+static void ines_link_state(struct mii_timestamper *mii_ts,
+ struct phy_device *phydev)
+{
+ struct ines_port *port = container_of(mii_ts, struct ines_port, mii_ts);
+ u32 port_conf, speed_conf;
+ unsigned long flags;
+
+ switch (phydev->speed) {
+ case SPEED_10:
+ speed_conf = PHY_SPEED_10 << PHY_SPEED_SHIFT;
+ break;
+ case SPEED_100:
+ speed_conf = PHY_SPEED_100 << PHY_SPEED_SHIFT;
+ break;
+ case SPEED_1000:
+ speed_conf = PHY_SPEED_1000 << PHY_SPEED_SHIFT;
+ break;
+ default:
+ pr_err("bad speed: %d\n", phydev->speed);
+ return;
+ }
+ spin_lock_irqsave(&port->lock, flags);
+
+ port_conf = ines_read32(port, port_conf);
+ port_conf &= ~(0x3 << PHY_SPEED_SHIFT);
+ port_conf |= speed_conf;
+
+ ines_write32(port, port_conf, port_conf);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static bool ines_match(struct sk_buff *skb, unsigned int ptp_class,
+ struct ines_timestamp *ts)
+{
+ u8 *msgtype, *data = skb_mac_header(skb);
+ unsigned int offset = 0;
+ u16 *portn, *seqid;
+ u64 *clkid;
+
+ if (unlikely(ptp_class & PTP_CLASS_V1))
+ return false;
+
+ if (ptp_class & PTP_CLASS_VLAN)
+ offset += VLAN_HLEN;
+
+ switch (ptp_class & PTP_CLASS_PMASK) {
+ case PTP_CLASS_IPV4:
+ offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
+ break;
+ case PTP_CLASS_IPV6:
+ offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
+ break;
+ case PTP_CLASS_L2:
+ offset += ETH_HLEN;
+ break;
+ default:
+ return false;
+ }
+
+ if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
+ return false;
+
+ msgtype = data + offset;
+ clkid = (u64 *)(data + offset + OFF_PTP_CLOCK_ID);
+ portn = (u16 *)(data + offset + OFF_PTP_PORT_NUM);
+ seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+
+ if (tag_to_msgtype(ts->tag & 0x7) != (*msgtype & 0xf)) {
+ pr_debug("msgtype mismatch ts %hhu != skb %hhu\n",
+ tag_to_msgtype(ts->tag & 0x7), *msgtype & 0xf);
+ return false;
+ }
+ if (cpu_to_be64(ts->clkid) != *clkid) {
+ pr_debug("clkid mismatch ts %llx != skb %llx\n",
+ cpu_to_be64(ts->clkid), *clkid);
+ return false;
+ }
+ if (ts->portnum != ntohs(*portn)) {
+ pr_debug("portn mismatch ts %hu != skb %hu\n",
+ ts->portnum, ntohs(*portn));
+ return false;
+ }
+ if (ts->seqid != ntohs(*seqid)) {
+ pr_debug("seqid mismatch ts %hu != skb %hu\n",
+ ts->seqid, ntohs(*seqid));
+ return false;
+ }
+
+ return true;
+}
+
+static bool ines_rxtstamp(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type)
+{
+ struct ines_port *port = container_of(mii_ts, struct ines_port, mii_ts);
+ struct skb_shared_hwtstamps *ssh;
+ u64 ns;
+
+ if (!port->rxts_enabled)
+ return false;
+
+ ns = ines_find_rxts(port, skb, type);
+ if (!ns)
+ return false;
+
+ ssh = skb_hwtstamps(skb);
+ ssh->hwtstamp = ns_to_ktime(ns);
+ netif_rx(skb);
+
+ return true;
+}
+
+static int ines_rxfifo_read(struct ines_port *port)
+{
+ u32 data_rd_pos, buf_stat, mask, ts_stat_rx;
+ struct ines_timestamp *ts;
+ unsigned int i;
+
+ mask = RX_FIFO_NE_1 << port->index;
+
+ for (i = 0; i < INES_FIFO_DEPTH; i++) {
+ if (list_empty(&port->pool)) {
+ pr_err("event pool is empty\n");
+ return -1;
+ }
+ buf_stat = ines_read32(port->clock, buf_stat);
+ if (!(buf_stat & mask))
+ break;
+
+ ts_stat_rx = ines_read32(port, ts_stat_rx);
+ data_rd_pos = (ts_stat_rx >> DATA_READ_POS_SHIFT) &
+ DATA_READ_POS_MASK;
+ if (data_rd_pos) {
+ pr_err("unexpected Rx read pos %u\n", data_rd_pos);
+ break;
+ }
+
+ ts = list_first_entry(&port->pool, struct ines_timestamp, list);
+ ts->tmo = jiffies + HZ;
+ ts->tag = ines_read32(port, ts_rx);
+ ts->sec = ines_rxts64(port, 3);
+ ts->nsec = ines_rxts64(port, 2);
+ ts->clkid = ines_rxts64(port, 4);
+ ts->portnum = ines_read32(port, ts_rx);
+ ts->seqid = ines_read32(port, ts_rx);
+
+ ines_dump_ts("Rx", ts);
+
+ list_del_init(&ts->list);
+ list_add_tail(&ts->list, &port->events);
+ }
+
+ return 0;
+}
+
+static u64 ines_rxts64(struct ines_port *port, unsigned int words)
+{
+ unsigned int i;
+ u64 result;
+ u16 word;
+
+ word = ines_read32(port, ts_rx);
+ result = word;
+ words--;
+ for (i = 0; i < words; i++) {
+ word = ines_read32(port, ts_rx);
+ result <<= 16;
+ result |= word;
+ }
+ return result;
+}
+
+static bool ines_timestamp_expired(struct ines_timestamp *ts)
+{
+ return time_after(jiffies, ts->tmo);
+}
+
+static int ines_ts_info(struct mii_timestamper *mii_ts,
+ struct ethtool_ts_info *info)
+{
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ info->phc_index = -1;
+
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON) |
+ (1 << HWTSTAMP_TX_ONESTEP_P2P);
+
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
+
+ return 0;
+}
+
+static u64 ines_txts64(struct ines_port *port, unsigned int words)
+{
+ unsigned int i;
+ u64 result;
+ u16 word;
+
+ word = ines_read32(port, ts_tx);
+ result = word;
+ words--;
+ for (i = 0; i < words; i++) {
+ word = ines_read32(port, ts_tx);
+ result <<= 16;
+ result |= word;
+ }
+ return result;
+}
+
+static bool ines_txts_onestep(struct ines_port *port, struct sk_buff *skb, int type)
+{
+ unsigned long flags;
+ u32 port_conf;
+
+ spin_lock_irqsave(&port->lock, flags);
+ port_conf = ines_read32(port, port_conf);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (port_conf & CM_ONE_STEP)
+ return is_sync_pdelay_resp(skb, type);
+
+ return false;
+}
+
+static void ines_txtstamp(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type)
+{
+ struct ines_port *port = container_of(mii_ts, struct ines_port, mii_ts);
+ struct sk_buff *old_skb = NULL;
+ unsigned long flags;
+
+ if (!port->txts_enabled || ines_txts_onestep(port, skb, type)) {
+ kfree_skb(skb);
+ return;
+ }
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ if (port->tx_skb)
+ old_skb = port->tx_skb;
+
+ port->tx_skb = skb;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (old_skb)
+ kfree_skb(old_skb);
+
+ schedule_delayed_work(&port->ts_work, 1);
+}
+
+static void ines_txtstamp_work(struct work_struct *work)
+{
+ struct ines_port *port =
+ container_of(work, struct ines_port, ts_work.work);
+ struct skb_shared_hwtstamps ssh;
+ struct sk_buff *skb;
+ unsigned long flags;
+ u64 ns;
+
+ spin_lock_irqsave(&port->lock, flags);
+ skb = port->tx_skb;
+ port->tx_skb = NULL;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ ns = ines_find_txts(port, skb);
+ if (!ns) {
+ kfree_skb(skb);
+ return;
+ }
+ ssh.hwtstamp = ns_to_ktime(ns);
+ skb_complete_tx_timestamp(skb, &ssh);
+}
+
+static bool is_sync_pdelay_resp(struct sk_buff *skb, int type)
+{
+ u8 *data = skb->data, *msgtype;
+ unsigned int offset = 0;
+
+ if (type & PTP_CLASS_VLAN)
+ offset += VLAN_HLEN;
+
+ switch (type & PTP_CLASS_PMASK) {
+ case PTP_CLASS_IPV4:
+ offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
+ break;
+ case PTP_CLASS_IPV6:
+ offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
+ break;
+ case PTP_CLASS_L2:
+ offset += ETH_HLEN;
+ break;
+ default:
+ return 0;
+ }
+
+ if (type & PTP_CLASS_V1)
+ offset += OFF_PTP_CONTROL;
+
+ if (skb->len < offset + 1)
+ return 0;
+
+ msgtype = data + offset;
+
+ switch ((*msgtype & 0xf)) {
+ case SYNC:
+ case PDELAY_RESP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static u8 tag_to_msgtype(u8 tag)
+{
+ switch (tag) {
+ case MESSAGE_TYPE_SYNC:
+ return SYNC;
+ case MESSAGE_TYPE_P_DELAY_REQ:
+ return PDELAY_REQ;
+ case MESSAGE_TYPE_P_DELAY_RESP:
+ return PDELAY_RESP;
+ case MESSAGE_TYPE_DELAY_REQ:
+ return DELAY_REQ;
+ }
+ return 0xf;
+}
+
+struct mii_timestamper *ines_ptp_probe_channel(struct device *device,
+ unsigned int index)
+{
+ struct device_node *node = device->of_node;
+ struct ines_port *port;
+
+ if (index > INES_N_PORTS - 1) {
+ dev_err(device, "bad port index %u\n", index);
+ return ERR_PTR(-EINVAL);
+ }
+ port = ines_find_port(node, index);
+ if (!port) {
+ dev_err(device, "missing port index %u\n", index);
+ return ERR_PTR(-ENODEV);
+ }
+ port->mii_ts.rxtstamp = ines_rxtstamp;
+ port->mii_ts.txtstamp = ines_txtstamp;
+ port->mii_ts.hwtstamp = ines_hwtstamp;
+ port->mii_ts.link_state = ines_link_state;
+ port->mii_ts.ts_info = ines_ts_info;
+
+ return &port->mii_ts;
+}
+
+static void ines_ptp_release_channel(struct device *device,
+ struct mii_timestamper *mii_ts)
+{
+}
+
+struct mii_timestamping_ctrl ines_ctrl = {
+ .probe_channel = ines_ptp_probe_channel,
+ .release_channel = ines_ptp_release_channel,
+};
+
+static int ines_ptp_ctrl_probe(struct platform_device *pld)
+{
+ struct ines_clock *clock;
+ struct resource *res;
+ void __iomem *addr;
+ int err = 0;
+
+ res = platform_get_resource(pld, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pld->dev, "missing memory resource\n");
+ return -EINVAL;
+ }
+ addr = devm_ioremap_resource(&pld->dev, res);
+ if (IS_ERR(addr)) {
+ err = PTR_ERR(addr);
+ goto out;
+ }
+ clock = kzalloc(sizeof(*clock), GFP_KERNEL);
+ if (!clock) {
+ err = -ENOMEM;
+ goto out;
+ }
+ if (ines_clock_init(clock, pld->dev.of_node, addr)) {
+ kfree(clock);
+ err = -ENOMEM;
+ goto out;
+ }
+ err = register_mii_tstamp_controller(&pld->dev, &ines_ctrl);
+ if (err) {
+ kfree(clock);
+ goto out;
+ }
+ mutex_lock(&ines_clocks_lock);
+ list_add_tail(&ines_clocks, &clock->list);
+ mutex_unlock(&ines_clocks_lock);
+
+ dev_set_drvdata(&pld->dev, clock);
+out:
+ return err;
+}
+
+static int ines_ptp_ctrl_remove(struct platform_device *pld)
+{
+ struct ines_clock *clock = dev_get_drvdata(&pld->dev);
+
+ unregister_mii_tstamp_controller(&pld->dev);
+ mutex_lock(&ines_clocks_lock);
+ list_del(&clock->list);
+ mutex_unlock(&ines_clocks_lock);
+ ines_clock_cleanup(clock);
+ kfree(clock);
+ return 0;
+}
+
+static const struct of_device_id ines_ptp_ctrl_of_match[] = {
+ { .compatible = "ines,ptp-ctrl" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, ines_ptp_ctrl_of_match);
+
+static struct platform_driver ines_ptp_ctrl_driver = {
+ .probe = ines_ptp_ctrl_probe,
+ .remove = ines_ptp_ctrl_remove,
+ .driver = {
+ .name = "ines_ptp_ctrl",
+ .of_match_table = of_match_ptr(ines_ptp_ctrl_of_match),
+ },
+};
+module_platform_driver(ines_ptp_ctrl_driver);
--
2.11.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH V5 net-next 5/6] net: mdio: of: Register discovered MII time stampers.
2019-05-31 5:56 ` [PATCH V5 net-next 5/6] net: mdio: of: Register discovered MII time stampers Richard Cochran
@ 2019-05-31 17:24 ` kbuild test robot
2019-05-31 17:24 ` [RFC PATCH] net: mdio: of: of_find_mii_timestamper() can be static kbuild test robot
1 sibling, 0 replies; 16+ messages in thread
From: kbuild test robot @ 2019-05-31 17:24 UTC (permalink / raw)
To: Richard Cochran
Cc: kbuild-all, netdev, David Miller, devicetree, Andrew Lunn,
Florian Fainelli, Jacob Keller, Mark Rutland, Miroslav Lichvar,
Rob Herring, Willem de Bruijn
Hi Richard,
I love your patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Richard-Cochran/Peer-to-Peer-One-Step-time-stamping/20190531-200348
reproduce:
# apt-get install sparse
# sparse version: v0.6.1-rc1-7-g2b96cd8-dirty
make ARCH=x86_64 allmodconfig
make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
>> drivers/of/of_mdio.c:46:24: sparse: sparse: symbol 'of_find_mii_timestamper' was not declared. Should it be static?
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC PATCH] net: mdio: of: of_find_mii_timestamper() can be static
2019-05-31 5:56 ` [PATCH V5 net-next 5/6] net: mdio: of: Register discovered MII time stampers Richard Cochran
2019-05-31 17:24 ` kbuild test robot
@ 2019-05-31 17:24 ` kbuild test robot
1 sibling, 0 replies; 16+ messages in thread
From: kbuild test robot @ 2019-05-31 17:24 UTC (permalink / raw)
To: Richard Cochran
Cc: kbuild-all, netdev, David Miller, devicetree, Andrew Lunn,
Florian Fainelli, Jacob Keller, Mark Rutland, Miroslav Lichvar,
Rob Herring, Willem de Bruijn
Fixes: 500a41a402da ("net: mdio: of: Register discovered MII time stampers.")
Signed-off-by: kbuild test robot <lkp@intel.com>
---
of_mdio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 255f47d..1251d73 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -43,7 +43,7 @@ static int of_get_phy_id(struct device_node *device, u32 *phy_id)
return -EINVAL;
}
-struct mii_timestamper *of_find_mii_timestamper(struct device_node *node)
+static struct mii_timestamper *of_find_mii_timestamper(struct device_node *node)
{
struct of_phandle_args arg;
int err;
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH V5 net-next 6/6] ptp: Add a driver for InES time stamping IP core.
2019-05-31 5:56 ` [PATCH V5 net-next 6/6] ptp: Add a driver for InES time stamping IP core Richard Cochran
@ 2019-05-31 20:22 ` kbuild test robot
2019-05-31 20:22 ` [RFC PATCH] ptp: ines_ptp_probe_channel() can be static kbuild test robot
1 sibling, 0 replies; 16+ messages in thread
From: kbuild test robot @ 2019-05-31 20:22 UTC (permalink / raw)
To: Richard Cochran
Cc: kbuild-all, netdev, David Miller, devicetree, Andrew Lunn,
Florian Fainelli, Jacob Keller, Mark Rutland, Miroslav Lichvar,
Rob Herring, Willem de Bruijn
Hi Richard,
I love your patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Richard-Cochran/Peer-to-Peer-One-Step-time-stamping/20190531-200348
reproduce:
# apt-get install sparse
# sparse version: v0.6.1-rc1-7-g2b96cd8-dirty
make ARCH=x86_64 allmodconfig
make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
>> drivers/ptp/ptp_ines.c:490:13: sparse: sparse: restricted __be64 degrades to integer
>> drivers/ptp/ptp_ines.c:495:28: sparse: sparse: cast to restricted __be16
>> drivers/ptp/ptp_ines.c:495:28: sparse: sparse: cast to restricted __be16
>> drivers/ptp/ptp_ines.c:495:28: sparse: sparse: cast to restricted __be16
>> drivers/ptp/ptp_ines.c:495:28: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:496:17: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:496:17: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:496:17: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:496:17: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:500:26: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:500:26: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:500:26: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:500:26: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:501:17: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:501:17: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:501:17: sparse: sparse: cast to restricted __be16
drivers/ptp/ptp_ines.c:501:17: sparse: sparse: cast to restricted __be16
>> drivers/ptp/ptp_ines.c:543:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
>> drivers/ptp/ptp_ines.c:543:28: sparse: expected void const volatile [noderef] <asn:2> *addr
>> drivers/ptp/ptp_ines.c:543:28: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:547:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:547:30: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:547:30: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:557:31: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:557:31: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:557:31: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:561:31: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:561:31: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:561:31: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:562:31: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:562:31: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:562:31: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:579:16: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:579:16: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:579:16: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:583:24: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:583:24: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:583:24: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:626:16: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:626:16: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:626:16: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:630:24: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:630:24: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:630:24: sparse: got unsigned int *
>> drivers/ptp/ptp_ines.c:208:21: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct ines_global_registers *regs @@ got ines_global_registers *regs @@
>> drivers/ptp/ptp_ines.c:208:21: sparse: expected struct ines_global_registers *regs
>> drivers/ptp/ptp_ines.c:208:21: sparse: got void [noderef] <asn:2> *base
>> drivers/ptp/ptp_ines.c:225:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
>> drivers/ptp/ptp_ines.c:225:9: sparse: expected void volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:225:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:226:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:226:9: sparse: expected void volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:226:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:228:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:228:9: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:228:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:229:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:229:9: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:229:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:230:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:230:9: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:230:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:231:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:231:9: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:231:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:235:17: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:235:17: sparse: expected void volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:235:17: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:313:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:313:28: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:313:28: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:318:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:318:30: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:318:30: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:326:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:326:30: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:326:30: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:330:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:330:30: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:330:30: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:331:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:331:30: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:331:30: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:401:21: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:401:21: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:401:21: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:405:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:405:9: sparse: expected void volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:405:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:406:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:406:9: sparse: expected void volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:406:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:407:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:407:9: sparse: expected void volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:407:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:440:21: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:440:21: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:440:21: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:444:9: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:444:9: sparse: expected void volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:444:9: sparse: got unsigned int *
drivers/ptp/ptp_ines.c:643:21: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const volatile [noderef] <asn:2> *addr @@ got ref] <asn:2> *addr @@
drivers/ptp/ptp_ines.c:643:21: sparse: expected void const volatile [noderef] <asn:2> *addr
drivers/ptp/ptp_ines.c:643:21: sparse: got unsigned int *
>> drivers/ptp/ptp_ines.c:756:24: sparse: sparse: symbol 'ines_ptp_probe_channel' was not declared. Should it be static?
>> drivers/ptp/ptp_ines.c:785:30: sparse: sparse: symbol 'ines_ctrl' was not declared. Should it be static?
Please review and possibly fold the followup patch.
vim +490 drivers/ptp/ptp_ines.c
416
417 static void ines_link_state(struct mii_timestamper *mii_ts,
418 struct phy_device *phydev)
419 {
420 struct ines_port *port = container_of(mii_ts, struct ines_port, mii_ts);
421 u32 port_conf, speed_conf;
422 unsigned long flags;
423
424 switch (phydev->speed) {
425 case SPEED_10:
426 speed_conf = PHY_SPEED_10 << PHY_SPEED_SHIFT;
427 break;
428 case SPEED_100:
429 speed_conf = PHY_SPEED_100 << PHY_SPEED_SHIFT;
430 break;
431 case SPEED_1000:
432 speed_conf = PHY_SPEED_1000 << PHY_SPEED_SHIFT;
433 break;
434 default:
435 pr_err("bad speed: %d\n", phydev->speed);
436 return;
437 }
438 spin_lock_irqsave(&port->lock, flags);
439
> 440 port_conf = ines_read32(port, port_conf);
441 port_conf &= ~(0x3 << PHY_SPEED_SHIFT);
442 port_conf |= speed_conf;
443
444 ines_write32(port, port_conf, port_conf);
445
446 spin_unlock_irqrestore(&port->lock, flags);
447 }
448
449 static bool ines_match(struct sk_buff *skb, unsigned int ptp_class,
450 struct ines_timestamp *ts)
451 {
452 u8 *msgtype, *data = skb_mac_header(skb);
453 unsigned int offset = 0;
454 u16 *portn, *seqid;
455 u64 *clkid;
456
457 if (unlikely(ptp_class & PTP_CLASS_V1))
458 return false;
459
460 if (ptp_class & PTP_CLASS_VLAN)
461 offset += VLAN_HLEN;
462
463 switch (ptp_class & PTP_CLASS_PMASK) {
464 case PTP_CLASS_IPV4:
465 offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
466 break;
467 case PTP_CLASS_IPV6:
468 offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
469 break;
470 case PTP_CLASS_L2:
471 offset += ETH_HLEN;
472 break;
473 default:
474 return false;
475 }
476
477 if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
478 return false;
479
480 msgtype = data + offset;
481 clkid = (u64 *)(data + offset + OFF_PTP_CLOCK_ID);
482 portn = (u16 *)(data + offset + OFF_PTP_PORT_NUM);
483 seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
484
485 if (tag_to_msgtype(ts->tag & 0x7) != (*msgtype & 0xf)) {
486 pr_debug("msgtype mismatch ts %hhu != skb %hhu\n",
487 tag_to_msgtype(ts->tag & 0x7), *msgtype & 0xf);
488 return false;
489 }
> 490 if (cpu_to_be64(ts->clkid) != *clkid) {
491 pr_debug("clkid mismatch ts %llx != skb %llx\n",
492 cpu_to_be64(ts->clkid), *clkid);
493 return false;
494 }
> 495 if (ts->portnum != ntohs(*portn)) {
> 496 pr_debug("portn mismatch ts %hu != skb %hu\n",
497 ts->portnum, ntohs(*portn));
498 return false;
499 }
> 500 if (ts->seqid != ntohs(*seqid)) {
501 pr_debug("seqid mismatch ts %hu != skb %hu\n",
502 ts->seqid, ntohs(*seqid));
503 return false;
504 }
505
506 return true;
507 }
508
509 static bool ines_rxtstamp(struct mii_timestamper *mii_ts,
510 struct sk_buff *skb, int type)
511 {
512 struct ines_port *port = container_of(mii_ts, struct ines_port, mii_ts);
513 struct skb_shared_hwtstamps *ssh;
514 u64 ns;
515
516 if (!port->rxts_enabled)
517 return false;
518
519 ns = ines_find_rxts(port, skb, type);
520 if (!ns)
521 return false;
522
523 ssh = skb_hwtstamps(skb);
524 ssh->hwtstamp = ns_to_ktime(ns);
525 netif_rx(skb);
526
527 return true;
528 }
529
530 static int ines_rxfifo_read(struct ines_port *port)
531 {
532 u32 data_rd_pos, buf_stat, mask, ts_stat_rx;
533 struct ines_timestamp *ts;
534 unsigned int i;
535
536 mask = RX_FIFO_NE_1 << port->index;
537
538 for (i = 0; i < INES_FIFO_DEPTH; i++) {
539 if (list_empty(&port->pool)) {
540 pr_err("event pool is empty\n");
541 return -1;
542 }
> 543 buf_stat = ines_read32(port->clock, buf_stat);
544 if (!(buf_stat & mask))
545 break;
546
547 ts_stat_rx = ines_read32(port, ts_stat_rx);
548 data_rd_pos = (ts_stat_rx >> DATA_READ_POS_SHIFT) &
549 DATA_READ_POS_MASK;
550 if (data_rd_pos) {
551 pr_err("unexpected Rx read pos %u\n", data_rd_pos);
552 break;
553 }
554
555 ts = list_first_entry(&port->pool, struct ines_timestamp, list);
556 ts->tmo = jiffies + HZ;
557 ts->tag = ines_read32(port, ts_rx);
558 ts->sec = ines_rxts64(port, 3);
559 ts->nsec = ines_rxts64(port, 2);
560 ts->clkid = ines_rxts64(port, 4);
561 ts->portnum = ines_read32(port, ts_rx);
562 ts->seqid = ines_read32(port, ts_rx);
563
564 ines_dump_ts("Rx", ts);
565
566 list_del_init(&ts->list);
567 list_add_tail(&ts->list, &port->events);
568 }
569
570 return 0;
571 }
572
573 static u64 ines_rxts64(struct ines_port *port, unsigned int words)
574 {
575 unsigned int i;
576 u64 result;
577 u16 word;
578
579 word = ines_read32(port, ts_rx);
580 result = word;
581 words--;
582 for (i = 0; i < words; i++) {
> 583 word = ines_read32(port, ts_rx);
584 result <<= 16;
585 result |= word;
586 }
587 return result;
588 }
589
590 static bool ines_timestamp_expired(struct ines_timestamp *ts)
591 {
592 return time_after(jiffies, ts->tmo);
593 }
594
595 static int ines_ts_info(struct mii_timestamper *mii_ts,
596 struct ethtool_ts_info *info)
597 {
598 info->so_timestamping =
599 SOF_TIMESTAMPING_TX_HARDWARE |
600 SOF_TIMESTAMPING_TX_SOFTWARE |
601 SOF_TIMESTAMPING_RX_HARDWARE |
602 SOF_TIMESTAMPING_RX_SOFTWARE |
603 SOF_TIMESTAMPING_SOFTWARE |
604 SOF_TIMESTAMPING_RAW_HARDWARE;
605
606 info->phc_index = -1;
607
608 info->tx_types =
609 (1 << HWTSTAMP_TX_OFF) |
610 (1 << HWTSTAMP_TX_ON) |
611 (1 << HWTSTAMP_TX_ONESTEP_P2P);
612
613 info->rx_filters =
614 (1 << HWTSTAMP_FILTER_NONE) |
615 (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
616
617 return 0;
618 }
619
620 static u64 ines_txts64(struct ines_port *port, unsigned int words)
621 {
622 unsigned int i;
623 u64 result;
624 u16 word;
625
> 626 word = ines_read32(port, ts_tx);
627 result = word;
628 words--;
629 for (i = 0; i < words; i++) {
630 word = ines_read32(port, ts_tx);
631 result <<= 16;
632 result |= word;
633 }
634 return result;
635 }
636
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC PATCH] ptp: ines_ptp_probe_channel() can be static
2019-05-31 5:56 ` [PATCH V5 net-next 6/6] ptp: Add a driver for InES time stamping IP core Richard Cochran
2019-05-31 20:22 ` kbuild test robot
@ 2019-05-31 20:22 ` kbuild test robot
1 sibling, 0 replies; 16+ messages in thread
From: kbuild test robot @ 2019-05-31 20:22 UTC (permalink / raw)
To: Richard Cochran
Cc: kbuild-all, netdev, David Miller, devicetree, Andrew Lunn,
Florian Fainelli, Jacob Keller, Mark Rutland, Miroslav Lichvar,
Rob Herring, Willem de Bruijn
Fixes: 49268f31cc1f ("ptp: Add a driver for InES time stamping IP core.")
Signed-off-by: kbuild test robot <lkp@intel.com>
---
ptp_ines.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/ptp/ptp_ines.c b/drivers/ptp/ptp_ines.c
index 59cb3f1..52c1e85 100644
--- a/drivers/ptp/ptp_ines.c
+++ b/drivers/ptp/ptp_ines.c
@@ -753,8 +753,8 @@ static u8 tag_to_msgtype(u8 tag)
return 0xf;
}
-struct mii_timestamper *ines_ptp_probe_channel(struct device *device,
- unsigned int index)
+static struct mii_timestamper *ines_ptp_probe_channel(struct device *device,
+ unsigned int index)
{
struct device_node *node = device->of_node;
struct ines_port *port;
@@ -782,7 +782,7 @@ static void ines_ptp_release_channel(struct device *device,
{
}
-struct mii_timestamping_ctrl ines_ctrl = {
+static struct mii_timestamping_ctrl ines_ctrl = {
.probe_channel = ines_ptp_probe_channel,
.release_channel = ines_ptp_release_channel,
};
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping
2019-05-31 5:56 [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping Richard Cochran
` (5 preceding siblings ...)
2019-05-31 5:56 ` [PATCH V5 net-next 6/6] ptp: Add a driver for InES time stamping IP core Richard Cochran
@ 2019-05-31 21:54 ` David Miller
2019-06-01 0:13 ` David Miller
6 siblings, 1 reply; 16+ messages in thread
From: David Miller @ 2019-05-31 21:54 UTC (permalink / raw)
To: richardcochran
Cc: netdev, devicetree, andrew, f.fainelli, jacob.e.keller,
mark.rutland, mlichvar, robh+dt, willemb
From: Richard Cochran <richardcochran@gmail.com>
Date: Thu, 30 May 2019 22:56:20 -0700
> This series adds support for PTP (IEEE 1588) P2P one-step time
> stamping along with a driver for a hardware device that supports this.
...
Series applied, will push out after build testing :-)
Thanks.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping
2019-05-31 21:54 ` [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping David Miller
@ 2019-06-01 0:13 ` David Miller
2019-06-01 5:09 ` Richard Cochran
0 siblings, 1 reply; 16+ messages in thread
From: David Miller @ 2019-06-01 0:13 UTC (permalink / raw)
To: richardcochran
Cc: netdev, devicetree, andrew, f.fainelli, jacob.e.keller,
mark.rutland, mlichvar, robh+dt, willemb
From: David Miller <davem@davemloft.net>
Date: Fri, 31 May 2019 14:54:56 -0700 (PDT)
> From: Richard Cochran <richardcochran@gmail.com>
> Date: Thu, 30 May 2019 22:56:20 -0700
>
>> This series adds support for PTP (IEEE 1588) P2P one-step time
>> stamping along with a driver for a hardware device that supports this.
> ...
>
> Series applied, will push out after build testing :-)
This also does not build.
Please do an allmodconfig build and save me from having to do this
another time.
Thank you.
====================
ERROR: "register_mii_tstamp_controller" [drivers/ptp/ptp_ines.ko] undefined!
ERROR: "unregister_mii_tstamp_controller" [drivers/ptp/ptp_ines.ko] undefined!
ERROR: "unregister_mii_timestamper" [drivers/of/of_mdio.ko] undefined!
ERROR: "register_mii_timestamper" [drivers/of/of_mdio.ko] undefined!
ERROR: "unregister_mii_timestamper" [drivers/net/phy/libphy.ko] undefined!
make[1]: *** [scripts/Makefile.modpost:91: __modpost] Error 1
make: *** [Makefile:1290: modules] Error 2
====================
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping
2019-06-01 0:13 ` David Miller
@ 2019-06-01 5:09 ` Richard Cochran
0 siblings, 0 replies; 16+ messages in thread
From: Richard Cochran @ 2019-06-01 5:09 UTC (permalink / raw)
To: David Miller
Cc: netdev, devicetree, andrew, f.fainelli, jacob.e.keller,
mark.rutland, mlichvar, robh+dt, willemb
On Fri, May 31, 2019 at 05:13:09PM -0700, David Miller wrote:
> This also does not build.
>
> Please do an allmodconfig build and save me from having to do this
> another time.
(Dons paper bag over head.)
I have a good excuse... it was the bay area fog that made me do it!
Sorry,
Richard
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V5 net-next 4/6] dt-bindings: ptp: Introduce MII time stamping devices.
2019-05-31 5:56 ` [PATCH V5 net-next 4/6] dt-bindings: ptp: Introduce MII time stamping devices Richard Cochran
@ 2019-07-08 21:38 ` Rob Herring
2019-07-09 5:11 ` Richard Cochran
0 siblings, 1 reply; 16+ messages in thread
From: Rob Herring @ 2019-07-08 21:38 UTC (permalink / raw)
To: Richard Cochran
Cc: netdev, David Miller, devicetree, Andrew Lunn, Florian Fainelli,
Jacob Keller, Mark Rutland, Miroslav Lichvar, Willem de Bruijn
On Thu, May 30, 2019 at 10:56:24PM -0700, Richard Cochran wrote:
> This patch add a new binding that allows non-PHY MII time stamping
> devices to find their buses. The new documentation covers both the
> generic binding and one upcoming user.
>
> Signed-off-by: Richard Cochran <richardcochran@gmail.com>
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
> ---
> Documentation/devicetree/bindings/ptp/ptp-ines.txt | 35 ++++++++++++++++++
> .../devicetree/bindings/ptp/timestamper.txt | 41 ++++++++++++++++++++++
> 2 files changed, 76 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/ptp/ptp-ines.txt
> create mode 100644 Documentation/devicetree/bindings/ptp/timestamper.txt
>
> diff --git a/Documentation/devicetree/bindings/ptp/ptp-ines.txt b/Documentation/devicetree/bindings/ptp/ptp-ines.txt
> new file mode 100644
> index 000000000000..4dee9eb89455
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/ptp/ptp-ines.txt
> @@ -0,0 +1,35 @@
> +ZHAW InES PTP time stamping IP core
> +
> +The IP core needs two different kinds of nodes. The control node
> +lives somewhere in the memory map and specifies the address of the
> +control registers. There can be up to three port handles placed as
> +attributes of PHY nodes. These associate a particular MII bus with a
> +port index within the IP core.
> +
> +Required properties of the control node:
> +
> +- compatible: "ines,ptp-ctrl"
This is an IP block that gets integrated into SoCs? It's not very
specific given that there could be different versions of the IP block
and SoC vendors can integrate various versions of the IP block in their
own unique (i.e. buggy) way.
> +- reg: physical address and size of the register bank
> +
> +Required format of the port handle within the PHY node:
> +
> +- timestamper: provides control node reference and
> + the port channel within the IP core
> +
> +Example:
> +
> + tstamper: timestamper@60000000 {
> + compatible = "ines,ptp-ctrl";
> + reg = <0x60000000 0x80>;
> + };
> +
> + ethernet@80000000 {
> + ...
> + mdio {
> + ...
> + phy@3 {
ethernet-phy is the correct node name.
> + ...
> + timestamper = <&tstamper 0>;
> + };
> + };
> + };
> diff --git a/Documentation/devicetree/bindings/ptp/timestamper.txt b/Documentation/devicetree/bindings/ptp/timestamper.txt
> new file mode 100644
> index 000000000000..88ea0bc7d662
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/ptp/timestamper.txt
> @@ -0,0 +1,41 @@
> +Time stamps from MII bus snooping devices
> +
> +This binding supports non-PHY devices that snoop the MII bus and
> +provide time stamps. In contrast to PHY time stamping drivers (which
> +can simply attach their interface directly to the PHY instance), stand
> +alone MII time stamping drivers use this binding to specify the
> +connection between the snooping device and a given network interface.
> +
> +Non-PHY MII time stamping drivers typically talk to the control
> +interface over another bus like I2C, SPI, UART, or via a memory mapped
> +peripheral. This controller device is associated with one or more
> +time stamping channels, each of which snoops on a MII bus.
> +
> +The "timestamper" property lives in a phy node and links a time
> +stamping channel from the controller device to that phy's MII bus.
> +
> +Example:
> +
> + tstamper: timestamper@10000000 {
> + compatible = "bigcorp,ts-ctrl";
Would be better to use a real example here.
> + };
> +
> + ethernet@20000000 {
> + mdio {
> + phy@1 {
> + timestamper = <&tstamper 0>;
> + };
> + };
> + };
> +
> + ethernet@30000000 {
> + mdio {
> + phy@2 {
> + timestamper = <&tstamper 1>;
> + };
> + };
> + };
> +
> +In this example, time stamps from the MII bus attached to phy@1 will
> +appear on time stamp channel 0 (zero), and those from phy@2 appear on
> +channel 1.
> --
> 2.11.0
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V5 net-next 4/6] dt-bindings: ptp: Introduce MII time stamping devices.
2019-07-08 21:38 ` Rob Herring
@ 2019-07-09 5:11 ` Richard Cochran
0 siblings, 0 replies; 16+ messages in thread
From: Richard Cochran @ 2019-07-09 5:11 UTC (permalink / raw)
To: Rob Herring
Cc: netdev, David Miller, devicetree, Andrew Lunn, Florian Fainelli,
Jacob Keller, Mark Rutland, Miroslav Lichvar, Willem de Bruijn
On Mon, Jul 08, 2019 at 03:38:37PM -0600, Rob Herring wrote:
> > +Required properties of the control node:
> > +
> > +- compatible: "ines,ptp-ctrl"
>
> This is an IP block that gets integrated into SoCs?
It is an IP block implemented in an FPGA (like the zync or the socfpga).
> It's not very
> specific given that there could be different versions of the IP block
> and SoC vendors can integrate various versions of the IP block in their
> own unique (i.e. buggy) way.
There is a version register where both the interface and FPGA are
versioned. The driver doesn't presently do anything with that field,
but if newer interfaces appear, then the driver can deal with that
without any DT help.
Thanks,
Richard
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2019-07-09 5:11 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-31 5:56 [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 1/6] net: Introduce peer to peer one step PTP " Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 2/6] net: Introduce a new MII time stamping interface Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 3/6] net: Add a layer for non-PHY MII time stamping drivers Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 4/6] dt-bindings: ptp: Introduce MII time stamping devices Richard Cochran
2019-07-08 21:38 ` Rob Herring
2019-07-09 5:11 ` Richard Cochran
2019-05-31 5:56 ` [PATCH V5 net-next 5/6] net: mdio: of: Register discovered MII time stampers Richard Cochran
2019-05-31 17:24 ` kbuild test robot
2019-05-31 17:24 ` [RFC PATCH] net: mdio: of: of_find_mii_timestamper() can be static kbuild test robot
2019-05-31 5:56 ` [PATCH V5 net-next 6/6] ptp: Add a driver for InES time stamping IP core Richard Cochran
2019-05-31 20:22 ` kbuild test robot
2019-05-31 20:22 ` [RFC PATCH] ptp: ines_ptp_probe_channel() can be static kbuild test robot
2019-05-31 21:54 ` [PATCH V5 net-next 0/6] Peer to Peer One-Step time stamping David Miller
2019-06-01 0:13 ` David Miller
2019-06-01 5:09 ` Richard Cochran
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).