Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 07 Aug 2026 08:14:45 +0000
From:      Kevin Bowling <kbowling@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 703c756a2d29 - main - ixgbe: Validate SR-IOV before restarting the PF
Message-ID:  <6a7593f5.44de9.3ab4256f@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=703c756a2d298e5841471eb7d4d40f95a0dafe50

commit 703c756a2d298e5841471eb7d4d40f95a0dafe50
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-06 11:05:32 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-07 08:05:26 +0000

    ixgbe: Validate SR-IOV before restarting the PF
    
    A deterministic IOV configuration error currently reaches the driver
    only after iflib has stopped the PF. The required cleanup restart then
    causes an avoidable carrier flap.
    
    Follow the igb pattern and validate the request in the PCI IOV method
    before entering the restart transaction. Reject queue layouts wider
    than the selected virtualization pool before they can alias unrelated
    82599 registers.
    
    MFC after:      2 weeks
---
 sys/dev/ixgbe/if_ix.c       | 23 +++++++++++++++-
 sys/dev/ixgbe/if_sriov.c    | 67 +++++++++++++++++++++++++++++++++------------
 sys/dev/ixgbe/ixgbe_sriov.h |  1 +
 3 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index 38029e3ec895..f800be109fc3 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -169,6 +169,9 @@ static int  ixgbe_if_detach(if_ctx_t);
 static int  ixgbe_if_shutdown(if_ctx_t);
 static int  ixgbe_if_suspend(if_ctx_t);
 static int  ixgbe_if_resume(if_ctx_t);
+#ifdef PCI_IOV
+static int  ixgbe_device_iov_init(device_t, uint16_t, const nvlist_t *);
+#endif
 
 static void ixgbe_if_stop(if_ctx_t);
 void ixgbe_if_enable_intr(if_ctx_t);
@@ -297,7 +300,7 @@ static device_method_t ix_methods[] = {
 	DEVMETHOD(device_suspend, iflib_device_suspend),
 	DEVMETHOD(device_resume, iflib_device_resume),
 #ifdef PCI_IOV
-	DEVMETHOD(pci_iov_init, iflib_device_iov_init_restart),
+	DEVMETHOD(pci_iov_init, ixgbe_device_iov_init),
 	DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit_restart),
 	DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf),
 #endif /* PCI_IOV */
@@ -320,6 +323,24 @@ MODULE_DEPEND(ix, ether, 1, 1, 1);
 MODULE_DEPEND(ix, iflib, 1, 1, 1);
 MODULE_DEPEND(ix, mdio, 1, 1, 1);
 
+#ifdef PCI_IOV
+static int
+ixgbe_device_iov_init(device_t dev, uint16_t num_vfs,
+    const nvlist_t *params)
+{
+	struct ixgbe_softc *sc;
+	if_ctx_t ctx;
+	int error;
+
+	ctx = device_get_softc(dev);
+	sc = iflib_get_softc(ctx);
+	error = ixgbe_iov_validate(sc, num_vfs);
+	if (error != 0)
+		return (error);
+	return (iflib_device_iov_init_restart(dev, num_vfs, params));
+}
+#endif
+
 static device_method_t ixgbe_if_methods[] = {
 	DEVMETHOD(ifdi_attach_pre, ixgbe_if_attach_pre),
 	DEVMETHOD(ifdi_attach_post, ixgbe_if_attach_post),
diff --git a/sys/dev/ixgbe/if_sriov.c b/sys/dev/ixgbe/if_sriov.c
index c05b82533081..b2325046d5e8 100644
--- a/sys/dev/ixgbe/if_sriov.c
+++ b/sys/dev/ixgbe/if_sriov.c
@@ -1028,18 +1028,20 @@ ixgbe_handle_mbx(void *context)
 } /* ixgbe_handle_mbx */
 
 int
-ixgbe_if_iov_init(if_ctx_t ctx, u16 num_vfs, const nvlist_t *config)
+ixgbe_iov_validate(struct ixgbe_softc *sc, u16 num_vfs)
 {
-	struct ixgbe_softc *sc;
-	int i, num_filters, retval = 0;
-
-	sc = iflib_get_softc(ctx);
-	sc->iov_mode = IXGBE_NO_VM;
+	int mode, pool, queue_count;
 
-	if (num_vfs == 0) {
-		/* Would we ever get num_vfs = 0? */
-		retval = EINVAL;
-		goto err_init_iov;
+	if (!(sc->feat_cap & IXGBE_FEATURE_SRIOV))
+		return (ENXIO);
+	if (num_vfs == 0)
+		return (EINVAL);
+	if (sc->vfs != NULL || sc->vf_mac_filters != NULL ||
+	    (sc->feat_en & IXGBE_FEATURE_SRIOV))
+		return (EBUSY);
+	if (sc->intr_type != IFLIB_INTR_MSIX) {
+		device_printf(sc->dev, "SR-IOV requires MSI-X\n");
+		return (ENOTSUP);
 	}
 
 	/*
@@ -1049,17 +1051,43 @@ ixgbe_if_iov_init(if_ctx_t ctx, u16 num_vfs, const nvlist_t *config)
 	 * With 32 VFs, you can have up to four queues per VF.
 	 */
 	if (num_vfs >= IXGBE_32_VM)
-		sc->iov_mode = IXGBE_64_VM;
+		mode = IXGBE_64_VM;
 	else
-		sc->iov_mode = IXGBE_32_VM;
+		mode = IXGBE_32_VM;
+	queue_count = ixgbe_vf_queues(mode);
+	if (sc->num_rx_queues > queue_count ||
+	    sc->num_tx_queues > queue_count) {
+		device_printf(sc->dev,
+		    "SR-IOV mode supports %d PF queues, but %d RX and %d TX "
+		    "queues are allocated\n", queue_count, sc->num_rx_queues,
+		    sc->num_tx_queues);
+		return (ENOSPC);
+	}
 
 	/* Again, reserving 1 VM's worth of queues for the PF */
-	sc->pool = sc->iov_mode - 1;
+	pool = mode - 1;
+	if (num_vfs > pool || num_vfs >= IXGBE_64_VM)
+		return (ENOSPC);
+	return (0);
+}
 
-	if ((num_vfs > sc->pool) || (num_vfs >= IXGBE_64_VM)) {
-		retval = ENOSPC;
-		goto err_init_iov;
-	}
+int
+ixgbe_if_iov_init(if_ctx_t ctx, u16 num_vfs, const nvlist_t *config)
+{
+	struct ixgbe_softc *sc;
+	int i, num_filters, retval;
+
+	(void)config;
+	sc = iflib_get_softc(ctx);
+	retval = ixgbe_iov_validate(sc, num_vfs);
+	if (retval != 0)
+		return (retval);
+
+	if (num_vfs >= IXGBE_32_VM)
+		sc->iov_mode = IXGBE_64_VM;
+	else
+		sc->iov_mode = IXGBE_32_VM;
+	sc->pool = sc->iov_mode - 1;
 
 	sc->vfs = malloc(sizeof(*sc->vfs) * num_vfs, M_IXGBE_SRIOV,
 	    M_NOWAIT | M_ZERO);
@@ -1093,6 +1121,11 @@ ixgbe_if_iov_init(if_ctx_t ctx, u16 num_vfs, const nvlist_t *config)
 	return (retval);
 
 err_init_iov:
+	free(sc->vf_mac_filters, M_IXGBE_SRIOV);
+	sc->vf_mac_filters = NULL;
+	sc->num_vf_mac_filters = 0;
+	free(sc->vfs, M_IXGBE_SRIOV);
+	sc->vfs = NULL;
 	sc->num_vfs = 0;
 	sc->pool = 0;
 	sc->iov_mode = IXGBE_NO_VM;
diff --git a/sys/dev/ixgbe/ixgbe_sriov.h b/sys/dev/ixgbe/ixgbe_sriov.h
index c38f4075b97a..443bf78e9a1d 100644
--- a/sys/dev/ixgbe/ixgbe_sriov.h
+++ b/sys/dev/ixgbe/ixgbe_sriov.h
@@ -74,6 +74,7 @@
 
 int  ixgbe_if_iov_vf_add(if_ctx_t, u16, const nvlist_t *);
 int  ixgbe_if_iov_init(if_ctx_t, u16, const nvlist_t *);
+int  ixgbe_iov_validate(struct ixgbe_softc *, u16);
 void ixgbe_if_iov_uninit(if_ctx_t);
 void ixgbe_initialize_iov(struct ixgbe_softc *);
 void ixgbe_recalculate_max_frame(struct ixgbe_softc *);


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a7593f5.44de9.3ab4256f>