Module Name: src Committed By: msaitoh Date: Tue Aug 20 04:11:22 UTC 2019
Modified Files: src/sys/dev/pci/ixgbe: ixgbe.c ixv.c src/sys/net: if_vlan.c Log Message: Fix a bug that VLAN HW "tagging" enable/disable may not refrect correctly. - Always call ec_vlan_cb() if it exists. - Some (or all?) ethernet drivers don't enable HW tagging if no any vlan is attached. ixgbe is one of them. Check the the transition and update VLAN HW tagging function. XXX pullup-9 To generate a diff of this commit: cvs rdiff -u -r1.199 -r1.200 src/sys/dev/pci/ixgbe/ixgbe.c cvs rdiff -u -r1.125 -r1.126 src/sys/dev/pci/ixgbe/ixv.c cvs rdiff -u -r1.143 -r1.144 src/sys/net/if_vlan.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/ixgbe/ixgbe.c diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.199 src/sys/dev/pci/ixgbe/ixgbe.c:1.200 --- src/sys/dev/pci/ixgbe/ixgbe.c:1.199 Tue Jul 30 08:44:28 2019 +++ src/sys/dev/pci/ixgbe/ixgbe.c Tue Aug 20 04:11:22 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.c,v 1.199 2019/07/30 08:44:28 msaitoh Exp $ */ +/* $NetBSD: ixgbe.c,v 1.200 2019/08/20 04:11:22 msaitoh Exp $ */ /****************************************************************************** @@ -219,6 +219,7 @@ static void ixgbe_configure_ivars(struct static u8 * ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); static void ixgbe_eitr_write(struct adapter *, uint32_t, uint32_t); +static void ixgbe_setup_vlan_hw_tagging(struct adapter *); static void ixgbe_setup_vlan_hw_support(struct adapter *); static int ixgbe_vlan_cb(struct ethercom *, uint16_t, bool); static int ixgbe_register_vlan(void *, struct ifnet *, u16); @@ -2305,6 +2306,7 @@ static int ixgbe_vlan_cb(struct ethercom *ec, uint16_t vid, bool set) { struct ifnet *ifp = &ec->ec_if; + struct adapter *adapter = ifp->if_softc; int rv; if (set) @@ -2312,6 +2314,16 @@ ixgbe_vlan_cb(struct ethercom *ec, uint1 else rv = ixgbe_unregister_vlan(ifp->if_softc, ifp, vid); + if (rv != 0) + return rv; + + /* + * Control VLAN HW tagging when ec_nvlan is changed from 1 to 0 + * or 0 to 1. + */ + if ((set && (ec->ec_nvlans == 1)) || (!set && (ec->ec_nvlans == 0))) + ixgbe_setup_vlan_hw_tagging(adapter); + return rv; } @@ -2381,21 +2393,15 @@ ixgbe_unregister_vlan(void *arg, struct } /* ixgbe_unregister_vlan */ static void -ixgbe_setup_vlan_hw_support(struct adapter *adapter) +ixgbe_setup_vlan_hw_tagging(struct adapter *adapter) { struct ethercom *ec = &adapter->osdep.ec; struct ixgbe_hw *hw = &adapter->hw; struct rx_ring *rxr; - int i; u32 ctrl; - struct vlanid_list *vlanidp; + int i; bool hwtagging; - /* - * This function is called from both if_init and ifflags_cb() - * on NetBSD. - */ - /* Enable HW tagging only if any vlan is attached */ hwtagging = (ec->ec_capenable & ETHERCAP_VLAN_HWTAGGING) && VLAN_ATTACHED(ec); @@ -2417,6 +2423,41 @@ ixgbe_setup_vlan_hw_support(struct adapt rxr->vtag_strip = hwtagging ? TRUE : FALSE; } + /* VLAN hw tagging for 82598 */ + if (hw->mac.type == ixgbe_mac_82598EB) { + ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); + if (hwtagging) + ctrl |= IXGBE_VLNCTRL_VME; + else + ctrl &= ~IXGBE_VLNCTRL_VME; + IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); + } +} /* ixgbe_setup_vlan_hw_tagging */ + +static void +ixgbe_setup_vlan_hw_support(struct adapter *adapter) +{ + struct ethercom *ec = &adapter->osdep.ec; + struct ixgbe_hw *hw = &adapter->hw; + int i; + u32 ctrl; + struct vlanid_list *vlanidp; + + /* + * This function is called from both if_init and ifflags_cb() + * on NetBSD. + */ + + /* + * Part 1: + * Setup VLAN HW tagging + */ + ixgbe_setup_vlan_hw_tagging(adapter); + + /* + * Part 2: + * Setup VLAN HW filter + */ /* Cleanup shadow_vfta */ for (i = 0; i < IXGBE_VFTA_SIZE; i++) adapter->shadow_vfta[i] = 0; @@ -2439,13 +2480,6 @@ ixgbe_setup_vlan_hw_support(struct adapt ctrl |= IXGBE_VLNCTRL_VFE; else ctrl &= ~IXGBE_VLNCTRL_VFE; - /* VLAN hw tagging for 82598 */ - if (hw->mac.type == ixgbe_mac_82598EB) { - if (hwtagging) - ctrl |= IXGBE_VLNCTRL_VME; - else - ctrl &= ~IXGBE_VLNCTRL_VME; - } IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); } /* ixgbe_setup_vlan_hw_support */ Index: src/sys/dev/pci/ixgbe/ixv.c diff -u src/sys/dev/pci/ixgbe/ixv.c:1.125 src/sys/dev/pci/ixgbe/ixv.c:1.126 --- src/sys/dev/pci/ixgbe/ixv.c:1.125 Tue Jul 30 08:38:03 2019 +++ src/sys/dev/pci/ixgbe/ixv.c Tue Aug 20 04:11:22 2019 @@ -1,4 +1,4 @@ -/*$NetBSD: ixv.c,v 1.125 2019/07/30 08:38:03 msaitoh Exp $*/ +/*$NetBSD: ixv.c,v 1.126 2019/08/20 04:11:22 msaitoh Exp $*/ /****************************************************************************** @@ -120,6 +120,7 @@ static void ixv_configure_ivars(struct a static u8 * ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); static void ixv_eitr_write(struct adapter *, uint32_t, uint32_t); +static void ixv_setup_vlan_tagging(struct adapter *); static int ixv_setup_vlan_support(struct adapter *); static int ixv_vlan_cb(struct ethercom *, uint16_t, bool); static int ixv_register_vlan(void *, struct ifnet *, u16); @@ -1935,33 +1936,22 @@ ixv_sysctl_rdt_handler(SYSCTLFN_ARGS) return sysctl_lookup(SYSCTLFN_CALL(&node)); } /* ixv_sysctl_rdt_handler */ -/************************************************************************ - * ixv_setup_vlan_support - ************************************************************************/ -static int -ixv_setup_vlan_support(struct adapter *adapter) +static void +ixv_setup_vlan_tagging(struct adapter *adapter) { struct ethercom *ec = &adapter->osdep.ec; struct ixgbe_hw *hw = &adapter->hw; struct rx_ring *rxr; - u32 ctrl, vid, vfta, retry; - struct vlanid_list *vlanidp; - int rv, error = 0; - bool usevlan; + u32 ctrl; + int i; bool hwtagging; - /* - * This function is called from both if_init and ifflags_cb() - * on NetBSD. - */ - usevlan = VLAN_ATTACHED(ec); - /* Enable HW tagging only if any vlan is attached */ hwtagging = (ec->ec_capenable & ETHERCAP_VLAN_HWTAGGING) && VLAN_ATTACHED(ec); /* Enable the queues */ - for (int i = 0; i < adapter->num_queues; i++) { + for (i = 0; i < adapter->num_queues; i++) { rxr = &adapter->rx_rings[i]; ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(rxr->me)); if (hwtagging) @@ -1975,10 +1965,38 @@ ixv_setup_vlan_support(struct adapter *a */ rxr->vtag_strip = hwtagging ? TRUE : FALSE; } +} /* ixv_setup_vlan_tagging */ + +/************************************************************************ + * ixv_setup_vlan_support + ************************************************************************/ +static int +ixv_setup_vlan_support(struct adapter *adapter) +{ + struct ethercom *ec = &adapter->osdep.ec; + struct ixgbe_hw *hw = &adapter->hw; + u32 vid, vfta, retry; + struct vlanid_list *vlanidp; + int rv, error = 0; - if (!usevlan) + /* + * This function is called from both if_init and ifflags_cb() + * on NetBSD. + */ + + /* + * Part 1: + * Setup VLAN HW tagging + */ + ixv_setup_vlan_tagging(adapter); + + if (!VLAN_ATTACHED(ec)) return 0; + /* + * Part 2: + * Setup VLAN HW filter + */ /* Cleanup shadow_vfta */ for (int i = 0; i < IXGBE_VFTA_SIZE; i++) adapter->shadow_vfta[i] = 0; @@ -2036,6 +2054,7 @@ static int ixv_vlan_cb(struct ethercom *ec, uint16_t vid, bool set) { struct ifnet *ifp = &ec->ec_if; + struct adapter *adapter = ifp->if_softc; int rv; if (set) @@ -2043,6 +2062,16 @@ ixv_vlan_cb(struct ethercom *ec, uint16_ else rv = ixv_unregister_vlan(ifp->if_softc, ifp, vid); + if (rv != 0) + return rv; + + /* + * Control VLAN HW tagging when ec_nvlan is changed from 1 to 0 + * or 0 to 1. + */ + if ((set && (ec->ec_nvlans == 1)) || (!set && (ec->ec_nvlans == 0))) + ixv_setup_vlan_tagging(adapter); + return rv; } Index: src/sys/net/if_vlan.c diff -u src/sys/net/if_vlan.c:1.143 src/sys/net/if_vlan.c:1.144 --- src/sys/net/if_vlan.c:1.143 Tue Aug 20 03:56:59 2019 +++ src/sys/net/if_vlan.c Tue Aug 20 04:11:22 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: if_vlan.c,v 1.143 2019/08/20 03:56:59 msaitoh Exp $ */ +/* $NetBSD: if_vlan.c,v 1.144 2019/08/20 04:11:22 msaitoh Exp $ */ /* * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -78,7 +78,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.143 2019/08/20 03:56:59 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.144 2019/08/20 04:11:22 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -485,41 +485,33 @@ vlan_config(struct ifvlan *ifv, struct i } error = 0; } - /* - * Add a vid to the list even if it's not enabled in case - * it's enabled later. - */ - if (ec->ec_capabilities & ETHERCAP_VLAN_HWFILTER) { - vidmem = kmem_alloc(sizeof(struct vlanid_list), - KM_SLEEP); - if (vidmem == NULL){ + /* Add a vid to the list */ + vidmem = kmem_alloc(sizeof(struct vlanid_list), KM_SLEEP); + if (vidmem == NULL) { + error = ENOMEM; + goto viderr; + } + vidmem->vid = vid; + mutex_enter(ec->ec_lock); + SIMPLEQ_INSERT_TAIL(&ec->ec_vids, vidmem, vid_list); + mutex_exit(ec->ec_lock); + + if (ec->ec_vlan_cb != NULL) { + /* + * Call ec_vlan_cb(). It will setup VLAN HW filter or + * HW tagging function. + */ + error = (*ec->ec_vlan_cb)(ec, vid, true); +viderr: + if (error) { ec->ec_nvlans--; if (ec->ec_nvlans == 0) { IFNET_LOCK(p); (void)ether_disable_vlan_mtu(p); IFNET_UNLOCK(p); } - error = ENOMEM; goto done; } - vidmem->vid = vid; - mutex_enter(ec->ec_lock); - SIMPLEQ_INSERT_TAIL(&ec->ec_vids, vidmem, vid_list); - mutex_exit(ec->ec_lock); - } - if (ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) { - if (ec->ec_vlan_cb != NULL) { - error = (*ec->ec_vlan_cb)(ec, vid, true); - if (error) { - ec->ec_nvlans--; - if (ec->ec_nvlans == 0) { - IFNET_LOCK(p); - (void)ether_disable_vlan_mtu(p); - IFNET_UNLOCK(p); - } - goto done; - } - } } /* * If the parent interface can do hardware-assisted @@ -658,8 +650,13 @@ vlan_unconfig_locked(struct ifvlan *ifv, } } mutex_exit(ec->ec_lock); - if (ec->ec_vlan_cb != NULL) + if (ec->ec_vlan_cb != NULL) { + /* + * Call ec_vlan_cb(). It will setup VLAN HW filter or + * HW tagging function. + */ (void)(*ec->ec_vlan_cb)(ec, vid, false); + } if (--ec->ec_nvlans == 0) { IFNET_LOCK(p); (void)ether_disable_vlan_mtu(p);