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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
7b78702ed7
@ -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 */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user