Commit 832e821c authored by Alexander Duyck's avatar Alexander Duyck Committed by Jeff Kirsher

igb: Refactor VFTA configuration

This patch starts the clean-up process on the VFTA configuration.
Specifically in this patch I attempt to address and simplify several items
while also updating the code to bring it more inline with what is already
in ixgbe.
Signed-off-by: default avatarAlexander Duyck <aduyck@mirantis.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent c3278587
......@@ -34,6 +34,7 @@
#include "e1000_mac.h"
#include "e1000_82575.h"
#include "e1000_i210.h"
#include "igb.h"
static s32 igb_get_invariants_82575(struct e1000_hw *);
static s32 igb_acquire_phy_82575(struct e1000_hw *);
......@@ -71,6 +72,32 @@ static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw);
static const u16 e1000_82580_rxpbs_table[] = {
36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 };
/* Due to a hw errata, if the host tries to configure the VFTA register
* while performing queries from the BMC or DMA, then the VFTA in some
* cases won't be written.
*/
/**
* igb_write_vfta_i350 - Write value to VLAN filter table
* @hw: pointer to the HW structure
* @offset: register offset in VLAN filter table
* @value: register value written to VLAN filter table
*
* Writes value at the given offset in the register array which stores
* the VLAN filter table.
**/
static void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
{
struct igb_adapter *adapter = hw->back;
int i;
for (i = 10; i--;)
array_wr32(E1000_VFTA, offset, value);
wrfl();
adapter->shadow_vfta[offset] = value;
}
/**
* igb_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO
* @hw: pointer to the HW structure
......@@ -429,6 +456,11 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw)
mac->ops.release_swfw_sync = igb_release_swfw_sync_82575;
}
if ((hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i354))
mac->ops.write_vfta = igb_write_vfta_i350;
else
mac->ops.write_vfta = igb_write_vfta;
/* Set if part includes ASF firmware */
mac->asf_firmware_present = true;
/* Set if manageability features are enabled. */
......@@ -1517,10 +1549,7 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw)
/* Disabling VLAN filtering */
hw_dbg("Initializing the IEEE VLAN\n");
if ((hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i354))
igb_clear_vfta_i350(hw);
else
igb_clear_vfta(hw);
igb_clear_vfta(hw);
/* Setup the receive address */
igb_init_rx_addrs(hw, rar_count);
......
......@@ -325,7 +325,7 @@ struct e1000_mac_operations {
s32 (*get_thermal_sensor_data)(struct e1000_hw *);
s32 (*init_thermal_sensor_thresh)(struct e1000_hw *);
#endif
void (*write_vfta)(struct e1000_hw *, u32, u32);
};
struct e1000_phy_operations {
......
......@@ -92,10 +92,8 @@ void igb_clear_vfta(struct e1000_hw *hw)
{
u32 offset;
for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
array_wr32(E1000_VFTA, offset, 0);
wrfl();
}
for (offset = E1000_VLAN_FILTER_TBL_SIZE; offset--;)
hw->mac.ops.write_vfta(hw, offset, 0);
}
/**
......@@ -107,54 +105,14 @@ void igb_clear_vfta(struct e1000_hw *hw)
* Writes value at the given offset in the register array which stores
* the VLAN filter table.
**/
static void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
{
struct igb_adapter *adapter = hw->back;
array_wr32(E1000_VFTA, offset, value);
wrfl();
}
/* Due to a hw errata, if the host tries to configure the VFTA register
* while performing queries from the BMC or DMA, then the VFTA in some
* cases won't be written.
*/
/**
* igb_clear_vfta_i350 - Clear VLAN filter table
* @hw: pointer to the HW structure
*
* Clears the register array which contains the VLAN filter table by
* setting all the values to 0.
**/
void igb_clear_vfta_i350(struct e1000_hw *hw)
{
u32 offset;
int i;
for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
for (i = 0; i < 10; i++)
array_wr32(E1000_VFTA, offset, 0);
wrfl();
}
}
/**
* igb_write_vfta_i350 - Write value to VLAN filter table
* @hw: pointer to the HW structure
* @offset: register offset in VLAN filter table
* @value: register value written to VLAN filter table
*
* Writes value at the given offset in the register array which stores
* the VLAN filter table.
**/
static void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
{
int i;
for (i = 0; i < 10; i++)
array_wr32(E1000_VFTA, offset, value);
wrfl();
adapter->shadow_vfta[offset] = value;
}
/**
......@@ -185,38 +143,42 @@ void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
/**
* igb_vfta_set - enable or disable vlan in VLAN filter table
* @hw: pointer to the HW structure
* @vid: VLAN id to add or remove
* @add: if true add filter, if false remove
* @vlan: VLAN id to add or remove
* @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 vid, bool add)
s32 igb_vfta_set(struct e1000_hw *hw, u32 vlan, bool vlan_on)
{
u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK;
u32 mask = 1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
u32 vfta;
struct igb_adapter *adapter = hw->back;
s32 ret_val = 0;
u32 regidx, vfta_delta, vfta;
if (vlan > 4095)
return E1000_ERR_PARAM;
/* Part 1
* The VFTA is a bitstring made up of 128 32-bit registers
* that enable the particular VLAN id, much like the MTA:
* bits[11-5]: which register
* bits[4-0]: which bit in the register
*/
regidx = vlan / 32;
vfta_delta = 1 << (vlan % 32);
vfta = adapter->shadow_vfta[regidx];
vfta = adapter->shadow_vfta[index];
/* vfta_delta represents the difference between the current value
* of vfta and the value we want in the register. Since the diff
* is an XOR mask we can just update vfta using an XOR.
*/
vfta_delta &= vlan_on ? ~vfta : vfta;
vfta ^= vfta_delta;
/* bit was set/cleared before we started */
if ((!!(vfta & mask)) == add) {
ret_val = -E1000_ERR_CONFIG;
} else {
if (add)
vfta |= mask;
else
vfta &= ~mask;
}
if ((hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i354))
igb_write_vfta_i350(hw, index, vfta);
else
igb_write_vfta(hw, index, vfta);
adapter->shadow_vfta[index] = vfta;
if (vfta_delta)
hw->mac.ops.write_vfta(hw, regidx, vfta);
return ret_val;
return 0;
}
/**
......
......@@ -56,7 +56,7 @@ s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
void igb_clear_hw_cntrs_base(struct e1000_hw *hw);
void igb_clear_vfta(struct e1000_hw *hw);
void igb_clear_vfta_i350(struct e1000_hw *hw);
void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add);
void igb_config_collision_dist(struct e1000_hw *hw);
void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment