git: 31fb4efd211c - main - ice: Add VF reset and policy failure injection

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Fri, 18 Sep 2026 00:28:04 UTC
The branch main has been updated by kbowling:

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

commit 31fb4efd211cbb2ea79463c6e8522bb362e29129
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-19 03:41:02 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-09-18 00:27:40 +0000

    ice: Add VF reset and policy failure injection
    
    Extend the optional ICE failure-injection facility with points for the
    MAC anti-spoof firmware update and each mandatory VF reset stage.
    
    The reset points report a failed Tx drain command, VFR timeout, receive
    queue disable, or final PCIe transaction drain after the corresponding
    hardware operation.  This permits fail-closed state and recovery tests
    without deliberately leaving live DMA during teardown.
    
    The points remain absent unless the kernel is built with
    options DRIVER_FAILPOINTS and retain the existing PF and VF selectors.
    
    MFC after:      2 weeks
    Sponsored by:   BBOX.io
    Differential Revision:  https://reviews.freebsd.org/D59025
---
 sys/dev/ice/ice_iov.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/sys/dev/ice/ice_iov.c b/sys/dev/ice/ice_iov.c
index ae56395aa776..68cfae7197db 100644
--- a/sys/dev/ice/ice_iov.c
+++ b/sys/dev/ice/ice_iov.c
@@ -265,6 +265,9 @@ ice_iov_configure_mac_anti_spoof(struct ice_softc *sc, struct ice_vf *vf)
 	struct ice_vsi *vsi = vf->vsi;
 	struct ice_hw *hw = &sc->hw;
 	bool enable;
+#ifdef DRIVER_FAILPOINTS
+	int error;
+#endif
 	int status;
 
 	enable = (atomic_load_acq_32(&vf->vf_flags) &
@@ -277,6 +280,8 @@ ice_iov_configure_mac_anti_spoof(struct ice_softc *sc, struct ice_vf *vf)
 	else
 		ctx.info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF;
 
+	ICE_IOV_FAIL_POINT(sc, vf->vf_num, mac_anti_spoof_update, error,
+	    fail);
 	status = ice_update_vsi(hw, vsi->idx, &ctx, NULL);
 	if (status != 0) {
 		device_printf(sc->dev,
@@ -289,6 +294,11 @@ ice_iov_configure_mac_anti_spoof(struct ice_softc *sc, struct ice_vf *vf)
 
 	vsi->info.sec_flags = ctx.info.sec_flags;
 	return (0);
+
+#ifdef DRIVER_FAILPOINTS
+fail:
+	return (error);
+#endif
 }
 
 /**
@@ -864,6 +874,11 @@ ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf, bool trigger_reset,
 	/* This zero-queue command is required to complete every VF reset. */
 	status = ice_dis_vsi_txq(hw->port_info, vf->vsi->idx, 0, 0,
 	    NULL, NULL, NULL, ICE_VF_RESET, vf->vf_num, NULL);
+	ICE_FAIL_POINT_CODE_COND(sc, _debug_fail_point_ice_iov,
+	    vf_reset_tx_disable, ice_iov_fail_vf_matches(vf->vf_num),
+	    FAIL_POINT_NONSLEEPABLE, {
+		status = ICE_ERR_AQ_ERROR;
+	});
 	if (status) {
 		device_printf(sc->dev,
 		    "%s: Failed to disable LAN Tx queues: err %s aq_err %s\n",
@@ -884,6 +899,11 @@ ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf, bool trigger_reset,
 
 		DELAY(ICE_VPGEN_VFRSTAT_WAIT_DELAY_US);
 	}
+	ICE_FAIL_POINT_CODE_COND(sc, _debug_fail_point_ice_iov,
+	    vf_reset_vfr_timeout, ice_iov_fail_vf_matches(vf->vf_num),
+	    FAIL_POINT_NONSLEEPABLE, {
+		reset_done = false;
+	});
 	if (!reset_done) {
 		device_printf(sc->dev,
 			"VF-%d Reset is stuck\n", vf->vf_num);
@@ -899,6 +919,12 @@ ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf, bool trigger_reset,
 		/* Hardware resets Tx queues; the PF must disable every Rx. */
 		for (bit = 0; bit < vf->vsi->num_rx_queues; bit++) {
 			status = ice_control_rx_queue(vf->vsi, bit, false);
+			ICE_FAIL_POINT_CODE_COND(sc,
+			    _debug_fail_point_ice_iov, vf_reset_rx_disable,
+			    ice_iov_fail_vf_matches(vf->vf_num),
+			    FAIL_POINT_NONSLEEPABLE, {
+				status = EIO;
+			});
 			if (status != 0) {
 				device_printf(sc->dev,
 				    "Unable to disable VF-%d Rx queue %d: %s\n",
@@ -918,6 +944,11 @@ ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf, bool trigger_reset,
 			break;
 		DELAY(ICE_PCI_CIAD_WAIT_DELAY_US);
 	}
+	ICE_FAIL_POINT_CODE_COND(sc, _debug_fail_point_ice_iov,
+	    vf_reset_pcie_pending, ice_iov_fail_vf_matches(vf->vf_num),
+	    FAIL_POINT_NONSLEEPABLE, {
+		i = ICE_PCI_CIAD_WAIT_COUNT;
+	});
 	if (i == ICE_PCI_CIAD_WAIT_COUNT) {
 		device_printf(sc->dev,
 		    "VF-%d PCI transactions remain after reset\n", vf->vf_num);