aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/igb
diff options
context:
space:
mode:
authorCorinna Vinschen <vinschen@redhat.com>2016-01-28 07:53:23 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2016-02-24 18:50:40 -0500
commit030f9f52642a20cbd8c1334a237e92e3ef55e2b1 (patch)
tree46918b2eb0cd4153f3af97d2dd8c3f39283df68c /drivers/net/ethernet/intel/igb
parentcc54a59ae6e528c70666033ed085d059f555a57d (diff)
igb: Fix VLAN tag stripping on Intel i350
Problem: When switching off VLAN offloading on an i350, the VLAN interface gets unusable. For testing, set up a VLAN on an i350 and some remote machine, e.g.: $ ip link add link eth0 name eth0.42 type vlan id 42 $ ip addr add 192.168.42.1/24 dev eth0.42 $ ip link set dev eth0.42 up Offloading is switched on by default: $ ethtool -k eth0 | grep vlan-offload rx-vlan-offload: on tx-vlan-offload: on $ ping -c 3 -I eth0.42 192.168.42.2 [...works as usual...] Now switch off VLAN offloading and try again: $ ethtool -K eth0 rxvlan off Actual changes: rx-vlan-offload: off tx-vlan-offload: off [requested on] $ ping -c 3 -I eth0.42 192.168.42.2 PING 192.168.42.2 (192.168.42.2) from 192.168.42.1 eth0.42: 56(84) bytes of da ta. --- 192.168.42.2 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 1999ms I can only reproduce it on an i350, the above works fine on a 82580. While inspecting the igb source, I came across the code in igb_set_vmolr which sets the E1000_VMOLR_STRVLAN/E1000_DVMOLR_STRVLAN flags once and for all, and in all of the igb code there's no other place where the STRVLAN is set or cleared. Thus, VLAN stripping is enabled in igb unconditionally, independently of the offloading setting. I compared that to the latest Intel igb-5.3.3.5 driver from http://sourceforge.net/projects/e1000/ which in fact sets and clears the STRVLAN flag independently from igb_set_vmolr in its own function igb_set_vf_vlan_strip, depending on the vlan settings. So I included the STRVLAN handling from the igb-5.3.3.5 driver into our current igb driver and tested the above scenario again. This time ping still works after switching off VLAN offloading. Tested on i350, with and without addtional VFs, as well as on 82580 successfully. Signed-off-by: Corinna Vinschen <vinschen@redhat.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/igb')
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index d90dcd16f57c..3b56f809967c 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3589,6 +3589,28 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
3589 return 0; 3589 return 0;
3590} 3590}
3591 3591
3592static inline void igb_set_vf_vlan_strip(struct igb_adapter *adapter,
3593 int vfn, bool enable)
3594{
3595 struct e1000_hw *hw = &adapter->hw;
3596 u32 val, reg;
3597
3598 if (hw->mac.type < e1000_82576)
3599 return;
3600
3601 if (hw->mac.type == e1000_i350)
3602 reg = E1000_DVMOLR(vfn);
3603 else
3604 reg = E1000_VMOLR(vfn);
3605
3606 val = rd32(reg);
3607 if (enable)
3608 val |= E1000_VMOLR_STRVLAN;
3609 else
3610 val &= ~(E1000_VMOLR_STRVLAN);
3611 wr32(reg, val);
3612}
3613
3592static inline void igb_set_vmolr(struct igb_adapter *adapter, 3614static inline void igb_set_vmolr(struct igb_adapter *adapter,
3593 int vfn, bool aupe) 3615 int vfn, bool aupe)
3594{ 3616{
@@ -3602,14 +3624,6 @@ static inline void igb_set_vmolr(struct igb_adapter *adapter,
3602 return; 3624 return;
3603 3625
3604 vmolr = rd32(E1000_VMOLR(vfn)); 3626 vmolr = rd32(E1000_VMOLR(vfn));
3605 vmolr |= E1000_VMOLR_STRVLAN; /* Strip vlan tags */
3606 if (hw->mac.type == e1000_i350) {
3607 u32 dvmolr;
3608
3609 dvmolr = rd32(E1000_DVMOLR(vfn));
3610 dvmolr |= E1000_DVMOLR_STRVLAN;
3611 wr32(E1000_DVMOLR(vfn), dvmolr);
3612 }
3613 if (aupe) 3627 if (aupe)
3614 vmolr |= E1000_VMOLR_AUPE; /* Accept untagged packets */ 3628 vmolr |= E1000_VMOLR_AUPE; /* Accept untagged packets */
3615 else 3629 else
@@ -6099,6 +6113,7 @@ static int igb_enable_port_vlan(struct igb_adapter *adapter, int vf,
6099 6113
6100 adapter->vf_data[vf].pf_vlan = vlan; 6114 adapter->vf_data[vf].pf_vlan = vlan;
6101 adapter->vf_data[vf].pf_qos = qos; 6115 adapter->vf_data[vf].pf_qos = qos;
6116 igb_set_vf_vlan_strip(adapter, vf, true);
6102 dev_info(&adapter->pdev->dev, 6117 dev_info(&adapter->pdev->dev,
6103 "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); 6118 "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf);
6104 if (test_bit(__IGB_DOWN, &adapter->state)) { 6119 if (test_bit(__IGB_DOWN, &adapter->state)) {
@@ -6126,6 +6141,7 @@ static int igb_disable_port_vlan(struct igb_adapter *adapter, int vf)
6126 6141
6127 adapter->vf_data[vf].pf_vlan = 0; 6142 adapter->vf_data[vf].pf_vlan = 0;
6128 adapter->vf_data[vf].pf_qos = 0; 6143 adapter->vf_data[vf].pf_qos = 0;
6144 igb_set_vf_vlan_strip(adapter, vf, false);
6129 6145
6130 return 0; 6146 return 0;
6131} 6147}
@@ -6146,6 +6162,7 @@ static int igb_set_vf_vlan_msg(struct igb_adapter *adapter, u32 *msgbuf, u32 vf)
6146{ 6162{
6147 int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; 6163 int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT;
6148 int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); 6164 int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK);
6165 int ret;
6149 6166
6150 if (adapter->vf_data[vf].pf_vlan) 6167 if (adapter->vf_data[vf].pf_vlan)
6151 return -1; 6168 return -1;
@@ -6154,7 +6171,10 @@ static int igb_set_vf_vlan_msg(struct igb_adapter *adapter, u32 *msgbuf, u32 vf)
6154 if (!vid && !add) 6171 if (!vid && !add)
6155 return 0; 6172 return 0;
6156 6173
6157 return igb_set_vf_vlan(adapter, vid, !!add, vf); 6174 ret = igb_set_vf_vlan(adapter, vid, !!add, vf);
6175 if (!ret)
6176 igb_set_vf_vlan_strip(adapter, vf, !!vid);
6177 return ret;
6158} 6178}
6159 6179
6160static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) 6180static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf)
@@ -6171,6 +6191,7 @@ static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf)
6171 igb_set_vmvir(adapter, vf_data->pf_vlan | 6191 igb_set_vmvir(adapter, vf_data->pf_vlan |
6172 (vf_data->pf_qos << VLAN_PRIO_SHIFT), vf); 6192 (vf_data->pf_qos << VLAN_PRIO_SHIFT), vf);
6173 igb_set_vmolr(adapter, vf, !vf_data->pf_vlan); 6193 igb_set_vmolr(adapter, vf, !vf_data->pf_vlan);
6194 igb_set_vf_vlan_strip(adapter, vf, !!(vf_data->pf_vlan));
6174 6195
6175 /* reset multicast table array for vf */ 6196 /* reset multicast table array for vf */
6176 adapter->vf_data[vf].num_vf_mc_hashes = 0; 6197 adapter->vf_data[vf].num_vf_mc_hashes = 0;
@@ -7323,6 +7344,8 @@ static void igb_vlan_mode(struct net_device *netdev, netdev_features_t features)
7323 ctrl &= ~E1000_CTRL_VME; 7344 ctrl &= ~E1000_CTRL_VME;
7324 wr32(E1000_CTRL, ctrl); 7345 wr32(E1000_CTRL, ctrl);
7325 } 7346 }
7347
7348 igb_set_vf_vlan_strip(adapter, adapter->vfs_allocated_count, enable);
7326} 7349}
7327 7350
7328static int igb_vlan_rx_add_vid(struct net_device *netdev, 7351static int igb_vlan_rx_add_vid(struct net_device *netdev,