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 @@ ...@@ -34,6 +34,7 @@
#include "e1000_mac.h" #include "e1000_mac.h"
#include "e1000_82575.h" #include "e1000_82575.h"
#include "e1000_i210.h" #include "e1000_i210.h"
#include "igb.h"
static s32 igb_get_invariants_82575(struct e1000_hw *); static s32 igb_get_invariants_82575(struct e1000_hw *);
static s32 igb_acquire_phy_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); ...@@ -71,6 +72,32 @@ static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw);
static const u16 e1000_82580_rxpbs_table[] = { static const u16 e1000_82580_rxpbs_table[] = {
36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 }; 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 * igb_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
...@@ -429,6 +456,11 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw) ...@@ -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; 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 */ /* Set if part includes ASF firmware */
mac->asf_firmware_present = true; mac->asf_firmware_present = true;
/* Set if manageability features are enabled. */ /* Set if manageability features are enabled. */
...@@ -1517,10 +1549,7 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw) ...@@ -1517,10 +1549,7 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw)
/* Disabling VLAN filtering */ /* Disabling VLAN filtering */
hw_dbg("Initializing the IEEE VLAN\n"); hw_dbg("Initializing the IEEE VLAN\n");
if ((hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i354)) igb_clear_vfta(hw);
igb_clear_vfta_i350(hw);
else
igb_clear_vfta(hw);
/* Setup the receive address */ /* Setup the receive address */
igb_init_rx_addrs(hw, rar_count); igb_init_rx_addrs(hw, rar_count);
......
...@@ -325,7 +325,7 @@ struct e1000_mac_operations { ...@@ -325,7 +325,7 @@ struct e1000_mac_operations {
s32 (*get_thermal_sensor_data)(struct e1000_hw *); s32 (*get_thermal_sensor_data)(struct e1000_hw *);
s32 (*init_thermal_sensor_thresh)(struct e1000_hw *); s32 (*init_thermal_sensor_thresh)(struct e1000_hw *);
#endif #endif
void (*write_vfta)(struct e1000_hw *, u32, u32);
}; };
struct e1000_phy_operations { struct e1000_phy_operations {
......
...@@ -92,10 +92,8 @@ void igb_clear_vfta(struct e1000_hw *hw) ...@@ -92,10 +92,8 @@ void igb_clear_vfta(struct e1000_hw *hw)
{ {
u32 offset; u32 offset;
for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { for (offset = E1000_VLAN_FILTER_TBL_SIZE; offset--;)
array_wr32(E1000_VFTA, offset, 0); hw->mac.ops.write_vfta(hw, offset, 0);
wrfl();
}
} }
/** /**
...@@ -107,54 +105,14 @@ void igb_clear_vfta(struct e1000_hw *hw) ...@@ -107,54 +105,14 @@ void igb_clear_vfta(struct e1000_hw *hw)
* Writes value at the given offset in the register array which stores * Writes value at the given offset in the register array which stores
* the VLAN filter table. * 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); array_wr32(E1000_VFTA, offset, value);
wrfl(); 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++) adapter->shadow_vfta[offset] = value;
array_wr32(E1000_VFTA, offset, value);
wrfl();
} }
/** /**
...@@ -185,38 +143,42 @@ void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) ...@@ -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 * igb_vfta_set - enable or disable vlan in VLAN filter table
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
* @vid: VLAN id to add or remove * @vlan: VLAN id to add or remove
* @add: if true add filter, if false 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 * Sets or clears a bit in the VLAN filter table array based on VLAN id
* and if we are adding or removing the filter * 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; 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 */ /* bit was set/cleared before we started */
if ((!!(vfta & mask)) == add) { if (vfta_delta)
ret_val = -E1000_ERR_CONFIG; hw->mac.ops.write_vfta(hw, regidx, vfta);
} 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;
return ret_val; return 0;
} }
/** /**
......
...@@ -56,7 +56,7 @@ s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, ...@@ -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_hw_cntrs_base(struct e1000_hw *hw);
void igb_clear_vfta(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); s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add);
void igb_config_collision_dist(struct e1000_hw *hw); void igb_config_collision_dist(struct e1000_hw *hw);
void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); 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