ixgbe: Do not allow PF to add VLVF entry unless it actually needs it
authorAlexander Duyck <aduyck@mirantis.com>
Thu, 7 Jan 2016 06:48:44 +0000 (22:48 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Mon, 4 Apr 2016 20:01:35 +0000 (13:01 -0700)
While doing the work on igb I realized there were a few cases where we were
still adding VLANs to the VLVF entries for the PF when they were not
needed.  This patch cleans that up so that the only time we add a PF entry
to the VLVF is either for VLAN 0 or if the PF has requested a VLAN that a VF
is already using.

Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c

index 7df3fe2..a01a7f2 100644 (file)
@@ -3908,7 +3908,9 @@ static int ixgbe_vlan_rx_add_vid(struct net_device *netdev,
        struct ixgbe_hw *hw = &adapter->hw;
 
        /* add VID to filter table */
-       hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), true, true);
+       if (!vid || !(adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC))
+               hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), true, !!vid);
+
        set_bit(vid, adapter->active_vlans);
 
        return 0;
@@ -3965,9 +3967,7 @@ static int ixgbe_vlan_rx_kill_vid(struct net_device *netdev,
        struct ixgbe_hw *hw = &adapter->hw;
 
        /* remove VID from filter table */
-       if (adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC)
-               ixgbe_update_pf_promisc_vlvf(adapter, vid);
-       else
+       if (vid && !(adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC))
                hw->mac.ops.set_vfta(hw, vid, VMDQ_P(0), false, true);
 
        clear_bit(vid, adapter->active_vlans);
index 80e47db..4bc2496 100644 (file)
@@ -589,40 +589,40 @@ static void ixgbe_clear_vmvir(struct ixgbe_adapter *adapter, u32 vf)
 static void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       u32 i;
+       u32 vlvfb_mask, pool_mask, i;
+
+       /* create mask for VF and other pools */
+       pool_mask = ~(1 << (VMDQ_P(0) % 32));
+       vlvfb_mask = 1 << (vf % 32);
 
        /* post increment loop, covers VLVF_ENTRIES - 1 to 0 */
        for (i = IXGBE_VLVF_ENTRIES; i--;) {
                u32 bits[2], vlvfb, vid, vfta, vlvf;
                u32 word = i * 2 + vf / 32;
-               u32 mask = 1 << (vf % 32);
+               u32 mask;
 
                vlvfb = IXGBE_READ_REG(hw, IXGBE_VLVFB(word));
 
                /* if our bit isn't set we can skip it */
-               if (!(vlvfb & mask))
+               if (!(vlvfb & vlvfb_mask))
                        continue;
 
                /* clear our bit from vlvfb */
-               vlvfb ^= mask;
+               vlvfb ^= vlvfb_mask;
 
                /* create 64b mask to chedk to see if we should clear VLVF */
                bits[word % 2] = vlvfb;
                bits[~word % 2] = IXGBE_READ_REG(hw, IXGBE_VLVFB(word ^ 1));
 
-               /* if promisc is enabled, PF will be present, leave VFTA */
-               if (adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC) {
-                       bits[VMDQ_P(0) / 32] &= ~(1 << (VMDQ_P(0) % 32));
-
-                       if (bits[0] || bits[1])
-                               goto update_vlvfb;
-                       goto update_vlvf;
-               }
-
                /* if other pools are present, just remove ourselves */
-               if (bits[0] || bits[1])
+               if (bits[(VMDQ_P(0) / 32) ^ 1] ||
+                   (bits[VMDQ_P(0) / 32] & pool_mask))
                        goto update_vlvfb;
 
+               /* if PF is present, leave VFTA */
+               if (bits[0] || bits[1])
+                       goto update_vlvf;
+
                /* if we cannot determine VLAN just remove ourselves */
                vlvf = IXGBE_READ_REG(hw, IXGBE_VLVF(i));
                if (!vlvf)
@@ -638,6 +638,9 @@ static void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf)
 update_vlvf:
                /* clear POOL selection enable */
                IXGBE_WRITE_REG(hw, IXGBE_VLVF(i), 0);
+
+               if (!(adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC))
+                       vlvfb = 0;
 update_vlvfb:
                /* clear pool bits */
                IXGBE_WRITE_REG(hw, IXGBE_VLVFB(word), vlvfb);