Page MenuHomeFreeBSD

D30002.id88395.diff
No OneTemporary

D30002.id88395.diff

Index: sys/dev/e1000/if_em.c
===================================================================
--- sys/dev/e1000/if_em.c
+++ sys/dev/e1000/if_em.c
@@ -296,6 +296,10 @@
static void em_update_stats_counters(struct adapter *);
static void em_add_hw_stats(struct adapter *adapter);
static int em_if_set_promisc(if_ctx_t ctx, int flags);
+static bool em_if_vlan_filter_capable(struct adapter *);
+static bool em_if_vlan_filter_used(struct adapter *);
+static void em_if_vlan_filter_enable(struct adapter *);
+static void em_if_vlan_filter_disable(struct adapter *);
static void em_setup_vlan_hw_support(struct adapter *);
static int em_sysctl_nvm_info(SYSCTL_HANDLER_ARGS);
static void em_print_nvm_info(struct adapter *);
@@ -1340,23 +1344,8 @@
adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx);
em_initialize_receive_unit(ctx);
- /* Use real VLAN Filter support? */
- if (if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) {
- if (if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER)
- /* Use real VLAN Filter support */
- em_setup_vlan_hw_support(adapter);
- else {
- u32 ctrl;
- ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
- ctrl |= E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
- }
- } else {
- u32 ctrl;
- ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
- ctrl &= ~E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
- }
+ /* Set up VLAN support and filter */
+ em_setup_vlan_hw_support(adapter);
/* Don't lose promiscuous settings */
em_if_set_promisc(ctx, if_getflags(ifp));
@@ -1674,14 +1663,19 @@
if (flags & IFF_PROMISC) {
reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
+ em_if_vlan_filter_disable(adapter);
/* Turn this on if you want to see bad packets */
if (em_debug_sbp)
reg_rctl |= E1000_RCTL_SBP;
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
- } else if (flags & IFF_ALLMULTI) {
- reg_rctl |= E1000_RCTL_MPE;
- reg_rctl &= ~E1000_RCTL_UPE;
- E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
+ } else {
+ if (flags & IFF_ALLMULTI) {
+ reg_rctl |= E1000_RCTL_MPE;
+ reg_rctl &= ~E1000_RCTL_UPE;
+ E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
+ }
+ if (em_if_vlan_filter_used(adapter))
+ em_if_vlan_filter_enable(adapter);
}
return (0);
}
@@ -3327,7 +3321,10 @@
/* are we on a vlan? */
if (ifp->if_vlantrunk != NULL)
psize += VLAN_TAG_SIZE;
- E1000_WRITE_REG(hw, E1000_RLPML, psize);
+ if (adapter->vf_ifp)
+ e1000_rlpml_set_vf(hw, psize);
+ else
+ E1000_WRITE_REG(hw, E1000_RLPML, psize);
} else {
srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
rctl |= E1000_RCTL_SZ_2048;
@@ -3411,6 +3408,7 @@
bit = vtag & 0x1F;
adapter->shadow_vfta[index] |= (1 << bit);
++adapter->num_vlans;
+ em_setup_vlan_hw_support(adapter);
}
static void
@@ -3423,41 +3421,105 @@
bit = vtag & 0x1F;
adapter->shadow_vfta[index] &= ~(1 << bit);
--adapter->num_vlans;
+ em_setup_vlan_hw_support(adapter);
+}
+
+static bool
+em_if_vlan_filter_capable(struct adapter *adapter)
+{
+ struct ifnet *ifp = iflib_get_ifp(adapter->ctx);
+
+ if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 1 &&
+ !em_disable_crc_stripping)
+ return (true);
+
+ return (false);
+}
+
+static bool
+em_if_vlan_filter_used(struct adapter *adapter)
+{
+ if (!em_if_vlan_filter_capable(adapter))
+ return (false);
+
+ for (int i = 0; i < EM_VFTA_SIZE; i++)
+ if (adapter->shadow_vfta[i] != 0) {
+ return (true);
+ }
+
+ return (false);
+}
+
+static void
+em_if_vlan_filter_enable(struct adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 reg;
+
+ reg = E1000_READ_REG(hw, E1000_RCTL);
+ reg &= ~E1000_RCTL_CFIEN;
+ reg |= E1000_RCTL_VFE;
+ E1000_WRITE_REG(hw, E1000_RCTL, reg);
+}
+
+static void
+em_if_vlan_filter_disable(struct adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 reg;
+
+ reg = E1000_READ_REG(hw, E1000_RCTL);
+ reg &= ~(E1000_RCTL_VFE | E1000_RCTL_CFIEN);
+ E1000_WRITE_REG(hw, E1000_RCTL, reg);
}
static void
em_setup_vlan_hw_support(struct adapter *adapter)
{
+ struct ifnet *ifp = iflib_get_ifp(adapter->ctx);
struct e1000_hw *hw = &adapter->hw;
u32 reg;
- /*
- * We get here thru init_locked, meaning
- * a soft reset, this has already cleared
- * the VFTA and other state, so if there
- * have been no vlan's registered do nothing.
- */
- if (adapter->num_vlans == 0)
+ if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING &&
+ !em_disable_crc_stripping) {
+ reg = E1000_READ_REG(hw, E1000_CTRL);
+ reg |= E1000_CTRL_VME;
+ E1000_WRITE_REG(hw, E1000_CTRL, reg);
+ } else {
+ reg = E1000_READ_REG(hw, E1000_CTRL);
+ reg &= ~E1000_CTRL_VME;
+ E1000_WRITE_REG(hw, E1000_CTRL, reg);
+ }
+
+ /* If we aren't doing HW filtering, we're done */
+ if (!em_if_vlan_filter_capable(adapter)) {
+ em_if_vlan_filter_disable(adapter);
return;
+ }
+
+ /* Disable interrupts for lem-class devices during the filter change */
+ if (hw->mac.type < em_mac_min)
+ em_if_intr_disable(adapter->ctx);
/*
* A soft reset zero's out the VFTA, so
* we need to repopulate it now.
*/
- for (int i = 0; i < EM_VFTA_SIZE; i++)
- if (adapter->shadow_vfta[i] != 0)
- E1000_WRITE_REG_ARRAY(hw, E1000_VFTA,
- i, adapter->shadow_vfta[i]);
- reg = E1000_READ_REG(hw, E1000_CTRL);
- reg |= E1000_CTRL_VME;
- E1000_WRITE_REG(hw, E1000_CTRL, reg);
+ for (int i = 0; i < EM_VFTA_SIZE; i++)
+ if (adapter->shadow_vfta[i] != 0) {
+ if (adapter->vf_ifp)
+ e1000_vfta_set_vf(hw, adapter->shadow_vfta[i], TRUE);
+ else
+ e1000_write_vfta(hw, i, adapter->shadow_vfta[i]);
+ }
/* Enable the Filter Table */
- reg = E1000_READ_REG(hw, E1000_RCTL);
- reg &= ~E1000_RCTL_CFIEN;
- reg |= E1000_RCTL_VFE;
- E1000_WRITE_REG(hw, E1000_RCTL, reg);
+ em_if_vlan_filter_enable(adapter);
+
+ /* Re-enable interrupts for lem-class devices */
+ if (hw->mac.type < em_mac_min)
+ em_if_intr_enable(adapter->ctx);
}
static void
@@ -4088,6 +4150,7 @@
{
switch (event) {
case IFLIB_RESTART_VLAN_CONFIG:
+ return (false);
default:
return (true);
}

File Metadata

Mime Type
text/plain
Expires
Sun, Jan 12, 3:16 PM (9 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15770617
Default Alt Text
D30002.id88395.diff (5 KB)

Event Timeline