git: 8b668bc7e7c8 - main - ixgbe: Preserve the full VF RSS domain in the shared RETA

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Mon, 10 Aug 2026 17:16:35 UTC
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=8b668bc7e7c8b0a1bcb018360a4aafa445ff554f

commit 8b668bc7e7c8b0a1bcb018360a4aafa445ff554f
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-10 15:53:10 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-10 17:16:11 +0000

    ixgbe: Preserve the full VF RSS domain in the shared RETA
    
    The 82599 and X540 share the global RSS redirection table between the
    PF and its VFs.  Programming that table from the PF queue count
    prevents a VF from using queue indices absent from the PF layout.  A
    one-queue PF consequently directs every flow for a two- or four-queue
    VF to queue zero.
    
    Program at least four queue indices while SR-IOV is active.  Each pool
    PSRTYPE.RQPL field masks the shared table to the queue subset available
    to that function, so the PF can continue using fewer queues.
    
    MFC after:      2 weeks
---
 sys/dev/ixgbe/if_ix.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index 9a59ce6b4fe8..8a80f15c77d8 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -661,7 +661,7 @@ ixgbe_initialize_rss_mapping(struct ixgbe_softc *sc)
 {
 	struct ixgbe_hw *hw = &sc->hw;
 	u32 reta = 0, mrqc, rss_key[10];
-	int queue_id, table_size, index_mult;
+	int queue_id, reta_queues, table_size, index_mult;
 	int i, j;
 	u32 rss_hash_config;
 
@@ -690,19 +690,31 @@ ixgbe_initialize_rss_mapping(struct ixgbe_softc *sc)
 		break;
 	}
 
+	/*
+	 * The global RETA is shared by the PF and VFs on 82599 and X540.
+	 * Program all four queue indices while SR-IOV is active so a VF can
+	 * use its full queue grant even when the PF uses fewer queues.
+	 * PSRTYPE.RQPL limits the subset selected within each pool.
+	 */
+	reta_queues = sc->num_rx_queues;
+#ifdef PCI_IOV
+	if (sc->iov_mode != IXGBE_NO_VM)
+		reta_queues = MAX(reta_queues, 4);
+#endif
+
 	/* Set up the redirection table */
 	for (i = 0, j = 0; i < table_size; i++, j++) {
-		if (j == sc->num_rx_queues)
+		if (j == reta_queues)
 			j = 0;
 
 		if (sc->feat_en & IXGBE_FEATURE_RSS) {
 			/*
 			 * Fetch the RSS bucket id for the given indirection
-			 * entry. Cap it at the number of configured buckets
-			 * (which is num_rx_queues.)
+			 * entry.  Cap it at the number of queue indices that must
+			 * be represented in the shared table.
 			 */
 			queue_id = rss_get_indirection_to_bucket(i);
-			queue_id = queue_id % sc->num_rx_queues;
+			queue_id = queue_id % reta_queues;
 		} else
 			queue_id = (j * index_mult);