net: stmmac: Get correct timestamp values from XGMAC
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>
This commit is contained in:
parent
83beee5a3a
commit
25e80cd05f
@ -997,6 +997,20 @@ re_enable:
|
||||
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,
|
||||
@ -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)
|
||||
|
@ -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,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,
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user