Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net Fix a bug that VLAN HW "tagging" enable/disable may ...



details:   https://anonhg.NetBSD.org/src/rev/d8face8106ce
branches:  trunk
changeset: 964855:d8face8106ce
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Tue Aug 20 04:11:22 2019 +0000

description:
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

diffstat:

 sys/dev/pci/ixgbe/ixgbe.c |  66 +++++++++++++++++++++++++++++++++++-----------
 sys/dev/pci/ixgbe/ixv.c   |  67 +++++++++++++++++++++++++++++++++-------------
 sys/net/if_vlan.c         |  57 ++++++++++++++++++---------------------
 3 files changed, 125 insertions(+), 65 deletions(-)

diffs (truncated from 338 to 300 lines):

diff -r f1069e92d08d -r d8face8106ce sys/dev/pci/ixgbe/ixgbe.c
--- a/sys/dev/pci/ixgbe/ixgbe.c Tue Aug 20 03:56:59 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.c Tue Aug 20 04:11:22 2019 +0000
@@ -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 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 @@
 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 @@
        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 */
 
 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;
+       u32             ctrl;
        int             i;
-       u32             ctrl;
-       struct vlanid_list *vlanidp;
        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 @@
                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 @@
                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 */
 
diff -r f1069e92d08d -r d8face8106ce sys/dev/pci/ixgbe/ixv.c
--- a/sys/dev/pci/ixgbe/ixv.c   Tue Aug 20 03:56:59 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixv.c   Tue Aug 20 04:11:22 2019 +0000
@@ -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 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 @@
        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 @@
                 */
                rxr->vtag_strip = hwtagging ? TRUE : FALSE;
        }
-
-       if (!usevlan)
+} /* 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;
+
+       /*
+        *  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 @@
 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 @@
        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;
 }
 
diff -r f1069e92d08d -r d8face8106ce sys/net/if_vlan.c
--- a/sys/net/if_vlan.c Tue Aug 20 03:56:59 2019 +0000
+++ b/sys/net/if_vlan.c Tue Aug 20 04:11:22 2019 +0000
@@ -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 @@
                        }
                        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;



Home | Main Index | Thread Index | Old Index