net/ixgbe/base: simplify VLAN management
This patch simplifies the adding and removing VLANs from VFTA/VLVF/VLVFB registers. The logic to determine the registers to use has been simplified to (vid / 32) and (1 - vid / 32). Many conditional paths and checks are no longer needed with this patch. Signed-off-by: Beilei Xing <beilei.xing@intel.com>
This commit is contained in:
parent
7c9a0b715d
commit
b978f7b38c
@ -1080,8 +1080,8 @@ s32 ixgbe_clear_vfta(struct ixgbe_hw *hw)
|
||||
* ixgbe_set_vfta - Set VLAN filter table
|
||||
* @hw: pointer to hardware structure
|
||||
* @vlan: VLAN id to write to VLAN filter
|
||||
* @vind: VMDq output index that maps queue to VLAN id in VFTA
|
||||
* @vlan_on: boolean flag to turn on/off VLAN in VFTA
|
||||
* @vind: VMDq output index that maps queue to VLAN id in VLVFB
|
||||
* @vlan_on: boolean flag to turn on/off VLAN
|
||||
*
|
||||
* Turn on/off specified VLAN in the VLAN filter table.
|
||||
**/
|
||||
@ -1095,18 +1095,20 @@ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on)
|
||||
* ixgbe_set_vlvf - Set VLAN Pool Filter
|
||||
* @hw: pointer to hardware structure
|
||||
* @vlan: VLAN id to write to VLAN filter
|
||||
* @vind: VMDq output index that maps queue to VLAN id in VFVFB
|
||||
* @vlan_on: boolean flag to turn on/off VLAN in VFVF
|
||||
* @vfta_changed: pointer to boolean flag which indicates whether VFTA
|
||||
* should be changed
|
||||
* @vind: VMDq output index that maps queue to VLAN id in VLVFB
|
||||
* @vlan_on: boolean flag to turn on/off VLAN in VLVF
|
||||
* @vfta_delta: pointer to the difference between the current value of VFTA
|
||||
* and the desired value
|
||||
* @vfta: the desired value of the VFTA
|
||||
*
|
||||
* Turn on/off specified bit in VLVF table.
|
||||
**/
|
||||
s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on,
|
||||
bool *vfta_changed)
|
||||
u32 *vfta_delta, u32 vfta)
|
||||
{
|
||||
return ixgbe_call_func(hw, hw->mac.ops.set_vlvf, (hw, vlan, vind,
|
||||
vlan_on, vfta_changed), IXGBE_NOT_IMPLEMENTED);
|
||||
vlan_on, vfta_delta, vfta),
|
||||
IXGBE_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,7 +126,7 @@ s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);
|
||||
s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan,
|
||||
u32 vind, bool vlan_on);
|
||||
s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
|
||||
bool vlan_on, bool *vfta_changed);
|
||||
bool vlan_on, u32 *vfta_delta, u32 vfta);
|
||||
s32 ixgbe_fc_enable(struct ixgbe_hw *hw);
|
||||
s32 ixgbe_setup_fc(struct ixgbe_hw *hw);
|
||||
s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build,
|
||||
|
@ -3853,24 +3853,20 @@ s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
|
||||
* ixgbe_set_vfta_generic - Set VLAN filter table
|
||||
* @hw: pointer to hardware structure
|
||||
* @vlan: VLAN id to write to VLAN filter
|
||||
* @vind: VMDq output index that maps queue to VLAN id in VFVFB
|
||||
* @vlan_on: boolean flag to turn on/off VLAN in VFVF
|
||||
* @vind: VMDq output index that maps queue to VLAN id in VLVFB
|
||||
* @vlan_on: boolean flag to turn on/off VLAN
|
||||
*
|
||||
* Turn on/off specified VLAN in the VLAN filter table.
|
||||
**/
|
||||
s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
|
||||
bool vlan_on)
|
||||
{
|
||||
s32 regindex;
|
||||
u32 bitindex;
|
||||
u32 vfta;
|
||||
u32 targetbit;
|
||||
s32 ret_val = IXGBE_SUCCESS;
|
||||
bool vfta_changed = false;
|
||||
u32 regidx, vfta_delta, vfta;
|
||||
s32 ret_val;
|
||||
|
||||
DEBUGFUNC("ixgbe_set_vfta_generic");
|
||||
|
||||
if (vlan > 4095)
|
||||
if (vlan > 4095 || vind > 63)
|
||||
return IXGBE_ERR_PARAM;
|
||||
|
||||
/*
|
||||
@ -3885,33 +3881,28 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
|
||||
* bits[11-5]: which register
|
||||
* bits[4-0]: which bit in the register
|
||||
*/
|
||||
regindex = (vlan >> 5) & 0x7F;
|
||||
bitindex = vlan & 0x1F;
|
||||
targetbit = (1 << bitindex);
|
||||
vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
|
||||
regidx = vlan / 32;
|
||||
vfta_delta = 1 << (vlan % 32);
|
||||
vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx));
|
||||
|
||||
if (vlan_on) {
|
||||
if (!(vfta & targetbit)) {
|
||||
vfta |= targetbit;
|
||||
vfta_changed = true;
|
||||
}
|
||||
} else {
|
||||
if ((vfta & targetbit)) {
|
||||
vfta &= ~targetbit;
|
||||
vfta_changed = true;
|
||||
}
|
||||
}
|
||||
/* 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 the vfta using an XOR
|
||||
*/
|
||||
vfta_delta &= vlan_on ? ~vfta : vfta;
|
||||
vfta ^= vfta_delta;
|
||||
|
||||
/* Part 2
|
||||
* Call ixgbe_set_vlvf_generic to set VLVFB and VLVF
|
||||
*/
|
||||
ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on,
|
||||
&vfta_changed);
|
||||
ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta,
|
||||
vfta);
|
||||
if (ret_val != IXGBE_SUCCESS)
|
||||
return ret_val;
|
||||
|
||||
if (vfta_changed)
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta);
|
||||
/* Update VFTA now that we are ready for traffic */
|
||||
if (vfta_delta)
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta);
|
||||
|
||||
return IXGBE_SUCCESS;
|
||||
}
|
||||
@ -3920,21 +3911,23 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
|
||||
* ixgbe_set_vlvf_generic - Set VLAN Pool Filter
|
||||
* @hw: pointer to hardware structure
|
||||
* @vlan: VLAN id to write to VLAN filter
|
||||
* @vind: VMDq output index that maps queue to VLAN id in VFVFB
|
||||
* @vlan_on: boolean flag to turn on/off VLAN in VFVF
|
||||
* @vfta_changed: pointer to boolean flag which indicates whether VFTA
|
||||
* should be changed
|
||||
* @vind: VMDq output index that maps queue to VLAN id in VLVFB
|
||||
* @vlan_on: boolean flag to turn on/off VLAN in VLVF
|
||||
* @vfta_delta: pointer to the difference between the current value of VFTA
|
||||
* and the desired value
|
||||
* @vfta: the desired value of the VFTA
|
||||
*
|
||||
* Turn on/off specified bit in VLVF table.
|
||||
**/
|
||||
s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
|
||||
bool vlan_on, bool *vfta_changed)
|
||||
bool vlan_on, u32 *vfta_delta, u32 vfta)
|
||||
{
|
||||
u32 vt;
|
||||
u32 bits;
|
||||
s32 vlvf_index;
|
||||
|
||||
DEBUGFUNC("ixgbe_set_vlvf_generic");
|
||||
|
||||
if (vlan > 4095)
|
||||
if (vlan > 4095 || vind > 63)
|
||||
return IXGBE_ERR_PARAM;
|
||||
|
||||
/* If VT Mode is set
|
||||
@ -3944,82 +3937,57 @@ s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
|
||||
* Or !vlan_on
|
||||
* clear the pool bit and possibly the vind
|
||||
*/
|
||||
vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
|
||||
if (vt & IXGBE_VT_CTL_VT_ENABLE) {
|
||||
s32 vlvf_index;
|
||||
u32 bits;
|
||||
if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE))
|
||||
return IXGBE_SUCCESS;
|
||||
vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
|
||||
if (vlvf_index < 0)
|
||||
return vlvf_index;
|
||||
|
||||
vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
|
||||
if (vlvf_index < 0)
|
||||
return vlvf_index;
|
||||
bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32));
|
||||
|
||||
if (vlan_on) {
|
||||
/* set the pool bit */
|
||||
if (vind < 32) {
|
||||
bits = IXGBE_READ_REG(hw,
|
||||
IXGBE_VLVFB(vlvf_index * 2));
|
||||
bits |= (1 << vind);
|
||||
IXGBE_WRITE_REG(hw,
|
||||
IXGBE_VLVFB(vlvf_index * 2),
|
||||
bits);
|
||||
} else {
|
||||
bits = IXGBE_READ_REG(hw,
|
||||
IXGBE_VLVFB((vlvf_index * 2) + 1));
|
||||
bits |= (1 << (vind - 32));
|
||||
IXGBE_WRITE_REG(hw,
|
||||
IXGBE_VLVFB((vlvf_index * 2) + 1),
|
||||
bits);
|
||||
}
|
||||
} else {
|
||||
/* clear the pool bit */
|
||||
if (vind < 32) {
|
||||
bits = IXGBE_READ_REG(hw,
|
||||
IXGBE_VLVFB(vlvf_index * 2));
|
||||
bits &= ~(1 << vind);
|
||||
IXGBE_WRITE_REG(hw,
|
||||
IXGBE_VLVFB(vlvf_index * 2),
|
||||
bits);
|
||||
bits |= IXGBE_READ_REG(hw,
|
||||
IXGBE_VLVFB((vlvf_index * 2) + 1));
|
||||
} else {
|
||||
bits = IXGBE_READ_REG(hw,
|
||||
IXGBE_VLVFB((vlvf_index * 2) + 1));
|
||||
bits &= ~(1 << (vind - 32));
|
||||
IXGBE_WRITE_REG(hw,
|
||||
IXGBE_VLVFB((vlvf_index * 2) + 1),
|
||||
bits);
|
||||
bits |= IXGBE_READ_REG(hw,
|
||||
IXGBE_VLVFB(vlvf_index * 2));
|
||||
}
|
||||
}
|
||||
/* set the pool bit */
|
||||
bits |= 1 << (vind % 32);
|
||||
if (vlan_on)
|
||||
goto vlvf_update;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
/* clear the pool bit */
|
||||
bits ^= 1 << (vind % 32);
|
||||
|
||||
if (!bits &&
|
||||
!IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) {
|
||||
/* Clear VFTA first, then disable VLVF. Otherwise
|
||||
* we run the risk of stray packets leaking into
|
||||
* the PF via the default pool
|
||||
*/
|
||||
if (bits) {
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index),
|
||||
(IXGBE_VLVF_VIEN | vlan));
|
||||
if ((!vlan_on) && (vfta_changed != NULL)) {
|
||||
/* someone wants to clear the vfta entry
|
||||
* but some pools/VFs are still using it.
|
||||
* Ignore it. */
|
||||
*vfta_changed = false;
|
||||
}
|
||||
} else
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
|
||||
if (vfta_delta)
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VFTA(vlan / 32), vfta);
|
||||
|
||||
/* disable VLVF and clear remaining bit from pool */
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0);
|
||||
|
||||
return IXGBE_SUCCESS;
|
||||
}
|
||||
/* 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 */
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan);
|
||||
|
||||
return IXGBE_SUCCESS;
|
||||
}
|
||||
@ -4042,7 +4010,7 @@ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
|
||||
for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) {
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2 + 1), 0);
|
||||
}
|
||||
|
||||
return IXGBE_SUCCESS;
|
||||
|
@ -135,7 +135,7 @@ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw);
|
||||
s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan,
|
||||
u32 vind, bool vlan_on);
|
||||
s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
|
||||
bool vlan_on, bool *vfta_changed);
|
||||
bool vlan_on, u32 *vfta_delta, u32 vfta);
|
||||
s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw);
|
||||
s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan);
|
||||
|
||||
|
@ -3866,7 +3866,7 @@ struct ixgbe_mac_operations {
|
||||
s32 (*disable_mc)(struct ixgbe_hw *);
|
||||
s32 (*clear_vfta)(struct ixgbe_hw *);
|
||||
s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool);
|
||||
s32 (*set_vlvf)(struct ixgbe_hw *, u32, u32, bool, bool *);
|
||||
s32 (*set_vlvf)(struct ixgbe_hw *, u32, u32, bool, u32 *, u32);
|
||||
s32 (*init_uta_tables)(struct ixgbe_hw *);
|
||||
void (*set_mac_anti_spoofing)(struct ixgbe_hw *, bool, int);
|
||||
void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, bool, int);
|
||||
|
Loading…
Reference in New Issue
Block a user