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 v5 02/10] bnge: add NTUPLE/ARFS VNIC
Date: Tue, 3 Nov 2026 18:06:42 +0530 [thread overview]
Message-ID: <20261103123651.442893-3-vikas.gupta@broadcom.com> (raw)
In-Reply-To: <20261103123651.442893-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.
The NTUPLE/aRFS VNIC is always allocated, so the function needs at
least BNGE_BASE_VNICS (2) VNICs and the matching RSS contexts.
Firmware grants these to every supported function. If it grants fewer,
bnge_reserve_rings() fails with -ENOMEM and the device does not probe,
as it would for any other missing ring resource.
The patch also removes BNGE_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO and
BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V3, which nothing uses, and renumbers
BNGE_FW_CAP_VNIC_RE_FLUSH from BIT_ULL(26) to BIT_ULL(24).
Signed-off-by: Vikas Gupta <vikas.gupta@broadcom.com>
Reviewed-by: Dharmender Garg <dharmender.garg@broadcom.com>
---
drivers/net/ethernet/broadcom/bnge/bnge.h | 4 +-
.../net/ethernet/broadcom/bnge/bnge_netdev.c | 58 +++++++++++++++++--
.../net/ethernet/broadcom/bnge/bnge_netdev.h | 1 +
.../net/ethernet/broadcom/bnge/bnge_resc.c | 21 ++++---
.../net/ethernet/broadcom/bnge/bnge_resc.h | 1 +
.../net/ethernet/broadcom/bnge/bnge_vnic.c | 33 ++++++++++-
.../net/ethernet/broadcom/bnge/bnge_vnic.h | 8 ++-
7 files changed, 107 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index bde54ba5d50f..3e8210626062 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -63,9 +63,7 @@ enum {
BNGE_FW_CAP_THRESHOLD_TEMP_SUPPORTED = BIT_ULL(21),
BNGE_FW_CAP_DFLT_VLAN_TPID_PCP = BIT_ULL(22),
BNGE_FW_CAP_VNIC_TUNNEL_TPA = BIT_ULL(23),
- BNGE_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO = BIT_ULL(24),
- BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V3 = BIT_ULL(25),
- BNGE_FW_CAP_VNIC_RE_FLUSH = BIT_ULL(26),
+ BNGE_FW_CAP_VNIC_RE_FLUSH = BIT_ULL(24),
};
enum {
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
index 31ca314fd52b..3248aae88c8d 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
@@ -1149,12 +1149,7 @@ static int bnge_alloc_vnic_attributes(struct bnge_net *bn)
static int bnge_alloc_vnics(struct bnge_net *bn)
{
- int num_vnics;
-
- /* Allocate only 1 VNIC for now
- * Additional VNICs will be added based on RFS/NTUPLE in future patches
- */
- num_vnics = 1;
+ int num_vnics = BNGE_BASE_VNICS;
bn->vnic_info = kzalloc_objs(struct bnge_vnic_info, num_vnics);
if (!bn->vnic_info)
@@ -1320,6 +1315,9 @@ 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;
+ 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_nq_tree;
@@ -2578,6 +2576,13 @@ static int bnge_init_chip(struct bnge_net *bn)
if (rc)
goto err_out;
+ rc = bnge_alloc_rfs_vnic(bn);
+ if (rc) {
+ netdev_err(bn->netdev,
+ "hwrm aRFS vnic alloc failure rc: %d\n", rc);
+ goto err_out;
+ }
+
if (bd->rss_cap & BNGE_RSS_CAP_RSS_HASH_TYPE_DELTA)
bnge_hwrm_update_rss_hash_cfg(bn);
@@ -3133,6 +3138,36 @@ static const struct netdev_stat_ops bnge_stat_ops = {
.get_base_stats = bnge_get_base_stats,
};
+static netdev_features_t bnge_fix_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ /* NTUPLE can only be changed while the interface is down. */
+ if (netif_running(dev)) {
+ if (dev->features & NETIF_F_NTUPLE)
+ features |= NETIF_F_NTUPLE;
+ else
+ features &= ~NETIF_F_NTUPLE;
+ }
+ return features;
+}
+
+static int bnge_set_features(struct net_device *dev, netdev_features_t features)
+{
+ struct bnge_net *bn = netdev_priv(dev);
+ u32 flags = bn->priv_flags;
+
+ flags &= ~BNGE_NET_EN_NTUPLE;
+ if (features & NETIF_F_NTUPLE)
+ flags |= BNGE_NET_EN_NTUPLE;
+
+ if (flags == bn->priv_flags)
+ return 0;
+
+ bn->priv_flags = flags;
+
+ return 0;
+}
+
static const struct net_device_ops bnge_netdev_ops = {
.ndo_open = bnge_open,
.ndo_stop = bnge_close,
@@ -3140,6 +3175,8 @@ static const struct net_device_ops bnge_netdev_ops = {
.ndo_get_stats64 = bnge_get_stats64,
.ndo_set_rx_mode_async = bnge_set_rx_mode,
.ndo_features_check = bnge_features_check,
+ .ndo_fix_features = bnge_fix_features,
+ .ndo_set_features = bnge_set_features,
};
static void bnge_init_mac_addr(struct bnge_dev *bd)
@@ -3265,6 +3302,13 @@ 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;
+}
+
int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs)
{
struct net_device *netdev;
@@ -3371,6 +3415,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 21f55ea056f4..ef5e235a7cdd 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c
@@ -191,12 +191,16 @@ 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)
{
- return 1;
+ return BNGE_BASE_VNICS;
}
u32 bnge_get_rxfh_indir_size(struct bnge_dev *bd)
@@ -222,8 +226,8 @@ static void bnge_copy_reserved_rings(struct bnge_dev *bd,
static bool bnge_rings_ok(struct bnge_hw_rings *hwr)
{
- return hwr->tx && hwr->rx && hwr->nq && hwr->grp && hwr->vnic &&
- hwr->stat && hwr->cmpl;
+ return hwr->tx && hwr->rx && hwr->nq && hwr->grp &&
+ hwr->vnic >= BNGE_BASE_VNICS && hwr->stat && hwr->cmpl;
}
static bool bnge_need_reserve_rings(struct bnge_dev *bd)
@@ -232,18 +236,21 @@ static bool bnge_need_reserve_rings(struct bnge_dev *bd)
u16 cprs = bnge_cprs_demand(bd);
u16 rx = bd->rx_nr_rings, stat;
u16 nqs = bnge_nqs_demand(bd);
- u16 vnic;
+ struct bnge_hw_rings hwr = {};
if (hw_resc->resv_tx_rings != bd->tx_nr_rings)
return true;
- vnic = bnge_get_total_vnics(bd);
+ hwr.grp = bd->rx_nr_rings;
+ hwr.vnic = bnge_get_total_vnics(bd);
if (bnge_is_agg_reqd(bd))
rx <<= 1;
stat = bnge_func_stat_ctxs_demand(bd);
if (hw_resc->resv_rx_rings != rx || hw_resc->resv_cp_rings != cprs ||
- hw_resc->resv_vnics != vnic || hw_resc->resv_stat_ctxs != stat)
+ hw_resc->resv_vnics != hwr.vnic ||
+ hw_resc->resv_rsscos_ctxs != bnge_get_total_rss_ctxs(bd, &hwr) ||
+ hw_resc->resv_stat_ctxs != stat)
return true;
if (hw_resc->resv_irqs != nqs)
return true;
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h
index c0b6992d7f82..97e8ef08974c 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 3a6c8f0a5954..d98a6196c859 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,30 @@ 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;
+ }
+
+ /* If bnge_setup_vnic() fails, the VNIC allocated above is not freed
+ * here; the caller (bnge_init_chip) unwinds via its err_out path.
+ */
+ 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 c81d3a64561e..72357e0b37ac 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_vnic.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_vnic.h
@@ -22,13 +22,16 @@ struct bnge_l2_filter;
#define BNGE_MAX_UC_ADDRS 4
enum {
- BNGE_VNIC_DEFAULT = 0
+ BNGE_VNIC_DEFAULT = 0,
+ BNGE_VNIC_NTUPLE = 1,
+ BNGE_BASE_VNICS = 2
};
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 {
@@ -60,4 +63,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.52.0
next prev parent reply other threads:[~2026-11-03 12:37 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 12:36 [PATCH net-next v5 00/10] add features to bnge Vikas Gupta
2026-11-03 12:36 ` [PATCH net-next v5 01/10] bnge: restructure VNIC and filter code Vikas Gupta
2026-11-03 12:36 ` Vikas Gupta [this message]
2026-11-03 12:36 ` [PATCH net-next v5 03/10] bnge: add helper functions for multi RSS contexts Vikas Gupta
2026-11-03 12:36 ` [PATCH net-next v5 04/10] bnge: add RXFH ethtool support Vikas Gupta
2026-11-03 12:36 ` [PATCH net-next v5 05/10] bnge: add ethtool support to manage RSS contexts Vikas Gupta
2026-11-03 12:36 ` [PATCH net-next v5 06/10] bnge: remove refcount from L2 filter Vikas Gupta
2026-11-03 12:36 ` [PATCH net-next v5 07/10] bnge: add NTUPLE filter infrastructure Vikas Gupta
2026-11-03 12:36 ` [PATCH net-next v5 08/10] bnge: add NTUPLE filter support in ethtool Vikas Gupta
2026-11-03 12:36 ` [PATCH net-next v5 09/10] bnge: add aRFS flow steering ndo support Vikas Gupta
2026-11-03 12:36 ` [PATCH net-next v5 10/10] bnge: add cpu_rmap support for IRQ affinity Vikas Gupta
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=20261103123651.442893-3-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®