fbnic exposes more queues than it configures until open, including after ethtool -L while down. A memory provider can bind to an unconfigured queue. Publish the selected counts at probe and on offline channel changes. Sashiko flagged the mismatch by code inspection; it was not reproduced on physical hardware. Tested with fbnic QEMU on Debian sid: offline ethtool -L changed RX/TX queues from 2 to 1 to 3. Reopening passed DHCP and ping. Network selftests were not run. Fixes: da43127a8edc ("eth: fbnic: support queue ops / zero-copy Rx") Reported-by: Sashiko Link: https://lore.kernel.org/netdev/178915061000.219967.7726187707862333281@kernel.org/ Signed-off-by: Björn Töpel --- .../net/ethernet/meta/fbnic/fbnic_ethtool.c | 7 +++++ .../net/ethernet/meta/fbnic/fbnic_netdev.c | 29 +++++++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c index 76e9a545bb16..b96354e56517 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c @@ -1631,6 +1631,13 @@ static int fbnic_set_channels(struct net_device *netdev, return -EINVAL; if (!netif_running(netdev)) { + unsigned int rxq = ch->rx_count + ch->combined_count; + unsigned int txq = ch->tx_count + ch->combined_count; + + err = netif_set_real_num_queues(netdev, txq, rxq); + if (err) + return err; + fbnic_set_queues(fbn, ch, max_napis); fbnic_reset_indir_tbl(fbn); return 0; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c index d1ed29312d54..1e16e10f3505 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c @@ -709,11 +709,12 @@ static const struct netdev_stat_ops fbnic_stat_ops = { .get_base_stats = fbnic_get_base_stats, }; -static void fbnic_reset_queues(struct fbnic_net *fbn, - unsigned int tx, unsigned int rx) +static int fbnic_reset_queues(struct fbnic_net *fbn, + unsigned int tx, unsigned int rx) { struct fbnic_dev *fbd = fbn->fbd; unsigned int max_napis; + int err; max_napis = fbd->num_irqs - FBNIC_NON_NAPI_VECTORS; @@ -724,6 +725,14 @@ static void fbnic_reset_queues(struct fbnic_net *fbn, fbn->num_rx_queues = rx; fbn->num_napi = max(tx, rx); + + err = netif_set_real_num_queues(fbn->netdev, tx, rx); + if (err) + return err; + + fbnic_reset_indir_tbl(fbn); + + return 0; } /** @@ -792,9 +801,9 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd) if (default_queues > fbd->max_num_queues) default_queues = fbd->max_num_queues; - fbnic_reset_queues(fbn, default_queues, default_queues); + if (fbnic_reset_queues(fbn, default_queues, default_queues)) + goto err_free_netdev; - fbnic_reset_indir_tbl(fbn); fbnic_rss_key_fill(fbn->rss_key); fbnic_rss_init_en_mask(fbn); @@ -839,13 +848,15 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd) netif_tx_stop_all_queues(netdev); - if (fbnic_phylink_create(netdev)) { - free_netdev(netdev); - fbd->netdev = NULL; - return NULL; - } + if (fbnic_phylink_create(netdev)) + goto err_free_netdev; return netdev; + +err_free_netdev: + free_netdev(netdev); + fbd->netdev = NULL; + return NULL; } static int fbnic_dsn_to_mac_addr(u64 dsn, char *addr) -- 2.55.0