Skip to content

Commit

Permalink
net: stmmac: Get correct timestamp values from XGMAC
Browse files Browse the repository at this point in the history
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.

Changes from v2:
	- Rework return code check (Jakub)
Changes from v1:
	- Rework the get timestamp function (David)

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jose Abreu authored and David S. Miller committed Aug 17, 2019
1 parent 83beee5 commit 25e80cd
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 9 deletions.
15 changes: 15 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,20 @@ 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;
u32 value;

if (readl_poll_timeout_atomic(ioaddr + XGMAC_TIMESTAMP_STATUS,
value, value & XGMAC_TXTSC, 100, 10000))
return -EBUSY;

*ts = readl(ioaddr + XGMAC_TXTIMESTAMP_NSEC) & XGMAC_TXTSSTSLO;
*ts += readl(ioaddr + XGMAC_TXTIMESTAMP_SEC) * 1000000000ULL;
return 0;
}

const struct stmmac_ops dwxgmac210_ops = {
.core_init = dwxgmac2_core_init,
.set_mac = dwxgmac2_set_mac,
Expand Down Expand Up @@ -1033,6 +1047,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)
Expand Down
15 changes: 9 additions & 6 deletions drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -113,13 +119,10 @@ 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;
return !ret;
}

static void dwxgmac2_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/hwif.h
Original file line number Diff line number Diff line change
Expand Up @@ -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...) \
Expand Down Expand Up @@ -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 {
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -443,18 +444,20 @@ 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);

netdev_dbg(priv->dev, "get valid TX hw timestamp %llu\n", ns);
/* pass tstamp to stack */
skb_tstamp_tx(skb, &shhwtstamp);
}

return;
}

/* stmmac_get_rx_hwtstamp - get HW RX timestamps
Expand Down

0 comments on commit 25e80cd

Please sign in to comment.