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: Alexander Duyck <aduyck@mirantis.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
c3278587e7
commit
832e821c51
4 changed files with 67 additions and 76 deletions
|
@ -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;
|
||||
|
||||
vfta = adapter->shadow_vfta[index];
|
||||
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_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);
|
||||
|
|
Loading…
Reference in a new issue