TX Timestamp in XGMAC comes from MAC instead of descriptors. Implement this in a new callback.
Also, RX Timestamp in XGMAC must be cheked against corruption and we need a barrier to make sure that descriptor fields are read correctly. Signed-off-by: Jose Abreu <joab...@synopsys.com> --- Cc: Giuseppe Cavallaro <peppe.cavall...@st.com> Cc: Alexandre Torgue <alexandre.tor...@st.com> Cc: Jose Abreu <joab...@synopsys.com> Cc: "David S. Miller" <da...@davemloft.net> Cc: Maxime Coquelin <mcoquelin.st...@gmail.com> Cc: net...@vger.kernel.org Cc: linux-st...@st-md-mailman.stormreply.com Cc: linux-arm-ker...@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- .../net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 22 ++++++++++++++++++++++ .../net/ethernet/stmicro/stmmac/dwxgmac2_descs.c | 18 +++++++++++------- drivers/net/ethernet/stmicro/stmmac/hwif.h | 4 ++++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 ++++++--- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 767f3fe5efaa..1161287d3a62 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -997,6 +997,27 @@ static int dwxgmac3_rxp_config(void __iomem *ioaddr, return ret; } +static int dwxgmac2_get_mac_tx_timestamp(struct mac_device_info *hw, u64 *ts) +{ + void __iomem *ioaddr = hw->pcsr; + int count = 0; + u32 value; + + do { + if (readl_poll_timeout_atomic(ioaddr + XGMAC_TIMESTAMP_STATUS, + value, value & XGMAC_TXTSC, + 100, 10000)) + break; + + *ts = readl(ioaddr + XGMAC_TXTIMESTAMP_NSEC) & XGMAC_TXTSSTSLO; + *ts += readl(ioaddr + XGMAC_TXTIMESTAMP_SEC) * 1000000000ULL; + } while (count++); + + if (count) + return 0; + return -EBUSY; +} + const struct stmmac_ops dwxgmac210_ops = { .core_init = dwxgmac2_core_init, .set_mac = dwxgmac2_set_mac, @@ -1033,6 +1054,7 @@ const struct stmmac_ops dwxgmac210_ops = { .rss_configure = dwxgmac2_rss_configure, .update_vlan_hash = dwxgmac2_update_vlan_hash, .rxp_config = dwxgmac3_rxp_config, + .get_mac_tx_timestamp = dwxgmac2_get_mac_tx_timestamp, }; int dwxgmac2_setup(struct stmmac_priv *priv) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c index 9ff9d9ac1a50..d70a90c12dbc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c @@ -98,11 +98,17 @@ static int dwxgmac2_rx_check_timestamp(void *desc) unsigned int rdes3 = le32_to_cpu(p->des3); bool desc_valid, ts_valid; + dma_rmb(); + desc_valid = !(rdes3 & XGMAC_RDES3_OWN) && (rdes3 & XGMAC_RDES3_CTXT); ts_valid = !(rdes3 & XGMAC_RDES3_TSD) && (rdes3 & XGMAC_RDES3_TSA); - if (likely(desc_valid && ts_valid)) + if (likely(desc_valid && ts_valid)) { + if ((p->des0 == 0xffffffff) && (p->des1 == 0xffffffff)) + return -EINVAL; return 0; + } + return -EINVAL; } @@ -113,13 +119,11 @@ static int dwxgmac2_get_rx_timestamp_status(void *desc, void *next_desc, unsigned int rdes3 = le32_to_cpu(p->des3); int ret = -EBUSY; - if (likely(rdes3 & XGMAC_RDES3_CDA)) { + if (likely(rdes3 & XGMAC_RDES3_CDA)) ret = dwxgmac2_rx_check_timestamp(next_desc); - if (ret) - return ret; - } - - return ret; + if (!ret) + return 1; + return 0; } static void dwxgmac2_init_rx_desc(struct dma_desc *p, int disable_rx_ic, diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 52fc2344b066..7e1523c6f456 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -339,6 +339,8 @@ struct stmmac_ops { /* VLAN */ void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash, bool is_double); + /* TX Timestamp */ + int (*get_mac_tx_timestamp)(struct mac_device_info *hw, u64 *ts); }; #define stmmac_core_init(__priv, __args...) \ @@ -413,6 +415,8 @@ struct stmmac_ops { stmmac_do_callback(__priv, mac, rss_configure, __args) #define stmmac_update_vlan_hash(__priv, __args...) \ stmmac_do_void_callback(__priv, mac, update_vlan_hash, __args) +#define stmmac_get_mac_tx_timestamp(__priv, __args...) \ + stmmac_do_callback(__priv, mac, get_mac_tx_timestamp, __args) /* PTP and HW Timer helpers */ struct stmmac_hwtimestamp { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 5ac86d6a8e40..075de483ce7b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -432,6 +432,7 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, struct sk_buff *skb) { struct skb_shared_hwtstamps shhwtstamp; + bool found = false; u64 ns = 0; if (!priv->hwts_tx_en) @@ -443,9 +444,13 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, /* check tx tstamp status */ if (stmmac_get_tx_timestamp_status(priv, p)) { - /* get the valid tstamp */ stmmac_get_timestamp(priv, p, priv->adv_ts, &ns); + found = true; + } else if (!stmmac_get_mac_tx_timestamp(priv, priv->hw, &ns)) { + found = true; + } + if (found) { memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); shhwtstamp.hwtstamp = ns_to_ktime(ns); @@ -453,8 +458,6 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, /* pass tstamp to stack */ skb_tstamp_tx(skb, &shhwtstamp); } - - return; } /* stmmac_get_rx_hwtstamp - get HW RX timestamps -- 2.7.4