Commit 36638d37 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-stmmac-est-implementation'

Rohan G Thomas says:

====================
net: stmmac: EST implementation

This patchset extends EST interrupt handling support to DWXGMAC IP
followed by refactoring of EST implementation. Added a separate
module for EST and moved all EST related functions to the new module.

Also added support for EST cycle-time-extension.
====================

Link: https://lore.kernel.org/r/20231201055252.1302-1-rohan.g.thomas@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents be5fc78a 9e95505f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
	      mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o	\
	      dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \
	      stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \
	      stmmac_xdp.o \
	      stmmac_xdp.o stmmac_est.o \
	      $(stmmac-y)

stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o
+1 −0
Original line number Diff line number Diff line
@@ -563,6 +563,7 @@ struct mac_device_info {
	const struct stmmac_hwtimestamp *ptp;
	const struct stmmac_tc_ops *tc;
	const struct stmmac_mmc_ops *mmc;
	const struct stmmac_est_ops *est;
	struct dw_xpcs *xpcs;
	struct phylink_pcs *lynx_pcs; /* Lynx external PCS */
	struct mii_regs mii;	/* MII register Addresses */
+0 −4
Original line number Diff line number Diff line
@@ -1247,8 +1247,6 @@ const struct stmmac_ops dwmac410_ops = {
	.set_arp_offload = dwmac4_set_arp_offload,
	.config_l3_filter = dwmac4_config_l3_filter,
	.config_l4_filter = dwmac4_config_l4_filter,
	.est_configure = dwmac5_est_configure,
	.est_irq_status = dwmac5_est_irq_status,
	.fpe_configure = dwmac5_fpe_configure,
	.fpe_send_mpacket = dwmac5_fpe_send_mpacket,
	.fpe_irq_status = dwmac5_fpe_irq_status,
@@ -1302,8 +1300,6 @@ const struct stmmac_ops dwmac510_ops = {
	.set_arp_offload = dwmac4_set_arp_offload,
	.config_l3_filter = dwmac4_config_l3_filter,
	.config_l4_filter = dwmac4_config_l4_filter,
	.est_configure = dwmac5_est_configure,
	.est_irq_status = dwmac5_est_irq_status,
	.fpe_configure = dwmac5_fpe_configure,
	.fpe_send_mpacket = dwmac5_fpe_send_mpacket,
	.fpe_irq_status = dwmac5_fpe_irq_status,
+0 −137
Original line number Diff line number Diff line
@@ -573,143 +573,6 @@ int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
	return 0;
}

static int dwmac5_est_write(void __iomem *ioaddr, u32 reg, u32 val, bool gcl)
{
	u32 ctrl;

	writel(val, ioaddr + MTL_EST_GCL_DATA);

	ctrl = (reg << ADDR_SHIFT);
	ctrl |= gcl ? 0 : GCRR;

	writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);

	ctrl |= SRWO;
	writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);

	return readl_poll_timeout(ioaddr + MTL_EST_GCL_CONTROL,
				  ctrl, !(ctrl & SRWO), 100, 5000);
}

int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
			 unsigned int ptp_rate)
{
	int i, ret = 0x0;
	u32 ctrl;

	ret |= dwmac5_est_write(ioaddr, BTR_LOW, cfg->btr[0], false);
	ret |= dwmac5_est_write(ioaddr, BTR_HIGH, cfg->btr[1], false);
	ret |= dwmac5_est_write(ioaddr, TER, cfg->ter, false);
	ret |= dwmac5_est_write(ioaddr, LLR, cfg->gcl_size, false);
	ret |= dwmac5_est_write(ioaddr, CTR_LOW, cfg->ctr[0], false);
	ret |= dwmac5_est_write(ioaddr, CTR_HIGH, cfg->ctr[1], false);
	if (ret)
		return ret;

	for (i = 0; i < cfg->gcl_size; i++) {
		ret = dwmac5_est_write(ioaddr, i, cfg->gcl[i], true);
		if (ret)
			return ret;
	}

	ctrl = readl(ioaddr + MTL_EST_CONTROL);
	ctrl &= ~PTOV;
	ctrl |= ((1000000000 / ptp_rate) * 6) << PTOV_SHIFT;
	if (cfg->enable)
		ctrl |= EEST | SSWL;
	else
		ctrl &= ~EEST;

	writel(ctrl, ioaddr + MTL_EST_CONTROL);

	/* Configure EST interrupt */
	if (cfg->enable)
		ctrl = (IECGCE | IEHS | IEHF | IEBE | IECC);
	else
		ctrl = 0;

	writel(ctrl, ioaddr + MTL_EST_INT_EN);

	return 0;
}

void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev,
			  struct stmmac_extra_stats *x, u32 txqcnt)
{
	u32 status, value, feqn, hbfq, hbfs, btrl;
	u32 txqcnt_mask = (1 << txqcnt) - 1;

	status = readl(ioaddr + MTL_EST_STATUS);

	value = (CGCE | HLBS | HLBF | BTRE | SWLC);

	/* Return if there is no error */
	if (!(status & value))
		return;

	if (status & CGCE) {
		/* Clear Interrupt */
		writel(CGCE, ioaddr + MTL_EST_STATUS);

		x->mtl_est_cgce++;
	}

	if (status & HLBS) {
		value = readl(ioaddr + MTL_EST_SCH_ERR);
		value &= txqcnt_mask;

		x->mtl_est_hlbs++;

		/* Clear Interrupt */
		writel(value, ioaddr + MTL_EST_SCH_ERR);

		/* Collecting info to shows all the queues that has HLBS
		 * issue. The only way to clear this is to clear the
		 * statistic
		 */
		if (net_ratelimit())
			netdev_err(dev, "EST: HLB(sched) Queue 0x%x\n", value);
	}

	if (status & HLBF) {
		value = readl(ioaddr + MTL_EST_FRM_SZ_ERR);
		feqn = value & txqcnt_mask;

		value = readl(ioaddr + MTL_EST_FRM_SZ_CAP);
		hbfq = (value & SZ_CAP_HBFQ_MASK(txqcnt)) >> SZ_CAP_HBFQ_SHIFT;
		hbfs = value & SZ_CAP_HBFS_MASK;

		x->mtl_est_hlbf++;

		/* Clear Interrupt */
		writel(feqn, ioaddr + MTL_EST_FRM_SZ_ERR);

		if (net_ratelimit())
			netdev_err(dev, "EST: HLB(size) Queue %u Size %u\n",
				   hbfq, hbfs);
	}

	if (status & BTRE) {
		if ((status & BTRL) == BTRL_MAX)
			x->mtl_est_btrlm++;
		else
			x->mtl_est_btre++;

		btrl = (status & BTRL) >> BTRL_SHIFT;

		if (net_ratelimit())
			netdev_info(dev, "EST: BTR Error Loop Count %u\n",
				    btrl);

		writel(BTRE, ioaddr + MTL_EST_STATUS);
	}

	if (status & SWLC) {
		writel(SWLC, ioaddr + MTL_EST_STATUS);
		netdev_info(dev, "EST: SWOL has been switched\n");
	}
}

void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
			  bool enable)
{
+0 −51
Original line number Diff line number Diff line
@@ -39,53 +39,6 @@
#define MAC_PPSx_INTERVAL(x)		(0x00000b88 + ((x) * 0x10))
#define MAC_PPSx_WIDTH(x)		(0x00000b8c + ((x) * 0x10))

#define MTL_EST_CONTROL			0x00000c50
#define PTOV				GENMASK(31, 24)
#define PTOV_SHIFT			24
#define SSWL				BIT(1)
#define EEST				BIT(0)

#define MTL_EST_STATUS			0x00000c58
#define BTRL				GENMASK(11, 8)
#define BTRL_SHIFT			8
#define BTRL_MAX			(0xF << BTRL_SHIFT)
#define SWOL				BIT(7)
#define SWOL_SHIFT			7
#define CGCE				BIT(4)
#define HLBS				BIT(3)
#define HLBF				BIT(2)
#define BTRE				BIT(1)
#define SWLC				BIT(0)

#define MTL_EST_SCH_ERR			0x00000c60
#define MTL_EST_FRM_SZ_ERR		0x00000c64
#define MTL_EST_FRM_SZ_CAP		0x00000c68
#define SZ_CAP_HBFS_MASK		GENMASK(14, 0)
#define SZ_CAP_HBFQ_SHIFT		16
#define SZ_CAP_HBFQ_MASK(_val)		({ typeof(_val) (val) = (_val);	\
					((val) > 4 ? GENMASK(18, 16) :	\
					 (val) > 2 ? GENMASK(17, 16) :	\
					 BIT(16)); })

#define MTL_EST_INT_EN			0x00000c70
#define IECGCE				CGCE
#define IEHS				HLBS
#define IEHF				HLBF
#define IEBE				BTRE
#define IECC				SWLC

#define MTL_EST_GCL_CONTROL		0x00000c80
#define BTR_LOW				0x0
#define BTR_HIGH			0x1
#define CTR_LOW				0x2
#define CTR_HIGH			0x3
#define TER				0x4
#define LLR				0x5
#define ADDR_SHIFT			8
#define GCRR				BIT(2)
#define SRWO				BIT(0)
#define MTL_EST_GCL_DATA		0x00000c84

#define MTL_RXP_CONTROL_STATUS		0x00000ca0
#define RXPI				BIT(31)
#define NPE				GENMASK(23, 16)
@@ -149,10 +102,6 @@ int dwmac5_rxp_config(void __iomem *ioaddr, struct stmmac_tc_entry *entries,
int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
			   struct stmmac_pps_cfg *cfg, bool enable,
			   u32 sub_second_inc, u32 systime_flags);
int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
			 unsigned int ptp_rate);
void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev,
			   struct stmmac_extra_stats *x, u32 txqcnt);
void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
			  bool enable);
void dwmac5_fpe_send_mpacket(void __iomem *ioaddr,
Loading