mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net] eth: fbnic: Keep real queue counts synchronized
@ 2026-09-15 18:08 Björn Töpel
  0 siblings, 0 replies; only message in thread
From: Björn Töpel @ 2026-09-15 18:08 UTC (permalink / raw)
  To: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
	David S. Miller, Eric Dumazet, Paolo Abeni, Russell King, netdev
  Cc: Björn Töpel, Mohsin Bashir, Mike Marciniszyn (Meta),
	Breno Leitao, Simon Horman, Mina Almasry, linux-kernel, Sashiko

alloc_etherdev_mq() initializes the real queue counts to the
allocation maximum. fbnic selects smaller defaults and can change its
private queue counts while the device is down, but does not publish
either value until the next open.

Resume can also allocate fewer IRQs and silently clamp the private
queue counts. Queues can share NAPI vectors, so changing the
configured queue counts is unnecessary.

These mismatches can expose an inactive queue for memory-provider
binding or hide an existing binding. A later channel expansion can
allocate the queue without recognizing its memory provider.

Publish default and offline channel counts immediately. Reset RSS
indirection whenever the queue-count helper runs. Preserve queue
counts across resume and share the remaining NAPI vectors when fewer
IRQs are available. The RSS table remains valid because it indexes RX
queues rather than NAPI vectors.

Fixes: da43127a8edc ("eth: fbnic: support queue ops / zero-copy Rx")
Reported-by: Sashiko <netdev-bot+sashiko@kernel.org>
Link: https://lore.kernel.org/netdev/178915061000.219967.7726187707862333281@kernel.org/
Signed-off-by: Björn Töpel <bjorn@kernel.org>
---
 .../net/ethernet/meta/fbnic/fbnic_ethtool.c   |  7 +++++
 .../net/ethernet/meta/fbnic/fbnic_netdev.c    | 29 +++++++++++++------
 .../net/ethernet/meta/fbnic/fbnic_netdev.h    |  3 --
 drivers/net/ethernet/meta/fbnic/fbnic_pci.c   | 12 ++++++--
 4 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
index 0e47088ec44b..bec611387333 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
@@ -1626,6 +1626,13 @@ static int fbnic_set_channels(struct net_device *netdev,
 		return -EINVAL;
 
 	if (!netif_running(netdev)) {
+		unsigned int rx_count = ch->rx_count + ch->combined_count;
+		unsigned int tx_count = ch->tx_count + ch->combined_count;
+
+		err = netif_set_real_num_queues(netdev, tx_count, rx_count);
+		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 10bf99be3f24..3b44a0ec2a8d 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
@@ -702,11 +702,12 @@ static const struct netdev_stat_ops fbnic_stat_ops = {
 	.get_base_stats		= fbnic_get_base_stats,
 };
 
-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;
 
@@ -717,6 +718,14 @@ 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;
 }
 
 /**
@@ -785,9 +794,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);
 
@@ -832,13 +841,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)
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
index eded20b0e9e4..ddf1b674737a 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
@@ -86,9 +86,6 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd);
 void fbnic_netdev_free(struct fbnic_dev *fbd);
 int fbnic_netdev_register(struct net_device *netdev);
 void fbnic_netdev_unregister(struct net_device *netdev);
-void fbnic_reset_queues(struct fbnic_net *fbn,
-			unsigned int tx, unsigned int rx);
-
 void fbnic_set_ethtool_ops(struct net_device *dev);
 
 int fbnic_ptp_setup(struct fbnic_dev *fbd);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
index 8b9bc9e8ea56..4dda566d580f 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
@@ -472,6 +472,7 @@ static int __fbnic_pm_resume(struct device *dev)
 {
 	struct fbnic_dev *fbd = dev_get_drvdata(dev);
 	struct net_device *netdev = fbd->netdev;
+	unsigned int max_queues, max_napis;
 	void __iomem * const *iomap_table;
 	struct fbnic_net *fbn;
 	int err;
@@ -510,12 +511,17 @@ static int __fbnic_pm_resume(struct device *dev)
 
 	fbn = netdev_priv(netdev);
 
-	/* Reset the queues if needed */
-	fbnic_reset_queues(fbn, fbn->num_tx_queues, fbn->num_rx_queues);
-
 	rtnl_lock();
 	netdev_lock(netdev);
 
+	/* Preserve queue counts, as RX queues may have memory providers bound.
+	 * The RSS table indexes RX queues and remains valid. Rebuild only the
+	 * NAPI layout, sharing vectors if fewer IRQs are available.
+	 */
+	max_napis = fbd->num_irqs - FBNIC_NON_NAPI_VECTORS;
+	max_queues = max(fbn->num_tx_queues, fbn->num_rx_queues);
+	fbn->num_napi = min(max_queues, max_napis);
+
 	if (netif_running(netdev))
 		err = __fbnic_open(fbn);
 

base-commit: 83a945a529d6e002dd7339c532288a931f463dba
-- 
2.55.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-15 18:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-15 18:08 [PATCH net] eth: fbnic: Keep real queue counts synchronized Björn Töpel

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®