mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
Merge branch 'net-stmmac-re-apply-taprio-offload-in-__stmmac_open-and-stmmac_resume'
Lorenzo Bianconi says: ==================== net: stmmac: re-apply taprio offload in __stmmac_open() and stmmac_resume() Reconfigure MTL_EST registers after sw reset in __stmmac_open(). Remove priv->est->enable dependency in est_configure(). Initialize est_lock at probe time. v4: https://lore.kernel.org/r/20261026-stmmac-est-fixes-v4-0-999dac4de44f@oss.qualcomm.com v2: https://lore.kernel.org/r/20260829-stmmac-est-reapply-after-open-v2-1-5e5ccb185e92@oss.qualcomm.com v1: https://lore.kernel.org/r/20260825-stmmac-est-reapply-after-open-v1-1-dfa80735e0a1@oss.qualcomm.com ==================== Link: https://patch.msgid.link/20261029-stmmac-est-fixes-v5-0-85b830a795a9@oss.qualcomm.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
e55f9e70b8
|
|
@ -620,7 +620,7 @@ struct stmmac_mmc_ops {
|
|||
|
||||
struct stmmac_est_ops {
|
||||
int (*configure)(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
||||
unsigned int ptp_rate);
|
||||
unsigned int ptp_rate, bool enable);
|
||||
void (*irq_status)(struct stmmac_priv *priv, struct net_device *dev,
|
||||
struct stmmac_extra_stats *x, u32 txqcnt);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ struct stmmac_est {
|
|||
u32 gcl[EST_GCL];
|
||||
u32 gcl_size;
|
||||
u32 max_sdu[MTL_MAX_TX_QUEUES];
|
||||
u32 pclass;
|
||||
};
|
||||
|
||||
struct stmmac_msi {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ static int est_write(void __iomem *est_addr, u32 reg, u32 val, bool gcl)
|
|||
}
|
||||
|
||||
static int est_configure(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
||||
unsigned int ptp_rate)
|
||||
unsigned int ptp_rate, bool enable)
|
||||
{
|
||||
void __iomem *est_addr = priv->estaddr;
|
||||
int i, ret = 0;
|
||||
|
|
@ -62,7 +62,7 @@ static int est_configure(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
|||
ctrl |= ((NSEC_PER_SEC / ptp_rate) * EST_GMAC5_PTOV_MUL) <<
|
||||
EST_GMAC5_PTOV_SHIFT;
|
||||
}
|
||||
if (cfg->enable)
|
||||
if (enable)
|
||||
ctrl |= EST_EEST | EST_SSWL | EST_DFBS;
|
||||
else
|
||||
ctrl &= ~EST_EEST;
|
||||
|
|
@ -70,7 +70,7 @@ static int est_configure(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
|||
writel(ctrl, est_addr + EST_CONTROL);
|
||||
|
||||
/* Configure EST interrupt */
|
||||
if (cfg->enable)
|
||||
if (enable)
|
||||
ctrl = EST_IECGCE | EST_IEHS | EST_IEHF | EST_IEBE | EST_IECC;
|
||||
else
|
||||
ctrl = 0;
|
||||
|
|
@ -80,6 +80,61 @@ static int est_configure(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int __stmmac_setup_est(struct stmmac_priv *priv)
|
||||
{
|
||||
struct timespec64 current_time, time;
|
||||
ktime_t current_time_ns, basetime;
|
||||
u64 cycle_time;
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&priv->est_lock);
|
||||
|
||||
priv->ptp_clock_ops.gettimex64(&priv->ptp_clock_ops, ¤t_time,
|
||||
NULL);
|
||||
current_time_ns = timespec64_to_ktime(current_time);
|
||||
|
||||
time.tv_nsec = priv->est->btr_reserve[0];
|
||||
time.tv_sec = priv->est->btr_reserve[1];
|
||||
basetime = timespec64_to_ktime(time);
|
||||
|
||||
cycle_time = (u64)priv->est->ctr[1] * NSEC_PER_SEC + priv->est->ctr[0];
|
||||
|
||||
time = stmmac_calc_tas_basetime(basetime, current_time_ns, cycle_time);
|
||||
priv->est->btr[0] = (u32)time.tv_nsec;
|
||||
priv->est->btr[1] = (u32)time.tv_sec;
|
||||
|
||||
err = stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate, true);
|
||||
if (err) {
|
||||
netdev_err(priv->dev, "failed to re-configure EST\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stmmac_setup_est(struct stmmac_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!priv->ptp_enabled)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&priv->est_lock);
|
||||
if (priv->est && priv->est->enable) {
|
||||
ret = __stmmac_setup_est(priv);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = stmmac_fpe_map_preemption_class(priv, priv->dev, NULL,
|
||||
priv->est->pclass);
|
||||
}
|
||||
unlock:
|
||||
mutex_unlock(&priv->est_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void est_irq_status(struct stmmac_priv *priv, struct net_device *dev,
|
||||
struct stmmac_extra_stats *x, u32 txqcnt)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
* stmmac EST(802.3 Qbv) handling
|
||||
*/
|
||||
|
||||
#ifndef __STMMAC_EST_H__
|
||||
#define __STMMAC_EST_H__
|
||||
|
||||
#define EST_GMAC4_OFFSET 0x00000c50
|
||||
#define EST_XGMAC_OFFSET 0x00001050
|
||||
|
||||
|
|
@ -65,3 +68,8 @@
|
|||
#define EST_GCL_DATA 0x00000034
|
||||
|
||||
extern const struct stmmac_est_ops dwmac510_est_ops;
|
||||
|
||||
int __stmmac_setup_est(struct stmmac_priv *priv);
|
||||
int stmmac_setup_est(struct stmmac_priv *priv);
|
||||
|
||||
#endif /* __STMMAC_EST_H__ */
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "stmmac_ptp.h"
|
||||
#include "stmmac_fpe.h"
|
||||
#include "stmmac.h"
|
||||
#include "stmmac_est.h"
|
||||
#include "stmmac_pcs.h"
|
||||
#include "stmmac_xdp.h"
|
||||
#include <linux/reset.h>
|
||||
|
|
@ -4204,6 +4205,10 @@ static int __stmmac_open(struct net_device *dev,
|
|||
if (ret)
|
||||
goto ptp_error;
|
||||
|
||||
ret = stmmac_setup_est(priv);
|
||||
if (ret)
|
||||
goto est_error;
|
||||
|
||||
stmmac_init_coalesce(priv);
|
||||
|
||||
phylink_start(priv->phylink);
|
||||
|
|
@ -4227,7 +4232,7 @@ static int __stmmac_open(struct net_device *dev,
|
|||
|
||||
for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
|
||||
hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
|
||||
|
||||
est_error:
|
||||
stmmac_release_ptp(priv);
|
||||
ptp_error:
|
||||
stmmac_stop_all_dma(priv);
|
||||
|
|
@ -8236,6 +8241,7 @@ static int __stmmac_dvr_probe(struct device *device,
|
|||
stmmac_napi_add(ndev);
|
||||
|
||||
mutex_init(&priv->lock);
|
||||
mutex_init(&priv->est_lock);
|
||||
rwlock_init(&priv->ptp_lock);
|
||||
|
||||
stmmac_fpe_init(priv);
|
||||
|
|
@ -8369,6 +8375,7 @@ void stmmac_dvr_remove(struct device *dev)
|
|||
|
||||
destroy_workqueue(priv->wq);
|
||||
mutex_destroy(&priv->lock);
|
||||
mutex_destroy(&priv->est_lock);
|
||||
bitmap_free(priv->af_xdp_zc_qps);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
|
@ -8551,6 +8558,10 @@ int stmmac_resume(struct device *dev)
|
|||
ret = stmmac_init_timestamping(priv);
|
||||
if (ret)
|
||||
goto error_stop_dma;
|
||||
|
||||
ret = stmmac_setup_est(priv);
|
||||
if (ret)
|
||||
goto error_stop_dma;
|
||||
}
|
||||
|
||||
init_coalesce:
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
|
||||
*******************************************************************************/
|
||||
#include "stmmac.h"
|
||||
#include "stmmac_est.h"
|
||||
#include "stmmac_ptp.h"
|
||||
|
||||
#define PTP_SAFE_TIME_OFFSET_NS 500000
|
||||
|
|
@ -54,8 +55,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
|
|||
u32 sec, nsec;
|
||||
u32 quotient, reminder;
|
||||
int neg_adj = 0;
|
||||
bool xmac, est_rst = false;
|
||||
int ret;
|
||||
bool xmac;
|
||||
|
||||
xmac = dwmac_is_xmac(priv->plat->core_type);
|
||||
|
||||
|
|
@ -69,47 +69,21 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
|
|||
nsec = reminder;
|
||||
|
||||
/* If EST is enabled, disabled it before adjust ptp time. */
|
||||
if (priv->est && priv->est->enable) {
|
||||
est_rst = true;
|
||||
mutex_lock(&priv->est_lock);
|
||||
priv->est->enable = false;
|
||||
mutex_lock(&priv->est_lock);
|
||||
if (priv->est && priv->est->enable)
|
||||
stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
}
|
||||
priv->plat->clk_ptp_rate, false);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
|
||||
write_lock_irqsave(&priv->ptp_lock, flags);
|
||||
stmmac_adjust_systime(priv, priv->ptpaddr, sec, nsec, neg_adj, xmac);
|
||||
write_unlock_irqrestore(&priv->ptp_lock, flags);
|
||||
|
||||
/* Calculate new basetime and re-configured EST after PTP time adjust. */
|
||||
if (est_rst) {
|
||||
struct timespec64 current_time, time;
|
||||
ktime_t current_time_ns, basetime;
|
||||
u64 cycle_time;
|
||||
|
||||
mutex_lock(&priv->est_lock);
|
||||
priv->ptp_clock_ops.gettimex64(&priv->ptp_clock_ops,
|
||||
¤t_time, NULL);
|
||||
current_time_ns = timespec64_to_ktime(current_time);
|
||||
time.tv_nsec = priv->est->btr_reserve[0];
|
||||
time.tv_sec = priv->est->btr_reserve[1];
|
||||
basetime = timespec64_to_ktime(time);
|
||||
cycle_time = (u64)priv->est->ctr[1] * NSEC_PER_SEC +
|
||||
priv->est->ctr[0];
|
||||
time = stmmac_calc_tas_basetime(basetime,
|
||||
current_time_ns,
|
||||
cycle_time);
|
||||
|
||||
priv->est->btr[0] = (u32)time.tv_nsec;
|
||||
priv->est->btr[1] = (u32)time.tv_sec;
|
||||
priv->est->enable = true;
|
||||
ret = stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
if (ret)
|
||||
netdev_err(priv->dev, "failed to configure EST\n");
|
||||
}
|
||||
mutex_lock(&priv->est_lock);
|
||||
if (priv->est && priv->est->enable)
|
||||
__stmmac_setup_est(priv);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -966,11 +966,12 @@ static void tc_taprio_map_maxsdu_txq(struct stmmac_priv *priv,
|
|||
static int tc_taprio_configure(struct stmmac_priv *priv,
|
||||
struct tc_taprio_qopt_offload *qopt)
|
||||
{
|
||||
u32 size, wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
|
||||
u32 wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
|
||||
struct netlink_ext_ack *extack = qopt->mqprio.extack;
|
||||
struct timespec64 time, current_time, qopt_time;
|
||||
ktime_t current_time_ns;
|
||||
int err, i, ret = 0;
|
||||
u32 *gcl = NULL;
|
||||
u64 ctr;
|
||||
|
||||
if (qopt->base_time < 0)
|
||||
|
|
@ -1013,44 +1014,46 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->est_lock);
|
||||
|
||||
if (qopt->cmd == TAPRIO_CMD_DESTROY)
|
||||
goto disable;
|
||||
|
||||
if (qopt->num_entries > dep)
|
||||
return -EINVAL;
|
||||
if (!qopt->cycle_time)
|
||||
return -ERANGE;
|
||||
if (qopt->cycle_time_extension >= BIT(wid + 7))
|
||||
return -ERANGE;
|
||||
|
||||
if (!priv->est) {
|
||||
priv->est = devm_kzalloc(priv->device, sizeof(*priv->est),
|
||||
GFP_KERNEL);
|
||||
if (!priv->est)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&priv->est_lock);
|
||||
} else {
|
||||
mutex_lock(&priv->est_lock);
|
||||
memset(priv->est, 0, sizeof(*priv->est));
|
||||
mutex_unlock(&priv->est_lock);
|
||||
if (qopt->num_entries > dep) {
|
||||
ret = -EINVAL;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
size = qopt->num_entries;
|
||||
if (!qopt->cycle_time ||
|
||||
qopt->cycle_time > (u64)U32_MAX * NSEC_PER_SEC) {
|
||||
ret = -ERANGE;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->est_lock);
|
||||
priv->est->gcl_size = size;
|
||||
priv->est->enable = qopt->cmd == TAPRIO_CMD_REPLACE;
|
||||
mutex_unlock(&priv->est_lock);
|
||||
if (qopt->cycle_time_extension >= BIT(wid + 7)) {
|
||||
ret = -ERANGE;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
gcl = kcalloc(qopt->num_entries, sizeof(*gcl), GFP_KERNEL);
|
||||
if (!gcl) {
|
||||
ret = -ENOMEM;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < qopt->num_entries; i++) {
|
||||
s64 delta_ns = qopt->entries[i].interval;
|
||||
u32 gates = qopt->entries[i].gate_mask;
|
||||
|
||||
if (delta_ns > GENMASK(wid - 1, 0))
|
||||
return -ERANGE;
|
||||
if (gates > GENMASK(31 - wid, 0))
|
||||
return -ERANGE;
|
||||
if (delta_ns > GENMASK(wid - 1, 0)) {
|
||||
ret = -ERANGE;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
if (gates > GENMASK(31 - wid, 0)) {
|
||||
ret = -ERANGE;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
switch (qopt->entries[i].command) {
|
||||
case TC_TAPRIO_CMD_SET_GATES:
|
||||
|
|
@ -1062,13 +1065,26 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
|
|||
gates &= ~BIT(0);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
ret = -EOPNOTSUPP;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
priv->est->gcl[i] = delta_ns | (gates << wid);
|
||||
gcl[i] = delta_ns | (gates << wid);
|
||||
}
|
||||
|
||||
mutex_lock(&priv->est_lock);
|
||||
if (!priv->est) {
|
||||
priv->est = devm_kzalloc(priv->device, sizeof(*priv->est),
|
||||
GFP_KERNEL);
|
||||
if (!priv->est) {
|
||||
ret = -ENOMEM;
|
||||
goto error_unlock;
|
||||
}
|
||||
} else {
|
||||
memset(priv->est, 0, sizeof(*priv->est));
|
||||
}
|
||||
memcpy(priv->est->gcl, gcl, sizeof(*gcl) * qopt->num_entries);
|
||||
priv->est->gcl_size = qopt->num_entries;
|
||||
|
||||
/* Adjust for real system time */
|
||||
priv->ptp_clock_ops.gettimex64(&priv->ptp_clock_ops, ¤t_time,
|
||||
NULL);
|
||||
|
|
@ -1092,8 +1108,7 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
|
|||
tc_taprio_map_maxsdu_txq(priv, qopt);
|
||||
|
||||
ret = stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
priv->plat->clk_ptp_rate, true);
|
||||
if (ret) {
|
||||
netdev_err(priv->dev, "failed to configure EST\n");
|
||||
goto disable;
|
||||
|
|
@ -1104,24 +1119,31 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
|
|||
if (ret)
|
||||
goto disable;
|
||||
|
||||
priv->est->pclass = qopt->mqprio.preemptible_tcs;
|
||||
priv->est->enable = true;
|
||||
|
||||
mutex_unlock(&priv->est_lock);
|
||||
kfree(gcl);
|
||||
|
||||
return 0;
|
||||
|
||||
disable:
|
||||
if (priv->est) {
|
||||
mutex_lock(&priv->est_lock);
|
||||
priv->est->enable = false;
|
||||
stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate);
|
||||
priv->plat->clk_ptp_rate, false);
|
||||
/* Reset taprio status */
|
||||
for (i = 0; i < priv->plat->tx_queues_to_use; i++) {
|
||||
priv->xstats.max_sdu_txq_drop[i] = 0;
|
||||
priv->xstats.mtl_est_txq_hlbf[i] = 0;
|
||||
priv->xstats.mtl_est_txq_hlbs[i] = 0;
|
||||
}
|
||||
mutex_unlock(&priv->est_lock);
|
||||
}
|
||||
|
||||
err = stmmac_fpe_map_preemption_class(priv, priv->dev, extack, 0);
|
||||
error_unlock:
|
||||
mutex_unlock(&priv->est_lock);
|
||||
kfree(gcl);
|
||||
|
||||
return qopt->cmd == TAPRIO_CMD_DESTROY ? err : ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user