diff options
author | Mitch A Williams <mitch.a.williams@intel.com> | 2012-11-17 02:10:16 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-11-28 06:57:23 -0500 |
commit | 2c1a10196511a2c1af612a59aa1e5385afca0533 (patch) | |
tree | 543cfd7a73f6367e204220dc590f2b339696e663 /drivers/net/ethernet/intel/igbvf | |
parent | 03f52a0a554210d5049eeed9f1bb29047dc807cb (diff) |
igbvf: work around i350 erratum
On i350 VF devices, VLAN tags will be byte-swapped in the receive
descriptor only when received packets are looped back from other
VFs. Check for this condition and swab the tag if needed.
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/igbvf')
-rw-r--r-- | drivers/net/ethernet/intel/igbvf/defines.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igbvf/igbvf.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igbvf/netdev.c | 15 |
3 files changed, 15 insertions, 3 deletions
diff --git a/drivers/net/ethernet/intel/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h index 3e18045d8f89..d9fa999b1685 100644 --- a/drivers/net/ethernet/intel/igbvf/defines.h +++ b/drivers/net/ethernet/intel/igbvf/defines.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ | 46 | #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ |
47 | #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ | 47 | #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ |
48 | 48 | ||
49 | #define E1000_RXDEXT_STATERR_LB 0x00040000 | ||
49 | #define E1000_RXDEXT_STATERR_CE 0x01000000 | 50 | #define E1000_RXDEXT_STATERR_CE 0x01000000 |
50 | #define E1000_RXDEXT_STATERR_SE 0x02000000 | 51 | #define E1000_RXDEXT_STATERR_SE 0x02000000 |
51 | #define E1000_RXDEXT_STATERR_SEQ 0x04000000 | 52 | #define E1000_RXDEXT_STATERR_SEQ 0x04000000 |
diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h index a895e2f7b34d..fdca7b672776 100644 --- a/drivers/net/ethernet/intel/igbvf/igbvf.h +++ b/drivers/net/ethernet/intel/igbvf/igbvf.h | |||
@@ -295,7 +295,7 @@ struct igbvf_info { | |||
295 | 295 | ||
296 | /* hardware capability, feature, and workaround flags */ | 296 | /* hardware capability, feature, and workaround flags */ |
297 | #define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0) | 297 | #define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0) |
298 | 298 | #define IGBVF_FLAG_RX_LB_VLAN_BSWAP (1 << 1) | |
299 | #define IGBVF_RX_DESC_ADV(R, i) \ | 299 | #define IGBVF_RX_DESC_ADV(R, i) \ |
300 | (&((((R).desc))[i].rx_desc)) | 300 | (&((((R).desc))[i].rx_desc)) |
301 | #define IGBVF_TX_DESC_ADV(R, i) \ | 301 | #define IGBVF_TX_DESC_ADV(R, i) \ |
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 4051ec404613..b44b9d3d07f4 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c | |||
@@ -107,12 +107,19 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter, | |||
107 | struct sk_buff *skb, | 107 | struct sk_buff *skb, |
108 | u32 status, u16 vlan) | 108 | u32 status, u16 vlan) |
109 | { | 109 | { |
110 | u16 vid; | ||
111 | |||
110 | if (status & E1000_RXD_STAT_VP) { | 112 | if (status & E1000_RXD_STAT_VP) { |
111 | u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; | 113 | if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) && |
114 | (status & E1000_RXDEXT_STATERR_LB)) | ||
115 | vid = be16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; | ||
116 | else | ||
117 | vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; | ||
112 | if (test_bit(vid, adapter->active_vlans)) | 118 | if (test_bit(vid, adapter->active_vlans)) |
113 | __vlan_hwaccel_put_tag(skb, vid); | 119 | __vlan_hwaccel_put_tag(skb, vid); |
114 | } | 120 | } |
115 | netif_receive_skb(skb); | 121 | |
122 | napi_gro_receive(&adapter->rx_ring->napi, skb); | ||
116 | } | 123 | } |
117 | 124 | ||
118 | static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter, | 125 | static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter, |
@@ -2767,6 +2774,10 @@ static int __devinit igbvf_probe(struct pci_dev *pdev, | |||
2767 | /* reset the hardware with the new settings */ | 2774 | /* reset the hardware with the new settings */ |
2768 | igbvf_reset(adapter); | 2775 | igbvf_reset(adapter); |
2769 | 2776 | ||
2777 | /* set hardware-specific flags */ | ||
2778 | if (adapter->hw.mac.type == e1000_vfadapt_i350) | ||
2779 | adapter->flags |= IGBVF_FLAG_RX_LB_VLAN_BSWAP; | ||
2780 | |||
2770 | strcpy(netdev->name, "eth%d"); | 2781 | strcpy(netdev->name, "eth%d"); |
2771 | err = register_netdev(netdev); | 2782 | err = register_netdev(netdev); |
2772 | if (err) | 2783 | if (err) |