aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/igb/e1000_mac.c
diff options
context:
space:
mode:
authorAlexander Duyck <aduyck@mirantis.com>2016-01-06 23:11:04 -0800
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2016-02-15 16:36:52 -0800
commit8b77c6b20f32511175dfd00322ae82fb31949d55 (patch)
tree07c031c4f72a598430b5bf172e3b8879c543c304 /drivers/net/ethernet/intel/igb/e1000_mac.c
parentigb: Always enable VLAN 0 even if 8021q is not loaded (diff)
downloadlinux-dev-8b77c6b20f32511175dfd00322ae82fb31949d55.tar.xz
linux-dev-8b77c6b20f32511175dfd00322ae82fb31949d55.zip
igb: Merge VLVF configuration into igb_vfta_set
This change makes it so that we can merge the configuration of the VLVF registers into the setting of the VFTA register. By doing this we simplify the logic and make use of similar functionality that we have already added for ixgbe making it easier to maintain both drivers. Signed-off-by: Alexander Duyck <aduyck@mirantis.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/igb/e1000_mac.c')
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.c119
1 files changed, 115 insertions, 4 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c
index 97f6fae48d1d..07cf4fe58338 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -141,21 +141,69 @@ void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
}
/**
+ * igb_find_vlvf_slot - find the VLAN id or the first empty slot
+ * @hw: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ * @vlvf_bypass: skip VLVF if no match is found
+ *
+ * return the VLVF index where this VLAN id should be placed
+ *
+ **/
+static s32 igb_find_vlvf_slot(struct e1000_hw *hw, u32 vlan, bool vlvf_bypass)
+{
+ s32 regindex, first_empty_slot;
+ u32 bits;
+
+ /* 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 ? -E1000_ERR_NO_SPACE : 0;
+
+ /* 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 = E1000_VLVF_ARRAY_SIZE; --regindex > 0;) {
+ bits = rd32(E1000_VLVF(regindex)) & E1000_VLVF_VLANID_MASK;
+ if (bits == vlan)
+ return regindex;
+ if (!first_empty_slot && !bits)
+ first_empty_slot = regindex;
+ }
+
+ return first_empty_slot ? : -E1000_ERR_NO_SPACE;
+}
+
+/**
* igb_vfta_set - enable or disable vlan in VLAN filter table
* @hw: pointer to the HW structure
* @vlan: VLAN id to add or remove
+ * @vind: VMDq output index that maps queue to VLAN id
* @vlan_on: if true add filter, if false remove
*
* Sets or clears a bit in the VLAN filter table array based on VLAN id
* and if we are adding or removing the filter
**/
-s32 igb_vfta_set(struct e1000_hw *hw, u32 vlan, bool vlan_on)
+s32 igb_vfta_set(struct e1000_hw *hw, u32 vlan, u32 vind,
+ bool vlan_on, bool vlvf_bypass)
{
struct igb_adapter *adapter = hw->back;
- u32 regidx, vfta_delta, vfta;
+ u32 regidx, vfta_delta, vfta, bits;
+ s32 vlvf_index;
- if (vlan > 4095)
- return E1000_ERR_PARAM;
+ if ((vlan > 4095) || (vind > 7))
+ return -E1000_ERR_PARAM;
+
+ /* this is a 2 part operation - first the VFTA, then the
+ * VLVF and VLVFB if VT Mode is set
+ * We don't write the VFTA until we know the VLVF part succeeded.
+ */
/* Part 1
* The VFTA is a bitstring made up of 128 32-bit registers
@@ -174,6 +222,69 @@ s32 igb_vfta_set(struct e1000_hw *hw, u32 vlan, bool vlan_on)
vfta_delta &= vlan_on ? ~vfta : vfta;
vfta ^= vfta_delta;
+ /* Part 2
+ * If VT Mode is set
+ * Either vlan_on
+ * make sure the VLAN is in VLVF
+ * set the vind bit in the matching VLVFB
+ * Or !vlan_on
+ * clear the pool bit and possibly the vind
+ */
+ if (!adapter->vfs_allocated_count)
+ goto vfta_update;
+
+ vlvf_index = igb_find_vlvf_slot(hw, vlan, vlvf_bypass);
+ if (vlvf_index < 0) {
+ if (vlvf_bypass)
+ goto vfta_update;
+ return vlvf_index;
+ }
+
+ bits = rd32(E1000_VLVF(vlvf_index));
+
+ /* set the pool bit */
+ bits |= 1 << (E1000_VLVF_POOLSEL_SHIFT + vind);
+ if (vlan_on)
+ goto vlvf_update;
+
+ /* clear the pool bit */
+ bits ^= 1 << (E1000_VLVF_POOLSEL_SHIFT + vind);
+
+ if (!(bits & E1000_VLVF_POOLSEL_MASK)) {
+ /* Clear VFTA first, then disable VLVF. Otherwise
+ * we run the risk of stray packets leaking into
+ * the PF via the default pool
+ */
+ if (vfta_delta)
+ hw->mac.ops.write_vfta(hw, regidx, vfta);
+
+ /* disable VLVF and clear remaining bit from pool */
+ wr32(E1000_VLVF(vlvf_index), 0);
+
+ return 0;
+ }
+
+ /* If there are still bits set in the VLVFB registers
+ * for the VLAN ID indicated we need to see if the
+ * caller is requesting that we clear the VFTA entry bit.
+ * If the caller has requested that we clear the VFTA
+ * entry bit but there are still pools/VFs using this VLAN
+ * ID entry then ignore the request. We're not worried
+ * about the case where we're turning the VFTA VLAN ID
+ * entry bit on, only when requested to turn it off as
+ * there may be multiple pools and/or VFs using the
+ * VLAN ID entry. In that case we cannot clear the
+ * VFTA bit until all pools/VFs using that VLAN ID have also
+ * been cleared. This will be indicated by "bits" being
+ * zero.
+ */
+ vfta_delta = 0;
+
+vlvf_update:
+ /* record pool change and enable VLAN ID if not already enabled */
+ wr32(E1000_VLVF(vlvf_index), bits | vlan | E1000_VLVF_VLANID_ENABLE);
+
+vfta_update:
/* bit was set/cleared before we started */
if (vfta_delta)
hw->mac.ops.write_vfta(hw, regidx, vfta);