Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+33 −4
Original line number Diff line number Diff line
@@ -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,9 +1549,6 @@ 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);

	/* Setup the receive address */
+1 −1
Original line number Diff line number Diff line
@@ -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 {
+32 −70
Original line number Diff line number Diff line
@@ -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)
{
	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)
void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
{
	int i;
	struct igb_adapter *adapter = hw->back;

	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;
}

/**
+1 −1
Original line number Diff line number Diff line
@@ -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);