Skip to content

Commit

Permalink
ice(4): Add basic VFLR handler
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
kgalazka committed Feb 12, 2025
1 parent 15de401 commit e0e855e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 9 deletions.
41 changes: 35 additions & 6 deletions sys/dev/ice/ice_iov.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions sys/dev/ice/ice_iov.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
21 changes: 18 additions & 3 deletions sys/dev/ice/if_ice_iflib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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--)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */

Expand Down

0 comments on commit e0e855e

Please sign in to comment.