git: f51ad3a266ec - main - e1000: Fence DMA when hardware reset fails

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Mon, 07 Sep 2026 10:02:34 UTC
The branch main has been updated by kbowling:

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

commit f51ad3a266ec1ea71c24329dbffdb66a3708b214
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-26 09:21:56 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-09-07 10:02:18 +0000

    e1000: Fence DMA when hardware reset fails
    
    iflib releases queue mappings after IFDI_STOP() returns.  If a
    Physical Function reset fails, returning with PCI bus mastering
    enabled can therefore leave the device able to access mappings which
    the framework is about to recycle.
    
    Disable bus mastering and drain pending PCIe transactions when reset
    fails during initialization or stop.  Re-enable and verify bus
    mastering only after a later reset succeeds and before queue
    programming begins.  Treat inability to establish the DMA fence as a
    fail-stop invariant violation.
    
    MFC after:      2 weeks
    Sponsored by:   BBOX.io
---
 sys/dev/e1000/if_em.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 5587920a47b5..2e872b82680f 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -1953,6 +1953,7 @@ em_if_init(if_ctx_t ctx)
 		(void)igbv_reset(ctx);
 		em_rebase_vf_stats(sc);
 	} else if (em_reset(ctx) != E1000_SUCCESS) {
+		em_fence_pci_busmaster(sc);
 		iflib_init_failed(ctx);
 		return;
 	}
@@ -1976,7 +1977,7 @@ em_if_init(if_ctx_t ctx)
 	 * Keep a fail-closed device fenced until reset and VF queue
 	 * sanitization have removed every stale DMA address.
 	 */
-	if (sc->vf_ifp && em_enable_pci_busmaster(sc) != 0) {
+	if (em_enable_pci_busmaster(sc) != 0) {
 		device_printf(sc->dev,
 		    "Unable to enable PCI bus mastering\n");
 		iflib_init_failed(ctx);
@@ -4141,6 +4142,7 @@ em_if_stop(if_ctx_t ctx)
 		if (!sc->vf_ifp && error != E1000_SUCCESS) {
 			device_printf(sc->dev, "Hardware reset failed while "
 			    "stopping: %d\n", error);
+			em_fence_pci_busmaster(sc);
 			return;
 		}
 	}