ixgbe: Add support for adding/removing VLAN on PF bypassing the VLVF
authorAlexander Duyck <aduyck@mirantis.com>
Tue, 3 Nov 2015 01:10:01 +0000 (17:10 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sat, 12 Dec 2015 09:29:28 +0000 (01:29 -0800)
This patch adds support for bypassing the VLVF entry creation when the PF
is adding a new VLAN.  The advantage to doing this is that we can then save
the VLVF entries for the VFs which must have them in order to function,
versus the PF which can fall back on the default pool entry.

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_82598.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h

index 8f09d291a0430a0260cda90da03a300d5ffd7116..d8a9fb8a59e20203c6e2f8910986dd1487ff493a 100644 (file)
@@ -880,11 +880,12 @@ static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
  *  @vlan: VLAN id to write to VLAN filter
  *  @vind: VMDq output index that maps queue to VLAN id in VFTA
  *  @vlan_on: boolean flag to turn on/off VLAN in VFTA
+ *  @vlvf_bypass: boolean flag - unused
  *
  *  Turn on/off specified VLAN in the VLAN filter table.
  **/
 static s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind,
-                               bool vlan_on)
+                               bool vlan_on, bool vlvf_bypass)
 {
        u32 regindex;
        u32 bitindex;
index 3f5fe60fdc11d98e6930f98c14254ffb03bf7e61..5fd860a8d6f75f150a4337abfca485c2214765db 100644 (file)
@@ -2999,16 +2999,21 @@ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
  *  return the VLVF index where this VLAN id should be placed
  *
  **/
-static s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
+static s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass)
 {
+       s32 regindex, first_empty_slot;
        u32 bits = 0;
-       u32 first_empty_slot = 0;
-       s32 regindex;
 
        /* short cut the special case */
        if (vlan == 0)
                return 0;
 
+       /* if vlvf_bypass is set we don't want to use an empty slot, we
+        * will simply bypass the VLVF if there are no entries present in the
+        * VLVF that contain our VLAN
+        */
+       first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0;
+
        /*
          * Search for the vlan id in the VLVF entries. Save off the first empty
          * slot found along the way
@@ -3044,11 +3049,12 @@ static s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
  *  @vlan: VLAN id to write to VLAN filter
  *  @vind: VMDq output index that maps queue to VLAN id in VFVFB
  *  @vlan_on: boolean flag to turn on/off VLAN in VFVF
+ *  @vlvf_bypass: boolean flag indicating updating default pool is okay
  *
  *  Turn on/off specified VLAN in the VLAN filter table.
  **/
 s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
-                          bool vlan_on)
+                          bool vlan_on, bool vlvf_bypass)
 {
        u32 regidx, vfta_delta, vfta, bits;
        s32 vlvf_index;
@@ -3090,9 +3096,12 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
        if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE))
                goto vfta_update;
 
-       vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
-       if (vlvf_index < 0)
+       vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass);
+       if (vlvf_index < 0) {
+               if (vlvf_bypass)
+                       goto vfta_update;
                return vlvf_index;
+       }
 
        bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32));
 
index a0044e4a8b90c92c49c08598423743fec070850c..2b9563137fd88f932053a9a867754fd2328d31c1 100644 (file)
@@ -92,7 +92,7 @@ s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq);
 s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
 s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw);
 s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan,
-                          u32 vind, bool vlan_on);
+                          u32 vind, bool vlan_on, bool vlvf_bypass);
 s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw);
 s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
                                 ixgbe_link_speed *speed,
index c539b1c712011d7c0e26e1e5f782989fd9bc4565..dcd99e61af6468f28fb2b1ca481d1da0a520fa4d 100644 (file)
@@ -3899,7 +3899,7 @@ 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);
+       hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), true, true);
        set_bit(vid, adapter->active_vlans);
 
        return 0;
@@ -3912,7 +3912,7 @@ static int ixgbe_vlan_rx_kill_vid(struct net_device *netdev,
        struct ixgbe_hw *hw = &adapter->hw;
 
        /* remove VID from filter table */
-       hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), false);
+       hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), false, true);
        clear_bit(vid, adapter->active_vlans);
 
        return 0;
index 61a054ace56dc40feb93f7d739c35a8a5623a0b0..3380f14517dc6a7e2e5bd678cff195a7bc728141 100644 (file)
@@ -452,11 +452,27 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter)
 static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
                             u32 vf)
 {
+       struct ixgbe_hw *hw = &adapter->hw;
+       int err;
+
        /* VLAN 0 is a special case, don't allow it to be removed */
        if (!vid && !add)
                return 0;
 
-       return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
+       /* If VLAN overlaps with one the PF is currently monitoring make
+        * sure that we are able to allocate a VLVF entry.  This may be
+        * redundant but it guarantees PF will maintain visibility to
+        * the VLAN.
+        */
+       if (add && test_bit(vid, adapter->active_vlans)) {
+               err = hw->mac.ops.set_vfta(hw, vid, VMDQ_P(0), true, false);
+               if (err)
+                       return err;
+       }
+
+       err = hw->mac.ops.set_vfta(hw, vid, vf, !!add, false);
+
+       return err;
 }
 
 static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
index 1329eddfc9ce7e7b1c8063549e4e9ce9b7039f0b..06add27c8b8c281a1a81ec80909fe8df0dc28452 100644 (file)
@@ -3300,7 +3300,7 @@ struct ixgbe_mac_operations {
        s32 (*enable_mc)(struct ixgbe_hw *);
        s32 (*disable_mc)(struct ixgbe_hw *);
        s32 (*clear_vfta)(struct ixgbe_hw *);
-       s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool);
+       s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool, bool);
        s32 (*init_uta_tables)(struct ixgbe_hw *);
        void (*set_mac_anti_spoofing)(struct ixgbe_hw *, bool, int);
        void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, bool, int);