u32 reg_idx, reg;
        int i, msix_vf;
 
+       /* Start by disabling VF's configuration API to prevent the OS from
+        * accessing the VF's VSI after it's freed / invalidated.
+        */
+       clear_bit(I40E_VF_STAT_INIT, &vf->vf_states);
+
        /* free vsi & disconnect it from the parent uplink */
        if (vf->lan_vsi_idx) {
                i40e_vsi_release(pf->vsi[vf->lan_vsi_idx]);
        /* reset some of the state variables keeping track of the resources */
        vf->num_queue_pairs = 0;
        vf->vf_states = 0;
-       clear_bit(I40E_VF_STAT_INIT, &vf->vf_states);
 }
 
 /**
        /* warn the VF */
        clear_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
 
+       /* Disable VF's configuration API during reset. The flag is re-enabled
+        * in i40e_alloc_vf_res(), when it's safe again to access VF's VSI.
+        * It's normally disabled in i40e_free_vf_res(), but it's safer
+        * to do it earlier to give some time to finish to any VF config
+        * functions that may still be running at this point.
+        */
+       clear_bit(I40E_VF_STAT_INIT, &vf->vf_states);
+
        /* In the case of a VFLR, the HW has already reset the VF and we
         * just need to clean up, so don't hit the VFRTRIG register.
         */
        if (!rsd)
                dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n",
                        vf->vf_id);
-       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_COMPLETED);
-       /* clear the reset bit in the VPGEN_VFRTRIG reg */
-       reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
-       reg &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
-       wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
 
        /* On initial reset, we won't have any queues */
        if (vf->lan_vsi_idx == 0)
 
        i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
 complete_reset:
-       /* reallocate VF resources to reset the VSI state */
+       /* free VF resources to begin resetting the VSI state */
        i40e_free_vf_res(vf);
+
+       /* Enable hardware by clearing the reset bit in the VPGEN_VFRTRIG reg.
+        * By doing this we allow HW to access VF memory at any point. If we
+        * did it any sooner, HW could access memory while it was being freed
+        * in i40e_free_vf_res(), causing an IOMMU fault.
+        *
+        * On the other hand, this needs to be done ASAP, because the VF driver
+        * is waiting for this to happen and may report a timeout. It's
+        * harmless, but it gets logged into Guest OS kernel log, so best avoid
+        * it.
+        */
+       reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
+       reg &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
+       wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
+
+       /* reallocate VF resources to finish resetting the VSI state */
        if (!i40e_alloc_vf_res(vf)) {
                int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
                i40e_enable_vf_mappings(vf);
                        i40e_notify_client_of_vf_reset(pf, abs_vf_id);
                vf->num_vlan = 0;
        }
-       /* tell the VF the reset is done */
+
+       /* Tell the VF driver the reset is done. This needs to be done only
+        * after VF has been fully initialized, because the VF driver may
+        * request resources immediately after setting this flag.
+        */
        wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE);
 
        i40e_flush(hw);