From: Vikas Gupta <vikas.gupta@broadcom.com>
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,
bhargava.marreddy@broadcom.com, rahul-rg.gupta@broadcom.com,
vsrama-krishna.nemani@broadcom.com,
rajashekar.hudumula@broadcom.com, dharmender.garg@broadcom.com,
ajit.khaparde@broadcom.com,
Vikas Gupta <vikas.gupta@broadcom.com>
Subject: [PATCH net-next 03/11] bnge: add NTUPLE/ARFS VNIC
Date: Fri, 14 Aug 2026 06:44:27 +0530 [thread overview]
Message-ID: <20260814011435.194631-4-vikas.gupta@broadcom.com> (raw)
In-Reply-To: <20260814011435.194631-1-vikas.gupta@broadcom.com>
Initialize the second VNIC, which is specifically used for the
NTUPLE/ARFS feature. This VNIC helps support the aRFS/NTUPLE
functionality. With this change, the total number of VNICs becomes 2.
Add bnge_set_dflt_rfs() to configure the default NTUPLE feature state
at netdev allocation time.
Also, allocate and configure the ARFS VNIC.
Signed-off-by: Vikas Gupta <vikas.gupta@broadcom.com>
Reviewed-by: Dharmender Garg <dharmender.garg@broadcom.com>
---
drivers/net/ethernet/broadcom/bnge/bnge.h | 6 ++
.../net/ethernet/broadcom/bnge/bnge_core.c | 7 ++
.../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 27 ++++++++
.../ethernet/broadcom/bnge/bnge_hwrm_lib.h | 1 +
.../net/ethernet/broadcom/bnge/bnge_netdev.c | 31 +++++++--
.../net/ethernet/broadcom/bnge/bnge_netdev.h | 1 +
.../net/ethernet/broadcom/bnge/bnge_resc.c | 69 ++++++++++++++++++-
.../net/ethernet/broadcom/bnge/bnge_resc.h | 1 +
.../net/ethernet/broadcom/bnge/bnge_vnic.c | 29 +++++++-
.../net/ethernet/broadcom/bnge/bnge_vnic.h | 7 +-
10 files changed, 170 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index bde54ba5d50f..d43c67232a86 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -74,6 +74,7 @@ enum {
BNGE_EN_STRIP_VLAN = BIT_ULL(2),
BNGE_EN_SHARED_CHNL = BIT_ULL(3),
BNGE_EN_UDP_GSO_SUPP = BIT_ULL(4),
+ BNGE_EN_ARFS_CAP = BIT_ULL(5),
};
#define BNGE_EN_ROCE (BNGE_EN_ROCE_V1 | BNGE_EN_ROCE_V2)
@@ -218,6 +219,11 @@ static inline bool bnge_is_roce_en(struct bnge_dev *bd)
return bd->flags & BNGE_EN_ROCE;
}
+static inline bool bnge_is_arfs_cap(struct bnge_dev *bd)
+{
+ return bd->flags & BNGE_EN_ARFS_CAP;
+}
+
static inline bool bnge_is_agg_reqd(struct bnge_dev *bd)
{
if (bd->netdev) {
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
index 68b74eb2c3a2..90e61a53a77d 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
@@ -93,6 +93,13 @@ static int bnge_func_qrcaps_qcfg(struct bnge_dev *bd)
return rc;
}
+ rc = bnge_hwrm_cfa_adv_flow_mgnt_qcaps(bd);
+ if (rc) {
+ dev_warn(bd->dev, "hwrm query adv flow mgnt failure rc: %d\n",
+ rc);
+ return rc;
+ }
+
rc = bnge_hwrm_vnic_qcaps(bd);
if (rc) {
dev_err(bd->dev, "vnic caps failure rc: %d\n", rc);
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
index 91d246c8dcf2..dd48c60aeef4 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
@@ -1636,3 +1636,30 @@ int bnge_hwrm_port_qstats(struct bnge_dev *bd, u8 flags)
return bnge_hwrm_req_send(bd, req);
}
+
+int bnge_hwrm_cfa_adv_flow_mgnt_qcaps(struct bnge_dev *bd)
+{
+ struct hwrm_cfa_adv_flow_mgnt_qcaps_output *resp;
+ struct hwrm_cfa_adv_flow_mgnt_qcaps_input *req;
+ u32 flags;
+ int rc;
+
+ rc = bnge_hwrm_req_init(bd, req, HWRM_CFA_ADV_FLOW_MGNT_QCAPS);
+ if (rc)
+ return rc;
+
+ resp = bnge_hwrm_req_hold(bd, req);
+ rc = bnge_hwrm_req_send(bd, req);
+ if (rc)
+ goto err_hwrm_drop;
+
+ flags = le32_to_cpu(resp->flags);
+
+ if (flags &
+ CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_NTUPLE_FLOW_RX_EXT_IP_PROTO_SUPPORTED)
+ bd->fw_cap |= BNGE_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO;
+
+err_hwrm_drop:
+ bnge_hwrm_req_drop(bd, req);
+ return rc;
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
index ae03041c36ac..2ae8ec9f33d3 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
@@ -67,4 +67,5 @@ int bnge_hwrm_shutdown_link(struct bnge_dev *bd);
int bnge_hwrm_port_qstats(struct bnge_dev *bd, u8 flags);
int bnge_hwrm_port_qstats_ext(struct bnge_dev *bd, u8 flags);
int bnge_hwrm_func_qstat_ext(struct bnge_dev *bd, struct bnge_stats_mem *stats);
+int bnge_hwrm_cfa_adv_flow_mgnt_qcaps(struct bnge_dev *bd);
#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 9e64b1933c02..0f5e46937828 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
@@ -1149,12 +1149,10 @@ static int bnge_alloc_vnic_attributes(struct bnge_net *bn)
static int bnge_alloc_vnics(struct bnge_net *bn)
{
- int num_vnics;
+ int num_vnics = 1;
- /* Allocate only 1 VNIC for now
- * Additional VNICs will be added based on RFS/NTUPLE in future patches
- */
- num_vnics = 1;
+ if (bn->priv_flags & BNGE_NET_EN_NTUPLE)
+ num_vnics++;
bn->vnic_info = kzalloc_objs(struct bnge_vnic_info, num_vnics);
if (!bn->vnic_info)
@@ -1320,6 +1318,10 @@ static int bnge_alloc_core(struct bnge_net *bn)
bn->vnic_info[BNGE_VNIC_DEFAULT].flags |= BNGE_VNIC_RSS_FLAG |
BNGE_VNIC_MCAST_FLAG |
BNGE_VNIC_UCAST_FLAG;
+ if (bn->priv_flags & BNGE_NET_EN_NTUPLE)
+ bn->vnic_info[BNGE_VNIC_NTUPLE].flags |= BNGE_VNIC_RSS_FLAG |
+ BNGE_VNIC_NTUPLE_FLAG;
+
rc = bnge_alloc_vnic_attributes(bn);
if (rc)
goto err_free_core;
@@ -2546,6 +2548,12 @@ static int bnge_init_chip(struct bnge_net *bn)
if (rc)
goto err_out;
+ if (bn->priv_flags & BNGE_NET_EN_NTUPLE) {
+ rc = bnge_alloc_rfs_vnic(bn);
+ if (rc)
+ goto err_out;
+ }
+
if (bd->rss_cap & BNGE_RSS_CAP_RSS_HASH_TYPE_DELTA)
bnge_hwrm_update_rss_hash_cfg(bn);
@@ -3233,6 +3241,17 @@ static void bnge_init_ring_params(struct bnge_net *bn)
bn->netdev->cfg->hds_thresh = max(BNGE_DEFAULT_RX_COPYBREAK, rx_size);
}
+static void bnge_set_dflt_rfs(struct bnge_net *bn)
+{
+ bn->netdev->hw_features |= NETIF_F_NTUPLE;
+ bn->netdev->features &= ~NETIF_F_NTUPLE;
+ bn->priv_flags &= ~BNGE_NET_EN_NTUPLE;
+ if (bnge_is_arfs_cap(bn->bd)) {
+ bn->priv_flags |= BNGE_NET_EN_NTUPLE;
+ bn->netdev->features |= NETIF_F_NTUPLE;
+ }
+}
+
int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs)
{
struct net_device *netdev;
@@ -3339,6 +3358,8 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs)
bnge_set_ring_params(bd);
bnge_init_l2_fltr_tbl(bn);
+ bnge_set_dflt_rfs(bn);
+
bnge_init_mac_addr(bd);
rc = bnge_probe_phy(bn, true);
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h
index ee649cc644db..c47a874df4ba 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h
@@ -152,6 +152,7 @@ enum {
BNGE_NET_EN_GRO = BIT(0),
BNGE_NET_EN_LRO = BIT(1),
BNGE_NET_EN_JUMBO = BIT(2),
+ BNGE_NET_EN_NTUPLE = BIT(3),
};
#define BNGE_NET_EN_TPA (BNGE_NET_EN_GRO | BNGE_NET_EN_LRO)
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
index 69a894b52485..e4090982099b 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
@@ -178,6 +178,16 @@ static int bnge_adjust_rings(struct bnge_dev *bd, u16 *rx,
return bnge_fix_rings_count(rx, tx, max_nq, sh);
}
+static unsigned int bnge_get_max_func_rss_ctxs(struct bnge_dev *bd)
+{
+ return bd->hw_resc.max_rsscos_ctxs;
+}
+
+static unsigned int bnge_get_max_func_vnics(struct bnge_dev *bd)
+{
+ return bd->hw_resc.max_vnics;
+}
+
int bnge_cal_nr_rss_ctxs(u16 rx_rings)
{
if (!rx_rings)
@@ -190,11 +200,24 @@ int bnge_cal_nr_rss_ctxs(u16 rx_rings)
static u16 bnge_get_total_rss_ctxs(struct bnge_dev *bd,
struct bnge_hw_rings *hwr)
{
- return bnge_cal_nr_rss_ctxs(hwr->grp);
+ u16 rss_ctx = bnge_cal_nr_rss_ctxs(hwr->grp);
+
+ rss_ctx *= hwr->vnic;
+
+ return rss_ctx;
}
static u16 bnge_get_total_vnics(struct bnge_dev *bd)
{
+ if (bd->netdev) {
+ struct bnge_net *bn = netdev_priv(bd->netdev);
+
+ if (bn->priv_flags & BNGE_NET_EN_NTUPLE)
+ return 2;
+ } else if (bnge_is_arfs_cap(bd)) {
+ return 2;
+ }
+
return 1;
}
@@ -563,6 +586,47 @@ static int bnge_alloc_rss_indir_tbl(struct bnge_dev *bd)
return 0;
}
+/* If runtime conditions support RFS */
+bool bnge_arfs_capable(struct bnge_dev *bd, bool new_rss_ctx)
+{
+ struct bnge_hw_rings hwr = {};
+ int max_vnics, max_rss_ctxs;
+
+ hwr.grp = bd->rx_nr_rings;
+ hwr.vnic = bnge_get_total_vnics(bd);
+ if (new_rss_ctx)
+ hwr.vnic++;
+ hwr.rss_ctx = bnge_get_total_rss_ctxs(bd, &hwr);
+ max_vnics = bnge_get_max_func_vnics(bd);
+ max_rss_ctxs = bnge_get_max_func_rss_ctxs(bd);
+
+ if (hwr.vnic > max_vnics || hwr.rss_ctx > max_rss_ctxs) {
+ if (bd->rx_nr_rings > 1)
+ dev_warn(bd->dev,
+ "Not enough resources to support NTUPLE filters\n");
+ return false;
+ }
+
+ /* Do not reduce VNIC and RSS ctx reservations. There is a FW
+ * issue that will mess up the default VNIC if we reduce the
+ * reservations.
+ */
+ if (hwr.vnic <= bd->hw_resc.resv_vnics &&
+ hwr.rss_ctx <= bd->hw_resc.resv_rsscos_ctxs)
+ return true;
+
+ bnge_hwrm_reserve_rings(bd, &hwr);
+ if (hwr.vnic <= bd->hw_resc.resv_vnics &&
+ hwr.rss_ctx <= bd->hw_resc.resv_rsscos_ctxs)
+ return true;
+
+ dev_warn(bd->dev, "Unable to reserve resources to support NTUPLE filters\n");
+ hwr.vnic = 1;
+ hwr.rss_ctx = 0;
+ bnge_hwrm_reserve_rings(bd, &hwr);
+ return false;
+}
+
int bnge_net_init_dflt_config(struct bnge_dev *bd)
{
struct bnge_hw_resc *hw_resc;
@@ -572,6 +636,9 @@ int bnge_net_init_dflt_config(struct bnge_dev *bd)
if (rc)
return rc;
+ if (bnge_arfs_capable(bd, false))
+ bd->flags |= BNGE_EN_ARFS_CAP;
+
rc = bnge_net_init_dflt_rings(bd, true);
if (rc)
goto err_free_tbl;
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
index b62a634669f6..1e55fbe6985b 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
@@ -75,6 +75,7 @@ void bnge_aux_init_dflt_config(struct bnge_dev *bd);
u32 bnge_get_rxfh_indir_size(struct bnge_dev *bd);
int bnge_cal_nr_rss_ctxs(u16 rx_rings);
bool bnge_aux_has_enough_resources(struct bnge_dev *bd);
+bool bnge_arfs_capable(struct bnge_dev *bd, bool new_rss_ctx);
static inline u32
bnge_adjust_pow_two(u32 total_ent, u16 ent_per_blk)
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_vnic.c b/drivers/net/ethernet/broadcom/bnge/bnge_vnic.c
index 80b4ad77c659..c79eb403844a 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_vnic.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_vnic.c
@@ -42,7 +42,11 @@ void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic)
for (i = 0; i < tbl_size; i++) {
u16 ring_id, j;
- j = bd->rss_indir_tbl[i];
+ if (vnic->flags & BNGE_VNIC_NTUPLE_FLAG)
+ j = ethtool_rxfh_indir_default(i, bd->rx_nr_rings);
+ else
+ j = bd->rss_indir_tbl[i];
+
rxr = &bn->rx_ring[j];
ring_id = rxr->rx_ring_struct.fw_ring_id;
@@ -98,3 +102,26 @@ int bnge_setup_vnic(struct bnge_net *bn, struct bnge_vnic_info *vnic)
}
return rc;
}
+
+static int bnge_alloc_and_setup_vnic(struct bnge_net *bn,
+ struct bnge_vnic_info *vnic,
+ u16 rx_rings)
+{
+ int rc;
+
+ rc = bnge_hwrm_vnic_alloc(bn->bd, vnic, rx_rings);
+ if (rc) {
+ netdev_err(bn->netdev, "hwrm vnic %u alloc failure rc: %d\n",
+ vnic->vnic_id, rc);
+ return rc;
+ }
+ return bnge_setup_vnic(bn, vnic);
+}
+
+int bnge_alloc_rfs_vnic(struct bnge_net *bn)
+{
+ struct bnge_vnic_info *vnic;
+
+ vnic = &bn->vnic_info[BNGE_VNIC_NTUPLE];
+ return bnge_alloc_and_setup_vnic(bn, vnic, bn->bd->rx_nr_rings);
+}
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_vnic.h b/drivers/net/ethernet/broadcom/bnge/bnge_vnic.h
index 30281e26f39f..93c6d736cbeb 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_vnic.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_vnic.h
@@ -21,13 +21,15 @@ struct bnge_l2_filter;
#define BNGE_MAX_UC_ADDRS 4
enum {
- BNGE_VNIC_DEFAULT = 0
+ BNGE_VNIC_DEFAULT = 0,
+ BNGE_VNIC_NTUPLE = 1
};
enum {
BNGE_VNIC_RSS_FLAG = BIT(0),
BNGE_VNIC_MCAST_FLAG = BIT(1),
- BNGE_VNIC_UCAST_FLAG = BIT(2)
+ BNGE_VNIC_UCAST_FLAG = BIT(2),
+ BNGE_VNIC_NTUPLE_FLAG = BIT(3)
};
struct bnge_vnic_info {
@@ -59,4 +61,5 @@ int bnge_hwrm_vnic_rss_cfg(struct bnge_net *bn,
struct bnge_vnic_info *vnic);
int bnge_setup_vnic(struct bnge_net *bn, struct bnge_vnic_info *vnic);
void bnge_set_dflt_rss_indir_tbl(struct bnge_dev *bd);
+int bnge_alloc_rfs_vnic(struct bnge_net *bn);
#endif /* _BNGE_VNIC_H_ */
--
2.47.1
next prev parent reply other threads:[~2026-08-14 1:15 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-14 1:14 [PATCH net-next 00/11] add features to bnge Vikas Gupta
2026-08-14 1:14 ` [PATCH net-next 01/11] bnge: update HSI Vikas Gupta
2026-08-14 1:14 ` [PATCH net-next 02/11] bnge: restructure VNIC and filter code Vikas Gupta
2026-08-14 1:14 ` Vikas Gupta [this message]
2026-08-14 1:14 ` [PATCH net-next 04/11] bnge: add helper functions for multi RSS contexts Vikas Gupta
2026-08-14 1:14 ` [PATCH net-next 05/11] bnge: add RXFH ethtool support Vikas Gupta
2026-08-14 1:14 ` [PATCH net-next 06/11] bnge: add ethtool support to manage RSS contexts Vikas Gupta
2026-08-14 1:14 ` [PATCH net-next 07/11] bnge: remove refcount from L2 filter Vikas Gupta
2026-08-14 1:14 ` [PATCH net-next 08/11] bnge: add NTUPLE filter infrastructure Vikas Gupta
2026-08-17 23:35 ` Jakub Kicinski
2026-08-14 1:14 ` [PATCH net-next 09/11] bnge: add NTUPLE filter support in ethtool Vikas Gupta
2026-08-14 1:14 ` [PATCH net-next 10/11] bnge: add aRFS flow steering ndo support Vikas Gupta
2026-08-17 23:36 ` Jakub Kicinski
2026-08-14 1:14 ` [PATCH net-next 11/11] bnge: add cpu_rmap support for IRQ affinity Vikas Gupta
2026-08-17 23:38 ` [PATCH net-next 00/11] add features to bnge Jakub Kicinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260814011435.194631-4-vikas.gupta@broadcom.com \
--to=vikas.gupta@broadcom.com \
--cc=ajit.khaparde@broadcom.com \
--cc=andrew+netdev@lunn.ch \
--cc=bhargava.marreddy@broadcom.com \
--cc=davem@davemloft.net \
--cc=dharmender.garg@broadcom.com \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rahul-rg.gupta@broadcom.com \
--cc=rajashekar.hudumula@broadcom.com \
--cc=vsrama-krishna.nemani@broadcom.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.