From c96a57bbf570520ab0cf0f3a0209a88caa066874 Mon Sep 17 00:00:00 2001 From: Yaroslav Tykhiy Date: Wed, 26 Jan 2005 13:44:47 +0000 Subject: Respect the current setting of IFCAP_VLAN_HWTAGGING on the interface when going to toggle VLAN support for internal reasons. If the IFCAP_VLAN_HWTAGGING bit is cleared, we should rely on the (re)init routine to turn VLAN support off and never touch the relevant hardware bits. This applies to other capability bits, too. The user obviously has a reason for clearing a capability bit, e.g., if his particular NIC is buggy and hangs if a certain hardware capability is turned on even for a fraction of a second. The flag adapter->em_insert_vlan_header still is set or reset irrespective of the IFCAP_VLAN_HWTAGGING setting, as before, in order to handle the case when a user sets promiscuous mode on an interface first and later turns its IFCAP_VLAN_HWTAGGING bit on. This change might look orthogonal to rev#1.85, but in fact it is not. It introduces bugfixes that hopefully will make implementing the general scheme mentioned in the commit message of rev#1.85 easier. --- sys/dev/em/if_em.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index 36fadddfdb35f..296c765df2c95 100644 --- a/sys/dev/em/if_em.c +++ b/sys/dev/em/if_em.c @@ -163,6 +163,7 @@ static void em_print_link_status(struct adapter *); static int em_get_buf(int i, struct adapter *, struct mbuf *); static void em_enable_vlans(struct adapter *); +static void em_disable_vlans(struct adapter *); static int em_encap(struct adapter *, struct mbuf **); static void em_smartspeed(struct adapter *); static int em_82547_fifo_workaround(struct adapter *, int); @@ -1511,11 +1512,9 @@ em_set_promisc(struct adapter * adapter) { u_int32_t reg_rctl; - u_int32_t ctrl; struct ifnet *ifp = &adapter->interface_data.ac_if; reg_rctl = E1000_READ_REG(&adapter->hw, RCTL); - ctrl = E1000_READ_REG(&adapter->hw, CTRL); if (ifp->if_flags & IFF_PROMISC) { reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); @@ -1524,8 +1523,8 @@ em_set_promisc(struct adapter * adapter) * This enables bridging of vlan tagged frames to occur * and also allows vlan tags to be seen in tcpdump */ - ctrl &= ~E1000_CTRL_VME; - E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); + if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) + em_disable_vlans(adapter); adapter->em_insert_vlan_header = 1; } else if (ifp->if_flags & IFF_ALLMULTI) { reg_rctl |= E1000_RCTL_MPE; @@ -1542,6 +1541,7 @@ static void em_disable_promisc(struct adapter * adapter) { u_int32_t reg_rctl; + struct ifnet *ifp = &adapter->interface_data.ac_if; reg_rctl = E1000_READ_REG(&adapter->hw, RCTL); @@ -1549,7 +1549,8 @@ em_disable_promisc(struct adapter * adapter) reg_rctl &= (~E1000_RCTL_MPE); E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl); - em_enable_vlans(adapter); + if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) + em_enable_vlans(adapter); adapter->em_insert_vlan_header = 0; return; @@ -2984,6 +2985,18 @@ em_enable_vlans(struct adapter *adapter) return; } +static void +em_disable_vlans(struct adapter *adapter) +{ + uint32_t ctrl; + + ctrl = E1000_READ_REG(&adapter->hw, CTRL); + ctrl &= ~E1000_CTRL_VME; + E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); + + return; +} + static void em_enable_intr(struct adapter * adapter) { -- cgit v1.3