From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from PH7PR06CU001.outbound.protection.outlook.com (mail-westus3azon11010025.outbound.protection.outlook.com [52.101.201.25]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F06ED3E6DFA; Tue, 6 Oct 2026 11:06:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.201.25 ARC-Seal:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791284800; cv=fail; b=Z3fuudulwW4BFgZr77jN81p8M93gWWLCMOETIhyBfdxOBuA9j/EiOsXlBbJr/upyv96nvH1HKcTBtlWL30kuRtaXkFLi8mgHLr6N+cVpEfjfYc4I/gmVSZlzJSzhxqIh2zeDy6DfkLDDkvk8dlZYURir8qXMOqAEKNE09PH587I= ARC-Message-Signature:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791284800; c=relaxed/simple; bh=KzlYvkpX4aEODvZ26tVslRGHWIXqyn4BpwGsRO6ZVgI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DdE330mZj6K949LxHCYq6fjsfGvRYZOGFT7e022bGX8cH516olmPAhVRfX62GqjzDGYRXVqHZdVmTZq3/CbWZ3EMhQYTRe83IMM9utYarOxlQLT2STedzqh9OUChE8XN7a6ZVDpWVgarwwu91J+HU4DzIIRfmQHAj7WEMa2gIRo= ARC-Authentication-Results:i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=vfwIAaY+; arc=fail smtp.client-ip=52.101.201.25 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="vfwIAaY+" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=gOK5GFvW/2RrWQK+NfOAB5Y9kmbbDm3ljn9GsDhxkR6Q1zCHdF1fX5CaQic4D0P32MMX0WrLyzdUFLOreDrFv+Lpw1AUPsLeI5mA69mlFMxUxUL6l9oYjFLDCsoOr7dh3c6cCoQzipJZcaZEX7PiZScjzuG4iTKPSdQZjACIbunkxrQJbIb+V8/k4pksTNITwQnreBZtGPJ7Bm7jB4tMMcDJi7cVo1YQGY9o7pFaoT7UtZwLX4hnJ+nuVXxwRO/kULtHm4gIQ280mMoUW0G+gtQx/eytJI0oKJU93LXXuNMwOcWUe5XUdKac0PJ+ATrLskYav2Vh6W64KAO8+jiFVg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=PXkpkA6GWhGK97eKJ0WCsKMVQVfrjj3dFUHF7nVSfi4=; b=BmjYUv42Yx+DCMBG2pUhQnTpwD5rY3D1KZDG2eoqO6x7AS72KTYyrHBZeYG4yEImmJ4sYm/fpKu6irMecQ55P5i8ZoqqogLaTokW+erue5usZ7hmZk/867jKF4nhZ1974F9oe5uW6LATI3csFGrobPdIoob8m0pxtGZgFuJM/mdJwWQB5o1nuIcH0b+bHizNuch7CsYEFo8Jz0DEjFiUMDhaX6UfcCgFdbOcggRlLHqQIHTgaodaoZgi12OOxDW2E0XuVrw77kQHPBYN8uioMxW5+orj+UdMnF3DOzdJiUdrj2Keim04SS0W9xAqQEvsv8SYPPQSZUiSoNhPkL05AQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=lunn.ch smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=PXkpkA6GWhGK97eKJ0WCsKMVQVfrjj3dFUHF7nVSfi4=; b=vfwIAaY+UiyL6FTzeAvlaxNmqs8I9zSXVwaVx9hXb6VrHkALCKv9HOIc6xU2jt9E1rzmQjvKwthJlHnGix/Pr/vYX6/XDBVpe81XRcYgczbw1Hhk6SMq9Byddj74UwlDYzHsXsLqNT012OdqEGVY7BSnny6jL20o6A67CSvMYCc= Received: from BN9P221CA0020.NAMP221.PROD.OUTLOOK.COM (2603:10b6:408:10a::32) by CH3PR12MB7668.namprd12.prod.outlook.com (2603:10b6:610:14d::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.451.26; Tue, 6 Oct 2026 11:06:28 +0000 Received: from IA0PEPF00000040.namprd04.prod.outlook.com (2603:10b6:408:10a:cafe::27) by BN9P221CA0020.outlook.office365.com (2603:10b6:408:10a::32) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.472.20 via Frontend Transport; Tue, 6 Oct 2026 11:06:26 +0000 X-MS-Exchange-Authentication-Results: mx.microsoft.com 1; spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb07.amd.com; pr=C Received: from satlexmb07.amd.com (165.204.84.17) by IA0PEPF00000040.mail.protection.outlook.com (10.167.249.168) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.496.14 via Frontend Transport; Tue, 6 Oct 2026 11:06:26 +0000 Received: from Satlexmb09.amd.com (10.181.42.218) by satlexmb07.amd.com (10.181.42.216) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 6 Oct 2026 06:06:23 -0500 Received: from satlexmb08.amd.com (10.181.42.217) by satlexmb09.amd.com (10.181.42.218) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 6 Oct 2026 06:06:20 -0500 Received: from xhdsuragupt40.xilinx.com (10.180.168.240) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 6 Oct 2026 06:06:16 -0500 From: Suraj Gupta To: Radhey Shyam Pandey , Andrew Lunn , "David S . Miller" , "Eric Dumazet" , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: Michal Simek , Russell King , , , , Subject: [PATCH net-next v4 6/6] net: xilinx: axienet: Add statistics support for XXV ethernet Date: Tue, 6 Oct 2026 16:35:50 +0530 Message-ID: <20261006110550.1990213-7-suraj.gupta2@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20261006110550.1990213-1-suraj.gupta2@amd.com> References: <20261006110550.1990213-1-suraj.gupta2@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: IA0PEPF00000040:EE_|CH3PR12MB7668:EE_ X-MS-Office365-Filtering-Correlation-Id: ae66488a-23a6-4260-8653-08df2399dde8 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|82310400026|1800799024|7416014|23010399003|36860700016|3023799007|56012099006|10063799003|6133799003|11063799006|10067099003|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: RKGuwM6h0QtP4a2+6zJwxdjele/12YsgTUbvHiWnKcXMBDkcSQsfnyDujQJ2whWS5MNMzQHYePoJTDRWr3wiDeNx5qXi5YRcUxzHRJWAEpsnOnJvPF3k8I/AbbN/byTAr3cNOWyaiAtySbRFgteyM86d/8jMxdk0MAVpDDonSSN6+jXvJzMauwpPYa76tSN6O8ORcf8BU9XGJU3VsNbTJrGQtmwWHCpaGwRwdOtJEMfnzf07O92teqDA41GJE07fIOroLv9G83762KpcqJcYpVWWZHDqd5CAE21CzxDKNlhK2sXgToSUr6HL0mKMznBCFtDKDr61JxJTkzooqfUMonT4zZy5Yz6RH3xpOwKAJW5Urc2QErdoA8TN6FHe5jChmwtAHw5hGA9BRHrp96r0A5Y4X6pvnVXCEKVAiWrgTbdkxX+KSNTNijYLCZKABnavd+q0XT/MhFmxpXUo7MTkgpYRJo9vKe9W7DUA0j5fdkhfb6U/cpbKkNxlNim2eAnzrXCeQRKTDFMkU2bWgoqr0uVWfba0Ea5VJZofY9kDt/srhkaegHeFyWQx2+gdQrSIvpo3OvsUPMQMBdl/chvARcn8YTIdNvt5JV1Y5qJmd5GjiAtR6eWhV6UCgY1DgWnwY2gYTjrFrENoxpxbxKjVGJ8Euagd/Il7ikBtzOtEYu1sLreBUK0tfYb2qduTmRsjlCB0PPcQl0uyKxt5lsD96w== X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:satlexmb07.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(376014)(82310400026)(1800799024)(7416014)(23010399003)(36860700016)(3023799007)(56012099006)(10063799003)(6133799003)(11063799006)(10067099003)(18002099003)(22082099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: dMH7OqkiOyW7ntDEtlF2L0bXcnYoidedHvShEBjZexT6FD7/J13E4nzpgxNGBBgXciuGo/dlIZ8Xq7cDyi8CGgdqwGMP408hOxzSOQY9kTDQ+jOHxiQBCFwOEGh/l1lFxwZdin98yQSFLsxGQsKIQYUCAZmfSE+2RcLDzSKWoUy4nMmRxs9+G/Jqfrr4H9x37Fc4aag/2Xvjv/a9TydkaAS7yLKa6k3lZSZb+ObsMdx/BCngWaEuHrBvD1JpRLSW3ruTmOmJw0ZSOSa/vx5vWeclGlj0ETTAInewwKx6Ee6Jvh5TI+jUel/2Z6F3tO6MUa6BTywvAxjpGc5GSmoBJTJFKCee+k39iJSEpD0otb6KAasWN0S7HqWiqLNcf5Vz3HIOwk6TQAiqLPDVG7iwrW3W+ehCZfTLlPpRzgnB268l+RFTkNSL9SWfJJW5XxqT X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Oct 2026 11:06:26.9428 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: ae66488a-23a6-4260-8653-08df2399dde8 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[satlexmb07.amd.com] X-MS-Exchange-CrossTenant-AuthSource: IA0PEPF00000040.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH3PR12MB7668 The XXV ethernet exposes a dedicated statistics block whose counters are clear-on-tick (PG210): writing TICK_REG latches the internal accumulators into the readable registers and clears them, so each post-TICK read yields the count for the interval since the previous TICK. Software accumulates those intervals, so no last-counter delta (as used by the 1G MAC) is needed. Feed both ndo_get_stats64() and the ethtool statistics (-S, pause, MAC and RMON) from this accumulator path through the axienet_config statistics ops. MAC control statistics stay unsupported as the hardware exposes no matching counters. Signed-off-by: Suraj Gupta --- drivers/net/ethernet/xilinx/xilinx_axienet.h | 2 + .../net/ethernet/xilinx/xilinx_axienet_main.c | 24 +- .../net/ethernet/xilinx/xilinx_axienet_xxv.c | 269 ++++++++++++++++++ .../net/ethernet/xilinx/xilinx_axienet_xxv.h | 55 ++++ 4 files changed, 348 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index 7ba2fe29e97b..e8e9732c1c84 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -549,6 +549,7 @@ struct skbuf_dma_descriptor { * @rx_ring_head: RX skb ring buffer head index. * @rx_ring_tail: RX skb ring buffer tail index. * @xxv_ip_version: XXV IP version. + * @xxv_stat_base: Software accumulators for the XXV clear-on-tick counters. * @axienet_config: MAC-type specific configuration and operations. */ struct axienet_local { @@ -603,6 +604,7 @@ struct axienet_local { u64 hw_stat_base[STAT_COUNT]; u32 hw_last_counter[STAT_COUNT]; + u64 xxv_stat_base[XXV_STAT_COUNT]; seqcount_mutex_t hw_stats_seqcount; struct mutex stats_lock; struct delayed_work stats_work; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index d0aa768452ea..0ba0d286350e 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -593,7 +593,11 @@ static void axienet_refresh_stats(struct work_struct *work) mutex_unlock(&lp->stats_lock); } - /* Just less than 2^32 bytes at 2.5 GBit/s */ + /* Re-arm the poll before any counter can overflow between updates: the + * 1G byte counter reaches just under 2^32 in this interval at 2.5 Gbit/s, + * and the XXV internal accumulators must be latched (via TICK in + * axienet_xxv_stats_update()) before they saturate at line rate. + */ schedule_delayed_work(&lp->stats_work, 13 * HZ); } @@ -602,7 +606,16 @@ static int __axienet_device_reset(struct axienet_local *lp) u32 value; int ret; - /* Save statistics counters in case they will be reset */ + /* Save statistics counters in case they will be reset. + * + * The XAE_FEATURE_STATS blocks in this function read the TEMAC + * statistics registers at XAE_STATS_OFFSET, i.e. they assume the 1G + * counter layout. This is safe because __axienet_device_reset() is + * only reached on the non-dmaengine path, which the + * non_dmaengine capability restricts to the 1G MAC. MACs that use their + * own statistics mechanism (e.g. XXV, which is dmaengine-only) never + * execute this path. + */ mutex_lock(&lp->stats_lock); if (lp->features & XAE_FEATURE_STATS) axienet_stats_update(lp, true); @@ -1785,6 +1798,13 @@ static int axienet_stop(struct net_device *ndev) lp->axienet_config->setoptions(ndev, lp->options & ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); + /* Final snapshot after RX/TX is disabled, so no frames are missed. */ + if (lp->axienet_config->stats_update) { + mutex_lock(&lp->stats_lock); + lp->axienet_config->stats_update(lp); + mutex_unlock(&lp->stats_lock); + } + if (!lp->use_dmaengine) { axienet_dma_stop(lp); cancel_work_sync(&lp->dma_err_task); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_xxv.c b/drivers/net/ethernet/xilinx/xilinx_axienet_xxv.c index 9f7efab84f82..4a2d03b6c480 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_xxv.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_xxv.c @@ -8,9 +8,11 @@ #include #include #include +#include #include #include #include +#include #include "xilinx_axienet.h" #include "xilinx_axienet_xxv.h" @@ -95,6 +97,69 @@ static struct axienet_option xxvenet_options[] = { {} }; +/* PG210 statistics-block offsets indexed by enum xxv_stat. Each entry is + * the 32-bit LSB register address; the corresponding MSB is at +4. + */ +static const u32 axienet_xxv_stat_offsets[XXV_STAT_COUNT] = { + [XXV_STAT_RX_TOTAL_PACKETS] = XXV_STAT_RX_TOTAL_PACKETS_OFFSET, + [XXV_STAT_RX_TOTAL_GOOD_PACKETS] = XXV_STAT_RX_TOTAL_GOOD_PACKETS_OFFSET, + [XXV_STAT_RX_TOTAL_BYTES] = XXV_STAT_RX_TOTAL_BYTES_OFFSET, + [XXV_STAT_RX_TOTAL_GOOD_BYTES] = XXV_STAT_RX_TOTAL_GOOD_BYTES_OFFSET, + [XXV_STAT_RX_BAD_FCS] = XXV_STAT_RX_BAD_FCS_OFFSET, + [XXV_STAT_RX_INRANGEERR] = XXV_STAT_RX_INRANGEERR_OFFSET, + [XXV_STAT_RX_MULTICAST] = XXV_STAT_RX_MULTICAST_OFFSET, + [XXV_STAT_RX_BROADCAST] = XXV_STAT_RX_BROADCAST_OFFSET, + [XXV_STAT_RX_UNDERSIZE] = XXV_STAT_RX_UNDERSIZE_OFFSET, + [XXV_STAT_RX_FRAGMENT] = XXV_STAT_RX_FRAGMENT_OFFSET, + [XXV_STAT_RX_JABBER] = XXV_STAT_RX_JABBER_OFFSET, + [XXV_STAT_RX_OVERSIZE] = XXV_STAT_RX_OVERSIZE_OFFSET, + [XXV_STAT_RX_PAUSE] = XXV_STAT_RX_PAUSE_OFFSET, + [XXV_STAT_TX_TOTAL_PACKETS] = XXV_STAT_TX_TOTAL_PACKETS_OFFSET, + [XXV_STAT_TX_TOTAL_GOOD_PACKETS] = XXV_STAT_TX_TOTAL_GOOD_PACKETS_OFFSET, + [XXV_STAT_TX_TOTAL_BYTES] = XXV_STAT_TX_TOTAL_BYTES_OFFSET, + [XXV_STAT_TX_TOTAL_GOOD_BYTES] = XXV_STAT_TX_TOTAL_GOOD_BYTES_OFFSET, + [XXV_STAT_TX_BAD_FCS] = XXV_STAT_TX_BAD_FCS_OFFSET, + [XXV_STAT_TX_FRAME_ERROR] = XXV_STAT_TX_FRAME_ERROR_OFFSET, + [XXV_STAT_TX_MULTICAST] = XXV_STAT_TX_MULTICAST_OFFSET, + [XXV_STAT_TX_BROADCAST] = XXV_STAT_TX_BROADCAST_OFFSET, + [XXV_STAT_TX_PAUSE] = XXV_STAT_TX_PAUSE_OFFSET, +}; + +/* XXV (PG210) counters exposed via ethtool -S. Only counters that have no + * standard uAPI are listed here; the totals include errored frames, so they + * are distinct from the good-frame counts in rtnl_link_stats64 and the + * IEEE MAC statistics. Every other XXV counter is reported through the + * dedicated stats64, pause, MAC and RMON callbacks instead. + */ +static const enum xxv_stat axienet_xxv_priv_stats[] = { + XXV_STAT_RX_TOTAL_PACKETS, + XXV_STAT_RX_TOTAL_BYTES, + XXV_STAT_TX_TOTAL_PACKETS, + XXV_STAT_TX_TOTAL_BYTES, + XXV_STAT_TX_BAD_FCS, + XXV_STAT_TX_FRAME_ERROR, +}; + +static const char axienet_xxv_ethtool_stats_strings[][ETH_GSTRING_LEN] = { + "RX Total Packets", + "RX Total Bytes", + "TX Total Packets", + "TX Total Bytes", + "TX Bad FCS", + "TX Frame Error", +}; + +static u64 axienet_xxv_read_counter(struct axienet_local *lp, enum xxv_stat stat) +{ + u32 off = axienet_xxv_stat_offsets[stat]; + u32 lsb, msb; + + lsb = axienet_ior(lp, off); + msb = axienet_ior(lp, off + XXV_STAT_MSB_OFFSET); + + return ((u64)msb << 32) | lsb; +} + static bool axienet_xxv_ip_has_gtwiz_status(u32 ip_version) { u8 minor = FIELD_GET(XXV_MIN_MASK, ip_version); @@ -134,6 +199,10 @@ static void axienet_xxv_setoptions(struct net_device *ndev, u32 options) static void axienet_xxv_probe_init(struct axienet_local *lp) { lp->xxv_ip_version = axienet_ior(lp, XXV_CONFIG_REVISION); + lp->features |= XAE_FEATURE_STATS; + + /* Throwaway tick to drain pre-open counts so stats start from zero. */ + axienet_iow(lp, XXV_TICKREG_OFFSET, XXV_TICKREG_STATEN_MASK); } /** @@ -308,6 +377,198 @@ static int axienet_10g25g_clk_init(struct axienet_local *lp) return 0; } +/** + * axienet_xxv_stats_update - Latch and accumulate XXV hardware counters + * @lp: Pointer to the axienet_local structure + * + * The XXV statistics counters are clear-on-tick (PG210): writing TICK_REG + * latches the internal accumulators into the readable STAT_*_LSB/MSB registers + * and clears the internal accumulators. Each post-TICK read therefore returns + * the count for the interval since the previous TICK, so software accumulates + * those intervals into lp->xxv_stat_base. A last-counter delta (as used by the + * free-running 1G MAC path) is not needed. + */ +static void axienet_xxv_stats_update(struct axienet_local *lp) +{ + u64 counter[XXV_STAT_COUNT]; + enum xxv_stat stat; + + /* Latch the clear-on-tick snapshot and read the counters outside the + * seqcount write section, so only the accumulator updates run inside it + * and the reader retry window stays short. + */ + axienet_iow(lp, XXV_TICKREG_OFFSET, XXV_TICKREG_STATEN_MASK); + for (stat = 0; stat < XXV_STAT_COUNT; stat++) + counter[stat] = axienet_xxv_read_counter(lp, stat); + + write_seqcount_begin(&lp->hw_stats_seqcount); + for (stat = 0; stat < XXV_STAT_COUNT; stat++) + lp->xxv_stat_base[stat] += counter[stat]; + write_seqcount_end(&lp->hw_stats_seqcount); +} + +/** + * axienet_xxv_get_stats64 - Fill rtnl_link_stats64 from XXV counters + * @lp: Pointer to the axienet_local structure + * @stats: Output rtnl_link_stats64 structure to populate + */ +static void axienet_xxv_get_stats64(struct axienet_local *lp, + struct rtnl_link_stats64 *stats) +{ + unsigned int start; + u64 tx_hw_errors; + + do { + start = read_seqcount_begin(&lp->hw_stats_seqcount); + stats->rx_crc_errors = lp->xxv_stat_base[XXV_STAT_RX_BAD_FCS]; + /* Both in-range length errors and frame-too-long (oversize) + * frames are IEEE 802.3 length errors, so fold them together + * into rx_length_errors; rx_over_errors is reserved for receiver + * FIFO/ring overflow, which the XXV MAC does not expose. + */ + stats->rx_length_errors = + lp->xxv_stat_base[XXV_STAT_RX_INRANGEERR] + + lp->xxv_stat_base[XXV_STAT_RX_OVERSIZE]; + stats->rx_errors = lp->xxv_stat_base[XXV_STAT_RX_UNDERSIZE] + + lp->xxv_stat_base[XXV_STAT_RX_FRAGMENT] + + lp->xxv_stat_base[XXV_STAT_RX_JABBER] + + stats->rx_crc_errors + + stats->rx_length_errors; + stats->multicast = lp->xxv_stat_base[XXV_STAT_RX_MULTICAST]; + tx_hw_errors = lp->xxv_stat_base[XXV_STAT_TX_BAD_FCS] + + lp->xxv_stat_base[XXV_STAT_TX_FRAME_ERROR]; + } while (read_seqcount_retry(&lp->hw_stats_seqcount, start)); + + /* Fold the HW TX error count into the software tx_errors seeded from + * dev->stats by the caller. The XXV xmit path bumps dev->stats.tx_errors + * for frames dropped on pad failure before they reach the MAC, while the + * HW counters only cover frames the MAC actually transmitted; the two are + * disjoint. This runs once, outside the seqcount retry loop, so a racing + * stats update cannot make the accumulation re-add on retry. + */ + stats->tx_errors += tx_hw_errors; +} + +/** + * axienet_xxv_get_ethtool_stats - Copy XXV counters for ethtool -S + * @lp: Pointer to the axienet_local structure + * @data: Output buffer sized for ARRAY_SIZE(axienet_xxv_priv_stats) u64 values + */ +static void axienet_xxv_get_ethtool_stats(struct axienet_local *lp, u64 *data) +{ + unsigned int i, start; + + do { + start = read_seqcount_begin(&lp->hw_stats_seqcount); + for (i = 0; i < ARRAY_SIZE(axienet_xxv_priv_stats); i++) + data[i] = lp->xxv_stat_base[axienet_xxv_priv_stats[i]]; + } while (read_seqcount_retry(&lp->hw_stats_seqcount, start)); +} + +/** + * axienet_xxv_get_strings - Copy XXV ethtool statistics name strings + * @data: Output buffer for the statistics name strings + */ +static void axienet_xxv_get_strings(u8 *data) +{ + memcpy(data, axienet_xxv_ethtool_stats_strings, + sizeof(axienet_xxv_ethtool_stats_strings)); +} + +/** + * axienet_xxv_get_sset_count - Number of XXV ethtool statistics + * + * Return: Count of XXV hardware statistics reported via ethtool -S. + */ +static int axienet_xxv_get_sset_count(void) +{ + return ARRAY_SIZE(axienet_xxv_ethtool_stats_strings); +} + +/** + * axienet_xxv_get_pause_stats - Fill ethtool pause frame statistics + * @lp: Pointer to the axienet_local structure + * @pause_stats: Output ethtool_pause_stats structure to populate + */ +static void axienet_xxv_get_pause_stats(struct axienet_local *lp, + struct ethtool_pause_stats *pause_stats) +{ + unsigned int start; + + do { + start = read_seqcount_begin(&lp->hw_stats_seqcount); + pause_stats->tx_pause_frames = + lp->xxv_stat_base[XXV_STAT_TX_PAUSE]; + pause_stats->rx_pause_frames = + lp->xxv_stat_base[XXV_STAT_RX_PAUSE]; + } while (read_seqcount_retry(&lp->hw_stats_seqcount, start)); +} + +/** + * axienet_xxv_get_eth_mac_stats - Fill IEEE 802.3 MAC statistics + * @lp: Pointer to the axienet_local structure + * @mac_stats: Output ethtool_eth_mac_stats structure to populate + */ +static void axienet_xxv_get_eth_mac_stats(struct axienet_local *lp, + struct ethtool_eth_mac_stats *mac_stats) +{ + unsigned int start; + + do { + start = read_seqcount_begin(&lp->hw_stats_seqcount); + mac_stats->FramesTransmittedOK = + lp->xxv_stat_base[XXV_STAT_TX_TOTAL_GOOD_PACKETS]; + mac_stats->FramesReceivedOK = + lp->xxv_stat_base[XXV_STAT_RX_TOTAL_GOOD_PACKETS]; + mac_stats->OctetsTransmittedOK = + lp->xxv_stat_base[XXV_STAT_TX_TOTAL_GOOD_BYTES]; + mac_stats->OctetsReceivedOK = + lp->xxv_stat_base[XXV_STAT_RX_TOTAL_GOOD_BYTES]; + mac_stats->FrameCheckSequenceErrors = + lp->xxv_stat_base[XXV_STAT_RX_BAD_FCS]; + mac_stats->MulticastFramesXmittedOK = + lp->xxv_stat_base[XXV_STAT_TX_MULTICAST]; + mac_stats->BroadcastFramesXmittedOK = + lp->xxv_stat_base[XXV_STAT_TX_BROADCAST]; + mac_stats->MulticastFramesReceivedOK = + lp->xxv_stat_base[XXV_STAT_RX_MULTICAST]; + mac_stats->BroadcastFramesReceivedOK = + lp->xxv_stat_base[XXV_STAT_RX_BROADCAST]; + mac_stats->InRangeLengthErrors = + lp->xxv_stat_base[XXV_STAT_RX_INRANGEERR]; + } while (read_seqcount_retry(&lp->hw_stats_seqcount, start)); +} + +/** + * axienet_xxv_get_rmon_stats - Fill RMON statistics and histogram ranges + * @lp: Pointer to the axienet_local structure + * @rmon_stats: Output ethtool_rmon_stats structure to populate + * @ranges: Set to the RMON histogram range table + */ +static void axienet_xxv_get_rmon_stats(struct axienet_local *lp, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges) +{ + unsigned int start; + + do { + start = read_seqcount_begin(&lp->hw_stats_seqcount); + rmon_stats->undersize_pkts = + lp->xxv_stat_base[XXV_STAT_RX_UNDERSIZE]; + rmon_stats->oversize_pkts = + lp->xxv_stat_base[XXV_STAT_RX_OVERSIZE]; + rmon_stats->fragments = + lp->xxv_stat_base[XXV_STAT_RX_FRAGMENT]; + rmon_stats->jabbers = + lp->xxv_stat_base[XXV_STAT_RX_JABBER]; + } while (read_seqcount_retry(&lp->hw_stats_seqcount, start)); + + /* XXV currently exposes only aggregate RMON counters, not per-bin + * histogram buckets. Keep ranges NULL until histogram bins are wired. + */ + *ranges = NULL; +} + const struct axienet_config axienet_10g25g_config = { .sw_padding = true, .internal_pcs = true, @@ -320,4 +581,12 @@ const struct axienet_config axienet_10g25g_config = { .get_regs = axienet_xxv_get_regs, .phylink_set_caps = axienet_xxv_phylink_set_capabilities, .pcs_ops = &axienet_xxv_pcs_ops, + .stats_update = axienet_xxv_stats_update, + .get_stats64 = axienet_xxv_get_stats64, + .get_ethtool_stats = axienet_xxv_get_ethtool_stats, + .get_strings = axienet_xxv_get_strings, + .get_sset_count = axienet_xxv_get_sset_count, + .get_pause_stats = axienet_xxv_get_pause_stats, + .get_eth_mac_stats = axienet_xxv_get_eth_mac_stats, + .get_rmon_stats = axienet_xxv_get_rmon_stats, }; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_xxv.h b/drivers/net/ethernet/xilinx/xilinx_axienet_xxv.h index 15a323ee05b2..ebfa7d57a859 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_xxv.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_xxv.h @@ -63,6 +63,33 @@ struct axienet_config; #define XXV_STAT_GTWIZ_OFFSET 0x000004A0 #define XXV_STAT_AN_LINK_CTL2_OFFSET 0x000009F0 +/* XXV statistics counter registers (PG210). Each counter is a pair of 32-bit + * registers; the MSB register is XXV_STAT_MSB_OFFSET bytes above the LSB. + */ +#define XXV_STAT_MSB_OFFSET 4 +#define XXV_STAT_TX_FRAME_ERROR_OFFSET 0x000006A0 +#define XXV_STAT_TX_TOTAL_PACKETS_OFFSET 0x00000700 +#define XXV_STAT_TX_TOTAL_GOOD_PACKETS_OFFSET 0x00000708 +#define XXV_STAT_TX_TOTAL_BYTES_OFFSET 0x00000710 +#define XXV_STAT_TX_TOTAL_GOOD_BYTES_OFFSET 0x00000718 +#define XXV_STAT_TX_BAD_FCS_OFFSET 0x000007B8 +#define XXV_STAT_TX_MULTICAST_OFFSET 0x000007D8 +#define XXV_STAT_TX_BROADCAST_OFFSET 0x000007E0 +#define XXV_STAT_TX_PAUSE_OFFSET 0x000007F0 +#define XXV_STAT_RX_TOTAL_PACKETS_OFFSET 0x00000808 +#define XXV_STAT_RX_TOTAL_GOOD_PACKETS_OFFSET 0x00000810 +#define XXV_STAT_RX_TOTAL_BYTES_OFFSET 0x00000818 +#define XXV_STAT_RX_TOTAL_GOOD_BYTES_OFFSET 0x00000820 +#define XXV_STAT_RX_UNDERSIZE_OFFSET 0x00000898 +#define XXV_STAT_RX_FRAGMENT_OFFSET 0x000008A0 +#define XXV_STAT_RX_OVERSIZE_OFFSET 0x000008A8 +#define XXV_STAT_RX_JABBER_OFFSET 0x000008B8 +#define XXV_STAT_RX_BAD_FCS_OFFSET 0x000008C0 +#define XXV_STAT_RX_MULTICAST_OFFSET 0x000008E0 +#define XXV_STAT_RX_BROADCAST_OFFSET 0x000008E8 +#define XXV_STAT_RX_PAUSE_OFFSET 0x000008F8 +#define XXV_STAT_RX_INRANGEERR_OFFSET 0x00000908 + /* XXV MAC Register Mask Definitions */ #define XXV_GT_RESET_MASK BIT(0) #define XXV_TC_TX_MASK BIT(0) @@ -70,6 +97,7 @@ struct axienet_config; #define XXV_RCW1_FCS_MASK BIT(1) #define XXV_TC_FCS_MASK BIT(1) #define XXV_RX_BLKLCK_MASK BIT(0) +#define XXV_TICKREG_STATEN_MASK BIT(0) #define XXV_GTWIZ_RESET_DONE (BIT(0) | BIT(1)) #define XXV_MAJ_MASK GENMASK(7, 0) #define XXV_MIN_MASK GENMASK(15, 8) @@ -81,6 +109,33 @@ struct axienet_config; #define XXV_STAT_CORE_SPEED_10G_MASK BIT(0) #define XXV_RX_STATUS_MASK BIT(0) +/* XXV (10G/25G) MAC statistics counters, used to index xxv_stat_base[]. */ +enum xxv_stat { + XXV_STAT_RX_TOTAL_PACKETS = 0, + XXV_STAT_RX_TOTAL_GOOD_PACKETS, + XXV_STAT_RX_TOTAL_BYTES, + XXV_STAT_RX_TOTAL_GOOD_BYTES, + XXV_STAT_RX_BAD_FCS, + XXV_STAT_RX_INRANGEERR, + XXV_STAT_RX_MULTICAST, + XXV_STAT_RX_BROADCAST, + XXV_STAT_RX_UNDERSIZE, + XXV_STAT_RX_FRAGMENT, + XXV_STAT_RX_JABBER, + XXV_STAT_RX_OVERSIZE, + XXV_STAT_RX_PAUSE, + XXV_STAT_TX_TOTAL_PACKETS, + XXV_STAT_TX_TOTAL_GOOD_PACKETS, + XXV_STAT_TX_TOTAL_BYTES, + XXV_STAT_TX_TOTAL_GOOD_BYTES, + XXV_STAT_TX_BAD_FCS, + XXV_STAT_TX_FRAME_ERROR, + XXV_STAT_TX_MULTICAST, + XXV_STAT_TX_BROADCAST, + XXV_STAT_TX_PAUSE, + XXV_STAT_COUNT, +}; + extern const struct axienet_config axienet_10g25g_config; #endif /* XILINX_AXIENET_XXV_H */ -- 2.25.1