From nobody Sun Apr 5 18:20:21 2026 Received: from mail-pj1-f97.google.com (mail-pj1-f97.google.com [209.85.216.97]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E5A2537C0F5 for ; Fri, 3 Apr 2026 07:38:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.97 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201896; cv=none; b=WV0I+KuLBf1xzIh1FjhwKu10dGQsQnavjqW7dXjitizJubrJ1pHUmO9aLDQd+nKr30RraJQi37VtKXsnrVSrc4VBA72MYuO7BcsQRZoMCAI2JmFDPKu6dCBu4lICgBhKaQhrToFzI4884LQ0mYF31yM0PQ1flMcOG80sz+TDyzE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201896; c=relaxed/simple; bh=EYofg1gpQ9rfOnBFkagL/sjEY+BAK75kZAJ+LOzBbnw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tNiifrSYC+yFKcRpW/CyCj1LjUUvTHdmJCVSz1iPAilFxVlISPyfz4Sanp2FW65HgVtxzAwNlTkMWsZNDAluu3imiV99gj1vF4frRT/fUTJQ5JILbfPeUHzm1KGwtc7sgL/ZP0ATPHjgomcPa26VkAZRZMcdOY9tUL4jL3QHryc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=D+clhTJ8; arc=none smtp.client-ip=209.85.216.97 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="D+clhTJ8" Received: by mail-pj1-f97.google.com with SMTP id 98e67ed59e1d1-3567e2b4159so1154907a91.0 for ; Fri, 03 Apr 2026 00:38:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201894; x=1775806694; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=cFGH6qymgtvzYwWHNnXSxQD4gLAcLHVZRmJAUNjPk0M=; b=Yk3RhKwPgwGA/zghaZSVigOlTNJ+Yr/7h0+cXEg7HJ6Opk8F4uYyzNG63UzFqwuFIO p9QdiXTz79bEHGIR44ZOLSoaxwuSDjmDqDWyg5H/pykd2APFlDWxZXZy80ZY39aHC2hX E1FYV7VdB9DsrjYyd38reMvg1WUPVoRSZzhP21cfA33QYoTWHorCUxuIJ8q5C4Q5byuX HOxSaz/41cZd+5a8lJT5iONFlqCYh2aq6ajAQt92W0pzqjZZ7WspBd0m9eeYtsvzMFoC F8PFKPmUPEVsrMbycxOfl+IzXArZyS1dpN46kaZqlxzgVIZHhEIfILBNnypphIzd6M2l udXg== X-Forwarded-Encrypted: i=1; AJvYcCVblQ4pu8NVdrafW8ccBVF2ic+V+f/u7y6+/saQDsYtTxbfaNHYOJNDSEh+YwaDcHEa07raVRyqv7oh7x0=@vger.kernel.org X-Gm-Message-State: AOJu0Ywhe8awJzq6zJOOKzt9cHHQuWegX/M/Xim2lANi4WnJWotfltMf jAk5bB1pphgWYT/2hI3fHXCelsNryae1Wqm0Rjarrsc1QyC1hVZouLX1aBJT9vhPeNbxoy1iQ3+ AM4xFEODCAQn/+qe7TUI390NhRc6hTFH8FVyKPRtzSlTrpZBoUW/lGYnztvVvQ6xuwBVyaH1Nw0 JRyozydf1Nz4LZUSMRH/Is0Bnq5QKfvlxw1Iy8Pb97WZQBj9K+15labxi3eCXFGl8Scfh/YUqyi q1rLpMn4pmSNVyBVO2KYUGRBw== X-Gm-Gg: AeBDiesbqYGs1ZSHVXKaYUhQgKPHbGMs5aConyH2N80Hjt+CQDHselsr/VDALx6QlVs qCmKZ9J56tdMzcDE4JVXbNNbYrBg5ZfVocszYqgG7A8KgwphtHYteNlkCbhGJqULVUi40iTIrLw bZjXCB+iyT6tOcm/vMM7N0/Zrwg1IJ4oeprSfZRmtZKmO+rxziGhcrV0C/cQ8LxobiurcHboQCa XSL88I7p/exp64bMu9RNLqXW0rsmBvLwlqEpjOGDtebMulzlOAs1wgkoxM7CdQRPbTMfxMTxC4I PRjb5NaJ+Ym7ZPkPxHoyaUecsJ1bwRUvqE2a80ZuCLa8mAtXf1GudpaQHgBwv6QoRGqt9lcII8Q zqKx4VWVAle9fIPH9wX+RoyOSeHUYMwY7ybWj5FzGp5xBcT3zKDdQepiH8idcRNOI+pfmFZwqSe MPp7NQLO7vMlqgf5iTw/IGTKtzRO7O9Q0cJJe9X6iISXwECrRscEmHfH9MrFYQQXc= X-Received: by 2002:a17:90b:37cc:b0:359:d54:846f with SMTP id 98e67ed59e1d1-35de680bc4amr2111666a91.7.1775201894198; Fri, 03 Apr 2026 00:38:14 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-15.dlp.protect.broadcom.com. [144.49.247.15]) by smtp-relay.gmail.com with ESMTPS id 98e67ed59e1d1-35de7caa2b2sm57617a91.1.2026.04.03.00.38.13 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:14 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-35d9278587bso1531265a91.2 for ; Fri, 03 Apr 2026 00:38:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201892; x=1775806692; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cFGH6qymgtvzYwWHNnXSxQD4gLAcLHVZRmJAUNjPk0M=; b=D+clhTJ8s2WM4A2jsD53Bbyi1T27F5+16KqF4IR9350LxjLejpo/+wPBD22CG9WxHA IwsySFvh8wLi58pI74nAjyQS0uo+QJHwsSs/a/l8PAx/YsimHgeBa2/c6rFIdw6Fzts0 Bh0M025dKXZnoO30IAwp2PjVeEOlyJNAp8Q8w= X-Forwarded-Encrypted: i=1; AJvYcCVXjbSxTGgv8T2qnrYN1a7k6cDYkbh7cJDk8SJAz9mYGdZkyLt5zZozmFBZ/qb5ofI88BvGd9bs+55jzSI=@vger.kernel.org X-Received: by 2002:a17:90b:1d8b:b0:35d:a0b7:960f with SMTP id 98e67ed59e1d1-35de67d99damr2017648a91.5.1775201892412; Fri, 03 Apr 2026 00:38:12 -0700 (PDT) X-Received: by 2002:a17:90b:1d8b:b0:35d:a0b7:960f with SMTP id 98e67ed59e1d1-35de67d99damr2017626a91.5.1775201891982; Fri, 03 Apr 2026 00:38:11 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:11 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Ajit Kumar Khaparde Subject: [PATCH net-next v11 01/10] bng_en: add per-PF workqueue, timer, and slow-path task Date: Fri, 3 Apr 2026 13:07:15 +0530 Message-ID: <20260403073724.194360-2-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Add a dedicated single-thread workqueue and a timer for each PF to drive deferred slow-path work such as link event handling and stats collection. The timer is stopped via timer_delete_sync() when interrupts are disabled and restarted on open. While the close path stops the timer to prevent new tasks from being scheduled, the sp_task and workqueue are preserved to maintain state continuity. Final draining and destruction of the workqueue are handled during PCI remove. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Ajit Kumar Khaparde --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 59 ++++++++++++++++++- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 12 +++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index a20dc3ca640c..8d5d828e19a3 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -101,6 +101,36 @@ static int bnge_alloc_ring_stats(struct bnge_net *bn) return rc; } =20 +static void bnge_timer(struct timer_list *t) +{ + struct bnge_net *bn =3D timer_container_of(bn, t, timer); + struct bnge_dev *bd =3D bn->bd; + + if (!netif_running(bn->netdev) || + !test_bit(BNGE_STATE_OPEN, &bd->state)) + return; + + /* Periodic work added by later patches */ + + mod_timer(&bn->timer, jiffies + bn->current_interval); +} + +static void bnge_sp_task(struct work_struct *work) +{ + struct bnge_net *bn =3D container_of(work, struct bnge_net, sp_task); + struct bnge_dev *bd =3D bn->bd; + + netdev_lock(bn->netdev); + if (!test_bit(BNGE_STATE_OPEN, &bd->state)) { + netdev_unlock(bn->netdev); + return; + } + + /* Event handling work added by later patches */ + + netdev_unlock(bn->netdev); +} + static void bnge_free_nq_desc_arr(struct bnge_nq_ring_info *nqr) { struct bnge_ring_struct *ring =3D &nqr->ring_struct; @@ -2507,6 +2537,9 @@ static int bnge_open_core(struct bnge_net *bn) bnge_enable_int(bn); =20 bnge_tx_enable(bn); + + mod_timer(&bn->timer, jiffies + bn->current_interval); + return 0; =20 err_free_irq: @@ -2542,6 +2575,8 @@ static void bnge_close_core(struct bnge_net *bn) bnge_tx_disable(bn); =20 clear_bit(BNGE_STATE_OPEN, &bd->state); + + timer_delete_sync(&bn->timer); bnge_shutdown_nic(bn); bnge_disable_napi(bn); bnge_free_all_rings_bufs(bn); @@ -2774,6 +2809,18 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_i= rqs) if (bd->tso_max_segs) netif_set_tso_max_segs(netdev, bd->tso_max_segs); =20 + INIT_WORK(&bn->sp_task, bnge_sp_task); + timer_setup(&bn->timer, bnge_timer, 0); + bn->current_interval =3D BNGE_TIMER_INTERVAL; + + bn->bnge_pf_wq =3D alloc_ordered_workqueue("bnge_pf_wq-%s", 0, + dev_name(bd->dev)); + if (!bn->bnge_pf_wq) { + netdev_err(netdev, "Unable to create workqueue.\n"); + rc =3D -ENOMEM; + goto err_netdev; + } + bn->rx_ring_size =3D BNGE_DEFAULT_RX_RING_SIZE; bn->tx_ring_size =3D BNGE_DEFAULT_TX_RING_SIZE; bn->rx_dir =3D DMA_FROM_DEVICE; @@ -2789,11 +2836,13 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_= irqs) rc =3D register_netdev(netdev); if (rc) { dev_err(bd->dev, "Register netdev failed rc: %d\n", rc); - goto err_netdev; + goto err_free_workq; } =20 return 0; =20 +err_free_workq: + destroy_workqueue(bn->bnge_pf_wq); err_netdev: free_netdev(netdev); return rc; @@ -2802,8 +2851,16 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_i= rqs) void bnge_netdev_free(struct bnge_dev *bd) { struct net_device *netdev =3D bd->netdev; + struct bnge_net *bn; + + bn =3D netdev_priv(netdev); =20 unregister_netdev(netdev); + + timer_shutdown_sync(&bn->timer); + cancel_work_sync(&bn->sp_task); + destroy_workqueue(bn->bnge_pf_wq); + free_netdev(netdev); bd->netdev =3D NULL; } diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 70f1a7c24814..d2ccee725454 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -224,6 +224,12 @@ struct bnge_tpa_info { #define BNGE_NQ_HDL_TYPE(hdl) (((hdl) & BNGE_NQ_HDL_TYPE_MASK) >> \ BNGE_NQ_HDL_TYPE_SHIFT) =20 +enum bnge_net_state { + BNGE_STATE_NAPI_DISABLED, +}; + +#define BNGE_TIMER_INTERVAL HZ + struct bnge_net { struct bnge_dev *bd; struct net_device *netdev; @@ -281,13 +287,17 @@ struct bnge_net { u32 stats_coal_ticks; =20 unsigned long state; -#define BNGE_STATE_NAPI_DISABLED 0 =20 u32 msg_enable; u16 max_tpa; __be16 vxlan_port; __be16 nge_port; __be16 vxlan_gpe_port; + + unsigned int current_interval; + struct timer_list timer; + struct workqueue_struct *bnge_pf_wq; + struct work_struct sp_task; }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 --=20 2.47.3 From nobody Sun Apr 5 18:20:21 2026 Received: from mail-dy1-f227.google.com (mail-dy1-f227.google.com [74.125.82.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B919337B00E for ; Fri, 3 Apr 2026 07:38:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201903; cv=none; b=HYtOAXNM19SM2fMZKzyqyzk86thH3etqiAQvlFNrfCYxq2Q3xQgsdhHmoAlZaa3XDa4AtwLu1cLx6xGaXrCCw5nXOL3Ws/LZpGKmt0CIaS9e5VZPGXTPh4BzFqyuJt17t+FmO1wynjj1CK5afYcznts/Wfvqm1UxwXff8ZPJsz4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201903; c=relaxed/simple; bh=INIC9Bd9qfPAqTiIgYzCJFLLvanXY/pZfMr6ESAT7jQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XEXxK36auQY0j/mS/Y9jymVkuyJ6SWYZobTB6izOfcdjHdhwXZcCGjWgZuklM1WOy0+0jPoUhhNHDe870yPKSdrwE47cnn6FhpyBkYvmk/s5GyRI9VUd4qWikGY5ppydCVrvYl26msZT6ynaIYohbgTR1l/a/8uqawROWK8G9dA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=K3ri/ZPV; arc=none smtp.client-ip=74.125.82.227 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="K3ri/ZPV" Received: by mail-dy1-f227.google.com with SMTP id 5a478bee46e88-2cbdd9852aaso877851eec.0 for ; Fri, 03 Apr 2026 00:38:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201900; x=1775806700; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=v0Hcb/raFTPNdLrLH4TWXWVkOkEgM6UeqKZRBGWApu8=; b=gS7BbWlkHN2OK2T3AU7e432cDpqZL705q6shKYiBfldEObyD9e0xjrW6ZNQUU9Ea9x wzQ9w9BX1Mn55LOnEyrLxh0ZUb6tnsNUiiQ++fxf1nTmT3Ex5uoDKw06XILb/Qi0lurv koziAWEb5+D/EmPz4kIfLpl+rWxj8TI0ndHfvfbdBL5pXvK9PZtoZL7rTJm32Kj7ECTq 8OmpNdpkvDaVJZm60DYMC1n0WoPuJAx+vpdbE8orta7U8hxBDyVAf52sIWo0/KKgFKU+ SERYgds3jFOgBxZ8DHme32yHUccDuK9ifWY2uI/xGdEnFjzDmq+wPWLcPttll8js+rh2 R1dw== X-Forwarded-Encrypted: i=1; AJvYcCUiKty+QDXNIXlA8V75bmiXCEeqiDP51h/L1pFKxlZKma1OXKHeT/xkGg+95ir+SSTqH43EUS4ABx6uk9c=@vger.kernel.org X-Gm-Message-State: AOJu0YzRxGxektE1qJya0ep8fnj+5FSJ+t3b0v/4fFCyzWWgEOKGJyQG uhXmtnlTokKjvPJUqsUAp1yYfKz/ClnIj+XrErY1yVi/XJaJ71IW9iUzk5osHgzXfMkhdLyuvfL HCqNBQbb1viXwdGx2S9TmpUo/qTKYNHakWCn4YkNa3aFa2bkvkQeH825qq5r6dzxpjVrUHdAyKt v8w9pLbZS7Tj125vfHReOG9yVXVoy/s4RdKRr7+Lm9AkkAYDKhHz/fkrSMGrL9kviI3pc6qWN4y 6aufgDYu72QBp2as/9Fx7tuaQ== X-Gm-Gg: AeBDiet4F8hCPdWaA8JKYXq4foCnV2JcJHmF+qbC0n/U5YPkYLUfyg+o4/PpTVBUX40 +1TrUyjqz6X1oT+g7wm2iMTXyraC96gzJaGKz+8sbmxKXQ7EffKiYUn1CygxRne0efuz7x05kYi yoz4qGE5Ym567eliwloW/04/xIo0iSAw69OVxGHH/UhJOf6G3NcXfWVZR6vlt9tR5OYVHrbxHeI ae9EBhiIz5aE1k2Puhyr8YIZAxFr7jnKBh93U3kOJVxx7kPfiz4t4ZmlItyik8Tg2/UAYxsYDDK 40163/B8PWY2rf8H9/PmJ52WQu3V5Cj93z+f8fbPHPLtK0foEpteHaAk9qfYaAEWOfyR1BtCoGX 8v0ZcXudJMbuAJmQ/Sy3xhCUS0w7DYIl9MUko7Hnltyi6Tn9r0ucC/AwXTGjrqC8dy9STznbJTs 9fewz8j5V2m0cyreWuj12CxeLCNUFWou8sG0Z5Gcf/2IWQHpyXytLPWY2ljgEQDmg= X-Received: by 2002:a05:7301:d1b:b0:2c4:b5bf:1d7 with SMTP id 5a478bee46e88-2cbf9af8ba5mr1067615eec.3.1775201899726; Fri, 03 Apr 2026 00:38:19 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-25.dlp.protect.broadcom.com. [144.49.247.25]) by smtp-relay.gmail.com with ESMTPS id 5a478bee46e88-2ca793f4e90sm380692eec.10.2026.04.03.00.38.19 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:19 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f70.google.com with SMTP id 98e67ed59e1d1-3594620fe97so3659481a91.1 for ; Fri, 03 Apr 2026 00:38:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201898; x=1775806698; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=v0Hcb/raFTPNdLrLH4TWXWVkOkEgM6UeqKZRBGWApu8=; b=K3ri/ZPV8pgMfW38g82KKcd26DkehkVzltx7ia9wTgjYJmFW9rGtkjqN2gzTED4rkd qXGnDoPeLfA1WHxdoZRiqHzZ0rs876mwDCizd73fWuOQ5Pt7ETCiqPTfllb1TE926bg7 Xhnsu7OPT/p1RIDSEV9hAQAiHLjXoRo2NxMm8= X-Forwarded-Encrypted: i=1; AJvYcCUgD8YMCDy4jcxOyvGXwv1Zv16sTkkjc0nm3USvdqBHJYWUgmkRwmDMhFb9C2NTRlrhl0o2QkIezcA+eb8=@vger.kernel.org X-Received: by 2002:a17:90b:5111:b0:35d:93ff:2855 with SMTP id 98e67ed59e1d1-35de67eba6amr1992998a91.8.1775201897637; Fri, 03 Apr 2026 00:38:17 -0700 (PDT) X-Received: by 2002:a17:90b:5111:b0:35d:93ff:2855 with SMTP id 98e67ed59e1d1-35de67eba6amr1992972a91.8.1775201897038; Fri, 03 Apr 2026 00:38:17 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:16 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula , Ajit Kumar Khaparde Subject: [PATCH net-next v11 02/10] bng_en: query PHY capabilities and report link status Date: Fri, 3 Apr 2026 13:07:16 +0530 Message-ID: <20260403073724.194360-3-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Query PHY capabilities and supported speeds from firmware, retrieve current link state (speed, duplex, pause, FEC), and log the information. Seed initial link state during probe. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula Reviewed-by: Ajit Kumar Khaparde --- drivers/net/ethernet/broadcom/bnge/Makefile | 3 +- drivers/net/ethernet/broadcom/bnge/bnge.h | 10 + .../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 237 +++++++++ .../ethernet/broadcom/bnge/bnge_hwrm_lib.h | 5 + .../net/ethernet/broadcom/bnge/bnge_link.c | 467 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_link.h | 193 ++++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.c | 54 +- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 12 + 8 files changed, 978 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_link.c create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_link.h diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethe= rnet/broadcom/bnge/Makefile index fa604ee20264..8e07cb307d21 100644 --- a/drivers/net/ethernet/broadcom/bnge/Makefile +++ b/drivers/net/ethernet/broadcom/bnge/Makefile @@ -11,4 +11,5 @@ bng_en-y :=3D bnge_core.o \ bnge_netdev.o \ bnge_ethtool.o \ bnge_auxr.o \ - bnge_txrx.o + bnge_txrx.o \ + bnge_link.o diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethern= et/broadcom/bnge/bnge.h index f376913aa321..83ee4749cc70 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h @@ -94,6 +94,11 @@ struct bnge_queue_info { u8 queue_profile; }; =20 +#define BNGE_PHY_FLAGS2_SHIFT 8 +#define BNGE_PHY_FL_NO_FCS PORT_PHY_QCAPS_RESP_FLAGS_NO_FCS +#define BNGE_PHY_FL_SPEEDS2 \ + (PORT_PHY_QCAPS_RESP_FLAGS2_SPEEDS2_SUPPORTED << 8) + struct bnge_dev { struct device *dev; struct pci_dev *pdev; @@ -207,6 +212,11 @@ struct bnge_dev { =20 struct bnge_auxr_priv *aux_priv; struct bnge_auxr_dev *auxr_dev; + + struct bnge_link_info link_info; + + /* Copied from flags and flags2 in hwrm_port_phy_qcaps_output */ + u32 phy_flags; }; =20 static inline bool bnge_is_roce_en(struct bnge_dev *bd) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.c index c46da3413417..acb712ddbd7e 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c @@ -981,6 +981,243 @@ void bnge_hwrm_vnic_ctx_free_one(struct bnge_dev *bd, vnic->fw_rss_cos_lb_ctx[ctx_idx] =3D INVALID_HW_RING_ID; } =20 +static bool bnge_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *res= p) +{ + return !resp->supported_speeds_auto_mode && + !resp->supported_speeds_force_mode && + !resp->supported_pam4_speeds_auto_mode && + !resp->supported_pam4_speeds_force_mode && + !resp->supported_speeds2_auto_mode && + !resp->supported_speeds2_force_mode; +} + +int bnge_hwrm_phy_qcaps(struct bnge_dev *bd) +{ + struct bnge_link_info *link_info =3D &bd->link_info; + struct hwrm_port_phy_qcaps_output *resp; + struct hwrm_port_phy_qcaps_input *req; + int rc; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_QCAPS); + if (rc) + return rc; + + resp =3D bnge_hwrm_req_hold(bd, req); + rc =3D bnge_hwrm_req_send(bd, req); + if (rc) + goto hwrm_phy_qcaps_exit; + + bd->phy_flags =3D resp->flags | + (le16_to_cpu(resp->flags2) << BNGE_PHY_FLAGS2_SHIFT); + + if (bnge_phy_qcaps_no_speed(resp)) { + link_info->phy_enabled =3D false; + netdev_warn(bd->netdev, "Ethernet link disabled\n"); + } else if (!link_info->phy_enabled) { + link_info->phy_enabled =3D true; + netdev_info(bd->netdev, "Ethernet link enabled\n"); + /* Phy re-enabled, reprobe the speeds */ + link_info->support_auto_speeds =3D 0; + link_info->support_pam4_auto_speeds =3D 0; + link_info->support_auto_speeds2 =3D 0; + } + + /* Firmware may report 0 for autoneg supported speeds when no + * SFP module is present. Skip the update to preserve the + * current supported speeds -- storing 0 would cause autoneg + * default fallback to advertise nothing. + */ + if (resp->supported_speeds_auto_mode) + link_info->support_auto_speeds =3D + le16_to_cpu(resp->supported_speeds_auto_mode); + if (resp->supported_pam4_speeds_auto_mode) + link_info->support_pam4_auto_speeds =3D + le16_to_cpu(resp->supported_pam4_speeds_auto_mode); + if (resp->supported_speeds2_auto_mode) + link_info->support_auto_speeds2 =3D + le16_to_cpu(resp->supported_speeds2_auto_mode); + + bd->port_count =3D resp->port_cnt; + +hwrm_phy_qcaps_exit: + bnge_hwrm_req_drop(bd, req); + return rc; +} + +int bnge_hwrm_set_link_setting(struct bnge_net *bn, bool set_pause) +{ + struct hwrm_port_phy_cfg_input *req; + struct bnge_dev *bd =3D bn->bd; + int rc; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_CFG); + if (rc) + return rc; + + if (set_pause) + bnge_hwrm_set_pause_common(bn, req); + + bnge_hwrm_set_link_common(bn, req); + + rc =3D bnge_hwrm_req_send(bd, req); + if (!rc) + bn->eth_link_info.force_link_chng =3D false; + + return rc; +} + +int bnge_update_link(struct bnge_net *bn, bool chng_link_state) +{ + struct hwrm_port_phy_qcfg_output *resp; + struct hwrm_port_phy_qcfg_input *req; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + bool support_changed; + u8 link_state; + int rc; + + link_info =3D &bd->link_info; + link_state =3D link_info->link_state; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_QCFG); + if (rc) + return rc; + + resp =3D bnge_hwrm_req_hold(bd, req); + rc =3D bnge_hwrm_req_send(bd, req); + if (rc) { + bnge_hwrm_req_drop(bd, req); + return rc; + } + + memcpy(&link_info->phy_qcfg_resp, resp, sizeof(*resp)); + link_info->phy_link_status =3D resp->link; + link_info->duplex =3D resp->duplex_state; + link_info->pause =3D resp->pause; + link_info->auto_mode =3D resp->auto_mode; + link_info->auto_pause_setting =3D resp->auto_pause; + link_info->lp_pause =3D resp->link_partner_adv_pause; + link_info->force_pause_setting =3D resp->force_pause; + link_info->duplex_setting =3D resp->duplex_cfg; + if (link_info->phy_link_status =3D=3D BNGE_LINK_LINK) { + link_info->link_speed =3D le16_to_cpu(resp->link_speed); + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) + link_info->active_lanes =3D resp->active_lanes; + } else { + link_info->link_speed =3D 0; + link_info->active_lanes =3D 0; + } + link_info->force_link_speed =3D le16_to_cpu(resp->force_link_speed); + link_info->force_pam4_link_speed =3D + le16_to_cpu(resp->force_pam4_link_speed); + link_info->force_link_speed2 =3D le16_to_cpu(resp->force_link_speeds2); + link_info->support_speeds =3D le16_to_cpu(resp->support_speeds); + link_info->support_pam4_speeds =3D le16_to_cpu(resp->support_pam4_speeds); + link_info->support_speeds2 =3D le16_to_cpu(resp->support_speeds2); + link_info->auto_link_speeds =3D le16_to_cpu(resp->auto_link_speed_mask); + link_info->auto_pam4_link_speeds =3D + le16_to_cpu(resp->auto_pam4_link_speed_mask); + link_info->auto_link_speeds2 =3D le16_to_cpu(resp->auto_link_speeds2); + link_info->lp_auto_link_speeds =3D + le16_to_cpu(resp->link_partner_adv_speeds); + link_info->lp_auto_pam4_link_speeds =3D + resp->link_partner_pam4_adv_speeds; + link_info->media_type =3D resp->media_type; + link_info->phy_type =3D resp->phy_type; + link_info->phy_addr =3D resp->eee_config_phy_addr & + PORT_PHY_QCFG_RESP_PHY_ADDR_MASK; + link_info->module_status =3D resp->module_status; + + link_info->fec_cfg =3D le16_to_cpu(resp->fec_cfg); + link_info->active_fec_sig_mode =3D resp->active_fec_signal_mode; + + if (chng_link_state) { + if (link_info->phy_link_status =3D=3D BNGE_LINK_LINK) + link_info->link_state =3D BNGE_LINK_STATE_UP; + else + link_info->link_state =3D BNGE_LINK_STATE_DOWN; + if (link_state !=3D link_info->link_state) + bnge_report_link(bd); + } else { + /* always link down if not required to update link state */ + link_info->link_state =3D BNGE_LINK_STATE_DOWN; + } + bnge_hwrm_req_drop(bd, req); + + if (!BNGE_PHY_CFG_ABLE(bd)) + return 0; + + support_changed =3D bnge_support_speed_dropped(bn); + if (support_changed && (bn->eth_link_info.autoneg & BNGE_AUTONEG_SPEED)) + rc =3D bnge_hwrm_set_link_setting(bn, true); + return rc; +} + +int bnge_hwrm_set_pause(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct hwrm_port_phy_cfg_input *req; + struct bnge_dev *bd =3D bn->bd; + bool pause_autoneg; + int rc; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_CFG); + if (rc) + return rc; + + pause_autoneg =3D !!(elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL); + + /* Prepare PHY pause-advertisement or forced-pause settings. */ + bnge_hwrm_set_pause_common(bn, req); + + /* Prepare speed/autoneg settings */ + if (pause_autoneg || elink_info->force_link_chng) + bnge_hwrm_set_link_common(bn, req); + + rc =3D bnge_hwrm_req_send(bd, req); + if (!rc && !pause_autoneg) { + /* Since changing of pause setting, with pause autoneg off, + * doesn't trigger any link change event, the driver needs to + * update the current MAC pause upon successful return of the + * phy_cfg command. + */ + bd->link_info.force_pause_setting =3D + bd->link_info.pause =3D elink_info->req_flow_ctrl; + bd->link_info.auto_pause_setting =3D 0; + if (!elink_info->force_link_chng) + bnge_report_link(bd); + } + if (!rc) + elink_info->force_link_chng =3D false; + + return rc; +} + +int bnge_hwrm_shutdown_link(struct bnge_dev *bd) +{ + struct hwrm_port_phy_cfg_input *req; + int rc; + + if (!BNGE_PHY_CFG_ABLE(bd)) + return 0; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_CFG); + if (rc) + return rc; + + req->flags =3D cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DWN); + rc =3D bnge_hwrm_req_send(bd, req); + if (!rc) { + /* Device is not obliged to link down in certain scenarios, + * even when forced. Setting the state unknown is consistent + * with driver startup and will force link state to be + * reported during subsequent open based on PORT_PHY_QCFG. + */ + bd->link_info.link_state =3D BNGE_LINK_STATE_UNKNOWN; + } + return rc; +} + void bnge_hwrm_stat_ctx_free(struct bnge_net *bn) { struct hwrm_stat_ctx_free_input *req; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.h index 38b046237feb..86ca3ac2244b 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h @@ -57,4 +57,9 @@ int hwrm_ring_alloc_send_msg(struct bnge_net *bn, int bnge_hwrm_set_async_event_cr(struct bnge_dev *bd, int idx); int bnge_hwrm_vnic_set_tpa(struct bnge_dev *bd, struct bnge_vnic_info *vni= c, u32 tpa_flags); +int bnge_update_link(struct bnge_net *bn, bool chng_link_state); +int bnge_hwrm_phy_qcaps(struct bnge_dev *bd); +int bnge_hwrm_set_link_setting(struct bnge_net *bn, bool set_pause); +int bnge_hwrm_set_pause(struct bnge_net *bn); +int bnge_hwrm_shutdown_link(struct bnge_dev *bd); #endif /* _BNGE_HWRM_LIB_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.c b/drivers/net/e= thernet/broadcom/bnge/bnge_link.c new file mode 100644 index 000000000000..f7e4d59f98ff --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.c @@ -0,0 +1,467 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2026 Broadcom. + +#include + +#include "bnge.h" +#include "bnge_link.h" +#include "bnge_hwrm_lib.h" + +static u32 bnge_fw_to_ethtool_speed(u16 fw_link_speed) +{ + switch (fw_link_speed) { + case BNGE_LINK_SPEED_50GB: + case BNGE_LINK_SPEED_50GB_PAM4: + return SPEED_50000; + case BNGE_LINK_SPEED_100GB: + case BNGE_LINK_SPEED_100GB_PAM4: + case BNGE_LINK_SPEED_100GB_PAM4_112: + return SPEED_100000; + case BNGE_LINK_SPEED_200GB: + case BNGE_LINK_SPEED_200GB_PAM4: + case BNGE_LINK_SPEED_200GB_PAM4_112: + return SPEED_200000; + case BNGE_LINK_SPEED_400GB: + case BNGE_LINK_SPEED_400GB_PAM4: + case BNGE_LINK_SPEED_400GB_PAM4_112: + return SPEED_400000; + case BNGE_LINK_SPEED_800GB: + case BNGE_LINK_SPEED_800GB_PAM4_112: + return SPEED_800000; + default: + return SPEED_UNKNOWN; + } +} + +static void bnge_set_auto_speed(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + elink_info->advertising =3D link_info->auto_link_speeds2; + return; + } + elink_info->advertising =3D link_info->auto_link_speeds; + elink_info->advertising_pam4 =3D link_info->auto_pam4_link_speeds; +} + +static void bnge_set_force_speed(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + elink_info->req_link_speed =3D link_info->force_link_speed2; + switch (elink_info->req_link_speed) { + case BNGE_LINK_SPEED_50GB_PAM4: + case BNGE_LINK_SPEED_100GB_PAM4: + case BNGE_LINK_SPEED_200GB_PAM4: + case BNGE_LINK_SPEED_400GB_PAM4: + elink_info->req_signal_mode =3D BNGE_SIG_MODE_PAM4; + break; + case BNGE_LINK_SPEED_100GB_PAM4_112: + case BNGE_LINK_SPEED_200GB_PAM4_112: + case BNGE_LINK_SPEED_400GB_PAM4_112: + case BNGE_LINK_SPEED_800GB_PAM4_112: + elink_info->req_signal_mode =3D BNGE_SIG_MODE_PAM4_112; + break; + default: + elink_info->req_signal_mode =3D BNGE_SIG_MODE_NRZ; + break; + } + } else if (link_info->force_pam4_link_speed) { + elink_info->req_link_speed =3D link_info->force_pam4_link_speed; + elink_info->req_signal_mode =3D BNGE_SIG_MODE_PAM4; + } else { + elink_info->req_link_speed =3D link_info->force_link_speed; + elink_info->req_signal_mode =3D BNGE_SIG_MODE_NRZ; + } +} + +void bnge_init_ethtool_link_settings(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (BNGE_AUTO_MODE(link_info->auto_mode)) { + elink_info->autoneg =3D BNGE_AUTONEG_SPEED; + if (link_info->auto_pause_setting & + PORT_PHY_QCFG_RESP_AUTO_PAUSE_AUTONEG_PAUSE) + elink_info->autoneg |=3D BNGE_AUTONEG_FLOW_CTRL; + bnge_set_auto_speed(bn); + } else { + elink_info->autoneg =3D 0; + elink_info->advertising =3D 0; + elink_info->advertising_pam4 =3D 0; + bnge_set_force_speed(bn); + elink_info->req_duplex =3D link_info->duplex_setting; + } + if (elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) + elink_info->req_flow_ctrl =3D + link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH; + else + elink_info->req_flow_ctrl =3D link_info->force_pause_setting; +} + +int bnge_probe_phy(struct bnge_net *bn, bool fw_dflt) +{ + struct bnge_dev *bd =3D bn->bd; + int rc; + + bd->phy_flags =3D 0; + rc =3D bnge_hwrm_phy_qcaps(bd); + if (rc) { + netdev_err(bn->netdev, + "Probe PHY can't get PHY qcaps (rc: %d)\n", rc); + return rc; + } + if (bd->phy_flags & BNGE_PHY_FL_NO_FCS) + bn->netdev->priv_flags |=3D IFF_SUPP_NOFCS; + else + bn->netdev->priv_flags &=3D ~IFF_SUPP_NOFCS; + if (!fw_dflt) + return 0; + + rc =3D bnge_update_link(bn, false); + if (rc) { + netdev_err(bn->netdev, "Probe PHY can't update link (rc: %d)\n", + rc); + return rc; + } + bnge_init_ethtool_link_settings(bn); + + return 0; +} + +void bnge_hwrm_set_link_common(struct bnge_net *bn, + struct hwrm_port_phy_cfg_input *req) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_dev *bd =3D bn->bd; + + if (elink_info->autoneg & BNGE_AUTONEG_SPEED) { + req->auto_mode |=3D PORT_PHY_CFG_REQ_AUTO_MODE_SPEED_MASK; + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + req->enables |=3D cpu_to_le32(BNGE_PHY_AUTO_SPEEDS2_MASK); + req->auto_link_speeds2_mask =3D + cpu_to_le16(elink_info->advertising); + } else if (elink_info->advertising) { + req->enables |=3D cpu_to_le32(BNGE_PHY_AUTO_SPEED_MASK); + req->auto_link_speed_mask =3D + cpu_to_le16(elink_info->advertising); + } + if (elink_info->advertising_pam4) { + req->enables |=3D + cpu_to_le32(BNGE_PHY_AUTO_PAM4_SPEED_MASK); + req->auto_link_pam4_speed_mask =3D + cpu_to_le16(elink_info->advertising_pam4); + } + req->enables |=3D cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE); + req->flags |=3D cpu_to_le32(BNGE_PHY_FLAGS_RESTART_AUTO); + } else { + req->flags |=3D cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE); + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + req->force_link_speeds2 =3D + cpu_to_le16(elink_info->req_link_speed); + req->enables |=3D + cpu_to_le32(BNGE_PHY_FLAGS_ENA_FORCE_SPEEDS2); + netif_info(bn, link, bn->netdev, + "Forcing FW speed2: %d\n", + (u32)elink_info->req_link_speed); + } else if (elink_info->req_signal_mode =3D=3D BNGE_SIG_MODE_PAM4) { + req->force_pam4_link_speed =3D + cpu_to_le16(elink_info->req_link_speed); + req->enables |=3D + cpu_to_le32(BNGE_PHY_FLAGS_ENA_FORCE_PM4_SPEED); + } else { + req->force_link_speed =3D + cpu_to_le16(elink_info->req_link_speed); + } + } + + /* tell FW that the setting takes effect immediately */ + req->flags |=3D cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESET_PHY); +} + +static bool bnge_auto_speed_updated(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) + return elink_info->advertising !=3D link_info->auto_link_speeds2; + + return elink_info->advertising !=3D link_info->auto_link_speeds || + elink_info->advertising_pam4 !=3D link_info->auto_pam4_link_speeds; +} + +void bnge_hwrm_set_pause_common(struct bnge_net *bn, + struct hwrm_port_phy_cfg_input *req) +{ + if (bn->eth_link_info.autoneg & BNGE_AUTONEG_FLOW_CTRL) { + req->auto_pause =3D PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE; + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_RX) + req->auto_pause |=3D PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_TX) + req->auto_pause |=3D PORT_PHY_CFG_REQ_AUTO_PAUSE_TX; + req->enables |=3D + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); + } else { + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_RX) + req->force_pause |=3D PORT_PHY_CFG_REQ_FORCE_PAUSE_RX; + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_TX) + req->force_pause |=3D PORT_PHY_CFG_REQ_FORCE_PAUSE_TX; + req->enables |=3D + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE); + req->auto_pause =3D req->force_pause; + req->enables |=3D + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); + } +} + +static bool bnge_force_speed_updated(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) + return elink_info->req_link_speed !=3D link_info->force_link_speed2; + + if (elink_info->req_signal_mode =3D=3D BNGE_SIG_MODE_NRZ) + return elink_info->req_link_speed !=3D link_info->force_link_speed; + + return elink_info->req_signal_mode =3D=3D BNGE_SIG_MODE_PAM4 && + elink_info->req_link_speed !=3D link_info->force_pam4_link_speed; +} + +int bnge_update_phy_setting(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + bool update_pause =3D false; + bool update_link =3D false; + int rc; + + link_info =3D &bd->link_info; + elink_info =3D &bn->eth_link_info; + rc =3D bnge_update_link(bn, true); + if (rc) { + netdev_err(bn->netdev, "failed to update link (rc: %d)\n", + rc); + return rc; + } + + if ((elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) && + (link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH) !=3D + elink_info->req_flow_ctrl) + update_pause =3D true; + if (!(elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) && + link_info->force_pause_setting !=3D elink_info->req_flow_ctrl) + update_pause =3D true; + if (!(elink_info->autoneg & BNGE_AUTONEG_SPEED)) { + if (BNGE_AUTO_MODE(link_info->auto_mode)) + update_link =3D true; + if (bnge_force_speed_updated(bn)) + update_link =3D true; + if (elink_info->req_duplex !=3D link_info->duplex_setting) + update_link =3D true; + } else { + if (link_info->auto_mode =3D=3D BNGE_LINK_AUTO_NONE) + update_link =3D true; + if (bnge_auto_speed_updated(bn)) + update_link =3D true; + } + + /* The last close may have shut down the link, so need to call + * PHY_CFG to bring it back up. + */ + if (!BNGE_LINK_IS_UP(bd)) + update_link =3D true; + + if (update_link) + rc =3D bnge_hwrm_set_link_setting(bn, update_pause); + else if (update_pause) + rc =3D bnge_hwrm_set_pause(bn); + + if (rc) { + netdev_err(bn->netdev, + "failed to update PHY setting (rc: %d)\n", rc); + return rc; + } + + return 0; +} + +void bnge_get_port_module_status(struct bnge_net *bn) +{ + struct hwrm_port_phy_qcfg_output *resp; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + u8 module_status; + + link_info =3D &bd->link_info; + resp =3D &link_info->phy_qcfg_resp; + + if (bnge_update_link(bn, true)) + return; + + module_status =3D link_info->module_status; + switch (module_status) { + case PORT_PHY_QCFG_RESP_MODULE_STATUS_DISABLETX: + case PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN: + case PORT_PHY_QCFG_RESP_MODULE_STATUS_WARNINGMSG: + netdev_warn(bn->netdev, + "Unqualified SFP+ module detected on port %d\n", + bd->pf.port_id); + netdev_warn(bn->netdev, "Module part number %.*s\n", + (int)sizeof(resp->phy_vendor_partnumber), + resp->phy_vendor_partnumber); + if (module_status =3D=3D PORT_PHY_QCFG_RESP_MODULE_STATUS_DISABLETX) + netdev_warn(bn->netdev, "TX is disabled\n"); + if (module_status =3D=3D PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN) + netdev_warn(bn->netdev, "SFP+ module is shut down\n"); + break; + } +} + +static bool bnge_support_dropped(u16 advertising, u16 supported) +{ + return (advertising & ~supported) !=3D 0; +} + +bool bnge_support_speed_dropped(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + bool changed; + + link_info =3D &bd->link_info; + + /* Check if any advertised speeds are no longer supported. The caller + * holds the netdev instance lock, so we can modify link_info settings. + */ + changed =3D false; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + if (bnge_support_dropped(elink_info->advertising, + link_info->support_auto_speeds2)) { + elink_info->advertising =3D + link_info->support_auto_speeds2; + return true; + } + return false; + } + if (bnge_support_dropped(elink_info->advertising, + link_info->support_auto_speeds)) { + elink_info->advertising =3D link_info->support_auto_speeds; + changed =3D true; + } + if (bnge_support_dropped(elink_info->advertising_pam4, + link_info->support_pam4_auto_speeds)) { + elink_info->advertising_pam4 =3D + link_info->support_pam4_auto_speeds; + changed =3D true; + } + return changed; +} + +static char *bnge_report_fec(struct bnge_link_info *link_info) +{ + u8 active_fec =3D link_info->active_fec_sig_mode & + PORT_PHY_QCFG_RESP_ACTIVE_FEC_MASK; + + switch (active_fec) { + default: + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_NONE_ACTIVE: + return "None"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_CLAUSE74_ACTIVE: + return "Clause 74 BaseR"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_CLAUSE91_ACTIVE: + return "Clause 91 RS(528,514)"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS544_1XN_ACTIVE: + return "Clause 91 RS544_1XN"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS544_IEEE_ACTIVE: + return "Clause 91 RS(544,514)"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS272_1XN_ACTIVE: + return "Clause 91 RS272_1XN"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS272_IEEE_ACTIVE: + return "Clause 91 RS(272,257)"; + } +} + +void bnge_report_link(struct bnge_dev *bd) +{ + if (BNGE_LINK_IS_UP(bd)) { + const char *signal =3D ""; + const char *flow_ctrl; + const char *duplex; + u32 speed; + u16 fec; + + netif_carrier_on(bd->netdev); + speed =3D bnge_fw_to_ethtool_speed(bd->link_info.link_speed); + if (speed =3D=3D SPEED_UNKNOWN) { + netdev_info(bd->netdev, + "NIC Link is Up, speed unknown\n"); + return; + } + if (bd->link_info.duplex =3D=3D BNGE_LINK_DUPLEX_FULL) + duplex =3D "full"; + else + duplex =3D "half"; + if (bd->link_info.pause =3D=3D BNGE_LINK_PAUSE_BOTH) + flow_ctrl =3D "ON - receive & transmit"; + else if (bd->link_info.pause =3D=3D BNGE_LINK_PAUSE_TX) + flow_ctrl =3D "ON - transmit"; + else if (bd->link_info.pause =3D=3D BNGE_LINK_PAUSE_RX) + flow_ctrl =3D "ON - receive"; + else + flow_ctrl =3D "none"; + if (bd->link_info.phy_qcfg_resp.option_flags & + PORT_PHY_QCFG_RESP_OPTION_FLAGS_SIGNAL_MODE_KNOWN) { + u8 sig_mode =3D bd->link_info.active_fec_sig_mode & + PORT_PHY_QCFG_RESP_SIGNAL_MODE_MASK; + switch (sig_mode) { + case PORT_PHY_QCFG_RESP_SIGNAL_MODE_NRZ: + signal =3D "(NRZ) "; + break; + case PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4: + signal =3D "(PAM4 56Gbps) "; + break; + case PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4_112: + signal =3D "(PAM4 112Gbps) "; + break; + default: + break; + } + } + netdev_info(bd->netdev, "NIC Link is Up, %u Mbps %s%s duplex, Flow contr= ol: %s\n", + speed, signal, duplex, flow_ctrl); + fec =3D bd->link_info.fec_cfg; + if (!(fec & PORT_PHY_QCFG_RESP_FEC_CFG_FEC_NONE_SUPPORTED)) + netdev_info(bd->netdev, "FEC autoneg %s encoding: %s\n", + (fec & BNGE_FEC_AUTONEG) ? "on" : "off", + bnge_report_fec(&bd->link_info)); + } else { + netif_carrier_off(bd->netdev); + netdev_info(bd->netdev, "NIC Link is Down\n"); + } +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.h b/drivers/net/e= thernet/broadcom/bnge/bnge_link.h new file mode 100644 index 000000000000..f22dec2899e3 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2026 Broadcom */ + +#ifndef _BNGE_LINK_H_ +#define _BNGE_LINK_H_ + +#define BNGE_PHY_CFG_ABLE(bd) \ + ((bd)->link_info.phy_enabled) + +#define BNGE_PHY_AUTO_SPEEDS2_MASK \ + PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEEDS2_MASK +#define BNGE_PHY_AUTO_SPEED_MASK \ + PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK +#define BNGE_PHY_AUTO_PAM4_SPEED_MASK \ + PORT_PHY_CFG_REQ_ENABLES_AUTO_PAM4_LINK_SPEED_MASK +#define BNGE_PHY_FLAGS_RESTART_AUTO \ + PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG +#define BNGE_PHY_FLAGS_ENA_FORCE_SPEEDS2 \ + PORT_PHY_CFG_REQ_ENABLES_FORCE_LINK_SPEEDS2 +#define BNGE_PHY_FLAGS_ENA_FORCE_PM4_SPEED \ + PORT_PHY_CFG_REQ_ENABLES_FORCE_PAM4_LINK_SPEED + +#define BNGE_LINK_LINK PORT_PHY_QCFG_RESP_LINK_LINK + +enum bnge_link_state { + BNGE_LINK_STATE_UNKNOWN, + BNGE_LINK_STATE_DOWN, + BNGE_LINK_STATE_UP, +}; + +#define BNGE_LINK_IS_UP(bd) \ + ((bd)->link_info.link_state =3D=3D BNGE_LINK_STATE_UP) + +#define BNGE_LINK_DUPLEX_FULL PORT_PHY_QCFG_RESP_DUPLEX_STATE_FULL + +#define BNGE_LINK_PAUSE_TX PORT_PHY_QCFG_RESP_PAUSE_TX +#define BNGE_LINK_PAUSE_RX PORT_PHY_QCFG_RESP_PAUSE_RX +#define BNGE_LINK_PAUSE_BOTH (PORT_PHY_QCFG_RESP_PAUSE_RX | \ + PORT_PHY_QCFG_RESP_PAUSE_TX) + +#define BNGE_LINK_AUTO_NONE PORT_PHY_QCFG_RESP_AUTO_MODE_NONE +#define BNGE_LINK_AUTO_MSK PORT_PHY_QCFG_RESP_AUTO_MODE_SPEED_MASK +#define BNGE_AUTO_MODE(mode) ((mode) > BNGE_LINK_AUTO_NONE && \ + (mode) <=3D BNGE_LINK_AUTO_MSK) + +#define BNGE_LINK_SPEED_50GB PORT_PHY_QCFG_RESP_LINK_SPEED_50GB +#define BNGE_LINK_SPEED_100GB PORT_PHY_QCFG_RESP_LINK_SPEED_100GB +#define BNGE_LINK_SPEED_200GB PORT_PHY_QCFG_RESP_LINK_SPEED_200GB +#define BNGE_LINK_SPEED_400GB PORT_PHY_QCFG_RESP_LINK_SPEED_400GB +#define BNGE_LINK_SPEED_800GB PORT_PHY_QCFG_RESP_LINK_SPEED_800GB + +#define BNGE_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB +#define BNGE_LINK_SPEED_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100GB + +#define BNGE_LINK_PAM4_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEE= DS_50G +#define BNGE_LINK_PAM4_SPEED_MSK_100GB \ + PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_100G +#define BNGE_LINK_PAM4_SPEED_MSK_200GB \ + PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_200G + +#define BNGE_LINK_SPEEDS2_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_50GB +#define BNGE_LINK_SPEEDS2_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100= GB +#define BNGE_LINK_SPEEDS2_MSK_50GB_PAM4 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_50GB_PAM4_56 +#define BNGE_LINK_SPEEDS2_MSK_100GB_PAM4 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB_PAM4_56 +#define BNGE_LINK_SPEEDS2_MSK_200GB_PAM4 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_200GB_PAM4_56 +#define BNGE_LINK_SPEEDS2_MSK_400GB_PAM4 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_400GB_PAM4_56 +#define BNGE_LINK_SPEEDS2_MSK_100GB_PAM4_112 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB_PAM4_112 +#define BNGE_LINK_SPEEDS2_MSK_200GB_PAM4_112 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_200GB_PAM4_112 +#define BNGE_LINK_SPEEDS2_MSK_400GB_PAM4_112 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_400GB_PAM4_112 +#define BNGE_LINK_SPEEDS2_MSK_800GB_PAM4_112 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_800GB_PAM4_112 + +#define BNGE_LINK_SPEED_50GB_PAM4 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_50GB_PAM4_56 +#define BNGE_LINK_SPEED_100GB_PAM4 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_100GB_PAM4_56 +#define BNGE_LINK_SPEED_200GB_PAM4 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_200GB_PAM4_56 +#define BNGE_LINK_SPEED_400GB_PAM4 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_400GB_PAM4_56 +#define BNGE_LINK_SPEED_100GB_PAM4_112 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_100GB_PAM4_112 +#define BNGE_LINK_SPEED_200GB_PAM4_112 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_200GB_PAM4_112 +#define BNGE_LINK_SPEED_400GB_PAM4_112 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_400GB_PAM4_112 +#define BNGE_LINK_SPEED_800GB_PAM4_112 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_800GB_PAM4_112 + +#define BNGE_FEC_NONE PORT_PHY_QCFG_RESP_FEC_CFG_FEC_NONE_SUPPORTED +#define BNGE_FEC_AUTONEG PORT_PHY_QCFG_RESP_FEC_CFG_FEC_AUTONEG_ENABLED +#define BNGE_FEC_ENC_BASE_R_CAP \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE74_SUPPORTED +#define BNGE_FEC_ENC_BASE_R PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE74_ENABLED +#define BNGE_FEC_ENC_RS_CAP \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE91_SUPPORTED +#define BNGE_FEC_ENC_LLRS_CAP \ + (PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_1XN_SUPPORTED | \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_IEEE_SUPPORTED) +#define BNGE_FEC_ENC_RS \ + (PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE91_ENABLED | \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS544_1XN_ENABLED | \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS544_IEEE_ENABLED) +#define BNGE_FEC_ENC_LLRS \ + (PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_1XN_ENABLED | \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_IEEE_ENABLED) + +struct bnge_link_info { + u8 phy_type; + u8 media_type; + u8 phy_addr; + u8 phy_link_status; + bool phy_enabled; + + u8 link_state; + u8 active_lanes; + u8 duplex; + u8 pause; + u8 lp_pause; + u8 auto_pause_setting; + u8 force_pause_setting; + u8 duplex_setting; + u8 auto_mode; + u16 link_speed; + u16 support_speeds; + u16 support_pam4_speeds; + u16 support_speeds2; + + u16 auto_link_speeds; /* fw adv setting */ + u16 auto_pam4_link_speeds; + u16 auto_link_speeds2; + + u16 support_auto_speeds; + u16 support_pam4_auto_speeds; + u16 support_auto_speeds2; + + u16 lp_auto_link_speeds; + u16 lp_auto_pam4_link_speeds; + u16 force_link_speed; + u16 force_pam4_link_speed; + u16 force_link_speed2; + + u8 module_status; + u8 active_fec_sig_mode; + u16 fec_cfg; + + /* A copy of phy_qcfg output used to report link + * info to VF + */ + struct hwrm_port_phy_qcfg_output phy_qcfg_resp; + + bool phy_retry; + unsigned long phy_retry_expires; +}; + +#define BNGE_AUTONEG_SPEED 1 +#define BNGE_AUTONEG_FLOW_CTRL 2 + +#define BNGE_SIG_MODE_NRZ PORT_PHY_QCFG_RESP_SIGNAL_MODE_NRZ +#define BNGE_SIG_MODE_PAM4 PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4 +#define BNGE_SIG_MODE_PAM4_112 PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4_112 +#define BNGE_SIG_MODE_MAX (PORT_PHY_QCFG_RESP_SIGNAL_MODE_LAST + 1) + +struct bnge_ethtool_link_info { + /* copy of requested setting from ethtool cmd */ + u8 autoneg; + u8 req_signal_mode; + u8 req_duplex; + u8 req_flow_ctrl; + u16 req_link_speed; + u16 advertising; /* user adv setting */ + u16 advertising_pam4; + bool force_link_chng; +}; + +void bnge_hwrm_set_link_common(struct bnge_net *bn, + struct hwrm_port_phy_cfg_input *req); +void bnge_hwrm_set_pause_common(struct bnge_net *bn, + struct hwrm_port_phy_cfg_input *req); +int bnge_update_phy_setting(struct bnge_net *bn); +void bnge_get_port_module_status(struct bnge_net *bn); +void bnge_report_link(struct bnge_dev *bd); +bool bnge_support_speed_dropped(struct bnge_net *bn); +void bnge_init_ethtool_link_settings(struct bnge_net *bn); +int bnge_probe_phy(struct bnge_net *bn, bool fw_dflt); +#endif /* _BNGE_LINK_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 8d5d828e19a3..185f5bfce1d5 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -101,6 +101,17 @@ static int bnge_alloc_ring_stats(struct bnge_net *bn) return rc; } =20 +void __bnge_queue_sp_work(struct bnge_net *bn) +{ + queue_work(bn->bnge_pf_wq, &bn->sp_task); +} + +static void bnge_queue_sp_work(struct bnge_net *bn, unsigned int event) +{ + set_bit(event, &bn->sp_event); + __bnge_queue_sp_work(bn); +} + static void bnge_timer(struct timer_list *t) { struct bnge_net *bn =3D timer_container_of(bn, t, timer); @@ -110,7 +121,14 @@ static void bnge_timer(struct timer_list *t) !test_bit(BNGE_STATE_OPEN, &bd->state)) return; =20 - /* Periodic work added by later patches */ + if (READ_ONCE(bd->link_info.phy_retry)) { + if (time_after(jiffies, READ_ONCE(bd->link_info.phy_retry_expires))) { + WRITE_ONCE(bd->link_info.phy_retry, false); + netdev_warn(bn->netdev, "failed to update PHY settings after maximum re= tries.\n"); + } else { + bnge_queue_sp_work(bn, BNGE_UPDATE_PHY_SP_EVENT); + } + } =20 mod_timer(&bn->timer, jiffies + bn->current_interval); } @@ -126,7 +144,17 @@ static void bnge_sp_task(struct work_struct *work) return; } =20 - /* Event handling work added by later patches */ + if (test_and_clear_bit(BNGE_UPDATE_PHY_SP_EVENT, &bn->sp_event)) { + int rc; + + rc =3D bnge_update_phy_setting(bn); + if (rc) { + netdev_warn(bn->netdev, "update PHY settings retry failed\n"); + } else { + WRITE_ONCE(bd->link_info.phy_retry, false); + netdev_info(bn->netdev, "update PHY settings retry succeeded\n"); + } + } =20 netdev_unlock(bn->netdev); } @@ -2496,6 +2524,8 @@ static void bnge_tx_enable(struct bnge_net *bn) /* Make sure napi polls see @dev_state change */ synchronize_net(); netif_tx_wake_all_queues(bn->netdev); + if (BNGE_LINK_IS_UP(bn->bd)) + netif_carrier_on(bn->netdev); } =20 static int bnge_open_core(struct bnge_net *bn) @@ -2532,6 +2562,16 @@ static int bnge_open_core(struct bnge_net *bn) =20 bnge_enable_napi(bn); =20 + rc =3D bnge_update_phy_setting(bn); + if (rc) { + netdev_warn(bn->netdev, "failed to update PHY settings (rc: %d)\n", + rc); + WRITE_ONCE(bd->link_info.phy_retry_expires, jiffies + 5 * HZ); + WRITE_ONCE(bd->link_info.phy_retry, true); + } else { + WRITE_ONCE(bd->link_info.phy_retry, false); + } + set_bit(BNGE_STATE_OPEN, &bd->state); =20 bnge_enable_int(bn); @@ -2540,6 +2580,9 @@ static int bnge_open_core(struct bnge_net *bn) =20 mod_timer(&bn->timer, jiffies + bn->current_interval); =20 + /* Poll link status and check for SFP+ module status */ + bnge_get_port_module_status(bn); + return 0; =20 err_free_irq: @@ -2591,6 +2634,8 @@ static int bnge_close(struct net_device *dev) struct bnge_net *bn =3D netdev_priv(dev); =20 bnge_close_core(bn); + bnge_hwrm_shutdown_link(bn->bd); + bn->sp_event =3D 0; =20 return 0; } @@ -2832,6 +2877,10 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_i= rqs) bnge_init_l2_fltr_tbl(bn); bnge_init_mac_addr(bd); =20 + rc =3D bnge_probe_phy(bn, true); + if (rc) + goto err_free_workq; + netdev->request_ops_lock =3D true; rc =3D register_netdev(netdev); if (rc) { @@ -2859,6 +2908,7 @@ void bnge_netdev_free(struct bnge_dev *bd) =20 timer_shutdown_sync(&bn->timer); cancel_work_sync(&bn->sp_task); + bn->sp_event =3D 0; destroy_workqueue(bn->bnge_pf_wq); =20 free_netdev(netdev); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index d2ccee725454..5636eb371e24 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -9,6 +9,7 @@ #include #include "bnge_db.h" #include "bnge_hw_def.h" +#include "bnge_link.h" =20 struct tx_bd { __le32 tx_bd_len_flags_type; @@ -230,6 +231,13 @@ enum bnge_net_state { =20 #define BNGE_TIMER_INTERVAL HZ =20 +enum bnge_sp_event { + BNGE_LINK_CHNG_SP_EVENT, + BNGE_LINK_SPEED_CHNG_SP_EVENT, + BNGE_LINK_CFG_CHANGE_SP_EVENT, + BNGE_UPDATE_PHY_SP_EVENT, +}; + struct bnge_net { struct bnge_dev *bd; struct net_device *netdev; @@ -298,6 +306,9 @@ struct bnge_net { struct timer_list timer; struct workqueue_struct *bnge_pf_wq; struct work_struct sp_task; + unsigned long sp_event; + + struct bnge_ethtool_link_info eth_link_info; }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 @@ -576,4 +587,5 @@ u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dma_addr_= t *mapping, struct bnge_rx_ring_info *rxr, gfp_t gfp); int bnge_alloc_rx_netmem(struct bnge_net *bn, struct bnge_rx_ring_info *rx= r, u16 prod, gfp_t gfp); +void __bnge_queue_sp_work(struct bnge_net *bn); #endif /* _BNGE_NETDEV_H_ */ --=20 2.47.3 From nobody Sun Apr 5 18:20:21 2026 Received: from mail-dy1-f228.google.com (mail-dy1-f228.google.com [74.125.82.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1048337C110 for ; Fri, 3 Apr 2026 07:38:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201908; cv=none; b=ml+xcYpCnSdg9ZK3H9z+BfnQLKA9hBxH7SHyPdXFIe5gAEEGmgQ9Unn3rMi5FDKa16XT6BMpRH8zB/xCNdoEVldYToGVQ/NN+2pgdcmLmpkvriFkaJbSiw/I/lMlSBKqpxs+kFSmoEgzPplRjZfsgrFejEa5FwmJGYTtEsi7gR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201908; c=relaxed/simple; bh=DqGPlhYaiG1O7JEDHqWa3H1d/pI4tw6HguKXBEaa6uQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mBOogqPBOh+1CTB0//kpCSArwcUKnXR5sL6FGK7QmBPxJQddkq7XBjttqoazywnXadrHK/Fr4NLAtSFvp6mThUftLGU+M1KGffx/g7TFguQ9VbwOkEjNsQIooK9RujgK2jdh/FNwsCkVKC6M71D0zcdu/AP88KUdHXKgw5u5z/w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=JsLfToOV; arc=none smtp.client-ip=74.125.82.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="JsLfToOV" Received: by mail-dy1-f228.google.com with SMTP id 5a478bee46e88-2cc1534e026so381547eec.1 for ; Fri, 03 Apr 2026 00:38:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201905; x=1775806705; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=1TuJSf0S4A1OFv0Em3mX7J7RcRrShBjLGY8NVX2zF+s=; b=EdKG/MKZCILWnGJ5CEiAx4OzrmF/zlRW9+5tdduYf23MAwkgqa6ttRFd7l7b424Zo7 Db6K+VMUBfmx15t7WeensIWHnZd+8pZiWMH+bmhaOf7+K07PPJMD5YBXJBXGbg4gRZxE NK03psyY6/myraiYbsvlnD4y9G5se4p1vT1quoJUw1uT0s7itm8bzzlBAtD/JVJzQN8G FJbuloVKH/9zxIZLYeSing2TQJIuKdOa14XJK+JdNMAParOnS3jymyuoye7mzErpxhof U3teB5q5XPYEsnh0meSvF0HJkcJ8g1rxj/aQJn230WLHaoC5FBzfGl1d30SB/gZ6kBKP N0Eg== X-Forwarded-Encrypted: i=1; AJvYcCXRjXI5SJl2lpbq9B8XWWXJ/RyHU+BjP4clhAqrLG5TRY4CVg9w+d7A9caY1sZqUapgIpNQycN9y1l/gGk=@vger.kernel.org X-Gm-Message-State: AOJu0YxrTIJZ9WB0LT+McMcpTSwjRmVoRhd6D6Eqh5IlYvzRRoDDZmhg aLlX1pJrQkzq9HJ5O5ZUNEW/fkqKuyMeZehCEd+auvsiR6EgzLZ2fplc0bwf/qqopXdmue2twpy go+Ga/1jiHkRFtgVU2IwEpb4WGW1PtHmOcz/VoI8n2sGh9FHOpzM++PgD2g0NuksjJ+WDH4MmYq uKAjtexgRQCxijtIxU620Kk5gJE/mMnhTXMYwW6FfelebS0wE3Cjy+DGT/i3KuRu6dphe0Ez7Zt U8MuqX8t8k5VcrHVp5xzBTZvw== X-Gm-Gg: AeBDietMMM20Ck4z1UEIYe4vZIeIe6ulzkPC7but3RA3NlTYOvCDkXCphTc4EBXWctU W1IOCibEVTwUyF11fFM4pcFtZ8nRDU2qcCa6nJTC2ku0fK4XkH1O8Lpc/+n7pum85E0M9Q4c3wq L6fHaRtvPjyhI3W2HT3V2yiDaZndm70pFaL9xzHUWSKcIvr2W0csYClnZhqBmj8HU0QWivhqOP+ OQtRBbc9N0Tpn5Imhe2H8E/R78xNboDHAzSM/dF3YMo84m9BxmY/NSUaaporkJqRnvfSi5nCBBY pPntp+c+3Bvk56iI42kPXBEJamsropcXzBY/tmLvGDmclQK+wDDN7MjlKUTzRrcguaSrWGFZe2T rb0pWcIcxQnLUMZr76mXdyd+GwlqQkO5S5rh3RYAP0nntN/Aco1mo+N1ORvEbY6fs3UP1a0WL6Q 3Nv2djVZZC/7IR8kTEIzZpoQ17lqMj3jsLLmwQQbtavfuEL6xb5bn77/k139ZyGaU= X-Received: by 2002:a05:7301:5793:b0:2c5:3b87:2ffc with SMTP id 5a478bee46e88-2cbf950387dmr1032154eec.7.1775201904954; Fri, 03 Apr 2026 00:38:24 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-24.dlp.protect.broadcom.com. [144.49.247.24]) by smtp-relay.gmail.com with ESMTPS id 5a478bee46e88-2cc804c237csm40831eec.8.2026.04.03.00.38.24 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:24 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f71.google.com with SMTP id 98e67ed59e1d1-35da99b90f6so2044079a91.1 for ; Fri, 03 Apr 2026 00:38:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201903; x=1775806703; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1TuJSf0S4A1OFv0Em3mX7J7RcRrShBjLGY8NVX2zF+s=; b=JsLfToOVjINqoR8NWI0+edfC4MncMkicwMreS02GHPY934n8CgkkKGHiyhN72kfA6c qbvoASmio0zJb9yRrmXlBEwD+wnS5ntbNankFiRErFCQoKFL7OmEk0mNFyNgo7sA2qrk HZI4yFMKkFwBefjsgRzF/0n4W73SVtUB5ymQQ= X-Forwarded-Encrypted: i=1; AJvYcCVVWS110PvOZVuLsGjB49u3XdjXBZF6WhycX2stsvXM9tMdEikCXH8aJGCbGYgiStB8DNDJd6biG5Gf2z0=@vger.kernel.org X-Received: by 2002:a17:90a:dfc3:b0:35b:e529:2d60 with SMTP id 98e67ed59e1d1-35de68712b0mr1732972a91.8.1775201902951; Fri, 03 Apr 2026 00:38:22 -0700 (PDT) X-Received: by 2002:a17:90a:dfc3:b0:35b:e529:2d60 with SMTP id 98e67ed59e1d1-35de68712b0mr1732952a91.8.1775201902337; Fri, 03 Apr 2026 00:38:22 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:21 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula , Ajit Kumar Khaparde Subject: [PATCH net-next v11 03/10] bng_en: add ethtool link settings, get_link, and nway_reset Date: Fri, 3 Apr 2026 13:07:17 +0530 Message-ID: <20260403073724.194360-4-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Add get/set_link_ksettings, get_link, and nway_reset support. Report supported, advertised, and link-partner speeds across NRZ, PAM4, and PAM4-112 signaling modes. Enable lane count reporting. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula Reviewed-by: Ajit Kumar Khaparde --- drivers/net/ethernet/broadcom/bnge/bnge.h | 2 + .../net/ethernet/broadcom/bnge/bnge_core.c | 1 + .../net/ethernet/broadcom/bnge/bnge_ethtool.c | 28 + .../net/ethernet/broadcom/bnge/bnge_link.c | 809 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_link.h | 7 + 5 files changed, 847 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethern= et/broadcom/bnge/bnge.h index 83ee4749cc70..e9b83c0c64b6 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h @@ -98,6 +98,8 @@ struct bnge_queue_info { #define BNGE_PHY_FL_NO_FCS PORT_PHY_QCAPS_RESP_FLAGS_NO_FCS #define BNGE_PHY_FL_SPEEDS2 \ (PORT_PHY_QCAPS_RESP_FLAGS2_SPEEDS2_SUPPORTED << 8) +#define BNGE_PHY_FL_NO_PAUSE \ + (PORT_PHY_QCAPS_RESP_FLAGS2_PAUSE_UNSUPPORTED << 8) =20 struct bnge_dev { struct device *dev; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/e= thernet/broadcom/bnge/bnge_core.c index b4090283df0f..1c14c5fe8d61 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c @@ -10,6 +10,7 @@ #include "bnge_devlink.h" #include "bnge_hwrm.h" #include "bnge_hwrm_lib.h" +#include "bnge_link.h" =20 MODULE_LICENSE("GPL"); MODULE_DESCRIPTION(DRV_SUMMARY); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c b/drivers/ne= t/ethernet/broadcom/bnge/bnge_ethtool.c index 569371c1b4f2..6bb74a84ea03 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c @@ -11,6 +11,29 @@ =20 #include "bnge.h" #include "bnge_ethtool.h" +#include "bnge_hwrm_lib.h" + +static int bnge_nway_reset(struct net_device *dev) +{ + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_dev *bd =3D bn->bd; + bool set_pause =3D false; + int rc =3D 0; + + if (!BNGE_PHY_CFG_ABLE(bd)) + return -EOPNOTSUPP; + + if (!(bn->eth_link_info.autoneg & BNGE_AUTONEG_SPEED)) + return -EINVAL; + + if (!(bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) + set_pause =3D true; + + if (netif_running(dev)) + rc =3D bnge_hwrm_set_link_setting(bn, set_pause); + + return rc; +} =20 static void bnge_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) @@ -24,7 +47,12 @@ static void bnge_get_drvinfo(struct net_device *dev, } =20 static const struct ethtool_ops bnge_ethtool_ops =3D { + .cap_link_lanes_supported =3D 1, + .get_link_ksettings =3D bnge_get_link_ksettings, + .set_link_ksettings =3D bnge_set_link_ksettings, .get_drvinfo =3D bnge_get_drvinfo, + .get_link =3D bnge_get_link, + .nway_reset =3D bnge_nway_reset, }; =20 void bnge_set_ethtool_ops(struct net_device *dev) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.c b/drivers/net/e= thernet/broadcom/bnge/bnge_link.c index f7e4d59f98ff..d8236a5daef2 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_link.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.c @@ -7,6 +7,51 @@ #include "bnge_link.h" #include "bnge_hwrm_lib.h" =20 +enum bnge_media_type { + BNGE_MEDIA_UNKNOWN =3D 0, + BNGE_MEDIA_CR, + BNGE_MEDIA_SR, + BNGE_MEDIA_LR_ER_FR, + BNGE_MEDIA_KR, + __BNGE_MEDIA_END, +}; + +static const enum bnge_media_type bnge_phy_types[] =3D { + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR4] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR4] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR10] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASECR4] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASESR4] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASELR4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASEER4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASECR] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASESR] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASELR] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASEER] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR2] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR2] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR2] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER2] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASECR2] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASESR2] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASELR2] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASEER2] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASECR8] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASESR8] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASELR8] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASEER8] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASECR4] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASESR4] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASELR4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASEER4] =3D BNGE_MEDIA_LR_ER_FR, +}; + static u32 bnge_fw_to_ethtool_speed(u16 fw_link_speed) { switch (fw_link_speed) { @@ -341,6 +386,19 @@ void bnge_get_port_module_status(struct bnge_net *bn) } } =20 +static void bnge_set_default_adv_speeds(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info =3D &bn->bd->link_info; + + if (bn->bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + elink_info->advertising =3D link_info->support_auto_speeds2; + return; + } + elink_info->advertising =3D link_info->support_auto_speeds; + elink_info->advertising_pam4 =3D link_info->support_pam4_auto_speeds; +} + static bool bnge_support_dropped(u16 advertising, u16 supported) { return (advertising & ~supported) !=3D 0; @@ -465,3 +523,754 @@ void bnge_report_link(struct bnge_dev *bd) netdev_info(bd->netdev, "NIC Link is Down\n"); } } + +static void bnge_get_ethtool_modes(struct bnge_net *bn, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_ethtool_link_info *elink_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + elink_info =3D &bn->eth_link_info; + link_info =3D &bd->link_info; + + if (!(bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) { + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, + lk_ksettings->link_modes.supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + lk_ksettings->link_modes.supported); + } + + if (link_info->support_auto_speeds || link_info->support_auto_speeds2 || + link_info->support_pam4_auto_speeds) + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + lk_ksettings->link_modes.supported); + + if (~elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) + return; + + if (link_info->auto_pause_setting & BNGE_LINK_PAUSE_RX) + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, + lk_ksettings->link_modes.advertising); + if (hweight8(link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH) =3D=3D= 1) + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + lk_ksettings->link_modes.advertising); + if (link_info->lp_pause & BNGE_LINK_PAUSE_RX) + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, + lk_ksettings->link_modes.lp_advertising); + if (hweight8(link_info->lp_pause & BNGE_LINK_PAUSE_BOTH) =3D=3D 1) + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + lk_ksettings->link_modes.lp_advertising); +} + +u32 bnge_get_link(struct net_device *dev) +{ + struct bnge_net *bn =3D netdev_priv(dev); + + return BNGE_LINK_IS_UP(bn->bd); +} + +static enum bnge_media_type +bnge_get_media(struct bnge_link_info *link_info) +{ + switch (link_info->media_type) { + case PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC: + return BNGE_MEDIA_CR; + default: + if (link_info->phy_type < ARRAY_SIZE(bnge_phy_types)) + return bnge_phy_types[link_info->phy_type]; + return BNGE_MEDIA_UNKNOWN; + } +} + +enum bnge_link_speed_indices { + BNGE_LINK_SPEED_UNKNOWN =3D 0, + BNGE_LINK_SPEED_50GB_IDX, + BNGE_LINK_SPEED_100GB_IDX, + BNGE_LINK_SPEED_200GB_IDX, + BNGE_LINK_SPEED_400GB_IDX, + BNGE_LINK_SPEED_800GB_IDX, + __BNGE_LINK_SPEED_END +}; + +static enum bnge_link_speed_indices bnge_fw_speed_idx(u16 speed) +{ + switch (speed) { + case BNGE_LINK_SPEED_50GB: + case BNGE_LINK_SPEED_50GB_PAM4: + return BNGE_LINK_SPEED_50GB_IDX; + case BNGE_LINK_SPEED_100GB: + case BNGE_LINK_SPEED_100GB_PAM4: + case BNGE_LINK_SPEED_100GB_PAM4_112: + return BNGE_LINK_SPEED_100GB_IDX; + case BNGE_LINK_SPEED_200GB: + case BNGE_LINK_SPEED_200GB_PAM4: + case BNGE_LINK_SPEED_200GB_PAM4_112: + return BNGE_LINK_SPEED_200GB_IDX; + case BNGE_LINK_SPEED_400GB: + case BNGE_LINK_SPEED_400GB_PAM4: + case BNGE_LINK_SPEED_400GB_PAM4_112: + return BNGE_LINK_SPEED_400GB_IDX; + case BNGE_LINK_SPEED_800GB: + case BNGE_LINK_SPEED_800GB_PAM4_112: + return BNGE_LINK_SPEED_800GB_IDX; + default: + return BNGE_LINK_SPEED_UNKNOWN; + } +} + +/* Compile-time link mode mapping table. + * Indexed by [speed_idx][sig_mode][media]. + */ +#define BNGE_LINK_M(speed, sig, media, lm) \ + [BNGE_LINK_SPEED_##speed##_IDX] \ + [BNGE_SIG_MODE_##sig] \ + [BNGE_MEDIA_##media] =3D ETHTOOL_LINK_MODE_##lm##_Full_BIT + +static const enum ethtool_link_mode_bit_indices +bnge_link_modes[__BNGE_LINK_SPEED_END] + [BNGE_SIG_MODE_MAX] + [__BNGE_MEDIA_END] =3D { + /* 50GB PAM4 */ + BNGE_LINK_M(50GB, PAM4, CR, 50000baseCR), + BNGE_LINK_M(50GB, PAM4, SR, 50000baseSR), + BNGE_LINK_M(50GB, PAM4, LR_ER_FR, 50000baseLR_ER_FR), + BNGE_LINK_M(50GB, PAM4, KR, 50000baseKR), + + /* 100GB NRZ */ + BNGE_LINK_M(100GB, NRZ, CR, 100000baseCR4), + BNGE_LINK_M(100GB, NRZ, SR, 100000baseSR4), + BNGE_LINK_M(100GB, NRZ, LR_ER_FR, 100000baseLR4_ER4), + BNGE_LINK_M(100GB, NRZ, KR, 100000baseKR4), + + /* 100GB PAM4 */ + BNGE_LINK_M(100GB, PAM4, CR, 100000baseCR2), + BNGE_LINK_M(100GB, PAM4, SR, 100000baseSR2), + BNGE_LINK_M(100GB, PAM4, LR_ER_FR, 100000baseLR2_ER2_FR2), + BNGE_LINK_M(100GB, PAM4, KR, 100000baseKR2), + + /* 100GB PAM4_112 */ + BNGE_LINK_M(100GB, PAM4_112, CR, 100000baseCR), + BNGE_LINK_M(100GB, PAM4_112, SR, 100000baseSR), + BNGE_LINK_M(100GB, PAM4_112, LR_ER_FR, 100000baseLR_ER_FR), + BNGE_LINK_M(100GB, PAM4_112, KR, 100000baseKR), + + /* 200GB PAM4 */ + BNGE_LINK_M(200GB, PAM4, CR, 200000baseCR4), + BNGE_LINK_M(200GB, PAM4, SR, 200000baseSR4), + BNGE_LINK_M(200GB, PAM4, LR_ER_FR, 200000baseLR4_ER4_FR4), + BNGE_LINK_M(200GB, PAM4, KR, 200000baseKR4), + + /* 200GB PAM4_112 */ + BNGE_LINK_M(200GB, PAM4_112, CR, 200000baseCR2), + BNGE_LINK_M(200GB, PAM4_112, SR, 200000baseSR2), + BNGE_LINK_M(200GB, PAM4_112, LR_ER_FR, 200000baseLR2_ER2_FR2), + BNGE_LINK_M(200GB, PAM4_112, KR, 200000baseKR2), + + /* 400GB PAM4 */ + BNGE_LINK_M(400GB, PAM4, CR, 400000baseCR8), + BNGE_LINK_M(400GB, PAM4, SR, 400000baseSR8), + BNGE_LINK_M(400GB, PAM4, LR_ER_FR, 400000baseLR8_ER8_FR8), + BNGE_LINK_M(400GB, PAM4, KR, 400000baseKR8), + + /* 400GB PAM4_112 */ + BNGE_LINK_M(400GB, PAM4_112, CR, 400000baseCR4), + BNGE_LINK_M(400GB, PAM4_112, SR, 400000baseSR4), + BNGE_LINK_M(400GB, PAM4_112, LR_ER_FR, 400000baseLR4_ER4_FR4), + BNGE_LINK_M(400GB, PAM4_112, KR, 400000baseKR4), + + /* 800GB PAM4_112 */ + BNGE_LINK_M(800GB, PAM4_112, CR, 800000baseCR8), + BNGE_LINK_M(800GB, PAM4_112, SR, 800000baseSR8), + BNGE_LINK_M(800GB, PAM4_112, KR, 800000baseKR8), +}; + +#define BNGE_LINK_MODE_UNKNOWN -1 + +static enum ethtool_link_mode_bit_indices +bnge_get_link_mode(struct bnge_net *bn) +{ + enum ethtool_link_mode_bit_indices link_mode; + struct bnge_ethtool_link_info *elink_info; + enum bnge_link_speed_indices speed; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + enum bnge_media_type media; + u8 sig_mode; + + elink_info =3D &bn->eth_link_info; + link_info =3D &bd->link_info; + + if (link_info->phy_link_status !=3D BNGE_LINK_LINK) + return BNGE_LINK_MODE_UNKNOWN; + + media =3D bnge_get_media(link_info); + if (BNGE_AUTO_MODE(link_info->auto_mode)) { + speed =3D bnge_fw_speed_idx(link_info->link_speed); + sig_mode =3D link_info->active_fec_sig_mode & + PORT_PHY_QCFG_RESP_SIGNAL_MODE_MASK; + } else { + speed =3D bnge_fw_speed_idx(elink_info->req_link_speed); + sig_mode =3D elink_info->req_signal_mode; + } + if (sig_mode >=3D BNGE_SIG_MODE_MAX) + return BNGE_LINK_MODE_UNKNOWN; + + /* Since ETHTOOL_LINK_MODE_10baseT_Half_BIT is defined as 0 and + * not actually supported, the zeroes in this map can be safely + * used to represent unknown link modes. + */ + link_mode =3D bnge_link_modes[speed][sig_mode][media]; + if (!link_mode) + return BNGE_LINK_MODE_UNKNOWN; + + return link_mode; +} + +static const u16 bnge_nrz_speed_masks[__BNGE_LINK_SPEED_END] =3D { + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_SPEED_MSK_100GB, +}; + +static const u16 bnge_pam4_speed_masks[__BNGE_LINK_SPEED_END] =3D { + [BNGE_LINK_SPEED_50GB_IDX] =3D BNGE_LINK_PAM4_SPEED_MSK_50GB, + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_PAM4_SPEED_MSK_100GB, + [BNGE_LINK_SPEED_200GB_IDX] =3D BNGE_LINK_PAM4_SPEED_MSK_200GB, +}; + +static const u16 bnge_nrz_speeds2_masks[__BNGE_LINK_SPEED_END] =3D { + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_100GB, +}; + +static const u16 bnge_pam4_speeds2_masks[__BNGE_LINK_SPEED_END] =3D { + [BNGE_LINK_SPEED_50GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_50GB_PAM4, + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_100GB_PAM4, + [BNGE_LINK_SPEED_200GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_200GB_PAM4, + [BNGE_LINK_SPEED_400GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_400GB_PAM4, +}; + +static const u16 bnge_pam4_112_speeds2_masks[__BNGE_LINK_SPEED_END] =3D { + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_100GB_PAM4_112, + [BNGE_LINK_SPEED_200GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_200GB_PAM4_112, + [BNGE_LINK_SPEED_400GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_400GB_PAM4_112, + [BNGE_LINK_SPEED_800GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_800GB_PAM4_112, +}; + +static enum bnge_link_speed_indices +bnge_encoding_speed_idx(u8 sig_mode, u32 phy_flags, u16 speed_msk) +{ + const u16 *speeds; + int idx, len; + + switch (sig_mode) { + case BNGE_SIG_MODE_NRZ: + if (phy_flags & BNGE_PHY_FL_SPEEDS2) { + speeds =3D bnge_nrz_speeds2_masks; + len =3D ARRAY_SIZE(bnge_nrz_speeds2_masks); + } else { + speeds =3D bnge_nrz_speed_masks; + len =3D ARRAY_SIZE(bnge_nrz_speed_masks); + } + break; + case BNGE_SIG_MODE_PAM4: + if (phy_flags & BNGE_PHY_FL_SPEEDS2) { + speeds =3D bnge_pam4_speeds2_masks; + len =3D ARRAY_SIZE(bnge_pam4_speeds2_masks); + } else { + speeds =3D bnge_pam4_speed_masks; + len =3D ARRAY_SIZE(bnge_pam4_speed_masks); + } + break; + case BNGE_SIG_MODE_PAM4_112: + speeds =3D bnge_pam4_112_speeds2_masks; + len =3D ARRAY_SIZE(bnge_pam4_112_speeds2_masks); + break; + default: + return BNGE_LINK_SPEED_UNKNOWN; + } + + for (idx =3D 0; idx < len; idx++) { + if (speeds[idx] =3D=3D speed_msk) + return idx; + } + + return BNGE_LINK_SPEED_UNKNOWN; +} + +#define BNGE_FW_SPEED_MSK_BITS 16 + +static void +__bnge_get_ethtool_speeds(unsigned long fw_mask, enum bnge_media_type medi= a, + u8 sig_mode, u32 phy_flags, unsigned long *et_mask) +{ + enum ethtool_link_mode_bit_indices link_mode; + enum bnge_link_speed_indices speed; + u8 bit; + + for_each_set_bit(bit, &fw_mask, BNGE_FW_SPEED_MSK_BITS) { + speed =3D bnge_encoding_speed_idx(sig_mode, phy_flags, 1 << bit); + if (!speed) + continue; + + link_mode =3D bnge_link_modes[speed][sig_mode][media]; + if (!link_mode) + continue; + + linkmode_set_bit(link_mode, et_mask); + } +} + +static void +bnge_get_ethtool_speeds(unsigned long fw_mask, enum bnge_media_type media, + u8 sig_mode, u32 phy_flags, unsigned long *et_mask) +{ + if (media) { + __bnge_get_ethtool_speeds(fw_mask, media, sig_mode, phy_flags, + et_mask); + return; + } + + /* list speeds for all media if unknown */ + for (media =3D 1; media < __BNGE_MEDIA_END; media++) + __bnge_get_ethtool_speeds(fw_mask, media, sig_mode, phy_flags, + et_mask); +} + +static void +bnge_get_all_ethtool_support_speeds(struct bnge_dev *bd, + enum bnge_media_type media, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_link_info *link_info =3D &bd->link_info; + u16 sp_nrz, sp_pam4, sp_pam4_112 =3D 0; + u32 phy_flags =3D bd->phy_flags; + + if (phy_flags & BNGE_PHY_FL_SPEEDS2) { + sp_nrz =3D link_info->support_speeds2; + sp_pam4 =3D link_info->support_speeds2; + sp_pam4_112 =3D link_info->support_speeds2; + } else { + sp_nrz =3D link_info->support_speeds; + sp_pam4 =3D link_info->support_pam4_speeds; + } + bnge_get_ethtool_speeds(sp_nrz, media, BNGE_SIG_MODE_NRZ, phy_flags, + lk_ksettings->link_modes.supported); + bnge_get_ethtool_speeds(sp_pam4, media, BNGE_SIG_MODE_PAM4, phy_flags, + lk_ksettings->link_modes.supported); + bnge_get_ethtool_speeds(sp_pam4_112, media, BNGE_SIG_MODE_PAM4_112, + phy_flags, lk_ksettings->link_modes.supported); +} + +static void +bnge_get_all_ethtool_adv_speeds(struct bnge_net *bn, + enum bnge_media_type media, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + u16 sp_nrz, sp_pam4, sp_pam4_112 =3D 0; + struct bnge_dev *bd =3D bn->bd; + u32 phy_flags; + + phy_flags =3D bd->phy_flags; + sp_nrz =3D elink_info->advertising; + + if (phy_flags & BNGE_PHY_FL_SPEEDS2) { + sp_pam4 =3D elink_info->advertising; + sp_pam4_112 =3D elink_info->advertising; + } else { + sp_pam4 =3D elink_info->advertising_pam4; + } + bnge_get_ethtool_speeds(sp_nrz, media, BNGE_SIG_MODE_NRZ, phy_flags, + lk_ksettings->link_modes.advertising); + bnge_get_ethtool_speeds(sp_pam4, media, BNGE_SIG_MODE_PAM4, phy_flags, + lk_ksettings->link_modes.advertising); + bnge_get_ethtool_speeds(sp_pam4_112, media, BNGE_SIG_MODE_PAM4_112, + phy_flags, + lk_ksettings->link_modes.advertising); +} + +static void +bnge_get_all_ethtool_lp_speeds(struct bnge_dev *bd, + enum bnge_media_type media, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_link_info *link_info =3D &bd->link_info; + u16 sp_nrz, sp_pam4, sp_pam4_112 =3D 0; + u32 phy_flags =3D bd->phy_flags; + + if (phy_flags & BNGE_PHY_FL_SPEEDS2) { + sp_nrz =3D link_info->lp_auto_link_speeds; + sp_pam4 =3D link_info->lp_auto_link_speeds; + sp_pam4_112 =3D link_info->lp_auto_link_speeds; + } else { + sp_nrz =3D link_info->lp_auto_link_speeds; + sp_pam4 =3D link_info->lp_auto_pam4_link_speeds; + } + + bnge_get_ethtool_speeds(sp_nrz, media, BNGE_SIG_MODE_NRZ, phy_flags, + lk_ksettings->link_modes.lp_advertising); + bnge_get_ethtool_speeds(sp_pam4, media, BNGE_SIG_MODE_PAM4, phy_flags, + lk_ksettings->link_modes.lp_advertising); + bnge_get_ethtool_speeds(sp_pam4_112, media, BNGE_SIG_MODE_PAM4_112, + phy_flags, + lk_ksettings->link_modes.lp_advertising); +} + +static void bnge_update_speed(u32 *delta, bool installed_media, u16 *speed= s, + u16 speed_msk, const unsigned long *et_mask, + enum ethtool_link_mode_bit_indices mode) +{ + bool mode_desired =3D linkmode_test_bit(mode, et_mask); + + if (!mode || !mode_desired) + return; + + /* installed media takes priority; for non-installed media, only allow + * one change per fw_speed bit (many to one mapping). + */ + if (installed_media || !(*delta & speed_msk)) { + *speeds |=3D speed_msk; + *delta |=3D speed_msk; + } +} + +static void bnge_set_ethtool_speeds(struct bnge_net *bn, + const unsigned long *et_mask) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + u16 const *sp_msks, *sp_pam4_msks, *sp_pam4_112_msks =3D NULL; + u16 *adv, *adv_pam4, *adv_pam4_112 =3D NULL; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + enum bnge_media_type media; + u32 delta_pam4_112 =3D 0; + u32 delta_pam4 =3D 0; + u32 delta_nrz =3D 0; + int i, m; + + /* Zero out the masks before accumulating new bits */ + elink_info->advertising =3D 0; + elink_info->advertising_pam4 =3D 0; + + link_info =3D &bd->link_info; + media =3D bnge_get_media(link_info); + adv =3D &elink_info->advertising; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + adv_pam4 =3D &elink_info->advertising; + adv_pam4_112 =3D &elink_info->advertising; + sp_msks =3D bnge_nrz_speeds2_masks; + sp_pam4_msks =3D bnge_pam4_speeds2_masks; + sp_pam4_112_msks =3D bnge_pam4_112_speeds2_masks; + } else { + adv_pam4 =3D &elink_info->advertising_pam4; + sp_msks =3D bnge_nrz_speed_masks; + sp_pam4_msks =3D bnge_pam4_speed_masks; + } + for (i =3D 1; i < __BNGE_LINK_SPEED_END; i++) { + /* accept any legal media from user */ + for (m =3D 1; m < __BNGE_MEDIA_END; m++) { + bnge_update_speed(&delta_nrz, m =3D=3D media, + adv, sp_msks[i], et_mask, + bnge_link_modes[i][BNGE_SIG_MODE_NRZ][m]); + bnge_update_speed(&delta_pam4, m =3D=3D media, + adv_pam4, sp_pam4_msks[i], et_mask, + bnge_link_modes[i][BNGE_SIG_MODE_PAM4][m]); + if (!adv_pam4_112) + continue; + + bnge_update_speed(&delta_pam4_112, m =3D=3D media, + adv_pam4_112, sp_pam4_112_msks[i], + et_mask, + bnge_link_modes[i][BNGE_SIG_MODE_PAM4_112][m]); + } + } +} + +static void +bnge_fw_to_ethtool_advertised_fec(struct bnge_link_info *link_info, + struct ethtool_link_ksettings *lk_ksettings) +{ + u16 fec_cfg =3D link_info->fec_cfg; + + if ((fec_cfg & BNGE_FEC_NONE) || !(fec_cfg & BNGE_FEC_AUTONEG)) { + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, + lk_ksettings->link_modes.advertising); + return; + } + if (fec_cfg & BNGE_FEC_ENC_BASE_R) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT, + lk_ksettings->link_modes.advertising); + if (fec_cfg & BNGE_FEC_ENC_RS) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, + lk_ksettings->link_modes.advertising); + if (fec_cfg & BNGE_FEC_ENC_LLRS) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_LLRS_BIT, + lk_ksettings->link_modes.advertising); +} + +static void +bnge_fw_to_ethtool_support_fec(struct bnge_link_info *link_info, + struct ethtool_link_ksettings *lk_ksettings) +{ + u16 fec_cfg =3D link_info->fec_cfg; + + if (fec_cfg & BNGE_FEC_NONE) { + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, + lk_ksettings->link_modes.supported); + return; + } + if (fec_cfg & BNGE_FEC_ENC_BASE_R_CAP) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT, + lk_ksettings->link_modes.supported); + if (fec_cfg & BNGE_FEC_ENC_RS_CAP) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, + lk_ksettings->link_modes.supported); + if (fec_cfg & BNGE_FEC_ENC_LLRS_CAP) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_LLRS_BIT, + lk_ksettings->link_modes.supported); +} + +static void bnge_get_default_speeds(struct bnge_net *bn, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct ethtool_link_settings *base =3D &lk_ksettings->base; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (link_info->link_state =3D=3D BNGE_LINK_STATE_UP) { + base->speed =3D bnge_fw_to_ethtool_speed(link_info->link_speed); + base->duplex =3D DUPLEX_HALF; + if (link_info->duplex & BNGE_LINK_DUPLEX_FULL) + base->duplex =3D DUPLEX_FULL; + lk_ksettings->lanes =3D link_info->active_lanes; + } else if (!elink_info->autoneg) { + base->speed =3D + bnge_fw_to_ethtool_speed(elink_info->req_link_speed); + base->duplex =3D DUPLEX_HALF; + if (elink_info->req_duplex =3D=3D BNGE_LINK_DUPLEX_FULL) + base->duplex =3D DUPLEX_FULL; + } +} + +int bnge_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct ethtool_link_settings *base =3D &lk_ksettings->base; + enum ethtool_link_mode_bit_indices link_mode; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + enum bnge_media_type media; + + ethtool_link_ksettings_zero_link_mode(lk_ksettings, lp_advertising); + ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising); + ethtool_link_ksettings_zero_link_mode(lk_ksettings, supported); + base->duplex =3D DUPLEX_UNKNOWN; + base->speed =3D SPEED_UNKNOWN; + link_info =3D &bd->link_info; + + bnge_get_ethtool_modes(bn, lk_ksettings); + media =3D bnge_get_media(link_info); + bnge_get_all_ethtool_support_speeds(bd, media, lk_ksettings); + bnge_fw_to_ethtool_support_fec(link_info, lk_ksettings); + link_mode =3D bnge_get_link_mode(bn); + if (link_mode !=3D BNGE_LINK_MODE_UNKNOWN) + ethtool_params_from_link_mode(lk_ksettings, link_mode); + else + bnge_get_default_speeds(bn, lk_ksettings); + + if (bn->eth_link_info.autoneg) { + bnge_fw_to_ethtool_advertised_fec(link_info, lk_ksettings); + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + lk_ksettings->link_modes.advertising); + base->autoneg =3D AUTONEG_ENABLE; + bnge_get_all_ethtool_adv_speeds(bn, media, lk_ksettings); + if (link_info->phy_link_status =3D=3D BNGE_LINK_LINK) + bnge_get_all_ethtool_lp_speeds(bd, media, lk_ksettings); + } else { + base->autoneg =3D AUTONEG_DISABLE; + } + + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, + lk_ksettings->link_modes.supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, + lk_ksettings->link_modes.advertising); + + if (link_info->media_type =3D=3D PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC) + base->port =3D PORT_DA; + else + base->port =3D PORT_FIBRE; + base->phy_address =3D link_info->phy_addr; + + return 0; +} + +static bool bnge_lanes_match(u32 user_lanes, u32 supported_lanes) +{ + /* 0 means lanes unspecified (auto) */ + return !user_lanes || user_lanes =3D=3D supported_lanes; +} + +static int +bnge_force_link_speed(struct net_device *dev, u32 ethtool_speed, u32 user_= lanes) +{ + u16 support_pam4_spds, support_spds2, support_spds; + struct bnge_ethtool_link_info *elink_info; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_link_info *link_info; + u8 sig_mode =3D BNGE_SIG_MODE_NRZ; + struct bnge_dev *bd =3D bn->bd; + u16 fw_speed =3D 0; + + elink_info =3D &bn->eth_link_info; + link_info =3D &bd->link_info; + support_pam4_spds =3D link_info->support_pam4_speeds; + support_spds2 =3D link_info->support_speeds2; + support_spds =3D link_info->support_speeds; + + switch (ethtool_speed) { + case SPEED_50000: + if (bnge_lanes_match(user_lanes, 1) && + (support_pam4_spds & BNGE_LINK_PAM4_SPEED_MSK_50GB)) { + fw_speed =3D PORT_PHY_CFG_REQ_FORCE_PAM4_LINK_SPEED_50GB; + sig_mode =3D BNGE_SIG_MODE_PAM4; + } else if (bnge_lanes_match(user_lanes, 1) && + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_50GB_PAM4)) { + fw_speed =3D BNGE_LINK_SPEED_50GB_PAM4; + sig_mode =3D BNGE_SIG_MODE_PAM4; + } + break; + case SPEED_100000: + if (bnge_lanes_match(user_lanes, 4) && + ((support_spds & BNGE_LINK_SPEED_MSK_100GB) || + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_100GB))) { + fw_speed =3D PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_100GB; + } else if (bnge_lanes_match(user_lanes, 2) && + (support_pam4_spds & BNGE_LINK_PAM4_SPEED_MSK_100GB)) { + fw_speed =3D PORT_PHY_CFG_REQ_FORCE_PAM4_LINK_SPEED_100GB; + sig_mode =3D BNGE_SIG_MODE_PAM4; + } else if (bnge_lanes_match(user_lanes, 2) && + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_100GB_PAM4)) { + fw_speed =3D BNGE_LINK_SPEED_100GB_PAM4; + sig_mode =3D BNGE_SIG_MODE_PAM4; + } else if (bnge_lanes_match(user_lanes, 1) && + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_100GB_PAM4_112)) { + fw_speed =3D BNGE_LINK_SPEED_100GB_PAM4_112; + sig_mode =3D BNGE_SIG_MODE_PAM4_112; + } + break; + case SPEED_200000: + if (bnge_lanes_match(user_lanes, 4) && + (support_pam4_spds & BNGE_LINK_PAM4_SPEED_MSK_200GB)) { + fw_speed =3D PORT_PHY_CFG_REQ_FORCE_PAM4_LINK_SPEED_200GB; + sig_mode =3D BNGE_SIG_MODE_PAM4; + } else if (bnge_lanes_match(user_lanes, 4) && + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_200GB_PAM4)) { + fw_speed =3D BNGE_LINK_SPEED_200GB_PAM4; + sig_mode =3D BNGE_SIG_MODE_PAM4; + } else if (bnge_lanes_match(user_lanes, 2) && + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_200GB_PAM4_112)) { + fw_speed =3D BNGE_LINK_SPEED_200GB_PAM4_112; + sig_mode =3D BNGE_SIG_MODE_PAM4_112; + } + break; + case SPEED_400000: + if (bnge_lanes_match(user_lanes, 8) && + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_400GB_PAM4)) { + fw_speed =3D BNGE_LINK_SPEED_400GB_PAM4; + sig_mode =3D BNGE_SIG_MODE_PAM4; + } else if (bnge_lanes_match(user_lanes, 4) && + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_400GB_PAM4_112)) { + fw_speed =3D BNGE_LINK_SPEED_400GB_PAM4_112; + sig_mode =3D BNGE_SIG_MODE_PAM4_112; + } + break; + case SPEED_800000: + if (bnge_lanes_match(user_lanes, 8) && + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_800GB_PAM4_112)) { + fw_speed =3D BNGE_LINK_SPEED_800GB_PAM4_112; + sig_mode =3D BNGE_SIG_MODE_PAM4_112; + } + break; + default: + break; + } + + if (!fw_speed) { + if (user_lanes) + netdev_err(dev, "unsupported speed or number of lanes!\n"); + else + netdev_err(dev, "unsupported speed!\n"); + return -EINVAL; + } + + if (elink_info->req_link_speed =3D=3D fw_speed && + elink_info->req_signal_mode =3D=3D sig_mode && + elink_info->autoneg =3D=3D 0) + return -EALREADY; + + elink_info->req_link_speed =3D fw_speed; + elink_info->req_signal_mode =3D sig_mode; + elink_info->req_duplex =3D BNGE_LINK_DUPLEX_FULL; + elink_info->autoneg =3D 0; + elink_info->advertising =3D 0; + elink_info->advertising_pam4 =3D 0; + + return 0; +} + +int bnge_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *lk_ksettings) +{ + const struct ethtool_link_settings *base =3D &lk_ksettings->base; + struct bnge_ethtool_link_info old_elink_info; + struct bnge_ethtool_link_info *elink_info; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_dev *bd =3D bn->bd; + bool set_pause =3D false; + int rc =3D 0; + + if (!BNGE_PHY_CFG_ABLE(bd)) + return -EOPNOTSUPP; + + elink_info =3D &bn->eth_link_info; + old_elink_info =3D *elink_info; + + if (base->autoneg =3D=3D AUTONEG_ENABLE) { + bnge_set_ethtool_speeds(bn, + lk_ksettings->link_modes.advertising); + elink_info->autoneg |=3D BNGE_AUTONEG_SPEED; + if (!elink_info->advertising && !elink_info->advertising_pam4) + bnge_set_default_adv_speeds(bn); + /* any change to autoneg will cause link change, therefore the + * driver should put back the original pause setting in autoneg + */ + if (!(bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) + set_pause =3D true; + } else { + if (base->duplex =3D=3D DUPLEX_HALF) { + netdev_err(dev, "HALF DUPLEX is not supported!\n"); + rc =3D -EINVAL; + goto set_setting_exit; + } + rc =3D bnge_force_link_speed(dev, base->speed, + lk_ksettings->lanes); + if (rc) { + if (rc =3D=3D -EALREADY) + rc =3D 0; + goto set_setting_exit; + } + } + + if (netif_running(dev)) { + rc =3D bnge_hwrm_set_link_setting(bn, set_pause); + if (rc) + *elink_info =3D old_elink_info; + } + +set_setting_exit: + return rc; +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.h b/drivers/net/e= thernet/broadcom/bnge/bnge_link.h index f22dec2899e3..70d0901b9a32 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_link.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.h @@ -4,6 +4,8 @@ #ifndef _BNGE_LINK_H_ #define _BNGE_LINK_H_ =20 +#include + #define BNGE_PHY_CFG_ABLE(bd) \ ((bd)->link_info.phy_enabled) =20 @@ -190,4 +192,9 @@ void bnge_report_link(struct bnge_dev *bd); bool bnge_support_speed_dropped(struct bnge_net *bn); void bnge_init_ethtool_link_settings(struct bnge_net *bn); int bnge_probe_phy(struct bnge_net *bn, bool fw_dflt); +int bnge_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *lk_ksettings); +int bnge_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *lk_ksettings); +u32 bnge_get_link(struct net_device *dev); #endif /* _BNGE_LINK_H_ */ --=20 2.47.3 From nobody Sun Apr 5 18:20:21 2026 Received: from mail-oa1-f100.google.com (mail-oa1-f100.google.com [209.85.160.100]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D73C34C134 for ; Fri, 3 Apr 2026 07:38:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.100 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201912; cv=none; b=c849uIp5s7XPgS6+heeBiS2d+RHn4kPjT34+GYaSrcyxDpYO1KIJv+p9ql9MdXx0wXLXwwaXKUHiWqiBKJSbLbR/q/8iDBNBtGk/RoYFHKkMzxM/4Rqk066MO0ncrOzhbNJWthlV28vginjeZtISmcS0ywtQTdmk12s5V+38pRE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201912; c=relaxed/simple; bh=VrDAR49IVycPOe7piWEfXsLgfQfX9bhGR7zSuE3NSoQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hChd3M95Ss8zquMOugerU3bTL7rIK+BUK8p+qjCGz4Lddojm8w3PY+RKitngfQr4cQEbdG+UnP7eMmTUqMYK0btKkQnI5lbEhs43tgeJk3rlkPrSwKefa/HTUmDhN/mCPMHnPCPvWDzb5Z6YiwZewCGMC4zuRb6kXz0o/Ze9qPM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=eZOduybr; arc=none smtp.client-ip=209.85.160.100 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="eZOduybr" Received: by mail-oa1-f100.google.com with SMTP id 586e51a60fabf-41708f6c3feso1112937fac.3 for ; Fri, 03 Apr 2026 00:38:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201909; x=1775806709; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=A2P7lgtvNOf8Os/zH65RPtJhaLvNMqNntscgZ8Xa5co=; b=Y/STk+Ak7Lw892Ccp7K33cn64uy20Vc7++yUS81JJiGuQZ2CrkGirbz4/TvMI58ESf xyXslIDos/wEbBiATrTWUX1DBA/QN5i0vVgyC5ka2GVP+eCTIqQ3IVx6QKh43bUoZd9F G5hQd/GMCVWJxomU78x4tdQser8sL+8IdBfae5co33iPicFi8cNEhJeYvTad9H3mSPZF U+I/A0VnlJoTx2hTv7KxrhC77yZ9aDWy3tN7bOTljKGRggPu29qXBfDmhLKTguqwOoEB Gssel8t5CfhC6gAa0WqAwoLA3Ffpj/J36yaQ31uGJKs4i+ODV6p0rNR7AXj4jzhIqrzL GmHA== X-Forwarded-Encrypted: i=1; AJvYcCUaxlb78BY+14D6i6JOyhH8aBHUWO+bbbrZPbdLUSN0mkORQoEa657s9742ReCyxQsNeSn7O+BHlrmKLSo=@vger.kernel.org X-Gm-Message-State: AOJu0Yx4fG92XKmdmluNoQQrSZN8r/LeHbBb/rls8352ESlValu6XCoX pMYtT8vJKMDFBzoSxXM6LuJzvwYwDNbZaYyfl0CPBIN2z5le1smKbqsBM5ujJUeLxpr6nPCS3/s 2+a3c2XEB5dkI/h/GOD6+fr0RoxVq4VrEit9t/4fGHMF/qLjlNcCD89XkGwvmVBb0PB2gegEwAI R2s6NIhSyO8MeuOR4C3MJaMPJIFNp+ie95LmNc7ywwF+eN/LaYjuoE3DaqRX/q4ibg3fxmDSPjp U067KhRY2xsnNPGUcPva08hYQ== X-Gm-Gg: ATEYQzzC08i2R8T53dzOgujE5JfXzQRIAQSDXFfL9x7J0hqV50vf2dkNqJ242eiiaSe eSNRdSCjLg+lGEgWzI8qiF6kMV6NEEHtLrOSun0wtWgbYiJE9Gdlo3SygxJjn1Sw53PpgdDRt0Y sRr3OqvOfbeOq6UVQJFL3fylj3MkLH0K6s0MS6ez1M5EUKs4J0ezP7b61dDZSQ+QSw9StS+L5Up wbzjD/jHcHebvBoKS0J+pmW+Al8SWiFE+uImEn5JYg/fkrP0GCsxzY6hiez7O1kWSZFL2TRO0qs 2Ce2EIS2C2SADem7yDdBG2qvsiSlCXjxI36GSErlqueKdQtdqpkZrG2tFvYyY0yvHreUdS9J7AO tYfv2QrNxxA0WHBNg8LgNm2Me2n5i57iQ6scXavqPz6sEP70KHmxDsM6WoEPUH0x5ibVth+AJTg zG16y9c/zKNWRDOCf8eF8kJBILvj6OURRCfY81K6X2PLDYIKA6kW2xVM7mEpoB0mU= X-Received: by 2002:a05:6870:b1c1:b0:3f1:6d93:4386 with SMTP id 586e51a60fabf-4230fc7bed0mr1107494fac.1.1775201909016; Fri, 03 Apr 2026 00:38:29 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-15.dlp.protect.broadcom.com. [144.49.247.15]) by smtp-relay.gmail.com with ESMTPS id 586e51a60fabf-4231c57141bsm70518fac.4.2026.04.03.00.38.28 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:29 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-3595485abbbso2113160a91.2 for ; Fri, 03 Apr 2026 00:38:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201907; x=1775806707; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=A2P7lgtvNOf8Os/zH65RPtJhaLvNMqNntscgZ8Xa5co=; b=eZOduybrP1jPwZPG/F6GQvFDnkGj5cRpAUvuagl24Cwm7SBPWP+DBHDpp11B5KN085 pmT6LtVt8GaAd8EDi2BBpWPwU1JQWi4+5Q3hkeacP/MqyLg/lkrHEYD7ijY8FK4bZvJb Mh7nWtmzJitrrsQlmajJ54FbUFxDXZfLau5Xw= X-Forwarded-Encrypted: i=1; AJvYcCW0qEacVUADYgt5tZkC8/H8IaYSGm4Y0J930DFtssKjQuU4BxW23GvP9RdrQlyLaqc8iidf/UeHLl4sHHA=@vger.kernel.org X-Received: by 2002:a17:90b:48c6:b0:35b:9ab6:1d4a with SMTP id 98e67ed59e1d1-35de697359emr1800814a91.18.1775201907342; Fri, 03 Apr 2026 00:38:27 -0700 (PDT) X-Received: by 2002:a17:90b:48c6:b0:35b:9ab6:1d4a with SMTP id 98e67ed59e1d1-35de697359emr1800796a91.18.1775201906882; Fri, 03 Apr 2026 00:38:26 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:26 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy Subject: [PATCH net-next v11 04/10] bng_en: implement ethtool pauseparam operations Date: Fri, 3 Apr 2026 13:07:18 +0530 Message-ID: <20260403073724.194360-5-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Implement .get_pauseparam and .set_pauseparam to support flow control configuration. This allows reporting and setting of autoneg, RX pause, and TX pause states. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta --- .../net/ethernet/broadcom/bnge/bnge_ethtool.c | 63 +++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_link.c | 45 +++++++++---- 2 files changed, 95 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c b/drivers/ne= t/ethernet/broadcom/bnge/bnge_ethtool.c index 6bb74a84ea03..424bf2d6721c 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c @@ -46,6 +46,67 @@ static void bnge_get_drvinfo(struct net_device *dev, strscpy(info->bus_info, pci_name(bd->pdev), sizeof(info->bus_info)); } =20 +static void bnge_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_dev *bd =3D bn->bd; + + if (bd->phy_flags & BNGE_PHY_FL_NO_PAUSE) { + epause->autoneg =3D 0; + epause->rx_pause =3D 0; + epause->tx_pause =3D 0; + return; + } + + epause->autoneg =3D !!(bn->eth_link_info.autoneg & + BNGE_AUTONEG_FLOW_CTRL); + epause->rx_pause =3D !!(bn->eth_link_info.req_flow_ctrl & + BNGE_LINK_PAUSE_RX); + epause->tx_pause =3D !!(bn->eth_link_info.req_flow_ctrl & + BNGE_LINK_PAUSE_TX); +} + +static int bnge_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ + struct bnge_ethtool_link_info old_elink_info, *elink_info; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_dev *bd =3D bn->bd; + int rc =3D 0; + + if (!BNGE_PHY_CFG_ABLE(bd) || (bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) + return -EOPNOTSUPP; + + elink_info =3D &bn->eth_link_info; + old_elink_info =3D *elink_info; + + if (epause->autoneg) { + if (!(elink_info->autoneg & BNGE_AUTONEG_SPEED)) + return -EINVAL; + + elink_info->autoneg |=3D BNGE_AUTONEG_FLOW_CTRL; + } else { + if (elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) + elink_info->force_link_chng =3D true; + elink_info->autoneg &=3D ~BNGE_AUTONEG_FLOW_CTRL; + } + + elink_info->req_flow_ctrl =3D 0; + if (epause->rx_pause) + elink_info->req_flow_ctrl |=3D BNGE_LINK_PAUSE_RX; + if (epause->tx_pause) + elink_info->req_flow_ctrl |=3D BNGE_LINK_PAUSE_TX; + + if (netif_running(dev)) { + rc =3D bnge_hwrm_set_pause(bn); + if (rc) + *elink_info =3D old_elink_info; + } + + return rc; +} + static const struct ethtool_ops bnge_ethtool_ops =3D { .cap_link_lanes_supported =3D 1, .get_link_ksettings =3D bnge_get_link_ksettings, @@ -53,6 +114,8 @@ static const struct ethtool_ops bnge_ethtool_ops =3D { .get_drvinfo =3D bnge_get_drvinfo, .get_link =3D bnge_get_link, .nway_reset =3D bnge_nway_reset, + .get_pauseparam =3D bnge_get_pauseparam, + .set_pauseparam =3D bnge_set_pauseparam, }; =20 void bnge_set_ethtool_ops(struct net_device *dev) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.c b/drivers/net/e= thernet/broadcom/bnge/bnge_link.c index d8236a5daef2..7751bf07740f 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_link.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.c @@ -302,6 +302,8 @@ int bnge_update_phy_setting(struct bnge_net *bn) struct bnge_dev *bd =3D bn->bd; bool update_pause =3D false; bool update_link =3D false; + bool hw_pause_autoneg; + bool pause_autoneg; int rc; =20 link_info =3D &bd->link_info; @@ -313,24 +315,41 @@ int bnge_update_phy_setting(struct bnge_net *bn) return rc; } =20 - if ((elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) && - (link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH) !=3D - elink_info->req_flow_ctrl) + pause_autoneg =3D !!(elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL); + hw_pause_autoneg =3D !!(link_info->auto_pause_setting & + PORT_PHY_QCFG_RESP_AUTO_PAUSE_AUTONEG_PAUSE); + + /* Check if pause autonegotiation state has changed */ + if (pause_autoneg !=3D hw_pause_autoneg) { update_pause =3D true; - if (!(elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) && - link_info->force_pause_setting !=3D elink_info->req_flow_ctrl) + } else if (pause_autoneg) { + /* If pause autoneg is enabled, check if the + * requested RX/TX bits changed + */ + if ((link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH) !=3D + elink_info->req_flow_ctrl) + update_pause =3D true; + } else { + /* If pause autoneg is disabled, check if the + * forced RX/TX bits changed + */ + if (link_info->force_pause_setting !=3D elink_info->req_flow_ctrl) + update_pause =3D true; + } + + /* Force update if link change is requested */ + if (elink_info->force_link_chng) update_pause =3D true; + + /* Check if link speed or duplex settings have changed */ if (!(elink_info->autoneg & BNGE_AUTONEG_SPEED)) { - if (BNGE_AUTO_MODE(link_info->auto_mode)) - update_link =3D true; - if (bnge_force_speed_updated(bn)) - update_link =3D true; - if (elink_info->req_duplex !=3D link_info->duplex_setting) + if (BNGE_AUTO_MODE(link_info->auto_mode) || + bnge_force_speed_updated(bn) || + elink_info->req_duplex !=3D link_info->duplex_setting) update_link =3D true; } else { - if (link_info->auto_mode =3D=3D BNGE_LINK_AUTO_NONE) - update_link =3D true; - if (bnge_auto_speed_updated(bn)) + if (link_info->auto_mode =3D=3D BNGE_LINK_AUTO_NONE || + bnge_auto_speed_updated(bn)) update_link =3D true; } =20 --=20 2.47.3 From nobody Sun Apr 5 18:20:21 2026 Received: from mail-qt1-f227.google.com (mail-qt1-f227.google.com [209.85.160.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E3D3D37C103 for ; Fri, 3 Apr 2026 07:38:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201916; cv=none; b=c1fZU5sImk/nkyQXaUfrUg1v86QIoPVtfZPaG0i5ndAr4VW9JVOBOFiokyylVmX6pjQp+4YG+L0v7rnSGEI1yvdY8hWSYfjFarNQvNZ6DkpFlLj/vt9WNtnoxllLStn+XFCaNOHTIOh9d4jsfpyI8plDGJNnx1FgFeVHULK5aeI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201916; c=relaxed/simple; bh=EjYjgwiOnKLxziRX51q2OxgLzh+hWJgbZkGWEZLOJ3o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OdKmRAyayMscPfXjrNQtmZ8IkZqbb1jrPo1rbW4pzDgEdA4NkFjzcSnNrrKl88qZOWYTuM9rHRFYeCRCZ4//iwUgiBf0+D40ha2U3mdsFDyYZeWRFPjosAaVIOMey7sK78J+ABPU4TNHSxsmxggFEUYyKVJdQu+/WHMXvv0zDsE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=gomX4v5H; arc=none smtp.client-ip=209.85.160.227 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="gomX4v5H" Received: by mail-qt1-f227.google.com with SMTP id d75a77b69052e-50d6144877aso8662431cf.3 for ; Fri, 03 Apr 2026 00:38:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201914; x=1775806714; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=mZC3ac4115lsgagZnqjuv2Trln6vcbIo8SxQmTDzf28=; b=cBWKARyS7LlxO3st1Klr0yJ/XqYWyP3xx1vgsN4u1gqIPZmT5ivHscRGsURhXlY8Pg H9g83ihnRSGwogG0Ea2++Gk+uY5iZf7zJ9jW4wHo5JspFZ1pwB+yZoXsz7zLiMbauxUE eqiHZL+Qk5iV9WoKxkCyRGfvHLbMv9HXuJ1K+IGQ/9enuKsnwKKjbbmhaAkPKOr0VstQ qOhswaPU5uJ9nzovCD2BAeyDjzJDlbkx5rwrT6gAuwyLv6YBAyxuy1t/Ih3t/z4o5TdO lRGAU5ofdDooxie4twGnbbJ5j4RBwix8oFFIXm99tH4vD+PKpOGGLpt0Zd5U/UaShEzK IkTw== X-Forwarded-Encrypted: i=1; AJvYcCU+7ly9eTiJMZyr5Vbd6Hcufii0twSD3LHT+UM2uRQhUU3c9/Eq+8Sow9pzjERRcOpLvsqnPqkVpgNFhIo=@vger.kernel.org X-Gm-Message-State: AOJu0YxktNieMNcF8Fi/vkOxYgL1SX06SpyzqXWG0mjYCbxoAdy5oUBw shU4gMqAxvA6//txoflb1rMVF2/i0iZqKtRqY/XG697Lj55jiKYSsX4rwQPxqQ1fYe1/mSB+Fct MgBTfhOFmhYpQ25evokWHkjk8YRPrZ9jDv67fhDlMbfwApTStd8mufbdJsBkbt/oF7XTzsDZFep h7FzrwEbHf20aIGhJAQ2wZ8Q4bnd7D5rzfK9yQK2ZVFE5bWMZo58wY5K65tELbRHms6xyPiksHZ /zwcnG2GUI0nS+Boe64VCqbUA== X-Gm-Gg: ATEYQzxCGniouSRXekgbq9uoaP3MwLHF+rGPzf+8VTJbnscdq32rwtQ1KopVw+vxFBz nNp+zPd+g0hxsuLSYcNzLLAdXss0Isazo1PdtPGlWQzaQKBaBLfYumIZMQldONgxtsRfJxaD1BC /lVbqzRlEUN7b9oyYiPrwLCL5yAYr25RI9tjnaxb1+Qr0PS2OTH4KMAMZNNoD3VSJ+vtB+KY94o xVIvbuGAsvEF+p7/6pCEzzB/uGNm82Jq03NQkFOBk4P+tal4bXMhAV4YGJPwlO6BmZT1H9AX6n+ fFoIcE2suJUWVcl91sinsjmE95YLN4qcpmUeVDUJTV4Vqp5L4DAfVEyKOGMpd8Evb5QMu0ualFA NgqcLY3snHTVmmeTPTZrWX9subd2xRA7QX247N34qs3vJdnYYTJxulu0NyrvyKrxksXUWPEnc0O Y7SX9yMmUvwLikOVeQ4nR/aA1kotlM2PlQxaYMtElQp06h/rkETvfF1DGBjxRgReQ= X-Received: by 2002:a05:622a:10d:b0:50b:3014:22a1 with SMTP id d75a77b69052e-50d62b64cdfmr30055021cf.67.1775201913762; Fri, 03 Apr 2026 00:38:33 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-25.dlp.protect.broadcom.com. [144.49.247.25]) by smtp-relay.gmail.com with ESMTPS id d75a77b69052e-50d4b61e671sm3239721cf.18.2026.04.03.00.38.33 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:33 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f71.google.com with SMTP id 98e67ed59e1d1-35da1c703d1so1664093a91.1 for ; Fri, 03 Apr 2026 00:38:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201912; x=1775806712; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mZC3ac4115lsgagZnqjuv2Trln6vcbIo8SxQmTDzf28=; b=gomX4v5HTqOWe31GrkDVXcOup8DgDbuhcs2d+iBq4W8XyX0vn3YfucB9bAXg13BIR5 1cAW5GYZNsmfrrNXCTcLUiv8u5Y8Rjye0+junYIk5KnOlahHFXQbOMOUlaZgm2XtZhkk T2aX2cFklXBKgP5svxuuLa1RK1m7D59QCA9ZM= X-Forwarded-Encrypted: i=1; AJvYcCWo5MNCt787V3jHRY12/MafM2CHpJXi137e4YVtyHQUmSE/smBGwEBpxBP0XXbjAIS94EnrdW5kb2qmmDM=@vger.kernel.org X-Received: by 2002:a17:90b:3f4d:b0:35d:93ff:2859 with SMTP id 98e67ed59e1d1-35de69a6469mr1963272a91.22.1775201912386; Fri, 03 Apr 2026 00:38:32 -0700 (PDT) X-Received: by 2002:a17:90b:3f4d:b0:35d:93ff:2859 with SMTP id 98e67ed59e1d1-35de69a6469mr1963256a91.22.1775201911985; Fri, 03 Apr 2026 00:38:31 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:31 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula , Ajit Kumar Khaparde Subject: [PATCH net-next v11 05/10] bng_en: add support for link async events Date: Fri, 3 Apr 2026 13:07:19 +0530 Message-ID: <20260403073724.194360-6-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Register for firmware asynchronous events, including link-status, link-speed, and PHY configuration changes. Upon event reception, re-query the PHY and update ethtool settings accordingly. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula Reviewed-by: Ajit Kumar Khaparde --- .../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 19 +++++++++- .../net/ethernet/broadcom/bnge/bnge_link.c | 18 ++++++++++ .../net/ethernet/broadcom/bnge/bnge_link.h | 1 + .../net/ethernet/broadcom/bnge/bnge_netdev.c | 23 ++++++++++++ .../net/ethernet/broadcom/bnge/bnge_txrx.c | 35 ++++++++++++++++--- 5 files changed, 91 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.c index acb712ddbd7e..de51add96ac3 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c @@ -15,6 +15,13 @@ #include "bnge_rmem.h" #include "bnge_resc.h" =20 +static const u16 bnge_async_events_arr[] =3D { + ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE, + ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE, + ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE, + ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE, +}; + int bnge_hwrm_ver_get(struct bnge_dev *bd) { u32 dev_caps_cfg, hwrm_ver, hwrm_spec_code; @@ -166,10 +173,12 @@ int bnge_hwrm_fw_set_time(struct bnge_dev *bd) =20 int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd) { + DECLARE_BITMAP(async_events_bmap, 256); struct hwrm_func_drv_rgtr_output *resp; struct hwrm_func_drv_rgtr_input *req; + u32 events[8]; u32 flags; - int rc; + int rc, i; =20 rc =3D bnge_hwrm_req_init(bd, req, HWRM_FUNC_DRV_RGTR); if (rc) @@ -190,6 +199,14 @@ int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd) req->ver_min =3D cpu_to_le16(DRV_VER_MIN); req->ver_upd =3D cpu_to_le16(DRV_VER_UPD); =20 + memset(async_events_bmap, 0, sizeof(async_events_bmap)); + for (i =3D 0; i < ARRAY_SIZE(bnge_async_events_arr); i++) + __set_bit(bnge_async_events_arr[i], async_events_bmap); + + bitmap_to_arr32(events, async_events_bmap, 256); + for (i =3D 0; i < ARRAY_SIZE(req->async_event_fwd); i++) + req->async_event_fwd[i] |=3D cpu_to_le32(events[i]); + resp =3D bnge_hwrm_req_hold(bd, req); rc =3D bnge_hwrm_req_send(bd, req); if (!rc) { diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.c b/drivers/net/e= thernet/broadcom/bnge/bnge_link.c index 7751bf07740f..9633f5b1b2f0 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_link.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.c @@ -1293,3 +1293,21 @@ int bnge_set_link_ksettings(struct net_device *dev, set_setting_exit: return rc; } + +void bnge_link_async_event_process(struct bnge_net *bn, u16 event_id) +{ + switch (event_id) { + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: + set_bit(BNGE_LINK_SPEED_CHNG_SP_EVENT, &bn->sp_event); + break; + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE: + case ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE: + set_bit(BNGE_LINK_CFG_CHANGE_SP_EVENT, &bn->sp_event); + break; + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: + set_bit(BNGE_LINK_CHNG_SP_EVENT, &bn->sp_event); + break; + default: + break; + } +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.h b/drivers/net/e= thernet/broadcom/bnge/bnge_link.h index 70d0901b9a32..d498d1d11a5b 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_link.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.h @@ -197,4 +197,5 @@ int bnge_set_link_ksettings(struct net_device *dev, int bnge_get_link_ksettings(struct net_device *dev, struct ethtool_link_ksettings *lk_ksettings); u32 bnge_get_link(struct net_device *dev); +void bnge_link_async_event_process(struct bnge_net *bn, u16 event_id); #endif /* _BNGE_LINK_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 185f5bfce1d5..90458b323120 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -136,6 +136,7 @@ static void bnge_timer(struct timer_list *t) static void bnge_sp_task(struct work_struct *work) { struct bnge_net *bn =3D container_of(work, struct bnge_net, sp_task); + bool speed_chng, cfg_chng, link_chng; struct bnge_dev *bd =3D bn->bd; =20 netdev_lock(bn->netdev); @@ -156,6 +157,28 @@ static void bnge_sp_task(struct work_struct *work) } } =20 + speed_chng =3D test_and_clear_bit(BNGE_LINK_SPEED_CHNG_SP_EVENT, + &bn->sp_event); + cfg_chng =3D test_and_clear_bit(BNGE_LINK_CFG_CHANGE_SP_EVENT, + &bn->sp_event); + link_chng =3D test_and_clear_bit(BNGE_LINK_CHNG_SP_EVENT, + &bn->sp_event); + + if (speed_chng || cfg_chng || link_chng) { + int rc; + + if (speed_chng) + bnge_hwrm_phy_qcaps(bd); + + rc =3D bnge_update_link(bn, true); + if (rc) + netdev_err(bn->netdev, "SP task cannot update link (rc: %d)\n", + rc); + + if (speed_chng || cfg_chng) + bnge_init_ethtool_link_settings(bn); + } + netdev_unlock(bn->netdev); } =20 diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index a2616f037557..7d45e057f2e8 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -1128,6 +1128,29 @@ static void __bnge_poll_work_done(struct bnge_net *b= n, struct bnge_napi *bnapi, } } =20 +static void bnge_async_event_process(struct bnge_net *bn, + struct hwrm_async_event_cmpl *cmpl) +{ + u16 event_id =3D le16_to_cpu(cmpl->event_id); + u32 data1 =3D le32_to_cpu(cmpl->event_data1); + u32 data2 =3D le32_to_cpu(cmpl->event_data2); + + netdev_dbg(bn->netdev, "hwrm event 0x%x {0x%x, 0x%x}\n", + event_id, data1, data2); + + switch (event_id) { + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE: + case ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE: + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: + bnge_link_async_event_process(bn, event_id); + break; + default: + return; + } + __bnge_queue_sp_work(bn); +} + static void bnge_hwrm_update_token(struct bnge_dev *bd, u16 seq_id, enum bnge_hwrm_wait_state state) @@ -1146,7 +1169,7 @@ bnge_hwrm_update_token(struct bnge_dev *bd, u16 seq_i= d, dev_err(bd->dev, "Invalid hwrm seq id %d\n", seq_id); } =20 -static int bnge_hwrm_handler(struct bnge_dev *bd, struct tx_cmp *txcmp) +static int bnge_hwrm_handler(struct bnge_net *bn, struct tx_cmp *txcmp) { struct hwrm_cmpl *h_cmpl =3D (struct hwrm_cmpl *)txcmp; u16 cmpl_type =3D TX_CMP_TYPE(txcmp), seq_id; @@ -1154,10 +1177,14 @@ static int bnge_hwrm_handler(struct bnge_dev *bd, s= truct tx_cmp *txcmp) switch (cmpl_type) { case CMPL_BASE_TYPE_HWRM_DONE: seq_id =3D le16_to_cpu(h_cmpl->sequence_id); - bnge_hwrm_update_token(bd, seq_id, BNGE_HWRM_COMPLETE); + bnge_hwrm_update_token(bn->bd, seq_id, BNGE_HWRM_COMPLETE); break; =20 case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: + bnge_async_event_process(bn, + (struct hwrm_async_event_cmpl *)txcmp); + break; + default: break; } @@ -1235,7 +1262,7 @@ static int __bnge_poll_work(struct bnge_net *bn, stru= ct bnge_cp_ring_info *cpr, } else if (unlikely(cmp_type =3D=3D CMPL_BASE_TYPE_HWRM_DONE || cmp_type =3D=3D CMPL_BASE_TYPE_HWRM_FWD_REQ || cmp_type =3D=3D CMPL_BA_TY_HWRM_ASY_EVT)) { - bnge_hwrm_handler(bn->bd, txcmp); + bnge_hwrm_handler(bn, txcmp); } raw_cons =3D NEXT_RAW_CMP(raw_cons); =20 @@ -1355,7 +1382,7 @@ int bnge_napi_poll(struct napi_struct *napi, int budg= et) budget - work_done); nqr->has_more_work |=3D cpr->has_more_work; } else { - bnge_hwrm_handler(bn->bd, (struct tx_cmp *)nqcmp); + bnge_hwrm_handler(bn, (struct tx_cmp *)nqcmp); } raw_cons =3D NEXT_RAW_CMP(raw_cons); } --=20 2.47.3 From nobody Sun Apr 5 18:20:21 2026 Received: from mail-yw1-f227.google.com (mail-yw1-f227.google.com [209.85.128.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F017137D116 for ; Fri, 3 Apr 2026 07:38:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201922; cv=none; b=kpgw6G3oB1oy5qi/+nOsL8crJ0Ti00aP7hJPIwygTJF+JQB5iDMIQnpktcpKzLzMxBaTGOYE9aPbn4+qTr/yAK42UfdSgiXo2tkkg/9Xwnr1QakYGb+cRpBMIkZBRKTkd4tzMNgH+ueG6lfpS3OR5qq6oCVA2uo0AsRSINZH1ZI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201922; c=relaxed/simple; bh=cIMHx8u5yl4PDp5nqCm8TEHUjeMx4jnhmQH/vWaEKUU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JrQpZh+fkWnPi6nLEDoMjH5ydA1R10BlIl1r4Qmd1rEpgtCT3cVHJGRkrrBSRhT9pwXf+2xIAB9w5+mP2Ztj5RJO1EdatiE5q0aocsbU4pwvLqhb9HdzJ4jBtnWI+wsl2mmWefY0c8+Z3CGiZrGOJ7thn5SNAgRb6UhZGYDK82E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=eJT9yfC3; arc=none smtp.client-ip=209.85.128.227 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="eJT9yfC3" Received: by mail-yw1-f227.google.com with SMTP id 00721157ae682-79a7109f568so18753207b3.1 for ; Fri, 03 Apr 2026 00:38:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201919; x=1775806719; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=lZvpsJxvmbolorLPTirxjgKM6N0/3HDH6HBz7IOvULY=; b=QAb5oSTbL67Znd04eK+T+D8vtgKsfTjnxBp130moL9zfyPbVA9lliMdLIlAApCK1qg 0x7W/MocYO60QKDhLqP53SPRUj/gzWsiR5LKtYUa1qKIjS1t699cx5DQpqRiKEh5uNeH Eh3HknmiU/nesO08LnN8JL8wbb0e85zGj9uqWA7/OlpBV5vqtijiaEWKBFWtuuSaN0wI dwtJiBhDChSAP+/d0PtPkoANAzu1YdzSC43TBWESX8qqk2aq30KSEdAKBBGBdylzh6of TuHlVCCAGyPfpaf46oh5++0NbZXJ7EfTU4c79V0ra2E9/q3E+Ar6opUHxA3vC0QQNFf8 lYjA== X-Forwarded-Encrypted: i=1; AJvYcCXBytYRJD5quh7IHa6azF6zBqM2hjCt2ek1a0ZZHS5XoCQzYM0xeJi14YkwCAJwizRGk4wmkQq6zjBfu1U=@vger.kernel.org X-Gm-Message-State: AOJu0YzsWilIunK12bTHIGcrlJd2GGyuQpgdHV3ZrJEr+qSl+Ivy1SFx xPRbIeM+kUNTSHQ5Qkomn0/sJDEAdloT94GrOkD5G3Krhk6vXWfckoFY84/udujDartvudNBaqs tca13zqxtLog9rVJFg0UhTsMCbo8ov+rTSdpclXUw3f3+89sj2OZ9HECNedsv1YWOkDDQZDYZFE Jd88HdlHQ+5sDiHMbYNVG7AO7H0xko69WFxkelvRj8syZ9vy3Al4MtzMfH+WwdjpbwLiLL1536y 8DjVbhCisrxOCsJC0FLCLLGgQ== X-Gm-Gg: AeBDiev7BAiJC5oxd3sz1mg6g7f0ZeFV0/cPhvhsb8o0cNONlgxgviNb7XrnhV7TCs6 thXgYBwMcmPDeJturkDgh1N0LXr1dr+XeA2Ck51HyclqU43j4ZBaxxrUuOyL/sRx/4tyEmqA8dQ 6ZHTX46E27zyyKoVlf5C6bzfG3CdsX8saSkQ0/yvfZpyXqkTHI7/gznZjbLwd61vCfSm7stjQzN BDze30fWpMaKwujALREhQ5uijk5pGq1Yp7X2hvOMUsfQO5CQxNQTXHzqQMkQXAbuB0mgv1qrzIb ZnbGs7+m3egV41hY5Rc8OLim+3/Ai8oinqA6oPF4RTa7KiJbSB3vCwMT96fm83UMXlsBfTyTAYn D3SFWn00VmmUtwDkAq5tNGOo0BUjc9O9boljlU+S3F+tlH8n28x8GogtBKWToWaIyR7Yt4YHhv1 Vojr9ksMyh7SdF8PJjdtYLPI6ftoN59qgnmdwbr3/6ttM4gdu3G+CK1oJxiIM+1hk= X-Received: by 2002:a05:690c:e68c:b0:79a:3d1a:a667 with SMTP id 00721157ae682-7a4d5f56494mr13170737b3.48.1775201918850; Fri, 03 Apr 2026 00:38:38 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-25.dlp.protect.broadcom.com. [144.49.247.25]) by smtp-relay.gmail.com with ESMTPS id 00721157ae682-7a36e223068sm3993957b3.3.2026.04.03.00.38.38 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:38 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-3568090851aso3812467a91.1 for ; Fri, 03 Apr 2026 00:38:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201917; x=1775806717; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lZvpsJxvmbolorLPTirxjgKM6N0/3HDH6HBz7IOvULY=; b=eJT9yfC3yESxtWnQIvmNcvW5aa2FInLmI3GXkplAVnfu0BbDroEOZrqgYJmmdlmKlV fXj4u0Iiq4h6B4tqR3BpASaaGH6m5dy5gzXKfJ+pYftIYk9zmSPtvhS7Tbq8k0QGHFnD mslJVjbQ1b6EAOU25t2vMHaxPmsKcROEcBPxs= X-Forwarded-Encrypted: i=1; AJvYcCXVolqvn30kTCMfwlpitsjUTWa95xZn70ohKdANWPwwbeanyxxZXoQSmlA4qvhEuNarQD4+lg5p9XJ82q8=@vger.kernel.org X-Received: by 2002:a17:90b:3812:b0:35b:e551:e776 with SMTP id 98e67ed59e1d1-35de69a9e03mr1847403a91.27.1775201917094; Fri, 03 Apr 2026 00:38:37 -0700 (PDT) X-Received: by 2002:a17:90b:3812:b0:35b:e551:e776 with SMTP id 98e67ed59e1d1-35de69a9e03mr1847379a91.27.1775201916426; Fri, 03 Apr 2026 00:38:36 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:35 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy Subject: [PATCH net-next v11 06/10] bng_en: add HW stats infra and structured ethtool ops Date: Fri, 3 Apr 2026 13:07:20 +0530 Message-ID: <20260403073724.194360-7-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Implement the hardware-level statistics foundation and modern structured ethtool operations. 1. Infrastructure: Add HWRM firmware wrappers (FUNC_QSTATS_EXT, PORT_QSTATS_EXT, and PORT_QSTATS) to query ring and port counters. 2. Structured ops: Implement .get_eth_phy_stats, .get_eth_mac_stats, .get_eth_ctrl_stats, .get_pause_stats, and .get_rmon_stats. Stats are initially reported as 0; accumulation logic is added in a subsequent patch. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta --- .../net/ethernet/broadcom/bnge/bnge_ethtool.c | 160 ++++++++++++++++ .../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 151 ++++++++++++++- .../ethernet/broadcom/bnge/bnge_hwrm_lib.h | 3 + .../net/ethernet/broadcom/bnge/bnge_netdev.c | 180 +++++++++++++++++- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 62 +++++- 5 files changed, 544 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c b/drivers/ne= t/ethernet/broadcom/bnge/bnge_ethtool.c index 424bf2d6721c..87226d5bf15c 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c @@ -46,6 +46,161 @@ static void bnge_get_drvinfo(struct net_device *dev, strscpy(info->bus_info, pci_name(bd->pdev), sizeof(info->bus_info)); } =20 +static void bnge_get_eth_phy_stats(struct net_device *dev, + struct ethtool_eth_phy_stats *phy_stats) +{ + struct bnge_net *bn =3D netdev_priv(dev); + u64 *rx; + + if (!(bn->flags & BNGE_FLAG_PORT_STATS_EXT)) + return; + + rx =3D bn->rx_port_stats_ext.sw_stats; + phy_stats->SymbolErrorDuringCarrier =3D + *(rx + BNGE_RX_STATS_EXT_OFFSET(rx_pcs_symbol_err)); +} + +static void bnge_get_eth_mac_stats(struct net_device *dev, + struct ethtool_eth_mac_stats *mac_stats) +{ + struct bnge_net *bn =3D netdev_priv(dev); + u64 *rx, *tx; + + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) + return; + + rx =3D bn->port_stats.sw_stats; + tx =3D bn->port_stats.sw_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + + mac_stats->FramesReceivedOK =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_good_frames); + mac_stats->FramesTransmittedOK =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_good_frames); + mac_stats->FrameCheckSequenceErrors =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_fcs_err_frames); + mac_stats->AlignmentErrors =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_align_err_frames); + mac_stats->OutOfRangeLengthField =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_oor_len_frames); + mac_stats->OctetsReceivedOK =3D BNGE_GET_RX_PORT_STATS64(rx, rx_bytes); + mac_stats->OctetsTransmittedOK =3D BNGE_GET_TX_PORT_STATS64(tx, tx_bytes); + mac_stats->MulticastFramesReceivedOK =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_mcast_frames); + mac_stats->BroadcastFramesReceivedOK =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_bcast_frames); + mac_stats->MulticastFramesXmittedOK =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_mcast_frames); + mac_stats->BroadcastFramesXmittedOK =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_bcast_frames); + mac_stats->FrameTooLongErrors =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_ovrsz_frames); +} + +static void bnge_get_eth_ctrl_stats(struct net_device *dev, + struct ethtool_eth_ctrl_stats *ctrl_stats) +{ + struct bnge_net *bn =3D netdev_priv(dev); + u64 *rx; + + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) + return; + + rx =3D bn->port_stats.sw_stats; + ctrl_stats->MACControlFramesReceived =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_ctrl_frames); +} + +static void bnge_get_pause_stats(struct net_device *dev, + struct ethtool_pause_stats *pause_stats) +{ + struct bnge_net *bn =3D netdev_priv(dev); + u64 *rx, *tx; + + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) + return; + + rx =3D bn->port_stats.sw_stats; + tx =3D bn->port_stats.sw_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + + pause_stats->rx_pause_frames =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_pause_frames); + pause_stats->tx_pause_frames =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_pause_frames); +} + +static const struct ethtool_rmon_hist_range bnge_rmon_ranges[] =3D { + { 0, 64 }, + { 65, 127 }, + { 128, 255 }, + { 256, 511 }, + { 512, 1023 }, + { 1024, 1518 }, + { 1519, 2047 }, + { 2048, 4095 }, + { 4096, 9216 }, + { 9217, 16383 }, + {} +}; + +static void bnge_get_rmon_stats(struct net_device *dev, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges) +{ + struct bnge_net *bn =3D netdev_priv(dev); + u64 *rx, *tx; + + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) + return; + + rx =3D bn->port_stats.sw_stats; + tx =3D bn->port_stats.sw_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + + rmon_stats->jabbers =3D BNGE_GET_RX_PORT_STATS64(rx, rx_jbr_frames); + rmon_stats->oversize_pkts =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_ovrsz_frames); + rmon_stats->undersize_pkts =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_undrsz_frames); + + rmon_stats->hist[0] =3D BNGE_GET_RX_PORT_STATS64(rx, rx_64b_frames); + rmon_stats->hist[1] =3D BNGE_GET_RX_PORT_STATS64(rx, rx_65b_127b_frames); + rmon_stats->hist[2] =3D BNGE_GET_RX_PORT_STATS64(rx, rx_128b_255b_frames); + rmon_stats->hist[3] =3D BNGE_GET_RX_PORT_STATS64(rx, rx_256b_511b_frames); + rmon_stats->hist[4] =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_512b_1023b_frames); + rmon_stats->hist[5] =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_1024b_1518b_frames); + rmon_stats->hist[6] =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_1519b_2047b_frames); + rmon_stats->hist[7] =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_2048b_4095b_frames); + rmon_stats->hist[8] =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_4096b_9216b_frames); + rmon_stats->hist[9] =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_9217b_16383b_frames); + + rmon_stats->hist_tx[0] =3D BNGE_GET_TX_PORT_STATS64(tx, tx_64b_frames); + rmon_stats->hist_tx[1] =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_65b_127b_frames); + rmon_stats->hist_tx[2] =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_128b_255b_frames); + rmon_stats->hist_tx[3] =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_256b_511b_frames); + rmon_stats->hist_tx[4] =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_512b_1023b_frames); + rmon_stats->hist_tx[5] =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_1024b_1518b_frames); + rmon_stats->hist_tx[6] =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_1519b_2047b_frames); + rmon_stats->hist_tx[7] =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_2048b_4095b_frames); + rmon_stats->hist_tx[8] =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_4096b_9216b_frames); + rmon_stats->hist_tx[9] =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_9217b_16383b_frames); + + *ranges =3D bnge_rmon_ranges; +} + static void bnge_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { @@ -116,6 +271,11 @@ static const struct ethtool_ops bnge_ethtool_ops =3D { .nway_reset =3D bnge_nway_reset, .get_pauseparam =3D bnge_get_pauseparam, .set_pauseparam =3D bnge_set_pauseparam, + .get_eth_phy_stats =3D bnge_get_eth_phy_stats, + .get_eth_mac_stats =3D bnge_get_eth_mac_stats, + .get_eth_ctrl_stats =3D bnge_get_eth_ctrl_stats, + .get_pause_stats =3D bnge_get_pause_stats, + .get_rmon_stats =3D bnge_get_rmon_stats, }; =20 void bnge_set_ethtool_ops(struct net_device *dev) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.c index de51add96ac3..cb3e7b1f0cd9 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c @@ -14,6 +14,7 @@ #include "bnge_hwrm_lib.h" #include "bnge_rmem.h" #include "bnge_resc.h" +#include "bnge_netdev.h" =20 static const u16 bnge_async_events_arr[] =3D { ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE, @@ -594,7 +595,7 @@ int bnge_hwrm_func_qcaps(struct bnge_dev *bd) struct hwrm_func_qcaps_output *resp; struct hwrm_func_qcaps_input *req; struct bnge_pf_info *pf =3D &bd->pf; - u32 flags; + u32 flags, flags_ext; int rc; =20 rc =3D bnge_hwrm_req_init(bd, req, HWRM_FUNC_QCAPS); @@ -612,6 +613,12 @@ int bnge_hwrm_func_qcaps(struct bnge_dev *bd) bd->flags |=3D BNGE_EN_ROCE_V1; if (flags & FUNC_QCAPS_RESP_FLAGS_ROCE_V2_SUPPORTED) bd->flags |=3D BNGE_EN_ROCE_V2; + if (flags & FUNC_QCAPS_RESP_FLAGS_EXT_STATS_SUPPORTED) + bd->fw_cap |=3D BNGE_FW_CAP_EXT_STATS_SUPPORTED; + + flags_ext =3D le32_to_cpu(resp->flags_ext); + if (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_EXT_HW_STATS_SUPPORTED) + bd->fw_cap |=3D BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED; =20 pf->fw_fid =3D le16_to_cpu(resp->fid); pf->port_id =3D le16_to_cpu(resp->port_id); @@ -1502,3 +1509,145 @@ int bnge_hwrm_vnic_set_tpa(struct bnge_dev *bd, str= uct bnge_vnic_info *vnic, =20 return bnge_hwrm_req_send(bd, req); } + +int bnge_hwrm_func_qstat_ext(struct bnge_dev *bd, struct bnge_stats_mem *s= tats) +{ + struct hwrm_func_qstats_ext_output *resp; + struct hwrm_func_qstats_ext_input *req; + __le64 *hw_masks; + int rc; + + if (!(bd->fw_cap & BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED)) + return -EOPNOTSUPP; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_FUNC_QSTATS_EXT); + if (rc) + return rc; + + req->fid =3D cpu_to_le16(0xffff); + req->flags =3D FUNC_QSTATS_EXT_REQ_FLAGS_COUNTER_MASK; + + resp =3D bnge_hwrm_req_hold(bd, req); + rc =3D bnge_hwrm_req_send(bd, req); + if (!rc) { + hw_masks =3D &resp->rx_ucast_pkts; + bnge_copy_hw_masks(stats->hw_masks, hw_masks, stats->len / 8); + } + bnge_hwrm_req_drop(bd, req); + return rc; +} + +int bnge_hwrm_port_qstats_ext(struct bnge_dev *bd, u8 flags) +{ + struct hwrm_queue_pri2cos_qcfg_output *resp_qc; + struct bnge_net *bn =3D netdev_priv(bd->netdev); + struct hwrm_queue_pri2cos_qcfg_input *req_qc; + struct hwrm_port_qstats_ext_output *resp_qs; + struct hwrm_port_qstats_ext_input *req_qs; + struct bnge_pf_info *pf =3D &bd->pf; + u32 tx_stat_size; + int rc; + + if (!(bn->flags & BNGE_FLAG_PORT_STATS_EXT)) + return 0; + + if (flags && !(bd->fw_cap & BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED)) + return -EOPNOTSUPP; + + rc =3D bnge_hwrm_req_init(bd, req_qs, HWRM_PORT_QSTATS_EXT); + if (rc) + return rc; + + req_qs->flags =3D flags; + req_qs->port_id =3D cpu_to_le16(pf->port_id); + req_qs->rx_stat_size =3D cpu_to_le16(sizeof(struct rx_port_stats_ext)); + req_qs->rx_stat_host_addr =3D + cpu_to_le64(bn->rx_port_stats_ext.hw_stats_map); + tx_stat_size =3D bn->tx_port_stats_ext.hw_stats ? + sizeof(struct tx_port_stats_ext) : 0; + req_qs->tx_stat_size =3D cpu_to_le16(tx_stat_size); + req_qs->tx_stat_host_addr =3D + cpu_to_le64(bn->tx_port_stats_ext.hw_stats_map); + resp_qs =3D bnge_hwrm_req_hold(bd, req_qs); + rc =3D bnge_hwrm_req_send(bd, req_qs); + if (!rc) { + bn->fw_rx_stats_ext_size =3D + le16_to_cpu(resp_qs->rx_stat_size) / 8; + bn->fw_tx_stats_ext_size =3D tx_stat_size ? + le16_to_cpu(resp_qs->tx_stat_size) / 8 : 0; + } else { + bn->fw_rx_stats_ext_size =3D 0; + bn->fw_tx_stats_ext_size =3D 0; + } + bnge_hwrm_req_drop(bd, req_qs); + + if (flags) + return rc; + + if (bn->fw_tx_stats_ext_size <=3D + offsetof(struct tx_port_stats_ext, pfc_pri0_tx_duration_us) / 8) { + bn->pri2cos_valid =3D false; + return rc; + } + + rc =3D bnge_hwrm_req_init(bd, req_qc, HWRM_QUEUE_PRI2COS_QCFG); + if (rc) + return rc; + + req_qc->flags =3D cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN); + + resp_qc =3D bnge_hwrm_req_hold(bd, req_qc); + rc =3D bnge_hwrm_req_send(bd, req_qc); + if (!rc) { + u8 *pri2cos; + int i, j; + + pri2cos =3D &resp_qc->pri0_cos_queue_id; + for (i =3D 0; i < 8; i++) { + u8 queue_id =3D pri2cos[i]; + u8 queue_idx; + + /* Per port queue IDs start from 0, 10, 20, etc */ + queue_idx =3D queue_id % 10; + if (queue_idx >=3D BNGE_MAX_QUEUE) { + bn->pri2cos_valid =3D false; + rc =3D -EINVAL; + goto drop_req; + } + for (j =3D 0; j < bd->max_q; j++) { + if (bd->q_ids[j] =3D=3D queue_id) + bn->pri2cos_idx[i] =3D queue_idx; + } + } + bn->pri2cos_valid =3D true; + } +drop_req: + bnge_hwrm_req_drop(bd, req_qc); + return rc; +} + +int bnge_hwrm_port_qstats(struct bnge_dev *bd, u8 flags) +{ + struct bnge_net *bn =3D netdev_priv(bd->netdev); + struct hwrm_port_qstats_input *req; + struct bnge_pf_info *pf =3D &bd->pf; + int rc; + + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) + return 0; + + if (flags && !(bd->fw_cap & BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED)) + return -EOPNOTSUPP; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_QSTATS); + if (rc) + return rc; + + req->flags =3D flags; + req->port_id =3D cpu_to_le16(pf->port_id); + req->tx_stat_host_addr =3D cpu_to_le64(bn->port_stats.hw_stats_map + + BNGE_TX_PORT_STATS_BYTE_OFFSET); + req->rx_stat_host_addr =3D cpu_to_le64(bn->port_stats.hw_stats_map); + + return bnge_hwrm_req_send(bd, req); +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.h index 86ca3ac2244b..3501de7a89b9 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h @@ -62,4 +62,7 @@ int bnge_hwrm_phy_qcaps(struct bnge_dev *bd); int bnge_hwrm_set_link_setting(struct bnge_net *bn, bool set_pause); int bnge_hwrm_set_pause(struct bnge_net *bn); int bnge_hwrm_shutdown_link(struct bnge_dev *bd); +int bnge_hwrm_port_qstats(struct bnge_dev *bd, u8 flags); +int bnge_hwrm_port_qstats_ext(struct bnge_dev *bd, u8 flags); +int bnge_hwrm_func_qstat_ext(struct bnge_dev *bd, struct bnge_stats_mem *s= tats); #endif /* _BNGE_HWRM_LIB_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 90458b323120..290bf1cd96c9 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -39,6 +39,10 @@ static void bnge_free_stats_mem(struct bnge_net *bn, { struct bnge_dev *bd =3D bn->bd; =20 + kfree(stats->hw_masks); + stats->hw_masks =3D NULL; + kfree(stats->sw_stats); + stats->sw_stats =3D NULL; if (stats->hw_stats) { dma_free_coherent(bd->dev, stats->len, stats->hw_stats, stats->hw_stats_map); @@ -47,7 +51,7 @@ static void bnge_free_stats_mem(struct bnge_net *bn, } =20 static int bnge_alloc_stats_mem(struct bnge_net *bn, - struct bnge_stats_mem *stats) + struct bnge_stats_mem *stats, bool alloc_masks) { struct bnge_dev *bd =3D bn->bd; =20 @@ -56,7 +60,20 @@ static int bnge_alloc_stats_mem(struct bnge_net *bn, if (!stats->hw_stats) return -ENOMEM; =20 + stats->sw_stats =3D kzalloc(stats->len, GFP_KERNEL); + if (!stats->sw_stats) + goto stats_mem_err; + + if (alloc_masks) { + stats->hw_masks =3D kzalloc(stats->len, GFP_KERNEL); + if (!stats->hw_masks) + goto stats_mem_err; + } return 0; + +stats_mem_err: + bnge_free_stats_mem(bn, stats); + return -ENOMEM; } =20 static void bnge_free_ring_stats(struct bnge_net *bn) @@ -75,6 +92,107 @@ static void bnge_free_ring_stats(struct bnge_net *bn) } } =20 +static void bnge_fill_masks(u64 *mask_arr, u64 mask, int count) +{ + int i; + + for (i =3D 0; i < count; i++) + mask_arr[i] =3D mask; +} + +void bnge_copy_hw_masks(u64 *mask_arr, __le64 *hw_mask_arr, int count) +{ + int i; + + for (i =3D 0; i < count; i++) + mask_arr[i] =3D le64_to_cpu(hw_mask_arr[i]); +} + +static void bnge_init_stats(struct bnge_net *bn) +{ + struct bnge_napi *bnapi =3D bn->bnapi[0]; + struct bnge_nq_ring_info *nqr; + struct bnge_stats_mem *stats; + struct bnge_dev *bd =3D bn->bd; + __le64 *rx_stats, *tx_stats; + int rc, rx_count, tx_count; + u64 *rx_masks, *tx_masks; + u8 flags; + + nqr =3D &bnapi->nq_ring; + stats =3D &nqr->stats; + rc =3D bnge_hwrm_func_qstat_ext(bd, stats); + if (rc) { + u64 mask =3D (1ULL << 48) - 1; + + bnge_fill_masks(stats->hw_masks, mask, stats->len / 8); + } + + if (bn->flags & BNGE_FLAG_PORT_STATS) { + stats =3D &bn->port_stats; + rx_stats =3D stats->hw_stats; + rx_masks =3D stats->hw_masks; + rx_count =3D sizeof(struct rx_port_stats) / 8; + tx_stats =3D rx_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + tx_masks =3D rx_masks + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + tx_count =3D sizeof(struct tx_port_stats) / 8; + + flags =3D PORT_QSTATS_REQ_FLAGS_COUNTER_MASK; + rc =3D bnge_hwrm_port_qstats(bd, flags); + if (rc) { + u64 mask =3D (1ULL << 40) - 1; + + bnge_fill_masks(rx_masks, mask, rx_count); + bnge_fill_masks(tx_masks, mask, tx_count); + } else { + bnge_copy_hw_masks(rx_masks, rx_stats, rx_count); + bnge_copy_hw_masks(tx_masks, tx_stats, tx_count); + } + bnge_hwrm_port_qstats(bd, 0); + } + + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + stats =3D &bn->rx_port_stats_ext; + rx_stats =3D stats->hw_stats; + rx_masks =3D stats->hw_masks; + rx_count =3D sizeof(struct rx_port_stats_ext) / 8; + stats =3D &bn->tx_port_stats_ext; + tx_stats =3D stats->hw_stats; + tx_masks =3D stats->hw_masks; + tx_count =3D sizeof(struct tx_port_stats_ext) / 8; + + flags =3D PORT_QSTATS_EXT_REQ_FLAGS_COUNTER_MASK; + rc =3D bnge_hwrm_port_qstats_ext(bd, flags); + if (rc) { + u64 mask =3D (1ULL << 40) - 1; + + bnge_fill_masks(rx_masks, mask, rx_count); + if (tx_stats) + bnge_fill_masks(tx_masks, mask, tx_count); + } else { + bnge_copy_hw_masks(rx_masks, rx_stats, rx_count); + if (tx_stats) + bnge_copy_hw_masks(tx_masks, tx_stats, + tx_count); + } + bnge_hwrm_port_qstats_ext(bd, 0); + } +} + +static void bnge_free_port_ext_stats(struct bnge_net *bn) +{ + bn->flags &=3D ~BNGE_FLAG_PORT_STATS_EXT; + bnge_free_stats_mem(bn, &bn->rx_port_stats_ext); + bnge_free_stats_mem(bn, &bn->tx_port_stats_ext); +} + +static void bnge_free_port_stats(struct bnge_net *bn) +{ + bn->flags &=3D ~BNGE_FLAG_PORT_STATS; + bnge_free_stats_mem(bn, &bn->port_stats); + bnge_free_port_ext_stats(bn); +} + static int bnge_alloc_ring_stats(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; @@ -88,12 +206,13 @@ static int bnge_alloc_ring_stats(struct bnge_net *bn) struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; =20 nqr->stats.len =3D size; - rc =3D bnge_alloc_stats_mem(bn, &nqr->stats); + rc =3D bnge_alloc_stats_mem(bn, &nqr->stats, !i); if (rc) goto err_free_ring_stats; =20 nqr->hw_stats_ctx_id =3D INVALID_STATS_CTX_ID; } + return 0; =20 err_free_ring_stats: @@ -101,6 +220,51 @@ static int bnge_alloc_ring_stats(struct bnge_net *bn) return rc; } =20 +static void bnge_alloc_port_ext_stats(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int rc; + + if (!(bd->fw_cap & BNGE_FW_CAP_EXT_STATS_SUPPORTED)) + return; + + if (!bn->rx_port_stats_ext.hw_stats) { + bn->rx_port_stats_ext.len =3D sizeof(struct rx_port_stats_ext); + rc =3D bnge_alloc_stats_mem(bn, &bn->rx_port_stats_ext, true); + /* Extended stats are optional */ + if (rc) + return; + } + + if (!bn->tx_port_stats_ext.hw_stats) { + bn->tx_port_stats_ext.len =3D sizeof(struct tx_port_stats_ext); + rc =3D bnge_alloc_stats_mem(bn, &bn->tx_port_stats_ext, true); + /* Extended stats are optional */ + if (rc) { + bnge_free_port_ext_stats(bn); + return; + } + } + bn->flags |=3D BNGE_FLAG_PORT_STATS_EXT; +} + +static int bnge_alloc_port_stats(struct bnge_net *bn) +{ + int rc; + + if (!bn->port_stats.hw_stats) { + bn->port_stats.len =3D BNGE_PORT_STATS_SIZE; + rc =3D bnge_alloc_stats_mem(bn, &bn->port_stats, true); + if (rc) + return rc; + + bn->flags |=3D BNGE_FLAG_PORT_STATS; + } + + bnge_alloc_port_ext_stats(bn); + return 0; +} + void __bnge_queue_sp_work(struct bnge_net *bn) { queue_work(bn->bnge_pf_wq, &bn->sp_task); @@ -1028,6 +1192,8 @@ static int bnge_alloc_core(struct bnge_net *bn) if (rc) goto err_free_core; =20 + bnge_init_stats(bn); + rc =3D bnge_alloc_vnics(bn); if (rc) goto err_free_core; @@ -2904,15 +3070,21 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_= irqs) if (rc) goto err_free_workq; =20 + rc =3D bnge_alloc_port_stats(bn); + if (rc) + goto err_free_workq; + netdev->request_ops_lock =3D true; rc =3D register_netdev(netdev); if (rc) { dev_err(bd->dev, "Register netdev failed rc: %d\n", rc); - goto err_free_workq; + goto err_free_port_stats; } =20 return 0; =20 +err_free_port_stats: + bnge_free_port_stats(bn); err_free_workq: destroy_workqueue(bn->bnge_pf_wq); err_netdev: @@ -2934,6 +3106,8 @@ void bnge_netdev_free(struct bnge_dev *bd) bn->sp_event =3D 0; destroy_workqueue(bn->bnge_pf_wq); =20 + bnge_free_port_stats(bn); + free_netdev(netdev); bd->netdev =3D NULL; } diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 5636eb371e24..15ededb801f6 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "bnge_db.h" #include "bnge_hw_def.h" #include "bnge_link.h" @@ -224,6 +225,42 @@ struct bnge_tpa_info { #define BNGE_NQ_HDL_IDX(hdl) ((hdl) & BNGE_NQ_HDL_IDX_MASK) #define BNGE_NQ_HDL_TYPE(hdl) (((hdl) & BNGE_NQ_HDL_TYPE_MASK) >> \ BNGE_NQ_HDL_TYPE_SHIFT) +#define BNGE_GET_RING_STATS64(sw, counter) \ + (*((sw) + offsetof(struct ctx_hw_stats, counter) / 8)) + +#define BNGE_GET_RX_PORT_STATS64(sw, counter) \ + (*((sw) + offsetof(struct rx_port_stats, counter) / 8)) + +#define BNGE_GET_TX_PORT_STATS64(sw, counter) \ + (*((sw) + offsetof(struct tx_port_stats, counter) / 8)) + +#define BNGE_PORT_STATS_SIZE \ + (sizeof(struct rx_port_stats) + sizeof(struct tx_port_stats) + 1024) + +#define BNGE_TX_PORT_STATS_BYTE_OFFSET \ + (sizeof(struct rx_port_stats) + 512) + +#define BNGE_RX_STATS_OFFSET(counter) \ + (offsetof(struct rx_port_stats, counter) / 8) + +#define BNGE_TX_STATS_OFFSET(counter) \ + ((offsetof(struct tx_port_stats, counter) + \ + BNGE_TX_PORT_STATS_BYTE_OFFSET) / 8) + +#define BNGE_RX_STATS_EXT_OFFSET(counter) \ + (offsetof(struct rx_port_stats_ext, counter) / 8) + +#define BNGE_TX_STATS_EXT_OFFSET(counter) \ + (offsetof(struct tx_port_stats_ext, counter) / 8) + +struct bnge_stats_mem { + u64 *sw_stats; + u64 *hw_masks; + void *hw_stats; + dma_addr_t hw_stats_map; + u32 len; + struct u64_stats_sync syncp; +}; =20 enum bnge_net_state { BNGE_STATE_NAPI_DISABLED, @@ -231,6 +268,11 @@ enum bnge_net_state { =20 #define BNGE_TIMER_INTERVAL HZ =20 +enum bnge_net_flag { + BNGE_FLAG_PORT_STATS =3D BIT(0), + BNGE_FLAG_PORT_STATS_EXT =3D BIT(1), +}; + enum bnge_sp_event { BNGE_LINK_CHNG_SP_EVENT, BNGE_LINK_SPEED_CHNG_SP_EVENT, @@ -309,6 +351,17 @@ struct bnge_net { unsigned long sp_event; =20 struct bnge_ethtool_link_info eth_link_info; + + u64 flags; + + struct bnge_stats_mem port_stats; + struct bnge_stats_mem rx_port_stats_ext; + struct bnge_stats_mem tx_port_stats_ext; + u16 fw_rx_stats_ext_size; + u16 fw_tx_stats_ext_size; + + u8 pri2cos_idx[8]; + bool pri2cos_valid; }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 @@ -374,14 +427,6 @@ void bnge_set_ring_params(struct bnge_dev *bd); bnge_writeq(bd, (db)->db_key64 | DBR_TYPE_NQ_ARM | \ DB_RING_IDX(db, idx), (db)->doorbell) =20 -struct bnge_stats_mem { - u64 *sw_stats; - u64 *hw_masks; - void *hw_stats; - dma_addr_t hw_stats_map; - int len; -}; - struct nqe_cn { __le16 type; #define NQ_CN_TYPE_MASK 0x3fUL @@ -588,4 +633,5 @@ u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dma_addr_= t *mapping, int bnge_alloc_rx_netmem(struct bnge_net *bn, struct bnge_rx_ring_info *rx= r, u16 prod, gfp_t gfp); void __bnge_queue_sp_work(struct bnge_net *bn); +void bnge_copy_hw_masks(u64 *mask_arr, __le64 *hw_mask_arr, int count); #endif /* _BNGE_NETDEV_H_ */ --=20 2.47.3 From nobody Sun Apr 5 18:20:21 2026 Received: from mail-qk1-f228.google.com (mail-qk1-f228.google.com [209.85.222.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 227CB37C90D for ; Fri, 3 Apr 2026 07:38:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201925; cv=none; b=J6fL5giZJR7XuS02LMZMDgKH8dCZkxVtjrxLmtY98ujJZT+k8kS6oe93uxjb8MoBaLHNF5qgACZMAPUC39ibzbyC9Ah9BNwdcbW1eRNyva+pcHkEspKvgjbnkV6JJvfyBYFAUpGX6wN5VwagR6tTYyq20O12eOallj+53FEz7Tg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201925; c=relaxed/simple; bh=xN6tiyKspxsgVMlC8vJzNsPDISw/N/AbJdMOGbgS6f0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=vDLQLCKJeczkwIzTU4QfJUpUlxZXKalqIJu25UrQhYvTYjKK7UW7Z0k+pu2Emqht+KGTTnwRpxw9gd0KPqDWoOMUViCef9Fi9z/FitTLpF/Q4ZYQYXrim8IDX4zCJeN1eIdNinOtqtMQfMX60iJ1LneqPsIxkVE3xDkGqJv0aYE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=bMhKxiKY; arc=none smtp.client-ip=209.85.222.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="bMhKxiKY" Received: by mail-qk1-f228.google.com with SMTP id af79cd13be357-8cd78a4ce8dso220650985a.3 for ; Fri, 03 Apr 2026 00:38:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201923; x=1775806723; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=1HFToVJAFcLFa0HENZoEwa3N44/rquYMYOZOURTmueM=; b=dHWqlY71/ommhZpcWLln8ksgWa9bpegHP0IScz3708m0zYGM6wKWy5I2BCySJqdPSp FBP0S6Xw0PuRemTuXMRX1bDl6jcXdvBy6x4iIIWJ68ocpjakRDtLWK9Um9gLeuyrXmhH IvjbmiAZL/+/QvWQLNkYC+ADgFIAmqHpSMVNLad1Lrh/zl4xoaEYKil1ypigeVLQpFZb kEzW4UVi37ow6kmn9k2x+ZdEZx+9qNPLzkTZzj6/RX1gITObhkyrkL+p5Q2LNG2ZCRnv JSAmTWrvNLd69oDCZgZ7DbR3yuAzW6eThy9UbFJh3A7nqfYg5dZh0dq1vBD3NhfpZznl 4cNQ== X-Forwarded-Encrypted: i=1; AJvYcCUAXhcIYno/U1M7rDhEn7Yx1eHs0r7GLpGyg4kL4ZHKmDVIyiWss3A0oWVWty7KdvHprJFjEwntZgZhReU=@vger.kernel.org X-Gm-Message-State: AOJu0YwKivtCzOqwAUSG3AV7tNFd+rprQAcqi4YAS4m5t7OjCOTcvMVF qzxfXjh/S77DQMTSGOQk3GNQ+srhiy7+px6/AvKEjkPBHKXzZlCK/nV8+TruxY1v8qE5O5gHFOQ 8jmiwy9gRzYWm7lquN/b/dZLCdw9R7/fSCoihTATIZLRQ0+kNm3kPy/sd6FgnSF6cEZVRfPFbLV l73k8TbpkkmO6Lx0PHxCAeo6/2+UQYGNJL1KzAO/tUahzeX+h4oWsogyVZYEynaP9P7A56Fg+7w QgmT1uZkjn03r4VFF3+396b7w== X-Gm-Gg: ATEYQzy4e3l3fGlI5hLWMzNU7dPOakSq6Orzv4VLX3RvG6PLPNxsbCbXxfA2XtebhvM l4v9EzKjWi2FqJJqcFaSnokT29fA+NjXiSu5CfKzTr9nnFgTQWjFRf0UHK2sk/nbO8X4EjzyBKB 8VlDeOOV1RmoDeMFft+eJy/8RbwyVqaBq16dW3QJL9Et0O07+/H0uK1PRfwd+X7ejX6pm9Qc4dm xZ4onjr6+wbxrTM8lwbOANiSScVEnZlucvTwpyjeU3TFXtIGXU1dZ8QhjCMy93OWpu0PQyOy6ou nW+GML6d5nRVL2rwuFl0Df4xVAHmkcZTYsOIg2py85Jsmeynz0S8/2Ifch96P6O3N9vWguJRb4g uDFJfg7NAoOTbDDHZbYbQqwQLg+bvlvkIMQxRO7VHRBa7Ycuoq5LN6uEvRej4ABOiJupMTQQFfV OaEXaawsO/sHAW/IxJxZ8KoegxYudXH3DdT4ukHGh4aHb3/eyljJECmp6QI94gsrQ= X-Received: by 2002:a05:620a:7113:b0:8cf:c08e:5f64 with SMTP id af79cd13be357-8d41adfbf80mr300904785a.40.1775201923041; Fri, 03 Apr 2026 00:38:43 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-24.dlp.protect.broadcom.com. [144.49.247.24]) by smtp-relay.gmail.com with ESMTPS id af79cd13be357-8d4bde1974bsm1975485a.7.2026.04.03.00.38.42 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:43 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-354c0234c1fso1870344a91.2 for ; Fri, 03 Apr 2026 00:38:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201922; x=1775806722; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1HFToVJAFcLFa0HENZoEwa3N44/rquYMYOZOURTmueM=; b=bMhKxiKYFMZCFi6py+WtSpyXiDJkA+1ioBJk6np4v53nSpHjeB/SH2ebHblzzvX2wq sNMd8fBIRSkpar3ukEPe7fYeXA4kmj3urSL3upCsJzXt96Qd1aFmFNrguobCGuGDlMYA 76JyRocuMKtplGxwSiCgfyaCgoKUl8h1RSIhI= X-Forwarded-Encrypted: i=1; AJvYcCU9CCcz9/yKNewkwOrzwLNZ8yrMUxwDC3kJSDeUDDkM5VKZraYbOGSWb9xzbaKPWgFKEozGmZFEl912tug=@vger.kernel.org X-Received: by 2002:a17:90b:3c4a:b0:35d:a412:3c79 with SMTP id 98e67ed59e1d1-35de69774ccmr1985050a91.30.1775201921840; Fri, 03 Apr 2026 00:38:41 -0700 (PDT) X-Received: by 2002:a17:90b:3c4a:b0:35d:a412:3c79 with SMTP id 98e67ed59e1d1-35de69774ccmr1985033a91.30.1775201921410; Fri, 03 Apr 2026 00:38:41 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:40 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rahul Gupta , Ajit Kumar Khaparde Subject: [PATCH net-next v11 07/10] bng_en: periodically fetch and accumulate hardware statistics Date: Fri, 3 Apr 2026 13:07:21 +0530 Message-ID: <20260403073724.194360-8-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Use the timer to schedule periodic stats collection via the workqueue when the link is up. Fetch fresh counters from hardware via DMA and accumulate them into 64-bit software shadows, handling wrap-around for counters narrower than 64 bits. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rahul Gupta Reviewed-by: Ajit Kumar Khaparde --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 97 +++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.h | 1 + 2 files changed, 98 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 290bf1cd96c9..61bac71c7f74 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -69,6 +69,9 @@ static int bnge_alloc_stats_mem(struct bnge_net *bn, if (!stats->hw_masks) goto stats_mem_err; } + + u64_stats_init(&stats->syncp); + return 0; =20 stats_mem_err: @@ -294,9 +297,97 @@ static void bnge_timer(struct timer_list *t) } } =20 + if (BNGE_LINK_IS_UP(bd) && bn->stats_coal_ticks) + bnge_queue_sp_work(bn, BNGE_PERIODIC_STATS_SP_EVENT); + mod_timer(&bn->timer, jiffies + bn->current_interval); } =20 +static void bnge_add_one_ctr(u64 hw, u64 *sw, u64 mask) +{ + u64 sw_tmp, sw_val; + + hw &=3D mask; + sw_val =3D READ_ONCE(*sw); + sw_tmp =3D (sw_val & ~mask) | hw; + if (hw < (sw_val & mask)) + sw_tmp +=3D mask + 1; + WRITE_ONCE(*sw, sw_tmp); +} + +static void __bnge_accumulate_stats(__le64 *hw_stats, u64 *sw_stats, u64 *= masks, + int count, struct u64_stats_sync *syncp) +{ + int i; + + u64_stats_update_begin(syncp); + for (i =3D 0; i < count; i++) { + u64 hw =3D le64_to_cpu(READ_ONCE(hw_stats[i])); + + if (masks[i] =3D=3D -1ULL) + WRITE_ONCE(sw_stats[i], hw); + else + bnge_add_one_ctr(hw, &sw_stats[i], masks[i]); + } + u64_stats_update_end(syncp); +} + +static void bnge_accumulate_stats(struct bnge_stats_mem *stats) +{ + if (!stats->hw_stats) + return; + + __bnge_accumulate_stats(stats->hw_stats, stats->sw_stats, + stats->hw_masks, stats->len / 8, &stats->syncp); +} + +static void bnge_accumulate_all_stats(struct bnge_dev *bd) +{ + struct bnge_net *bn =3D netdev_priv(bd->netdev); + struct bnge_stats_mem *ring0_stats =3D NULL; + int i; + + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + struct bnge_nq_ring_info *nqr; + struct bnge_stats_mem *stats; + + nqr =3D &bnapi->nq_ring; + stats =3D &nqr->stats; + + if (!ring0_stats) + ring0_stats =3D &bn->bnapi[0]->nq_ring.stats; + + __bnge_accumulate_stats(stats->hw_stats, stats->sw_stats, + ring0_stats->hw_masks, + ring0_stats->len / 8, &stats->syncp); + } + + if (bn->flags & BNGE_FLAG_PORT_STATS) { + struct bnge_stats_mem *stats =3D &bn->port_stats; + __le64 *hw_stats =3D stats->hw_stats; + u64 *sw_stats =3D stats->sw_stats; + u64 *masks =3D stats->hw_masks; + u16 cnt; + + cnt =3D sizeof(struct rx_port_stats) / 8; + __bnge_accumulate_stats(hw_stats, sw_stats, masks, cnt, + &stats->syncp); + + hw_stats +=3D BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + sw_stats +=3D BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + masks +=3D BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + cnt =3D sizeof(struct tx_port_stats) / 8; + __bnge_accumulate_stats(hw_stats, sw_stats, masks, cnt, + &stats->syncp); + } + + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + bnge_accumulate_stats(&bn->rx_port_stats_ext); + bnge_accumulate_stats(&bn->tx_port_stats_ext); + } +} + static void bnge_sp_task(struct work_struct *work) { struct bnge_net *bn =3D container_of(work, struct bnge_net, sp_task); @@ -309,6 +400,12 @@ static void bnge_sp_task(struct work_struct *work) return; } =20 + if (test_and_clear_bit(BNGE_PERIODIC_STATS_SP_EVENT, &bn->sp_event)) { + bnge_hwrm_port_qstats(bd, 0); + bnge_hwrm_port_qstats_ext(bd, 0); + bnge_accumulate_all_stats(bd); + } + if (test_and_clear_bit(BNGE_UPDATE_PHY_SP_EVENT, &bn->sp_event)) { int rc; =20 diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 15ededb801f6..a73f51b01bc2 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -278,6 +278,7 @@ enum bnge_sp_event { BNGE_LINK_SPEED_CHNG_SP_EVENT, BNGE_LINK_CFG_CHANGE_SP_EVENT, BNGE_UPDATE_PHY_SP_EVENT, + BNGE_PERIODIC_STATS_SP_EVENT, }; =20 struct bnge_net { --=20 2.47.3 From nobody Sun Apr 5 18:20:21 2026 Received: from mail-oo1-f98.google.com (mail-oo1-f98.google.com [209.85.161.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A84EC37C90D for ; Fri, 3 Apr 2026 07:38:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.98 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201930; cv=none; b=Z8z0RdqwITUELgJA0pxAFoGtnpSFRKHesf3MxzQaW87WalrtaauDchkeU+zsEkuYQhs5215hC4senXF+UpTjrSC/GeY9MU9LBsH6+rO8/RBu7/ecC+GZiomDOHF5l+ap0jmQO2EmvMxbRnsH7WV5FPDQGY42dE9+k91Akkljewg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201930; c=relaxed/simple; bh=UZaqlO8VeMfK4aEKq77j2AIGkI8+JtmAtIhTVoDJFvo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kE97s4xL2NvHcs1lsltTtEaQwJIb/pIwQ4nEvcWjEXnB8H1GTek5x4bQ3vhH3tse2Js0wVZRFMKmTsBHFNOieLn/qGUxAyP3fxKqHKslFciQ+1slMIe3SYwOaH+1NHOqVX0FVDDyWJ47Grg6qEPJm/4GdhDlbYuzEzGVHyzVDWI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=e9eZdd6K; arc=none smtp.client-ip=209.85.161.98 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="e9eZdd6K" Received: by mail-oo1-f98.google.com with SMTP id 006d021491bc7-67de15e8452so1685743eaf.0 for ; Fri, 03 Apr 2026 00:38:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201928; x=1775806728; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=h6lKK5aP5kx8lPrjwqHaz+xkwFO79/yzuqTI3BWKwFM=; b=ESDVIOXi79yY6vjh09DftsyYi33BaPjQurwKuzghP+umjSGHHbhspgZl7t6IHtIPwO 1rhSwE77oXgxAxpt5skyC7t11qBJV6eKmh4uDAk6Ta0NmUP9+6jx6VC3e0ODoDDWwsm2 nOVmBTunQSowRmvpybMoL43mhXZX6zJPvjZx70J3pkb0DsDqyile1crhJ4+lOtcBkhj3 EyMgCUG9lSplRYn6uFaRRLoy2SUPEib8N2pPlC3vrYPGn3E//Bv0MSJbfTtNkRVOeB9g KDTcow3U7hQCE7PVs5xnYMbaERo9PvUXMtIv81SPN16Gn/jeIzgRsY+bIQwimQzrxGnF dnWQ== X-Forwarded-Encrypted: i=1; AJvYcCUGzttdNTWr0gYG1e98AKlIEMHKeCHqidzZyLNyBPmP43UYJPOHT0ebmbTf4tNNhAue+IxZE1HBZszcPQo=@vger.kernel.org X-Gm-Message-State: AOJu0Yyik5G9Pqof7glB4QZXopgHFIaBl49nky+3HuqaNv+j22Xrjp+M YuDEsSc0TfNTqzIj6t5bP9kQ9TRwYHP1GPbrVe+yqDdEyyI4yIu/L5xX27ace+YrnFRFh3fCm7B wy9+jtgHGEgdzRyB22rIyddPvW2UCW2yUI40y8AaxEqjtH+S+QV8RLMjasgBcDzq9iBcxcTjcN3 lRujhlIUf05xwzyFboHtE5NnhZAnAjuLwASQW+bVQ/vm6UJOHiRamq5BG76mL8KzN8aiPpdzJl5 EmmViZagK7Y4Gl4ieSemDUrNw== X-Gm-Gg: ATEYQzwvgb8TpL6VFdEb50+gqJANqoV+j/BfHuMMZoUU7xHqF4KoSE4kDVE3x8tsfF0 Kn/2tfLslsefbaoqoplF1odX8wuv07L2h/qfb7nnhhmJNhdXktwUlUKHAnMcjJSeDPOI74w0Udd O3Gt6y5Cvej1va51yfd+USDKJ1akJtsN4q3jT/Et8S6uyAMK9FyN/ITg53krzZhUU7qUe9ODaBH Zh5WEVzT7neH/L6WCblfazEL0D8UKmtQQ7sz+j8f5iVRl/8T/9MXKpRd4NoWFxED5uL2hSnQvFZ quXPdJkL8TU5xiZl6X7wCRxu3oeArVv+tqKzd5DteF8w0LfnmpqcESgBVlExeTKp82x8wj3X/GK dQFphEScPYx1X69jboebBM/7PByRLozCwQM7zifDC+4yH85jxVSlz67/12GT6H6fE0mKlvxWqla +v73x02SpcGjG9EUOhDVTL79X1o+irKTtbC0lAXt524tVtRz8nx4BkZbnJY2C4qk4= X-Received: by 2002:a05:6820:998:b0:67f:31e3:81a with SMTP id 006d021491bc7-6821dd77ea0mr1011138eaf.2.1775201928279; Fri, 03 Apr 2026 00:38:48 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-15.dlp.protect.broadcom.com. [144.49.247.15]) by smtp-relay.gmail.com with ESMTPS id 006d021491bc7-680a56f31dbsm246545eaf.5.2026.04.03.00.38.47 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:48 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-35845fcf0f5so1749048a91.0 for ; Fri, 03 Apr 2026 00:38:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201926; x=1775806726; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=h6lKK5aP5kx8lPrjwqHaz+xkwFO79/yzuqTI3BWKwFM=; b=e9eZdd6KfD55KRyDamEMpT0Mf2Ke+Jc/fgFDAUVjXbCo76cuSRduLi08fAxMW3MbRR Miaxm4AccVrP/MIb3aOz9VZViuvOyqXXjhFJG9YeuhSlpLoytHcwKtLqOH6bspOjBYXb 0dIYmp2fwnKM1hsKwwelEmzC4rfmc2JXOpxrQ= X-Forwarded-Encrypted: i=1; AJvYcCW8ANzwJNPRTntyLmYgdrCKiBTkR2RQV/Keg8pJNtrrclgSm7NuNe0w9f6+OLpvt7gz1nmQn/ek0+gEnLM=@vger.kernel.org X-Received: by 2002:a17:90b:2b50:b0:35d:9276:eba7 with SMTP id 98e67ed59e1d1-35de5972e5emr1736049a91.7.1775201926563; Fri, 03 Apr 2026 00:38:46 -0700 (PDT) X-Received: by 2002:a17:90b:2b50:b0:35d:9276:eba7 with SMTP id 98e67ed59e1d1-35de5972e5emr1736038a91.7.1775201926090; Fri, 03 Apr 2026 00:38:46 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:45 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy Subject: [PATCH net-next v11 08/10] bng_en: implement ndo_get_stats64 Date: Fri, 3 Apr 2026 13:07:22 +0530 Message-ID: <20260403073724.194360-9-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Implement the ndo_get_stats64 callback to report aggregate network statistics. The driver gathers these by accumulating the per-ring counters into the provided rtnl_link_stats64 structure. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 61bac71c7f74..9a5d667defea 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -2897,6 +2897,46 @@ static int bnge_shutdown_nic(struct bnge_net *bn) return 0; } =20 +static void bnge_get_port_stats64(struct bnge_net *bn, + struct rtnl_link_stats64 *stats) +{ + unsigned int start; + u64 *tx, *rx; + + rx =3D bn->port_stats.sw_stats; + tx =3D bn->port_stats.sw_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + + do { + start =3D u64_stats_fetch_begin(&bn->port_stats.syncp); + + stats->rx_crc_errors =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_fcs_err_frames); + stats->rx_frame_errors =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_align_err_frames); + stats->rx_length_errors =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_undrsz_frames) + + BNGE_GET_RX_PORT_STATS64(rx, rx_ovrsz_frames) + + BNGE_GET_RX_PORT_STATS64(rx, rx_runt_frames); + stats->rx_errors =3D + BNGE_GET_RX_PORT_STATS64(rx, rx_false_carrier_frames) + + BNGE_GET_RX_PORT_STATS64(rx, rx_jbr_frames); + stats->collisions =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_total_collisions); + stats->tx_fifo_errors =3D + BNGE_GET_TX_PORT_STATS64(tx, tx_fifo_underruns); + stats->tx_errors =3D BNGE_GET_TX_PORT_STATS64(tx, tx_err); + } while (u64_stats_fetch_retry(&bn->port_stats.syncp, start)); +} + +static void bnge_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct bnge_net *bn =3D netdev_priv(dev); + + if (bn->flags & BNGE_FLAG_PORT_STATS) + bnge_get_port_stats64(bn, stats); +} + static void bnge_close_core(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; @@ -2930,6 +2970,7 @@ static const struct net_device_ops bnge_netdev_ops = =3D { .ndo_open =3D bnge_open, .ndo_stop =3D bnge_close, .ndo_start_xmit =3D bnge_start_xmit, + .ndo_get_stats64 =3D bnge_get_stats64, .ndo_features_check =3D bnge_features_check, }; =20 --=20 2.47.3 From nobody Sun Apr 5 18:20:21 2026 Received: from mail-pg1-f228.google.com (mail-pg1-f228.google.com [209.85.215.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 89CD0378D63 for ; Fri, 3 Apr 2026 07:38:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201936; cv=none; b=uTVdBZNVKuYjOmAHkS0Jxn8q4gws0HnNzpXwd2AS9pD2GzP2KToDFLYFqFyQWHvhqrkK0H2RkmUoGybZ1ldmZ4+Q2X2ERaa/PiPyOA42U/63FsiEyF5M+jcWefjAfMUjB4g6eFH3RiNufqmwY2dOTkLerSZdArFAeF9vdX/953Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201936; c=relaxed/simple; bh=ZZqrPTcVEVCs2us9N1me1Ia3g2J0SjMmqgrQS0luHOY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XSBoJr8K9p05vuajx+APHg2TdpV7VpAqD6Ys81gvU549exvTFIDEIdYZNW7g3fYNF8H6aheKo1upDFw+op+6P5T7wORARVYXbq4eDV+vCabdKEjXrYPtmW6+UKkFn9tJ3m9jUTbmg6dCjI0zvEFdtqT+aJYtUXBfkSLlY6KmN34= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=Jc98MH7y; arc=none smtp.client-ip=209.85.215.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="Jc98MH7y" Received: by mail-pg1-f228.google.com with SMTP id 41be03b00d2f7-c70c112cb61so920659a12.0 for ; Fri, 03 Apr 2026 00:38:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201933; x=1775806733; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=jBA5mYoFs7U2kVrS4kBVEGeuAEMM/jKmYSPSiTVI568=; b=P/X7lL90JVFb6Nda+bQR+k39Fo9HSud7tFOSbx9wbeIbJMsr5/onWKWeEoNnYOacH7 zx5j0GBNnb8lm79CBgcWw6r+i9lXEjXf4NEv2Pvf52rWwMfWhZG/LzhX+cpDWKpy5Lef nXo94dsfJwD5O1bEB8G+xJkccv9tDD1UywKqMxc1UGaOTRutdV2XHtzTrfGqvQs4vHfv DG7rnI0joM0FKtOIOgMr1RC9UERxsCrMvsQF5MbOIhkiPMqQYomgnn7VvqEBq0WoqQVx gtGiKjB8KRbAkFQ24oYksaEHjdT+JuKREGb5B846KFHR6cXVcELNSRTfTvdUI0g0ZFoA MyAw== X-Forwarded-Encrypted: i=1; AJvYcCWhe1eskqN9XdN0+6++yu2/XGXg8fVkTvbqPyT4KDZUf0lX10Mb8U+Y4PbE4Ezpz5G7sgu6VDqJslZlBbk=@vger.kernel.org X-Gm-Message-State: AOJu0YxWqGsCHO51XZLEmUMfEJ8XAmxCIAV7NaK+slYBryVbhpQ6KnjW n3EPZXt+bYSgXIGbkUIhdsMBPWnMi/uvVVy+1mEhXi0QuJODjfQdiAXkTDE4as2whbpg5KO02bL VBj7F4p2VWKbGMeDWX+bVuXvKE8y1d2vlPrIMHTJmkRrGxWMaUmHdxdIzPB0If9LLo5y5G5z13r iRYVN16VdppcAGL8YxVWyZuEOHvYx5gzYfMNrkhWZEZIpNDhvfSLnQ1NuxIiHNq6b2fM8C5mXVU fOpmMBqIydBuhPWaxdkkqSccQ== X-Gm-Gg: ATEYQzxQylBmVT58JPuGTrXU5JtFj3lZi+R+z8A4hPPWQ3fchpT3hMvOmoL2lvdCScQ QrRXgb1MVjl2R5INFmzzKogJ+4hpg2WMGscS4iQgp+6Bj4iE4x5TFEa4Fsb3dd6Vsf/HenjPAoU eocbGs0NJ6mTESlX8DCqnb6Ko5nqye5JR0PpS4N4y1FuuQvoygQI4hJrghlO3kYjsgCeWf4u9M3 Gyp3rVXKcxNOznJMUaY2S/MoFogAF8AKq6NeLAMabRFNK0qPmwM4Qh7X4IOfAX2XWEQzBPtYlyt s3T9bgGCSV/2WcEquFtBsPCQjD+APbedztTPmc32rRtjFDFF0ytkhha06Z4N5jxy+QVZapxTywE vL6yK9Ee4Y8G0iyVKFEA+UR6kGL5r6pcHA1shZWk2k62PWtS1lPhIhjrVZLMrreA58RTF7Mz8Ed CGpFBqTffjq3inYOmhAxo0wOlT8a2T4cwmilbLs+zwRp81+ndzFoBtoRJ/fDpYxP8= X-Received: by 2002:a05:6300:210f:b0:39c:126c:93b5 with SMTP id adf61e73a8af0-39f2ee49b59mr2056327637.21.1775201932874; Fri, 03 Apr 2026 00:38:52 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-25.dlp.protect.broadcom.com. [144.49.247.25]) by smtp-relay.gmail.com with ESMTPS id 41be03b00d2f7-c76c649e760sm253238a12.3.2026.04.03.00.38.52 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:52 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-35c1874336aso3798248a91.3 for ; Fri, 03 Apr 2026 00:38:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201931; x=1775806731; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jBA5mYoFs7U2kVrS4kBVEGeuAEMM/jKmYSPSiTVI568=; b=Jc98MH7y5L1cGo7xYBR7wtVxUV0+SYbiNostYOApL7aGUcpi7sZLq3kxK0B29WMCml zv8JJ3VjS8vKIewHE67L/ArYPo4lGLcNrvQB2PJQyTsSZ5oXDqPeTXXtPU8E6mucSBmf i71m9zb27tMaMsSa5WsZEjXIM3MbXnx+d8PEA= X-Forwarded-Encrypted: i=1; AJvYcCV9uPl6NwHm3ZKdSWafspfrsn+TAOTdZEcbv1Uorfu+Pr5GCx3nzl8TDsIWtEO+YhLdUsjWlZF5UMVyVKA=@vger.kernel.org X-Received: by 2002:a17:90a:d005:b0:35d:9d28:e897 with SMTP id 98e67ed59e1d1-35de699f483mr1758397a91.28.1775201930961; Fri, 03 Apr 2026 00:38:50 -0700 (PDT) X-Received: by 2002:a17:90a:d005:b0:35d:9d28:e897 with SMTP id 98e67ed59e1d1-35de699f483mr1758378a91.28.1775201930506; Fri, 03 Apr 2026 00:38:50 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:50 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy Subject: [PATCH net-next v11 09/10] bng_en: implement netdev_stat_ops Date: Fri, 3 Apr 2026 13:07:23 +0530 Message-ID: <20260403073724.194360-10-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Implement netdev_stat_ops to provide standardized per-queue statistics via the Netlink API. Below is the description of the hardware drop counters: rx-hw-drop-overruns: Packets dropped by HW due to resource limitations (e.g., no BDs available in the host ring). rx-hw-drops: Total packets dropped by HW (sum of overruns and error drops). tx-hw-drop-errors: Packets dropped by HW because they were invalid or malformed. tx-hw-drops: Total packets dropped by HW (sum of resource limitations and error drops). The implementation was verified using the ynl tool: ./tools/net/ynl/pyynl/cli.py --spec \ Documentation/netlink/specs/netdev.yaml --dump qstats-get --json \ '{"ifindex":14, "scope":"queue"}' [{'ifindex': 14, 'queue-id': 0, 'queue-type': 'rx', 'rx-bytes': 758, 'rx-hw-drop-overruns': 0, 'rx-hw-drops': 0, 'rx-packets': 11}, {'ifindex': 14, 'queue-id': 1, 'queue-type': 'rx', 'rx-bytes': 0, 'rx-hw-drop-overruns': 0, 'rx-hw-drops': 0, 'rx-packets': 0}, {'ifindex': 14, 'queue-id': 0, 'queue-type': 'tx', 'tx-bytes': 0, 'tx-hw-drop-errors': 0, 'tx-hw-drops': 0, 'tx-packets': 0}, {'ifindex': 14, 'queue-id': 1, 'queue-type': 'tx', 'tx-bytes': 0, 'tx-hw-drop-errors': 0, 'tx-hw-drops': 0, 'tx-packets': 0}, {'ifindex': 14, 'queue-id': 2, 'queue-type': 'tx', 'tx-bytes': 810, 'tx-hw-drop-errors': 0, 'tx-hw-drops': 0, 'tx-packets': 10},] Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 227 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.h | 7 + 2 files changed, 234 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 9a5d667defea..84090b048ba6 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -2859,6 +2859,7 @@ static int bnge_open_core(struct bnge_net *bn) } =20 set_bit(BNGE_STATE_OPEN, &bd->state); + set_bit(BNGE_STATE_STATS_ENABLE, &bn->state); =20 bnge_enable_int(bn); =20 @@ -2897,6 +2898,77 @@ static int bnge_shutdown_nic(struct bnge_net *bn) return 0; } =20 +static void bnge_add_prev_ring_stats64(struct bnge_net *bn, + struct rtnl_link_stats64 *stats) +{ + struct netdev_queue_stats_rx *rx_save =3D &bn->rxq_prv_stats; + struct netdev_queue_stats_tx *tx_save =3D &bn->txq_prv_stats; + struct rtnl_link_stats64 *stats64_save =3D &bn->prv_stats64; + + stats->rx_packets +=3D rx_save->packets; + stats->tx_packets +=3D tx_save->packets; + stats->rx_bytes +=3D rx_save->bytes; + stats->tx_bytes +=3D tx_save->bytes; + stats->rx_missed_errors +=3D rx_save->hw_drop_overruns; + stats->tx_dropped +=3D tx_save->hw_drop_errors; + + stats->multicast +=3D stats64_save->multicast; +} + +static void bnge_get_ring_stats64(struct bnge_dev *bd, + struct rtnl_link_stats64 *stats) +{ + struct bnge_net *bn =3D netdev_priv(bd->netdev); + int i; + + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + u64 tx_bytes, tx_packets, tx_dropped; + u64 multicast, rx_missed_errors; + struct bnge_nq_ring_info *nqr; + u64 rx_bytes, rx_packets; + unsigned int start; + u64 *sw; + + nqr =3D &bnapi->nq_ring; + sw =3D nqr->stats.sw_stats; + + do { + start =3D u64_stats_fetch_begin(&nqr->stats.syncp); + + rx_packets =3D BNGE_GET_RING_STATS64(sw, rx_ucast_pkts); + rx_packets +=3D BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); + rx_packets +=3D BNGE_GET_RING_STATS64(sw, rx_bcast_pkts); + + tx_packets =3D BNGE_GET_RING_STATS64(sw, tx_ucast_pkts); + tx_packets +=3D BNGE_GET_RING_STATS64(sw, tx_mcast_pkts); + tx_packets +=3D BNGE_GET_RING_STATS64(sw, tx_bcast_pkts); + + rx_bytes =3D BNGE_GET_RING_STATS64(sw, rx_ucast_bytes); + rx_bytes +=3D BNGE_GET_RING_STATS64(sw, rx_mcast_bytes); + rx_bytes +=3D BNGE_GET_RING_STATS64(sw, rx_bcast_bytes); + + tx_bytes =3D BNGE_GET_RING_STATS64(sw, tx_ucast_bytes); + tx_bytes +=3D BNGE_GET_RING_STATS64(sw, tx_mcast_bytes); + tx_bytes +=3D BNGE_GET_RING_STATS64(sw, tx_bcast_bytes); + + multicast =3D BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); + rx_missed_errors =3D + BNGE_GET_RING_STATS64(sw, rx_discard_pkts); + tx_dropped =3D + BNGE_GET_RING_STATS64(sw, tx_error_pkts); + } while (u64_stats_fetch_retry(&nqr->stats.syncp, start)); + + stats->rx_packets +=3D rx_packets; + stats->tx_packets +=3D tx_packets; + stats->rx_bytes +=3D rx_bytes; + stats->tx_bytes +=3D tx_bytes; + stats->multicast +=3D multicast; + stats->rx_missed_errors +=3D rx_missed_errors; + stats->tx_dropped +=3D tx_dropped; + } +} + static void bnge_get_port_stats64(struct bnge_net *bn, struct rtnl_link_stats64 *stats) { @@ -2928,6 +3000,22 @@ static void bnge_get_port_stats64(struct bnge_net *b= n, } while (u64_stats_fetch_retry(&bn->port_stats.syncp, start)); } =20 +static void bnge_fill_prev_stats64(struct bnge_net *bn, + struct rtnl_link_stats64 *stats) +{ + struct netdev_queue_stats_rx *rx_save =3D &bn->rxq_prv_stats; + struct netdev_queue_stats_tx *tx_save =3D &bn->txq_prv_stats; + struct rtnl_link_stats64 *stats64_save =3D &bn->prv_stats64; + + stats->rx_packets =3D rx_save->packets; + stats->tx_packets =3D tx_save->packets; + stats->rx_bytes =3D rx_save->bytes; + stats->tx_bytes =3D tx_save->bytes; + stats->rx_missed_errors =3D rx_save->hw_drop_overruns; + stats->tx_dropped =3D tx_save->hw_drop_errors; + stats->multicast =3D stats64_save->multicast; +} + static void bnge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { @@ -2935,6 +3023,57 @@ static void bnge_get_stats64(struct net_device *dev, =20 if (bn->flags & BNGE_FLAG_PORT_STATS) bnge_get_port_stats64(bn, stats); + + spin_lock_bh(&bn->stats_lock); + if (!test_bit(BNGE_STATE_STATS_ENABLE, &bn->state)) { + bnge_fill_prev_stats64(bn, stats); + spin_unlock_bh(&bn->stats_lock); + return; + } + + bnge_get_ring_stats64(bn->bd, stats); + bnge_add_prev_ring_stats64(bn, stats); + spin_unlock_bh(&bn->stats_lock); +} + +static void bnge_save_ring_stats(struct bnge_net *bn) +{ + struct netdev_queue_stats_rx *rx_save =3D &bn->rxq_prv_stats; + struct netdev_queue_stats_tx *tx_save =3D &bn->txq_prv_stats; + struct rtnl_link_stats64 *stats64_save =3D &bn->prv_stats64; + int i; + + for (i =3D 0; i < bn->bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + struct bnge_nq_ring_info *nqr; + u64 *sw; + + nqr =3D &bnapi->nq_ring; + sw =3D nqr->stats.sw_stats; + + rx_save->packets +=3D BNGE_GET_RING_STATS64(sw, rx_ucast_pkts); + rx_save->packets +=3D BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); + rx_save->packets +=3D BNGE_GET_RING_STATS64(sw, rx_bcast_pkts); + rx_save->bytes +=3D BNGE_GET_RING_STATS64(sw, rx_ucast_bytes); + rx_save->bytes +=3D BNGE_GET_RING_STATS64(sw, rx_mcast_bytes); + rx_save->bytes +=3D BNGE_GET_RING_STATS64(sw, rx_bcast_bytes); + rx_save->hw_drop_overruns +=3D BNGE_GET_RING_STATS64(sw, rx_discard_pkts= ); + rx_save->hw_drops +=3D BNGE_GET_RING_STATS64(sw, rx_error_pkts) + + BNGE_GET_RING_STATS64(sw, rx_discard_pkts); + + tx_save->packets +=3D BNGE_GET_RING_STATS64(sw, tx_ucast_pkts); + tx_save->packets +=3D BNGE_GET_RING_STATS64(sw, tx_mcast_pkts); + tx_save->packets +=3D BNGE_GET_RING_STATS64(sw, tx_bcast_pkts); + tx_save->bytes +=3D BNGE_GET_RING_STATS64(sw, tx_ucast_bytes); + tx_save->bytes +=3D BNGE_GET_RING_STATS64(sw, tx_mcast_bytes); + tx_save->bytes +=3D BNGE_GET_RING_STATS64(sw, tx_bcast_bytes); + tx_save->hw_drop_errors +=3D BNGE_GET_RING_STATS64(sw, tx_error_pkts); + tx_save->hw_drops +=3D BNGE_GET_RING_STATS64(sw, tx_discard_pkts) + + BNGE_GET_RING_STATS64(sw, tx_error_pkts); + + stats64_save->multicast +=3D + BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); + } } =20 static void bnge_close_core(struct bnge_net *bn) @@ -2948,6 +3087,13 @@ static void bnge_close_core(struct bnge_net *bn) timer_delete_sync(&bn->timer); bnge_shutdown_nic(bn); bnge_disable_napi(bn); + + /* Save ring stats before shutdown */ + spin_lock_bh(&bn->stats_lock); + bnge_save_ring_stats(bn); + clear_bit(BNGE_STATE_STATS_ENABLE, &bn->state); + spin_unlock_bh(&bn->stats_lock); + bnge_free_all_rings_bufs(bn); bnge_free_irq(bn); bnge_del_napi(bn); @@ -2966,6 +3112,85 @@ static int bnge_close(struct net_device *dev) return 0; } =20 +static void bnge_get_queue_stats_rx(struct net_device *dev, int i, + struct netdev_queue_stats_rx *stats) +{ + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_nq_ring_info *nqr; + u64 *sw; + + if (!bn->bnapi) + return; + + nqr =3D &bn->bnapi[i]->nq_ring; + sw =3D nqr->stats.sw_stats; + + stats->packets =3D 0; + stats->packets +=3D BNGE_GET_RING_STATS64(sw, rx_ucast_pkts); + stats->packets +=3D BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); + stats->packets +=3D BNGE_GET_RING_STATS64(sw, rx_bcast_pkts); + + stats->bytes =3D 0; + stats->bytes +=3D BNGE_GET_RING_STATS64(sw, rx_ucast_bytes); + stats->bytes +=3D BNGE_GET_RING_STATS64(sw, rx_mcast_bytes); + stats->bytes +=3D BNGE_GET_RING_STATS64(sw, rx_bcast_bytes); + + stats->hw_drop_overruns =3D BNGE_GET_RING_STATS64(sw, rx_discard_pkts); + stats->hw_drops =3D BNGE_GET_RING_STATS64(sw, rx_error_pkts) + + stats->hw_drop_overruns; +} + +static void bnge_get_queue_stats_tx(struct net_device *dev, int i, + struct netdev_queue_stats_tx *stats) +{ + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_napi *bnapi; + u64 *sw; + + if (!bn->tx_ring) + return; + + bnapi =3D bn->tx_ring[bn->tx_ring_map[i]].bnapi; + sw =3D bnapi->nq_ring.stats.sw_stats; + + stats->packets =3D 0; + stats->packets +=3D BNGE_GET_RING_STATS64(sw, tx_ucast_pkts); + stats->packets +=3D BNGE_GET_RING_STATS64(sw, tx_mcast_pkts); + stats->packets +=3D BNGE_GET_RING_STATS64(sw, tx_bcast_pkts); + + stats->bytes =3D 0; + stats->bytes +=3D BNGE_GET_RING_STATS64(sw, tx_ucast_bytes); + stats->bytes +=3D BNGE_GET_RING_STATS64(sw, tx_mcast_bytes); + stats->bytes +=3D BNGE_GET_RING_STATS64(sw, tx_bcast_bytes); + + stats->hw_drop_errors =3D BNGE_GET_RING_STATS64(sw, tx_error_pkts); + stats->hw_drops =3D BNGE_GET_RING_STATS64(sw, tx_discard_pkts) + + stats->hw_drop_errors; +} + +static void bnge_get_base_stats(struct net_device *dev, + struct netdev_queue_stats_rx *rx, + struct netdev_queue_stats_tx *tx) +{ + struct bnge_net *bn =3D netdev_priv(dev); + + rx->packets =3D bn->rxq_prv_stats.packets; + rx->bytes =3D bn->rxq_prv_stats.bytes; + rx->hw_drops =3D bn->rxq_prv_stats.hw_drops; + rx->hw_drop_overruns =3D bn->rxq_prv_stats.hw_drop_overruns; + + tx->packets =3D bn->txq_prv_stats.packets; + tx->bytes =3D bn->txq_prv_stats.bytes; + tx->hw_drops =3D bn->txq_prv_stats.hw_drops; + tx->hw_drop_errors =3D bn->txq_prv_stats.hw_drop_errors; +} + +static const struct netdev_stat_ops bnge_stat_ops =3D { + .get_queue_stats_rx =3D bnge_get_queue_stats_rx, + .get_queue_stats_tx =3D bnge_get_queue_stats_tx, + .get_base_stats =3D bnge_get_base_stats, +}; + static const struct net_device_ops bnge_netdev_ops =3D { .ndo_open =3D bnge_open, .ndo_stop =3D bnge_close, @@ -3112,6 +3337,7 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_ir= qs) bd->netdev =3D netdev; =20 netdev->netdev_ops =3D &bnge_netdev_ops; + netdev->stat_ops =3D &bnge_stat_ops; =20 bnge_set_ethtool_ops(netdev); =20 @@ -3211,6 +3437,7 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_ir= qs) rc =3D bnge_alloc_port_stats(bn); if (rc) goto err_free_workq; + spin_lock_init(&bn->stats_lock); =20 netdev->request_ops_lock =3D true; rc =3D register_netdev(netdev); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index a73f51b01bc2..f4636b5b0cf3 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "bnge_db.h" #include "bnge_hw_def.h" #include "bnge_link.h" @@ -264,6 +265,7 @@ struct bnge_stats_mem { =20 enum bnge_net_state { BNGE_STATE_NAPI_DISABLED, + BNGE_STATE_STATS_ENABLE, }; =20 #define BNGE_TIMER_INTERVAL HZ @@ -361,6 +363,11 @@ struct bnge_net { u16 fw_rx_stats_ext_size; u16 fw_tx_stats_ext_size; =20 + struct netdev_queue_stats_rx rxq_prv_stats; + struct netdev_queue_stats_tx txq_prv_stats; + struct rtnl_link_stats64 prv_stats64; + spinlock_t stats_lock; + u8 pri2cos_idx[8]; bool pri2cos_valid; }; --=20 2.47.3 From nobody Sun Apr 5 18:20:21 2026 Received: from mail-vk1-f225.google.com (mail-vk1-f225.google.com [209.85.221.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B625237C935 for ; Fri, 3 Apr 2026 07:38:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.225 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201939; cv=none; b=fZdUbRBP/BpPzTtvLEwvK9HuruF6cUxZ4RDVTDfLaiUeY7E5LWDMNE+oGhbkLfLG9JQGdOitWkp6oaZq3aFbEarFnaZiZ1DaRhY2rdNWwlKS3O2m2llahVSaOd6RETxKed35yIk3blDxv0aKxfCtQSxVRMxZ+atfjhUu34pslq8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775201939; c=relaxed/simple; bh=qk2jLxImllBMmDH5LNrKwwmLvzU9Lk+Bx2fnMPw+170=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TXXGG7BoEW+8mInmFCspedMzE0JnXJAdZWgIcUFPv3lKq6HqNHB1nFGWMNLlD18Y/I10ZSWBKn4YOItwT3esjbulPj2DVIfCD5d5usMml5WaY9IWVa0YOv17VBKX72yfDE4T7m9mJOqUkaX4mwEjUNtEXHhAiwsu/u3hMxpnZXo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=YjdMwBai; arc=none smtp.client-ip=209.85.221.225 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="YjdMwBai" Received: by mail-vk1-f225.google.com with SMTP id 71dfb90a1353d-56d958880ecso614946e0c.2 for ; Fri, 03 Apr 2026 00:38:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775201937; x=1775806737; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=SS9FUW95ER649tGSy8V3qlQPbp/q9DaqfpLM8Bg25nE=; b=g1oUwy9TEMXOyYxz8snPuaGdb9pFjV8+geMKSKqVG+HpceciJvMgm2YqTPw+WQkuDZ q6S5nI5HWKxmsfHPB2GJYLorZH3DZ1jD8nCB8OlKANX+ekG5maG8ulGkrFE32yPtT3p6 CT0JJjy6HgU7VsXgm5bKsQ6qD01PmZVE2X0PrmoiQd7ALq2sGNges+nMLfz/Kkj4e9wH 25SJt75M6msFLMwGUsmy/+AvbKMIizKmgbA8mCi3ukuLT6MHqcK0/C53DTTMOyLmRj0L 4ABtJhfcMJQ8n+Pj5/lLWkNhtz3FlKGJ2dj2tg+CfjJIVeAW1JsfNwo2/s5Zy+fIQwch kMnw== X-Forwarded-Encrypted: i=1; AJvYcCWIyYcGvDx9hM2IwYhgYg4SCDftmqcBJ+LgcXg4GTKK6Zn0EWlsK+wM5g4RqUmQadX05/x1+FYbOGrm8v0=@vger.kernel.org X-Gm-Message-State: AOJu0Yw86+eji1JKdWLnWahUhwcTj+eDS0mAunWf6kIeXFqcpLG0OJU/ PWAF0pFBlZ2U4l1gR5LmQU5hVGEl70cgP7DH3P/Vr8G3u8qP7DK1kBudmesOCtWwOFY+tifKV2N eHRw7/eKBRQJiJ4pmW3XtGcjSputjBt+wn6ZzD4vFzk9bS0hfglVIlmWvmXse/PAxSnUaYM4hz0 k2wCGWKgJflFuf4nhuTSOvbzkUAddbD8d5DgOtOyhhcV41HihVYIVurj81eAs+gPm7TOc9eoXrI GWvWTHhT24l3vDKBpr2y0lxiQ== X-Gm-Gg: AeBDievv4GlecZNV9nqUDkYQMCZJO9vlOAah/V2KMf2UYhSqCGGb7PwQ0YVURYVPkj9 LfV+h6BcmfIeIULiFNd8yl835QvDzJ3O1LxUqcTLtGD0vORarIzFs1n+4zkvcAfxDd+gVy8QXxb 5aqm8dZrzwp9lqYFhuXlCU9QZKrumvk39Jj9TEbG/s+4/gChBuPJDGLgAB7Cs5yK4i8tHex81zu gq0j/w2R/0Suu5+SBYudw6tRfnbG5Yh5pVm8+KBelO1i0IfEIOnEWLuwANtrtqHGdlQrQZ7av+n jzs3DErpMpDxj1lH2zFEMQNrg+iIaURt5jgGlxkiasj0KAItlmusuQSKf1ox3VSZXfmJNjmR0y7 0/EFiLoP+t7CoU3C9/3oayqHcCmVPukDxmW+xK/eZIZcKNWakmaCpezsAVI3yNSbtu6BLJ7Cx4+ mQcImX802EGRTEjhzCWm1LhyS/DaEuNlZxmaOtOjl+MHLy72OMyw9HEO/CGDgEdqk= X-Received: by 2002:a05:6122:4b05:b0:56d:3b69:87d2 with SMTP id 71dfb90a1353d-56dab9df26emr700050e0c.11.1775201936691; Fri, 03 Apr 2026 00:38:56 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-24.dlp.protect.broadcom.com. [144.49.247.24]) by smtp-relay.gmail.com with ESMTPS id 71dfb90a1353d-56d9bcbb3e4sm515781e0c.4.2026.04.03.00.38.56 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Apr 2026 00:38:56 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f70.google.com with SMTP id 98e67ed59e1d1-35842aa350fso3833403a91.0 for ; Fri, 03 Apr 2026 00:38:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1775201935; x=1775806735; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SS9FUW95ER649tGSy8V3qlQPbp/q9DaqfpLM8Bg25nE=; b=YjdMwBaiT/Gh5LOn/Yq+O1d0wfdrLxi/RFtIxLbFq/wWuXohMOk7cYyiXqv7W9PhIN AhQaoItF97klMY2JU0Z97y0dFm6ooB35N4YY1aBOqpQsNifODubQVZd7FQJG2iqtbqsb CsaklMdIDvJdP6+p9JlXYYzCnuf/L+ItPPICU= X-Forwarded-Encrypted: i=1; AJvYcCV6/c75Tg4aeU4BuI7I1xJF8fxA5Ca+8KUud31gDoS6U22/Lmu2sdArNjVGS7fYxWRINHl+Ni1ZhdcN31w=@vger.kernel.org X-Received: by 2002:a17:90b:3a4f:b0:35c:1c77:fac8 with SMTP id 98e67ed59e1d1-35de6957963mr1875329a91.30.1775201935347; Fri, 03 Apr 2026 00:38:55 -0700 (PDT) X-Received: by 2002:a17:90b:3a4f:b0:35c:1c77:fac8 with SMTP id 98e67ed59e1d1-35de6957963mr1875309a91.30.1775201934890; Fri, 03 Apr 2026 00:38:54 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe9377b7sm13124901a91.10.2026.04.03.00.38.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 00:38:54 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy Subject: [PATCH net-next v11 10/10] bng_en: add support for ethtool -S stats display Date: Fri, 3 Apr 2026 13:07:24 +0530 Message-ID: <20260403073724.194360-11-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> References: <20260403073724.194360-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Implement the legacy ethtool statistics interface (get_sset_count, get_strings, get_ethtool_stats) to expose hardware counters not available through standard kernel stats APIs. Ex: a) Per-queue ring stats rxq0_ucast_packets: 2 rxq0_mcast_packets: 0 rxq0_bcast_packets: 15 rxq0_ucast_bytes: 120 rxq0_mcast_bytes: 0 rxq0_bcast_bytes: 900 txq0_ucast_packets: 0 txq0_mcast_packets: 0 txq0_bcast_packets: 0 txq0_ucast_bytes: 0 txq0_mcast_bytes: 0 txq0_bcast_bytes: 0 b) Per-queue TPA(LRO/GRO) stats rxq4_tpa_eligible_pkt: 0 rxq4_tpa_eligible_bytes: 0 rxq4_tpa_pkt: 0 rxq4_tpa_bytes: 0 rxq4_tpa_errors: 0 rxq4_tpa_events: 0 c) Port level stats rxp_good_vlan_frames: 0 rxp_mtu_err_frames: 0 rxp_tagged_frames: 0 rxp_double_tagged_frames: 0 rxp_pfc_ena_frames_pri0: 0 rxp_pfc_ena_frames_pri1: 0 rxp_pfc_ena_frames_pri2: 0 rxp_pfc_ena_frames_pri3: 0 rxp_pfc_ena_frames_pri4: 0 rxp_pfc_ena_frames_pri5: 0 rxp_pfc_ena_frames_pri6: 0 rxp_pfc_ena_frames_pri7: 0 rxp_eee_lpi_events: 0 rxp_eee_lpi_duration: 0 rxp_runt_bytes: 0 rxp_runt_frames: 0 txp_good_vlan_frames: 0 txp_jabber_frames: 0 txp_fcs_err_frames: 0 txp_pfc_ena_frames_pri0: 0 txp_pfc_ena_frames_pri1: 0 txp_pfc_ena_frames_pri2: 0 txp_pfc_ena_frames_pri3: 0 txp_pfc_ena_frames_pri4: 0 txp_pfc_ena_frames_pri5: 0 txp_pfc_ena_frames_pri6: 0 txp_pfc_ena_frames_pri7: 0 txp_eee_lpi_events: 0 txp_eee_lpi_duration: 0 txp_xthol_frames: 0 d) Per-priority stats rx_bytes_pri0: 4182650 rx_bytes_pri1: 4182650 rx_bytes_pri2: 4182650 rx_bytes_pri3: 4182650 rx_bytes_pri4: 4182650 rx_bytes_pri5: 4182650 rx_bytes_pri6: 4182650 rx_bytes_pri7: 4182650 Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta --- .../net/ethernet/broadcom/bnge/bnge_ethtool.c | 481 ++++++++++++++++++ 1 file changed, 481 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c b/drivers/ne= t/ethernet/broadcom/bnge/bnge_ethtool.c index 87226d5bf15c..2467e44de291 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c @@ -35,6 +35,271 @@ static int bnge_nway_reset(struct net_device *dev) return rc; } =20 +static const char * const bnge_ring_q_stats_str[] =3D { + "ucast_packets", + "mcast_packets", + "bcast_packets", + "ucast_bytes", + "mcast_bytes", + "bcast_bytes", +}; + +static const char * const bnge_ring_tpa2_stats_str[] =3D { + "tpa_eligible_pkt", + "tpa_eligible_bytes", + "tpa_pkt", + "tpa_bytes", + "tpa_errors", + "tpa_events", +}; + +#define BNGE_RX_PORT_STATS_ENTRY(suffix) \ + { BNGE_RX_STATS_OFFSET(rx_##suffix), "rxp_" __stringify(suffix) } + +#define BNGE_TX_PORT_STATS_ENTRY(suffix) \ + { BNGE_TX_STATS_OFFSET(tx_##suffix), "txp_" __stringify(suffix) } + +#define BNGE_RX_STATS_EXT_ENTRY(counter) \ + { BNGE_RX_STATS_EXT_OFFSET(counter), __stringify(counter) } + +#define BNGE_TX_STATS_EXT_ENTRY(counter) \ + { BNGE_TX_STATS_EXT_OFFSET(counter), __stringify(counter) } + +#define BNGE_RX_STATS_EXT_PFC_ENTRY(n) \ + BNGE_RX_STATS_EXT_ENTRY(pfc_pri##n##_rx_duration_us), \ + BNGE_RX_STATS_EXT_ENTRY(pfc_pri##n##_rx_transitions) + +#define BNGE_TX_STATS_EXT_PFC_ENTRY(n) \ + BNGE_TX_STATS_EXT_ENTRY(pfc_pri##n##_tx_duration_us), \ + BNGE_TX_STATS_EXT_ENTRY(pfc_pri##n##_tx_transitions) + +#define BNGE_RX_STATS_EXT_PFC_ENTRIES \ + BNGE_RX_STATS_EXT_PFC_ENTRY(0), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(1), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(2), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(3), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(4), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(5), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(6), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(7) + +#define BNGE_TX_STATS_EXT_PFC_ENTRIES \ + BNGE_TX_STATS_EXT_PFC_ENTRY(0), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(1), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(2), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(3), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(4), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(5), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(6), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(7) + +#define BNGE_RX_STATS_EXT_COS_ENTRY(n) \ + BNGE_RX_STATS_EXT_ENTRY(rx_bytes_cos##n), \ + BNGE_RX_STATS_EXT_ENTRY(rx_packets_cos##n) + +#define BNGE_TX_STATS_EXT_COS_ENTRY(n) \ + BNGE_TX_STATS_EXT_ENTRY(tx_bytes_cos##n), \ + BNGE_TX_STATS_EXT_ENTRY(tx_packets_cos##n) + +#define BNGE_RX_STATS_EXT_COS_ENTRIES \ + BNGE_RX_STATS_EXT_COS_ENTRY(0), \ + BNGE_RX_STATS_EXT_COS_ENTRY(1), \ + BNGE_RX_STATS_EXT_COS_ENTRY(2), \ + BNGE_RX_STATS_EXT_COS_ENTRY(3), \ + BNGE_RX_STATS_EXT_COS_ENTRY(4), \ + BNGE_RX_STATS_EXT_COS_ENTRY(5), \ + BNGE_RX_STATS_EXT_COS_ENTRY(6), \ + BNGE_RX_STATS_EXT_COS_ENTRY(7) \ + +#define BNGE_TX_STATS_EXT_COS_ENTRIES \ + BNGE_TX_STATS_EXT_COS_ENTRY(0), \ + BNGE_TX_STATS_EXT_COS_ENTRY(1), \ + BNGE_TX_STATS_EXT_COS_ENTRY(2), \ + BNGE_TX_STATS_EXT_COS_ENTRY(3), \ + BNGE_TX_STATS_EXT_COS_ENTRY(4), \ + BNGE_TX_STATS_EXT_COS_ENTRY(5), \ + BNGE_TX_STATS_EXT_COS_ENTRY(6), \ + BNGE_TX_STATS_EXT_COS_ENTRY(7) \ + +#define BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(n) \ + BNGE_RX_STATS_EXT_ENTRY(rx_discard_bytes_cos##n), \ + BNGE_RX_STATS_EXT_ENTRY(rx_discard_packets_cos##n) + +#define BNGE_RX_STATS_EXT_DISCARD_COS_ENTRIES \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(0), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(1), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(2), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(3), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(4), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(5), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(6), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(7) + +#define BNGE_RX_STATS_PRI_ENTRY(counter, n) \ + { BNGE_RX_STATS_EXT_OFFSET(counter##_cos0), \ + __stringify(counter##_pri##n) } + +#define BNGE_TX_STATS_PRI_ENTRY(counter, n) \ + { BNGE_TX_STATS_EXT_OFFSET(counter##_cos0), \ + __stringify(counter##_pri##n) } + +#define BNGE_RX_STATS_PRI_ENTRIES(counter) \ + BNGE_RX_STATS_PRI_ENTRY(counter, 0), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 1), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 2), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 3), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 4), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 5), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 6), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 7) + +#define BNGE_TX_STATS_PRI_ENTRIES(counter) \ + BNGE_TX_STATS_PRI_ENTRY(counter, 0), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 1), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 2), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 3), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 4), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 5), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 6), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 7) + +#define NUM_RING_Q_HW_STATS ARRAY_SIZE(bnge_ring_q_stats_str) + +static const struct { + long offset; + char string[ETH_GSTRING_LEN]; +} bnge_tx_port_stats_ext_arr[] =3D { + BNGE_TX_STATS_EXT_COS_ENTRIES, + BNGE_TX_STATS_EXT_PFC_ENTRIES, +}; + +static const struct { + long base_off; + char string[ETH_GSTRING_LEN]; +} bnge_rx_bytes_pri_arr[] =3D { + BNGE_RX_STATS_PRI_ENTRIES(rx_bytes), +}; + +static const struct { + long base_off; + char string[ETH_GSTRING_LEN]; +} bnge_rx_pkts_pri_arr[] =3D { + BNGE_RX_STATS_PRI_ENTRIES(rx_packets), +}; + +static const struct { + long base_off; + char string[ETH_GSTRING_LEN]; +} bnge_tx_bytes_pri_arr[] =3D { + BNGE_TX_STATS_PRI_ENTRIES(tx_bytes), +}; + +static const struct { + long base_off; + char string[ETH_GSTRING_LEN]; +} bnge_tx_pkts_pri_arr[] =3D { + BNGE_TX_STATS_PRI_ENTRIES(tx_packets), +}; + +static const struct { + long offset; + char string[ETH_GSTRING_LEN]; +} bnge_port_stats_arr[] =3D { + BNGE_RX_PORT_STATS_ENTRY(good_vlan_frames), + BNGE_RX_PORT_STATS_ENTRY(mtu_err_frames), + BNGE_RX_PORT_STATS_ENTRY(tagged_frames), + BNGE_RX_PORT_STATS_ENTRY(double_tagged_frames), + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri0), + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri1), + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri2), + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri3), + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri4), + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri5), + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri6), + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri7), + BNGE_RX_PORT_STATS_ENTRY(eee_lpi_events), + BNGE_RX_PORT_STATS_ENTRY(eee_lpi_duration), + BNGE_RX_PORT_STATS_ENTRY(runt_bytes), + BNGE_RX_PORT_STATS_ENTRY(runt_frames), + + BNGE_TX_PORT_STATS_ENTRY(good_vlan_frames), + BNGE_TX_PORT_STATS_ENTRY(jabber_frames), + BNGE_TX_PORT_STATS_ENTRY(fcs_err_frames), + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri0), + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri1), + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri2), + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri3), + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri4), + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri5), + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri6), + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri7), + BNGE_TX_PORT_STATS_ENTRY(eee_lpi_events), + BNGE_TX_PORT_STATS_ENTRY(eee_lpi_duration), + BNGE_TX_PORT_STATS_ENTRY(xthol_frames), +}; + +static const struct { + long offset; + char string[ETH_GSTRING_LEN]; +} bnge_port_stats_ext_arr[] =3D { + BNGE_RX_STATS_EXT_ENTRY(continuous_pause_events), + BNGE_RX_STATS_EXT_ENTRY(resume_pause_events), + BNGE_RX_STATS_EXT_ENTRY(continuous_roce_pause_events), + BNGE_RX_STATS_EXT_ENTRY(resume_roce_pause_events), + BNGE_RX_STATS_EXT_COS_ENTRIES, + BNGE_RX_STATS_EXT_PFC_ENTRIES, + BNGE_RX_STATS_EXT_ENTRY(rx_bits), + BNGE_RX_STATS_EXT_ENTRY(rx_buffer_passed_threshold), + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRIES, + BNGE_RX_STATS_EXT_ENTRY(rx_filter_miss), +}; + +static int bnge_get_num_tpa_ring_stats(struct bnge_dev *bd) +{ + if (BNGE_SUPPORTS_TPA(bd)) + return BNGE_NUM_TPA_RING_STATS; + return 0; +} + +#define BNGE_NUM_PORT_STATS ARRAY_SIZE(bnge_port_stats_arr) +#define BNGE_NUM_STATS_PRI \ + (ARRAY_SIZE(bnge_rx_bytes_pri_arr) + \ + ARRAY_SIZE(bnge_rx_pkts_pri_arr) + \ + ARRAY_SIZE(bnge_tx_bytes_pri_arr) + \ + ARRAY_SIZE(bnge_tx_pkts_pri_arr)) + +static int bnge_get_num_ring_stats(struct bnge_dev *bd) +{ + int rx, tx; + + rx =3D NUM_RING_Q_HW_STATS + bnge_get_num_tpa_ring_stats(bd); + tx =3D NUM_RING_Q_HW_STATS; + return rx * bd->rx_nr_rings + + tx * bd->tx_nr_rings_per_tc; +} + +static u32 bnge_get_num_stats(struct bnge_net *bn) +{ + u32 num_stats =3D bnge_get_num_ring_stats(bn->bd); + u32 len; + + if (bn->flags & BNGE_FLAG_PORT_STATS) + num_stats +=3D BNGE_NUM_PORT_STATS; + + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + len =3D min_t(u32, bn->fw_rx_stats_ext_size, + ARRAY_SIZE(bnge_port_stats_ext_arr)); + num_stats +=3D len; + len =3D min_t(u32, bn->fw_tx_stats_ext_size, + ARRAY_SIZE(bnge_tx_port_stats_ext_arr)); + num_stats +=3D len; + if (bn->pri2cos_valid) + num_stats +=3D BNGE_NUM_STATS_PRI; + } + + return num_stats; +} + static void bnge_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -46,6 +311,219 @@ static void bnge_get_drvinfo(struct net_device *dev, strscpy(info->bus_info, pci_name(bd->pdev), sizeof(info->bus_info)); } =20 +static int bnge_get_sset_count(struct net_device *dev, int sset) +{ + struct bnge_net *bn =3D netdev_priv(dev); + + switch (sset) { + case ETH_SS_STATS: + return bnge_get_num_stats(bn); + default: + return -EOPNOTSUPP; + } +} + +static bool is_rx_ring(struct bnge_dev *bd, u16 ring_num) +{ + return ring_num < bd->rx_nr_rings; +} + +static bool is_tx_ring(struct bnge_dev *bd, u16 ring_num) +{ + u16 tx_base =3D 0; + + if (!(bd->flags & BNGE_EN_SHARED_CHNL)) + tx_base =3D bd->rx_nr_rings; + + return ring_num >=3D tx_base && ring_num < (tx_base + bd->tx_nr_rings_per= _tc); +} + +static void bnge_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *buf) +{ + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_dev *bd =3D bn->bd; + u32 tpa_stats; + u32 i, j =3D 0; + + if (!bn->bnapi) { + j +=3D bnge_get_num_ring_stats(bd); + goto skip_ring_stats; + } + + tpa_stats =3D bnge_get_num_tpa_ring_stats(bd); + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + struct bnge_nq_ring_info *nqr; + u64 *sw_stats; + int k; + + nqr =3D &bnapi->nq_ring; + sw_stats =3D nqr->stats.sw_stats; + + if (is_rx_ring(bd, i)) { + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, rx_ucast_pkts); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, rx_mcast_pkts); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, rx_bcast_pkts); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, rx_ucast_bytes); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, rx_mcast_bytes); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, rx_bcast_bytes); + } + if (is_tx_ring(bd, i)) { + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, tx_ucast_pkts); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, tx_mcast_pkts); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, tx_bcast_pkts); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, tx_ucast_bytes); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, tx_mcast_bytes); + buf[j++] =3D BNGE_GET_RING_STATS64(sw_stats, tx_bcast_bytes); + } + if (!tpa_stats || !is_rx_ring(bd, i)) + continue; + + k =3D BNGE_NUM_RX_RING_STATS + BNGE_NUM_TX_RING_STATS; + for (; k < BNGE_NUM_RX_RING_STATS + BNGE_NUM_TX_RING_STATS + + tpa_stats; j++, k++) + buf[j] =3D sw_stats[k]; + } + +skip_ring_stats: + if (bn->flags & BNGE_FLAG_PORT_STATS) { + u64 *port_stats =3D bn->port_stats.sw_stats; + + for (i =3D 0; i < BNGE_NUM_PORT_STATS; i++, j++) + buf[j] =3D *(port_stats + bnge_port_stats_arr[i].offset); + } + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + u64 *rx_port_stats_ext =3D bn->rx_port_stats_ext.sw_stats; + u64 *tx_port_stats_ext =3D bn->tx_port_stats_ext.sw_stats; + u32 len; + + len =3D min_t(u32, bn->fw_rx_stats_ext_size, + ARRAY_SIZE(bnge_port_stats_ext_arr)); + for (i =3D 0; i < len; i++, j++) { + buf[j] =3D *(rx_port_stats_ext + + bnge_port_stats_ext_arr[i].offset); + } + len =3D min_t(u32, bn->fw_tx_stats_ext_size, + ARRAY_SIZE(bnge_tx_port_stats_ext_arr)); + for (i =3D 0; i < len; i++, j++) { + buf[j] =3D *(tx_port_stats_ext + + bnge_tx_port_stats_ext_arr[i].offset); + } + if (bn->pri2cos_valid) { + for (i =3D 0; i < 8; i++, j++) { + long n =3D bnge_rx_bytes_pri_arr[i].base_off + + bn->pri2cos_idx[i]; + + buf[j] =3D *(rx_port_stats_ext + n); + } + for (i =3D 0; i < 8; i++, j++) { + long n =3D bnge_rx_pkts_pri_arr[i].base_off + + bn->pri2cos_idx[i]; + + buf[j] =3D *(rx_port_stats_ext + n); + } + for (i =3D 0; i < 8; i++, j++) { + long n =3D bnge_tx_bytes_pri_arr[i].base_off + + bn->pri2cos_idx[i]; + + buf[j] =3D *(tx_port_stats_ext + n); + } + for (i =3D 0; i < 8; i++, j++) { + long n =3D bnge_tx_pkts_pri_arr[i].base_off + + bn->pri2cos_idx[i]; + + buf[j] =3D *(tx_port_stats_ext + n); + } + } + } +} + +static void bnge_get_strings(struct net_device *dev, u32 stringset, u8 *bu= f) +{ + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_dev *bd =3D bn->bd; + u32 i, j, num_str; + const char *str; + + switch (stringset) { + case ETH_SS_STATS: + for (i =3D 0; i < bd->nq_nr_rings; i++) { + if (is_rx_ring(bd, i)) + for (j =3D 0; j < NUM_RING_Q_HW_STATS; j++) { + str =3D bnge_ring_q_stats_str[j]; + ethtool_sprintf(&buf, "rxq%d_%s", i, + str); + } + if (is_tx_ring(bd, i)) + for (j =3D 0; j < NUM_RING_Q_HW_STATS; j++) { + str =3D bnge_ring_q_stats_str[j]; + ethtool_sprintf(&buf, "txq%d_%s", i, + str); + } + num_str =3D bnge_get_num_tpa_ring_stats(bd); + if (!num_str || !is_rx_ring(bd, i)) + continue; + + for (j =3D 0; j < num_str; j++) { + str =3D bnge_ring_tpa2_stats_str[j]; + ethtool_sprintf(&buf, "rxq%d_%s", i, str); + } + } + + if (bn->flags & BNGE_FLAG_PORT_STATS) + for (i =3D 0; i < BNGE_NUM_PORT_STATS; i++) { + str =3D bnge_port_stats_arr[i].string; + ethtool_puts(&buf, str); + } + + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + u32 len; + + len =3D min_t(u32, bn->fw_rx_stats_ext_size, + ARRAY_SIZE(bnge_port_stats_ext_arr)); + for (i =3D 0; i < len; i++) { + str =3D bnge_port_stats_ext_arr[i].string; + ethtool_puts(&buf, str); + } + + len =3D min_t(u32, bn->fw_tx_stats_ext_size, + ARRAY_SIZE(bnge_tx_port_stats_ext_arr)); + for (i =3D 0; i < len; i++) { + str =3D bnge_tx_port_stats_ext_arr[i].string; + ethtool_puts(&buf, str); + } + + if (bn->pri2cos_valid) { + for (i =3D 0; i < 8; i++) { + str =3D bnge_rx_bytes_pri_arr[i].string; + ethtool_puts(&buf, str); + } + + for (i =3D 0; i < 8; i++) { + str =3D bnge_rx_pkts_pri_arr[i].string; + ethtool_puts(&buf, str); + } + + for (i =3D 0; i < 8; i++) { + str =3D bnge_tx_bytes_pri_arr[i].string; + ethtool_puts(&buf, str); + } + + for (i =3D 0; i < 8; i++) { + str =3D bnge_tx_pkts_pri_arr[i].string; + ethtool_puts(&buf, str); + } + } + } + break; + default: + netdev_err(bd->netdev, "%s invalid request %x\n", + __func__, stringset); + break; + } +} + static void bnge_get_eth_phy_stats(struct net_device *dev, struct ethtool_eth_phy_stats *phy_stats) { @@ -271,6 +749,9 @@ static const struct ethtool_ops bnge_ethtool_ops =3D { .nway_reset =3D bnge_nway_reset, .get_pauseparam =3D bnge_get_pauseparam, .set_pauseparam =3D bnge_set_pauseparam, + .get_sset_count =3D bnge_get_sset_count, + .get_strings =3D bnge_get_strings, + .get_ethtool_stats =3D bnge_get_ethtool_stats, .get_eth_phy_stats =3D bnge_get_eth_phy_stats, .get_eth_mac_stats =3D bnge_get_eth_mac_stats, .get_eth_ctrl_stats =3D bnge_get_eth_ctrl_stats, --=20 2.47.3