mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 15:12:13 +02:00
Merge branch 'net-stmmac-add-support-for-coarse-timestamping'
Maxime Chevallier says: ==================== net: stmmac: Add support for coarse timestamping This is V2 for coarse timetamping support in stmmac. This version uses a dedicated devlink param "ts_coarse" to control this mode. This doesn't conflict with Russell's cleanup of hwif. Maxime [1] : https://lore.kernel.org/netdev/20200514102808.31163-1-olivier.dautricourt@orolia.com/ V1: https://lore.kernel.org/netdev/20251015102725.1297985-1-maxime.chevallier@bootlin.com/ ==================== Link: https://patch.msgid.link/20251024070720.71174-1-maxime.chevallier@bootlin.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
cebba694d2
|
|
@ -99,5 +99,6 @@ parameters, info versions, and other features it supports.
|
|||
prestera
|
||||
qed
|
||||
sfc
|
||||
stmmac
|
||||
ti-cpsw-switch
|
||||
zl3073x
|
||||
|
|
|
|||
31
Documentation/networking/devlink/stmmac.rst
Normal file
31
Documentation/networking/devlink/stmmac.rst
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=======================================
|
||||
stmmac (synopsys dwmac) devlink support
|
||||
=======================================
|
||||
|
||||
This document describes the devlink features implemented by the ``stmmac``
|
||||
device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
The ``stmmac`` driver implements the following driver-specific parameters.
|
||||
|
||||
.. list-table:: Driver-specific parameters implemented
|
||||
:widths: 5 5 5 85
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Mode
|
||||
- Description
|
||||
* - ``ts_coarse``
|
||||
- Boolean
|
||||
- runtime
|
||||
- Enable the Coarse timestamping mode. In Coarse mode, the ptp clock is
|
||||
expected to be updated through an external PPS input, but the subsecond
|
||||
increment used for timestamping is set to 1/ptp_clock_rate. In Fine mode
|
||||
(i.e. Coarse mode == false), the ptp clock frequency is adjusted more
|
||||
frequently, but the subsecond increment is set to 2/ptp_clock_rate.
|
||||
Coarse mode is suitable for PTP Grand Master operation. If unsure, leave
|
||||
the parameter to False.
|
||||
|
|
@ -10,6 +10,7 @@ config STMMAC_ETH
|
|||
select PHYLINK
|
||||
select CRC32
|
||||
select RESET_CONTROLLER
|
||||
select NET_DEVLINK
|
||||
help
|
||||
This is the driver for the Ethernet IPs built around a
|
||||
Synopsys IP Core.
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ struct stmmac_priv {
|
|||
u32 sarc_type;
|
||||
u32 rx_riwt[MTL_MAX_RX_QUEUES];
|
||||
int hwts_rx_en;
|
||||
bool tsfupdt_coarse;
|
||||
|
||||
void __iomem *ioaddr;
|
||||
struct net_device *dev;
|
||||
|
|
@ -369,6 +370,8 @@ struct stmmac_priv {
|
|||
/* XDP BPF Program */
|
||||
unsigned long *af_xdp_zc_qps;
|
||||
struct bpf_prog *xdp_prog;
|
||||
|
||||
struct devlink *devlink;
|
||||
};
|
||||
|
||||
enum stmmac_state {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include <linux/phylink.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/bpf_trace.h>
|
||||
#include <net/devlink.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/xdp_sock_drv.h>
|
||||
|
|
@ -58,8 +59,7 @@
|
|||
* with fine resolution and binary rollover. This avoid non-monotonic behavior
|
||||
* (clock jumps) when changing timestamping settings at runtime.
|
||||
*/
|
||||
#define STMMAC_HWTS_ACTIVE (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | \
|
||||
PTP_TCR_TSCTRLSSR)
|
||||
#define STMMAC_HWTS_ACTIVE (PTP_TCR_TSENA | PTP_TCR_TSCTRLSSR)
|
||||
|
||||
#define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16)
|
||||
#define TSO_MAX_BUFF_SIZE (SZ_16K - 1)
|
||||
|
|
@ -148,6 +148,15 @@ static void stmmac_exit_fs(struct net_device *dev);
|
|||
|
||||
#define STMMAC_COAL_TIMER(x) (ns_to_ktime((x) * NSEC_PER_USEC))
|
||||
|
||||
struct stmmac_devlink_priv {
|
||||
struct stmmac_priv *stmmac_priv;
|
||||
};
|
||||
|
||||
enum stmmac_dl_param_id {
|
||||
STMMAC_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
|
||||
STMMAC_DEVLINK_PARAM_ID_TS_COARSE,
|
||||
};
|
||||
|
||||
/**
|
||||
* stmmac_set_clk_tx_rate() - set the clock rate for the MAC transmit clock
|
||||
* @bsp_priv: BSP private data structure (unused)
|
||||
|
|
@ -464,6 +473,33 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
|
|||
}
|
||||
}
|
||||
|
||||
static void stmmac_update_subsecond_increment(struct stmmac_priv *priv)
|
||||
{
|
||||
bool xmac = dwmac_is_xmac(priv->plat->core_type);
|
||||
u32 sec_inc = 0;
|
||||
u64 temp = 0;
|
||||
|
||||
stmmac_config_hw_tstamping(priv, priv->ptpaddr, priv->systime_flags);
|
||||
|
||||
/* program Sub Second Increment reg */
|
||||
stmmac_config_sub_second_increment(priv, priv->ptpaddr,
|
||||
priv->plat->clk_ptp_rate,
|
||||
xmac, &sec_inc);
|
||||
temp = div_u64(1000000000ULL, sec_inc);
|
||||
|
||||
/* Store sub second increment for later use */
|
||||
priv->sub_second_inc = sec_inc;
|
||||
|
||||
/* calculate default added value:
|
||||
* formula is :
|
||||
* addend = (2^32)/freq_div_ratio;
|
||||
* where, freq_div_ratio = 1e9ns/sec_inc
|
||||
*/
|
||||
temp = (u64)(temp << 32);
|
||||
priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate);
|
||||
stmmac_config_addend(priv, priv->ptpaddr, priv->default_addend);
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_hwtstamp_set - control hardware timestamping.
|
||||
* @dev: device pointer.
|
||||
|
|
@ -648,6 +684,8 @@ static int stmmac_hwtstamp_set(struct net_device *dev,
|
|||
priv->hwts_tx_en = config->tx_type == HWTSTAMP_TX_ON;
|
||||
|
||||
priv->systime_flags = STMMAC_HWTS_ACTIVE;
|
||||
if (!priv->tsfupdt_coarse)
|
||||
priv->systime_flags |= PTP_TCR_TSCFUPDT;
|
||||
|
||||
if (priv->hwts_tx_en || priv->hwts_rx_en) {
|
||||
priv->systime_flags |= tstamp_all | ptp_v2 |
|
||||
|
|
@ -697,10 +735,7 @@ static int stmmac_hwtstamp_get(struct net_device *dev,
|
|||
static int stmmac_init_tstamp_counter(struct stmmac_priv *priv,
|
||||
u32 systime_flags)
|
||||
{
|
||||
bool xmac = dwmac_is_xmac(priv->plat->core_type);
|
||||
struct timespec64 now;
|
||||
u32 sec_inc = 0;
|
||||
u64 temp = 0;
|
||||
|
||||
if (!priv->plat->clk_ptp_rate) {
|
||||
netdev_err(priv->dev, "Invalid PTP clock rate");
|
||||
|
|
@ -710,23 +745,7 @@ static int stmmac_init_tstamp_counter(struct stmmac_priv *priv,
|
|||
stmmac_config_hw_tstamping(priv, priv->ptpaddr, systime_flags);
|
||||
priv->systime_flags = systime_flags;
|
||||
|
||||
/* program Sub Second Increment reg */
|
||||
stmmac_config_sub_second_increment(priv, priv->ptpaddr,
|
||||
priv->plat->clk_ptp_rate,
|
||||
xmac, &sec_inc);
|
||||
temp = div_u64(1000000000ULL, sec_inc);
|
||||
|
||||
/* Store sub second increment for later use */
|
||||
priv->sub_second_inc = sec_inc;
|
||||
|
||||
/* calculate default added value:
|
||||
* formula is :
|
||||
* addend = (2^32)/freq_div_ratio;
|
||||
* where, freq_div_ratio = 1e9ns/sec_inc
|
||||
*/
|
||||
temp = (u64)(temp << 32);
|
||||
priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate);
|
||||
stmmac_config_addend(priv, priv->ptpaddr, priv->default_addend);
|
||||
stmmac_update_subsecond_increment(priv);
|
||||
|
||||
/* initialize system time */
|
||||
ktime_get_real_ts64(&now);
|
||||
|
|
@ -757,7 +776,8 @@ static int stmmac_init_timestamping(struct stmmac_priv *priv)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = stmmac_init_tstamp_counter(priv, STMMAC_HWTS_ACTIVE);
|
||||
ret = stmmac_init_tstamp_counter(priv, STMMAC_HWTS_ACTIVE |
|
||||
PTP_TCR_TSCFUPDT);
|
||||
if (ret) {
|
||||
netdev_warn(priv->dev, "PTP init failed\n");
|
||||
return ret;
|
||||
|
|
@ -7392,6 +7412,95 @@ static const struct xdp_metadata_ops stmmac_xdp_metadata_ops = {
|
|||
.xmo_rx_timestamp = stmmac_xdp_rx_timestamp,
|
||||
};
|
||||
|
||||
static int stmmac_dl_ts_coarse_set(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct stmmac_devlink_priv *dl_priv = devlink_priv(dl);
|
||||
struct stmmac_priv *priv = dl_priv->stmmac_priv;
|
||||
|
||||
priv->tsfupdt_coarse = ctx->val.vbool;
|
||||
|
||||
if (priv->tsfupdt_coarse)
|
||||
priv->systime_flags &= ~PTP_TCR_TSCFUPDT;
|
||||
else
|
||||
priv->systime_flags |= PTP_TCR_TSCFUPDT;
|
||||
|
||||
/* In Coarse mode, we can use a smaller subsecond increment, let's
|
||||
* reconfigure the systime, subsecond increment and addend.
|
||||
*/
|
||||
stmmac_update_subsecond_increment(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmmac_dl_ts_coarse_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
{
|
||||
struct stmmac_devlink_priv *dl_priv = devlink_priv(dl);
|
||||
struct stmmac_priv *priv = dl_priv->stmmac_priv;
|
||||
|
||||
ctx->val.vbool = priv->tsfupdt_coarse;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct devlink_param stmmac_devlink_params[] = {
|
||||
DEVLINK_PARAM_DRIVER(STMMAC_DEVLINK_PARAM_ID_TS_COARSE, "ts_coarse",
|
||||
DEVLINK_PARAM_TYPE_BOOL,
|
||||
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
|
||||
stmmac_dl_ts_coarse_get,
|
||||
stmmac_dl_ts_coarse_set, NULL),
|
||||
};
|
||||
|
||||
/* None of the generic devlink parameters are implemented */
|
||||
static const struct devlink_ops stmmac_devlink_ops = {};
|
||||
|
||||
static int stmmac_register_devlink(struct stmmac_priv *priv)
|
||||
{
|
||||
struct stmmac_devlink_priv *dl_priv;
|
||||
int ret;
|
||||
|
||||
/* For now, what is exposed over devlink is only relevant when
|
||||
* timestamping is available and we have a valid ptp clock rate
|
||||
*/
|
||||
if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp) ||
|
||||
!priv->plat->clk_ptp_rate)
|
||||
return 0;
|
||||
|
||||
priv->devlink = devlink_alloc(&stmmac_devlink_ops, sizeof(*dl_priv),
|
||||
priv->device);
|
||||
if (!priv->devlink)
|
||||
return -ENOMEM;
|
||||
|
||||
dl_priv = devlink_priv(priv->devlink);
|
||||
dl_priv->stmmac_priv = priv;
|
||||
|
||||
ret = devlink_params_register(priv->devlink, stmmac_devlink_params,
|
||||
ARRAY_SIZE(stmmac_devlink_params));
|
||||
if (ret)
|
||||
goto dl_free;
|
||||
|
||||
devlink_register(priv->devlink);
|
||||
return 0;
|
||||
|
||||
dl_free:
|
||||
devlink_free(priv->devlink);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stmmac_unregister_devlink(struct stmmac_priv *priv)
|
||||
{
|
||||
if (!priv->devlink)
|
||||
return;
|
||||
|
||||
devlink_unregister(priv->devlink);
|
||||
devlink_params_unregister(priv->devlink, stmmac_devlink_params,
|
||||
ARRAY_SIZE(stmmac_devlink_params));
|
||||
devlink_free(priv->devlink);
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_dvr_probe
|
||||
* @device: device pointer
|
||||
|
|
@ -7665,6 +7774,10 @@ int stmmac_dvr_probe(struct device *device,
|
|||
goto error_phy_setup;
|
||||
}
|
||||
|
||||
ret = stmmac_register_devlink(priv);
|
||||
if (ret)
|
||||
goto error_devlink_setup;
|
||||
|
||||
ret = register_netdev(ndev);
|
||||
if (ret) {
|
||||
dev_err(priv->device, "%s: ERROR %i registering the device\n",
|
||||
|
|
@ -7687,6 +7800,8 @@ int stmmac_dvr_probe(struct device *device,
|
|||
return ret;
|
||||
|
||||
error_netdev_register:
|
||||
stmmac_unregister_devlink(priv);
|
||||
error_devlink_setup:
|
||||
phylink_destroy(priv->phylink);
|
||||
error_phy_setup:
|
||||
stmmac_pcs_clean(ndev);
|
||||
|
|
@ -7723,6 +7838,8 @@ void stmmac_dvr_remove(struct device *dev)
|
|||
#ifdef CONFIG_DEBUG_FS
|
||||
stmmac_exit_fs(ndev);
|
||||
#endif
|
||||
stmmac_unregister_devlink(priv);
|
||||
|
||||
phylink_destroy(priv->phylink);
|
||||
if (priv->plat->stmmac_rst)
|
||||
reset_control_assert(priv->plat->stmmac_rst);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user