From nobody Sun Feb 8 13:38:51 2026 Received: from mail-vk1-f228.google.com (mail-vk1-f228.google.com [209.85.221.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 7D05E36A036 for ; Fri, 16 Jan 2026 19:38:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592289; cv=none; b=jRVcjWTMD6bHtbPa+7udpHd4PAP/Ghqp4Nm1+z85AeFDrJ6szkj8nQEnKI7vWPqhUP0W++BrJ8n6etNJX8Bt3BtnN6NNg5VeBkYlIuuvLTUHaAuUtVgzkseNwkoDfGi4ooOwwZIiK44Wp461XGXWR9TWh9FlIDFL1dcG9OvX6uw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592289; c=relaxed/simple; bh=G42HEdK63RMSkNcCPQGCk4X08ncSFrRURRT8K21yxRE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CTo0EAsq0jaKdDZbAJGy2g4XmEbFiROYIM2wuVIAfHMuaAfL9xs3RLAHCtkqBzMLyt0/ZWlBn5ribnkxkuzdk5qX9ykNreZDH7Y/5h6zXGxUBXwZu2p7jHoq8R/0chjfnYBc0VVRui/V2ebVwfCynUBSOBBsenuAWUrT6WysAUg= 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=TnqKRr2H; arc=none smtp.client-ip=209.85.221.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="TnqKRr2H" Received: by mail-vk1-f228.google.com with SMTP id 71dfb90a1353d-5636227a6e6so789880e0c.3 for ; Fri, 16 Jan 2026 11:38:07 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768592286; x=1769197086; 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=j+LZXKqMgWYLVyBOeC4F2lWpaTvH4xkFAKNX+z/IZvpZPtJv97WlopGXnuWhZDIraM YRL32ML5MXDR15iplXVsm2usNcnUeGgBbhA4YnGrPW1s9iiYxmO+tmwhyqOq6EsVhKqg 5y3WtkhCOHAvtt6EHCFzoRnoTxyb9nZoPkpuqW9fQ85f0gyzBE2gJwJioCUOUWD6qiuw ElARVZ2B/yr53MnrL76RivTRiroCnoGkAm292wMH8qKNYHC8sR5Ucd69F7MCQsLN/hJr e4mwYqY2PeL30xCKG2KCTGAtF1Z4PuA+QTkKeB6MwuuOApxEoT6I1gmkY4XqR1Z1ubN9 T8aA== X-Forwarded-Encrypted: i=1; AJvYcCVMtWEX2BrWORSQHDhN8xY3YG5fade1PKmpZyaM3EFADamUihkJSc/ba1soctyNcUNuWYd2TMADUZhVT5k=@vger.kernel.org X-Gm-Message-State: AOJu0YzsFobcgUwjeES6gyOdHDbhYaA8ICT8KfUzdSuYhG6DinKvdxcs VudVljg/6yAOeIL8QPe6l4Wtzgn5N05bSGWsgwOWVqfK5a2kY0LfZzsiVtU3fI65phS7hE7ccra VgED37w2B24I4/q/UkEfVbbqiAhYYAKd25JirmvTyvBXNsp7ngZpV0VB7QH1xCF/cr9xMIW1gMU FOFZT7fkWu1Qb+48kHwa9kLT5pHaPOzzfn+a980Cqp5yxFLYWvXpfaTwolVUWNqoZDwRg//C9CX Gip6Cq8Fch1NIgLMVSB5TLYRw== X-Gm-Gg: AY/fxX6Omp73EYF52P+xgMpV2Y8APU2JqBCUGXyFX0E2ZAB0cn6bQ4IWO6uGjXpTs8e 8mpnQ4AAzxVpxlAn6oEysdJY44nHWxbhW+AeLHIaZ0OrJN0S9Rd6UZHbp2u7yomsMh8qDBJjlzK 2+H0BnKtWp/q6xdm0Yk6Ukkdqa3d9x3K1RlqIl3GY/1lbIDtv6r1N4k41JTCbsmu+uHkKat9drb B5SY2ZP6jvopX+Pox/qOpAfnxaucMRTiCt2mcdryMIcrpPd8CK7z3Wi5hXaQnPIZn38QsX5L54H nNbgLD+70fdOMxm32W50Q/o9egxQvSU+3bihdvITtkRttrBPhWB/RLeqIv31zR3PTv1+J09umN4 vxEStihQL77OZEibhqFpz8UHxp/pjLp+nIVY4jXQM7tilIBrsObKLg4mEXGpBqjv1e/lp1OHLgD KcS1zHm9XAXGZNjUX1sPtS6N7CCnGx85WR6nH+ZOp1h3AcQtFt94s= X-Received: by 2002:a05:6122:925:b0:54a:a048:45a4 with SMTP id 71dfb90a1353d-563b5c9f3e9mr1386620e0c.16.1768592284418; Fri, 16 Jan 2026 11:38:04 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-72.dlp.protect.broadcom.com. [144.49.247.72]) by smtp-relay.gmail.com with ESMTPS id 71dfb90a1353d-563b70f24f5sm401073e0c.5.2026.01.16.11.38.03 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Jan 2026 11:38:04 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f70.google.com with SMTP id 98e67ed59e1d1-34ac814f308so3552782a91.3 for ; Fri, 16 Jan 2026 11:38:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1768592283; x=1769197083; 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=TnqKRr2HJHW6c7Y1BW+NnwDF82gK1C9hQtuWGPxPAVs/vPqPC2UC0IBhzjHDGkcWyE LZa8Gz16qHm4WOMHSD12eb1aIR5j/WAUc876En9QBdHQFH8CVYQF9OlFJK+jeY6+X8En qC4WzFTJtxWYPLSzmzGMR26zjaZywyn746yLI= X-Forwarded-Encrypted: i=1; AJvYcCWf6zDB2QxUwka1HOhCwhP+bGVXJVIwyMN7sxvNTjI8N0aAlA7prCPQsI1Sful7hauoWWZSjSPh1B95ZfQ=@vger.kernel.org X-Received: by 2002:a17:90b:3890:b0:34c:99d6:175d with SMTP id 98e67ed59e1d1-35272ec5844mr3471682a91.2.1768592282931; Fri, 16 Jan 2026 11:38:02 -0800 (PST) X-Received: by 2002:a17:90b:3890:b0:34c:99d6:175d with SMTP id 98e67ed59e1d1-35272ec5844mr3471669a91.2.1768592282527; Fri, 16 Jan 2026 11:38:02 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35273121856sm2764909a91.15.2026.01.16.11.37.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jan 2026 11:38:02 -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: [v5, net-next 1/8] bng_en: Extend bnge_set_ring_params() for rx-copybreak Date: Sat, 17 Jan 2026 01:07:25 +0530 Message-ID: <20260116193732.157898-2-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260116193732.157898-1-bhargava.marreddy@broadcom.com> References: <20260116193732.157898-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 Sun Feb 8 13:38:51 2026 Received: from mail-dl1-f97.google.com (mail-dl1-f97.google.com [74.125.82.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 0FCA839C643 for ; Fri, 16 Jan 2026 19:38:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.97 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592296; cv=none; b=dqIGfNP0MBssfHaYvZ910XCU4/Gq0ur8+1HK1g5RrFdyhzYRWsYkYBNvNXgkYNwHGwDBnIfGUrEiIFQ2g6IgDbeqjqPJ/zPJrADPaU1cdLO2on6eeReuh6SApQiu+QLnfs8tzT2rcQFYjUAVs2d/hJqVOHkZfn0YUiKnHYXTmN0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592296; c=relaxed/simple; bh=0M9yD58dcmUkG3pPAh1CJBM4YPNI6kKMSN2sMWPihYk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ObFxhb4gZdpqY5vjVgoCz0RTiDnMFXIE0LDNlCnUMvVh0gXVMN1iWxotGXLcFeP74mwerx2SUGt+Se/6mcyaESfglYipueWp3Lx3AGaqxsrEHqsKwlvg2lGTCP3eUiQLeLMO3QLwqh2UoOjNkLUa5Ew2+L7QlXEK8HzsUtBgIxI= 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=EUulwRkz; arc=none smtp.client-ip=74.125.82.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="EUulwRkz" Received: by mail-dl1-f97.google.com with SMTP id a92af1059eb24-12336c0a8b6so4930964c88.1 for ; Fri, 16 Jan 2026 11:38:13 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768592291; x=1769197091; 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=E3+e3YOETaqwO8CMtV5g67XrhFgjOLGtph6DOG8R9LU=; b=tKiiWMqTWGe676/YGzM3J9XsfaTclj3BUMwn7qV8920sU3VsttlM/BxEZIpPwpXBvD Jy2WJx+3phsfPmcM096Dqc7TATwYt9mFp5yfcx8Uk4TYqQGHXUxzR5RI7ATbUNPeh7Kn obGfq28BwWCmnJaOAM4YuEUWy2H0ouQU6u+kY0GzA4L8parGkF+3wEwPzK7FQo1Tkxuj 83VmEnIcIqzcIQUXIN3Lek2izgTLUV1jB7kt5vq/hA1Thu8f4LJBNO8A8vdIt904ZIc0 5O9HHFZMZI1qwMb0AAxV/AyM63/j1prNRnar0bZqAHVhRoiCIvUvfWEJDKTCXIagp8nv iJfA== X-Forwarded-Encrypted: i=1; AJvYcCXD7H7X0OSBbIA1RGTJTxEA3s7yEncRf8ImkagbBUpMjjUnlnItZK1h+/KYEeXgodkhdtYOGRgua9Zn/H8=@vger.kernel.org X-Gm-Message-State: AOJu0YyakSRO07g58lS4t+nGm6kSZi5qnRuLe8n25C0qyxKn9RQF9P5t DGt92/io5pvEl9QauYqssAxQ8scTkB1Kzt6vm5F8OazOou7km7rj+Po+GfO1sssAbXFNo6CH/Ls cxb4bqEh5/uUuND8olioKFZtV9nNgm79Og4/1tYdGNsG474LFS6KZVmOmLmJlFExt9I8ogw+K+4 SnINIHUHFGhkQmyRh35ZEtJRIfe6Q6F4NHgNQN7hPmlAQBVm65wSa1D3ajHPTbrf3uAZdp412Mz j5nn9z9O6Fy50yGIfyrresazg== X-Gm-Gg: AY/fxX5WqqxysU2IEZ/AWlvsdpXxKzoNoAwG6uZPuOYUGCjKsPT8dtHcNqnrUIi/hDy dcgDfmd9cfYVDMa6onwBvVoeg2gWWaJkXi8JuKXVFMQpWlhidDem242EEm6gPvRnydZ62UPJBb0 Hj47QM98II7sQznKfqN57gnTyhgaxNMq58PCD9mK/hXOjbDxgGBIItrlY/lyvWiVQ4AG0kf8F8j dEb1i2WfWKmUiEOtMe55f76Ug4qi90XGjVYntWyohencbE+v3BCGv6CWg0cvPt1W93Unpmbx/oJ pkH1z39+F32ScMNN5LkmlvKpFO78mi1XL4cce4QhouZCodaCVrF3lU9RrUqJT5g0Ks20lORLaIG 1Ih78NUDW5Tj1Q/bMea30LQ4owQs28xO7goVD1iCMOdXLzXMn+/yAVITXOeYUBJx5gEu5DY8PNT 1itwd2XaPhoSLKW2lZRohGppbYFrMbT8YZZRSR6Gl1biDixD2Fdt0= X-Received: by 2002:a05:7022:2514:b0:122:2f4:b247 with SMTP id a92af1059eb24-1244a75ea33mr3350937c88.28.1768592291030; Fri, 16 Jan 2026 11:38:11 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-72.dlp.protect.broadcom.com. [144.49.247.72]) by smtp-relay.gmail.com with ESMTPS id a92af1059eb24-1244ac45d6asm646183c88.1.2026.01.16.11.38.10 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Jan 2026 11:38:11 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pg1-f198.google.com with SMTP id 41be03b00d2f7-c54e81eeab9so1558675a12.3 for ; Fri, 16 Jan 2026 11:38:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1768592288; x=1769197088; 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=E3+e3YOETaqwO8CMtV5g67XrhFgjOLGtph6DOG8R9LU=; b=EUulwRkzblEYAyaPiJnHxX6tL93HA3jCEte+C4f4w2slOBGZ6g9P9jr+72OX8rewVp G/0E9nHIytUIHizD9Y0q+viVfjpnevh/EGTWBgMOW8c7sp2MJsOrc//cAYqruC2mdGCL KcBXkY8jj0koo90KziDumd9iT5f+xChhlH02k= X-Forwarded-Encrypted: i=1; AJvYcCVmib7ZZp6aocDO7A4neQKA9dyCgDdLtKKnTYo/wco9gTHyNXi2KkCJGHoWP6ofEelcbUnMiXR8YyfeFdI=@vger.kernel.org X-Received: by 2002:a17:90b:3511:b0:32d:d5f1:fe7f with SMTP id 98e67ed59e1d1-35272f29b65mr3737102a91.15.1768592288029; Fri, 16 Jan 2026 11:38:08 -0800 (PST) X-Received: by 2002:a17:90b:3511:b0:32d:d5f1:fe7f with SMTP id 98e67ed59e1d1-35272f29b65mr3737079a91.15.1768592287481; Fri, 16 Jan 2026 11:38:07 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35273121856sm2764909a91.15.2026.01.16.11.38.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jan 2026 11:38:07 -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: [v5, net-next 2/8] bng_en: Add RX support Date: Sat, 17 Jan 2026 01:07:26 +0530 Message-ID: <20260116193732.157898-3-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260116193732.157898-1-bhargava.marreddy@broadcom.com> References: <20260116193732.157898-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 | 201 +++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.c | 117 +++- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 60 +- .../net/ethernet/broadcom/bnge/bnge_txrx.c | 560 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_txrx.h | 90 +++ 6 files changed, 1010 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..cae7b8ece219 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h @@ -0,0 +1,201 @@ +/* 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)) + +#define HWRM_RING_ALLOC_TX 0x1 +#define HWRM_RING_ALLOC_RX 0x2 +#define HWRM_RING_ALLOC_AGG 0x4 +#define HWRM_RING_ALLOC_CMPL 0x8 +#define HWRM_RING_ALLOC_NQ 0x10 +#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..850e3c67e9ac --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -0,0 +1,560 @@ +// 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); + + 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..f5aa5ac888a9 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2025 Broadcom */ + +#ifndef _BNGE_TXRX_H_ +#define _BNGE_TXRX_H_ + +#include +#include "bnge_netdev.h" + +#define BNGE_MIN_PKT_SIZE 52 + +#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 Sun Feb 8 13:38:51 2026 Received: from mail-yw1-f226.google.com (mail-yw1-f226.google.com [209.85.128.226]) (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 866993939AE for ; Fri, 16 Jan 2026 19:38:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592298; cv=none; b=CsJ3V1QnyIZWllehp1PPlZcg3fCFC7is6ZGfF46eNbsmJW2sEMsFmgDwsSi2qBjBGotuTL6NQb3qclh+crgwY/THA0qB6ffGkC5FZsMwsLF2QHr3Xik1JN4KoehP5GelDL0Xj5MiiU8wyfQbetpdRh8sXvd47SJVBuLfL7Ea3Tc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592298; c=relaxed/simple; bh=x88N3oxkXRPiWEgxunQ43AN6MNHv3SUlHx6gqxlfUpc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Rpyqu+85uxVrtLh6yP450MUeWRP+lky4EwGC8suP7g16xIJkP23+GWU7nmRGTyd2iwDl/wmfv6gBAVXRMOrsrzcRmLS902COn6JKfjiYmU4RwytifMntjPiQ2ZULpomXvfdYNOUwjUO+9yIcr6CX8p4mJwlX0hiXs66lWny2bSQ= 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=SfMzVjzF; arc=none smtp.client-ip=209.85.128.226 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="SfMzVjzF" Received: by mail-yw1-f226.google.com with SMTP id 00721157ae682-78d6a3c3b77so38089167b3.0 for ; Fri, 16 Jan 2026 11:38:16 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768592295; x=1769197095; 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=dzdMWEzSJ2Iibm3SBd/RgNfSnuzOKnyQSBjs/m3tLHM=; b=p0mXj76IjeICINJtp7CizJ/cMRnYz+/6en4osggsHM33kBCtCDWc6SsNXEsgWZX+P2 l3acEkd34eDjRi9XZRP/va+j23gZNj/paKt9qT9nnpuAZKJWDxHfTzYwV3jI+N5/U49H nxJGCMd1Zdek3C8SBjJd2sJ3EMhHDPfdfI9m0bB6/vJ7P8ppHbBqyAQJTcNNaAO9qyX5 3g1atP5WUxSd+zmuZ6U2K2sJUdCX7Rj+0saTNdI4ZAEZsTF/fz7/wTv9FlB1Gi1YcPTP dInh1XAbpOWGhmpNSX5Jcb702BCk2OziMhdPfz4HfL38XKMMvvAll0DuaASszFjBvS6a Y00w== X-Forwarded-Encrypted: i=1; AJvYcCWS0yQSUZAnToc+E8EEdkonpADJshPSI4RieEVSo1bNtS1sSh9No4VEbhueg4NVLZWLGgvhife7QU7K+gg=@vger.kernel.org X-Gm-Message-State: AOJu0YyEYJK3cb0cs3DezFN9AwKv8TE30dX0EFl5VvoYy5dxF1dfAw/1 V3TFjv/NdJTW/k7/RXTE4qyRIIpKl4BCTcnk1YqC9KGMMIYI8BKAkLx4n0T9gCLHb5/hPtuJQgD 9CJcWDqDMx23chIeoNeywEYX/dIZJ59FzoEngallyoOAKrirQCqFcyBZKEO3Chw1Goa9G3uFHnq sSc7DMeWJlyfvGK8u1D5OyGxdx5XNqyFGJKLzF6g54USz4ZmKvt14RRAi5EnXIKWiR/v7LETBCC XpGvDj9QqGJi+coA6hvOl2GkQ== X-Gm-Gg: AY/fxX5fTwf8kEmX/MM9SC9LAZ4JFuDrwl75NZPYaLOAFe9XCi57e19lST91OZsYuo7 6KNCj4s545fYsmFYAbXfc8UNka9yCbbmUb7RyM+FUq13ITWqhlClNhpAXlpBJmRHwvII3X+peNr WTEfJ+BZZrkJjjk4Mxo3M0PTfSr144UfKJ69DOCmU6lZ75uFO3zybPnZcxB+XNW3tpDuV0itupv jAutZlPlPqLhtM+yBOI+OSEyTJQmrqLcT8AdWn/8mRE9cvEcqYltpsA6MQl85RtxnoItu3B+CbW yAX2BpfPxIbAe/6PlvZdfYFVSK6J5ItSDHyfTxe1PtuPKkYd9qqJ0t5BDMqRGruL3jMxL2KbgQG bSiO73a6tVnSYfPm0eUVT+5/oipaO18JsjJsyHTC3pM38j8+Krl/83bv7oDae1Mt339+SIg/So6 6y24m1XDQduiBcFGYw73Z8pdgTXXE3uGG+iqc8z5CieXsVa3Fy0+E= X-Received: by 2002:a05:690e:1489:b0:646:5127:a024 with SMTP id 956f58d0204a3-6490a5eefc2mr5721293d50.7.1768592295381; Fri, 16 Jan 2026 11:38:15 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-72.dlp.protect.broadcom.com. [144.49.247.72]) by smtp-relay.gmail.com with ESMTPS id 956f58d0204a3-649170a0137sm207287d50.13.2026.01.16.11.38.15 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Jan 2026 11:38:15 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f70.google.com with SMTP id 98e67ed59e1d1-34ab8aafd24so2484719a91.0 for ; Fri, 16 Jan 2026 11:38:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1768592293; x=1769197093; 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=dzdMWEzSJ2Iibm3SBd/RgNfSnuzOKnyQSBjs/m3tLHM=; b=SfMzVjzFlsMlS8ZDFW+a84yJQMMRF8dqqIsWP+9zcQkCI6KwNdRTlwRalWHgznecpc 7URm9t7hjlam6SiukRvsm/G03oP/iAZDRXpRQnr17yDPCeMMTNzbWzfh47Odv0+RpZQ2 UwsGyzZJ/mlEXDuwCILYFLSAbQLoZDnBjmMLQ= X-Forwarded-Encrypted: i=1; AJvYcCWz368utDwRafJcW0x9wEavZ6PtysDy4B/MDAeCHOslvjmNeGiO+STfEERI/wme1R/ocUmvnTmfV1m7dbo=@vger.kernel.org X-Received: by 2002:a17:90b:2246:b0:34a:a16d:77c3 with SMTP id 98e67ed59e1d1-35272bcb638mr3448713a91.2.1768592292459; Fri, 16 Jan 2026 11:38:12 -0800 (PST) X-Received: by 2002:a17:90b:2246:b0:34a:a16d:77c3 with SMTP id 98e67ed59e1d1-35272bcb638mr3448694a91.2.1768592292011; Fri, 16 Jan 2026 11:38:12 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35273121856sm2764909a91.15.2026.01.16.11.38.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jan 2026 11:38:11 -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: [v5, net-next 3/8] bng_en: Handle an HWRM completion request Date: Sat, 17 Jan 2026 01:07:27 +0530 Message-ID: <20260116193732.157898-4-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260116193732.157898-1-bhargava.marreddy@broadcom.com> References: <20260116193732.157898-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 850e3c67e9ac..360ff6e2fa58 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -377,6 +377,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) { @@ -427,8 +464,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) { @@ -546,6 +586,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 Sun Feb 8 13:38:51 2026 Received: from mail-pl1-f228.google.com (mail-pl1-f228.google.com [209.85.214.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 B38FA34C140 for ; Fri, 16 Jan 2026 19:38:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592306; cv=none; b=HJ3FJ32Af/3LVkW3XFNeouAtlfHrx7xeEcMjYLjlG4OOIVuWPTvOXHDAZebFWmZ8ekLqmF2sgE0lPJ8sHj5/zjKdLgWXlz52wPSsiZtyesS/nhjDC6s404ASnls9c6WNC8N+p8XgC6zEaVUtOaNex9opHSmW4KQSDSXFzuQ/Sss= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592306; c=relaxed/simple; bh=H4d1GmIpDpk+qEEU1o/FcreRLGh2PG8degWZnE9mrEY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ln1fNEQBhlDX2PlYCrG0YRqZB8gXz0DI1S65UApy2pWxVpVV6wBg31F1UtGmH/EwcrUBKQMqLpvkOeZv81JOVpnDn5zYCEnpdKFwKpZkwn90e79P/eLgRrNwLh0eY7xnqLiuU/IrczdC3k5DcEHV7KW1V2Y7xZL3tO8hQUG5LC4= 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=K7s0puAs; arc=none smtp.client-ip=209.85.214.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="K7s0puAs" Received: by mail-pl1-f228.google.com with SMTP id d9443c01a7336-29f1bc40b35so25072755ad.2 for ; Fri, 16 Jan 2026 11:38:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768592299; x=1769197099; 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=5RE1Ydonxn/EbzGQfkPi595Jg1sH7wQCQVQgQmIM5tc=; b=HVj8MIjfeNiy9pIh40kmhQEANMa4gDP+rY6noS2khlfyEMiLGLF3mjF6y9yrHE17hz dobd6v7DebtFcPXCaLUWOaQD95AuPjKAmvhkLDBy6OSqekwZxN9JHg+fKT3aFAPJR8oI 3Pfj7oUEYjBDg0NwSoekbSiZ5CeRidc4v+ntalMbuZac0azL4OsrZ1w5NQBRGu/9zTqV 1oRizzPyZFtG+hmKlDd5ZtyUuxslb3emdAQBO6dZmZbOkjBFMs5kVoADWyGeH0yvPAdA 47fMccz49kMZYxTJzA9cGtI8DMO/HxXfevZTWHQkOQgIjXe4FG5j5lvvi0jX2jJFG+ug Hvfw== X-Forwarded-Encrypted: i=1; AJvYcCXwTJI/vzOY/1kQ58WiiFPSlwDRsKEoedjPI2n5ZzcHZz0o0FvPSD7FMO3K1/SZ6IXV3pxbp26mcVKuD24=@vger.kernel.org X-Gm-Message-State: AOJu0YxUsn1gQld3zrg6rvPSJziIDmrhuR+pfC7LoWNQWXSmohYaoVPo 7oSI7ug0iW4I8NJMYOlMzkCQyt2hp+V+zBrNVybQiH6kD0cjYpgiGMCdh7Cn7J5WzzKnhY5fdEB i5SZIFMd4CTMvC5oUlhAsD04Ko9Ntguap3kWNYWxb8Ws2HP2RBMquPUgErJ5WRITfrrMu77BloX PDwssV3Qsj17U4+db6ufLh8dzLhEID2ZB9Fg2pfwWXxXEEkbiRXAFTdMmKEdhMyksZLyjuN8nea hR98HIHVsty2UweKAKmdlNqkA== X-Gm-Gg: AY/fxX7e5w6xQlN2SIFqZJVy6tGAHBkv5ahPLw+GYuB48KXbzANmdVVFcGM+Ed/nnGc 5iSXGkGknRUbXZBR0dS8l8skGxyPJw/TvdngbfhW5nD2pgd9xZQSknfpc4WL2Ph+bEQ5hADVYvi Ig1o14/puOi5qwJCm8OeEjOuu1jqPUDV9Xaa7cx65l+OOIvjc5QeinZs4gcD/VIONuhckHgV0nb SDp8godITjP+TcLhguI4qozsIkfNC8aKMZcL8q7X74NfLtMK5DnfjV88YPZUM2UyMaZ4I5YKfpo nDCQqDfX4n1dPkP7eOMCouycbm1lBStdX1AADG4x6zrj7f/H5l+5pPhfaUo9kUUnYQK34yjCDNB SJ1b+Trrndmr/iQYJ8xuBZATlZ5oyj2OZ480PPXlQpQyuKBM3d2XCH1y1FNzqW9OpB0y9pF3CpY CFFovm2jmZImdfazuai7Ud1S95xFtH3HsrV28g/1vf8sPWR4se/hDAWQ== X-Received: by 2002:a17:903:1210:b0:2a0:d692:5681 with SMTP id d9443c01a7336-2a717555332mr42111615ad.24.1768592299031; Fri, 16 Jan 2026 11:38:19 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-118.dlp.protect.broadcom.com. [144.49.247.118]) by smtp-relay.gmail.com with ESMTPS id d9443c01a7336-2a7193ac321sm4117515ad.60.2026.01.16.11.38.18 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Jan 2026 11:38:19 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f69.google.com with SMTP id 98e67ed59e1d1-34c21341f56so4507832a91.2 for ; Fri, 16 Jan 2026 11:38:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1768592297; x=1769197097; 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=5RE1Ydonxn/EbzGQfkPi595Jg1sH7wQCQVQgQmIM5tc=; b=K7s0puAsd4bfRxja1j2fw0QkNeMqGp/1bjhILnvCEDkBtbChCPDqa4fDHzFwekIQmn WcCdhdB0LNGn4Xpd/HtBvWprsldL8z3Xu3sIGy/mUhcIuTgLz8xAmNYBl4an6HWWnU5N KIJsBUcjX+Kfu9UGMZXA8P5fdiw1QxrfU85LE= X-Forwarded-Encrypted: i=1; AJvYcCVH0LfD/5tQTrVXW1Zb7Kz7PxuGR6GZ5iWJq4EcNsrggJqAbYvYKvm9qAUGqYRWlcvttlXpmz6Fshe4PQI=@vger.kernel.org X-Received: by 2002:a17:90b:3890:b0:34c:99d6:175d with SMTP id 98e67ed59e1d1-35272ec5844mr3472094a91.2.1768592297252; Fri, 16 Jan 2026 11:38:17 -0800 (PST) X-Received: by 2002:a17:90b:3890:b0:34c:99d6:175d with SMTP id 98e67ed59e1d1-35272ec5844mr3472078a91.2.1768592296857; Fri, 16 Jan 2026 11:38:16 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35273121856sm2764909a91.15.2026.01.16.11.38.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jan 2026 11:38:16 -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: [v5, net-next 4/8] bng_en: Add TX support Date: Sat, 17 Jan 2026 01:07:28 +0530 Message-ID: <20260116193732.157898-5-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260116193732.157898-1-bhargava.marreddy@broadcom.com> References: <20260116193732.157898-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, 493 insertions(+), 12 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 360ff6e2fa58..9e069faf2a58 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; @@ -366,11 +383,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; @@ -443,9 +535,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)) @@ -600,3 +709,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 f5aa5ac888a9..81a24d8f9689 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h @@ -7,7 +7,33 @@ #include #include "bnge_netdev.h" =20 -#define BNGE_MIN_PKT_SIZE 52 +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); +} =20 #define TX_OPAQUE_IDX_MASK 0x0000ffff #define TX_OPAQUE_BDS_MASK 0x00ff0000 @@ -26,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. @@ -70,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)) @@ -85,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 Sun Feb 8 13:38:51 2026 Received: from mail-oa1-f98.google.com (mail-oa1-f98.google.com [209.85.160.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 6D56F3A1A59 for ; Fri, 16 Jan 2026 19:38:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.98 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592306; cv=none; b=tYbSLK5o0eyWj5Tmk9o7DeqwQQSMV7IMkuXcWIWObtfDD87HxkQptHFI9GjTlsIaB+gM2DwprFly26RXFfPrYGprsNWeBD7Y/mnBg3v+qDco+wOgektpG76gkrDODTXVbGvt9tnCHkVTKHNUbX9gla6lj3rSQ4fA3jSTDs2Tp6k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592306; c=relaxed/simple; bh=Lds7sMXzJrLrd0gBwEEuZ07H+OYaihFRhMfpOkt8Sd0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gNvLvGQBWotvg36+ZXnKvWcZPTV9yAFvo1xV8Cjokjl3GD3B+f3+IEmfIO7Ul+w885SlLkO3Bu+oKwRG/RTp+M2WISrU85G5InyhUr0fKU35+Vx7hla5ECwdcyaWmJw83ZB3e38QLxM8MpS7ibMtFGPbCtjoy/Hi2hoaYh7LktA= 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=K2R1lkKJ; arc=none smtp.client-ip=209.85.160.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="K2R1lkKJ" Received: by mail-oa1-f98.google.com with SMTP id 586e51a60fabf-4043eea60a3so1148120fac.2 for ; Fri, 16 Jan 2026 11:38:24 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768592303; x=1769197103; 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=4dWnjTr3AjoXWLMl2brB8ngehg3o0HcGu3374LRPyGE=; b=deRmIF7IeFQz+GHbYOuIEtCoq5mGS92snPYWZ6/u9FWM3GDPVDcaeJdsXI1NcsUAPC wD9v5F5i9ZOF3SNQbMTOktVeWots5/gDaAR5s38qgbzyoX51XZnn8ygX5rLttmwtbMcM SVKa5h2rrVXcnzkkadNABnKmdNCZpODrr5O6CI2lylBXHQnDUlgpQFEmHOvIhkYrvwxw qF8M1982Gzokz5lSKNuX8+dXKM0pj+vqdmSdRxJg2u89uSEMAg4JrBg+UNM7N631sJtU jRnkB444GRfAqHEbqO0lYm5acmu52bRlfDVZqZqIrAQugSPRSUhxjgCOUM/Mpj29wJ+v 8YlQ== X-Forwarded-Encrypted: i=1; AJvYcCVnfE1eO5NvavdztKG5OsmCJaF3RkL1sh8z73hsRs2jr8EORZ8ZpaZGiFUhbdzCZ5LzEJKxQPBNMYdA94Q=@vger.kernel.org X-Gm-Message-State: AOJu0YxxrW6vqqD74HgZrQj+fYtMpK43YD9bWixDk6qAUDMv/Y0k912V 2Wn6CmKXMVQLUmT8pCMLWZSmMFO4/Qdi0ncvl3V0HlATTTS8kokZYCYZenz9C4QiS9Dxh7bo0km 1aU6X7XVa054fzSMmZZAN+jdQY6dUXXLqVaMLG+QxqzLigWdAoLbJfSQBN88QPPl5NmwPAoXxn/ c8GRKKkodflUpZ+fWiauoVdOBq8/dfTIHyQJJGVz0i9Bvs3y+3kgzAs4hfS/HAkebUyJexKoG1k 24ppQWyruPeDlQrv7W1j77JcQ== X-Gm-Gg: AY/fxX5OeJNYGgYA2m2Oy8aUbJ5JtwdHxPZ3//sDbksLaVFNTm5z/HI9QCG2AaPld1w PjacO9jd3qlNV6wVLLnzumcGonGESG/giOVqc1+dGYja3NXikoTMuEQFk/wC3mp5Pnn6FkwOoLB 9hbHs0aD1HXIsieJTLalZdd+sNeyJDcxl0Ukqx4FiHnEp8pnUuvUlAgKyHhskCmb0XJoQYQEwvD 4Rkiy0rgRRyvYSSe6WwR9vcojIO3PYvVGxK9SdgcCJ8awP2NwyWuFJMmZHFNiAqyOdp6KXtWV1E tdNXkAd2YSPukeayYfydXneULqQWx9ACpRisEBLNm3FG9FxusuMOnt6CVJJcN0EUH4MMEQNNF9H 2rGC9YSnJ1Q16ENdMNlGwEXlzbddSihkIEC46+D4cUu3z9aITnMmbcyMQbg51ySND0wSQFp6Wxf K5ZoLP0HmyO0DCE7J9KOUOL0w0gS6l1J1oyluykJxXsgFzkC99WCs= X-Received: by 2002:a05:6870:64a0:b0:3d2:c24:30fc with SMTP id 586e51a60fabf-4044c492471mr1838014fac.48.1768592303103; Fri, 16 Jan 2026 11:38:23 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-72.dlp.protect.broadcom.com. [144.49.247.72]) by smtp-relay.gmail.com with ESMTPS id 586e51a60fabf-4044bb0a87csm377605fac.2.2026.01.16.11.38.22 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Jan 2026 11:38:23 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-34c704d5d15so4006469a91.1 for ; Fri, 16 Jan 2026 11:38:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1768592302; x=1769197102; 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=4dWnjTr3AjoXWLMl2brB8ngehg3o0HcGu3374LRPyGE=; b=K2R1lkKJa0McK6CL+LhmhlnysA+O8YjMyUDRJKjhtHmRUb4qlN6vGuE9biNvB7eQ/c 4GXkui3CnZOtPMRMXCmAAkZYNw7erggX5ikobgVQwIL+nZPWbhj9B/xvKH2yHL9+gSDD WwhBwkjd1g1x1DDj1IOB2w4PcHseRLJRjz01c= X-Forwarded-Encrypted: i=1; AJvYcCUfLC55EA0gbwdS5h8BpqvrZlsmVCV/Wdj50BJFRml0HS+I+90eVlqknUNoSLeVkPhtlrpOdGME2R5v+TA=@vger.kernel.org X-Received: by 2002:a17:90b:5485:b0:349:9d63:8511 with SMTP id 98e67ed59e1d1-35272faec68mr3198762a91.25.1768592301736; Fri, 16 Jan 2026 11:38:21 -0800 (PST) X-Received: by 2002:a17:90b:5485:b0:349:9d63:8511 with SMTP id 98e67ed59e1d1-35272faec68mr3198753a91.25.1768592301391; Fri, 16 Jan 2026 11:38:21 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35273121856sm2764909a91.15.2026.01.16.11.38.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jan 2026 11:38:20 -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: [v5, net-next 5/8] bng_en: Add ndo_features_check support Date: Sat, 17 Jan 2026 01:07:29 +0530 Message-ID: <20260116193732.157898-6-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260116193732.157898-1-bhargava.marreddy@broadcom.com> References: <20260116193732.157898-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 | 23 +++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_txrx.h | 3 +++ 3 files changed, 27 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 9e069faf2a58..dffb8c17babe 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -960,3 +960,26 @@ 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; + +#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_GSO_MASK; + + return vlan_features_check(skb, 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 Sun Feb 8 13:38: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 5C7733A1D1E for ; Fri, 16 Jan 2026 19:38:29 +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=1768592315; cv=none; b=NVL5ngCkD5y5i1P77lX5X3+FmB3ox8Snfa26/F4cMqmB2jGLCFA6Rohdy+FHoUoQ7fXJICBkqPtPCv/1FlqHqJqB+VsUqRkNbeS2ODUXOEpwCEEjiljSDnd2ZUlLGE0I4Q5s+i/Y9y2lE7cBha02QHXBqshMLV+7d2TEH3/qBAs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592315; c=relaxed/simple; bh=DqVDdrUmUgnoPczOkA2yjkr17ZFl1olwB/kfFAfs0bY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hU1qtqLJSamJPnL/Eiazr65Ty8X6mAkw4Fto0COaRSXNO4T1NqSPpIF042wEvz3d6GWY7rBl0wKsIBME5NilMUMvt4UdTdIhi+Ki7xK/enAmOHoF/0XYJzplG1A5o2uw505e9HK/+Alg5OyJcofgKOEc879WXfBQYFZ9X4Q7Ojg= 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=RkM8tTmY; 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="RkM8tTmY" Received: by mail-oa1-f97.google.com with SMTP id 586e51a60fabf-4042e22be7dso1542370fac.2 for ; Fri, 16 Jan 2026 11:38:29 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768592308; x=1769197108; 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=BMXY0UWdHBq5h06n3Vm0wEYB0m4mnzSYwCLT5X25rYI=; b=Fl6tPKwj1AoTvh7ZvgZ63uGM6LySwOFnJCXYmAv2gw/oMmiKrq9vqzVvTeP+MCF3rX hqzRYXl304TIA4rIP8Wce2GhIcppUVFAiVnsl9do8llXZZUWteqL0mqCxjjaPkrYK0eU z6SgG9PjnWERm9d8se5oFx4r8E/Cn+QvFI2fKvX518qtlCeJ52h+l85+xqCF6OwEv7J+ 5nNxe/+m0Rbowj2BEEJP3FfGqyj+YhkcfyGdCANXowSwIPnPnYa3bXqjrMQq41sVRg/f jtve4PAAkrpkfKptL5qW+Zy5IuHUIt2kW2iTExs2HdTKdDq0cO7/+H4TLNN3KAZH+ij3 kqAg== X-Forwarded-Encrypted: i=1; AJvYcCW19f8HJsjpnLGjYkp0Ooeg1SNJnrNKmtyshrnUqJWu5HjpZP1ZG7JXYSvlGo5rdIydWxsBbNbKz6wXuEQ=@vger.kernel.org X-Gm-Message-State: AOJu0YzK/4LNl6LYofl7qpqJmzyZBnjHzS8gpVNWqSEgz3SHxKO4l4u6 vuSfYxXS1iEY9UO2qodvvAZRo7mr65+iGbwNukwx14eJifP2pt3Kv/OLUdQklTP9YMVKAR5f3wE kzXSMuKxEa4Z+FJfCAsCg24wkpBgJMNmmA39RHLjpxG2gAQH9sEIRao50P2mdc9mwGu//Ik33o2 MIVJ+AlmwtHfZqb0lHrlKDqjSHVdNRMc+vikQXpd3iY6asITbkBXvknoKS8ueL/2f5ZrqbONZky dltJDLis5wSSiuYPu0Gnv7Amg== X-Gm-Gg: AY/fxX4qB7sO/jaAZ9un8Ro7TXcRUoau3Cg04bsbQV+4q4QOzxXhmU4BtiGAEmV1TQi V9Wiwxxw4iLm8K20le2lOxOrTnh8KAv7iyXh9pLv48w5GuqjL2Ll4ut1ll1dbjT00sknKt0jvJM VqAhxk/OXFlduV7VZDoB3cN9obc67u77gRWC0xfsqS/Zl1c2wtswATVy8F37kQjppyT869Cansb 3MhSGGU27IEEnnevruTKaFl3l4qID8GyVWHSvZFUm89oQ3C7c8bvTekdoKMcKOT/8X+PlgHV3ac FcA2pwYjxhUKgdkdIuXO63FIUR3GjWUNhUAW3vM3nl8PZr12V5PeV+aIrdko2YulFLG+jeBeroH lwbqdcwkY7tzeUTHRAI9aVeiIALsKkcJu7q0yLbx1j5s0qs7Lrka/5/6NLm7wkRFkLPgcnPK88R c+PJB0jo/33wgt/UDlttBf5pl5Co3wy9Wv7XuckKIybFXvVcSGodnrIQ== X-Received: by 2002:a05:6870:8916:b0:3f4:fa99:29fa with SMTP id 586e51a60fabf-4044c20e023mr1615101fac.24.1768592307676; Fri, 16 Jan 2026 11:38:27 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-118.dlp.protect.broadcom.com. [144.49.247.118]) by smtp-relay.gmail.com with ESMTPS id 586e51a60fabf-4044bb713dbsm374847fac.8.2026.01.16.11.38.27 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Jan 2026 11:38:27 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f71.google.com with SMTP id 98e67ed59e1d1-34c6cda4a92so1948087a91.3 for ; Fri, 16 Jan 2026 11:38:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1768592306; x=1769197106; 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=BMXY0UWdHBq5h06n3Vm0wEYB0m4mnzSYwCLT5X25rYI=; b=RkM8tTmYWlLGdM2EbaSgF0gw21udTKbD5DmpHPqvOAn29xOeaPMHo/wkA5177xfFK4 YoUxzdwteApgTpUvYFQqZ+16KVgJDmk7nqnS1V4RbCKxtGBAgzmZiI8Ompq6a54LtJnx GDMjtJJvKfxMwaL3H0/+Q3NfvTN/34Et4Qi+4= X-Forwarded-Encrypted: i=1; AJvYcCUDDl1Hzqcr1HXJ4MoNb9QZ33CFzSn8wcVQjI/f9aHmJhqFJIvskrn+5QW9Q2cW8pp/dHCqzJIyUdZMx6k=@vger.kernel.org X-Received: by 2002:a17:90b:3511:b0:32d:d5f1:fe7f with SMTP id 98e67ed59e1d1-35272f29b65mr3737657a91.15.1768592306300; Fri, 16 Jan 2026 11:38:26 -0800 (PST) X-Received: by 2002:a17:90b:3511:b0:32d:d5f1:fe7f with SMTP id 98e67ed59e1d1-35272f29b65mr3737645a91.15.1768592305887; Fri, 16 Jan 2026 11:38:25 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35273121856sm2764909a91.15.2026.01.16.11.38.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jan 2026 11:38:25 -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: [v5, net-next 6/8] bng_en: Add support to handle AGG events Date: Sat, 17 Jan 2026 01:07:30 +0530 Message-ID: <20260116193732.157898-7-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260116193732.157898-1-bhargava.marreddy@broadcom.com> References: <20260116193732.157898-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, 251 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h b/drivers/net= /ethernet/broadcom/bnge/bnge_hw_def.h index cae7b8ece219..d38540f5021a 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 dffb8c17babe..d6c8557fcb19 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) { @@ -219,15 +405,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 @@ -256,11 +443,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]; @@ -268,11 +459,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; } @@ -284,14 +487,25 @@ 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) + if (!skb) { + if (agg_bufs) + bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, + agg_bufs); 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; } =20 + if (agg_bufs) { + skb =3D bnge_rx_agg_netmems_skb(bn, cpr, skb, cp_cons, + agg_bufs); + if (!skb) + goto oom_next_rx; + } + if (RX_CMP_HASH_VALID(rxcmp)) { enum pkt_hash_types type; =20 @@ -467,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 Sun Feb 8 13:38:51 2026 Received: from mail-vk1-f225.google.com (mail-vk1-f225.google.com [209.85.221.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EF65D34A76D for ; Fri, 16 Jan 2026 19:38:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.225 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592319; cv=none; b=TqzSiGBvaIzGKJwMy6X2D2CNdyYf4yW+x5106+h720Wy+f6uwF4d7RSsLV42T6TmCwhDTUefUVHkmgcBaEn/VbBaH380zuvx8U1MO5GhjzMNmdUHtJMtoIfTYfLHhmE9BaVltYn9DIPB+SGVZdicUkf8NW5iGPmhVQDyXVJS6IY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592319; c=relaxed/simple; bh=ja3px7r2PA2NqumQG0F0MlUB357beD9j64TrWfVritI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RUq76XkRT/VEcXGpp7cZJqgHpGf9HvgKgSbisL2CUgcyV/Bhlm6ENhg06IPDNKTyd/M+bk3kaiHJRIe/rwg/fvGsqQCBoJUex5Yl3tJIqvdTCxmQI+HJLgrgTI/4oFnHNr32Un5U96K2b78vAi7lpegiKYLgFgQ217D0GJDiveI= 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=Be0K6WVs; arc=none smtp.client-ip=209.85.221.225 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="Be0K6WVs" Received: by mail-vk1-f225.google.com with SMTP id 71dfb90a1353d-56378a18ba4so783187e0c.1 for ; Fri, 16 Jan 2026 11:38:34 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768592313; x=1769197113; 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=dedGYRJvx8jJXaMmFCBckfM9zhXu28AKEa9fyjbpzaY=; b=fmNhedpB/8B9AebxIQpjc4jRDYddG+DE4hxYySLvgmXBvsuTvd3Ilo0AyKLrmC4MWC CVE4gOnlYRB9pxTN/PC9SMQg2FhNJgJLJStRnQCr5ftUfozNFdMMvWT9uQUO/udxWVG0 8dV7i2OGziSH2xPDu5yzwMbg46/zsBcq2yXOk17C4IaRehMPIeVXBgamH+a3xKC8LK8z BLSl5EZM7tPA+rgnxbbOM5O5h6YlXP2DQlt7PAX4KpLmJJhbIznwGHZVIs63BEP6xHJ1 roQkTvSztaW9hB+rBsncOTNB0j2BO0XpXcrtYKWnrw6JBWVROqWyMJZ6x6HIKw3OGNwW bLtA== X-Forwarded-Encrypted: i=1; AJvYcCXETrH4H5YYsm88z8L+OUWXsgIbE91ReQ+J+eAL3+lhOKKgG11e2OUM9vanWzQ3oQM56uSf8go2aicbfiM=@vger.kernel.org X-Gm-Message-State: AOJu0Yy4iBel0UVckh6xRt5Os738aCWTLEtIPsg7mLmC7947keG/BocP BgD7Htvnef8kZlw7rQ3+13G+e5Uyf39u1askOFMy+7rFfmwSwpEYMVztsgCXbcYDFK0UbCZId/h zZIOpoNZp1yQGP4ASBEsl0pjk0lnRoZU4DnhtRZoVSdh8Gz5QJAz4Jyg6M+ujj0lp5D1vWV065x NgoCAWeD0OYect1OB8kbE/d1mxsuhW1eRAohmhxj0U+4ztO9XKMULC/8qXLgttwU83IcyzkG4ps VuuN1+RpmOzZ4GdobwiyO9c9Q== X-Gm-Gg: AY/fxX4Rbj/6lR7B2OxIgb8+rTcmnnQwZUu5QYSKKcmI32cBc9htCL3TIq1JOxDZAF9 H/pU8kyskHqrKgDqYT55RgxoT2z5xEJftZZ3vutUoDSlMQAUBV9GKN0sff679czay8H3WlaNvVY dmt/0LRWrnQBdG9reskguXdV0HNPNPeC26P/uLjKCEyhmKfSmBWnmvzHhXYXQ5HeGQjZ7YaeS1y wfq6uwmob2mTvbUFSlXM+MKrMGcMNwv4E3xmjhWcMu2dMtLDhW27jLepvAIbhr1IfYSjYeA98zo IxtVlS//kcBgeKS9QveQwm8VDAXtY5YEnWmmesQX8FLRA6OkXw6kl+YWH7kUTCb/I0wQVwWqDBt FMAzGkYGHxrzickLQQAtbouknzx+s6K9DutGmq1Xh3FFixMwqUMB0Jvur+oPhyhAi0yOLQPpVaF ZKhdHoLdWe/yleZpCYJO+/9qigL4mhm+y6IMaxSXv8x+u6PaEj7VU= X-Received: by 2002:a05:6122:3c82:b0:563:6566:b2d9 with SMTP id 71dfb90a1353d-563b73b90b8mr1040422e0c.18.1768592313074; Fri, 16 Jan 2026 11:38:33 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-72.dlp.protect.broadcom.com. [144.49.247.72]) by smtp-relay.gmail.com with ESMTPS id 71dfb90a1353d-563b710b43esm410392e0c.7.2026.01.16.11.38.32 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Jan 2026 11:38:33 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-34c37b8dc4fso4331907a91.2 for ; Fri, 16 Jan 2026 11:38:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1768592311; x=1769197111; 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=dedGYRJvx8jJXaMmFCBckfM9zhXu28AKEa9fyjbpzaY=; b=Be0K6WVsupRWPIxTHstsrS+M0qOaeKldvf/GZFjwpD3GVZlSdCjk/8b8wBX8Djn/lG T1XhBKjE329shST4DLS7Wans3nrkTqmO7e7CC7yHrOPDptGsUTBU3YTGcB1ZD+EeOesV ubLDL4WhKAe6zYoKH4nXIsugOleGP7A+quykk= X-Forwarded-Encrypted: i=1; AJvYcCVQQ6ptDtvlfatjdY6DJDSrT762uqE1hnEwVDIs7uKKbajwf/Sxl7mavm1W99oNWqFEwTbLZWkMUWHfE4c=@vger.kernel.org X-Received: by 2002:a17:90b:1fcd:b0:349:5b1b:78bf with SMTP id 98e67ed59e1d1-352732559c7mr3175180a91.23.1768592311150; Fri, 16 Jan 2026 11:38:31 -0800 (PST) X-Received: by 2002:a17:90b:1fcd:b0:349:5b1b:78bf with SMTP id 98e67ed59e1d1-352732559c7mr3175158a91.23.1768592310693; Fri, 16 Jan 2026 11:38:30 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35273121856sm2764909a91.15.2026.01.16.11.38.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jan 2026 11:38:30 -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: [v5, net-next 7/8] bng_en: Add TPA related functions Date: Sat, 17 Jan 2026 01:07:31 +0530 Message-ID: <20260116193732.157898-8-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260116193732.157898-1-bhargava.marreddy@broadcom.com> References: <20260116193732.157898-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 | 248 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.c | 123 +++++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.h | 47 ++++ 3 files changed, 418 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h b/drivers/net= /ethernet/broadcom/bnge/bnge_hw_def.h index d38540f5021a..1cc39cd44291 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h @@ -212,4 +212,252 @@ struct rx_agg_cmp { #define HWRM_RING_ALLOC_AGG 0x4 #define HWRM_RING_ALLOC_CMPL 0x8 #define HWRM_RING_ALLOC_NQ 0x10 + +#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) + +struct rx_tpa_start_cmp { + __le32 rx_tpa_start_cmp_len_flags_type; + #define RX_TPA_START_CMP_TYPE (0x3f << 0) + #define RX_TPA_START_CMP_FLAGS (0x3ff << 6) + #define RX_TPA_START_CMP_FLAGS_SHIFT 6 + #define RX_TPA_START_CMP_FLAGS_ERROR (0x1 << 6) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT (0x7 << 7) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_SHIFT 7 + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 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 (0x1 << 10) + #define RX_TPA_START_CMP_FLAGS_TIMESTAMP (0x1 << 11) + #define RX_TPA_START_CMP_FLAGS_ITYPES (0xf << 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 (0xffff << 16) + #define RX_TPA_START_CMP_LEN_SHIFT 16 + + u32 rx_tpa_start_cmp_opaque; + __le32 rx_tpa_start_cmp_misc_v1; + #define RX_TPA_START_CMP_V1 (0x1 << 0) + #define RX_TPA_START_CMP_RSS_HASH_TYPE (0x7f << 9) + #define RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT 9 + #define RX_TPA_START_CMP_V3_RSS_HASH_TYPE (0x1ff << 7) + #define RX_TPA_START_CMP_V3_RSS_HASH_TYPE_SHIFT 7 + #define RX_TPA_START_CMP_AGG_ID (0x7f << 25) + #define RX_TPA_START_CMP_AGG_ID_SHIFT 25 + #define RX_TPA_START_CMP_AGG_ID_P5 (0xffff << 16) + #define RX_TPA_START_CMP_AGG_ID_SHIFT_P5 16 + #define RX_TPA_START_CMP_METADATA1 (0xf << 28) + #define RX_TPA_START_CMP_METADATA1_SHIFT 28 + #define RX_TPA_START_METADATA1_TPID_SEL (0x7 << 28) + #define RX_TPA_START_METADATA1_TPID_8021Q (0x1 << 28) + #define RX_TPA_START_METADATA1_TPID_8021AD (0x0 << 28) + #define RX_TPA_START_METADATA1_VALID (0x8 << 28) + + __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_P5) >> RX_TPA_START_CMP_AGG_ID_SHIFT_P5) + +#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) + +struct rx_tpa_start_cmp_ext { + __le32 rx_tpa_start_cmp_flags2; + #define RX_TPA_START_CMP_FLAGS2_IP_CS_CALC (0x1 << 0) + #define RX_TPA_START_CMP_FLAGS2_L4_CS_CALC (0x1 << 1) + #define RX_TPA_START_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2) + #define RX_TPA_START_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3) + #define RX_TPA_START_CMP_FLAGS2_IP_TYPE (0x1 << 8) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_VALID (0x1 << 9) + #define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT (0x3 << 10) + #define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT_SHIFT 10 + #define RX_TPA_START_CMP_V3_FLAGS2_T_IP_TYPE (0x1 << 10) + #define RX_TPA_START_CMP_V3_FLAGS2_AGG_GRO (0x1 << 11) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL (0xffff << 16) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_SHIFT 16 + + __le32 rx_tpa_start_cmp_metadata; + __le32 rx_tpa_start_cmp_cfa_code_v2; + #define RX_TPA_START_CMP_V2 (0x1 << 0) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_MASK (0x7 << 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 (0xffff << 16) + #define RX_TPA_START_CMPL_CFA_CODE_SHIFT 16 + #define RX_TPA_START_CMP_METADATA0_TCI_MASK (0xffff << 16) + #define RX_TPA_START_CMP_METADATA0_VID_MASK (0x0fff << 16) + #define RX_TPA_START_CMP_METADATA0_SFT 16 + __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) + +struct rx_tpa_end_cmp { + __le32 rx_tpa_end_cmp_len_flags_type; + #define RX_TPA_END_CMP_TYPE (0x3f << 0) + #define RX_TPA_END_CMP_FLAGS (0x3ff << 6) + #define RX_TPA_END_CMP_FLAGS_SHIFT 6 + #define RX_TPA_END_CMP_FLAGS_PLACEMENT (0x7 << 7) + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_SHIFT 7 + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 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 (0x1 << 10) + #define RX_TPA_END_CMP_FLAGS_ITYPES (0xf << 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 (0xffff << 16) + #define RX_TPA_END_CMP_LEN_SHIFT 16 + + u32 rx_tpa_end_cmp_opaque; + __le32 rx_tpa_end_cmp_misc_v1; + #define RX_TPA_END_CMP_V1 (0x1 << 0) + #define RX_TPA_END_CMP_AGG_BUFS (0x3f << 1) + #define RX_TPA_END_CMP_AGG_BUFS_SHIFT 1 + #define RX_TPA_END_CMP_TPA_SEGS (0xff << 8) + #define RX_TPA_END_CMP_TPA_SEGS_SHIFT 8 + #define RX_TPA_END_CMP_PAYLOAD_OFFSET (0xff << 16) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT 16 + #define RX_TPA_END_CMP_AGG_ID (0xffff << 16) + #define RX_TPA_END_CMP_AGG_ID_SHIFT 16 + + __le32 rx_tpa_end_cmp_tsdelta; + #define RX_TPA_END_GRO_TS (0x1 << 31) +}; + +#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))) + +struct rx_tpa_end_cmp_ext { + __le32 rx_tpa_end_cmp_dup_acks; + #define RX_TPA_END_CMP_TPA_DUP_ACKS (0xf << 0) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_P5 (0xff << 16) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT_P5 16 + #define RX_TPA_END_CMP_AGG_BUFS_P5 (0xff << 24) + #define RX_TPA_END_CMP_AGG_BUFS_SHIFT_P5 24 + + __le32 rx_tpa_end_cmp_seg_len; + #define RX_TPA_END_CMP_TPA_SEG_LEN (0xffff << 0) + + __le32 rx_tpa_end_cmp_errors_v2; + #define RX_TPA_END_CMP_V2 (0x1 << 0) + #define RX_TPA_END_CMP_ERRORS (0x3 << 1) + #define RX_TPA_END_CMP_ERRORS_P5 (0x7 << 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) + + 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_P5) >> \ + RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT_P5) + +#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_P5) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT_P5) + +#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..7800c870d6d3 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,29 @@ 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 +1254,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..1d700e74d106 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -153,6 +153,46 @@ 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_AGG_IDX_BMAP_SIZE (MAX_TPA / BITS_PER_LONG) +struct bnge_tpa_idx_map { + u16 agg_id_tbl[1024]; + unsigned long agg_idx_bmap[BNGE_AGG_IDX_BMAP_SIZE]; +}; + +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; + +#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) + + 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 +285,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 +434,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 Sun Feb 8 13:38:51 2026 Received: from mail-qv1-f98.google.com (mail-qv1-f98.google.com [209.85.219.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 163DA3A1D02 for ; Fri, 16 Jan 2026 19:38:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.98 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592325; cv=none; b=UIcUVGdDJTJnNEzfANby74VcdCSAp3/Em9LfxYOi9yoys4eiOI3JVJFW83+yzMh+/tGNHziS3LS971iiBszyZ1/VVCTBYMDQkp1MHXarwb4sAI9+1AJ6frRzNbRkqqXjJzPGPHFoz0pI0wIKqcpOUremRGyVMhOJ9lwNXHuCex0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768592325; c=relaxed/simple; bh=q0Mr3xmQ9t1PW7VDR9LFlbYRKMVXh1lD/Cts1exQZ+0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cS1pzbPvdd+t5l95Q/i54V6LUWsaqCEECDnhYTttfvY4x/wLlmDy8d1cVTeJvq3z5p3AH9piEkej/vHAv30bVcUhru+PstMrQNgT9Jgxs4ofx5ePHMK81m9IpH5uL2uwdHW/dAuSNw+G+eyGovF+3BgSetJ+4WqzpGGkCRpbvtk= 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=ZiDI7vAU; arc=none smtp.client-ip=209.85.219.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="ZiDI7vAU" Received: by mail-qv1-f98.google.com with SMTP id 6a1803df08f44-88a37cb5afdso48031596d6.0 for ; Fri, 16 Jan 2026 11:38:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768592318; x=1769197118; 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=mE5sZL9lSqyNObwFvV9SbkGR3tD8SkuFH528O+nmWiM=; b=GvukrrwTjKu5ugQ1ZlK6FGPYcRlkuLRj+vWh90e2PEdm5KkayToX8zrYPRoy0HOr5W lRogkh1uUaLmfx8p/jwhRpCGg88ZT5UiKuBDAai/S6tPK8qvS25U0YhX6V5pJBZXmpzA cUXwBYUTbV5GCkfu2quKE8E9cP1jARkb0eprz3w1ksW6roaRiiInVntPlsoLaeTR9bWG XkNZyqErqvQi/PDA53TJIqzjMcRKCCe3T/M/oWPcl6aIPus4C/YNP8hXTyvr5yP/qwR7 vYgWGCl49Xtyow3dCipv3OKDAV2cY+mliUo4BfoI2ZPz5OxkXILDK66hxmThLgi0HJ9Y G/uA== X-Forwarded-Encrypted: i=1; AJvYcCVV5gzE+6vUG86h+F0cizgdMlP2XzrsUstBqpRr8N/n0Jxwy+ZAh5fi0smDEHYXg+ngfl+V9UXmOxJBZW4=@vger.kernel.org X-Gm-Message-State: AOJu0YwSxPvPOuqexrnGV6s2qC6/nIpWw447T0lwvlDn5dzCpje/qnyJ d+6MS+SQpv2n6zKSzjHPe7W8XMSMGo7Z8SNRZHj3eeX/0xT4icgSd9xtZH+ZyP8KMJMIQHSQ9w6 5TePPKpRbrwXK+At+YTu3gNkGacts9/1slqh32lqg/fXFX6pnoumUkNUAuSTMj0tIt1Gyk6NYNJ TfMlkiyxeytws8NpAWwRm6AFdqEtSP6HpNydi6i8dWYOgTQW+CeTZAa5n6m4oh15xrBpFxU4qBD aiZBPK6o/pibZIpwjH70T/XbQ== X-Gm-Gg: AY/fxX5y4yXckwxT+6wXGxOyZlLQDnvry8FRhmRsachNLGZhwahhb8uC8UOWlrKttEv FcHLB7weTK8wtqvTmlfYJvxhbHooedmr2p7grkF65kBRx77udFCM04zdEQllHs1GAYFtZXZz5JZ 1tSv/8o+MfSyempL6d+On23+xOXGM4ZLE49CPtHJbxHWK2DFsAFplGbZzlvm1wF/vWS6LpSCRMG +FdNXfNh0fg3mF/qfJmb3IwlODIxfvyluD5wQgCz0+pJr9WmAwfsaVX7GgrR8N8rxeDsLHI666e jtmrLd+l/qUfnBRp5x4N1yS2JIC2u5cj1Rguw1cEb93BRp7kFBk6Egma5GchZ4CKLz30vvOBfRY 0sWwVaZEjmofy9g/ymSYUkwIMiTxF6gLPAwgvlqfv/h3t+316FmRQTXzDHLDaCmOFx48k5L1l+y goPnl7cEYWnEHM39yzOX0loiA/M5BAeYYfK+doRbICvpyMeiI2f6s= X-Received: by 2002:a05:6214:f28:b0:88a:2ed6:252 with SMTP id 6a1803df08f44-89389f8586emr99714516d6.5.1768592317602; Fri, 16 Jan 2026 11:38:37 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-72.dlp.protect.broadcom.com. [144.49.247.72]) by smtp-relay.gmail.com with ESMTPS id 6a1803df08f44-8942e6e6129sm1919886d6.26.2026.01.16.11.38.37 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Jan 2026 11:38:37 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-34c93f0849dso2445492a91.1 for ; Fri, 16 Jan 2026 11:38:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1768592316; x=1769197116; 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=mE5sZL9lSqyNObwFvV9SbkGR3tD8SkuFH528O+nmWiM=; b=ZiDI7vAU/098P0WjrfHjFoZTjzhaOl7F8s/ImfGFXLfXUf4OmA4mWOrJBOeeOSo8oc nyMuNIysKqdMtE46hg/fLDD2eEYT3oQJXT8rjssfyijz/uVxBrphLaP9fwkJ2qbpksXZ aH9KtjpUImSdTdXPdBaLb1mrhoQa/6w9TB4wI= X-Forwarded-Encrypted: i=1; AJvYcCXhej8xghZMwh2Str+C2YU9OS/GXeXT1Noa5116bCqWmtIAuUSSs0ctRiiuPrwI0GC1Vu55Qz91fP8etrM=@vger.kernel.org X-Received: by 2002:a17:90b:2543:b0:34c:2aac:21a7 with SMTP id 98e67ed59e1d1-35267816ab8mr8154313a91.7.1768592316156; Fri, 16 Jan 2026 11:38:36 -0800 (PST) X-Received: by 2002:a17:90b:2543:b0:34c:2aac:21a7 with SMTP id 98e67ed59e1d1-35267816ab8mr8154276a91.7.1768592315524; Fri, 16 Jan 2026 11:38:35 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35273121856sm2764909a91.15.2026.01.16.11.38.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jan 2026 11:38:35 -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: [v5, net-next 8/8] bng_en: Add support for TPA events Date: Sat, 17 Jan 2026 01:07:32 +0530 Message-ID: <20260116193732.157898-9-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260116193732.157898-1-bhargava.marreddy@broadcom.com> References: <20260116193732.157898-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_netdev.h | 3 +- .../net/ethernet/broadcom/bnge/bnge_txrx.c | 435 +++++++++++++++++- 5 files changed, 520 insertions(+), 12 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 7800c870d6d3..0f28aae29bad 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -2278,6 +2278,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]; @@ -2312,6 +2333,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_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 1d700e74d106..658620727957 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -159,10 +159,9 @@ enum { #define MAX_TPA_MASK (MAX_TPA - 1) #define MAX_TPA_SEGS 0x3f =20 -#define BNGE_AGG_IDX_BMAP_SIZE (MAX_TPA / BITS_PER_LONG) struct bnge_tpa_idx_map { u16 agg_id_tbl[1024]; - unsigned long agg_idx_bmap[BNGE_AGG_IDX_BMAP_SIZE]; + DECLARE_BITMAP(agg_idx_bmap, MAX_TPA); }; =20 struct bnge_tpa_info { diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index d6c8557fcb19..bc5a387aae48 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%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 %x\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; @@ -303,6 +481,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) { @@ -395,6 +775,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 @@ -427,6 +808,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 *) @@ -441,6 +827,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); @@ -475,7 +883,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; } @@ -490,7 +899,7 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bnge= _cp_ring_info *cpr, if (!skb) { if (agg_bufs) bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, - agg_bufs); + agg_bufs, false); goto oom_next_rx; } } else { @@ -501,7 +910,7 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bnge= _cp_ring_info *cpr, =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 +1001,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