net/ixgbe/base: allow bypassing VLAN pool filters
authorBeilei Xing <beilei.xing@intel.com>
Thu, 23 Jun 2016 07:22:30 +0000 (15:22 +0800)
committerBruce Richardson <bruce.richardson@intel.com>
Mon, 27 Jun 2016 14:17:53 +0000 (16:17 +0200)
This patch adds support for the VLAN pool filter (VLVF) to be
bypassed when adding or removing a VLAN filter table array (VFTA) entry.
The PF can utilize the default pool while preserving the VLVF for the
VFs use.
Meanwhile, update the VF operations and drivers where corresponding
functionality is invoked.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
drivers/net/ixgbe/base/ixgbe_82598.c
drivers/net/ixgbe/base/ixgbe_82598.h
drivers/net/ixgbe/base/ixgbe_api.c
drivers/net/ixgbe/base/ixgbe_api.h
drivers/net/ixgbe/base/ixgbe_common.c
drivers/net/ixgbe/base/ixgbe_common.h
drivers/net/ixgbe/base/ixgbe_type.h
drivers/net/ixgbe/base/ixgbe_vf.c
drivers/net/ixgbe/base/ixgbe_vf.h
drivers/net/ixgbe/ixgbe_ethdev.c
drivers/net/ixgbe/ixgbe_pf.c

index 9e65fff..db80880 100644 (file)
@@ -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)
index 89dd11a..0326e70 100644 (file)
@@ -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,
index 90deaf1..1786867 100644 (file)
@@ -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);
 }
 
index 9431d14..c126982 100644 (file)
@@ -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,
index 4551a2a..80ea3b9 100644 (file)
@@ -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;
 
index b4cd366..a790ede 100644 (file)
@@ -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,
index b1fd079..3bf0de0 100644 (file)
@@ -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);
index 81ea6c7..a75074a 100644 (file)
@@ -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;
index 9be2cda..8851cb8 100644 (file)
@@ -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,
index a8fdeb3..d61af37 100644 (file)
@@ -4261,7 +4261,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;
                        }
                }
@@ -4283,7 +4284,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;
@@ -4602,7 +4603,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;
                }
@@ -4664,7 +4666,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));
index 7ffefec..56393ff 100644 (file)
@@ -544,7 +544,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