Skip to content

Commit

Permalink
net: stmmac: Calculate CDC error only once
Browse files Browse the repository at this point in the history
The clock domain crossing error (CDC) is calculated at every fetch of Tx or Rx
timestamps. It includes a division. Especially on arm32 based systems it is
expensive. It also requires two conditionals in the hotpath.

Add a compensation value cache to struct plat_stmmacenet_data and subtract it
unconditionally in the RX/TX functions which spares the conditionals.

The value is initialized to 0 and if supported calculated in the PTP
initialization code.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
Link: https://lore.kernel.org/r/20211122111931.135135-1-kurt@linutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Kurt Kanzenbach authored and Jakub Kicinski committed Nov 24, 2021
1 parent 2106efd commit c6d5f19
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 10 deletions.
12 changes: 2 additions & 10 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,14 +511,6 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
return true;
}

static inline u32 stmmac_cdc_adjust(struct stmmac_priv *priv)
{
/* Correct the clk domain crossing(CDC) error */
if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate)
return (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;
return 0;
}

/* stmmac_get_tx_hwtstamp - get HW TX timestamps
* @priv: driver private structure
* @p : descriptor pointer
Expand Down Expand Up @@ -550,7 +542,7 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
}

if (found) {
ns -= stmmac_cdc_adjust(priv);
ns -= priv->plat->cdc_error_adj;

memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
shhwtstamp.hwtstamp = ns_to_ktime(ns);
Expand Down Expand Up @@ -587,7 +579,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
if (stmmac_get_rx_timestamp_status(priv, p, np, priv->adv_ts)) {
stmmac_get_timestamp(priv, desc, priv->adv_ts, &ns);

ns -= stmmac_cdc_adjust(priv);
ns -= priv->plat->cdc_error_adj;

netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns);
shhwtstamp = skb_hwtstamps(skb);
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,11 @@ void stmmac_ptp_register(struct stmmac_priv *priv)
if (priv->plat->ptp_max_adj)
stmmac_ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;

/* Calculate the clock domain crossing (CDC) error if necessary */
priv->plat->cdc_error_adj = 0;
if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate)
priv->plat->cdc_error_adj = (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;

stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
stmmac_ptp_clock_ops.n_ext_ts = priv->dma_cap.aux_snapshot_n;

Expand Down
1 change: 1 addition & 0 deletions include/linux/stmmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ struct plat_stmmacenet_data {
unsigned int clk_ref_rate;
unsigned int mult_fact_100ns;
s32 ptp_max_adj;
u32 cdc_error_adj;
struct reset_control *stmmac_rst;
struct reset_control *stmmac_ahb_rst;
struct stmmac_axi *axi;
Expand Down

0 comments on commit c6d5f19

Please sign in to comment.