Skip to content

Commit

Permalink
Merge branch 'stmmac-EST-interrupts-and-ethtool'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 18, 2021
2 parents 09bef83 + 9f29895 commit 7b78702
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 0 deletions.
6 changes: 6 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
86 changes: 86 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac5.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
32 changes: 32 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac5.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/hwif.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand Down Expand Up @@ -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)

Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4314,6 +4314,10 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
if (stmmac_safety_feat_interrupt(priv))
return IRQ_HANDLED;

if (priv->dma_cap.estsel)
stmmac_est_irq_status(priv, priv->ioaddr, priv->dev,
&priv->xstats, tx_cnt);

/* To handle GMAC own interrupts */
if ((priv->plat->has_gmac) || xmac) {
int status = stmmac_host_irq_status(priv, priv->hw, &priv->xstats);
Expand Down

0 comments on commit 7b78702

Please sign in to comment.