0) + return (error); + } + ixl_pf_qmgr_clear_queue_flags(&vf->qtag); + + error = ixl_vf_release_resources(pf, vf); + if (error != 0) + return (error); + + error = ixl_flush_pcie(pf, vf); + if (error != 0) { + device_printf(pf->dev, + "Timed out waiting for PCIe activity to stop on VF-%d\n", + vf->vf_num); + return (error); + } + wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_num), VIRTCHNL_VFR_COMPLETED); vfrtrig = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_num)); vfrtrig &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK; wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_num), vfrtrig); - if (vf->vsi.seid != 0) - ixl_disable_rings(pf, &vf->vsi, &vf->qtag); - ixl_pf_qmgr_clear_queue_flags(&vf->qtag); + ixl_free_filters(&vf->vsi.ftl); + vf->vsi.num_hw_filters = 0; + vf->vsi.num_macs = 0; + vf->vsi.num_vlans = 0; + bit_nclear(vf->vsi.vlans_map, 0, IXL_VLANS_MAP_LEN - 1); - ixl_vf_release_resources(pf, vf); - ixl_vf_setup_vsi(pf, vf); + error = ixl_vf_setup_vsi(pf, vf); + if (error != 0) + return (error); ixl_vf_map_queues(pf, vf); wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_num), VIRTCHNL_VFR_VFACTIVE); ixl_flush(hw); + return (0); } static int @@ -519,7 +553,12 @@ static void ixl_vf_reset_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, uint16_t msg_size) { - ixl_reset_vf(pf, vf); + int error; + + error = ixl_reset_vf(pf, vf); + if (error != 0) + device_printf(pf->dev, "Failed to reset VF-%d: %d\n", + vf->vf_num, error); /* No response to a reset message. */ } @@ -1614,8 +1653,12 @@ ixl_handle_vflr(struct ixl_pf *pf) vflrstat_mask); ixl_dbg_iov(pf, "Reinitializing VF-%d\n", i); - ixl_reinit_vf(pf, vf); - ixl_dbg_iov(pf, "Reinitializing VF-%d done\n", i); + if (ixl_reinit_vf(pf, vf) != 0) + device_printf(pf->dev, + "Failed to reinitialize VF-%d\n", i); + else + ixl_dbg_iov(pf, + "Reinitializing VF-%d done\n", i); } } @@ -1766,17 +1809,24 @@ ixl_if_iov_uninit(if_ctx_t ctx) struct ixl_pf *pf = iflib_get_softc(ctx); struct i40e_hw *hw; struct ixl_vf *vfs; - int i, num_vfs; + int error, i, num_vfs; hw = &pf->hw; for (i = 0; i < pf->num_vfs; i++) { - if (pf->vfs[i].vsi.seid != 0) - i40e_aq_delete_element(hw, pf->vfs[i].vsi.seid, NULL); - ixl_pf_qmgr_release(&pf->qmgr, &pf->vfs[i].qtag); + error = ixl_vf_release_resources(pf, &pf->vfs[i]); + if (error == 0) { + if (pf->vfs[i].qtag.qmgr != NULL) + ixl_pf_qmgr_release(&pf->qmgr, + &pf->vfs[i].qtag); + ixl_dbg_iov(pf, "VF %d: %d released\n", i, + pf->vfs[i].qtag.num_allocated); + } else { + device_printf(pf->dev, + "retaining VF-%d queue allocation after failed " + "VSI release\n", i); + } ixl_free_filters(&pf->vfs[i].vsi.ftl); - ixl_dbg_iov(pf, "VF %d: %d released\n", - i, pf->vfs[i].qtag.num_allocated); ixl_dbg_iov(pf, "Unallocated total: %d\n", ixl_pf_qmgr_get_num_free(&pf->qmgr)); } @@ -1836,13 +1886,20 @@ ixl_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params) { struct ixl_pf *pf = iflib_get_softc(ctx); char sysctl_name[IXL_QUEUE_NAME_LEN]; + struct sysctl_ctx_list sysctl_ctx; struct ixl_vf *vf; const void *mac; size_t size; - int error; + int cleanup_error, error; int vf_num_queues; vf = &pf->vfs[vfnum]; + if (vf->vf_flags & VF_FLAG_ENABLED) + return (EBUSY); + /* Preserve the context initialized for every VF slot in iov_init. */ + sysctl_ctx = vf->vsi.sysctl_ctx; + bzero(vf, sizeof(*vf)); + vf->vsi.sysctl_ctx = sysctl_ctx; vf->vf_num = vfnum; vf->vsi.back = pf; vf->vf_flags = VF_FLAG_ENABLED; @@ -1853,10 +1910,6 @@ ixl_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params) if (error != 0) goto out; - error = ixl_vf_setup_vsi(pf, vf); - if (error != 0) - goto out; - if (nvlist_exists_binary(params, "mac-addr")) { mac = nvlist_get_binary(params, "mac-addr", &size); bcopy(mac, vf->mac, ETHER_ADDR_LEN); @@ -1879,11 +1932,21 @@ ixl_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params) vf->vf_flags |= VF_FLAG_VLAN_CAP; /* VF needs to be reset before it can be used */ - ixl_reset_vf(pf, vf); + error = ixl_reset_vf(pf, vf); out: if (error == 0) { snprintf(sysctl_name, sizeof(sysctl_name), "vf%d", vfnum); ixl_vsi_add_sysctls(&vf->vsi, sysctl_name, false); + } else { + cleanup_error = ixl_vf_release_resources(pf, vf); + ixl_free_filters(&vf->vsi.ftl); + if (cleanup_error == 0 && vf->qtag.qmgr != NULL) + ixl_pf_qmgr_release(&pf->qmgr, &vf->qtag); + else if (cleanup_error != 0) + device_printf(pf->dev, + "retaining VF-%u queue allocation after failed " + "VSI release\n", vfnum); + vf->vf_flags = 0; } return (error);