Skip to content

Commit

Permalink
net: stmmac: fix taprio configuration when base_time is in the past
Browse files Browse the repository at this point in the history
The Synopsys TSN MAC supports Qbv base times in the past, but only up to a
certain limit. As a result, a taprio qdisc configuration with a small
base time (for example when treating the base time as a simple phase
offset) is not applied by the hardware and silently ignored.

This was observed on an NXP i.MX8MPlus device, but likely affects all
TSN-variants of the MAC.

Fix the issue by making sure the base time is in the future, pushing it by
an integer amount of cycle times if needed. (a similar check is already
done in several other taprio implementations, see for example
drivers/net/ethernet/intel/igc/igc_tsn.c#L116 or
drivers/net/dsa/sja1105/sja1105_ptp.h#L39).

Fixes: b60189e ("net: stmmac: Integrate EST with TAPRIO scheduler API")
Signed-off-by: Yannick Vignon <yannick.vignon@nxp.com>
Link: https://lore.kernel.org/r/20210113131557.24651-2-yannick.vignon@oss.nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Yackou authored and kuba-moo committed Jan 14, 2021
1 parent b76889f commit fe28c53
Showing 1 changed file with 18 additions and 2 deletions.
20 changes: 18 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,8 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
{
u32 size, wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
struct plat_stmmacenet_data *plat = priv->plat;
struct timespec64 time;
struct timespec64 time, current_time;
ktime_t current_time_ns;
bool fpe = false;
int i, ret = 0;
u64 ctr;
Expand Down Expand Up @@ -694,7 +695,22 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
}

/* Adjust for real system time */
time = ktime_to_timespec64(qopt->base_time);
priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, &current_time);
current_time_ns = timespec64_to_ktime(current_time);
if (ktime_after(qopt->base_time, current_time_ns)) {
time = ktime_to_timespec64(qopt->base_time);
} else {
ktime_t base_time;
s64 n;

n = div64_s64(ktime_sub_ns(current_time_ns, qopt->base_time),
qopt->cycle_time);
base_time = ktime_add_ns(qopt->base_time,
(n + 1) * qopt->cycle_time);

time = ktime_to_timespec64(base_time);
}

priv->plat->est->btr[0] = (u32)time.tv_nsec;
priv->plat->est->btr[1] = (u32)time.tv_sec;

Expand Down

0 comments on commit fe28c53

Please sign in to comment.