summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2025-04-23 14:35:12 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:26:32 +0300
commit1f00c201e6e9b133daf85002c6526a376d7809f1 (patch)
treefc3d681c54db21a7ae3f6d0302a80271e2742286
parentf150ff58bac9a045d9f4b2459e8883992b206559 (diff)
downloadlinux-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.h36
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c76
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)