diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2025-04-23 14:35:12 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:26:32 +0300 |
| commit | 1f00c201e6e9b133daf85002c6526a376d7809f1 (patch) | |
| tree | fc3d681c54db21a7ae3f6d0302a80271e2742286 | |
| parent | f150ff58bac9a045d9f4b2459e8883992b206559 (diff) | |
| download | linux-1f00c201e6e9b133daf85002c6526a376d7809f1.tar.gz linux-1f00c201e6e9b133daf85002c6526a376d7809f1.zip | |
net: stmmac: dwxgmac2: Collect Rx-frames statistics
DW XGMAC2 write-back Receive DMA-descriptors contains some info about the
received payload frame. In particular it's:
1. error conditions
2. level 2 frame type
3. level 3 packet type
4. filters status
Let's use that info to collect the controller-specific statistics as it's
done in the DW GMAC and DW QoE Ether sub-modules.
Note alas the write-back Transmit DMA-descriptors don't provide even the
error-status data. That's why the change concerns the Rx DMA-descriptors
only.
Also note this may worsens the iperf3 results a bit on the systems with
quite weak CPU and system bus performance. Our DW XGMAC lost up to 50-70
Mbit/s due to the additional DMA-descriptors parsing.
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 36 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c | 76 |
2 files changed, 108 insertions, 4 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index eb6c9bab94cb..b8b3a0519484 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -460,6 +460,13 @@ #define XGMAC_TDES3_VLTV BIT(16) #define XGMAC_TDES3_VT GENMASK(15, 0) #define XGMAC_TDES3_FL GENMASK(14, 0) +#define XGMAC_RDES2_L4FM BIT(28) +#define XGMAC_RDES2_L3FM BIT(27) +#define XGMAC_RDES2_MADRM GENMASK(26, 19) +#define XGMAC_RDES2_HF BIT(18) +#define XGMAC_RDES2_DAF BIT(17) +#define XGMAC_RDES2_SAF BIT(16) +#define XGMAC_RDES2_VF BIT(15) #define XGMAC_RDES2_HL GENMASK(9, 0) #define XGMAC_RDES3_OWN BIT(31) #define XGMAC_RDES3_CTXT BIT(30) @@ -468,11 +475,38 @@ #define XGMAC_RDES3_CDA BIT(27) #define XGMAC_RDES3_RSV BIT(26) #define XGMAC_RDES3_L34T GENMASK(23, 20) -#define XGMAC_RDES3_ET_LT GENMASK(19, 16) #define XGMAC_L34T_IP4TCP 0x1 #define XGMAC_L34T_IP4UDP 0x2 +#define XGMAC_L34T_IP4ICMP 0x3 +#define XGMAC_L34T_IP4IGMP 0x4 +#define XGMAC_L34T_IP4UNKNOWN 0x7 #define XGMAC_L34T_IP6TCP 0x9 #define XGMAC_L34T_IP6UDP 0xA +#define XGMAC_L34T_IP6ICMP 0xB +#define XGMAC_L34T_IP6UNKNOWN 0xF +#define XGMAC_RDES3_ET_LT GENMASK(19, 16) +#define XGMAC_ET_RECEIVE_WATCHDOG 1 +#define XGMAC_ET_XGMII_ERROR 2 +#define XGMAC_ET_CRC_ERROR 3 +#define XGMAC_ET_GIANT_PACKET 4 +#define XGMAC_ET_IP_HDR_ERROR 5 +#define XGMAC_ET_IP_PAYLOAD_ERROR 6 +#define XGMAC_ET_OVERFLOW_ERROR 7 +#define XGMAC_ET_DESC_ERROR 8 +#define XGMAC_L2T_LENGTH_PACKET 0 +#define XGMAC_L2T_MAC_CONTROL 1 +#define XGMAC_L2T_DCB_CONTROL 2 +#define XGMAC_L2T_ARP_REQUEST 3 +#define XGMAC_L2T_OAM_PACKET 4 +#define XGMAC_L2T_CUSTOM_TYPE 5 +#define XGMAC_L2T_AV_CONTROL 6 +#define XGMAC_L2T_OTHER_TYPE 7 +#define XGMAC_L2T_VLAN_STAG 8 +#define XGMAC_L2T_VLAN_CTAG 9 +#define XGMAC_L2T_DVLAN_CCTAG 10 +#define XGMAC_L2T_DVLAN_SSTAG 11 +#define XGMAC_L2T_DVLAN_SCTAG 12 +#define XGMAC_L2T_DVLAN_CSTAG 13 #define XGMAC_RDES3_ES BIT(15) #define XGMAC_RDES3_PL GENMASK(13, 0) #define XGMAC_RDES3_TSD BIT(6) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c index 11c68c05d9b8..7a32fc8018cf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c @@ -26,7 +26,10 @@ static int dwxgmac2_get_tx_status(struct stmmac_extra_stats *x, static int dwxgmac2_get_rx_status(struct stmmac_extra_stats *x, struct dma_desc *p) { + u32 rdes2 = le32_to_cpu(p->des2); u32 rdes3 = le32_to_cpu(p->des3); + int ret = good_frame; + int l34t; if (unlikely(rdes3 & XGMAC_RDES3_OWN)) return dma_own; @@ -34,10 +37,77 @@ static int dwxgmac2_get_rx_status(struct stmmac_extra_stats *x, return discard_frame; if (likely(!(rdes3 & XGMAC_RDES3_LD))) return rx_not_ls; - if (unlikely((rdes3 & XGMAC_RDES3_ES) && (rdes3 & XGMAC_RDES3_LD))) - return discard_frame; - return good_frame; + if (likely(!(rdes3 & XGMAC_RDES3_ES))) { + int l2t = FIELD_GET(XGMAC_RDES3_ET_LT, rdes3); + + switch (l2t) { + case XGMAC_L2T_AV_CONTROL: + x->av_pkt_rcvd++; + break; + case XGMAC_L2T_VLAN_STAG ... XGMAC_L2T_DVLAN_CSTAG: + x->rx_vlan++; + break; + } + } else { + int et = FIELD_GET(XGMAC_RDES3_ET_LT, rdes3); + + switch (et) { + case XGMAC_ET_RECEIVE_WATCHDOG: + x->rx_watchdog++; + break; + case XGMAC_ET_XGMII_ERROR: + x->rx_mii++; + break; + case XGMAC_ET_CRC_ERROR: + x->rx_crc_errors++; + break; + case XGMAC_ET_GIANT_PACKET: + x->rx_length++; + break; + case XGMAC_ET_IP_HDR_ERROR: + x->ip_hdr_err++; + break; + case XGMAC_ET_IP_PAYLOAD_ERROR: + x->ip_payload_err++; + break; + case XGMAC_ET_OVERFLOW_ERROR: + x->rx_gmac_overflow++; + break; + case XGMAC_ET_DESC_ERROR: + x->rx_desc++; + break; + } + + ret = discard_frame; + } + + l34t = FIELD_GET(XGMAC_RDES3_L34T, rdes3); + + switch (l34t) { + case XGMAC_L34T_IP4TCP ... XGMAC_L34T_IP4IGMP: + case XGMAC_L34T_IP4UNKNOWN: + x->ipv4_pkt_rcvd++; + break; + case XGMAC_L34T_IP6TCP ... XGMAC_L34T_IP6ICMP: + case XGMAC_L34T_IP6UNKNOWN: + x->ipv6_pkt_rcvd++; + break; + } + + if (unlikely(rdes2 & XGMAC_RDES2_SAF)) + x->sa_rx_filter_fail++; + + if (unlikely(rdes2 & XGMAC_RDES2_DAF)) + x->da_rx_filter_fail++; + + if (unlikely(rdes2 & XGMAC_RDES2_L3FM)) + x->l3_filter_match++; + + if (unlikely(rdes2 & XGMAC_RDES2_L4FM)) + x->l4_filter_match++; + + return ret; } static int dwxgmac2_get_tx_len(struct dma_desc *p) |
