This patch adds support for the VLVF to be bypassed when adding or
removing a VFTA entry.  The PF can utilize the default pool while
preserving the VLVF for the VFs use.
Meanwhile, update corresponding VF ops and drivers where corresponding
ops is invoked.

Signed-off-by: Beilei Xing <beilei.xing at intel.com>
---
 drivers/net/ixgbe/base/ixgbe_82598.c  |  5 ++-
 drivers/net/ixgbe/base/ixgbe_82598.h  |  3 +-
 drivers/net/ixgbe/base/ixgbe_api.c    | 11 ++++--
 drivers/net/ixgbe/base/ixgbe_api.h    |  5 ++-
 drivers/net/ixgbe/base/ixgbe_common.c | 71 +++++++++++++++++++----------------
 drivers/net/ixgbe/base/ixgbe_common.h |  7 ++--
 drivers/net/ixgbe/base/ixgbe_type.h   |  5 ++-
 drivers/net/ixgbe/base/ixgbe_vf.c     |  6 ++-
 drivers/net/ixgbe/base/ixgbe_vf.h     |  3 +-
 drivers/net/ixgbe/ixgbe_ethdev.c      | 11 ++++--
 drivers/net/ixgbe/ixgbe_pf.c          |  2 +-
 11 files changed, 76 insertions(+), 53 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_82598.c 
b/drivers/net/ixgbe/base/ixgbe_82598.c
index 9e65fff..db80880 100644
--- a/drivers/net/ixgbe/base/ixgbe_82598.c
+++ b/drivers/net/ixgbe/base/ixgbe_82598.c
@@ -995,17 +995,20 @@ 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
+ *  @bypass_vlvf: boolean flag - unused
  *
  *  Turn on/off specified VLAN in the VLAN filter table.
  **/
 s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind,
-                        bool vlan_on)
+                        bool vlan_on, bool bypass_vlvf)
 {
        u32 regindex;
        u32 bitindex;
        u32 bits;
        u32 vftabyte;

+       UNREFERENCED_1PARAMETER(bypass_vlvf);
+
        DEBUGFUNC("ixgbe_set_vfta_82598");

        if (vlan > 4095)
diff --git a/drivers/net/ixgbe/base/ixgbe_82598.h 
b/drivers/net/ixgbe/base/ixgbe_82598.h
index 89dd11a..0326e70 100644
--- a/drivers/net/ixgbe/base/ixgbe_82598.h
+++ b/drivers/net/ixgbe/base/ixgbe_82598.h
@@ -39,7 +39,8 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw);
 s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw);
 void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw);
 s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
-s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool 
vlan_on);
+s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on,
+                        bool vlvf_bypass);
 s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val);
 s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val);
 s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
diff --git a/drivers/net/ixgbe/base/ixgbe_api.c 
b/drivers/net/ixgbe/base/ixgbe_api.c
index 90deaf1..1786867 100644
--- a/drivers/net/ixgbe/base/ixgbe_api.c
+++ b/drivers/net/ixgbe/base/ixgbe_api.c
@@ -1082,13 +1082,15 @@ s32 ixgbe_clear_vfta(struct ixgbe_hw *hw)
  *  @vlan: VLAN id to write to VLAN filter
  *  @vind: VMDq output index that maps queue to VLAN id in VLVFB
  *  @vlan_on: boolean flag to turn on/off VLAN
+ *  @vlvf_bypass: boolean flag indicating updating the default pool is okay
  *
  *  Turn on/off specified VLAN in the VLAN filter table.
  **/
-s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on)
+s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on,
+                  bool vlvf_bypass)
 {
        return ixgbe_call_func(hw, hw->mac.ops.set_vfta, (hw, vlan, vind,
-                              vlan_on), IXGBE_NOT_IMPLEMENTED);
+                                 vlan_on, vlvf_bypass), IXGBE_NOT_IMPLEMENTED);
 }

 /**
@@ -1100,14 +1102,15 @@ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 
vind, bool vlan_on)
  *  @vfta_delta: pointer to the difference between the current value of VFTA
  *               and the desired value
  *  @vfta: the desired value of the VFTA
+ *  @vlvf_bypass: boolean flag indicating updating the default pool is okay
  *
  *  Turn on/off specified bit in VLVF table.
  **/
 s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on,
-                  u32 *vfta_delta, u32 vfta)
+                  u32 *vfta_delta, u32 vfta, bool vlvf_bypass)
 {
        return ixgbe_call_func(hw, hw->mac.ops.set_vlvf, (hw, vlan, vind,
-                              vlan_on, vfta_delta, vfta),
+                               vlan_on, vfta_delta, vfta, vlvf_bypass),
                               IXGBE_NOT_IMPLEMENTED);
 }

diff --git a/drivers/net/ixgbe/base/ixgbe_api.h 
b/drivers/net/ixgbe/base/ixgbe_api.h
index 9431d14..c126982 100644
--- a/drivers/net/ixgbe/base/ixgbe_api.h
+++ b/drivers/net/ixgbe/base/ixgbe_api.h
@@ -124,9 +124,10 @@ s32 ixgbe_enable_mc(struct ixgbe_hw *hw);
 s32 ixgbe_disable_mc(struct ixgbe_hw *hw);
 s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);
 s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan,
-                  u32 vind, bool vlan_on);
+                  u32 vind, bool vlan_on, bool vlvf_bypass);
 s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
-                  bool vlan_on, u32 *vfta_delta, u32 vfta);
+                  bool vlan_on, u32 *vfta_delta, u32 vfta,
+                  bool vlvf_bypass);
 s32 ixgbe_fc_enable(struct ixgbe_hw *hw);
 s32 ixgbe_setup_fc(struct ixgbe_hw *hw);
 s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build,
diff --git a/drivers/net/ixgbe/base/ixgbe_common.c 
b/drivers/net/ixgbe/base/ixgbe_common.c
index 4551a2a..80ea3b9 100644
--- a/drivers/net/ixgbe/base/ixgbe_common.c
+++ b/drivers/net/ixgbe/base/ixgbe_common.c
@@ -3809,44 +3809,44 @@ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
  *  return the VLVF index where this VLAN id should be placed
  *
  **/
-s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
+s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass)
 {
-       u32 bits = 0;
-       u32 first_empty_slot = 0;
-       s32 regindex;
+       s32 regindex, first_empty_slot;
+       u32 bits;

        /* short cut the special case */
        if (vlan == 0)
                return 0;

-       /*
-         * Search for the vlan id in the VLVF entries. Save off the first empty
-         * slot found along the way
-         */
-       for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) {
+       /* 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;
+
+       /* add VLAN enable bit for comparison */
+       vlan |= IXGBE_VLVF_VIEN;
+
+       /* Search for the vlan id in the VLVF entries. Save off the first empty
+        * slot found along the way.
+        *
+        * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1
+        */
+       for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) {
                bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
-               if (!bits && !(first_empty_slot))
+               if (bits == vlan)
+                       return regindex;
+               if (!first_empty_slot && !bits)
                        first_empty_slot = regindex;
-               else if ((bits & 0x0FFF) == vlan)
-                       break;
        }

-       /*
-         * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan
-         * in the VLVF. Else use the first empty VLVF register for this
-         * vlan id.
-         */
-       if (regindex >= IXGBE_VLVF_ENTRIES) {
-               if (first_empty_slot)
-                       regindex = first_empty_slot;
-               else {
-                       ERROR_REPORT1(IXGBE_ERROR_SOFTWARE,
-                                    "No space in VLVF.\n");
-                       regindex = IXGBE_ERR_NO_SPACE;
-               }
-       }
+       /* If we are here then we didn't find the VLAN.  Return first empty
+        * slot we found during our search, else error.
+        */
+       if (!first_empty_slot)
+               ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n");

-       return regindex;
+       return first_empty_slot ? first_empty_slot : IXGBE_ERR_NO_SPACE;
 }

 /**
@@ -3855,11 +3855,12 @@ 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 VLVFB
  *  @vlan_on: boolean flag to turn on/off VLAN
+ *  @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;
        s32 ret_val;
@@ -3896,10 +3897,14 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 
vlan, u32 vind,
         * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF
         */
        ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta,
-                                        vfta);
-       if (ret_val != IXGBE_SUCCESS)
+                                        vfta, vlvf_bypass);
+       if (ret_val != IXGBE_SUCCESS) {
+               if (vlvf_bypass)
+                       goto vfta_update;
                return ret_val;
+       }

+vfta_update:
        /* Update VFTA now that we are ready for traffic */
        if (vfta_delta)
                IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta);
@@ -3916,11 +3921,13 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 
vlan, u32 vind,
  *  @vfta_delta: pointer to the difference between the current value of VFTA
  * and the desired value
  *  @vfta: the desired value of the VFTA
+ *  @vlvf_bypass: boolean flag indicating updating default pool is okay
  *
  *  Turn on/off specified bit in VLVF table.
  **/
 s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
-                          bool vlan_on, u32 *vfta_delta, u32 vfta)
+                          bool vlan_on, u32 *vfta_delta, u32 vfta,
+                          bool vlvf_bypass)
 {
        u32 bits;
        s32 vlvf_index;
@@ -3939,7 +3946,7 @@ s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, 
u32 vind,
         */
        if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE))
                return IXGBE_SUCCESS;
-       vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
+       vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass);
        if (vlvf_index < 0)
                return vlvf_index;

diff --git a/drivers/net/ixgbe/base/ixgbe_common.h 
b/drivers/net/ixgbe/base/ixgbe_common.h
index b4cd366..a790ede 100644
--- a/drivers/net/ixgbe/base/ixgbe_common.h
+++ b/drivers/net/ixgbe/base/ixgbe_common.h
@@ -133,11 +133,12 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 
rar, u32 vmdq);
 s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, 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_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
-                          bool vlan_on, u32 *vfta_delta, u32 vfta);
+                          bool vlan_on, u32 *vfta_delta, u32 vfta,
+                          bool vlvf_bypass);
 s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw);
-s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan);
+s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass);

 s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
                               ixgbe_link_speed *speed,
diff --git a/drivers/net/ixgbe/base/ixgbe_type.h 
b/drivers/net/ixgbe/base/ixgbe_type.h
index b1fd079..3bf0de0 100644
--- a/drivers/net/ixgbe/base/ixgbe_type.h
+++ b/drivers/net/ixgbe/base/ixgbe_type.h
@@ -3865,8 +3865,9 @@ 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_vlvf)(struct ixgbe_hw *, u32, u32, bool, u32 *, u32);
+       s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool, bool);
+       s32 (*set_vlvf)(struct ixgbe_hw *, u32, u32, bool, u32 *, u32,
+                       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);
diff --git a/drivers/net/ixgbe/base/ixgbe_vf.c 
b/drivers/net/ixgbe/base/ixgbe_vf.c
index 81ea6c7..a75074a 100644
--- a/drivers/net/ixgbe/base/ixgbe_vf.c
+++ b/drivers/net/ixgbe/base/ixgbe_vf.c
@@ -424,13 +424,15 @@ s32 ixgbe_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 
*mc_addr_list,
  *  @vlan: 12 bit VLAN ID
  *  @vind: unused by VF drivers
  *  @vlan_on: if true then set bit, else clear bit
+ *  @vlvf_bypass: boolean flag indicating updating default pool is okay
  **/
-s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on)
+s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
+                     bool vlan_on, bool vlvf_bypass)
 {
        struct ixgbe_mbx_info *mbx = &hw->mbx;
        u32 msgbuf[2];
        s32 ret_val;
-       UNREFERENCED_1PARAMETER(vind);
+       UNREFERENCED_2PARAMETER(vind, vlvf_bypass);

        msgbuf[0] = IXGBE_VF_SET_VLAN;
        msgbuf[1] = vlan;
diff --git a/drivers/net/ixgbe/base/ixgbe_vf.h 
b/drivers/net/ixgbe/base/ixgbe_vf.h
index 9be2cda..8851cb8 100644
--- a/drivers/net/ixgbe/base/ixgbe_vf.h
+++ b/drivers/net/ixgbe/base/ixgbe_vf.h
@@ -131,7 +131,8 @@ s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, 
u8 *addr);
 s32 ixgbe_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list,
                                 u32 mc_addr_count, ixgbe_mc_addr_itr,
                                 bool clear);
-s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on);
+s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
+                     bool vlan_on, bool vlvf_bypass);
 void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size);
 int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api);
 int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index eec607c..9497feb 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4129,7 +4129,8 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, 
bool on)
                        mask = 1;
                        for (j = 0; j < 32; j++){
                                if (vfta & mask)
-                                       ixgbe_set_vfta(hw, (i<<5)+j, 0, on);
+                                       ixgbe_set_vfta(hw, (i<<5)+j, 0,
+                                                      on, false);
                                mask<<=1;
                        }
                }
@@ -4151,7 +4152,7 @@ ixgbevf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t 
vlan_id, int on)
        PMD_INIT_FUNC_TRACE();

        /* vind is not used in VF driver, set to 0, check ixgbe_set_vfta_vf */
-       ret = ixgbe_set_vfta(hw, vlan_id, 0, !!on);
+       ret = ixgbe_set_vfta(hw, vlan_id, 0, !!on, false);
        if (ret) {
                PMD_INIT_LOG(ERR, "Unable to set VF vlan");
                return ret;
@@ -4449,7 +4450,8 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, 
uint16_t vlan,
                return -ENOTSUP;
        for (pool_idx = 0; pool_idx < ETH_64_POOLS; pool_idx++) {
                if (pool_mask & ((uint64_t)(1ULL << pool_idx))) {
-                       ret = hw->mac.ops.set_vfta(hw,vlan,pool_idx,vlan_on);
+                       ret = hw->mac.ops.set_vfta(hw, vlan, pool_idx,
+                                                  vlan_on, false);
                        if (ret < 0)
                                return ret;
                }
@@ -4511,7 +4513,8 @@ ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
                        if (mirror_conf->vlan.vlan_mask & (1ULL << i)) {
                                /* search vlan id related pool vlan filter 
index */
                                reg_index = ixgbe_find_vlvf_slot(hw,
-                                               mirror_conf->vlan.vlan_id[i]);
+                                                mirror_conf->vlan.vlan_id[i],
+                                                false);
                                if (reg_index < 0)
                                        return -EINVAL;
                                vlvf = IXGBE_READ_REG(hw, 
IXGBE_VLVF(reg_index));
diff --git a/drivers/net/ixgbe/ixgbe_pf.c b/drivers/net/ixgbe/ixgbe_pf.c
index a2787d9..7cfb87b 100644
--- a/drivers/net/ixgbe/ixgbe_pf.c
+++ b/drivers/net/ixgbe/ixgbe_pf.c
@@ -545,7 +545,7 @@ ixgbe_vf_set_vlan(struct rte_eth_dev *dev, uint32_t vf, 
uint32_t *msgbuf)
                vfinfo[vf].vlan_count++;
        else if (vfinfo[vf].vlan_count)
                vfinfo[vf].vlan_count--;
-       return hw->mac.ops.set_vfta(hw, vid, vf, (bool)add);
+       return hw->mac.ops.set_vfta(hw, vid, vf, (bool)add, false);
 }

 static int
-- 
2.5.0

Reply via email to