diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -4023,7 +4023,15 @@ bit = vtag & 0x1F; sc->shadow_vfta[index] |= (1 << bit); ++sc->num_vlans; - em_if_vlan_filter_write(sc); + if (!sc->vf_ifp) + em_if_vlan_filter_write(sc); + else + /* + * Physical funtion may reject registering VLAN + * but we have no way to inform the stack + * about that. + */ + e1000_vfta_set_vf(&sc->hw, vtag, true); } static void @@ -4036,7 +4044,10 @@ bit = vtag & 0x1F; sc->shadow_vfta[index] &= ~(1 << bit); --sc->num_vlans; - em_if_vlan_filter_write(sc); + if (!sc->vf_ifp) + em_if_vlan_filter_write(sc); + else + e1000_vfta_set_vf(&sc->hw, vtag, false); } static bool @@ -4094,22 +4105,15 @@ { struct e1000_hw *hw = &sc->hw; - if (sc->vf_ifp) - return; + KASSERT(!sc->vf_ifp, ("VLAN filter write on VF\n")); /* Disable interrupts for lem(4) devices during the filter change */ if (hw->mac.type < em_mac_min) em_if_intr_disable(sc->ctx); for (int i = 0; i < EM_VFTA_SIZE; i++) - if (sc->shadow_vfta[i] != 0) { - /* XXXKB: incomplete VF support, we returned above */ - if (sc->vf_ifp) - e1000_vfta_set_vf(hw, sc->shadow_vfta[i], - true); - else - e1000_write_vfta(hw, i, sc->shadow_vfta[i]); - } + if (sc->shadow_vfta[i] != 0) + e1000_write_vfta(hw, i, sc->shadow_vfta[i]); /* Re-enable interrupts for lem-class devices */ if (hw->mac.type < em_mac_min) @@ -4124,8 +4128,10 @@ if_t ifp = iflib_get_ifp(ctx); u32 reg; - /* XXXKB: Return early if we are a VF until VF decap and filter - * management is ready and tested. + /* + * Only PFs have control over VLAN HW filtering + * configuration. VFs have to act as if it's always + * enabled. */ if (sc->vf_ifp) return;