reassign 690956 src:linux 3.2.23-1 tags 690956 + upstream patch moreinfo quit
Hi Andrey, Andrey Melnikov wrote: > In wheezy i386 with e1000 driver 7.3.21-k8-NAPI vlan's not working > without switching off rx-vlan-offload. > Backport patch e1000: fix vlan processing regression > commit 52f5509fe8ccb607ff9b84ad618f244262336475 from upstream. Please test the attached patch. (See [1] for instructions.) Thanks, Jonathan [1] http://kernel-handbook.alioth.debian.org/ch-common-tasks.html
From: Jiri Pirko <jpi...@redhat.com> Date: Tue, 20 Mar 2012 18:10:01 +0000 Subject: e1000: fix vlan processing regression commit 52f5509fe8ccb607ff9b84ad618f244262336475 upstream. This patch fixes a regression introduced by commit "e1000: do vlan cleanup (799d531)". Apparently some e1000 chips (not mine) are sensitive about the order of setting vlan filter and vlan stripping/inserting functionality. So this patch changes the order so it's the same as before vlan cleanup. Reported-by: Ben Greear <gree...@candelatech.com> Signed-off-by: Jiri Pirko <jpi...@redhat.com> Tested-by: Ben Greear <gree...@candelatech.com> Tested-by: Aaron Brown <aaron.f.br...@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirs...@intel.com> Signed-off-by: Jonathan Nieder <jrnie...@gmail.com> --- drivers/net/ethernet/intel/e1000/e1000_main.c | 76 +++++++++++++++------------ 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index c5f6b0e60c39..6546191a5951 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -168,6 +168,8 @@ static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, static bool e1000_vlan_used(struct e1000_adapter *adapter); static void e1000_vlan_mode(struct net_device *netdev, u32 features); +static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, + bool filter_on); static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid); static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); static void e1000_restore_vlan(struct e1000_adapter *adapter); @@ -1219,7 +1221,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (err) goto err_register; - e1000_vlan_mode(netdev, netdev->features); + e1000_vlan_filter_on_off(adapter, false); /* print bus type/speed/width info */ e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n", @@ -4553,43 +4555,11 @@ static bool e1000_vlan_used(struct e1000_adapter *adapter) return false; } -static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, - bool filter_on) +static void __e1000_vlan_mode(struct e1000_adapter *adapter, u32 features) { struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_disable(adapter); - - if (filter_on) { - /* enable VLAN receive filtering */ - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_CFIEN; - if (!(adapter->netdev->flags & IFF_PROMISC)) - rctl |= E1000_RCTL_VFE; - ew32(RCTL, rctl); - e1000_update_mng_vlan(adapter); - } else { - /* disable VLAN receive filtering */ - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_VFE; - ew32(RCTL, rctl); - } - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); -} - -static void e1000_vlan_mode(struct net_device *netdev, u32 features) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; u32 ctrl; - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_disable(adapter); - ctrl = er32(CTRL); if (features & NETIF_F_HW_VLAN_RX) { /* enable VLAN tag insert/strip */ @@ -4599,6 +4569,44 @@ static void e1000_vlan_mode(struct net_device *netdev, u32 features) ctrl &= ~E1000_CTRL_VME; } ew32(CTRL, ctrl); +} +static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, + bool filter_on) +{ + struct e1000_hw *hw = &adapter->hw; + u32 rctl; + + if (!test_bit(__E1000_DOWN, &adapter->flags)) + e1000_irq_disable(adapter); + + __e1000_vlan_mode(adapter, adapter->netdev->features); + if (filter_on) { + /* enable VLAN receive filtering */ + rctl = er32(RCTL); + rctl &= ~E1000_RCTL_CFIEN; + if (!(adapter->netdev->flags & IFF_PROMISC)) + rctl |= E1000_RCTL_VFE; + ew32(RCTL, rctl); + e1000_update_mng_vlan(adapter); + } else { + /* disable VLAN receive filtering */ + rctl = er32(RCTL); + rctl &= ~E1000_RCTL_VFE; + ew32(RCTL, rctl); + } + + if (!test_bit(__E1000_DOWN, &adapter->flags)) + e1000_irq_enable(adapter); +} + +static void e1000_vlan_mode(struct net_device *netdev, u32 features) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (!test_bit(__E1000_DOWN, &adapter->flags)) + e1000_irq_disable(adapter); + + __e1000_vlan_mode(adapter, features); if (!test_bit(__E1000_DOWN, &adapter->flags)) e1000_irq_enable(adapter); -- 1.8.0.rc2