bnxt_set_channels() rejects channel changes that alter the RSS table
size when IFF_RXFH_CONFIGURED is set, because non-default context
sizes were locked at creation.
Replace the rejection with the new resize helpers. All validation runs
before any mutation:
1. ethtool_rxfh_indir_can_resize() checks context 0.
2. ethtool_rxfh_contexts_resize_all() validates and resizes
all non-default contexts (all-or-none).
3. ethtool_rxfh_indir_resize() applies context 0 changes.
When context 0 uses defaults (!IFF_RXFH_CONFIGURED), steps 1 and 3 are
skipped; the driver regenerates the table via
bnxt_set_dflt_rss_indir_tbl().
Signed-off-by: Björn Töpel <bjorn@kernel.org>
---
.../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 23 +++++++++++++++----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 26fcd52c8a61..7608e5d95630 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -977,11 +977,24 @@ static int bnxt_set_channels(struct net_device *dev,
tx_xdp = req_rx_rings;
}
- if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) !=
- bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) &&
- netif_is_rxfh_configured(dev)) {
- netdev_warn(dev, "RSS table size change required, RSS table entries must be default to proceed\n");
- return -EINVAL;
+ if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) != bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings)) {
+ u32 new_size = bnxt_get_nr_rss_ctxs(bp, req_rx_rings) * BNXT_RSS_TABLE_ENTRIES_P5;
+ u32 old_size = bnxt_get_rxfh_indir_size(dev);
+
+ /* Validate context 0 can be resized before mutating anything */
+ if (netif_is_rxfh_configured(dev) &&
+ ethtool_rxfh_indir_can_resize(bp->rss_indir_tbl, old_size, new_size)) {
+ netdev_warn(dev, "RSS table size change not supported with current indirection table\n");
+ return -EINVAL;
+ }
+
+ rc = ethtool_rxfh_contexts_resize_all(dev, new_size);
+ if (rc)
+ return rc;
+
+ /* All validated; apply context 0 resize */
+ if (netif_is_rxfh_configured(dev))
+ ethtool_rxfh_indir_resize(bp->rss_indir_tbl, old_size, new_size);
}
rc = bnxt_check_rings(bp, req_tx_rings, req_rx_rings, sh, tcs, tx_xdp);
--
2.53.0
On Tue, 3 Mar 2026 19:15:30 +0100 Björn Töpel wrote:
> - if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) !=
> - bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) &&
> - netif_is_rxfh_configured(dev)) {
> - netdev_warn(dev, "RSS table size change required, RSS table entries must be default to proceed\n");
> - return -EINVAL;
> + if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) != bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings)) {
> + u32 new_size = bnxt_get_nr_rss_ctxs(bp, req_rx_rings) * BNXT_RSS_TABLE_ENTRIES_P5;
> + u32 old_size = bnxt_get_rxfh_indir_size(dev);
> +
> + /* Validate context 0 can be resized before mutating anything */
> + if (netif_is_rxfh_configured(dev) &&
> + ethtool_rxfh_indir_can_resize(bp->rss_indir_tbl, old_size, new_size)) {
> + netdev_warn(dev, "RSS table size change not supported with current indirection table\n");
> + return -EINVAL;
> + }
> +
> + rc = ethtool_rxfh_contexts_resize_all(dev, new_size);
> + if (rc)
> + return rc;
> +
> + /* All validated; apply context 0 resize */
> + if (netif_is_rxfh_configured(dev))
> + ethtool_rxfh_indir_resize(bp->rss_indir_tbl, old_size, new_size);
> }
>
> rc = bnxt_check_rings(bp, req_tx_rings, req_rx_rings, sh, tcs, tx_xdp);
You resize the tables even if something else fails later on.
I think either this if () should only contain the validation checks,
and the actual resizing has to happen later.
Or you need to "un-resize" (which should never fail so it's fine).
On Wed, 4 Mar 2026 at 01:05, Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Tue, 3 Mar 2026 19:15:30 +0100 Björn Töpel wrote:
> > - if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) !=
> > - bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) &&
> > - netif_is_rxfh_configured(dev)) {
> > - netdev_warn(dev, "RSS table size change required, RSS table entries must be default to proceed\n");
> > - return -EINVAL;
> > + if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) != bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings)) {
> > + u32 new_size = bnxt_get_nr_rss_ctxs(bp, req_rx_rings) * BNXT_RSS_TABLE_ENTRIES_P5;
> > + u32 old_size = bnxt_get_rxfh_indir_size(dev);
> > +
> > + /* Validate context 0 can be resized before mutating anything */
> > + if (netif_is_rxfh_configured(dev) &&
> > + ethtool_rxfh_indir_can_resize(bp->rss_indir_tbl, old_size, new_size)) {
> > + netdev_warn(dev, "RSS table size change not supported with current indirection table\n");
> > + return -EINVAL;
> > + }
> > +
> > + rc = ethtool_rxfh_contexts_resize_all(dev, new_size);
> > + if (rc)
> > + return rc;
> > +
> > + /* All validated; apply context 0 resize */
> > + if (netif_is_rxfh_configured(dev))
> > + ethtool_rxfh_indir_resize(bp->rss_indir_tbl, old_size, new_size);
> > }
> >
> > rc = bnxt_check_rings(bp, req_tx_rings, req_rx_rings, sh, tcs, tx_xdp);
>
> You resize the tables even if something else fails later on.
> I think either this if () should only contain the validation checks,
> and the actual resizing has to happen later.
> Or you need to "un-resize" (which should never fail so it's fine).
Good point!
On Tue, Mar 3, 2026 at 10:15 AM Björn Töpel <bjorn@kernel.org> wrote:
>
> bnxt_set_channels() rejects channel changes that alter the RSS table
> size when IFF_RXFH_CONFIGURED is set, because non-default context
> sizes were locked at creation.
Thanks for the patch. I want to point out that when running newer FW,
the RSS table size will not change when the channel count changes. If
FW supports it, we'll always use the largest RSS table size for better
traffic balance. A few more comments below.
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> index 26fcd52c8a61..7608e5d95630 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> @@ -977,11 +977,24 @@ static int bnxt_set_channels(struct net_device *dev,
> tx_xdp = req_rx_rings;
> }
>
> - if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) !=
> - bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) &&
> - netif_is_rxfh_configured(dev)) {
> - netdev_warn(dev, "RSS table size change required, RSS table entries must be default to proceed\n");
> - return -EINVAL;
> + if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) != bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings)) {
> + u32 new_size = bnxt_get_nr_rss_ctxs(bp, req_rx_rings) * BNXT_RSS_TABLE_ENTRIES_P5;
If the table size changes, it must be a P5 chip (and running older
FW). Addng a comment for this will be useful.
Also, this if statement should be moved below the bnxt_check_rings()
call. We don't want to change the RSS table unless it is confirmed
that we have enough rings to satisfy the new channels count.
> + u32 old_size = bnxt_get_rxfh_indir_size(dev);
> +
> + /* Validate context 0 can be resized before mutating anything */
> + if (netif_is_rxfh_configured(dev) &&
> + ethtool_rxfh_indir_can_resize(bp->rss_indir_tbl, old_size, new_size)) {
> + netdev_warn(dev, "RSS table size change not supported with current indirection table\n");
> + return -EINVAL;
> + }
> +
> + rc = ethtool_rxfh_contexts_resize_all(dev, new_size);
> + if (rc)
> + return rc;
> +
> + /* All validated; apply context 0 resize */
> + if (netif_is_rxfh_configured(dev))
> + ethtool_rxfh_indir_resize(bp->rss_indir_tbl, old_size, new_size);
> }
>
> rc = bnxt_check_rings(bp, req_tx_rings, req_rx_rings, sh, tcs, tx_xdp);
> --
> 2.53.0
>
On Tue, 3 Mar 2026 at 20:20, Michael Chan <michael.chan@broadcom.com> wrote:
>
> On Tue, Mar 3, 2026 at 10:15 AM Björn Töpel <bjorn@kernel.org> wrote:
> >
> > bnxt_set_channels() rejects channel changes that alter the RSS table
> > size when IFF_RXFH_CONFIGURED is set, because non-default context
> > sizes were locked at creation.
>
> Thanks for the patch. I want to point out that when running newer FW,
> the RSS table size will not change when the channel count changes. If
> FW supports it, we'll always use the largest RSS table size for better
> traffic balance. A few more comments below.
Ok! Is there a changelog somewhere, what FW version that fixes this issue?
> > diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > index 26fcd52c8a61..7608e5d95630 100644
> > --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > @@ -977,11 +977,24 @@ static int bnxt_set_channels(struct net_device *dev,
> > tx_xdp = req_rx_rings;
> > }
> >
> > - if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) !=
> > - bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) &&
> > - netif_is_rxfh_configured(dev)) {
> > - netdev_warn(dev, "RSS table size change required, RSS table entries must be default to proceed\n");
> > - return -EINVAL;
> > + if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) != bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings)) {
> > + u32 new_size = bnxt_get_nr_rss_ctxs(bp, req_rx_rings) * BNXT_RSS_TABLE_ENTRIES_P5;
>
> If the table size changes, it must be a P5 chip (and running older
> FW). Addng a comment for this will be useful.
>
> Also, this if statement should be moved below the bnxt_check_rings()
> call. We don't want to change the RSS table unless it is confirmed
> that we have enough rings to satisfy the new channels count.
Will fix! Thanks for having a look!
© 2016 - 2026 Red Hat, Inc.