Commit 7b78702e authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'stmmac-EST-interrupts-and-ethtool'



Mohammad Athari Bin Ismail says:

====================
net: stmmac: EST interrupts and ethtool

This patchset adds support for handling EST interrupts and reporting EST
errors. Additionally, the errors are added into ethtool statistic.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 09bef832 9f298959
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -182,6 +182,12 @@ struct stmmac_extra_stats {
	/* TSO */
	unsigned long tx_tso_frames;
	unsigned long tx_tso_nfrags;
	/* EST */
	unsigned long mtl_est_cgce;
	unsigned long mtl_est_hlbs;
	unsigned long mtl_est_hlbf;
	unsigned long mtl_est_btre;
	unsigned long mtl_est_btrlm;
};

/* Safety Feature statistics exposed by ethtool */
+86 −0
Original line number Diff line number Diff line
@@ -595,9 +595,95 @@ int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
		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)
{
+32 −0
Original line number Diff line number Diff line
@@ -38,6 +38,36 @@
#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
@@ -111,6 +141,8 @@ int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
			   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);

+4 −0
Original line number Diff line number Diff line
@@ -393,6 +393,8 @@ struct stmmac_ops {
	void (*set_arp_offload)(struct mac_device_info *hw, bool en, u32 addr);
	int (*est_configure)(void __iomem *ioaddr, struct stmmac_est *cfg,
			     unsigned int ptp_rate);
	void (*est_irq_status)(void __iomem *ioaddr, struct net_device *dev,
			       struct stmmac_extra_stats *x, u32 txqcnt);
	void (*fpe_configure)(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
			      bool enable);
};
@@ -491,6 +493,8 @@ struct stmmac_ops {
	stmmac_do_void_callback(__priv, mac, set_arp_offload, __args)
#define stmmac_est_configure(__priv, __args...) \
	stmmac_do_callback(__priv, mac, est_configure, __args)
#define stmmac_est_irq_status(__priv, __args...) \
	stmmac_do_void_callback(__priv, mac, est_irq_status, __args)
#define stmmac_fpe_configure(__priv, __args...) \
	stmmac_do_void_callback(__priv, mac, fpe_configure, __args)

+6 −0
Original line number Diff line number Diff line
@@ -158,6 +158,12 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
	/* TSO */
	STMMAC_STAT(tx_tso_frames),
	STMMAC_STAT(tx_tso_nfrags),
	/* EST */
	STMMAC_STAT(mtl_est_cgce),
	STMMAC_STAT(mtl_est_hlbs),
	STMMAC_STAT(mtl_est_hlbf),
	STMMAC_STAT(mtl_est_btre),
	STMMAC_STAT(mtl_est_btrlm),
};
#define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)

Loading