2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-23 12:43:55 +08:00

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: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Alexander Duyck 2009-10-27 23:47:35 +00:00 committed by David S. Miller
parent 7d5753f08c
commit 51466239fb

View File

@ -963,24 +963,23 @@ static void igb_irq_enable(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 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) &&
(vid != old_vid) &&
!vlan_group_get_device(adapter->vlgrp, old_vid))
igb_vlan_rx_kill_vid(netdev, old_vid);
} else
adapter->mng_vlan_id = vid;
if (hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
/* add VID to filter table */
igb_vfta_set(hw, vid, true);
adapter->mng_vlan_id = vid;
} else {
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)
/* 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.
* 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
@ -1924,14 +1918,6 @@ static int igb_close(struct net_device *netdev)
igb_free_all_tx_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;
}
@ -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;
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)
return -1;
@ -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 (!(reg & E1000_VLVF_VLANID_ENABLE)) {
/* add VID to filter table, if bit already set
* PF must have added it outside of table */
if (igb_vfta_set(hw, vid, true))
reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT +
adapter->vfs_allocated_count);
/* add VID to filter table */
igb_vfta_set(hw, vid, true);
reg |= E1000_VLVF_VLANID_ENABLE;
}
reg &= ~E1000_VLVF_VLANID_MASK;
reg |= vid;
wr32(E1000_VLVF(i), reg);
/* 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)
reg |= size;
wr32(E1000_VMOLR(vf), reg);
}
adapter->vf_data[vf].vlans_enabled++;
adapter->vf_data[vf].vlans_enabled++;
return 0;
}
} else {
@ -5393,21 +5379,15 @@ static void igb_vlan_rx_register(struct net_device *netdev,
ctrl |= E1000_CTRL_VME;
wr32(E1000_CTRL, ctrl);
/* enable VLAN receive filtering */
/* Disable CFI check */
rctl = rd32(E1000_RCTL);
rctl &= ~E1000_RCTL_CFIEN;
wr32(E1000_RCTL, rctl);
igb_update_mng_vlan(adapter);
} else {
/* disable VLAN tag insert/strip */
ctrl = rd32(E1000_CTRL);
ctrl &= ~E1000_CTRL_VME;
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);
@ -5422,16 +5402,11 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
struct e1000_hw *hw = &adapter->hw;
int pf_id = adapter->vfs_allocated_count;
if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
(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);
/* attempt to add filter to vlvf array */
igb_vlvf_set(adapter, vid, true, pf_id);
/* 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)
@ -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 e1000_hw *hw = &adapter->hw;
int pf_id = adapter->vfs_allocated_count;
s32 err;
igb_irq_disable(adapter);
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)
if (!test_bit(__IGB_DOWN, &adapter->state))
igb_irq_enable(adapter);
if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
(vid == adapter->mng_vlan_id)) {
/* release control to f/w */
igb_release_hw_control(adapter);
return;
}
/* remove vlan from VLVF table array */
err = igb_vlvf_set(adapter, vid, false, pf_id);
/* remove vid from vlvf if sr-iov is enabled,
* if not in vlvf remove from vfta */
if (igb_vlvf_set(adapter, vid, false, pf_id))
/* if vid was not present in VLVF just remove it from table */
if (err)
igb_vfta_set(hw, vid, false);
}