From nobody Sat Feb 7 09:29:51 2026 Received: from mail-oa1-f97.google.com (mail-oa1-f97.google.com [209.85.160.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 8169B1D7995 for ; Fri, 23 Jan 2026 19:35:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.97 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196925; cv=none; b=fbx4t3QfCvqYrwlRRmM+31ySxHtQRKK7OrPrFKCrtr2xecYrQ9iFkSDaYQh4an+zgyAnkOqajcAcOyWVoItnlYBNhNgF7fpjEgVhMJIWqjtz8EcP9wjriEhoOE6JN7oGdyUVmIA17C2RWsuDSKfqQjJVfH6YhNRzpyYvIPYJNCM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196925; c=relaxed/simple; bh=G42HEdK63RMSkNcCPQGCk4X08ncSFrRURRT8K21yxRE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=vDNc8l7Dy2goXH9JjgET2x1Ut3U7vT7ZHVLtRAgP90lMyfcDGeN4VvVONmv7IIvRjuOfezETPWFmlQyEJZ4zKa+ULQOgXtMbV/b6dPr/TnyXVSVs6mSXYqdD0/l+LWMCdX8SUNgH2PRdGWZ50lfbMEI4d4GhChO7tIc9Uvi7HAU= 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=AML2SMEQ; arc=none smtp.client-ip=209.85.160.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="AML2SMEQ" Received: by mail-oa1-f97.google.com with SMTP id 586e51a60fabf-404254ffe8aso1678093fac.0 for ; Fri, 23 Jan 2026 11:35:23 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769196922; x=1769801722; 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=P5v6be/rvU1Ddm94jt+LcDTFwMP9w1kpc8KK4AcGhZ4=; b=Ti9EjbiajmOj3LhuUSNys2u8KNT35hNcCt6ko/qc+iesyZMb0LJ5T7zDls1bpt4q/X aO+xLXIQBuf3C+SAdV9NKpYytZc2tCBL6uFm0YJUL/o3Gy3PFDfaQtcqhtjP/VaatHrS nj8QIi505BCS4wo5FPEDVZlXCPBChO8QAbrTH1PBW1iPNPrvoAW4rtb+oFDOCrouxyG3 v5Q1j3vWBL4m6pSl/BUixxnF7tY1ffiYten2quNu9Gd58OSbNJNF0nP4PTH1Bs2DhDil gDbrz7xXgU+hQjIP1MVe1QKjrkAG3QhDsAkP/WXb92F3BuSsXwZW1MnYx6c19ozeLh6S UFZg== X-Forwarded-Encrypted: i=1; AJvYcCWwik78XEmHMNR1/9zW3AR31WOJuVDbgCl8AB4WFO3gRzrs0Ta19oNj8U0PxjN8rc2GgZUIYHRE42m06LU=@vger.kernel.org X-Gm-Message-State: AOJu0YyISeon4O288UbS6IVklxBi7O0kh5FX6TYLWlZEcVX5qIen0xCa qC5j3iOQ1hiE+wKMEvRQX5wqxRyQjN9UKn8SyO6tcC2ND+KXfpxWr4dyBMqnJe7Jg/fPPj5uckj SIcdZiBh+E2me1cB92XzOH4SfPUd/aZr3uasB5JZplnil3MNRvTuFL6psEJI99IUB2RFhKJdfQZ 0AJJkfIZSDVjLXcWSseP0cwKcswponKv4jh6a4iEv75FI7lPZRAoIaQBrxHipRvsXMI+Ya8KyZw Rw5iXas58x2k3J0zj7l9Gm96Q== X-Gm-Gg: AZuq6aKFRTllxROzsF85Fq0rkkMfhuGlhMYlyGPFeIUNZGNE53HXY2oK07lNYwSpovY cN5rBmR82IdwO0iMqBIIeFtPVuWHFjdsGSo8e96nL4PKZgJnKiJBN1QGQrkGbdIus3rvYuABlEZ JojD9+H9Xyi/U1rAKmNHP7oh9/JZRCd+jZkCl5bptN4I8kjTaJIF0EQw9BD6KQSi3NeXFEqThRG XP8aPGcQcXJmOBApltANg1O2egNwvsVEijrbSQIQ5lqv3pPdTM88NQ0yC46leaObtAXJTSaDeGD LT0opqpVEeAJ7jW/Xv9bmTnVToEmSoqH+qT35+RJacs9jM49U643PUdUsxsHK1Ad1YLhL/wgYAB suAsqHr/sGPiN2vlnsfiyJ+2qrXQan4ytjzHzaJWYudpOTeWGrq0bwjSAF5EGsOlsbocZsU0AU7 vOsCZTq9vvpUg3d0clblZ3QnNaJAz+TPwnazZ8iAnbWAI06G16K6mI2w== X-Received: by 2002:a05:6870:2383:b0:3e0:bd2c:f459 with SMTP id 586e51a60fabf-408ac19fb08mr2157012fac.12.1769196922178; Fri, 23 Jan 2026 11:35:22 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-100.dlp.protect.broadcom.com. [144.49.247.100]) by smtp-relay.gmail.com with ESMTPS id 586e51a60fabf-408afba0f93sm304305fac.9.2026.01.23.11.35.21 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Jan 2026 11:35:22 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pf1-f200.google.com with SMTP id d2e1a72fcca58-7fc82eff4adso2126654b3a.1 for ; Fri, 23 Jan 2026 11:35:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1769196921; x=1769801721; 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=P5v6be/rvU1Ddm94jt+LcDTFwMP9w1kpc8KK4AcGhZ4=; b=AML2SMEQiPnbbZz01QQX91jWy+BJISpKoQzm1CevWZ3AHQLiC3eDex/yvTtc3bAWED txOB8IEjjRlfkpPm4kWUUzOSpJK/ZzuFFOAyG99DxsGWPQbW8oggK8OOEx+Sklx0lF+R edx6Rc0DCqMz/yh1qGmBkc7ILkRWJe2VSFcnQ= X-Forwarded-Encrypted: i=1; AJvYcCXfjEuPBnQr/Aqt+auNHThVse2RLop9UU7D/XPYTmPqPBPl8wyRo2fqvZTDD3udpmZSODAIfszSb/OLIJ4=@vger.kernel.org X-Received: by 2002:a05:6a00:894:b0:81f:5acb:55fc with SMTP id d2e1a72fcca58-82317a492f7mr3396665b3a.10.1769196920700; Fri, 23 Jan 2026 11:35:20 -0800 (PST) X-Received: by 2002:a05:6a00:894:b0:81f:5acb:55fc with SMTP id d2e1a72fcca58-82317a492f7mr3396644b3a.10.1769196920158; Fri, 23 Jan 2026 11:35:20 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8231873e519sm2843206b3a.49.2026.01.23.11.35.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Jan 2026 11:35:19 -0800 (PST) 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, ajit.khaparde@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v6, net-next 1/8] bng_en: Extend bnge_set_ring_params() for rx-copybreak Date: Sat, 24 Jan 2026 01:04:57 +0530 Message-ID: <20260123193504.285573-2-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260123193504.285573-1-bhargava.marreddy@broadcom.com> References: <20260123193504.285573-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 rx-copybreak support in bnge_set_ring_params() Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 19 +++++++++++++++++-- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 5 +++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 832eeb960bd2..8bd019ea55a2 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include =20 @@ -2295,7 +2296,6 @@ void bnge_set_ring_params(struct bnge_dev *bd) rx_space =3D rx_size + ALIGN(NET_SKB_PAD, 8) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); =20 - bn->rx_copy_thresh =3D BNGE_RX_COPY_THRESH; ring_size =3D bn->rx_ring_size; bn->rx_agg_ring_size =3D 0; bn->rx_agg_nr_pages =3D 0; @@ -2334,7 +2334,10 @@ void bnge_set_ring_params(struct bnge_dev *bd) bn->rx_agg_ring_size =3D agg_ring_size; bn->rx_agg_ring_mask =3D (bn->rx_agg_nr_pages * RX_DESC_CNT) - 1; =20 - rx_size =3D SKB_DATA_ALIGN(BNGE_RX_COPY_THRESH + NET_IP_ALIGN); + rx_size =3D max3(BNGE_DEFAULT_RX_COPYBREAK, + bn->rx_copybreak, + bn->netdev->cfg_pending->hds_thresh); + rx_size =3D SKB_DATA_ALIGN(rx_size + NET_IP_ALIGN); rx_space =3D rx_size + NET_SKB_PAD + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); } @@ -2367,6 +2370,17 @@ void bnge_set_ring_params(struct bnge_dev *bd) bn->cp_ring_mask =3D bn->cp_bit - 1; } =20 +static void bnge_init_ring_params(struct bnge_net *bn) +{ + u32 rx_size; + + bn->rx_copybreak =3D BNGE_DEFAULT_RX_COPYBREAK; + /* Try to fit 4 chunks into a 4k page */ + rx_size =3D SZ_1K - + NET_SKB_PAD - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + bn->netdev->cfg->hds_thresh =3D max(BNGE_DEFAULT_RX_COPYBREAK, rx_size); +} + int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs) { struct net_device *netdev; @@ -2456,6 +2470,7 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_ir= qs) bn->rx_dir =3D DMA_FROM_DEVICE; =20 bnge_set_tpa_flags(bd); + bnge_init_ring_params(bn); bnge_set_ring_params(bd); =20 bnge_init_l2_fltr_tbl(bn); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index fb3b961536ba..557cca472db6 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -135,7 +135,8 @@ struct bnge_ring_grp_info { u16 nq_fw_ring_id; }; =20 -#define BNGE_RX_COPY_THRESH 256 +#define BNGE_DEFAULT_RX_COPYBREAK 256 +#define BNGE_MAX_RX_COPYBREAK 1024 =20 #define BNGE_HW_FEATURE_VLAN_ALL_RX \ (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX) @@ -186,7 +187,7 @@ struct bnge_net { u32 rx_buf_size; u32 rx_buf_use_size; /* usable size */ u32 rx_agg_ring_size; - u32 rx_copy_thresh; + u32 rx_copybreak; u32 rx_ring_mask; u32 rx_agg_ring_mask; u16 rx_nr_pages; --=20 2.47.3 From nobody Sat Feb 7 09:29:51 2026 Received: from mail-pl1-f227.google.com (mail-pl1-f227.google.com [209.85.214.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 B5B551D7995 for ; Fri, 23 Jan 2026 19:35:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196931; cv=none; b=XM+skzHeltv4f9i5x82NRA3LkrivMCSpJsS5Q+xy0sfwpgoco0OIqPGKTwDzBHM/SK4ahZvOx+mmPemCxmYuG6bArIouzgaeR2ZTYJ+5ly3lDvcCbptweDE0o6kNCuF57S9UYjFxaGnI+CKep1KTPdnevz4yKlbwcxZ0yjeiBLE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196931; c=relaxed/simple; bh=6w3ufLyc3MHPh7Hs0E4UjpwXUwbQxqS0rYRHHm4x5vA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Qx8Gcy7h/lJWkUQb+yEUpfprAOeDPZR1TviMgob3Y1p/UTVqD/pgl6LDq8PT4UBpGzsAVamsJPh3czvBk3u496AAFbNxwmas0KNNzfy34+SV7OYqqm1DZ79oDVD6OIfxVVdmG+nezPROCWn2i8ZQhfD0AFFfJH5nhspYCK+CTuA= 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=PxBYsEDA; arc=none smtp.client-ip=209.85.214.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="PxBYsEDA" Received: by mail-pl1-f227.google.com with SMTP id d9443c01a7336-2a0a95200e8so17322895ad.0 for ; Fri, 23 Jan 2026 11:35:28 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769196928; x=1769801728; 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=IvBgO6SSoqtvVZ+LGyPQVFZ2Q6W6Y7yDtebRO64mVY4=; b=EF3COPK/jclY2Utki9+dPibQ7/vKHe7e73Rd5KF8ysAu2JB84sBf1Ac3itq+mp5NAb t2pIyrUFUpjnWsZ60Svrt5m6eGPkD4vWfH3jk+GPIuUDmvmHZ7b61ezzczmIkTpZOWvB mGAUUo87Bo+zZaB+3xOVwKty/VDBBlMQyRkJKko2b5nAAtgGfZYA//hWEcPIRt+F8vaX v3Wv9y+K1fH5bE8nECSqZD+XNNFBJF0QRnfbMYiqPGIGvl7+b7thPtzvZhsD3SiraOes CDbICyW+Zh4DNqJNcz40lp+aHDWHK0qFqUvnJRkIYvzQ3kbLsnutMUR9TvuBD136WKPR AvAw== X-Forwarded-Encrypted: i=1; AJvYcCVkZWDoJk45TBAI1ZTKJGedOO0uF41S/1/u4drEh9l+prlPxAWF+HlTb38TLionfkwNwfFiWKluHcHQHrE=@vger.kernel.org X-Gm-Message-State: AOJu0YwGj8OIVC3+vNZPo7lWD7WJVxD+aGQar3RcTo3M7n27miIvn6JG 0zuuAN3tanf9nGHaACqrzRfQwLtDa6mZSdpySYxqV9vOPfN8fikNoSP50i8i6tleLreZZfJBl0B tT8Ng+7gOGmr78adranFQtYDsX8o29/RRouxqYmDnW+7e0na3ERzBNOlH1du0pqoSbTHg8A9ev+ H/YvAK20koct643Lt4h+lT7ad7FO4Jw6xnw8ReUFkm7yKGxk3Ey3aUxUkWbt0NFs8RzzxRpsoPc n2XsGVtxo1pYQwW11d0JTQaOw== X-Gm-Gg: AZuq6aIWumoT90Sus5PuKtyRRsXrkXe92ktaDzCy0lSNqLeqEYhCslX7OnZ5udonW3G iNrjyveTFB10CQrHxtrkUkQgPBdExJ+VmuqeOt9RdYPCRJPafUIycf2pE+zBe9TJ0mnJr8mzqx0 JPcJaCaqXVkG6LwxEA6X/6EEQz5aI4LNxsgQYFfNJfIqHAK0rHblBHGDcAcewjupcPypCnB5Eh3 TstbVWMkcOtAXXmGveFZitNlgkSTuc5IiLvuhFQ8y7pk0K+5agAnq2uM5H1+z5OmjEVXzEa3hq8 ZaBgEYWZLz59hRcdhlEkpncxGhgHYa/Odon7fM624eg6MwCzLWi7QOZ3t9ke6DEsCpiz0+23GCA mK1rnJ0jb2aadNSpoMBVDuuRTrErUJrajYYDh0yWgr9UQJhysMb/OKNQKfkFL54AJddHIoqvjSh u0gGU0wL8tGvVnfAzgC+/EtAtiD3LNccuGVkwS/idE08OIPdUHXys= X-Received: by 2002:a17:90b:5443:b0:34a:b8fc:f1d1 with SMTP id 98e67ed59e1d1-35368857c91mr3173309a91.24.1769196928036; Fri, 23 Jan 2026 11:35:28 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-77.dlp.protect.broadcom.com. [144.49.247.77]) by smtp-relay.gmail.com with ESMTPS id 98e67ed59e1d1-3533520210esm821219a91.1.2026.01.23.11.35.27 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Jan 2026 11:35:28 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pg1-f200.google.com with SMTP id 41be03b00d2f7-c613929d317so1412973a12.2 for ; Fri, 23 Jan 2026 11:35:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1769196926; x=1769801726; 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=IvBgO6SSoqtvVZ+LGyPQVFZ2Q6W6Y7yDtebRO64mVY4=; b=PxBYsEDARcmMSUW5Yu3GoZcT5icTXdmpSEwZ5r08KnBNJ29kFeP+nnj1nlUEbsodd/ CueMA4BVb8yNP+ditzMvMOwFnlHvFcNryzEpNo44BLsiyQlQAJT8yPmfAagc5OtZKRZV zeMd0OP2BNDBaBtrnTtDTfEtMH1mtt7r+gL+4= X-Forwarded-Encrypted: i=1; AJvYcCVatfT1R5Dd9ObV3GroKJd91oOrgfyZ1pMxMbFy/2eyRwYUAcb1QhhfD1KYpePgrqtbQKomCFBd1ngxJoA=@vger.kernel.org X-Received: by 2002:a17:90b:5346:b0:340:c060:4d44 with SMTP id 98e67ed59e1d1-35367029868mr3441725a91.14.1769196925473; Fri, 23 Jan 2026 11:35:25 -0800 (PST) X-Received: by 2002:a17:90b:5346:b0:340:c060:4d44 with SMTP id 98e67ed59e1d1-35367029868mr3441701a91.14.1769196924746; Fri, 23 Jan 2026 11:35:24 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8231873e519sm2843206b3a.49.2026.01.23.11.35.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Jan 2026 11:35:24 -0800 (PST) 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, ajit.khaparde@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula , Rahul Gupta Subject: [v6, net-next 2/8] bng_en: Add RX support Date: Sat, 24 Jan 2026 01:04:58 +0530 Message-ID: <20260123193504.285573-3-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260123193504.285573-1-bhargava.marreddy@broadcom.com> References: <20260123193504.285573-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 support to receive packet using NAPI, build and deliver the skb to stack. With help of meta data available in completions, fill the appropriate information in skb. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula Reviewed-by: Ajit Kumar Khaparde Reviewed-by: Rahul Gupta --- drivers/net/ethernet/broadcom/bnge/Makefile | 3 +- .../net/ethernet/broadcom/bnge/bnge_hw_def.h | 195 ++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.c | 117 +++- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 60 +- .../net/ethernet/broadcom/bnge/bnge_txrx.c | 562 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_txrx.h | 88 +++ 6 files changed, 1004 insertions(+), 21 deletions(-) create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_txrx.c create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_txrx.h diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethe= rnet/broadcom/bnge/Makefile index ea6596854e5c..fa604ee20264 100644 --- a/drivers/net/ethernet/broadcom/bnge/Makefile +++ b/drivers/net/ethernet/broadcom/bnge/Makefile @@ -10,4 +10,5 @@ bng_en-y :=3D bnge_core.o \ bnge_resc.o \ bnge_netdev.o \ bnge_ethtool.o \ - bnge_auxr.o + bnge_auxr.o \ + bnge_txrx.o diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h b/drivers/net= /ethernet/broadcom/bnge/bnge_hw_def.h new file mode 100644 index 000000000000..0e28352f41f2 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2025 Broadcom */ + +#ifndef _BNGE_HW_DEF_H_ +#define _BNGE_HW_DEF_H_ + +#define TX_BD_FLAGS_TCP_UDP_CHKSUM BIT(0) +#define TX_BD_FLAGS_IP_CKSUM BIT(1) +#define TX_BD_FLAGS_NO_CRC BIT(2) +#define TX_BD_FLAGS_STAMP BIT(3) +#define TX_BD_FLAGS_T_IP_CHKSUM BIT(4) +#define TX_BD_FLAGS_LSO BIT(5) +#define TX_BD_FLAGS_IPID_FMT BIT(6) +#define TX_BD_FLAGS_T_IPID BIT(7) +#define TX_BD_HSIZE GENMASK(23, 16) +#define TX_BD_HSIZE_SHIFT 16 + +#define TX_BD_CFA_ACTION GENMASK(31, 16) +#define TX_BD_CFA_ACTION_SHIFT 16 + +#define TX_BD_CFA_META_MASK 0xfffffff +#define TX_BD_CFA_META_VID_MASK 0xfff +#define TX_BD_CFA_META_PRI_MASK GENMASK(15, 12) +#define TX_BD_CFA_META_PRI_SHIFT 12 +#define TX_BD_CFA_META_TPID_MASK GENMASK(17, 16) +#define TX_BD_CFA_META_TPID_SHIFT 16 +#define TX_BD_CFA_META_KEY GENMASK(31, 28) +#define TX_BD_CFA_META_KEY_SHIFT 28 +#define TX_BD_CFA_META_KEY_VLAN BIT(28) + +struct tx_bd_ext { + __le32 tx_bd_hsize_lflags; + __le32 tx_bd_mss; + __le32 tx_bd_cfa_action; + __le32 tx_bd_cfa_meta; +}; + +#define TX_CMP_SQ_CONS_IDX(txcmp) \ + (le32_to_cpu((txcmp)->sq_cons_idx) & TX_CMP_SQ_CONS_IDX_MASK) + +#define RX_CMP_CMP_TYPE GENMASK(5, 0) +#define RX_CMP_FLAGS_ERROR BIT(6) +#define RX_CMP_FLAGS_PLACEMENT GENMASK(9, 7) +#define RX_CMP_FLAGS_RSS_VALID BIT(10) +#define RX_CMP_FLAGS_PKT_METADATA_PRESENT BIT(11) +#define RX_CMP_FLAGS_ITYPES_SHIFT 12 +#define RX_CMP_FLAGS_ITYPES_MASK 0xf000 +#define RX_CMP_FLAGS_ITYPE_UNKNOWN (0 << 12) +#define RX_CMP_FLAGS_ITYPE_IP (1 << 12) +#define RX_CMP_FLAGS_ITYPE_TCP (2 << 12) +#define RX_CMP_FLAGS_ITYPE_UDP (3 << 12) +#define RX_CMP_FLAGS_ITYPE_FCOE (4 << 12) +#define RX_CMP_FLAGS_ITYPE_ROCE (5 << 12) +#define RX_CMP_FLAGS_ITYPE_PTP_WO_TS (8 << 12) +#define RX_CMP_FLAGS_ITYPE_PTP_W_TS (9 << 12) +#define RX_CMP_LEN GENMASK(31, 16) +#define RX_CMP_LEN_SHIFT 16 + +#define RX_CMP_V1 BIT(0) +#define RX_CMP_AGG_BUFS GENMASK(5, 1) +#define RX_CMP_AGG_BUFS_SHIFT 1 +#define RX_CMP_RSS_HASH_TYPE GENMASK(15, 9) +#define RX_CMP_RSS_HASH_TYPE_SHIFT 9 +#define RX_CMP_V3_RSS_EXT_OP_LEGACY GENMASK(15, 12) +#define RX_CMP_V3_RSS_EXT_OP_LEGACY_SHIFT 12 +#define RX_CMP_V3_RSS_EXT_OP_NEW GENMASK(11, 8) +#define RX_CMP_V3_RSS_EXT_OP_NEW_SHIFT 8 +#define RX_CMP_PAYLOAD_OFFSET GENMASK(23, 16) +#define RX_CMP_PAYLOAD_OFFSET_SHIFT 16 +#define RX_CMP_SUB_NS_TS GENMASK(19, 16) +#define RX_CMP_SUB_NS_TS_SHIFT 16 +#define RX_CMP_METADATA1 GENMASK(31, 28) +#define RX_CMP_METADATA1_SHIFT 28 +#define RX_CMP_METADATA1_TPID_SEL GENMASK(30, 28) +#define RX_CMP_METADATA1_TPID_8021Q BIT(28) +#define RX_CMP_METADATA1_TPID_8021AD (0x0 << 28) +#define RX_CMP_METADATA1_VALID BIT(31) + +struct rx_cmp { + __le32 rx_cmp_len_flags_type; + u32 rx_cmp_opaque; + __le32 rx_cmp_misc_v1; + __le32 rx_cmp_rss_hash; +}; + +#define RX_CMP_FLAGS2_IP_CS_CALC BIT(0) +#define RX_CMP_FLAGS2_L4_CS_CALC BIT(1) +#define RX_CMP_FLAGS2_T_IP_CS_CALC BIT(2) +#define RX_CMP_FLAGS2_T_L4_CS_CALC BIT(3) +#define RX_CMP_FLAGS2_META_FORMAT_VLAN BIT(4) + +#define RX_CMP_FLAGS2_METADATA_TCI_MASK GENMASK(15, 0) +#define RX_CMP_FLAGS2_METADATA_VID_MASK GENMASK(11, 0) +#define RX_CMP_FLAGS2_METADATA_TPID_MASK GENMASK(31, 16) +#define RX_CMP_FLAGS2_METADATA_TPID_SFT 16 + +#define RX_CMP_V BIT(0) +#define RX_CMPL_ERRORS_MASK GENMASK(15, 1) +#define RX_CMPL_ERRORS_SFT 1 +#define RX_CMPL_ERRORS_BUFFER_ERROR_MASK GENMASK(3, 1) +#define RX_CMPL_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) +#define RX_CMPL_ERRORS_BUFFER_ERROR_DID_NOT_FIT (0x1 << 1) +#define RX_CMPL_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (0x2 << 1) +#define RX_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) +#define RX_CMPL_ERRORS_IP_CS_ERROR BIT(4) +#define RX_CMPL_ERRORS_L4_CS_ERROR BIT(5) +#define RX_CMPL_ERRORS_T_IP_CS_ERROR BIT(6) +#define RX_CMPL_ERRORS_T_L4_CS_ERROR BIT(7) +#define RX_CMPL_ERRORS_CRC_ERROR BIT(8) +#define RX_CMPL_ERRORS_T_PKT_ERROR_MASK GENMASK(11, 9) +#define RX_CMPL_ERRORS_T_PKT_ERROR_NO_ERROR (0x0 << 9) +#define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_VERSION (0x1 << 9) +#define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_HDR_LEN (0x2 << 9) +#define RX_CMPL_ERRORS_T_PKT_ERROR_TUNNEL_TOTAL_ERROR (0x3 << 9) +#define RX_CMPL_ERRORS_T_PKT_ERROR_T_IP_TOTAL_ERROR (0x4 << 9) +#define RX_CMPL_ERRORS_T_PKT_ERROR_T_UDP_TOTAL_ERROR (0x5 << 9) +#define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL (0x6 << 9) +#define RX_CMPL_ERRORS_PKT_ERROR_MASK GENMASK(15, 12) +#define RX_CMPL_ERRORS_PKT_ERROR_NO_ERROR (0x0 << 12) +#define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_VERSION (0x1 << 12) +#define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_HDR_LEN (0x2 << 12) +#define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_TTL (0x3 << 12) +#define RX_CMPL_ERRORS_PKT_ERROR_IP_TOTAL_ERROR (0x4 << 12) +#define RX_CMPL_ERRORS_PKT_ERROR_UDP_TOTAL_ERROR (0x5 << 12) +#define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN (0x6 << 12) +#define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN_TOO_SMALL (0x7 << 12) +#define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN (0x8 << 12) + +#define RX_CMPL_CFA_CODE_MASK GENMASK(31, 16) +#define RX_CMPL_CFA_CODE_SFT 16 +#define RX_CMPL_METADATA0_TCI_MASK GENMASK(31, 16) +#define RX_CMPL_METADATA0_VID_MASK GENMASK(27, 16) +#define RX_CMPL_METADATA0_SFT 16 + +struct rx_cmp_ext { + __le32 rx_cmp_flags2; + __le32 rx_cmp_meta_data; + __le32 rx_cmp_cfa_code_errors_v2; + __le32 rx_cmp_timestamp; +}; + +#define RX_CMP_L2_ERRORS \ + cpu_to_le32(RX_CMPL_ERRORS_BUFFER_ERROR_MASK | RX_CMPL_ERRORS_CRC_ERROR) + +#define RX_CMP_L4_CS_BITS \ + (cpu_to_le32(RX_CMP_FLAGS2_L4_CS_CALC | RX_CMP_FLAGS2_T_L4_CS_CALC)) + +#define RX_CMP_L4_CS_ERR_BITS \ + (cpu_to_le32(RX_CMPL_ERRORS_L4_CS_ERROR | RX_CMPL_ERRORS_T_L4_CS_ERROR)) + +#define RX_CMP_L4_CS_OK(rxcmp1) \ + (((rxcmp1)->rx_cmp_flags2 & RX_CMP_L4_CS_BITS) && \ + !((rxcmp1)->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS)) + +#define RX_CMP_METADATA0_TCI(rxcmp1) \ + ((le32_to_cpu((rxcmp1)->rx_cmp_cfa_code_errors_v2) & \ + RX_CMPL_METADATA0_TCI_MASK) >> RX_CMPL_METADATA0_SFT) + +#define RX_CMP_ENCAP(rxcmp1) \ + ((le32_to_cpu((rxcmp1)->rx_cmp_flags2) & \ + RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3) + +#define RX_CMP_V3_HASH_TYPE_LEGACY(rxcmp) \ + ((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & \ + RX_CMP_V3_RSS_EXT_OP_LEGACY) >> RX_CMP_V3_RSS_EXT_OP_LEGACY_SHIFT) + +#define RX_CMP_V3_HASH_TYPE_NEW(rxcmp) \ + ((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_V3_RSS_EXT_OP_NEW) >>\ + RX_CMP_V3_RSS_EXT_OP_NEW_SHIFT) + +#define RX_CMP_V3_HASH_TYPE(bd, rxcmp) \ + (((bd)->rss_cap & BNGE_RSS_CAP_RSS_TCAM) ? \ + RX_CMP_V3_HASH_TYPE_NEW(rxcmp) : \ + RX_CMP_V3_HASH_TYPE_LEGACY(rxcmp)) + +#define EXT_OP_INNER_4 0x0 +#define EXT_OP_OUTER_4 0x2 +#define EXT_OP_INNFL_3 0x8 +#define EXT_OP_OUTFL_3 0xa + +#define RX_CMP_VLAN_VALID(rxcmp) \ + ((rxcmp)->rx_cmp_misc_v1 & cpu_to_le32(RX_CMP_METADATA1_VALID)) + +#define RX_CMP_VLAN_TPID_SEL(rxcmp) \ + (le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_METADATA1_TPID_SEL) + +#define RSS_PROFILE_ID_MASK GENMASK(4, 0) + +#define RX_CMP_HASH_TYPE(rxcmp) \ + (((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_RSS_HASH_TYPE) >>\ + RX_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK) + +#define RX_CMP_HASH_VALID(rxcmp) \ + ((rxcmp)->rx_cmp_len_flags_type & cpu_to_le32(RX_CMP_FLAGS_RSS_VALID)) +#endif /* _BNGE_HW_DEF_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 8bd019ea55a2..aef22f77e583 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -21,6 +21,7 @@ #include "bnge_hwrm_lib.h" #include "bnge_ethtool.h" #include "bnge_rmem.h" +#include "bnge_txrx.h" =20 #define BNGE_RING_TO_TC_OFF(bd, tx) \ ((tx) % (bd)->tx_nr_rings_per_tc) @@ -857,6 +858,13 @@ u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr) return txr->tx_cpr->ring_struct.fw_ring_id; } =20 +static void bnge_db_nq_arm(struct bnge_net *bn, + struct bnge_db_info *db, u32 idx) +{ + bnge_writeq(bn->bd, db->db_key64 | DBR_TYPE_NQ_ARM | + DB_RING_IDX(db, idx), db->doorbell); +} + static void bnge_db_nq(struct bnge_net *bn, struct bnge_db_info *db, u32 i= dx) { bnge_writeq(bn->bd, db->db_key64 | DBR_TYPE_NQ_MASK | @@ -879,12 +887,6 @@ static int bnge_cp_num_to_irq_num(struct bnge_net *bn,= int n) return nqr->ring_struct.map_idx; } =20 -static irqreturn_t bnge_msix(int irq, void *dev_instance) -{ - /* NAPI scheduling to be added in a future patch */ - return IRQ_HANDLED; -} - static void bnge_init_nq_tree(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; @@ -942,9 +944,8 @@ static u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dm= a_addr_t *mapping, return page_address(page) + offset; } =20 -static int bnge_alloc_rx_data(struct bnge_net *bn, - struct bnge_rx_ring_info *rxr, - u16 prod, gfp_t gfp) +int bnge_alloc_rx_data(struct bnge_net *bn, struct bnge_rx_ring_info *rxr, + u16 prod, gfp_t gfp) { struct bnge_sw_rx_bd *rx_buf =3D &rxr->rx_buf_ring[RING_RX(bn, prod)]; struct rx_bd *rxbd; @@ -1756,6 +1757,82 @@ static int bnge_cfg_def_vnic(struct bnge_net *bn) return rc; } =20 +static void bnge_disable_int(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i; + + if (!bn->bnapi) + return; + + 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_ring_struct *ring; + + nqr =3D &bnapi->nq_ring; + ring =3D &nqr->ring_struct; + + if (ring->fw_ring_id !=3D INVALID_HW_RING_ID) + bnge_db_nq(bn, &nqr->nq_db, nqr->nq_raw_cons); + } +} + +static void bnge_disable_int_sync(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i; + + bnge_disable_int(bn); + for (i =3D 0; i < bd->nq_nr_rings; i++) { + int map_idx =3D bnge_cp_num_to_irq_num(bn, i); + + synchronize_irq(bd->irq_tbl[map_idx].vector); + } +} + +static void bnge_enable_int(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + 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; + + nqr =3D &bnapi->nq_ring; + bnge_db_nq_arm(bn, &nqr->nq_db, nqr->nq_raw_cons); + } +} + +static void bnge_disable_napi(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i; + + if (test_and_set_bit(BNGE_STATE_NAPI_DISABLED, &bn->state)) + return; + + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + + napi_disable_locked(&bnapi->napi); + } +} + +static void bnge_enable_napi(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i; + + clear_bit(BNGE_STATE_NAPI_DISABLED, &bn->state); + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + + napi_enable_locked(&bnapi->napi); + } +} + static void bnge_hwrm_vnic_free(struct bnge_net *bn) { int i; @@ -1887,6 +1964,12 @@ static void bnge_hwrm_ring_free(struct bnge_net *bn,= bool close_path) bnge_hwrm_rx_agg_ring_free(bn, &bn->rx_ring[i], close_path); } =20 + /* The completion rings are about to be freed. After that the + * IRQ doorbell will not work anymore. So we need to disable + * IRQ here. + */ + bnge_disable_int_sync(bn); + for (i =3D 0; i < bd->nq_nr_rings; i++) { struct bnge_napi *bnapi =3D bn->bnapi[i]; struct bnge_nq_ring_info *nqr; @@ -2086,16 +2169,6 @@ static int bnge_init_chip(struct bnge_net *bn) return rc; } =20 -static int bnge_napi_poll(struct napi_struct *napi, int budget) -{ - int work_done =3D 0; - - /* defer NAPI implementation to next patch series */ - napi_complete_done(napi, work_done); - - return work_done; -} - static void bnge_init_napi(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; @@ -2193,7 +2266,12 @@ static int bnge_open_core(struct bnge_net *bn) netdev_err(bn->netdev, "bnge_init_nic err: %d\n", rc); goto err_free_irq; } + + bnge_enable_napi(bn); + set_bit(BNGE_STATE_OPEN, &bd->state); + + bnge_enable_int(bn); return 0; =20 err_free_irq: @@ -2236,6 +2314,7 @@ static void bnge_close_core(struct bnge_net *bn) =20 clear_bit(BNGE_STATE_OPEN, &bd->state); bnge_shutdown_nic(bn); + bnge_disable_napi(bn); bnge_free_all_rings_bufs(bn); bnge_free_irq(bn); bnge_del_napi(bn); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 557cca472db6..9303305733b4 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 "bnge_db.h" +#include "bnge_hw_def.h" =20 struct tx_bd { __le32 tx_bd_len_flags_type; @@ -173,10 +174,16 @@ enum { #define RING_RX_AGG(bn, idx) ((idx) & (bn)->rx_agg_ring_mask) #define NEXT_RX_AGG(idx) ((idx) + 1) =20 +#define BNGE_NQ_HDL_IDX_MASK 0x00ffffff +#define BNGE_NQ_HDL_TYPE_MASK 0xff000000 #define BNGE_NQ_HDL_TYPE_SHIFT 24 #define BNGE_NQ_HDL_TYPE_RX 0x00 #define BNGE_NQ_HDL_TYPE_TX 0x01 =20 +#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) + struct bnge_net { struct bnge_dev *bd; struct net_device *netdev; @@ -232,6 +239,9 @@ struct bnge_net { u8 rss_hash_key_updated:1; int rsscos_nr_ctxs; u32 stats_coal_ticks; + + unsigned long state; +#define BNGE_STATE_NAPI_DISABLED 0 }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 @@ -278,9 +288,25 @@ void bnge_set_ring_params(struct bnge_dev *bd); txr =3D (iter < BNGE_MAX_TXR_PER_NAPI - 1) ? \ (bnapi)->tx_ring[++iter] : NULL) =20 +#define DB_EPOCH(db, idx) (((idx) & (db)->db_epoch_mask) << \ + ((db)->db_epoch_shift)) + +#define DB_TOGGLE(tgl) ((tgl) << DBR_TOGGLE_SFT) + +#define DB_RING_IDX(db, idx) (((idx) & (db)->db_ring_mask) | \ + DB_EPOCH(db, idx)) + #define BNGE_SET_NQ_HDL(cpr) \ (((cpr)->cp_ring_type << BNGE_NQ_HDL_TYPE_SHIFT) | (cpr)->cp_idx) =20 +#define BNGE_DB_NQ(bd, db, idx) \ + bnge_writeq(bd, (db)->db_key64 | DBR_TYPE_NQ | DB_RING_IDX(db, idx),\ + (db)->doorbell) + +#define BNGE_DB_NQ_ARM(bd, db, idx) \ + bnge_writeq(bd, (db)->db_key64 | DBR_TYPE_NQ_ARM | \ + DB_RING_IDX(db, idx), (db)->doorbell) + struct bnge_stats_mem { u64 *sw_stats; u64 *hw_masks; @@ -289,6 +315,25 @@ struct bnge_stats_mem { int len; }; =20 +struct nqe_cn { + __le16 type; + #define NQ_CN_TYPE_MASK 0x3fUL + #define NQ_CN_TYPE_SFT 0 + #define NQ_CN_TYPE_CQ_NOTIFICATION 0x30UL + #define NQ_CN_TYPE_LAST NQ_CN_TYPE_CQ_NOTIFICATION + #define NQ_CN_TOGGLE_MASK 0xc0UL + #define NQ_CN_TOGGLE_SFT 6 + __le16 reserved16; + __le32 cq_handle_low; + __le32 v; + #define NQ_CN_V 0x1UL + __le32 cq_handle_high; +}; + +#define NQE_CN_TYPE(type) ((type) & NQ_CN_TYPE_MASK) +#define NQE_CN_TOGGLE(type) (((type) & NQ_CN_TOGGLE_MASK) >> \ + NQ_CN_TOGGLE_SFT) + struct bnge_cp_ring_info { struct bnge_napi *bnapi; dma_addr_t *desc_mapping; @@ -298,6 +343,10 @@ struct bnge_cp_ring_info { u8 cp_idx; u32 cp_raw_cons; struct bnge_db_info cp_db; + bool had_work_done; + bool has_more_work; + bool had_nqe_notify; + u8 toggle; }; =20 struct bnge_nq_ring_info { @@ -310,8 +359,9 @@ struct bnge_nq_ring_info { =20 struct bnge_stats_mem stats; u32 hw_stats_ctx_id; + bool has_more_work; =20 - int cp_ring_count; + u16 cp_ring_count; struct bnge_cp_ring_info *cp_ring_arr; }; =20 @@ -374,6 +424,12 @@ struct bnge_napi { struct bnge_nq_ring_info nq_ring; struct bnge_rx_ring_info *rx_ring; struct bnge_tx_ring_info *tx_ring[BNGE_MAX_TXR_PER_NAPI]; + u8 events; +#define BNGE_RX_EVENT 1 +#define BNGE_AGG_EVENT 2 +#define BNGE_TX_EVENT 4 +#define BNGE_REDIRECT_EVENT 8 +#define BNGE_TX_CMP_EVENT 0x10 }; =20 #define INVALID_STATS_CTX_ID -1 @@ -452,4 +508,6 @@ struct bnge_l2_filter { u16 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr); u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr); void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic= ); +int bnge_alloc_rx_data(struct bnge_net *bn, struct bnge_rx_ring_info *rxr, + u16 prod, gfp_t gfp); #endif /* _BNGE_NETDEV_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c new file mode 100644 index 000000000000..e4312fcad756 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -0,0 +1,562 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2025 Broadcom. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bnge.h" +#include "bnge_hwrm.h" +#include "bnge_hwrm_lib.h" +#include "bnge_netdev.h" +#include "bnge_rmem.h" +#include "bnge_txrx.h" + +irqreturn_t bnge_msix(int irq, void *dev_instance) +{ + struct bnge_napi *bnapi =3D dev_instance; + struct bnge_nq_ring_info *nqr; + struct bnge_net *bn; + u32 cons; + + bn =3D bnapi->bn; + nqr =3D &bnapi->nq_ring; + cons =3D RING_CMP(bn, nqr->nq_raw_cons); + + prefetch(&nqr->desc_ring[CP_RING(cons)][CP_IDX(cons)]); + napi_schedule(&bnapi->napi); + return IRQ_HANDLED; +} + +static void bnge_sched_reset_rxr(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr) +{ + /* TODO: Initiate reset task */ + rxr->rx_next_cons =3D 0xffff; +} + +void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a) +{ + struct bnge_sw_rx_bd *cons_rx_buf, *prod_rx_buf; + struct bnge_net *bn =3D rxr->bnapi->bn; + struct rx_bd *cons_bd, *prod_bd; + u16 prod =3D rxr->rx_prod; + + prod_rx_buf =3D &rxr->rx_buf_ring[RING_RX(bn, prod)]; + cons_rx_buf =3D &rxr->rx_buf_ring[cons]; + + prod_rx_buf->data =3D data; + prod_rx_buf->data_ptr =3D cons_rx_buf->data_ptr; + + prod_rx_buf->mapping =3D cons_rx_buf->mapping; + + prod_bd =3D &rxr->rx_desc_ring[RX_RING(bn, prod)][RX_IDX(prod)]; + cons_bd =3D &rxr->rx_desc_ring[RX_RING(bn, cons)][RX_IDX(cons)]; + + prod_bd->rx_bd_haddr =3D cons_bd->rx_bd_haddr; +} + +static void bnge_deliver_skb(struct bnge_net *bn, struct bnge_napi *bnapi, + struct sk_buff *skb) +{ + skb_mark_for_recycle(skb); + skb_record_rx_queue(skb, bnapi->index); + napi_gro_receive(&bnapi->napi, skb); +} + +static struct sk_buff *bnge_copy_skb(struct bnge_napi *bnapi, u8 *data, + unsigned int len, dma_addr_t mapping) +{ + struct bnge_net *bn =3D bnapi->bn; + struct bnge_dev *bd =3D bn->bd; + struct sk_buff *skb; + + skb =3D napi_alloc_skb(&bnapi->napi, len); + if (!skb) + return NULL; + + dma_sync_single_for_cpu(bd->dev, mapping, len, bn->rx_dir); + + memcpy(skb->data - NET_IP_ALIGN, data - NET_IP_ALIGN, + len + NET_IP_ALIGN); + + dma_sync_single_for_device(bd->dev, mapping, len, bn->rx_dir); + + skb_put(skb, len); + + return skb; +} + +static enum pkt_hash_types bnge_rss_ext_op(struct bnge_net *bn, + struct rx_cmp *rxcmp) +{ + u8 ext_op =3D RX_CMP_V3_HASH_TYPE(bn->bd, rxcmp); + + switch (ext_op) { + case EXT_OP_INNER_4: + case EXT_OP_OUTER_4: + case EXT_OP_INNFL_3: + case EXT_OP_OUTFL_3: + return PKT_HASH_TYPE_L4; + default: + return PKT_HASH_TYPE_L3; + } +} + +static struct sk_buff *bnge_rx_vlan(struct sk_buff *skb, u8 cmp_type, + struct rx_cmp *rxcmp, + struct rx_cmp_ext *rxcmp1) +{ + __be16 vlan_proto; + u16 vtag; + + if (cmp_type =3D=3D CMP_TYPE_RX_L2_CMP) { + __le32 flags2 =3D rxcmp1->rx_cmp_flags2; + u32 meta_data; + + if (!(flags2 & cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN))) + return skb; + + meta_data =3D le32_to_cpu(rxcmp1->rx_cmp_meta_data); + vtag =3D meta_data & RX_CMP_FLAGS2_METADATA_TCI_MASK; + vlan_proto =3D + htons(meta_data >> RX_CMP_FLAGS2_METADATA_TPID_SFT); + if (eth_type_vlan(vlan_proto)) + __vlan_hwaccel_put_tag(skb, vlan_proto, vtag); + else + goto vlan_err; + } else if (cmp_type =3D=3D CMP_TYPE_RX_L2_V3_CMP) { + if (RX_CMP_VLAN_VALID(rxcmp)) { + u32 tpid_sel =3D RX_CMP_VLAN_TPID_SEL(rxcmp); + + if (tpid_sel =3D=3D RX_CMP_METADATA1_TPID_8021Q) + vlan_proto =3D htons(ETH_P_8021Q); + else if (tpid_sel =3D=3D RX_CMP_METADATA1_TPID_8021AD) + vlan_proto =3D htons(ETH_P_8021AD); + else + goto vlan_err; + vtag =3D RX_CMP_METADATA0_TCI(rxcmp1); + __vlan_hwaccel_put_tag(skb, vlan_proto, vtag); + } + } + return skb; + +vlan_err: + skb_mark_for_recycle(skb); + dev_kfree_skb(skb); + return NULL; +} + +static struct sk_buff *bnge_rx_skb(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr, u16 cons, + void *data, u8 *data_ptr, + dma_addr_t dma_addr, + unsigned int len) +{ + struct bnge_dev *bd =3D bn->bd; + u16 prod =3D rxr->rx_prod; + struct sk_buff *skb; + int err; + + err =3D bnge_alloc_rx_data(bn, rxr, prod, GFP_ATOMIC); + if (unlikely(err)) { + bnge_reuse_rx_data(rxr, cons, data); + return NULL; + } + + dma_sync_single_for_cpu(bd->dev, dma_addr, len, bn->rx_dir); + skb =3D napi_build_skb(data, bn->rx_buf_size); + if (!skb) { + page_pool_free_va(rxr->head_pool, data, true); + return NULL; + } + + skb_mark_for_recycle(skb); + skb_reserve(skb, bn->rx_offset); + skb_put(skb, len); + return skb; +} + +/* returns the following: + * 1 - 1 packet successfully received + * -EBUSY - completion ring does not have all the agg buffers yet + * -ENOMEM - packet aborted due to out of memory + * -EIO - packet aborted due to hw error indicated in BD + */ +static int bnge_rx_pkt(struct bnge_net *bn, struct bnge_cp_ring_info *cpr, + u32 *raw_cons, u8 *event) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + struct net_device *dev =3D bn->netdev; + struct bnge_rx_ring_info *rxr; + struct bnge_sw_rx_bd *rx_buf; + struct rx_cmp_ext *rxcmp1; + u16 cons, prod, cp_cons; + u32 tmp_raw_cons, flags; + u8 *data_ptr, cmp_type; + struct rx_cmp *rxcmp; + dma_addr_t dma_addr; + struct sk_buff *skb; + unsigned int len; + void *data; + int rc =3D 0; + + rxr =3D bnapi->rx_ring; + + tmp_raw_cons =3D *raw_cons; + cp_cons =3D RING_CMP(bn, tmp_raw_cons); + rxcmp =3D (struct rx_cmp *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + cmp_type =3D RX_CMP_TYPE(rxcmp); + + tmp_raw_cons =3D NEXT_RAW_CMP(tmp_raw_cons); + cp_cons =3D RING_CMP(bn, tmp_raw_cons); + rxcmp1 =3D (struct rx_cmp_ext *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + if (!RX_CMP_VALID(bn, rxcmp1, tmp_raw_cons)) + return -EBUSY; + + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + prod =3D rxr->rx_prod; + + cons =3D rxcmp->rx_cmp_opaque; + if (unlikely(cons !=3D rxr->rx_next_cons)) { + /* 0xffff is forced error, don't print it */ + if (rxr->rx_next_cons !=3D 0xffff) + netdev_warn(bn->netdev, "RX cons %x !=3D expected cons %x\n", + cons, rxr->rx_next_cons); + bnge_sched_reset_rxr(bn, rxr); + goto next_rx_no_prod_no_len; + } + rx_buf =3D &rxr->rx_buf_ring[cons]; + data =3D rx_buf->data; + data_ptr =3D rx_buf->data_ptr; + prefetch(data_ptr); + + *event |=3D BNGE_RX_EVENT; + + rx_buf->data =3D NULL; + if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L2_ERRORS) { + bnge_reuse_rx_data(rxr, cons, data); + rc =3D -EIO; + goto next_rx_no_len; + } + + flags =3D le32_to_cpu(rxcmp->rx_cmp_len_flags_type); + len =3D flags >> RX_CMP_LEN_SHIFT; + dma_addr =3D rx_buf->mapping; + + if (len <=3D bn->rx_copybreak) { + skb =3D bnge_copy_skb(bnapi, data_ptr, len, dma_addr); + bnge_reuse_rx_data(rxr, cons, data); + if (!skb) + goto oom_next_rx; + } else { + skb =3D bnge_rx_skb(bn, rxr, cons, data, data_ptr, dma_addr, len); + if (!skb) + goto oom_next_rx; + } + + if (RX_CMP_HASH_VALID(rxcmp)) { + enum pkt_hash_types type; + + if (cmp_type =3D=3D CMP_TYPE_RX_L2_V3_CMP) { + type =3D bnge_rss_ext_op(bn, rxcmp); + } else { + u32 itypes =3D RX_CMP_ITYPES(rxcmp); + + if (itypes =3D=3D RX_CMP_FLAGS_ITYPE_TCP || + itypes =3D=3D RX_CMP_FLAGS_ITYPE_UDP) + type =3D PKT_HASH_TYPE_L4; + else + type =3D PKT_HASH_TYPE_L3; + } + skb_set_hash(skb, le32_to_cpu(rxcmp->rx_cmp_rss_hash), type); + } + + skb->protocol =3D eth_type_trans(skb, dev); + + if (skb->dev->features & BNGE_HW_FEATURE_VLAN_ALL_RX) { + skb =3D bnge_rx_vlan(skb, cmp_type, rxcmp, rxcmp1); + if (!skb) + goto next_rx; + } + + skb_checksum_none_assert(skb); + if (RX_CMP_L4_CS_OK(rxcmp1)) { + if (dev->features & NETIF_F_RXCSUM) { + skb->ip_summed =3D CHECKSUM_UNNECESSARY; + skb->csum_level =3D RX_CMP_ENCAP(rxcmp1); + } + } + + bnge_deliver_skb(bn, bnapi, skb); + rc =3D 1; + +next_rx: + /* Update Stats */ +next_rx_no_len: + rxr->rx_prod =3D NEXT_RX(prod); + rxr->rx_next_cons =3D RING_RX(bn, NEXT_RX(cons)); + +next_rx_no_prod_no_len: + *raw_cons =3D tmp_raw_cons; + return rc; + +oom_next_rx: + rc =3D -ENOMEM; + goto next_rx; +} + +/* In netpoll mode, if we are using a combined completion ring, we need to + * discard the rx packets and recycle the buffers. + */ +static int bnge_force_rx_discard(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u32 *raw_cons, u8 *event) +{ + u32 tmp_raw_cons =3D *raw_cons; + struct rx_cmp_ext *rxcmp1; + struct rx_cmp *rxcmp; + u16 cp_cons; + u8 cmp_type; + int rc; + + cp_cons =3D RING_CMP(bn, tmp_raw_cons); + rxcmp =3D (struct rx_cmp *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + tmp_raw_cons =3D NEXT_RAW_CMP(tmp_raw_cons); + cp_cons =3D RING_CMP(bn, tmp_raw_cons); + rxcmp1 =3D (struct rx_cmp_ext *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + if (!RX_CMP_VALID(bn, rxcmp1, tmp_raw_cons)) + return -EBUSY; + + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + cmp_type =3D RX_CMP_TYPE(rxcmp); + if (cmp_type =3D=3D CMP_TYPE_RX_L2_CMP || + cmp_type =3D=3D CMP_TYPE_RX_L2_V3_CMP) { + rxcmp1->rx_cmp_cfa_code_errors_v2 |=3D + cpu_to_le32(RX_CMPL_ERRORS_CRC_ERROR); + } + rc =3D bnge_rx_pkt(bn, cpr, raw_cons, event); + return rc; +} + +static void __bnge_poll_work_done(struct bnge_net *bn, struct bnge_napi *b= napi, + int budget) +{ + struct bnge_rx_ring_info *rxr =3D bnapi->rx_ring; + + if ((bnapi->events & BNGE_RX_EVENT)) { + bnge_db_write(bn->bd, &rxr->rx_db, rxr->rx_prod); + bnapi->events &=3D ~BNGE_RX_EVENT; + } +} + +static int __bnge_poll_work(struct bnge_net *bn, struct bnge_cp_ring_info = *cpr, + int budget) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + u32 raw_cons =3D cpr->cp_raw_cons; + struct tx_cmp *txcmp; + int rx_pkts =3D 0; + u8 event =3D 0; + u32 cons; + + cpr->has_more_work =3D 0; + cpr->had_work_done =3D 1; + while (1) { + u8 cmp_type; + int rc; + + cons =3D RING_CMP(bn, raw_cons); + txcmp =3D &cpr->desc_ring[CP_RING(cons)][CP_IDX(cons)]; + + if (!TX_CMP_VALID(bn, txcmp, raw_cons)) + break; + + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + cmp_type =3D TX_CMP_TYPE(txcmp); + if (cmp_type =3D=3D CMP_TYPE_TX_L2_CMP || + cmp_type =3D=3D CMP_TYPE_TX_L2_COAL_CMP) { + /* + * Tx Compl Processing + */ + } else if (cmp_type >=3D CMP_TYPE_RX_L2_CMP && + cmp_type <=3D CMP_TYPE_RX_L2_TPA_START_V3_CMP) { + if (likely(budget)) + rc =3D bnge_rx_pkt(bn, cpr, &raw_cons, &event); + else + rc =3D bnge_force_rx_discard(bn, cpr, &raw_cons, + &event); + if (likely(rc >=3D 0)) + rx_pkts +=3D rc; + /* Increment rx_pkts when rc is -ENOMEM to count towards + * the NAPI budget. Otherwise, we may potentially loop + * here forever if we consistently cannot allocate + * buffers. + */ + else if (rc =3D=3D -ENOMEM && budget) + rx_pkts++; + else if (rc =3D=3D -EBUSY) /* partial completion */ + break; + } + + raw_cons =3D NEXT_RAW_CMP(raw_cons); + + if (rx_pkts && rx_pkts =3D=3D budget) { + cpr->has_more_work =3D 1; + break; + } + } + + cpr->cp_raw_cons =3D raw_cons; + bnapi->events |=3D event; + return rx_pkts; +} + +static void __bnge_poll_cqs_done(struct bnge_net *bn, struct bnge_napi *bn= api, + u64 dbr_type, int budget) +{ + struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; + int i; + + for (i =3D 0; i < nqr->cp_ring_count; i++) { + struct bnge_cp_ring_info *cpr =3D &nqr->cp_ring_arr[i]; + struct bnge_db_info *db; + + if (cpr->had_work_done) { + u32 tgl =3D 0; + + if (dbr_type =3D=3D DBR_TYPE_CQ_ARMALL) { + cpr->had_nqe_notify =3D 0; + tgl =3D cpr->toggle; + } + db =3D &cpr->cp_db; + bnge_writeq(bn->bd, + db->db_key64 | dbr_type | DB_TOGGLE(tgl) | + DB_RING_IDX(db, cpr->cp_raw_cons), + db->doorbell); + cpr->had_work_done =3D 0; + } + } + __bnge_poll_work_done(bn, bnapi, budget); +} + +static int __bnge_poll_cqs(struct bnge_net *bn, struct bnge_napi *bnapi, + int budget) +{ + struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; + int i, work_done =3D 0; + + for (i =3D 0; i < nqr->cp_ring_count; i++) { + struct bnge_cp_ring_info *cpr =3D &nqr->cp_ring_arr[i]; + + if (cpr->had_nqe_notify) { + work_done +=3D __bnge_poll_work(bn, cpr, + budget - work_done); + nqr->has_more_work |=3D cpr->has_more_work; + } + } + return work_done; +} + +int bnge_napi_poll(struct napi_struct *napi, int budget) +{ + struct bnge_napi *bnapi =3D container_of(napi, struct bnge_napi, napi); + struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; + u32 raw_cons =3D nqr->nq_raw_cons; + struct bnge_net *bn =3D bnapi->bn; + struct bnge_dev *bd =3D bn->bd; + struct nqe_cn *nqcmp; + int work_done =3D 0; + u32 cons; + + if (nqr->has_more_work) { + nqr->has_more_work =3D 0; + work_done =3D __bnge_poll_cqs(bn, bnapi, budget); + } + + while (1) { + u16 type; + + cons =3D RING_CMP(bn, raw_cons); + nqcmp =3D &nqr->desc_ring[CP_RING(cons)][CP_IDX(cons)]; + + if (!NQ_CMP_VALID(bn, nqcmp, raw_cons)) { + if (nqr->has_more_work) + break; + + __bnge_poll_cqs_done(bn, bnapi, DBR_TYPE_CQ_ARMALL, + budget); + nqr->nq_raw_cons =3D raw_cons; + if (napi_complete_done(napi, work_done)) + BNGE_DB_NQ_ARM(bd, &nqr->nq_db, + nqr->nq_raw_cons); + goto poll_done; + } + + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + + type =3D le16_to_cpu(nqcmp->type); + if (NQE_CN_TYPE(type) =3D=3D NQ_CN_TYPE_CQ_NOTIFICATION) { + u32 idx =3D le32_to_cpu(nqcmp->cq_handle_low); + u32 cq_type =3D BNGE_NQ_HDL_TYPE(idx); + struct bnge_cp_ring_info *cpr; + + /* No more budget for RX work */ + if (budget && work_done >=3D budget && + cq_type =3D=3D BNGE_NQ_HDL_TYPE_RX) + break; + + idx =3D BNGE_NQ_HDL_IDX(idx); + cpr =3D &nqr->cp_ring_arr[idx]; + cpr->had_nqe_notify =3D 1; + cpr->toggle =3D NQE_CN_TOGGLE(type); + work_done +=3D __bnge_poll_work(bn, cpr, + budget - work_done); + nqr->has_more_work |=3D cpr->has_more_work; + } + raw_cons =3D NEXT_RAW_CMP(raw_cons); + } + + __bnge_poll_cqs_done(bn, bnapi, DBR_TYPE_CQ, budget); + if (raw_cons !=3D nqr->nq_raw_cons) { + nqr->nq_raw_cons =3D raw_cons; + BNGE_DB_NQ(bd, &nqr->nq_db, raw_cons); + } +poll_done: + return work_done; +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.h new file mode 100644 index 000000000000..0d8db88529eb --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2025 Broadcom */ + +#ifndef _BNGE_TXRX_H_ +#define _BNGE_TXRX_H_ + +#include +#include "bnge_netdev.h" + +#define TX_OPAQUE_IDX_MASK 0x0000ffff +#define TX_OPAQUE_BDS_MASK 0x00ff0000 +#define TX_OPAQUE_BDS_SHIFT 16 +#define TX_OPAQUE_RING_MASK 0xff000000 +#define TX_OPAQUE_RING_SHIFT 24 + +#define SET_TX_OPAQUE(bn, txr, idx, bds) \ + (((txr)->tx_napi_idx << TX_OPAQUE_RING_SHIFT) | \ + ((bds) << TX_OPAQUE_BDS_SHIFT) | ((idx) & (bn)->tx_ring_mask)) + +#define TX_OPAQUE_IDX(opq) ((opq) & TX_OPAQUE_IDX_MASK) +#define TX_OPAQUE_RING(opq) (((opq) & TX_OPAQUE_RING_MASK) >> \ + TX_OPAQUE_RING_SHIFT) +#define TX_OPAQUE_BDS(opq) (((opq) & TX_OPAQUE_BDS_MASK) >> \ + TX_OPAQUE_BDS_SHIFT) +#define TX_OPAQUE_PROD(bn, opq) ((TX_OPAQUE_IDX(opq) + TX_OPAQUE_BDS(opq))= &\ + (bn)->tx_ring_mask) + +/* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one ext= ra + * BD because the first TX BD is always a long BD. + */ +#define BNGE_MIN_TX_DESC_CNT (MAX_SKB_FRAGS + 2) + +#define RX_RING(bn, x) (((x) & (bn)->rx_ring_mask) >> (BNGE_PAGE_SHIFT - 4= )) +#define RX_AGG_RING(bn, x) (((x) & (bn)->rx_agg_ring_mask) >> \ + (BNGE_PAGE_SHIFT - 4)) +#define RX_IDX(x) ((x) & (RX_DESC_CNT - 1)) + +#define TX_RING(bn, x) (((x) & (bn)->tx_ring_mask) >> (BNGE_PAGE_SHIFT - 4= )) +#define TX_IDX(x) ((x) & (TX_DESC_CNT - 1)) + +#define CP_RING(x) (((x) & ~(CP_DESC_CNT - 1)) >> (BNGE_PAGE_SHIFT - 4)) +#define CP_IDX(x) ((x) & (CP_DESC_CNT - 1)) + +#define TX_CMP_VALID(bn, txcmp, raw_cons) \ + (!!((txcmp)->tx_cmp_errors_v & cpu_to_le32(TX_CMP_V)) =3D=3D \ + !((raw_cons) & (bn)->cp_bit)) + +#define RX_CMP_VALID(bn, rxcmp1, raw_cons) \ + (!!((rxcmp1)->rx_cmp_cfa_code_errors_v2 & cpu_to_le32(RX_CMP_V)) =3D=3D\ + !((raw_cons) & (bn)->cp_bit)) + +#define RX_AGG_CMP_VALID(bn, agg, raw_cons) \ + (!!((agg)->rx_agg_cmp_v & cpu_to_le32(RX_AGG_CMP_V)) =3D=3D \ + !((raw_cons) & (bn)->cp_bit)) + +#define NQ_CMP_VALID(bn, nqcmp, raw_cons) \ + (!!((nqcmp)->v & cpu_to_le32(NQ_CN_V)) =3D=3D !((raw_cons) & (bn)->cp_bit= )) + +#define TX_CMP_TYPE(txcmp) \ + (le32_to_cpu((txcmp)->tx_cmp_flags_type) & CMP_TYPE) + +#define RX_CMP_TYPE(rxcmp) \ + (le32_to_cpu((rxcmp)->rx_cmp_len_flags_type) & RX_CMP_CMP_TYPE) + +#define RING_RX(bn, idx) ((idx) & (bn)->rx_ring_mask) +#define NEXT_RX(idx) ((idx) + 1) + +#define RING_RX_AGG(bn, idx) ((idx) & (bn)->rx_agg_ring_mask) +#define NEXT_RX_AGG(idx) ((idx) + 1) + +#define RING_TX(bn, idx) ((idx) & (bn)->tx_ring_mask) +#define NEXT_TX(idx) ((idx) + 1) + +#define ADV_RAW_CMP(idx, n) ((idx) + (n)) +#define NEXT_RAW_CMP(idx) ADV_RAW_CMP(idx, 1) +#define RING_CMP(bn, idx) ((idx) & (bn)->cp_ring_mask) + +#define RX_CMP_ITYPES(rxcmp) \ + (le32_to_cpu((rxcmp)->rx_cmp_len_flags_type) & RX_CMP_FLAGS_ITYPES_MASK) + +#define RX_CMP_CFA_CODE(rxcmpl1) \ + ((le32_to_cpu((rxcmpl1)->rx_cmp_cfa_code_errors_v2) & \ + RX_CMPL_CFA_CODE_MASK) >> RX_CMPL_CFA_CODE_SFT) + +irqreturn_t bnge_msix(int irq, void *dev_instance); +void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a); +int bnge_napi_poll(struct napi_struct *napi, int budget); +#endif /* _BNGE_TXRX_H_ */ --=20 2.47.3 From nobody Sat Feb 7 09:29:51 2026 Received: from mail-pl1-f225.google.com (mail-pl1-f225.google.com [209.85.214.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 D7089296BBB for ; Fri, 23 Jan 2026 19:35:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.225 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196935; cv=none; b=fLzq/g/gF6mR+DKAr5hAaAo103TXyzbCO+ulIP9fKclLl0WUyAuk5Vb+5GTFmLjKybhhXG2z7xFpT9l6PhdGfHHNCWPbHokapnYOiwrxyWBVN1+IG7vuOLyEo877a+NJgBWboyYX5oCp58Iz5kenrzvRplT3O4o/JRhpLw3qzE4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196935; c=relaxed/simple; bh=NSKp7+7796MkKBcTdo3o37PF7/jU1LGtASKoU0av4kc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=adCtVj7o0jZh/SnDPb393pXKHtWiMPuwkHvNdR1PZYZs/GgGaP4apIddZTRo8SdV2Q41LEb0iijv5TuaMQnvdN7NoaKFepCKIctm/ltG8BWzEVMxRpR2zEj5chXz/yC1HzyTacu3JEEr+5dri5/ImOsjmaKwi0Aoc+X/btqa3pE= 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=Jq8d1aMt; arc=none smtp.client-ip=209.85.214.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="Jq8d1aMt" Received: by mail-pl1-f225.google.com with SMTP id d9443c01a7336-2a7a23f5915so16291825ad.2 for ; Fri, 23 Jan 2026 11:35:33 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769196933; x=1769801733; 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=xdSkCegsAvP47246YGZJCy4msn+ummvP4ChY2ZXTpKs=; b=bIgpzM+yJ4O1fh6MH3kdWDsvoS8HCSCLbYKzJ6wWgJ1XXBYR7fHF76D9ZjeM6XsMqG Vgd9QFfuFwRR7wy0DitSbEwGBgYvHUsggYFaL/sphXPG1c9RmYFtvL8WNZiE1GLV1Rb2 F9wMvCn5LtJHpLiLuI9DR4aq/f+zkz+5SvSzAxAq9fCRsursnHx0dJnZlaCqeHkzXlWm 2eGoffuCPvv7GxiXNgCwwxwPGCRREdc3N4KD1Nsipv27mwmoon0ELbQlJF8EAzQDZMB2 9wWwFjG0JwbNER0xm+Npf0xfKWWSfZRhHRRj6YcZtca6XRaNPmzIprCNi6kW/snqLDnn auWw== X-Forwarded-Encrypted: i=1; AJvYcCVZVx1uVZ39IV7R3wewghsyIM3J5IP2lcdybs6wSFfd/mYEzX/zDcQdbZKXIEHIFA3UdGbYk3z/hPZIZoU=@vger.kernel.org X-Gm-Message-State: AOJu0Yw4q9pPCMIlxFSy6m+VVU0wVU653frotWOqCJYtXXz/ZE2bP74V ehB3EOsK3BIr5q7GLCLTkX7L11+I7yo1LYMzoZ8+nTpIVVTz5KiF9O/khxEMZtoFZmkfpLEoml+ YXeIUhgJNQcXrb5KfVJ3A7cq+9GP1Jly6xWOVVKS69x9YEQyVeUX42PR5pBC7ZUJVG4WS5gZowt FR0L1RNWf2igPFBn0bhCrKG5UcLhYHW1/F6cp52QORnQ8ou5o3WOv/w3BQZ/3LAy5kBM2YsJj3P 0mbZlwpMYNnBoxs4gVKy0CLww== X-Gm-Gg: AZuq6aI29zTbPhpXBf40EsJPIzn7In6YLe20yF1gXQZ7PchkjKo9MrzhXyDBdJET2wN VZ+q22Ll/orhMG2o1+54H5NJOmcmjVgeVHe94YGIYt2255Kjev6ZUe7bVQaUMOQ4f1i4naYB7p7 ublgHW98iLZMOJL5nKaTpJ3ugHw2fk1w5u5b2ktTNgtb70FZqlyNKzvS6AZUe+e+kxhtSJzh6To r/tHS5SIsofn4enPSJigYmeXY2hUc0lNOBKi81ZPDvmXbcHJoKUVcE+j1Xkq0wFwhFaevF0f08S pP5awdFslYJzgLqPWYPZ9QRndMRHLnwR9Y0/e+2MRvuDJpUuGmeMw8WkKmO4VGHLfuGQbRwpiwT qI6koiezzVEAoSsN8O0n2nV0+Cq4fye1F8RdpYICnR2Y3s1vBS1oiUf1ZB1qTG5gn0ClrhvvPqC 2/5TMbG5FTJvrOTAWD6Nh96pQx+uvWGrIsgytFz5EH6yv5FD1WUhI= X-Received: by 2002:a17:902:ec8e:b0:2a3:6b54:5d42 with SMTP id d9443c01a7336-2a80ec82615mr22743065ad.59.1769196933148; Fri, 23 Jan 2026 11:35:33 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-77.dlp.protect.broadcom.com. [144.49.247.77]) by smtp-relay.gmail.com with ESMTPS id d9443c01a7336-2a802fa5fabsm2738495ad.50.2026.01.23.11.35.32 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Jan 2026 11:35:33 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f69.google.com with SMTP id 98e67ed59e1d1-34c64cd48a8so2640217a91.0 for ; Fri, 23 Jan 2026 11:35:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1769196930; x=1769801730; 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=xdSkCegsAvP47246YGZJCy4msn+ummvP4ChY2ZXTpKs=; b=Jq8d1aMtFaHzr9VJIRTM7PJrZ+RQj1k8B5+7od2JL6p6R8aqt3QvKtw5/WCrCshiYH 3WICfJBujzWqVylr9Nd01D+gIVe/q0U9Cs55XhC7XTFPJGywyym7lei8hzTsrVE8olO7 jzdvY9ANoj8j8HmP8ltyBxFObPkPJ/P1NUJ7o= X-Forwarded-Encrypted: i=1; AJvYcCXq+M59z+81PfJ0eeJVKYMSXfRM0cLGotYQmmQ2nveDQOzbGxOBbg6k7nts/3Njb3zukK30AD5KnabbKdw=@vger.kernel.org X-Received: by 2002:a17:90b:5145:b0:352:d97d:4bf5 with SMTP id 98e67ed59e1d1-3537af94d91mr1794440a91.27.1769196929556; Fri, 23 Jan 2026 11:35:29 -0800 (PST) X-Received: by 2002:a17:90b:5145:b0:352:d97d:4bf5 with SMTP id 98e67ed59e1d1-3537af94d91mr1794419a91.27.1769196929021; Fri, 23 Jan 2026 11:35:29 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8231873e519sm2843206b3a.49.2026.01.23.11.35.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Jan 2026 11:35:28 -0800 (PST) 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, ajit.khaparde@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v6, net-next 3/8] bng_en: Handle an HWRM completion request Date: Sat, 24 Jan 2026 01:04:59 +0530 Message-ID: <20260123193504.285573-4-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260123193504.285573-1-bhargava.marreddy@broadcom.com> References: <20260123193504.285573-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" Since the HWRM completion for a sent request lands on the NQ, add functions to handle the HWRM completion event. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 3 +- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 1 + .../net/ethernet/broadcom/bnge/bnge_txrx.c | 44 ++++++++++++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index aef22f77e583..594e83759802 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -2303,8 +2303,7 @@ static int bnge_open(struct net_device *dev) =20 static int bnge_shutdown_nic(struct bnge_net *bn) { - /* TODO: close_path =3D 0 until we make NAPI functional */ - bnge_hwrm_resource_free(bn, 0); + bnge_hwrm_resource_free(bn, 1); return 0; } =20 diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 9303305733b4..4cc69b6cf30c 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -77,6 +77,7 @@ struct tx_cmp { #define CMPL_BASE_TYPE_HWRM_FWD_REQ 0x22UL #define CMPL_BASE_TYPE_HWRM_FWD_RESP 0x24UL #define CMPL_BASE_TYPE_HWRM_ASYNC_EVENT 0x2eUL + #define CMPL_BA_TY_HWRM_ASY_EVT CMPL_BASE_TYPE_HWRM_ASYNC_EVENT #define TX_CMP_FLAGS_ERROR (1 << 6) #define TX_CMP_FLAGS_PUSH (1 << 7) u32 tx_cmp_opaque; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index e4312fcad756..5d16adf2315b 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -379,6 +379,43 @@ static void __bnge_poll_work_done(struct bnge_net *bn,= struct bnge_napi *bnapi, } } =20 +static void +bnge_hwrm_update_token(struct bnge_dev *bd, u16 seq_id, + enum bnge_hwrm_wait_state state) +{ + struct bnge_hwrm_wait_token *token; + + rcu_read_lock(); + hlist_for_each_entry_rcu(token, &bd->hwrm_pending_list, node) { + if (token->seq_id =3D=3D seq_id) { + WRITE_ONCE(token->state, state); + rcu_read_unlock(); + return; + } + } + rcu_read_unlock(); + dev_err(bd->dev, "Invalid hwrm seq id %d\n", seq_id); +} + +static int bnge_hwrm_handler(struct bnge_dev *bd, struct tx_cmp *txcmp) +{ + struct hwrm_cmpl *h_cmpl =3D (struct hwrm_cmpl *)txcmp; + u16 cmpl_type =3D TX_CMP_TYPE(txcmp), seq_id; + + 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); + break; + + case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: + default: + break; + } + + return 0; +} + static int __bnge_poll_work(struct bnge_net *bn, struct bnge_cp_ring_info = *cpr, int budget) { @@ -429,8 +466,11 @@ static int __bnge_poll_work(struct bnge_net *bn, struc= t bnge_cp_ring_info *cpr, rx_pkts++; else if (rc =3D=3D -EBUSY) /* partial completion */ break; + } 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); } - raw_cons =3D NEXT_RAW_CMP(raw_cons); =20 if (rx_pkts && rx_pkts =3D=3D budget) { @@ -548,6 +588,8 @@ int bnge_napi_poll(struct napi_struct *napi, int budget) work_done +=3D __bnge_poll_work(bn, cpr, budget - work_done); nqr->has_more_work |=3D cpr->has_more_work; + } else { + bnge_hwrm_handler(bn->bd, (struct tx_cmp *)nqcmp); } raw_cons =3D NEXT_RAW_CMP(raw_cons); } --=20 2.47.3 From nobody Sat Feb 7 09:29:52 2026 Received: from mail-qv1-f99.google.com (mail-qv1-f99.google.com [209.85.219.99]) (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 348532BDC2C for ; Fri, 23 Jan 2026 19:35:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.99 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196940; cv=none; b=OkBiAW3umw0BG1XRrwHY3N4lNAvatnXY+edLTb8opstbNi2XjssH7YR7WjF3ITZqhHro9WUHHTj3BuLruImCqI5tM2BtQcISmY6I91LOEqHEdChs0hM87JZhtmZDDAbk27JH7BUXrfPAq6dbauz6FviujDRDvXhtlFAANOgZZaA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196940; c=relaxed/simple; bh=bi62xsMrVcNtHeqzWRc/4O7cgR+YwcaEFxU8TxpFkT0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TbjiSiIlVDzRBr/IsvYqSAP7aQKcrnvtEjIpiP4kX1X7aWNdh0y49l50vVz035wWi0xKPoq6bA2TO8bCwjz4zg7ooxdClq84E7zkazi8PjU7bEiP607hvihwhDl8+sSkUCDMc9Su0n5laQANz7q+NrP7hiGkWXHkOXEXoBP6DyI= 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=TYmlIanP; arc=none smtp.client-ip=209.85.219.99 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="TYmlIanP" Received: by mail-qv1-f99.google.com with SMTP id 6a1803df08f44-88a3d2f3299so29762556d6.2 for ; Fri, 23 Jan 2026 11:35:37 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769196936; x=1769801736; 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=wD/7/SXKzG6TPzSmli2AoLgaE/YU7QESwj7vOTKqi+8=; b=J8anf9GwN76hkqWfEOeJ3pQU7dMlpHKL0G85I+rcX86Q89/ZwAVCv3aHDaUgK7mcH4 HwbSIGiPLNG08sgArkyHjDxP23Ih/invq1GlCyZqZQgVaERt/Fn5w5ZwOeiUyQ5NHLhj FjCmvV/jI1UIinX91lQBym1AfVz8VwVFoXcbHLkLhi7anvUDXOLtHhIqul+CuUDq2TKw RpcaQ0QW9Vp3rddclXvKo8yvXWkAS2AviKgZNGQiqZIi9vQ21guhpquZ4mlkrQ5vMcIq jseE7MF6bdl/mLg0x/EdXqGDGEuRaYwoIiM+8itvkgG4SG0XA/4AB97E+YtbFsxsDZ4i KKlg== X-Forwarded-Encrypted: i=1; AJvYcCXxGwU7mcPDC4cwDAUpodMhJ6NXZjcBgNunq0NEjQvIUlhOkFWPSci4FOx3zezIT3Au94q0Tx6UabZDiNg=@vger.kernel.org X-Gm-Message-State: AOJu0YwN0B7Ix5R/Dd3kdSIj59+s0iE0Hg4yTwx0Igm1UTL6ujpJcvE6 Uyr620Sms1naGr6nHANl/mhq+ndIVFnSJdddAttmQVjAYOjjtC3LEWEtxrANhedDE6ERTi1rc+/ CK1dw9rjxMvdQ20VpWgxA+aNalWgkD6o6NbNQ8VqRVI1XoDzB7REMmPGSzjpZjsXYzQfvW91YEp 13SNGlm/obK2h/8WoqUTYK6D0lBFJlAKlXteXnTDuhtVqfQ1v6wpAMAnDR3xKPx9drPYVAaG6Nj ZEUM7MFH+argEbBfD+KHG22SA== X-Gm-Gg: AZuq6aIXL4Y5YLRvk6i2vG7e1u4K8huyRKKuuEBEcltCJnQL3oT8YPHIkNCc2q0Kzlw iS8dzHKY8Z4MQlMtSg7d5kIWf5XNb6WIstaTHBPuE/35ZXK/ldvuWC0hp1LXslpMqNL9J3c1HmM Hu/u2DP5WUT4qSVfRBY8dsxDH+h6W8/bTGljHhJfH4//guDf9Iy9qLS+wCCDTc3/+VQXga3k+J1 aOV7fhmhXdIYd3z2/EH+/bccbvfVwmm6mk1lDJB3js0mVSjhKC/xMvzb1b5ujDTbuGOpq0wsqHk l3612sGksA1pUEX5+wOjwyxXEQAlpWeb9vCT/RC8RJ60yR8sV9HeeF12XKzQVmWO1nFJu7dd65D T9Q/5X9y80FDYCQslwHlT3LSq24nZBsWlbCsci3tyXd3aWaIHBiPrXqF1cweZbLYjkkw9aB2l5l cCDT+RCsCfuSiPgyAiXChOzNZUnF33aBRT+X8rKUrnQWZbZ+4DQnmWIQ== X-Received: by 2002:a05:6214:1d02:b0:894:6f05:3185 with SMTP id 6a1803df08f44-89497d035b4mr28951266d6.0.1769196935873; Fri, 23 Jan 2026 11:35:35 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-100.dlp.protect.broadcom.com. [144.49.247.100]) by smtp-relay.gmail.com with ESMTPS id 6a1803df08f44-8949189d12asm3891436d6.30.2026.01.23.11.35.35 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Jan 2026 11:35:35 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pg1-f199.google.com with SMTP id 41be03b00d2f7-c56848e6f53so1421649a12.0 for ; Fri, 23 Jan 2026 11:35:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1769196934; x=1769801734; 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=wD/7/SXKzG6TPzSmli2AoLgaE/YU7QESwj7vOTKqi+8=; b=TYmlIanPhMVmM5TW3dHf+940JglVfd7EQy6b8X18NCWWeBBIY4Ix5x7opqyZueWma5 CRNiNYhczGicAG2U345n9RlFBXe7C7RmKEly+ECZ3/naPbUUP2hP10damNqB8pp2IJNm pDDd5krSCT9k1Aex89TcLSewHIxrVgHIVSBq8= X-Forwarded-Encrypted: i=1; AJvYcCUy1e0A8atDWooHNTwqzdjstkYt1+Ta2bjLCO29FaLQaw/AGOt//WsCrtWXkezxjGaXPaZPZvrdMTj+nxw=@vger.kernel.org X-Received: by 2002:a05:6a00:1741:b0:81f:852b:a934 with SMTP id d2e1a72fcca58-823215d88d0mr1995357b3a.24.1769196934157; Fri, 23 Jan 2026 11:35:34 -0800 (PST) X-Received: by 2002:a05:6a00:1741:b0:81f:852b:a934 with SMTP id d2e1a72fcca58-823215d88d0mr1995332b3a.24.1769196933553; Fri, 23 Jan 2026 11:35:33 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8231873e519sm2843206b3a.49.2026.01.23.11.35.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Jan 2026 11:35:33 -0800 (PST) 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, ajit.khaparde@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula , Rahul Gupta Subject: [v6, net-next 4/8] bng_en: Add TX support Date: Sat, 24 Jan 2026 01:05:00 +0530 Message-ID: <20260123193504.285573-5-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260123193504.285573-1-bhargava.marreddy@broadcom.com> References: <20260123193504.285573-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 functions to support xmit along with TSO/GSO. Also, add functions to handle TX completion events in the NAPI context. This commit introduces the fundamental transmit data path Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula Reviewed-by: Ajit Kumar Khaparde Reviewed-by: Rahul Gupta --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 100 ++++- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 3 + .../net/ethernet/broadcom/bnge/bnge_txrx.c | 366 +++++++++++++++++- .../net/ethernet/broadcom/bnge/bnge_txrx.h | 36 +- 4 files changed, 494 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 594e83759802..2c1df5d48b5e 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -393,9 +393,60 @@ static void bnge_free_rx_ring_pair_bufs(struct bnge_ne= t *bn) bnge_free_one_rx_ring_pair_bufs(bn, &bn->rx_ring[i]); } =20 +static void bnge_free_tx_skbs(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + u16 max_idx; + int i; + + max_idx =3D bn->tx_nr_pages * TX_DESC_CNT; + for (i =3D 0; i < bd->tx_nr_rings; i++) { + struct bnge_tx_ring_info *txr =3D &bn->tx_ring[i]; + int j; + + if (!txr->tx_buf_ring) + continue; + + for (j =3D 0; j < max_idx;) { + struct bnge_sw_tx_bd *tx_buf =3D &txr->tx_buf_ring[j]; + struct sk_buff *skb; + int k, last; + + skb =3D tx_buf->skb; + if (!skb) { + j++; + continue; + } + + tx_buf->skb =3D NULL; + + dma_unmap_single(bd->dev, + dma_unmap_addr(tx_buf, mapping), + skb_headlen(skb), + DMA_TO_DEVICE); + + last =3D tx_buf->nr_frags; + j +=3D 2; + for (k =3D 0; k < last; k++, j++) { + int ring_idx =3D j & bn->tx_ring_mask; + skb_frag_t *frag =3D &skb_shinfo(skb)->frags[k]; + + tx_buf =3D &txr->tx_buf_ring[ring_idx]; + dma_unmap_page(bd->dev, + dma_unmap_addr(tx_buf, mapping), + skb_frag_size(frag), + DMA_TO_DEVICE); + } + dev_kfree_skb(skb); + } + netdev_tx_reset_queue(netdev_get_tx_queue(bd->netdev, i)); + } +} + static void bnge_free_all_rings_bufs(struct bnge_net *bn) { bnge_free_rx_ring_pair_bufs(bn); + bnge_free_tx_skbs(bn); } =20 static void bnge_free_rx_rings(struct bnge_net *bn) @@ -1829,6 +1880,8 @@ static void bnge_enable_napi(struct bnge_net *bn) for (i =3D 0; i < bd->nq_nr_rings; i++) { struct bnge_napi *bnapi =3D bn->bnapi[i]; =20 + bnapi->tx_fault =3D 0; + napi_enable_locked(&bnapi->napi); } } @@ -2235,6 +2288,42 @@ static int bnge_init_nic(struct bnge_net *bn) return rc; } =20 +static void bnge_tx_disable(struct bnge_net *bn) +{ + struct bnge_tx_ring_info *txr; + int i; + + if (bn->tx_ring) { + for (i =3D 0; i < bn->bd->tx_nr_rings; i++) { + txr =3D &bn->tx_ring[i]; + WRITE_ONCE(txr->dev_state, BNGE_DEV_STATE_CLOSING); + } + } + /* Make sure napi polls see @dev_state change */ + synchronize_net(); + + if (!bn->netdev) + return; + /* Drop carrier first to prevent TX timeout */ + netif_carrier_off(bn->netdev); + /* Stop all TX queues */ + netif_tx_disable(bn->netdev); +} + +static void bnge_tx_enable(struct bnge_net *bn) +{ + struct bnge_tx_ring_info *txr; + int i; + + for (i =3D 0; i < bn->bd->tx_nr_rings; i++) { + txr =3D &bn->tx_ring[i]; + WRITE_ONCE(txr->dev_state, 0); + } + /* Make sure napi polls see @dev_state change */ + synchronize_net(); + netif_tx_wake_all_queues(bn->netdev); +} + static int bnge_open_core(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; @@ -2272,6 +2361,8 @@ static int bnge_open_core(struct bnge_net *bn) set_bit(BNGE_STATE_OPEN, &bd->state); =20 bnge_enable_int(bn); + + bnge_tx_enable(bn); return 0; =20 err_free_irq: @@ -2282,13 +2373,6 @@ static int bnge_open_core(struct bnge_net *bn) return rc; } =20 -static netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device = *dev) -{ - dev_kfree_skb_any(skb); - - return NETDEV_TX_OK; -} - static int bnge_open(struct net_device *dev) { struct bnge_net *bn =3D netdev_priv(dev); @@ -2311,6 +2395,8 @@ static void bnge_close_core(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; =20 + bnge_tx_disable(bn); + clear_bit(BNGE_STATE_OPEN, &bd->state); bnge_shutdown_nic(bn); bnge_disable_napi(bn); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 4cc69b6cf30c..d7cef5c5ba68 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -243,6 +243,8 @@ struct bnge_net { =20 unsigned long state; #define BNGE_STATE_NAPI_DISABLED 0 + + u32 msg_enable; }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 @@ -431,6 +433,7 @@ struct bnge_napi { #define BNGE_TX_EVENT 4 #define BNGE_REDIRECT_EVENT 8 #define BNGE_TX_CMP_EVENT 0x10 + u8 tx_fault:1; }; =20 #define INVALID_STATS_CTX_ID -1 diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index 5d16adf2315b..efd08c93008a 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -50,6 +50,23 @@ static void bnge_sched_reset_rxr(struct bnge_net *bn, rxr->rx_next_cons =3D 0xffff; } =20 +static void bnge_sched_reset_txr(struct bnge_net *bn, + struct bnge_tx_ring_info *txr, + u16 curr) +{ + struct bnge_napi *bnapi =3D txr->bnapi; + + if (bnapi->tx_fault) + return; + + netdev_err(bn->netdev, "Invalid Tx completion (ring:%d tx_hw_cons:%u cons= :%u prod:%u curr:%u)", + txr->txq_index, txr->tx_hw_cons, + txr->tx_cons, txr->tx_prod, curr); + WARN_ON_ONCE(1); + bnapi->tx_fault =3D 1; + /* TODO: Initiate reset task */ +} + void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a) { struct bnge_sw_rx_bd *cons_rx_buf, *prod_rx_buf; @@ -368,11 +385,86 @@ static int bnge_force_rx_discard(struct bnge_net *bn, return rc; } =20 +static void __bnge_tx_int(struct bnge_net *bn, struct bnge_tx_ring_info *t= xr, + int budget) +{ + u16 hw_cons =3D txr->tx_hw_cons; + struct bnge_dev *bd =3D bn->bd; + unsigned int tx_bytes =3D 0; + unsigned int tx_pkts =3D 0; + struct netdev_queue *txq; + u16 cons =3D txr->tx_cons; + skb_frag_t *frag; + + txq =3D netdev_get_tx_queue(bn->netdev, txr->txq_index); + + while (SW_TX_RING(bn, cons) !=3D hw_cons) { + struct bnge_sw_tx_bd *tx_buf; + struct sk_buff *skb; + int j, last; + + tx_buf =3D &txr->tx_buf_ring[SW_TX_RING(bn, cons)]; + skb =3D tx_buf->skb; + if (unlikely(!skb)) { + bnge_sched_reset_txr(bn, txr, cons); + return; + } + + cons =3D NEXT_TX(cons); + tx_pkts++; + tx_bytes +=3D skb->len; + tx_buf->skb =3D NULL; + + dma_unmap_single(bd->dev, dma_unmap_addr(tx_buf, mapping), + skb_headlen(skb), DMA_TO_DEVICE); + last =3D tx_buf->nr_frags; + + for (j =3D 0; j < last; j++) { + frag =3D &skb_shinfo(skb)->frags[j]; + cons =3D NEXT_TX(cons); + tx_buf =3D &txr->tx_buf_ring[SW_TX_RING(bn, cons)]; + netmem_dma_unmap_page_attrs(bd->dev, + dma_unmap_addr(tx_buf, + mapping), + skb_frag_size(frag), + DMA_TO_DEVICE, 0); + } + + cons =3D NEXT_TX(cons); + + napi_consume_skb(skb, budget); + } + + WRITE_ONCE(txr->tx_cons, cons); + + __netif_txq_completed_wake(txq, tx_pkts, tx_bytes, + bnge_tx_avail(bn, txr), bn->tx_wake_thresh, + (READ_ONCE(txr->dev_state) =3D=3D + BNGE_DEV_STATE_CLOSING)); +} + +static void bnge_tx_int(struct bnge_net *bn, struct bnge_napi *bnapi, + int budget) +{ + struct bnge_tx_ring_info *txr; + int i; + + bnge_for_each_napi_tx(i, bnapi, txr) { + if (txr->tx_hw_cons !=3D SW_TX_RING(bn, txr->tx_cons)) + __bnge_tx_int(bn, txr, budget); + } + + bnapi->events &=3D ~BNGE_TX_CMP_EVENT; +} + static void __bnge_poll_work_done(struct bnge_net *bn, struct bnge_napi *b= napi, int budget) { struct bnge_rx_ring_info *rxr =3D bnapi->rx_ring; =20 + if ((bnapi->events & BNGE_TX_CMP_EVENT) && !bnapi->tx_fault) + bnge_tx_int(bn, bnapi, budget); + if ((bnapi->events & BNGE_RX_EVENT)) { bnge_db_write(bn->bd, &rxr->rx_db, rxr->rx_prod); bnapi->events &=3D ~BNGE_RX_EVENT; @@ -445,9 +537,26 @@ static int __bnge_poll_work(struct bnge_net *bn, struc= t bnge_cp_ring_info *cpr, cmp_type =3D TX_CMP_TYPE(txcmp); if (cmp_type =3D=3D CMP_TYPE_TX_L2_CMP || cmp_type =3D=3D CMP_TYPE_TX_L2_COAL_CMP) { - /* - * Tx Compl Processing - */ + u32 opaque =3D txcmp->tx_cmp_opaque; + struct bnge_tx_ring_info *txr; + u16 tx_freed; + + txr =3D bnapi->tx_ring[TX_OPAQUE_RING(opaque)]; + event |=3D BNGE_TX_CMP_EVENT; + if (cmp_type =3D=3D CMP_TYPE_TX_L2_COAL_CMP) + txr->tx_hw_cons =3D TX_CMP_SQ_CONS_IDX(txcmp); + else + txr->tx_hw_cons =3D TX_OPAQUE_PROD(bn, opaque); + tx_freed =3D ((txr->tx_hw_cons - txr->tx_cons) & + bn->tx_ring_mask); + /* return full budget so NAPI will complete. */ + if (unlikely(tx_freed >=3D bn->tx_wake_thresh)) { + rx_pkts =3D budget; + raw_cons =3D NEXT_RAW_CMP(raw_cons); + if (budget) + cpr->has_more_work =3D 1; + break; + } } else if (cmp_type >=3D CMP_TYPE_RX_L2_CMP && cmp_type <=3D CMP_TYPE_RX_L2_TPA_START_V3_CMP) { if (likely(budget)) @@ -602,3 +711,254 @@ int bnge_napi_poll(struct napi_struct *napi, int budg= et) poll_done: return work_done; } + +static u16 bnge_xmit_get_cfa_action(struct sk_buff *skb) +{ + struct metadata_dst *md_dst =3D skb_metadata_dst(skb); + + if (!md_dst || md_dst->type !=3D METADATA_HW_PORT_MUX) + return 0; + + return md_dst->u.port_info.port_id; +} + +static const u16 bnge_lhint_arr[] =3D { + TX_BD_FLAGS_LHINT_512_AND_SMALLER, + TX_BD_FLAGS_LHINT_512_TO_1023, + TX_BD_FLAGS_LHINT_1024_TO_2047, + TX_BD_FLAGS_LHINT_1024_TO_2047, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, +}; + +static void bnge_txr_db_kick(struct bnge_net *bn, struct bnge_tx_ring_info= *txr, + u16 prod) +{ + /* Sync BD data before updating doorbell */ + wmb(); + bnge_db_write(bn->bd, &txr->tx_db, prod); + txr->kick_pending =3D 0; +} + +static u32 bnge_get_gso_hdr_len(struct sk_buff *skb) +{ + bool udp_gso =3D !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4); + u32 hdr_len; + + if (skb->encapsulation) { + if (udp_gso) + hdr_len =3D skb_inner_transport_offset(skb) + + sizeof(struct udphdr); + else + hdr_len =3D skb_inner_tcp_all_headers(skb); + } else if (udp_gso) { + hdr_len =3D skb_transport_offset(skb) + sizeof(struct udphdr); + } else { + hdr_len =3D skb_tcp_all_headers(skb); + } + + return hdr_len; +} + +netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + u32 len, free_size, vlan_tag_flags, cfa_action, flags; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_tx_ring_info *txr; + struct bnge_dev *bd =3D bn->bd; + struct bnge_sw_tx_bd *tx_buf; + struct tx_bd *txbd, *txbd0; + struct netdev_queue *txq; + struct tx_bd_ext *txbd1; + u16 prod, last_frag; + unsigned int length; + dma_addr_t mapping; + __le32 lflags =3D 0; + skb_frag_t *frag; + int i; + + i =3D skb_get_queue_mapping(skb); + txq =3D netdev_get_tx_queue(dev, i); + txr =3D &bn->tx_ring[bn->tx_ring_map[i]]; + prod =3D txr->tx_prod; + + free_size =3D bnge_tx_avail(bn, txr); + if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) { + /* We must have raced with NAPI cleanup */ + if (net_ratelimit() && txr->kick_pending) + netif_warn(bn, tx_err, dev, + "bnge: ring busy w/ flush pending!\n"); + if (!netif_txq_try_stop(txq, bnge_tx_avail(bn, txr), + bn->tx_wake_thresh)) + return NETDEV_TX_BUSY; + } + + if (unlikely(ipv6_hopopt_jumbo_remove(skb))) + goto tx_free; + + last_frag =3D skb_shinfo(skb)->nr_frags; + + txbd =3D &txr->tx_desc_ring[TX_RING(bn, prod)][TX_IDX(prod)]; + + tx_buf =3D &txr->tx_buf_ring[SW_TX_RING(bn, prod)]; + tx_buf->skb =3D skb; + tx_buf->nr_frags =3D last_frag; + + vlan_tag_flags =3D 0; + cfa_action =3D bnge_xmit_get_cfa_action(skb); + if (skb_vlan_tag_present(skb)) { + vlan_tag_flags =3D TX_BD_CFA_META_KEY_VLAN | + skb_vlan_tag_get(skb); + /* Currently supports 8021Q, 8021AD vlan offloads + * QINQ1, QINQ2, QINQ3 vlan headers are deprecated + */ + if (skb->vlan_proto =3D=3D htons(ETH_P_8021Q)) + vlan_tag_flags |=3D 1 << TX_BD_CFA_META_TPID_SHIFT; + } + + if (unlikely(skb->no_fcs)) + lflags |=3D cpu_to_le32(TX_BD_FLAGS_NO_CRC); + + if (eth_skb_pad(skb)) + goto tx_kick_pending; + + len =3D skb_headlen(skb); + + mapping =3D dma_map_single(bd->dev, skb->data, len, DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(bd->dev, mapping))) + goto tx_free; + + dma_unmap_addr_set(tx_buf, mapping, mapping); + flags =3D (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD | + TX_BD_CNT(last_frag + 2); + + txbd->tx_bd_haddr =3D cpu_to_le64(mapping); + txbd->tx_bd_opaque =3D SET_TX_OPAQUE(bn, txr, prod, 2 + last_frag); + + prod =3D NEXT_TX(prod); + txbd1 =3D (struct tx_bd_ext *) + &txr->tx_desc_ring[TX_RING(bn, prod)][TX_IDX(prod)]; + + if (skb_is_gso(skb)) { + u32 hdr_len =3D bnge_get_gso_hdr_len(skb); + + lflags |=3D cpu_to_le32(TX_BD_FLAGS_LSO | TX_BD_FLAGS_T_IPID | + (hdr_len << (TX_BD_HSIZE_SHIFT - 1))); + length =3D skb_shinfo(skb)->gso_size; + txbd1->tx_bd_mss =3D cpu_to_le32(length); + length +=3D hdr_len; + } else { + length =3D skb->len; + if (skb->ip_summed =3D=3D CHECKSUM_PARTIAL) { + lflags |=3D cpu_to_le32(TX_BD_FLAGS_TCP_UDP_CHKSUM); + txbd1->tx_bd_mss =3D 0; + } + } + + flags |=3D bnge_lhint_arr[length >> 9]; + + txbd->tx_bd_len_flags_type =3D cpu_to_le32(flags); + txbd1->tx_bd_hsize_lflags =3D lflags; + txbd1->tx_bd_cfa_meta =3D cpu_to_le32(vlan_tag_flags); + txbd1->tx_bd_cfa_action =3D + cpu_to_le32(cfa_action << TX_BD_CFA_ACTION_SHIFT); + txbd0 =3D txbd; + for (i =3D 0; i < last_frag; i++) { + frag =3D &skb_shinfo(skb)->frags[i]; + + prod =3D NEXT_TX(prod); + txbd =3D &txr->tx_desc_ring[TX_RING(bn, prod)][TX_IDX(prod)]; + + len =3D skb_frag_size(frag); + mapping =3D skb_frag_dma_map(bd->dev, frag, 0, len, + DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(bd->dev, mapping))) + goto tx_dma_error; + + tx_buf =3D &txr->tx_buf_ring[SW_TX_RING(bn, prod)]; + netmem_dma_unmap_addr_set(skb_frag_netmem(frag), tx_buf, + mapping, mapping); + + txbd->tx_bd_haddr =3D cpu_to_le64(mapping); + + flags =3D len << TX_BD_LEN_SHIFT; + txbd->tx_bd_len_flags_type =3D cpu_to_le32(flags); + } + + flags &=3D ~TX_BD_LEN; + txbd->tx_bd_len_flags_type =3D + cpu_to_le32(((len) << TX_BD_LEN_SHIFT) | flags | + TX_BD_FLAGS_PACKET_END); + + netdev_tx_sent_queue(txq, skb->len); + + prod =3D NEXT_TX(prod); + WRITE_ONCE(txr->tx_prod, prod); + + if (!netdev_xmit_more() || netif_xmit_stopped(txq)) { + bnge_txr_db_kick(bn, txr, prod); + } else { + if (free_size >=3D bn->tx_wake_thresh) + txbd0->tx_bd_len_flags_type |=3D + cpu_to_le32(TX_BD_FLAGS_NO_CMPL); + txr->kick_pending =3D 1; + } + + if (unlikely(bnge_tx_avail(bn, txr) <=3D MAX_SKB_FRAGS + 1)) { + if (netdev_xmit_more()) { + txbd0->tx_bd_len_flags_type &=3D + cpu_to_le32(~TX_BD_FLAGS_NO_CMPL); + bnge_txr_db_kick(bn, txr, prod); + } + + netif_txq_try_stop(txq, bnge_tx_avail(bn, txr), + bn->tx_wake_thresh); + } + return NETDEV_TX_OK; + +tx_dma_error: + last_frag =3D i; + + /* start back at beginning and unmap skb */ + prod =3D txr->tx_prod; + tx_buf =3D &txr->tx_buf_ring[SW_TX_RING(bn, prod)]; + dma_unmap_single(bd->dev, dma_unmap_addr(tx_buf, mapping), + skb_headlen(skb), DMA_TO_DEVICE); + prod =3D NEXT_TX(prod); + + /* unmap remaining mapped pages */ + for (i =3D 0; i < last_frag; i++) { + prod =3D NEXT_TX(prod); + tx_buf =3D &txr->tx_buf_ring[SW_TX_RING(bn, prod)]; + frag =3D &skb_shinfo(skb)->frags[i]; + netmem_dma_unmap_page_attrs(bd->dev, + dma_unmap_addr(tx_buf, mapping), + skb_frag_size(frag), + DMA_TO_DEVICE, 0); + } + +tx_free: + dev_kfree_skb_any(skb); + +tx_kick_pending: + if (txr->kick_pending) + bnge_txr_db_kick(bn, txr, txr->tx_prod); + txr->tx_buf_ring[SW_TX_RING(bn, txr->tx_prod)].skb =3D NULL; + dev_core_stats_tx_dropped_inc(dev); + return NETDEV_TX_OK; +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.h index 0d8db88529eb..81a24d8f9689 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h @@ -7,6 +7,34 @@ #include #include "bnge_netdev.h" =20 +static inline u32 bnge_tx_avail(struct bnge_net *bn, + const struct bnge_tx_ring_info *txr) +{ + u32 used =3D READ_ONCE(txr->tx_prod) - READ_ONCE(txr->tx_cons); + + return bn->tx_ring_size - (used & bn->tx_ring_mask); +} + +static inline void bnge_writeq_relaxed(struct bnge_dev *bd, u64 val, + void __iomem *addr) +{ +#if BITS_PER_LONG =3D=3D 32 + spin_lock(&bd->db_lock); + lo_hi_writeq_relaxed(val, addr); + spin_unlock(&bd->db_lock); +#else + writeq_relaxed(val, addr); +#endif +} + +/* For TX and RX ring doorbells with no ordering guarantee*/ +static inline void bnge_db_write_relaxed(struct bnge_net *bn, + struct bnge_db_info *db, u32 idx) +{ + bnge_writeq_relaxed(bn->bd, db->db_key64 | DB_RING_IDX(db, idx), + db->doorbell); +} + #define TX_OPAQUE_IDX_MASK 0x0000ffff #define TX_OPAQUE_BDS_MASK 0x00ff0000 #define TX_OPAQUE_BDS_SHIFT 16 @@ -24,6 +52,11 @@ TX_OPAQUE_BDS_SHIFT) #define TX_OPAQUE_PROD(bn, opq) ((TX_OPAQUE_IDX(opq) + TX_OPAQUE_BDS(opq))= &\ (bn)->tx_ring_mask) +#define TX_BD_CNT(n) (((n) << TX_BD_FLAGS_BD_CNT_SHIFT) & TX_BD_FLAGS_BD_C= NT) + +#define TX_MAX_BD_CNT 32 + +#define TX_MAX_FRAGS (TX_MAX_BD_CNT - 2) =20 /* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one ext= ra * BD because the first TX BD is always a long BD. @@ -68,7 +101,7 @@ #define RING_RX_AGG(bn, idx) ((idx) & (bn)->rx_agg_ring_mask) #define NEXT_RX_AGG(idx) ((idx) + 1) =20 -#define RING_TX(bn, idx) ((idx) & (bn)->tx_ring_mask) +#define SW_TX_RING(bn, idx) ((idx) & (bn)->tx_ring_mask) #define NEXT_TX(idx) ((idx) + 1) =20 #define ADV_RAW_CMP(idx, n) ((idx) + (n)) @@ -83,6 +116,7 @@ RX_CMPL_CFA_CODE_MASK) >> RX_CMPL_CFA_CODE_SFT) =20 irqreturn_t bnge_msix(int irq, void *dev_instance); +netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device *dev); void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a); int bnge_napi_poll(struct napi_struct *napi, int budget); #endif /* _BNGE_TXRX_H_ */ --=20 2.47.3 From nobody Sat Feb 7 09:29:52 2026 Received: from mail-yw1-f225.google.com (mail-yw1-f225.google.com [209.85.128.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 2FA0A1F75A6 for ; Fri, 23 Jan 2026 19:35:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.225 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196942; cv=none; b=l/owS6ifWM7tbFmV/6q6pFiLj7ZIdpURgqJivMRD3oHreyz4dne+S67m1/FSk4ko0zrwV7JTLdfaSiRIXOv4HfI3iLO0QZJ8gm17gPMgto0wQkSRUFPHlmvAZ+7QChBzS8iJgD2SjlYXvN/RU6lsLT1tu+RsWdyLM3uwE/hqw6I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196942; c=relaxed/simple; bh=+Zc6l/SwHKnLCayJhbpyWDPUKoNOWSCBVYgFGpSy/3E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Xz2Uj9RZfyglza9REr/Puqu5hVLqZiK63s0GdTU6srw7HqYx8GzocjM3jEUEIeNNgxnWa1WHOqpYnu8LKjl+1UJwjla64H2FwyXreLISyk48gnt6dQRS9CeAQPFi8wAc1+7DZKGyHmXKm9gG4hZ8HoMbRFrLywmTxN/TZc9y9Hg= 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=Y42DBoai; arc=none smtp.client-ip=209.85.128.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="Y42DBoai" Received: by mail-yw1-f225.google.com with SMTP id 00721157ae682-78fdb90b670so24714857b3.2 for ; Fri, 23 Jan 2026 11:35:40 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769196940; x=1769801740; 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=PdLE4jDYZgc7is6bLs44R3LFutP/tV6g4ht/06BO8G0=; b=wJXdrvz9J6/sr4lNB/uLS0Fg/6gD4JgKrzDkxY7kuEWECsNvbLVhRcczKAXwmDK6yV dUs30Mk/YPbqcmDoQ+lAdjjBjz7xmSrDiEc9EPw2ScR5LXgvTHAT2g5kwehHINvsFBen krB/TMb7aigdvlvxdepnndArJWjoVEct6HkFlFoRSwVwkmrihqdgHn1jAMQUcTxrNqro kFurQFXG7kXhNd4w5QnnC3mstZ79p6PExq7zpw6mQ1JapzSA0av6cya+fccGaakODsfD BGKvF4JUArL107KmroZrwpjRXYWOzzs7PBLAT82+lSuPsOx4fUN2tcPgpelD7YbD5JcL KFtw== X-Forwarded-Encrypted: i=1; AJvYcCUC+PUlquAQCFfd8gQi3ofOj+dUZCAcdusZU/8Dm9hyfMFthXKTno++uv+m9Ir+DJ+OiAiDWaszRFSIv84=@vger.kernel.org X-Gm-Message-State: AOJu0YyrRf9IbHWu7Fgv26fkbSuQhzTyjqqnADYh/NuSsi7Vd38RKQ+I DzF6JBVxbkcsZBmITHrX9CSPj85ZSkUpyc+TIGCp1ZIpYn88wlmEwjrfW1ALWzXmS+2Ib4J22D7 SItz6H3rssCnN4suHao4xXtb5c6fOpZV/m05gpybHJD/Ii/zNEZ30nk3dVhHmp0QQJP9pFRcb6E uzha6O6GjTGNJ5RtJQBCAnPeHKtTGOzYxRvPqeDLvY9klahKXkMRwxz26P6+TAJoXlO/0GushVZ keqDuGu5RSrjZFg4nd+mrL+Cw== X-Gm-Gg: AZuq6aIYR/HOgy880gUysC8JRBl5Hw1MZAfG070+A+6eOEDXkkpOzkEQQhdPAn7Wrz0 IVivtcprjykfzl9OBtCScWI1OGnM3fIeT3NLfY7n2Ofh6thHXUJkPNu8LOerDfw+bquX9kMilfM x3+60tpbGIdEXCNmciJEz4iL+nckCu6mMFsFkPuuLF5+jpJHNuC9cC3orVmZJSv6ze/ZaYehlYe 5AABVCK0B1GtMwNj1S2l3QNx9nGyFxD35PjKvKtyUC0VWUXgqrz0jcvF2/SKhHZxVw8djPVw+Aq 2M2W4qhZzPvC7RCBxKWOu793p2pXAc8p9it7j0qxRUsx7i18Te27G+MUCq8DB/xX99gS81Z/VON Bobvb14nDO+5La/NRxu9JQxXdyEUuYH5LwJqao8KQ+inKCAQFsyLy7Mv+gfOPO2yB6L3RKnG22J YiWpnoGWhD3cN3f7lNP5MCNeROn+/hr2ISJUwP72q6hNu6vpjd2JmDCA== X-Received: by 2002:a05:690c:d96:b0:784:ad94:ac70 with SMTP id 00721157ae682-794398ecc3cmr34391087b3.9.1769196940028; Fri, 23 Jan 2026 11:35:40 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-100.dlp.protect.broadcom.com. [144.49.247.100]) by smtp-relay.gmail.com with ESMTPS id 00721157ae682-7943af0ebd0sm1728477b3.1.2026.01.23.11.35.39 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Jan 2026 11:35:40 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pf1-f199.google.com with SMTP id d2e1a72fcca58-81e81fbbb8cso2554100b3a.3 for ; Fri, 23 Jan 2026 11:35:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1769196939; x=1769801739; 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=PdLE4jDYZgc7is6bLs44R3LFutP/tV6g4ht/06BO8G0=; b=Y42DBoai0Kdqc/pRM6btFJou6qh553VMDaFOiw30TCsmjSAp9Jt708kVFrceAP54B4 dSl8zslAnE+cPlc8uGE3X+ejOwi0i2l5qKnmVfcIybqtb3XM0JTXDuOQKN/oYTUkGRY1 VWgjuaHdzpi18p5t8eCbQPaZOD49qAjeh11lM= X-Forwarded-Encrypted: i=1; AJvYcCVJAqkrTBKUZo0lrvaTxzdkWUyCZQh2WMbPL+7+2RbVAgzzIx1GNHqfXLdZxcz1SoUdCJLemRAqEG97MD4=@vger.kernel.org X-Received: by 2002:a05:6a00:1790:b0:81e:b2ba:5b3a with SMTP id d2e1a72fcca58-82317c13039mr3557632b3a.8.1769196938357; Fri, 23 Jan 2026 11:35:38 -0800 (PST) X-Received: by 2002:a05:6a00:1790:b0:81e:b2ba:5b3a with SMTP id d2e1a72fcca58-82317c13039mr3557611b3a.8.1769196937837; Fri, 23 Jan 2026 11:35:37 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8231873e519sm2843206b3a.49.2026.01.23.11.35.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Jan 2026 11:35:37 -0800 (PST) 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, ajit.khaparde@broadcom.com, Bhargava Marreddy , Rahul Gupta Subject: [v6, net-next 5/8] bng_en: Add ndo_features_check support Date: Sat, 24 Jan 2026 01:05:01 +0530 Message-ID: <20260123193504.285573-6-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260123193504.285573-1-bhargava.marreddy@broadcom.com> References: <20260123193504.285573-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 ndo_features_check to validate hardware constraints per-packet: - Disable SG if nr_frags exceeds hardware limit. - Disable GSO if packet/fragment length exceeds supported maximum. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Ajit Kumar Khaparde Reviewed-by: Rahul Gupta --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 1 + .../net/ethernet/broadcom/bnge/bnge_txrx.c | 24 +++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_txrx.h | 3 +++ 3 files changed, 28 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 2c1df5d48b5e..2c8f8949d500 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -2420,6 +2420,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_features_check =3D bnge_features_check, }; =20 static void bnge_init_mac_addr(struct bnge_dev *bd) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index efd08c93008a..33f39a57f12d 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -962,3 +962,27 @@ netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struc= t net_device *dev) dev_core_stats_tx_dropped_inc(dev); return NETDEV_TX_OK; } + +netdev_features_t bnge_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) +{ + u32 len; + + features =3D vlan_features_check(skb, features); +#if (MAX_SKB_FRAGS > TX_MAX_FRAGS) + if (skb_shinfo(skb)->nr_frags > TX_MAX_FRAGS) + features &=3D ~NETIF_F_SG; +#endif + + if (skb_is_gso(skb)) + len =3D bnge_get_gso_hdr_len(skb) + skb_shinfo(skb)->gso_size; + else + len =3D skb->len; + + len >>=3D 9; + if (unlikely(len >=3D ARRAY_SIZE(bnge_lhint_arr))) + features &=3D ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); + + return features; +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.h index 81a24d8f9689..32be5eb46870 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h @@ -119,4 +119,7 @@ irqreturn_t bnge_msix(int irq, void *dev_instance); netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device *dev); void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a); int bnge_napi_poll(struct napi_struct *napi, int budget); +netdev_features_t bnge_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features); #endif /* _BNGE_TXRX_H_ */ --=20 2.47.3 From nobody Sat Feb 7 09:29:52 2026 Received: from mail-ot1-f98.google.com (mail-ot1-f98.google.com [209.85.210.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 2667C2BDC3E for ; Fri, 23 Jan 2026 19:35:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.98 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196948; cv=none; b=mueFtqLZggZ9asCJ+BdegiAqE6/clrl265j8UDmiM+OverjyL9y3UipA3XHF4fnqEpTbaHmY+Pzca1rq9A3ZACB6YamaUouo93vWGqTaJHxoQjRzrtRZO3E+Xkjag6OvkIcMqV1LSF6TfJEaYsX2069t3PUL6j2M36Z0LnH0ZxA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196948; c=relaxed/simple; bh=+426l+HxRyq3a7RSISVqDALXB+wvYRf//cVq+Ymj6vg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oeHDtuG5ftXveXKymi6k0cS4RdtRrpJYmNQSKqnC7HgGgKvVHCQBMpfAPqipE5MAdAXjzb9qjY+e7QYBwQrvxs+13HXDpoecAziFXLEtCFRxV3mDeG22TXLn5j908qemY12RO8V9LNXwmPACTviWt/S5z71EO8VQP4CUVo/ZKBA= 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=WQacgNma; arc=none smtp.client-ip=209.85.210.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="WQacgNma" Received: by mail-ot1-f98.google.com with SMTP id 46e09a7af769-7d148dd3421so924219a34.0 for ; Fri, 23 Jan 2026 11:35:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769196945; x=1769801745; 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=k2PNNrzYfwF6RJOlif8UuJP8LkFjNKReEQi+5VZis0Q=; b=W4QwbPm2Rj2wZIRScFssNXVsplc0egzHuICZqCsRrUbcQ90UiEX7SJVuINTICxXdiW 9JTh+5Us5PCSNqnoUZtuAWfZc8fUTGrSvAXyii/w9TsrtlQBiGSLl3wfVxWRx2f9gE4J ipVtmsE2bXTu4h/bbNGjQrigPTfCH0z8t0yATDip5o5S+b45OYZYD8H/KKG3f8mAn+G4 0WWQjkIa0ognR9breRPnQuQMcW0hw5AKHyckL768sNtM+seqclL4iAsaoe8ezHsoVtjJ W5yWCRVWtlmDpbYmmYsPtz2JtwE9qYAaHUhqUPgfoxsSlnj+YhoFPzScw7YlU0tASETT m4nQ== X-Forwarded-Encrypted: i=1; AJvYcCXUWVbyA5sjl62YyGI6R+H4cqebbpWxP5tOsePd1L5qgRGbXih7Dj77lbeYxd8C1hYjFbwhIFA1ePVtIYk=@vger.kernel.org X-Gm-Message-State: AOJu0YyZf8Qi9DiP9I/0WFtz8x4UyTyY+VDZtwlk7cK3sZ/RSEBGW8Nb DJRfzLH22L2i8zzDPXVFWGryvaUya8xy8Td+4flJhAPSoaDZgIrek24ctzZKY0cIwlllARcT9cg R6HBUvIKTQ10pUPDk07ULW/+HxpEBREI2slRlMyXFUcLGqPjtWenL2QhkAcHgJphXPVIdDQQr4n YxcwrYSdssMC46Xxh1Sqw49rE7LHDgr7UMmhKGh3Qo+Yjzr4laF1jevip+HppYI8xJ57KCJbwm3 +/m8LaKFG6PbD+EyqtyC5YM0g== X-Gm-Gg: AZuq6aIr/Rrk1qGVItmBiDlP/+GHiPWWtx5/2Pwod5Gqqn/PjqznJA17/tx4CLDmLIc VxmkKBm482HGGWXMZHFY+FXEPrWKtYiURzfp+LHIDOieh2OrE5+gvQScFG4WJraKpFEgFsW27ky ythU6uWVxm0QaXRrPXSNIL97LJ37UkUmp7Si/iDawSJ16EUHcj8GTIGZZhnplr4ik0ml7Amctzx zLqlB3kCLLzYNF9GpKcbNcL77pt8XIRN6s1bj6WrlDzSeGKMcP4OgGBsifGO+cVj47xzu94DW54 woJO3/W7WC6iuSinOfIveQVEOZjV4JUERSIx2stok3ldWQE+NTJOZKSzOSWZ1OYmDSTVACTcZMB Mve5IreoLSKrEbACfWemTiRml6a3SjvdJT0XwY/2DTPwdBiRXro9ruwNWBqSGGcsDe5zuobp0tG SwxoOCDPm91CzRqA0SjMwtU82iCdx63aIc60rYOJuwNCAfyYYvdl5BaA== X-Received: by 2002:a05:6830:3687:b0:7cf:e312:1ab4 with SMTP id 46e09a7af769-7d15a62312dmr2232169a34.19.1769196944917; Fri, 23 Jan 2026 11:35:44 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-102.dlp.protect.broadcom.com. [144.49.247.102]) by smtp-relay.gmail.com with ESMTPS id 46e09a7af769-7d15b3c052fsm523616a34.8.2026.01.23.11.35.44 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Jan 2026 11:35:44 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pf1-f198.google.com with SMTP id d2e1a72fcca58-81c68fef4d4so4759786b3a.2 for ; Fri, 23 Jan 2026 11:35:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1769196943; x=1769801743; 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=k2PNNrzYfwF6RJOlif8UuJP8LkFjNKReEQi+5VZis0Q=; b=WQacgNmadqk7Q45/fKxDfaSfOsURMR5eq/MLEqKwKbfSOht/Cd9xaeCFGu6u2tjHti CwbKW1E3SOojr+Qiz39m9wQOU6NXa/EHAw5R8S6veW5vVPyXaIFY5YySHzkExGp/9SHC b6FpG238P7M2HRL98Ej2QyfV4W/J7t27y9zoc= X-Forwarded-Encrypted: i=1; AJvYcCVtDR8x4qoefalfOoYMrHMBRVRoySLIWh/x5Wg5q1FPE0DBDEQrXMsdrpBHCvGGppLG/sHvELbJwYOjSK4=@vger.kernel.org X-Received: by 2002:a05:6a00:3d51:b0:823:1252:9428 with SMTP id d2e1a72fcca58-82317d937femr3300342b3a.9.1769196942730; Fri, 23 Jan 2026 11:35:42 -0800 (PST) X-Received: by 2002:a05:6a00:3d51:b0:823:1252:9428 with SMTP id d2e1a72fcca58-82317d937femr3300319b3a.9.1769196942157; Fri, 23 Jan 2026 11:35:42 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8231873e519sm2843206b3a.49.2026.01.23.11.35.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Jan 2026 11:35:41 -0800 (PST) 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, ajit.khaparde@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v6, net-next 6/8] bng_en: Add support to handle AGG events Date: Sat, 24 Jan 2026 01:05:02 +0530 Message-ID: <20260123193504.285573-7-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260123193504.285573-1-bhargava.marreddy@broadcom.com> References: <20260123193504.285573-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 AGG event handling in the RX path to receive packet data on AGG rings. This enables Jumbo and HDS functionality. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_hw_def.h | 14 ++ .../net/ethernet/broadcom/bnge/bnge_netdev.c | 17 +- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 5 + .../net/ethernet/broadcom/bnge/bnge_txrx.c | 223 +++++++++++++++++- .../net/ethernet/broadcom/bnge/bnge_txrx.h | 1 + 5 files changed, 250 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h b/drivers/net= /ethernet/broadcom/bnge/bnge_hw_def.h index 0e28352f41f2..d2c2acf44e82 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h @@ -139,6 +139,20 @@ struct rx_cmp_ext { __le32 rx_cmp_timestamp; }; =20 +#define RX_AGG_CMP_TYPE GENMASK(5, 0) +#define RX_AGG_CMP_LEN GENMASK(31, 16) +#define RX_AGG_CMP_LEN_SHIFT 16 +#define RX_AGG_CMP_V BIT(0) +#define RX_AGG_CMP_AGG_ID GENMASK(31, 16) +#define RX_AGG_CMP_AGG_ID_SHIFT 16 + +struct rx_agg_cmp { + __le32 rx_agg_cmp_len_flags_type; + u32 rx_agg_cmp_opaque; + __le32 rx_agg_cmp_v; + __le32 rx_agg_cmp_unused; +}; + #define RX_CMP_L2_ERRORS \ cpu_to_le32(RX_CMPL_ERRORS_BUFFER_ERROR_MASK | RX_CMPL_ERRORS_CRC_ERROR) =20 diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 2c8f8949d500..5b0e326c5056 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -979,9 +982,9 @@ static netmem_ref __bnge_alloc_rx_netmem(struct bnge_ne= t *bn, return netmem; } =20 -static u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dma_addr_t *mapping, - struct bnge_rx_ring_info *rxr, - gfp_t gfp) +u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dma_addr_t *mapping, + struct bnge_rx_ring_info *rxr, + gfp_t gfp) { unsigned int offset; struct page *page; @@ -1048,7 +1051,7 @@ static int bnge_alloc_one_rx_ring_bufs(struct bnge_ne= t *bn, return 0; } =20 -static u16 bnge_find_next_agg_idx(struct bnge_rx_ring_info *rxr, u16 idx) +u16 bnge_find_next_agg_idx(struct bnge_rx_ring_info *rxr, u16 idx) { u16 next, max =3D rxr->rx_agg_bmap_size; =20 @@ -1058,9 +1061,9 @@ static u16 bnge_find_next_agg_idx(struct bnge_rx_ring= _info *rxr, u16 idx) return next; } =20 -static int bnge_alloc_rx_netmem(struct bnge_net *bn, - struct bnge_rx_ring_info *rxr, - u16 prod, gfp_t gfp) +int bnge_alloc_rx_netmem(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr, + u16 prod, gfp_t gfp) { struct bnge_sw_rx_agg_bd *rx_agg_buf; u16 sw_prod =3D rxr->rx_sw_agg_prod; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index d7cef5c5ba68..ee036ce63655 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -514,4 +514,9 @@ u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr); void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic= ); int bnge_alloc_rx_data(struct bnge_net *bn, struct bnge_rx_ring_info *rxr, u16 prod, gfp_t gfp); +u16 bnge_find_next_agg_idx(struct bnge_rx_ring_info *rxr, u16 idx); +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); #endif /* _BNGE_NETDEV_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index 33f39a57f12d..363f835438f4 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,191 @@ irqreturn_t bnge_msix(int irq, void *dev_instance) return IRQ_HANDLED; } =20 +static struct rx_agg_cmp *bnge_get_agg(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u16 cp_cons, u16 curr) +{ + struct rx_agg_cmp *agg; + + cp_cons =3D RING_CMP(bn, ADV_RAW_CMP(cp_cons, curr)); + agg =3D (struct rx_agg_cmp *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + return agg; +} + +static void bnge_reuse_rx_agg_bufs(struct bnge_cp_ring_info *cpr, u16 idx, + u16 start, u32 agg_bufs) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + struct bnge_net *bn =3D bnapi->bn; + struct bnge_rx_ring_info *rxr; + u16 prod, sw_prod; + u32 i; + + rxr =3D bnapi->rx_ring; + sw_prod =3D rxr->rx_sw_agg_prod; + prod =3D rxr->rx_agg_prod; + + for (i =3D 0; i < agg_bufs; i++) { + struct bnge_sw_rx_agg_bd *cons_rx_buf, *prod_rx_buf; + struct rx_agg_cmp *agg; + struct rx_bd *prod_bd; + netmem_ref netmem; + u16 cons; + + agg =3D bnge_get_agg(bn, cpr, idx, start + i); + cons =3D agg->rx_agg_cmp_opaque; + __clear_bit(cons, rxr->rx_agg_bmap); + + if (unlikely(test_bit(sw_prod, rxr->rx_agg_bmap))) + sw_prod =3D bnge_find_next_agg_idx(rxr, sw_prod); + + __set_bit(sw_prod, rxr->rx_agg_bmap); + prod_rx_buf =3D &rxr->rx_agg_buf_ring[sw_prod]; + cons_rx_buf =3D &rxr->rx_agg_buf_ring[cons]; + + /* It is possible for sw_prod to be equal to cons, so + * set cons_rx_buf->netmem to 0 first. + */ + netmem =3D cons_rx_buf->netmem; + cons_rx_buf->netmem =3D 0; + prod_rx_buf->netmem =3D netmem; + prod_rx_buf->offset =3D cons_rx_buf->offset; + + prod_rx_buf->mapping =3D cons_rx_buf->mapping; + + prod_bd =3D &rxr->rx_agg_desc_ring[RX_AGG_RING(bn, prod)] + [RX_IDX(prod)]; + + prod_bd->rx_bd_haddr =3D cpu_to_le64(cons_rx_buf->mapping); + prod_bd->rx_bd_opaque =3D sw_prod; + + prod =3D NEXT_RX_AGG(prod); + sw_prod =3D RING_RX_AGG(bn, NEXT_RX_AGG(sw_prod)); + } + rxr->rx_agg_prod =3D prod; + rxr->rx_sw_agg_prod =3D sw_prod; +} + +static int bnge_agg_bufs_valid(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u8 agg_bufs, u32 *raw_cons) +{ + struct rx_agg_cmp *agg; + u16 last; + + *raw_cons =3D ADV_RAW_CMP(*raw_cons, agg_bufs); + last =3D RING_CMP(bn, *raw_cons); + agg =3D (struct rx_agg_cmp *) + &cpr->desc_ring[CP_RING(last)][CP_IDX(last)]; + return RX_AGG_CMP_VALID(bn, agg, *raw_cons); +} + +static int bnge_discard_rx(struct bnge_net *bn, struct bnge_cp_ring_info *= cpr, + u32 *raw_cons, void *cmp) +{ + u32 tmp_raw_cons =3D *raw_cons; + struct rx_cmp *rxcmp =3D cmp; + u8 cmp_type, agg_bufs =3D 0; + + cmp_type =3D RX_CMP_TYPE(rxcmp); + + if (cmp_type =3D=3D CMP_TYPE_RX_L2_CMP) { + agg_bufs =3D (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & + RX_CMP_AGG_BUFS) >> + RX_CMP_AGG_BUFS_SHIFT; + } + + if (agg_bufs) { + if (!bnge_agg_bufs_valid(bn, cpr, agg_bufs, &tmp_raw_cons)) + return -EBUSY; + } + *raw_cons =3D tmp_raw_cons; + return 0; +} + +static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u16 idx, u32 agg_bufs, + struct sk_buff *skb) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + struct skb_shared_info *shinfo; + struct bnge_rx_ring_info *rxr; + u32 i, total_frag_len =3D 0; + u16 prod; + + rxr =3D bnapi->rx_ring; + prod =3D rxr->rx_agg_prod; + shinfo =3D skb_shinfo(skb); + + for (i =3D 0; i < agg_bufs; i++) { + struct bnge_sw_rx_agg_bd *cons_rx_buf; + struct rx_agg_cmp *agg; + u16 cons, frag_len; + netmem_ref netmem; + + agg =3D bnge_get_agg(bn, cpr, idx, i); + cons =3D agg->rx_agg_cmp_opaque; + frag_len =3D (le32_to_cpu(agg->rx_agg_cmp_len_flags_type) & + RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT; + + cons_rx_buf =3D &rxr->rx_agg_buf_ring[cons]; + skb_add_rx_frag_netmem(skb, i, cons_rx_buf->netmem, + cons_rx_buf->offset, + frag_len, BNGE_RX_PAGE_SIZE); + __clear_bit(cons, rxr->rx_agg_bmap); + + /* It is possible for bnge_alloc_rx_netmem() to allocate + * a sw_prod index that equals the cons index, so we + * need to clear the cons entry now. + */ + netmem =3D cons_rx_buf->netmem; + cons_rx_buf->netmem =3D 0; + + if (bnge_alloc_rx_netmem(bn, rxr, prod, GFP_ATOMIC) !=3D 0) { + skb->len -=3D frag_len; + skb->data_len -=3D frag_len; + skb->truesize -=3D BNGE_RX_PAGE_SIZE; + + --shinfo->nr_frags; + cons_rx_buf->netmem =3D netmem; + + /* Update prod since possibly some netmems have been + * allocated already. + */ + rxr->rx_agg_prod =3D prod; + bnge_reuse_rx_agg_bufs(cpr, idx, i, agg_bufs - i); + return 0; + } + + page_pool_dma_sync_netmem_for_cpu(rxr->page_pool, netmem, 0, + BNGE_RX_PAGE_SIZE); + + total_frag_len +=3D frag_len; + prod =3D NEXT_RX_AGG(prod); + } + rxr->rx_agg_prod =3D prod; + return total_frag_len; +} + +static struct sk_buff *bnge_rx_agg_netmems_skb(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + struct sk_buff *skb, u16 idx, + u32 agg_bufs) +{ + u32 total_frag_len; + + total_frag_len =3D __bnge_rx_agg_netmems(bn, cpr, idx, agg_bufs, skb); + if (!total_frag_len) { + skb_mark_for_recycle(skb); + dev_kfree_skb(skb); + return NULL; + } + + return skb; +} + static void bnge_sched_reset_rxr(struct bnge_net *bn, struct bnge_rx_ring_info *rxr) { @@ -221,15 +407,16 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bn= ge_cp_ring_info *cpr, struct bnge_napi *bnapi =3D cpr->bnapi; struct net_device *dev =3D bn->netdev; struct bnge_rx_ring_info *rxr; + u32 tmp_raw_cons, flags, misc; struct bnge_sw_rx_bd *rx_buf; struct rx_cmp_ext *rxcmp1; u16 cons, prod, cp_cons; - u32 tmp_raw_cons, flags; u8 *data_ptr, cmp_type; struct rx_cmp *rxcmp; dma_addr_t dma_addr; struct sk_buff *skb; unsigned int len; + u8 agg_bufs; void *data; int rc =3D 0; =20 @@ -258,11 +445,15 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bn= ge_cp_ring_info *cpr, =20 cons =3D rxcmp->rx_cmp_opaque; if (unlikely(cons !=3D rxr->rx_next_cons)) { + int rc1 =3D bnge_discard_rx(bn, cpr, &tmp_raw_cons, rxcmp); + /* 0xffff is forced error, don't print it */ if (rxr->rx_next_cons !=3D 0xffff) netdev_warn(bn->netdev, "RX cons %x !=3D expected cons %x\n", cons, rxr->rx_next_cons); bnge_sched_reset_rxr(bn, rxr); + if (rc1) + return rc1; goto next_rx_no_prod_no_len; } rx_buf =3D &rxr->rx_buf_ring[cons]; @@ -270,11 +461,23 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bn= ge_cp_ring_info *cpr, data_ptr =3D rx_buf->data_ptr; prefetch(data_ptr); =20 + misc =3D le32_to_cpu(rxcmp->rx_cmp_misc_v1); + agg_bufs =3D (misc & RX_CMP_AGG_BUFS) >> RX_CMP_AGG_BUFS_SHIFT; + + if (agg_bufs) { + if (!bnge_agg_bufs_valid(bn, cpr, agg_bufs, &tmp_raw_cons)) + return -EBUSY; + + cp_cons =3D NEXT_CMP(bn, cp_cons); + *event |=3D BNGE_AGG_EVENT; + } *event |=3D BNGE_RX_EVENT; =20 rx_buf->data =3D NULL; if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L2_ERRORS) { bnge_reuse_rx_data(rxr, cons, data); + if (agg_bufs) + bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs); rc =3D -EIO; goto next_rx_no_len; } @@ -286,10 +489,19 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bn= ge_cp_ring_info *cpr, if (len <=3D bn->rx_copybreak) { skb =3D bnge_copy_skb(bnapi, data_ptr, len, dma_addr); bnge_reuse_rx_data(rxr, cons, data); - if (!skb) - goto oom_next_rx; } else { skb =3D bnge_rx_skb(bn, rxr, cons, data, data_ptr, dma_addr, len); + } + + if (!skb) { + if (agg_bufs) + bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs); + goto oom_next_rx; + } + + if (agg_bufs) { + skb =3D bnge_rx_agg_netmems_skb(bn, cpr, skb, cp_cons, + agg_bufs); if (!skb) goto oom_next_rx; } @@ -469,6 +681,11 @@ static void __bnge_poll_work_done(struct bnge_net *bn,= struct bnge_napi *bnapi, bnge_db_write(bn->bd, &rxr->rx_db, rxr->rx_prod); bnapi->events &=3D ~BNGE_RX_EVENT; } + + if (bnapi->events & BNGE_AGG_EVENT) { + bnge_db_write(bn->bd, &rxr->rx_agg_db, rxr->rx_agg_prod); + bnapi->events &=3D ~BNGE_AGG_EVENT; + } } =20 static void diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.h index 32be5eb46870..2a17ff639100 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h @@ -107,6 +107,7 @@ static inline void bnge_db_write_relaxed(struct bnge_ne= t *bn, #define ADV_RAW_CMP(idx, n) ((idx) + (n)) #define NEXT_RAW_CMP(idx) ADV_RAW_CMP(idx, 1) #define RING_CMP(bn, idx) ((idx) & (bn)->cp_ring_mask) +#define NEXT_CMP(bn, idx) RING_CMP(bn, ADV_RAW_CMP(idx, 1)) =20 #define RX_CMP_ITYPES(rxcmp) \ (le32_to_cpu((rxcmp)->rx_cmp_len_flags_type) & RX_CMP_FLAGS_ITYPES_MASK) --=20 2.47.3 From nobody Sat Feb 7 09:29:52 2026 Received: from mail-yw1-f228.google.com (mail-yw1-f228.google.com [209.85.128.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 1EABD2D9792 for ; Fri, 23 Jan 2026 19:35:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196952; cv=none; b=Q11tJ+WiMszsqhjZVJl7M4qIkG691KDxlffA6bjJLOcOiwWLx4uw3i/ZX26CZ0tBUmLL0Lvwpbrp+RjHMFUXMMZbCu8AgdM2C9LfnTYZsumU/z4b1LMhYizqeWZPvqPEGUvj9PfXtPPooqHYyg/PikXyuhosNvwMZb+OxovvcmM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196952; c=relaxed/simple; bh=IDtYlfyHd9puO8uzddW7kcDwMbhw00sKaMmn1ogyjtE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kBVxmgy6Vik3gWZ+0pNHYIQ8ogHL91Ip0qW9CgdqjL6wb38Gjgk085zEUTkrhK4zn5+4JEp5kB6upvx+yvitQkBnetEmjXRYQ2RZv+3C06V2ZVwbJP4GoPk+jnNFm6ltFyPGnRNWA5Kar9CODemUyEh0f20aXAkGjo3l7za94GM= 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=dfwI2u9C; arc=none smtp.client-ip=209.85.128.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="dfwI2u9C" Received: by mail-yw1-f228.google.com with SMTP id 00721157ae682-79414ab1497so24442487b3.1 for ; Fri, 23 Jan 2026 11:35:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769196949; x=1769801749; 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=l5OU/RLBNz5QlYQHo4MnTuUpoycaD8XZR+hOfHOhW5Q=; b=gxbMhrEP6yfWUIWf5u9J1askQ8Rt3SBe3pY2WX7dE/uaZgKqFz+tRDKIUi7QBdFvko S2CqTZzHBx1dKbRbk6XMm/vN781LQK4fcX6LlyzNsJ+ze0JrNBHsBmAoo+bsPOh/Kfs7 oCICwRFPvS4sF1YdksmrxAmB1+7QAt3J+3tL0uOcNpMCwAShdDBp0V9WBesrlP0MCdz1 cf2lk+oeCA4qcVozMX7X+4YANFZsgl6UvkOvRsGl2MDUz8vhKNuEq+CRitgDhlxLzEl7 p9S6xSoUY0Wn1A7mmB1kAGZ8gB7rizmc1iVHvD67EXFcacrTdnVyKcuWFjYNcNBMFkAz OVtw== X-Forwarded-Encrypted: i=1; AJvYcCXH9R1ci/EFzAAFY2Kz5tPNBGwIvYl+tWcn4jQBmVuo8XlPN+ERGPvD4oEzVXfFDun0D03w11pyzl74rf8=@vger.kernel.org X-Gm-Message-State: AOJu0YwYoH2PgJQecadqyww4Qk2j6WtZqJiGGfqHwTsJHgGkN5eqXkPF VK6hQmihdfU56gk76Fai4zDJfdvJP3ZD7AT5HVXiuVHw+MYwMSXViggRNI0PIvsbNwH+6OLulVV Th9uCGpU2xqR8KXhhxV5FlUosx/+eb5HDV+5Xy65jMQr0xuA1qCnMN+nEUCypZDU2dgnTaxfEon gxHsGYWyh+aYMXC/BcbqKPLWnejWb8HlCkbbHdL8+hbDxuSMndzX4zXpA2cyGeTsJn1VPKjNsoF Zk2HGMLfUTgAghihPSyoU7RdQ== X-Gm-Gg: AZuq6aIzz4jK2E1oiAH0/cpI5GVJAbic/vNl5YCmn8fME3Ceq5+TdFpThlkPTGvhcHi Zi8kxUMf9+XyiJ88WRn+4VlGpVm8RCBOL5y9Y+0uiK6q4/4nYdXCZmzWG/P7qz4Jf25iVuiEW3a 5aMcPKapTIHS9P29+1AHTvf+F7nJAXfrpPsmaoghOyLZpDlVueC1Rui4AuywHzm4IymrNEAN4+I MSuF3BYJdw4UScswFugZ2JmcNiYO3rzZ3CgvzNrBU0kE2tAEfbvuJ91awMc61sztnMWTMOE+IoY LObdU+qSoQ8y9xwuIvzOJz9J6qdl2gtKeBzvOBqUGeNBDMKcCJkzD//Y08d04Eyq1+opXst2p5N wdo1lz6CKnehZ5mAGJi6rcQ1V4khL8DAWcr5vV3VtXN8VrPy2exo/nDVyceSj40zZ8xXKC8TPmt CpLpvyiJl/5oDwaJSShtK3Z8i31AIS7xnud28pbkAvNVm34iZz07feCw== X-Received: by 2002:a05:690c:4c03:b0:78c:5bb4:1d43 with SMTP id 00721157ae682-794399c75c2mr34312037b3.45.1769196948965; Fri, 23 Jan 2026 11:35:48 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-102.dlp.protect.broadcom.com. [144.49.247.102]) by smtp-relay.gmail.com with ESMTPS id 00721157ae682-7943af0f9f6sm1659547b3.7.2026.01.23.11.35.48 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Jan 2026 11:35:48 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pf1-f197.google.com with SMTP id d2e1a72fcca58-81e7fd70908so4583639b3a.2 for ; Fri, 23 Jan 2026 11:35:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1769196947; x=1769801747; 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=l5OU/RLBNz5QlYQHo4MnTuUpoycaD8XZR+hOfHOhW5Q=; b=dfwI2u9CKUNh138627fU31lBII/o4kdUSlsLxgDtim7SIYiVXrdBLwOVHHowId8yDw MHsQEPttzPoKBOnZg2k5l+CvesXvfmtjdeQ5UeFtAH9B5u0n6NA6JIk9zZ5J2RbpevvP F3M7zuOcrGcrZiIyfqE5aXhs2gfpxoUPT5SUo= X-Forwarded-Encrypted: i=1; AJvYcCWZN3juW4wN31uQluxKLScSXXvBw6s9HUQsFI0PlNgEulXVXjljc1F9hJlqNtRV17Go2gxrwoN9U0+PQ+8=@vger.kernel.org X-Received: by 2002:a05:6a00:4ac9:b0:81d:e9b1:b6e3 with SMTP id d2e1a72fcca58-82317d95c45mr3591363b3a.14.1769196947076; Fri, 23 Jan 2026 11:35:47 -0800 (PST) X-Received: by 2002:a05:6a00:4ac9:b0:81d:e9b1:b6e3 with SMTP id d2e1a72fcca58-82317d95c45mr3591343b3a.14.1769196946503; Fri, 23 Jan 2026 11:35:46 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8231873e519sm2843206b3a.49.2026.01.23.11.35.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Jan 2026 11:35:46 -0800 (PST) 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, ajit.khaparde@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v6, net-next 7/8] bng_en: Add TPA related functions Date: Sat, 24 Jan 2026 01:05:03 +0530 Message-ID: <20260123193504.285573-8-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260123193504.285573-1-bhargava.marreddy@broadcom.com> References: <20260123193504.285573-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 the functions to handle TPA events in RX path. This helps the next patch enable TPA functionality. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_hw_def.h | 239 +++++++++++++++++- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 124 +++++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.h | 46 ++++ 3 files changed, 408 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h b/drivers/net= /ethernet/broadcom/bnge/bnge_hw_def.h index d2c2acf44e82..49828dc05514 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h @@ -143,7 +143,7 @@ struct rx_cmp_ext { #define RX_AGG_CMP_LEN GENMASK(31, 16) #define RX_AGG_CMP_LEN_SHIFT 16 #define RX_AGG_CMP_V BIT(0) -#define RX_AGG_CMP_AGG_ID GENMASK(31, 16) +#define RX_AGG_CMP_AGG_ID GENMASK(25, 16) #define RX_AGG_CMP_AGG_ID_SHIFT 16 =20 struct rx_agg_cmp { @@ -206,4 +206,241 @@ struct rx_agg_cmp { =20 #define RX_CMP_HASH_VALID(rxcmp) \ ((rxcmp)->rx_cmp_len_flags_type & cpu_to_le32(RX_CMP_FLAGS_RSS_VALID)) + +#define TPA_AGG_AGG_ID(rx_agg) \ + ((le32_to_cpu((rx_agg)->rx_agg_cmp_v) & \ + RX_AGG_CMP_AGG_ID) >> RX_AGG_CMP_AGG_ID_SHIFT) + +#define RX_TPA_START_CMP_TYPE GENMASK(5, 0) +#define RX_TPA_START_CMP_FLAGS GENMASK(15, 6) +#define RX_TPA_START_CMP_FLAGS_SHIFT 6 +#define RX_TPA_START_CMP_FLAGS_ERROR BIT(6) +#define RX_TPA_START_CMP_FLAGS_PLACEMENT GENMASK(9, 7) +#define RX_TPA_START_CMP_FLAGS_PLACEMENT_SHIFT 7 +#define RX_TPA_START_CMP_FLAGS_PLACEMENT_JUMBO BIT(7) +#define RX_TPA_START_CMP_FLAGS_PLACEMENT_HDS (0x2 << 7) +#define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7) +#define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7) +#define RX_TPA_START_CMP_FLAGS_RSS_VALID BIT(10) +#define RX_TPA_START_CMP_FLAGS_TIMESTAMP BIT(11) +#define RX_TPA_START_CMP_FLAGS_ITYPES GENMASK(15, 12) +#define RX_TPA_START_CMP_FLAGS_ITYPES_SHIFT 12 +#define RX_TPA_START_CMP_FLAGS_ITYPE_TCP (0x2 << 12) +#define RX_TPA_START_CMP_LEN GENMASK(31, 16) +#define RX_TPA_START_CMP_LEN_SHIFT 16 +#define RX_TPA_START_CMP_V1 BIT(0) +#define RX_TPA_START_CMP_RSS_HASH_TYPE GENMASK(15, 9) +#define RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT 9 +#define RX_TPA_START_CMP_V3_RSS_HASH_TYPE GENMASK(15, 7) +#define RX_TPA_START_CMP_V3_RSS_HASH_TYPE_SHIFT 7 +#define RX_TPA_START_CMP_AGG_ID GENMASK(25, 16) +#define RX_TPA_START_CMP_AGG_ID_SHIFT 16 +#define RX_TPA_START_CMP_METADATA1 GENMASK(31, 28) +#define RX_TPA_START_CMP_METADATA1_SHIFT 28 +#define RX_TPA_START_METADATA1_TPID_SEL GENMASK(30, 28) +#define RX_TPA_START_METADATA1_TPID_8021Q BIT(28) +#define RX_TPA_START_METADATA1_TPID_8021AD (0x0 << 28) +#define RX_TPA_START_METADATA1_VALID BIT(31) + +struct rx_tpa_start_cmp { + __le32 rx_tpa_start_cmp_len_flags_type; + u32 rx_tpa_start_cmp_opaque; + __le32 rx_tpa_start_cmp_misc_v1; + __le32 rx_tpa_start_cmp_rss_hash; +}; + +#define TPA_START_HASH_VALID(rx_tpa_start) \ + ((rx_tpa_start)->rx_tpa_start_cmp_len_flags_type & \ + cpu_to_le32(RX_TPA_START_CMP_FLAGS_RSS_VALID)) + +#define TPA_START_HASH_TYPE(rx_tpa_start) \ + (((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_RSS_HASH_TYPE) >> \ + RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK) + +#define TPA_START_V3_HASH_TYPE(rx_tpa_start) \ + (((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_V3_RSS_HASH_TYPE) >> \ + RX_TPA_START_CMP_V3_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK) + +#define TPA_START_AGG_ID(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_AGG_ID) >> RX_TPA_START_CMP_AGG_ID_SHIFT) + +#define TPA_START_ERROR(rx_tpa_start) \ + ((rx_tpa_start)->rx_tpa_start_cmp_len_flags_type & \ + cpu_to_le32(RX_TPA_START_CMP_FLAGS_ERROR)) + +#define TPA_START_VLAN_VALID(rx_tpa_start) \ + ((rx_tpa_start)->rx_tpa_start_cmp_misc_v1 & \ + cpu_to_le32(RX_TPA_START_METADATA1_VALID)) + +#define TPA_START_VLAN_TPID_SEL(rx_tpa_start) \ + (le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_METADATA1_TPID_SEL) + +#define RX_TPA_START_CMP_FLAGS2_IP_CS_CALC BIT(0) +#define RX_TPA_START_CMP_FLAGS2_L4_CS_CALC BIT(1) +#define RX_TPA_START_CMP_FLAGS2_T_IP_CS_CALC BIT(2) +#define RX_TPA_START_CMP_FLAGS2_T_L4_CS_CALC BIT(3) +#define RX_TPA_START_CMP_FLAGS2_IP_TYPE BIT(8) +#define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_VALID BIT(9) +#define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT GENMASK(11, 10) +#define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT_SHIFT 10 +#define RX_TPA_START_CMP_V3_FLAGS2_T_IP_TYPE BIT(10) +#define RX_TPA_START_CMP_V3_FLAGS2_AGG_GRO BIT(11) +#define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL GENMASK(31, 16) +#define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_SHIFT 16 +#define RX_TPA_START_CMP_V2 BIT(0) +#define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_MASK GENMASK(3, 1) +#define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_SHIFT 1 +#define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) +#define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) +#define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_FLUSH (0x5 << 1) +#define RX_TPA_START_CMP_CFA_CODE GENMASK(31, 16) +#define RX_TPA_START_CMPL_CFA_CODE_SHIFT 16 +#define RX_TPA_START_CMP_METADATA0_TCI_MASK GENMASK(31, 16) +#define RX_TPA_START_CMP_METADATA0_VID_MASK GENMASK(27, 16) +#define RX_TPA_START_CMP_METADATA0_SFT 16 + +struct rx_tpa_start_cmp_ext { + __le32 rx_tpa_start_cmp_flags2; + __le32 rx_tpa_start_cmp_metadata; + __le32 rx_tpa_start_cmp_cfa_code_v2; + __le32 rx_tpa_start_cmp_hdr_info; +}; + +#define TPA_START_CFA_CODE(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_cfa_code_v2) & \ + RX_TPA_START_CMP_CFA_CODE) >> RX_TPA_START_CMPL_CFA_CODE_SHIFT) + +#define TPA_START_IS_IPV6(rx_tpa_start) \ + (!!((rx_tpa_start)->rx_tpa_start_cmp_flags2 & \ + cpu_to_le32(RX_TPA_START_CMP_FLAGS2_IP_TYPE))) + +#define TPA_START_ERROR_CODE(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_cfa_code_v2) & \ + RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_MASK) >> \ + RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_SHIFT) + +#define TPA_START_METADATA0_TCI(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_cfa_code_v2) & \ + RX_TPA_START_CMP_METADATA0_TCI_MASK) >> \ + RX_TPA_START_CMP_METADATA0_SFT) + +#define RX_TPA_END_CMP_TYPE GENMASK(5, 0) +#define RX_TPA_END_CMP_FLAGS GENMASK(15, 6) +#define RX_TPA_END_CMP_FLAGS_SHIFT 6 +#define RX_TPA_END_CMP_FLAGS_PLACEMENT GENMASK(9, 7) +#define RX_TPA_END_CMP_FLAGS_PLACEMENT_SHIFT 7 +#define RX_TPA_END_CMP_FLAGS_PLACEMENT_JUMBO BIT(7) +#define RX_TPA_END_CMP_FLAGS_PLACEMENT_HDS (0x2 << 7) +#define RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7) +#define RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7) +#define RX_TPA_END_CMP_FLAGS_RSS_VALID BIT(10) +#define RX_TPA_END_CMP_FLAGS_ITYPES GENMASK(15, 12) +#define RX_TPA_END_CMP_FLAGS_ITYPES_SHIFT 12 +#define RX_TPA_END_CMP_FLAGS_ITYPE_TCP (0x2 << 12) +#define RX_TPA_END_CMP_LEN GENMASK(31, 16) +#define RX_TPA_END_CMP_LEN_SHIFT 16 +#define RX_TPA_END_CMP_V1 BIT(0) +#define RX_TPA_END_CMP_TPA_SEGS GENMASK(15, 8) +#define RX_TPA_END_CMP_TPA_SEGS_SHIFT 8 +#define RX_TPA_END_CMP_AGG_ID GENMASK(25, 16) +#define RX_TPA_END_CMP_AGG_ID_SHIFT 16 +#define RX_TPA_END_GRO_TS BIT(31) + +struct rx_tpa_end_cmp { + __le32 rx_tpa_end_cmp_len_flags_type; + u32 rx_tpa_end_cmp_opaque; + __le32 rx_tpa_end_cmp_misc_v1; + __le32 rx_tpa_end_cmp_tsdelta; +}; + +#define TPA_END_AGG_ID(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_AGG_ID) >> RX_TPA_END_CMP_AGG_ID_SHIFT) + +#define TPA_END_TPA_SEGS(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_TPA_SEGS) >> RX_TPA_END_CMP_TPA_SEGS_SHIFT) + +#define RX_TPA_END_CMP_FLAGS_PLACEMENT_ANY_GRO \ + cpu_to_le32(RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_JUMBO & \ + RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_HDS) + +#define TPA_END_GRO(rx_tpa_end) \ + ((rx_tpa_end)->rx_tpa_end_cmp_len_flags_type & \ + RX_TPA_END_CMP_FLAGS_PLACEMENT_ANY_GRO) + +#define TPA_END_GRO_TS(rx_tpa_end) \ + (!!((rx_tpa_end)->rx_tpa_end_cmp_tsdelta & \ + cpu_to_le32(RX_TPA_END_GRO_TS))) + +#define RX_TPA_END_CMP_TPA_DUP_ACKS GENMASK(3, 0) +#define RX_TPA_END_CMP_PAYLOAD_OFFSET GENMASK(23, 16) +#define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT 16 +#define RX_TPA_END_CMP_AGG_BUFS GENMASK(31, 24) +#define RX_TPA_END_CMP_AGG_BUFS_SHIFT 24 +#define RX_TPA_END_CMP_TPA_SEG_LEN GENMASK(15, 0) +#define RX_TPA_END_CMP_V2 BIT(0) +#define RX_TPA_END_CMP_ERRORS GENMASK(2, 1) +#define RX_TPA_END_CMPL_ERRORS_SHIFT 1 +#define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) +#define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (0x2 << 1) +#define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) +#define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_RSV_ERROR (0x4 << 1) +#define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_FLUSH (0x5 << 1) + +struct rx_tpa_end_cmp_ext { + __le32 rx_tpa_end_cmp_dup_acks; + __le32 rx_tpa_end_cmp_seg_len; + __le32 rx_tpa_end_cmp_errors_v2; + u32 rx_tpa_end_cmp_start_opaque; +}; + +#define TPA_END_ERRORS(rx_tpa_end_ext) \ + ((rx_tpa_end_ext)->rx_tpa_end_cmp_errors_v2 & \ + cpu_to_le32(RX_TPA_END_CMP_ERRORS)) + +#define TPA_END_PAYLOAD_OFF(rx_tpa_end_ext) \ + ((le32_to_cpu((rx_tpa_end_ext)->rx_tpa_end_cmp_dup_acks) & \ + RX_TPA_END_CMP_PAYLOAD_OFFSET) >> \ + RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT) + +#define TPA_END_AGG_BUFS(rx_tpa_end_ext) \ + ((le32_to_cpu((rx_tpa_end_ext)->rx_tpa_end_cmp_dup_acks) & \ + RX_TPA_END_CMP_AGG_BUFS) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT) + +#define EVENT_DATA1_RESET_NOTIFY_FATAL(data1) \ + (((data1) & \ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_MASK) =3D=3D\ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_EXCEPTION_FATAL) + +#define EVENT_DATA1_RESET_NOTIFY_FW_ACTIVATION(data1) \ + (((data1) & \ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_MASK) =3D=3D\ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_ACTIVATION) + +#define EVENT_DATA2_RESET_NOTIFY_FW_STATUS_CODE(data2) \ + ((data2) & \ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA2_FW_STATUS_CODE_MASK) + +#define EVENT_DATA1_RECOVERY_MASTER_FUNC(data1) \ + (!!((data1) & \ + ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_MASTER_FUNC)) + +#define EVENT_DATA1_RECOVERY_ENABLED(data1) \ + (!!((data1) & \ + ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_RECOVERY_ENABLED)) + +#define BNGE_EVENT_ERROR_REPORT_TYPE(data1) \ + (((data1) & \ + ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK) >>\ + ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_SFT) + +#define BNGE_EVENT_INVALID_SIGNAL_DATA(data2) \ + (((data2) & \ + ASYNC_EVENT_CMPL_ERROR_REPORT_INVALID_SIGNAL_EVENT_DATA2_PIN_ID_MASK) >= >\ + ASYNC_EVENT_CMPL_ERROR_REPORT_INVALID_SIGNAL_EVENT_DATA2_PIN_ID_SFT) #endif /* _BNGE_HW_DEF_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 5b0e326c5056..6e240f48d89b 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -377,11 +377,37 @@ static void bnge_free_one_agg_ring_bufs(struct bnge_n= et *bn, } } =20 +static void bnge_free_one_tpa_info_data(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr) +{ + int i; + + for (i =3D 0; i < bn->max_tpa; i++) { + struct bnge_tpa_info *tpa_info =3D &rxr->rx_tpa[i]; + u8 *data =3D tpa_info->data; + + if (!data) + continue; + + tpa_info->data =3D NULL; + page_pool_free_va(rxr->head_pool, data, false); + } +} + static void bnge_free_one_rx_ring_pair_bufs(struct bnge_net *bn, struct bnge_rx_ring_info *rxr) { + struct bnge_tpa_idx_map *map; + + if (rxr->rx_tpa) + bnge_free_one_tpa_info_data(bn, rxr); + bnge_free_one_rx_ring_bufs(bn, rxr); bnge_free_one_agg_ring_bufs(bn, rxr); + + map =3D rxr->rx_tpa_idx_map; + if (map) + memset(map->agg_idx_bmap, 0, sizeof(map->agg_idx_bmap)); } =20 static void bnge_free_rx_ring_pair_bufs(struct bnge_net *bn) @@ -452,11 +478,70 @@ static void bnge_free_all_rings_bufs(struct bnge_net = *bn) bnge_free_tx_skbs(bn); } =20 +static void bnge_free_tpa_info(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i, j; + + for (i =3D 0; i < bd->rx_nr_rings; i++) { + struct bnge_rx_ring_info *rxr =3D &bn->rx_ring[i]; + + kfree(rxr->rx_tpa_idx_map); + rxr->rx_tpa_idx_map =3D NULL; + if (rxr->rx_tpa) { + for (j =3D 0; j < bn->max_tpa; j++) { + kfree(rxr->rx_tpa[j].agg_arr); + rxr->rx_tpa[j].agg_arr =3D NULL; + } + } + kfree(rxr->rx_tpa); + rxr->rx_tpa =3D NULL; + } +} + +static int bnge_alloc_tpa_info(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i, j; + + if (!bd->max_tpa_v2) + return 0; + + bn->max_tpa =3D max_t(u16, bd->max_tpa_v2, MAX_TPA); + for (i =3D 0; i < bd->rx_nr_rings; i++) { + struct bnge_rx_ring_info *rxr =3D &bn->rx_ring[i]; + + rxr->rx_tpa =3D kcalloc(bn->max_tpa, sizeof(struct bnge_tpa_info), + GFP_KERNEL); + if (!rxr->rx_tpa) + goto err_free_tpa_info; + + for (j =3D 0; j < bn->max_tpa; j++) { + struct rx_agg_cmp *agg; + + agg =3D kcalloc(MAX_SKB_FRAGS, sizeof(*agg), GFP_KERNEL); + if (!agg) + goto err_free_tpa_info; + rxr->rx_tpa[j].agg_arr =3D agg; + } + rxr->rx_tpa_idx_map =3D kzalloc(sizeof(*rxr->rx_tpa_idx_map), + GFP_KERNEL); + if (!rxr->rx_tpa_idx_map) + goto err_free_tpa_info; + } + return 0; + +err_free_tpa_info: + bnge_free_tpa_info(bn); + return -ENOMEM; +} + static void bnge_free_rx_rings(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; int i; =20 + bnge_free_tpa_info(bn); for (i =3D 0; i < bd->rx_nr_rings; i++) { struct bnge_rx_ring_info *rxr =3D &bn->rx_ring[i]; struct bnge_ring_struct *ring; @@ -581,6 +666,12 @@ static int bnge_alloc_rx_rings(struct bnge_net *bn) goto err_free_rx_rings; } } + + if (bn->priv_flags & BNGE_NET_EN_TPA) { + rc =3D bnge_alloc_tpa_info(bn); + if (rc) + goto err_free_rx_rings; + } return rc; =20 err_free_rx_rings: @@ -1126,6 +1217,30 @@ static int bnge_alloc_one_agg_ring_bufs(struct bnge_= net *bn, return -ENOMEM; } =20 +static int bnge_alloc_one_tpa_info_data(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr) +{ + dma_addr_t mapping; + u8 *data; + int i; + + for (i =3D 0; i < bn->max_tpa; i++) { + data =3D __bnge_alloc_rx_frag(bn, &mapping, rxr, + GFP_KERNEL); + if (!data) + goto err_free_tpa_info_data; + + rxr->rx_tpa[i].data =3D data; + rxr->rx_tpa[i].data_ptr =3D data + bn->rx_offset; + rxr->rx_tpa[i].mapping =3D mapping; + } + return 0; + +err_free_tpa_info_data: + bnge_free_one_tpa_info_data(bn, rxr); + return -ENOMEM; +} + static int bnge_alloc_one_rx_ring_pair_bufs(struct bnge_net *bn, int ring_= nr) { struct bnge_rx_ring_info *rxr =3D &bn->rx_ring[ring_nr]; @@ -1140,8 +1255,17 @@ static int bnge_alloc_one_rx_ring_pair_bufs(struct b= nge_net *bn, int ring_nr) if (rc) goto err_free_one_rx_ring_bufs; } + + if (rxr->rx_tpa) { + rc =3D bnge_alloc_one_tpa_info_data(bn, rxr); + if (rc) + goto err_free_one_agg_ring_bufs; + } + return 0; =20 +err_free_one_agg_ring_bufs: + bnge_free_one_agg_ring_bufs(bn, rxr); err_free_one_rx_ring_bufs: bnge_free_one_rx_ring_bufs(bn, rxr); return rc; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index ee036ce63655..89c9775f610e 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -153,6 +153,45 @@ enum { =20 #define BNGE_NET_EN_TPA (BNGE_NET_EN_GRO | BNGE_NET_EN_LRO) =20 +#define BNGE_NO_FW_ACCESS(bd) (pci_channel_offline((bd)->pdev)) + +#define MAX_TPA 256 +#define MAX_TPA_MASK (MAX_TPA - 1) +#define MAX_TPA_SEGS 0x3f + +#define BNGE_TPA_INNER_L3_OFF(hdr_info) \ + (((hdr_info) >> 18) & 0x1ff) + +#define BNGE_TPA_INNER_L2_OFF(hdr_info) \ + (((hdr_info) >> 9) & 0x1ff) + +#define BNGE_TPA_OUTER_L3_OFF(hdr_info) \ + ((hdr_info) & 0x1ff) + +struct bnge_tpa_idx_map { + u16 agg_id_tbl[1024]; + DECLARE_BITMAP(agg_idx_bmap, MAX_TPA); +}; + +struct bnge_tpa_info { + void *data; + u8 *data_ptr; + dma_addr_t mapping; + u16 len; + unsigned short gso_type; + u32 flags2; + u32 metadata; + enum pkt_hash_types hash_type; + u32 rss_hash; + u32 hdr_info; + + u16 cfa_code; /* cfa_code in TPA start compl */ + u8 agg_count; + u8 vlan_valid:1; + u8 cfa_code_valid:1; + struct rx_agg_cmp *agg_arr; +}; + /* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one extra * BD because the first TX BD is always a long BD. */ @@ -245,6 +284,10 @@ struct bnge_net { #define BNGE_STATE_NAPI_DISABLED 0 =20 u32 msg_enable; + u16 max_tpa; + __be16 vxlan_port; + __be16 nge_port; + __be16 vxlan_gpe_port; }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 @@ -390,6 +433,9 @@ struct bnge_rx_ring_info { dma_addr_t rx_desc_mapping[MAX_RX_PAGES]; dma_addr_t rx_agg_desc_mapping[MAX_RX_AGG_PAGES]; =20 + struct bnge_tpa_info *rx_tpa; + struct bnge_tpa_idx_map *rx_tpa_idx_map; + struct bnge_ring_struct rx_ring_struct; struct bnge_ring_struct rx_agg_ring_struct; struct page_pool *page_pool; --=20 2.47.3 From nobody Sat Feb 7 09:29:52 2026 Received: from mail-pg1-f227.google.com (mail-pg1-f227.google.com [209.85.215.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 7154F2DAFDD for ; Fri, 23 Jan 2026 19:35:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196956; cv=none; b=p4XGj+ElCi/GN5WWmIAYs0qPQStLaIfL2946YVkbI+sl99mNWpf7ZGNTmhZ/jJQCtGrR8PPmUoAQvMofNM7uk3GGyLY51VEJdnevcY8EDbjwFK8o1SiwfiuHrbBvonUiOIOy2GhpUbai6qH8ftKQIICMWNWyt3QDI/Ezb8jrzr0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769196956; c=relaxed/simple; bh=prPzBnxeeMUWdAKzGYCuyJ95STzszX1/WTbLT0a/WAU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Gmx28ffcOODMnDr3BEloeIWQymbrkBvuS+5r+agjtPHDc8m9YilbEqlhhVYqnkLhVS3xWt0pjpH4b+ozbNH4RzQOJ6XB27IyxOCpupTwNso/7jSVf+I74bbnO++o+dCJtIcekz2QuH7jqv8makJMtTCvhp9YaV3PlRiyxpOgaC0= 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=SC164VuF; arc=none smtp.client-ip=209.85.215.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="SC164VuF" Received: by mail-pg1-f227.google.com with SMTP id 41be03b00d2f7-c63555db09fso514345a12.1 for ; Fri, 23 Jan 2026 11:35:54 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769196954; x=1769801754; 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=wTcjSb6ZwansrR5rl4czcgB7EtYaLy+a0+IL3nt4vsg=; b=kM+41QdmiTbiq9bsBdL+ZV9ugra/NurbGJbDgsMyYBXZ8MPBeb15UxkUHKnYxkJGB0 p4enSLomg6yV6xZJC6JVptz9FBdxy3iKe20G1sxKqB0UxcsT/0Dh0pr6rq55ohtIQcD+ eWbmekDvC4VaullVkCV+vQ3O9R7+wGVmo+BhIVfAbW5mEbytw6xtUaKTjUFsf1YhsxlO 17a8v8/4xjiXNLAOw5OBZp847rHn2/G9SQVXygvNFYZlkpcKv2qsqm4VhVcK1PnzMZlm Q4WtmuxkMLuEc+8DvRlp8Yf5Sj1yIP5nV7LN+DHKQal3yhq1HiKRzny+ADkzuEN6VW52 fg8Q== X-Forwarded-Encrypted: i=1; AJvYcCV7OGqxVA5EXEpHPcGMusgEjPGt3icTBhSrbcNFTBr6pIIHMPCPXNw4my0o6HwGu7DafYfCGZ8DYVK/S5s=@vger.kernel.org X-Gm-Message-State: AOJu0Yz26x8eNa+GGxUhB2OzG3YsKci0QfblHi+GEy3kybYeg0I4HxHf Meqk2uL+EO6fXwZAgTxPfu3LjfTzRYLVdGFsFtj5RAoA2X8U7vgfx3h5ccpBgv7Wt5Me+H7sd9d Eif8k5eBvWcoCeVlbuDq+M/CWssjvKuCjUNBno6WC9mzH/QPJm9z9fUG2DJmud0Nk97R4lsoxCe zIfjVRw4qJYTVOol2LP0E4wlDiVgmjzBq3AkI8f546WhjZMEPasfw/Vi1+JeJhkDepsW6wJiS5A hl+Zdw/4rhV33Ysccqmv+g+aw== X-Gm-Gg: AZuq6aJWe7S+CniY7H94gRlQOkWK1FnMxOy/YdXGbQKq0D0csOoNpCynB9s+XwUPQuh OItt8xiomJcmuYevYYs0YuxC32a93uaop1wc2Hazith3WUDjS7HtdikCtUnRwkKZHj7yEK9m6BJ qR/k+oQDk2HA04YUgsPqHN4UWlnR/3fkHdAplxb80SwFAlf7JNR3wSoshYMsGrM12w0gYnV68Di vanXaf2o0oP7dm5dGvt1fjzxIMgJuMNtEnXQAoPWPmF0dN+4ooGHxnZCZgaMvE+GPyM8QnbcDBK gqtTDacG26aEUXY8U95fPgLjNWpesFX2JdDfZbGG9hiXajyqWQ1A0UHpK/zM6WBm9J+EfQfQ/K1 NshmB2+72v7YsDTXaFf56wq/724Qy0U6W9/wHSQH5oCQekifRzXPn2suzT7T24ylaUrmjbcS/BO ggRcy6jSXsf69oQn1QYzzBjJJXxtP8+VOsk1UgJBc2ohvE0QdGUv33Dg== X-Received: by 2002:a17:90b:58c8:b0:34f:6ddc:d9de with SMTP id 98e67ed59e1d1-35335646b94mr5716884a91.16.1769196953569; Fri, 23 Jan 2026 11:35:53 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-100.dlp.protect.broadcom.com. [144.49.247.100]) by smtp-relay.gmail.com with ESMTPS id 98e67ed59e1d1-3536dc432basm414869a91.6.2026.01.23.11.35.53 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Jan 2026 11:35:53 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pf1-f198.google.com with SMTP id d2e1a72fcca58-8216fece04cso2544842b3a.0 for ; Fri, 23 Jan 2026 11:35:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1769196952; x=1769801752; 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=wTcjSb6ZwansrR5rl4czcgB7EtYaLy+a0+IL3nt4vsg=; b=SC164VuF5h/jR5FnQA7fYwAK7QKVFzJMWCJqcbN3iWF6/b2F3b5prOr4wXj16Z2AGs /hlWHuRjJmSPljqUur3tA8grNGNQN/eu8fcdkr3cucP2477NKOzpHz24fxYPUHcHTcnL YpaeAzPlTAA3mCvctv/2lUtkHNFUfJUyD7guw= X-Forwarded-Encrypted: i=1; AJvYcCUph7FmW3vwR8KEcUfL+TlaxS9CTMeOQLQkVjlf2mGOEg/h7xWe+3F/OxpSkCXEw/c85oaxRk00pedfjN0=@vger.kernel.org X-Received: by 2002:a05:6a00:138c:b0:81c:5bca:8104 with SMTP id d2e1a72fcca58-82317b3094amr3007036b3a.24.1769196951338; Fri, 23 Jan 2026 11:35:51 -0800 (PST) X-Received: by 2002:a05:6a00:138c:b0:81c:5bca:8104 with SMTP id d2e1a72fcca58-82317b3094amr3007016b3a.24.1769196950782; Fri, 23 Jan 2026 11:35:50 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8231873e519sm2843206b3a.49.2026.01.23.11.35.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Jan 2026 11:35:50 -0800 (PST) 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, ajit.khaparde@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v6, net-next 8/8] bng_en: Add support for TPA events Date: Sat, 24 Jan 2026 01:05:04 +0530 Message-ID: <20260123193504.285573-9-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260123193504.285573-1-bhargava.marreddy@broadcom.com> References: <20260123193504.285573-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" Enable TPA functionality in the VNIC and add functions to handle TPA events, which help in processing LRO/GRO. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 65 +++ .../ethernet/broadcom/bnge/bnge_hwrm_lib.h | 2 + .../net/ethernet/broadcom/bnge/bnge_netdev.c | 27 ++ .../net/ethernet/broadcom/bnge/bnge_txrx.c | 436 +++++++++++++++++- 4 files changed, 520 insertions(+), 10 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 198f49b40dbf..d4b1c0d2c44c 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c @@ -1183,3 +1183,68 @@ int bnge_hwrm_set_async_event_cr(struct bnge_dev *bd= , int idx) req->async_event_cr =3D cpu_to_le16(idx); return bnge_hwrm_req_send(bd, req); } + +#define BNGE_DFLT_TUNL_TPA_BMAP \ + (VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_GRE | \ + VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_IPV4 | \ + VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_IPV6) + +static void bnge_hwrm_vnic_update_tunl_tpa(struct bnge_dev *bd, + struct hwrm_vnic_tpa_cfg_input *req) +{ + struct bnge_net *bn =3D netdev_priv(bd->netdev); + u32 tunl_tpa_bmap =3D BNGE_DFLT_TUNL_TPA_BMAP; + + if (!(bd->fw_cap & BNGE_FW_CAP_VNIC_TUNNEL_TPA)) + return; + + if (bn->vxlan_port) + tunl_tpa_bmap |=3D VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_VXLAN; + if (bn->vxlan_gpe_port) + tunl_tpa_bmap |=3D VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_VXLAN_GPE; + if (bn->nge_port) + tunl_tpa_bmap |=3D VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_GENEVE; + + req->enables |=3D cpu_to_le32(VNIC_TPA_CFG_REQ_ENABLES_TNL_TPA_EN); + req->tnl_tpa_en_bitmap =3D cpu_to_le32(tunl_tpa_bmap); +} + +int bnge_hwrm_vnic_set_tpa(struct bnge_dev *bd, struct bnge_vnic_info *vni= c, + u32 tpa_flags) +{ + struct bnge_net *bn =3D netdev_priv(bd->netdev); + struct hwrm_vnic_tpa_cfg_input *req; + int rc; + + if (vnic->fw_vnic_id =3D=3D INVALID_HW_RING_ID) + return 0; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_VNIC_TPA_CFG); + if (rc) + return rc; + + if (tpa_flags) { + u32 flags; + + flags =3D VNIC_TPA_CFG_REQ_FLAGS_TPA | + VNIC_TPA_CFG_REQ_FLAGS_ENCAP_TPA | + VNIC_TPA_CFG_REQ_FLAGS_RSC_WND_UPDATE | + VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_ECN | + VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_SAME_GRE_SEQ; + if (tpa_flags & BNGE_NET_EN_GRO) + flags |=3D VNIC_TPA_CFG_REQ_FLAGS_GRO; + + req->flags =3D cpu_to_le32(flags); + req->enables =3D + cpu_to_le32(VNIC_TPA_CFG_REQ_ENABLES_MAX_AGG_SEGS | + VNIC_TPA_CFG_REQ_ENABLES_MAX_AGGS | + VNIC_TPA_CFG_REQ_ENABLES_MIN_AGG_LEN); + req->max_agg_segs =3D cpu_to_le16(MAX_TPA_SEGS); + req->max_aggs =3D cpu_to_le16(bn->max_tpa); + req->min_agg_len =3D cpu_to_le32(512); + bnge_hwrm_vnic_update_tunl_tpa(bd, req); + } + req->vnic_id =3D cpu_to_le16(vnic->fw_vnic_id); + + 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 042f28e84a05..38b046237feb 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h @@ -55,4 +55,6 @@ int hwrm_ring_alloc_send_msg(struct bnge_net *bn, struct bnge_ring_struct *ring, u32 ring_type, u32 map_index); 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); #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 6e240f48d89b..abb9b6bc91e0 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -2279,6 +2279,27 @@ static int bnge_request_irq(struct bnge_net *bn) return rc; } =20 +static int bnge_set_tpa(struct bnge_net *bn, bool set_tpa) +{ + u32 tpa_flags =3D 0; + int rc, i; + + if (set_tpa) + tpa_flags =3D bn->priv_flags & BNGE_NET_EN_TPA; + else if (BNGE_NO_FW_ACCESS(bn->bd)) + return 0; + for (i =3D 0; i < bn->nr_vnics; i++) { + rc =3D bnge_hwrm_vnic_set_tpa(bn->bd, &bn->vnic_info[i], + tpa_flags); + if (rc) { + netdev_err(bn->netdev, "hwrm vnic set tpa failure rc for vnic %d: %x\n", + i, rc); + return rc; + } + } + return 0; +} + static int bnge_init_chip(struct bnge_net *bn) { struct bnge_vnic_info *vnic =3D &bn->vnic_info[BNGE_VNIC_DEFAULT]; @@ -2313,6 +2334,12 @@ static int bnge_init_chip(struct bnge_net *bn) if (bd->rss_cap & BNGE_RSS_CAP_RSS_HASH_TYPE_DELTA) bnge_hwrm_update_rss_hash_cfg(bn); =20 + if (bn->priv_flags & BNGE_NET_EN_TPA) { + rc =3D bnge_set_tpa(bn, true); + if (rc) + goto err_out; + } + /* Filter for default vnic 0 */ rc =3D bnge_hwrm_set_vnic_filter(bn, 0, 0, bn->netdev->dev_addr); if (rc) { diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index 363f835438f4..3c41e439369d 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,15 @@ irqreturn_t bnge_msix(int irq, void *dev_instance) return IRQ_HANDLED; } =20 +static struct rx_agg_cmp *bnge_get_tpa_agg(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr, + u16 agg_id, u16 curr) +{ + struct bnge_tpa_info *tpa_info =3D &rxr->rx_tpa[agg_id]; + + return &tpa_info->agg_arr[curr]; +} + static struct rx_agg_cmp *bnge_get_agg(struct bnge_net *bn, struct bnge_cp_ring_info *cpr, u16 cp_cons, u16 curr) @@ -57,7 +67,7 @@ static struct rx_agg_cmp *bnge_get_agg(struct bnge_net *b= n, } =20 static void bnge_reuse_rx_agg_bufs(struct bnge_cp_ring_info *cpr, u16 idx, - u16 start, u32 agg_bufs) + u16 start, u32 agg_bufs, bool tpa) { struct bnge_napi *bnapi =3D cpr->bnapi; struct bnge_net *bn =3D bnapi->bn; @@ -76,7 +86,10 @@ static void bnge_reuse_rx_agg_bufs(struct bnge_cp_ring_i= nfo *cpr, u16 idx, netmem_ref netmem; u16 cons; =20 - agg =3D bnge_get_agg(bn, cpr, idx, start + i); + if (tpa) + agg =3D bnge_get_tpa_agg(bn, rxr, idx, start + i); + else + agg =3D bnge_get_agg(bn, cpr, idx, start + i); cons =3D agg->rx_agg_cmp_opaque; __clear_bit(cons, rxr->rx_agg_bmap); =20 @@ -137,6 +150,8 @@ static int bnge_discard_rx(struct bnge_net *bn, struct = bnge_cp_ring_info *cpr, agg_bufs =3D (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & RX_CMP_AGG_BUFS) >> RX_CMP_AGG_BUFS_SHIFT; + } else if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_END_CMP) { + return 0; } =20 if (agg_bufs) { @@ -149,7 +164,7 @@ static int bnge_discard_rx(struct bnge_net *bn, struct = bnge_cp_ring_info *cpr, =20 static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, struct bnge_cp_ring_info *cpr, - u16 idx, u32 agg_bufs, + u16 idx, u32 agg_bufs, bool tpa, struct sk_buff *skb) { struct bnge_napi *bnapi =3D cpr->bnapi; @@ -168,7 +183,10 @@ static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, u16 cons, frag_len; netmem_ref netmem; =20 - agg =3D bnge_get_agg(bn, cpr, idx, i); + if (tpa) + agg =3D bnge_get_tpa_agg(bn, rxr, idx, i); + else + agg =3D bnge_get_agg(bn, cpr, idx, i); cons =3D agg->rx_agg_cmp_opaque; frag_len =3D (le32_to_cpu(agg->rx_agg_cmp_len_flags_type) & RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT; @@ -198,7 +216,7 @@ static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, * allocated already. */ rxr->rx_agg_prod =3D prod; - bnge_reuse_rx_agg_bufs(cpr, idx, i, agg_bufs - i); + bnge_reuse_rx_agg_bufs(cpr, idx, i, agg_bufs - i, tpa); return 0; } =20 @@ -215,11 +233,12 @@ static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, static struct sk_buff *bnge_rx_agg_netmems_skb(struct bnge_net *bn, struct bnge_cp_ring_info *cpr, struct sk_buff *skb, u16 idx, - u32 agg_bufs) + u32 agg_bufs, bool tpa) { u32 total_frag_len; =20 - total_frag_len =3D __bnge_rx_agg_netmems(bn, cpr, idx, agg_bufs, skb); + total_frag_len =3D __bnge_rx_agg_netmems(bn, cpr, idx, agg_bufs, + tpa, skb); if (!total_frag_len) { skb_mark_for_recycle(skb); dev_kfree_skb(skb); @@ -253,6 +272,165 @@ static void bnge_sched_reset_txr(struct bnge_net *bn, /* TODO: Initiate reset task */ } =20 +static u16 bnge_tpa_alloc_agg_idx(struct bnge_rx_ring_info *rxr, u16 agg_i= d) +{ + struct bnge_tpa_idx_map *map =3D rxr->rx_tpa_idx_map; + u16 idx =3D agg_id & MAX_TPA_MASK; + + if (test_bit(idx, map->agg_idx_bmap)) { + idx =3D find_first_zero_bit(map->agg_idx_bmap, MAX_TPA); + if (idx >=3D MAX_TPA) + return INVALID_HW_RING_ID; + } + __set_bit(idx, map->agg_idx_bmap); + map->agg_id_tbl[agg_id] =3D idx; + return idx; +} + +static void bnge_free_agg_idx(struct bnge_rx_ring_info *rxr, u16 idx) +{ + struct bnge_tpa_idx_map *map =3D rxr->rx_tpa_idx_map; + + __clear_bit(idx, map->agg_idx_bmap); +} + +static u16 bnge_lookup_agg_idx(struct bnge_rx_ring_info *rxr, u16 agg_id) +{ + struct bnge_tpa_idx_map *map =3D rxr->rx_tpa_idx_map; + + return map->agg_id_tbl[agg_id]; +} + +static void bnge_tpa_metadata(struct bnge_tpa_info *tpa_info, + struct rx_tpa_start_cmp *tpa_start, + struct rx_tpa_start_cmp_ext *tpa_start1) +{ + tpa_info->cfa_code_valid =3D 1; + tpa_info->cfa_code =3D TPA_START_CFA_CODE(tpa_start1); + tpa_info->vlan_valid =3D 0; + if (tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) { + tpa_info->vlan_valid =3D 1; + tpa_info->metadata =3D + le32_to_cpu(tpa_start1->rx_tpa_start_cmp_metadata); + } +} + +static void bnge_tpa_metadata_v2(struct bnge_tpa_info *tpa_info, + struct rx_tpa_start_cmp *tpa_start, + struct rx_tpa_start_cmp_ext *tpa_start1) +{ + tpa_info->vlan_valid =3D 0; + if (TPA_START_VLAN_VALID(tpa_start)) { + u32 tpid_sel =3D TPA_START_VLAN_TPID_SEL(tpa_start); + u32 vlan_proto =3D ETH_P_8021Q; + + tpa_info->vlan_valid =3D 1; + if (tpid_sel =3D=3D RX_TPA_START_METADATA1_TPID_8021AD) + vlan_proto =3D ETH_P_8021AD; + tpa_info->metadata =3D vlan_proto << 16 | + TPA_START_METADATA0_TCI(tpa_start1); + } +} + +static void bnge_tpa_start(struct bnge_net *bn, struct bnge_rx_ring_info *= rxr, + u8 cmp_type, struct rx_tpa_start_cmp *tpa_start, + struct rx_tpa_start_cmp_ext *tpa_start1) +{ + struct bnge_sw_rx_bd *cons_rx_buf, *prod_rx_buf; + struct bnge_tpa_info *tpa_info; + u16 cons, prod, agg_id; + struct rx_bd *prod_bd; + dma_addr_t mapping; + + agg_id =3D TPA_START_AGG_ID(tpa_start); + agg_id =3D bnge_tpa_alloc_agg_idx(rxr, agg_id); + if (unlikely(agg_id =3D=3D INVALID_HW_RING_ID)) { + netdev_warn(bn->netdev, "Unable to allocate agg ID for ring %d, agg 0x%l= x\n", + rxr->bnapi->index, TPA_START_AGG_ID(tpa_start)); + bnge_sched_reset_rxr(bn, rxr); + return; + } + cons =3D tpa_start->rx_tpa_start_cmp_opaque; + prod =3D rxr->rx_prod; + cons_rx_buf =3D &rxr->rx_buf_ring[cons]; + prod_rx_buf =3D &rxr->rx_buf_ring[RING_RX(bn, prod)]; + tpa_info =3D &rxr->rx_tpa[agg_id]; + + if (unlikely(cons !=3D rxr->rx_next_cons || + TPA_START_ERROR(tpa_start))) { + netdev_warn(bn->netdev, "TPA cons %x, expected cons %x, error code %lx\n= ", + cons, rxr->rx_next_cons, + TPA_START_ERROR_CODE(tpa_start1)); + bnge_sched_reset_rxr(bn, rxr); + return; + } + prod_rx_buf->data =3D tpa_info->data; + prod_rx_buf->data_ptr =3D tpa_info->data_ptr; + + mapping =3D tpa_info->mapping; + prod_rx_buf->mapping =3D mapping; + + prod_bd =3D &rxr->rx_desc_ring[RX_RING(bn, prod)][RX_IDX(prod)]; + + prod_bd->rx_bd_haddr =3D cpu_to_le64(mapping); + + tpa_info->data =3D cons_rx_buf->data; + tpa_info->data_ptr =3D cons_rx_buf->data_ptr; + cons_rx_buf->data =3D NULL; + tpa_info->mapping =3D cons_rx_buf->mapping; + + tpa_info->len =3D + le32_to_cpu(tpa_start->rx_tpa_start_cmp_len_flags_type) >> + RX_TPA_START_CMP_LEN_SHIFT; + if (likely(TPA_START_HASH_VALID(tpa_start))) { + tpa_info->hash_type =3D PKT_HASH_TYPE_L4; + if (TPA_START_IS_IPV6(tpa_start1)) + tpa_info->gso_type =3D SKB_GSO_TCPV6; + else + tpa_info->gso_type =3D SKB_GSO_TCPV4; + tpa_info->rss_hash =3D + le32_to_cpu(tpa_start->rx_tpa_start_cmp_rss_hash); + } else { + tpa_info->hash_type =3D PKT_HASH_TYPE_NONE; + tpa_info->gso_type =3D 0; + netif_warn(bn, rx_err, bn->netdev, "TPA packet without valid hash\n"); + } + tpa_info->flags2 =3D le32_to_cpu(tpa_start1->rx_tpa_start_cmp_flags2); + tpa_info->hdr_info =3D le32_to_cpu(tpa_start1->rx_tpa_start_cmp_hdr_info); + if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_START_CMP) + bnge_tpa_metadata(tpa_info, tpa_start, tpa_start1); + else + bnge_tpa_metadata_v2(tpa_info, tpa_start, tpa_start1); + tpa_info->agg_count =3D 0; + + rxr->rx_prod =3D NEXT_RX(prod); + cons =3D RING_RX(bn, NEXT_RX(cons)); + rxr->rx_next_cons =3D RING_RX(bn, NEXT_RX(cons)); + cons_rx_buf =3D &rxr->rx_buf_ring[cons]; + + bnge_reuse_rx_data(rxr, cons, cons_rx_buf->data); + rxr->rx_prod =3D NEXT_RX(rxr->rx_prod); + cons_rx_buf->data =3D NULL; +} + +static void bnge_abort_tpa(struct bnge_cp_ring_info *cpr, u16 idx, u32 agg= _bufs) +{ + if (agg_bufs) + bnge_reuse_rx_agg_bufs(cpr, idx, 0, agg_bufs, true); +} + +static void bnge_tpa_agg(struct bnge_net *bn, struct bnge_rx_ring_info *rx= r, + struct rx_agg_cmp *rx_agg) +{ + u16 agg_id =3D TPA_AGG_AGG_ID(rx_agg); + struct bnge_tpa_info *tpa_info; + + agg_id =3D bnge_lookup_agg_idx(rxr, agg_id); + tpa_info =3D &rxr->rx_tpa[agg_id]; + + tpa_info->agg_arr[tpa_info->agg_count++] =3D *rx_agg; +} + void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a) { struct bnge_sw_rx_bd *cons_rx_buf, *prod_rx_buf; @@ -305,6 +483,208 @@ static struct sk_buff *bnge_copy_skb(struct bnge_napi= *bnapi, u8 *data, return skb; } =20 +#ifdef CONFIG_INET +static void bnge_gro_tunnel(struct sk_buff *skb, __be16 ip_proto) +{ + struct udphdr *uh =3D NULL; + + if (ip_proto =3D=3D htons(ETH_P_IP)) { + struct iphdr *iph =3D (struct iphdr *)skb->data; + + if (iph->protocol =3D=3D IPPROTO_UDP) + uh =3D (struct udphdr *)(iph + 1); + } else { + struct ipv6hdr *iph =3D (struct ipv6hdr *)skb->data; + + if (iph->nexthdr =3D=3D IPPROTO_UDP) + uh =3D (struct udphdr *)(iph + 1); + } + if (uh) { + if (uh->check) + skb_shinfo(skb)->gso_type |=3D SKB_GSO_UDP_TUNNEL_CSUM; + else + skb_shinfo(skb)->gso_type |=3D SKB_GSO_UDP_TUNNEL; + } +} + +static struct sk_buff *bnge_gro_func(struct bnge_tpa_info *tpa_info, + int payload_off, int tcp_ts, + struct sk_buff *skb) +{ + u16 outer_ip_off, inner_ip_off, inner_mac_off; + u32 hdr_info =3D tpa_info->hdr_info; + int iphdr_len, nw_off; + + inner_ip_off =3D BNGE_TPA_INNER_L3_OFF(hdr_info); + inner_mac_off =3D BNGE_TPA_INNER_L2_OFF(hdr_info); + outer_ip_off =3D BNGE_TPA_OUTER_L3_OFF(hdr_info); + + nw_off =3D inner_ip_off - ETH_HLEN; + skb_set_network_header(skb, nw_off); + iphdr_len =3D (tpa_info->flags2 & RX_TPA_START_CMP_FLAGS2_IP_TYPE) ? + sizeof(struct ipv6hdr) : sizeof(struct iphdr); + skb_set_transport_header(skb, nw_off + iphdr_len); + + if (inner_mac_off) { /* tunnel */ + __be16 proto =3D *((__be16 *)(skb->data + outer_ip_off - + ETH_HLEN - 2)); + + bnge_gro_tunnel(skb, proto); + } + + return skb; +} + +static struct sk_buff *bnge_gro_skb(struct bnge_net *bn, + struct bnge_tpa_info *tpa_info, + struct rx_tpa_end_cmp *tpa_end, + struct rx_tpa_end_cmp_ext *tpa_end1, + struct sk_buff *skb) +{ + int payload_off; + u16 segs; + + segs =3D TPA_END_TPA_SEGS(tpa_end); + if (segs =3D=3D 1) + return skb; + + NAPI_GRO_CB(skb)->count =3D segs; + skb_shinfo(skb)->gso_size =3D + le32_to_cpu(tpa_end1->rx_tpa_end_cmp_seg_len); + skb_shinfo(skb)->gso_type =3D tpa_info->gso_type; + payload_off =3D TPA_END_PAYLOAD_OFF(tpa_end1); + skb =3D bnge_gro_func(tpa_info, payload_off, + TPA_END_GRO_TS(tpa_end), skb); + if (likely(skb)) + tcp_gro_complete(skb); + + return skb; +} +#endif + +static struct sk_buff *bnge_tpa_end(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u32 *raw_cons, + struct rx_tpa_end_cmp *tpa_end, + struct rx_tpa_end_cmp_ext *tpa_end1, + u8 *event) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + struct net_device *dev =3D bn->netdev; + struct bnge_tpa_info *tpa_info; + struct bnge_rx_ring_info *rxr; + u8 *data_ptr, agg_bufs; + struct sk_buff *skb; + u16 idx =3D 0, agg_id; + dma_addr_t mapping; + unsigned int len; + void *data; + + rxr =3D bnapi->rx_ring; + agg_id =3D TPA_END_AGG_ID(tpa_end); + agg_id =3D bnge_lookup_agg_idx(rxr, agg_id); + agg_bufs =3D TPA_END_AGG_BUFS(tpa_end1); + tpa_info =3D &rxr->rx_tpa[agg_id]; + if (unlikely(agg_bufs !=3D tpa_info->agg_count)) { + netdev_warn(bn->netdev, "TPA end agg_buf %d !=3D expected agg_bufs %d\n", + agg_bufs, tpa_info->agg_count); + agg_bufs =3D tpa_info->agg_count; + } + tpa_info->agg_count =3D 0; + *event |=3D BNGE_AGG_EVENT; + bnge_free_agg_idx(rxr, agg_id); + idx =3D agg_id; + data =3D tpa_info->data; + data_ptr =3D tpa_info->data_ptr; + prefetch(data_ptr); + len =3D tpa_info->len; + mapping =3D tpa_info->mapping; + + if (unlikely(agg_bufs > MAX_SKB_FRAGS || TPA_END_ERRORS(tpa_end1))) { + bnge_abort_tpa(cpr, idx, agg_bufs); + if (agg_bufs > MAX_SKB_FRAGS) + netdev_warn(bn->netdev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n", + agg_bufs, (int)MAX_SKB_FRAGS); + return NULL; + } + + if (len <=3D bn->rx_copybreak) { + skb =3D bnge_copy_skb(bnapi, data_ptr, len, mapping); + if (!skb) { + bnge_abort_tpa(cpr, idx, agg_bufs); + return NULL; + } + } else { + dma_addr_t new_mapping; + u8 *new_data; + + new_data =3D __bnge_alloc_rx_frag(bn, &new_mapping, rxr, + GFP_ATOMIC); + if (!new_data) { + bnge_abort_tpa(cpr, idx, agg_bufs); + return NULL; + } + + tpa_info->data =3D new_data; + tpa_info->data_ptr =3D new_data + bn->rx_offset; + tpa_info->mapping =3D new_mapping; + + skb =3D napi_build_skb(data, bn->rx_buf_size); + dma_sync_single_for_cpu(bn->bd->dev, mapping, + bn->rx_buf_use_size, bn->rx_dir); + + if (!skb) { + page_pool_free_va(rxr->head_pool, data, true); + bnge_abort_tpa(cpr, idx, agg_bufs); + return NULL; + } + skb_mark_for_recycle(skb); + skb_reserve(skb, bn->rx_offset); + skb_put(skb, len); + } + + if (agg_bufs) { + skb =3D bnge_rx_agg_netmems_skb(bn, cpr, skb, idx, agg_bufs, + true); + /* Page reuse already handled by bnge_rx_agg_netmems_skb(). */ + if (!skb) + return NULL; + } + + skb->protocol =3D eth_type_trans(skb, dev); + + if (tpa_info->hash_type !=3D PKT_HASH_TYPE_NONE) + skb_set_hash(skb, tpa_info->rss_hash, tpa_info->hash_type); + + if (tpa_info->vlan_valid && + (dev->features & BNGE_HW_FEATURE_VLAN_ALL_RX)) { + __be16 vlan_proto =3D htons(tpa_info->metadata >> + RX_CMP_FLAGS2_METADATA_TPID_SFT); + u16 vtag =3D tpa_info->metadata & RX_CMP_FLAGS2_METADATA_TCI_MASK; + + if (eth_type_vlan(vlan_proto)) { + __vlan_hwaccel_put_tag(skb, vlan_proto, vtag); + } else { + dev_kfree_skb(skb); + return NULL; + } + } + + skb_checksum_none_assert(skb); + if (likely(tpa_info->flags2 & RX_TPA_START_CMP_FLAGS2_L4_CS_CALC)) { + skb->ip_summed =3D CHECKSUM_UNNECESSARY; + skb->csum_level =3D + (tpa_info->flags2 & RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3; + } + +#ifdef CONFIG_INET + if (bn->priv_flags & BNGE_NET_EN_GRO) + skb =3D bnge_gro_skb(bn, tpa_info, tpa_end, tpa_end1, skb); +#endif + + return skb; +} + static enum pkt_hash_types bnge_rss_ext_op(struct bnge_net *bn, struct rx_cmp *rxcmp) { @@ -397,6 +777,7 @@ static struct sk_buff *bnge_rx_skb(struct bnge_net *bn, =20 /* returns the following: * 1 - 1 packet successfully received + * 0 - successful TPA_START, packet not completed yet * -EBUSY - completion ring does not have all the agg buffers yet * -ENOMEM - packet aborted due to out of memory * -EIO - packet aborted due to hw error indicated in BD @@ -429,6 +810,11 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bng= e_cp_ring_info *cpr, =20 cmp_type =3D RX_CMP_TYPE(rxcmp); =20 + if (cmp_type =3D=3D CMP_TYPE_RX_TPA_AGG_CMP) { + bnge_tpa_agg(bn, rxr, (struct rx_agg_cmp *)rxcmp); + goto next_rx_no_prod_no_len; + } + tmp_raw_cons =3D NEXT_RAW_CMP(tmp_raw_cons); cp_cons =3D RING_CMP(bn, tmp_raw_cons); rxcmp1 =3D (struct rx_cmp_ext *) @@ -443,6 +829,28 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bng= e_cp_ring_info *cpr, dma_rmb(); prod =3D rxr->rx_prod; =20 + if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_START_CMP || + cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_START_V3_CMP) { + bnge_tpa_start(bn, rxr, cmp_type, + (struct rx_tpa_start_cmp *)rxcmp, + (struct rx_tpa_start_cmp_ext *)rxcmp1); + + *event |=3D BNGE_RX_EVENT; + goto next_rx_no_prod_no_len; + + } else if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_END_CMP) { + skb =3D bnge_tpa_end(bn, cpr, &tmp_raw_cons, + (struct rx_tpa_end_cmp *)rxcmp, + (struct rx_tpa_end_cmp_ext *)rxcmp1, event); + rc =3D -ENOMEM; + if (likely(skb)) { + bnge_deliver_skb(bn, bnapi, skb); + rc =3D 1; + } + *event |=3D BNGE_RX_EVENT; + goto next_rx_no_prod_no_len; + } + cons =3D rxcmp->rx_cmp_opaque; if (unlikely(cons !=3D rxr->rx_next_cons)) { int rc1 =3D bnge_discard_rx(bn, cpr, &tmp_raw_cons, rxcmp); @@ -477,7 +885,8 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bnge= _cp_ring_info *cpr, if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L2_ERRORS) { bnge_reuse_rx_data(rxr, cons, data); if (agg_bufs) - bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs); + bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs, + false); rc =3D -EIO; goto next_rx_no_len; } @@ -495,13 +904,14 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bn= ge_cp_ring_info *cpr, =20 if (!skb) { if (agg_bufs) - bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs); + bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, + agg_bufs,false); goto oom_next_rx; } =20 if (agg_bufs) { skb =3D bnge_rx_agg_netmems_skb(bn, cpr, skb, cp_cons, - agg_bufs); + agg_bufs, false); if (!skb) goto oom_next_rx; } @@ -592,6 +1002,12 @@ static int bnge_force_rx_discard(struct bnge_net *bn, cmp_type =3D=3D CMP_TYPE_RX_L2_V3_CMP) { rxcmp1->rx_cmp_cfa_code_errors_v2 |=3D cpu_to_le32(RX_CMPL_ERRORS_CRC_ERROR); + } else if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_END_CMP) { + struct rx_tpa_end_cmp_ext *tpa_end1; + + tpa_end1 =3D (struct rx_tpa_end_cmp_ext *)rxcmp1; + tpa_end1->rx_tpa_end_cmp_errors_v2 |=3D + cpu_to_le32(RX_TPA_END_CMP_ERRORS); } rc =3D bnge_rx_pkt(bn, cpr, raw_cons, event); return rc; --=20 2.47.3