Commit 51466239 authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller

igb: rework handling of the vfta and vlvf registers in relation to mng_vlan

This patch corrects some errors in how vlans are being handled when vfs
start interacting with the management vlans.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7d5753f0
...@@ -963,24 +963,23 @@ static void igb_irq_enable(struct igb_adapter *adapter) ...@@ -963,24 +963,23 @@ static void igb_irq_enable(struct igb_adapter *adapter)
static void igb_update_mng_vlan(struct igb_adapter *adapter) static void igb_update_mng_vlan(struct igb_adapter *adapter)
{ {
struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw;
u16 vid = adapter->hw.mng_cookie.vlan_id; u16 vid = adapter->hw.mng_cookie.vlan_id;
u16 old_vid = adapter->mng_vlan_id; u16 old_vid = adapter->mng_vlan_id;
if (adapter->vlgrp) {
if (!vlan_group_get_device(adapter->vlgrp, vid)) {
if (adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
igb_vlan_rx_add_vid(netdev, vid);
adapter->mng_vlan_id = vid;
} else
adapter->mng_vlan_id = IGB_MNG_VLAN_NONE;
if ((old_vid != (u16)IGB_MNG_VLAN_NONE) && if (hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
(vid != old_vid) && /* add VID to filter table */
!vlan_group_get_device(adapter->vlgrp, old_vid)) igb_vfta_set(hw, vid, true);
igb_vlan_rx_kill_vid(netdev, old_vid); adapter->mng_vlan_id = vid;
} else } else {
adapter->mng_vlan_id = vid; adapter->mng_vlan_id = IGB_MNG_VLAN_NONE;
}
if ((old_vid != (u16)IGB_MNG_VLAN_NONE) &&
(vid != old_vid) &&
!vlan_group_get_device(adapter->vlgrp, old_vid)) {
/* remove VID from filter table */
igb_vfta_set(hw, old_vid, false);
} }
} }
...@@ -1847,11 +1846,6 @@ static int igb_open(struct net_device *netdev) ...@@ -1847,11 +1846,6 @@ static int igb_open(struct net_device *netdev)
/* e1000_power_up_phy(adapter); */ /* e1000_power_up_phy(adapter); */
adapter->mng_vlan_id = IGB_MNG_VLAN_NONE;
if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
igb_update_mng_vlan(adapter);
/* before we allocate an interrupt, we must be ready to handle it. /* before we allocate an interrupt, we must be ready to handle it.
* Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
* as soon as we call pci_request_irq, so we have to setup our * as soon as we call pci_request_irq, so we have to setup our
...@@ -1924,14 +1918,6 @@ static int igb_close(struct net_device *netdev) ...@@ -1924,14 +1918,6 @@ static int igb_close(struct net_device *netdev)
igb_free_all_tx_resources(adapter); igb_free_all_tx_resources(adapter);
igb_free_all_rx_resources(adapter); igb_free_all_rx_resources(adapter);
/* kill manageability vlan ID if supported, but not if a vlan with
* the same ID is registered on the host OS (let 8021q kill it) */
if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
!(adapter->vlgrp &&
vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id)))
igb_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
return 0; return 0;
} }
...@@ -4235,7 +4221,11 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf) ...@@ -4235,7 +4221,11 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf)
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 reg, i; u32 reg, i;
/* It is an error to call this function when VFs are not enabled */ /* The vlvf table only exists on 82576 hardware and newer */
if (hw->mac.type < e1000_82576)
return -1;
/* we only need to do this if VMDq is enabled */
if (!adapter->vfs_allocated_count) if (!adapter->vfs_allocated_count)
return -1; return -1;
...@@ -4265,16 +4255,12 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf) ...@@ -4265,16 +4255,12 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf)
/* if !enabled we need to set this up in vfta */ /* if !enabled we need to set this up in vfta */
if (!(reg & E1000_VLVF_VLANID_ENABLE)) { if (!(reg & E1000_VLVF_VLANID_ENABLE)) {
/* add VID to filter table, if bit already set /* add VID to filter table */
* PF must have added it outside of table */ igb_vfta_set(hw, vid, true);
if (igb_vfta_set(hw, vid, true))
reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT +
adapter->vfs_allocated_count);
reg |= E1000_VLVF_VLANID_ENABLE; reg |= E1000_VLVF_VLANID_ENABLE;
} }
reg &= ~E1000_VLVF_VLANID_MASK; reg &= ~E1000_VLVF_VLANID_MASK;
reg |= vid; reg |= vid;
wr32(E1000_VLVF(i), reg); wr32(E1000_VLVF(i), reg);
/* do not modify RLPML for PF devices */ /* do not modify RLPML for PF devices */
...@@ -4290,8 +4276,8 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf) ...@@ -4290,8 +4276,8 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf)
reg |= size; reg |= size;
wr32(E1000_VMOLR(vf), reg); wr32(E1000_VMOLR(vf), reg);
} }
adapter->vf_data[vf].vlans_enabled++;
adapter->vf_data[vf].vlans_enabled++;
return 0; return 0;
} }
} else { } else {
...@@ -5393,21 +5379,15 @@ static void igb_vlan_rx_register(struct net_device *netdev, ...@@ -5393,21 +5379,15 @@ static void igb_vlan_rx_register(struct net_device *netdev,
ctrl |= E1000_CTRL_VME; ctrl |= E1000_CTRL_VME;
wr32(E1000_CTRL, ctrl); wr32(E1000_CTRL, ctrl);
/* enable VLAN receive filtering */ /* Disable CFI check */
rctl = rd32(E1000_RCTL); rctl = rd32(E1000_RCTL);
rctl &= ~E1000_RCTL_CFIEN; rctl &= ~E1000_RCTL_CFIEN;
wr32(E1000_RCTL, rctl); wr32(E1000_RCTL, rctl);
igb_update_mng_vlan(adapter);
} else { } else {
/* disable VLAN tag insert/strip */ /* disable VLAN tag insert/strip */
ctrl = rd32(E1000_CTRL); ctrl = rd32(E1000_CTRL);
ctrl &= ~E1000_CTRL_VME; ctrl &= ~E1000_CTRL_VME;
wr32(E1000_CTRL, ctrl); wr32(E1000_CTRL, ctrl);
if (adapter->mng_vlan_id != (u16)IGB_MNG_VLAN_NONE) {
igb_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
adapter->mng_vlan_id = IGB_MNG_VLAN_NONE;
}
} }
igb_rlpml_set(adapter); igb_rlpml_set(adapter);
...@@ -5422,16 +5402,11 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) ...@@ -5422,16 +5402,11 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
int pf_id = adapter->vfs_allocated_count; int pf_id = adapter->vfs_allocated_count;
if ((hw->mng_cookie.status & /* attempt to add filter to vlvf array */
E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && igb_vlvf_set(adapter, vid, true, pf_id);
(vid == adapter->mng_vlan_id))
return;
/* add vid to vlvf if sr-iov is enabled,
* if that fails add directly to filter table */
if (igb_vlvf_set(adapter, vid, true, pf_id))
igb_vfta_set(hw, vid, true);
/* add the filter since PF can receive vlans w/o entry in vlvf */
igb_vfta_set(hw, vid, true);
} }
static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
...@@ -5439,6 +5414,7 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) ...@@ -5439,6 +5414,7 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
struct igb_adapter *adapter = netdev_priv(netdev); struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
int pf_id = adapter->vfs_allocated_count; int pf_id = adapter->vfs_allocated_count;
s32 err;
igb_irq_disable(adapter); igb_irq_disable(adapter);
vlan_group_set_device(adapter->vlgrp, vid, NULL); vlan_group_set_device(adapter->vlgrp, vid, NULL);
...@@ -5446,17 +5422,11 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) ...@@ -5446,17 +5422,11 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
if (!test_bit(__IGB_DOWN, &adapter->state)) if (!test_bit(__IGB_DOWN, &adapter->state))
igb_irq_enable(adapter); igb_irq_enable(adapter);
if ((adapter->hw.mng_cookie.status & /* remove vlan from VLVF table array */
E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && err = igb_vlvf_set(adapter, vid, false, pf_id);
(vid == adapter->mng_vlan_id)) {
/* release control to f/w */
igb_release_hw_control(adapter);
return;
}
/* remove vid from vlvf if sr-iov is enabled, /* if vid was not present in VLVF just remove it from table */
* if not in vlvf remove from vfta */ if (err)
if (igb_vlvf_set(adapter, vid, false, pf_id))
igb_vfta_set(hw, vid, false); igb_vfta_set(hw, vid, false);
} }
......
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