diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2025-08-20 15:03:46 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:29:52 +0300 |
| commit | b3e0ead2417a30df046b237e7fc6959976f97541 (patch) | |
| tree | cbde9fcba97d41349e2e1d21fdd4c1fe467fc5cf | |
| parent | 5b30901e83d34769a3e59fdfde75cb4eb50fb554 (diff) | |
| download | linux-b3e0ead2417a30df046b237e7fc6959976f97541.tar.gz linux-b3e0ead2417a30df046b237e7fc6959976f97541.zip | |
net: stmmac: dwmac1000: Collect DMA missing frames statistics
DW GMACs have been supporting the missing frames (due to Rx buffer
unavailable or MTL FIFO overflow events) statistics from very initial
controller release. It has been implemented in the same way as can be
found on the even older DW MAC100 devices. It isn't clear why the support
hasn't been added to the driver for both versions of the controller
together, but let's fix that flaw especially seeing the counters are
exceptionally useful on the interface performance debugging. The solution
is to just reuse the already implemented dwmac100_dma_diagnostic_fr()
method for DW GMACs too by moving the function to the dwmac_lib.c module.
Note the change also fixes the counter data missing after overflows.
Indeed the former dwmac_dma_diagnostic_fr() method didn't add the current
counters value if the counters overflow had happened. It's wrong since the
counters will continue to be incremented even after that. In the meantime
reading the CSR will erase the current values from the CSR.
Fixes: 1c901a46d576 ("stmmac: add MMC support exported via ethtool (v3)")
Fixes: 47dd7a540b8a ("net: add support for STMicroelectronics Ethernet controllers.")
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac100.h | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 28 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 9 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 19 |
5 files changed, 30 insertions, 33 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h index 547863cb982f..576cbf766cc1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h @@ -68,12 +68,6 @@ enum ttc_control { DMA_CONTROL_OSF = 0x00000004, /* Operate On 2nd Frame */ }; -/* STMAC110 DMA Missed Frame Counter register defines */ -#define DMA_MISSED_FRAME_OVE 0x10000000 /* FIFO Overflow Overflow */ -#define DMA_MISSED_FRAME_OVE_CNTR 0x0ffe0000 /* Overflow Frame Counter */ -#define DMA_MISSED_FRAME_OVE_M 0x00010000 /* Missed Frame Overflow */ -#define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */ - extern const struct stmmac_dma_ops dwmac100_dma_ops; #endif /* __DWMAC100_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index 3ac7a7949529..a4b5b1a51f0a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -259,6 +259,7 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = { .dump_regs = dwmac1000_dump_dma_regs, .dma_rx_mode = dwmac1000_dma_operation_mode_rx, .dma_tx_mode = dwmac1000_dma_operation_mode_tx, + .dma_diagnostic_fr = dwmac_dma_diagnostic_fr, .enable_dma_transmission = dwmac_enable_dma_transmission, .enable_dma_reception = dwmac_enable_dma_reception, .enable_dma_irq = dwmac_enable_dma_irq, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index 0acdf3e23ac1..093d09267e38 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c @@ -82,32 +82,6 @@ static void dwmac100_dump_dma_regs(struct stmmac_priv *priv, readl(ioaddr + DMA_CUR_RX_BUF_ADDR); } -/* DMA controller has two counters to track the number of the missed frames. */ -static void dwmac100_dma_diagnostic_fr(struct stmmac_priv *priv, - void __iomem *ioaddr, - struct stmmac_extra_stats *x, - u32 chan) -{ - u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR); - - if (unlikely(csr8)) { - if (csr8 & DMA_MISSED_FRAME_OVE) { - x->rx_overflow_cntr += 0x800; - } else { - unsigned int ove_cntr; - ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17); - x->rx_overflow_cntr += ove_cntr; - } - - if (csr8 & DMA_MISSED_FRAME_OVE_M) { - x->rx_missed_cntr += 0xffff; - } else { - unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR); - x->rx_missed_cntr += miss_f; - } - } -} - const struct stmmac_dma_ops dwmac100_dma_ops = { .reset = dwmac_dma_reset, .init = dwmac100_dma_init, @@ -115,7 +89,7 @@ const struct stmmac_dma_ops dwmac100_dma_ops = { .init_tx_chan = dwmac100_dma_init_tx, .dump_regs = dwmac100_dump_dma_regs, .dma_tx_mode = dwmac100_dma_operation_mode_tx, - .dma_diagnostic_fr = dwmac100_dma_diagnostic_fr, + .dma_diagnostic_fr = dwmac_dma_diagnostic_fr, .enable_dma_transmission = dwmac_enable_dma_transmission, .enable_dma_irq = dwmac_enable_dma_irq, .disable_dma_irq = dwmac_disable_dma_irq, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index 79c4eb8f42d4..a4e034c9fecf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -119,9 +119,16 @@ static inline u32 dma_chan_base_addr(u32 base, u32 chan) #define DMA_CHAN_STATUS(chan) dma_chan_base_addr(DMA_STATUS, chan) #define DMA_CHAN_CONTROL(chan) dma_chan_base_addr(DMA_CONTROL, chan) #define DMA_CHAN_INTR_ENA(chan) dma_chan_base_addr(DMA_INTR_ENA, chan) +#define DMA_CHAN_MISSED_FRAME_CTR(chan) \ + dma_chan_base_addr(DMA_MISSED_FRAME_CTR, chan) #define DMA_CHAN_RX_WATCHDOG(chan) \ dma_chan_base_addr(DMA_RX_WATCHDOG, chan) +/* DMA Missed Frame Counter */ +#define DMA_MISSED_FRAME_OVFCNTOVF BIT(28) +#define DMA_MISSED_FRAME_OVFFRMCNT GENMASK(27, 17) +#define DMA_MISSED_FRAME_MISCNTOVF BIT(16) +#define DMA_MISSED_FRAME_MISFRMCNT GENMASK(15, 0) /* Rx watchdog register */ #define DMA_RX_WATCHDOG 0x00001024 @@ -162,6 +169,8 @@ void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan); int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, struct stmmac_extra_stats *x, u32 chan, u32 dir); +void dwmac_dma_diagnostic_fr(struct stmmac_priv *priv, void __iomem *ioaddr, + struct stmmac_extra_stats *x, u32 chan); int dwmac_dma_reset(void __iomem *ioaddr); #endif /* __DWMAC_DMA_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index 64e43adc51a6..75dd1d370f64 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -246,6 +246,25 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, return ret; } +void dwmac_dma_diagnostic_fr(struct stmmac_priv *priv, void __iomem *ioaddr, + struct stmmac_extra_stats *x, u32 chan) +{ + u32 csr8 = readl(ioaddr + DMA_CHAN_MISSED_FRAME_CTR(chan)); + unsigned long cntr; + + cntr = FIELD_GET(DMA_MISSED_FRAME_OVFFRMCNT, csr8); + if (csr8 & DMA_MISSED_FRAME_OVFCNTOVF) + cntr += FIELD_MAX(DMA_MISSED_FRAME_OVFFRMCNT) + 1; + + x->rx_overflow_cntr += cntr; + + cntr = FIELD_GET(DMA_MISSED_FRAME_MISFRMCNT, csr8); + if (csr8 & DMA_MISSED_FRAME_MISCNTOVF) + cntr += FIELD_MAX(DMA_MISSED_FRAME_MISFRMCNT) + 1; + + x->rx_missed_cntr += cntr; +} + void stmmac_set_mac_addr(void __iomem *ioaddr, const u8 addr[6], unsigned int high, unsigned int low) { |
