ixgbe: Add support for adding/removing VLAN on PF bypassing the VLVF

This patch adds support for bypassing the VLVF entry creation when the PF
is adding a new VLAN.  The advantage to doing this is that we can then save
the VLVF entries for the VFs which must have them in order to function,
versus the PF which can fall back on the default pool entry.

Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
Alexander Duyck 2015-11-02 17:10:01 -08:00 committed by Jeff Kirsher
parent 5ac736a65a
commit b6488b662b
6 changed files with 38 additions and 12 deletions

View File

@ -880,11 +880,12 @@ static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
* @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
* @vlvf_bypass: boolean flag - unused
*
* Turn on/off specified VLAN in the VLAN filter table.
**/
static s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind,
bool vlan_on)
bool vlan_on, bool vlvf_bypass)
{
u32 regindex;
u32 bitindex;

View File

@ -2999,16 +2999,21 @@ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
* return the VLVF index where this VLAN id should be placed
*
**/
static s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
static s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass)
{
s32 regindex, first_empty_slot;
u32 bits = 0;
u32 first_empty_slot = 0;
s32 regindex;
/* short cut the special case */
if (vlan == 0)
return 0;
/* if vlvf_bypass is set we don't want to use an empty slot, we
* will simply bypass the VLVF if there are no entries present in the
* VLVF that contain our VLAN
*/
first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0;
/*
* Search for the vlan id in the VLVF entries. Save off the first empty
* slot found along the way
@ -3044,11 +3049,12 @@ static s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
* @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
* @vlvf_bypass: boolean flag indicating updating default pool is okay
*
* 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)
bool vlan_on, bool vlvf_bypass)
{
u32 regidx, vfta_delta, vfta, bits;
s32 vlvf_index;
@ -3090,9 +3096,12 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE))
goto vfta_update;
vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
if (vlvf_index < 0)
vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass);
if (vlvf_index < 0) {
if (vlvf_bypass)
goto vfta_update;
return vlvf_index;
}
bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32));

View File

@ -92,7 +92,7 @@ s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq);
s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
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);
u32 vind, bool vlan_on, bool vlvf_bypass);
s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw);
s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,

View File

@ -3899,7 +3899,7 @@ static int ixgbe_vlan_rx_add_vid(struct net_device *netdev,
struct ixgbe_hw *hw = &adapter->hw;
/* add VID to filter table */
hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), true);
hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), true, true);
set_bit(vid, adapter->active_vlans);
return 0;
@ -3912,7 +3912,7 @@ static int ixgbe_vlan_rx_kill_vid(struct net_device *netdev,
struct ixgbe_hw *hw = &adapter->hw;
/* remove VID from filter table */
hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), false);
hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), false, true);
clear_bit(vid, adapter->active_vlans);
return 0;

View File

@ -452,11 +452,27 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter)
static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
u32 vf)
{
struct ixgbe_hw *hw = &adapter->hw;
int err;
/* VLAN 0 is a special case, don't allow it to be removed */
if (!vid && !add)
return 0;
return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
/* If VLAN overlaps with one the PF is currently monitoring make
* sure that we are able to allocate a VLVF entry. This may be
* redundant but it guarantees PF will maintain visibility to
* the VLAN.
*/
if (add && test_bit(vid, adapter->active_vlans)) {
err = hw->mac.ops.set_vfta(hw, vid, VMDQ_P(0), true, false);
if (err)
return err;
}
err = hw->mac.ops.set_vfta(hw, vid, vf, !!add, false);
return err;
}
static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)

View File

@ -3300,7 +3300,7 @@ struct ixgbe_mac_operations {
s32 (*enable_mc)(struct ixgbe_hw *);
s32 (*disable_mc)(struct ixgbe_hw *);
s32 (*clear_vfta)(struct ixgbe_hw *);
s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool);
s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool, bool);
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);