From 51466239fb9f95343e88c14475a0f99fe4882c54 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 27 Oct 2009 23:47:35 +0000 Subject: [PATCH] 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 Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 94 +++++++++++++------------------------- 1 file changed, 32 insertions(+), 62 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 3ab297844d6a..91709272ae1f 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -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); } -- 2.34.1