The branch main has been updated by imp:

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

commit 925a15b969a586bc9beec1afdc477f0d6e0aa625
Author:     Krzysztof Galazka <krzysztof.gala...@intel.com>
AuthorDate: 2025-02-12 16:17:53 +0000
Commit:     Warner Losh <i...@freebsd.org>
CommitDate: 2025-07-18 19:16:16 +0000

    ice(4): Add basic VFLR handler
    
    PF driver needs to tear down and setup VF configuration after
    a reset event, e.g. due to reloading a VF driver. Re-use
    ice_reset_vf function for that by adding new parameter,
    which decides if new reset has to be triggered.
    This most likely does not cover all necessary steps
    and will be extended in future commits.
    
    Signed-off-by: Krzysztof Galazka <krzysztof.gala...@intel.com>
    Reviewed by: imp
    Pull Request: https://github.com/freebsd/freebsd-src/pull/1573
---
 sys/dev/ice/ice_iov.c      | 41 +++++++++++++++++++++++++++++++++++------
 sys/dev/ice/ice_iov.h      |  2 ++
 sys/dev/ice/if_ice_iflib.c | 21 ++++++++++++++++++---
 3 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/sys/dev/ice/ice_iov.c b/sys/dev/ice/ice_iov.c
index b11fb225f30a..af0bef7bf2f0 100644
--- a/sys/dev/ice/ice_iov.c
+++ b/sys/dev/ice/ice_iov.c
@@ -41,7 +41,8 @@
 
 static struct ice_vf *ice_iov_get_vf(struct ice_softc *sc, int vf_num);
 static void ice_iov_ready_vf(struct ice_softc *sc, struct ice_vf *vf);
-static void ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf);
+static void ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf,
+                        bool trigger_vflr);
 static void ice_iov_setup_intr_mapping(struct ice_softc *sc, struct ice_vf 
*vf);
 
 static void ice_vc_version_msg(struct ice_softc *sc, struct ice_vf *vf,
@@ -461,6 +462,31 @@ ice_iov_uninit(struct ice_softc *sc)
        sc->num_vfs = 0;
 }
 
+/**
+ * ice_iov_handle_vflr - Process VFLR event
+ * @sc: device softc structure
+ *
+ * Identifys which VFs have been reset and re-configure
+ * them.
+ */
+void
+ice_iov_handle_vflr(struct ice_softc *sc)
+{
+       struct ice_hw *hw = &sc->hw;
+       struct ice_vf *vf;
+       u32 reg, reg_idx, bit_idx;
+
+       for (int i = 0; i < sc->num_vfs; i++) {
+               vf = &sc->vfs[i];
+
+               reg_idx = (hw->func_caps.vf_base_id + vf->vf_num) / 32;
+               bit_idx = (hw->func_caps.vf_base_id + vf->vf_num) % 32;
+               reg = rd32(hw, GLGEN_VFLRSTAT(reg_idx));
+               if (reg & BIT(bit_idx))
+                       ice_reset_vf(sc, vf, false);
+       }
+}
+
 /**
  * ice_iov_ready_vf - Setup VF interrupts and mark it as ready
  * @sc: device softc structure
@@ -494,6 +520,7 @@ ice_iov_ready_vf(struct ice_softc *sc, struct ice_vf *vf)
  * ice_reset_vf - Perform a hardware reset (VFR) on a VF
  * @sc: device softc structure
  * @vf: driver's VF structure for VF to be reset
+ * @trigger_vflr: trigger a reset or only handle already executed reset
  *
  * Performs a VFR for the given VF. This function busy waits until the
  * reset completes in the HW, notifies the VF that the reset is done
@@ -504,7 +531,7 @@ ice_iov_ready_vf(struct ice_softc *sc, struct ice_vf *vf)
  * ice_iov_setup_intr_mapping()
  */
 static void
-ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf)
+ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf, bool trigger_vflr)
 {
        u16 global_vf_num, reg_idx, bit_idx;
        struct ice_hw *hw = &sc->hw;
@@ -514,9 +541,11 @@ ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf)
 
        global_vf_num = vf->vf_num + hw->func_caps.vf_base_id;
 
-       reg = rd32(hw, VPGEN_VFRTRIG(vf->vf_num));
-       reg |= VPGEN_VFRTRIG_VFSWR_M;
-       wr32(hw, VPGEN_VFRTRIG(vf->vf_num), reg);
+       if (trigger_vflr) {
+               reg = rd32(hw, VPGEN_VFRTRIG(vf->vf_num));
+               reg |= VPGEN_VFRTRIG_VFSWR_M;
+               wr32(hw, VPGEN_VFRTRIG(vf->vf_num), reg);
+       }
 
        /* clear the VFLR bit for the VF in a GLGEN_VFLRSTAT register */
        reg_idx = (global_vf_num) / 32;
@@ -1581,7 +1610,7 @@ ice_vc_handle_vf_msg(struct ice_softc *sc, struct 
ice_rq_event_info *event)
                ice_vc_version_msg(sc, vf, msg);
                break;
        case VIRTCHNL_OP_RESET_VF:
-               ice_reset_vf(sc, vf);
+               ice_reset_vf(sc, vf, true);
                break;
        case VIRTCHNL_OP_GET_VF_RESOURCES:
                ice_vc_get_vf_res_msg(sc, vf, msg);
diff --git a/sys/dev/ice/ice_iov.h b/sys/dev/ice/ice_iov.h
index 4da94259e00f..c2ac5fcd5c94 100644
--- a/sys/dev/ice/ice_iov.h
+++ b/sys/dev/ice/ice_iov.h
@@ -108,6 +108,8 @@ int ice_iov_init(struct ice_softc *sc, uint16_t num_vfs, 
const nvlist_t *params)
 int ice_iov_add_vf(struct ice_softc *sc, uint16_t vfnum, const nvlist_t 
*params);
 void ice_iov_uninit(struct ice_softc *sc);
 
+void ice_iov_handle_vflr(struct ice_softc *sc);
+
 void ice_vc_handle_vf_msg(struct ice_softc *sc, struct ice_rq_event_info 
*event);
 void ice_vc_notify_all_vfs_link_state(struct ice_softc *sc);
 
diff --git a/sys/dev/ice/if_ice_iflib.c b/sys/dev/ice/if_ice_iflib.c
index 359964d17cd6..1469d2916465 100644
--- a/sys/dev/ice/if_ice_iflib.c
+++ b/sys/dev/ice/if_ice_iflib.c
@@ -1712,6 +1712,11 @@ ice_if_msix_intr_assign(if_ctx_t ctx, int msix)
        /* For future interrupt assignments */
        sc->last_rid = rid + sc->irdma_vectors;
 
+#ifdef PCI_IOV
+       /* Create soft IRQ for handling VF resets */
+       iflib_softirq_alloc_generic(ctx, NULL, IFLIB_INTR_IOV, sc, 0, "iov");
+#endif
+
        return (0);
 fail:
        for (; i >= 0; i--, vector--)
@@ -2456,6 +2461,15 @@ ice_if_update_admin_status(if_ctx_t ctx)
        /* Check and update link status */
        ice_update_link_status(sc, false);
 
+#ifdef PCI_IOV
+       /*
+        * Schedule VFs' reset handler after global resets
+        * and other events were processed.
+        */
+       if (ice_testandclear_state(&sc->state, ICE_STATE_VFLR_PENDING))
+               iflib_iov_intr_deferred(ctx);
+#endif
+
        /*
         * If there are still messages to process, we need to reschedule
         * ourselves. Otherwise, we can just re-enable the interrupt. We'll be
@@ -3457,12 +3471,13 @@ ice_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const 
nvlist_t *params)
  * Performs the necessar teardown or setup required for a VF after
  * a VFLR is initiated.
  *
- * @remark This is unimplemented
+ * @remark This is a wrapper for ice_iov_handle_vflr
  */
 static void
-ice_if_vflr_handle(if_ctx_t ctx __unused)
+ice_if_vflr_handle(if_ctx_t ctx)
 {
-       return;
+       struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx);
+       ice_iov_handle_vflr(sc);
 }
 #endif /* PCI_IOV */
 

Reply via email to