diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2011-08-26 03:47:11 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-10-13 01:46:40 -0400 |
commit | 8be10e9130a75c49ddcffdfca74b19b1c3169230 (patch) | |
tree | ac49a3aad46de7dd4c424751cbe5eb0782047853 /drivers/net/ethernet/intel | |
parent | 9ab64ba3c74540cfb8716232834df486bcc6120d (diff) |
igb: Add workaround for byte swapped VLAN on i350 local traffic
On i350 when traffic is looped back from a VF to the PF the value is byte
swapped from the normal format. In order to address this we need to add a
flag indicating that the ring will need to byte swap the loopback packets
prior to processing them.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.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')
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_defines.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 29 |
3 files changed, 25 insertions, 6 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index 68558be6f9e7..f5fc5725ea94 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h | |||
@@ -85,6 +85,7 @@ | |||
85 | #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ | 85 | #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ |
86 | #define E1000_RXD_STAT_TS 0x10000 /* Pkt was time stamped */ | 86 | #define E1000_RXD_STAT_TS 0x10000 /* Pkt was time stamped */ |
87 | 87 | ||
88 | #define E1000_RXDEXT_STATERR_LB 0x00040000 | ||
88 | #define E1000_RXDEXT_STATERR_CE 0x01000000 | 89 | #define E1000_RXDEXT_STATERR_CE 0x01000000 |
89 | #define E1000_RXDEXT_STATERR_SE 0x02000000 | 90 | #define E1000_RXDEXT_STATERR_SE 0x02000000 |
90 | #define E1000_RXDEXT_STATERR_SEQ 0x04000000 | 91 | #define E1000_RXDEXT_STATERR_SEQ 0x04000000 |
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 4e665a9b4763..4c500a76972e 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h | |||
@@ -245,6 +245,7 @@ struct igb_ring { | |||
245 | 245 | ||
246 | enum e1000_ring_flags_t { | 246 | enum e1000_ring_flags_t { |
247 | IGB_RING_FLAG_RX_SCTP_CSUM, | 247 | IGB_RING_FLAG_RX_SCTP_CSUM, |
248 | IGB_RING_FLAG_RX_LB_VLAN_BSWAP, | ||
248 | IGB_RING_FLAG_TX_CTX_IDX, | 249 | IGB_RING_FLAG_TX_CTX_IDX, |
249 | IGB_RING_FLAG_TX_DETECT_HANG | 250 | IGB_RING_FLAG_TX_DETECT_HANG |
250 | }; | 251 | }; |
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 9e7930686cd0..582432f24166 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -735,6 +735,11 @@ static int igb_alloc_queues(struct igb_adapter *adapter) | |||
735 | /* set flag indicating ring supports SCTP checksum offload */ | 735 | /* set flag indicating ring supports SCTP checksum offload */ |
736 | if (adapter->hw.mac.type >= e1000_82576) | 736 | if (adapter->hw.mac.type >= e1000_82576) |
737 | set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); | 737 | set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); |
738 | |||
739 | /* On i350, loopback VLAN packets have the tag byte-swapped. */ | ||
740 | if (adapter->hw.mac.type == e1000_i350) | ||
741 | set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); | ||
742 | |||
738 | adapter->rx_ring[i] = ring; | 743 | adapter->rx_ring[i] = ring; |
739 | } | 744 | } |
740 | /* Restore the adapter's original node */ | 745 | /* Restore the adapter's original node */ |
@@ -5864,6 +5869,23 @@ static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, | |||
5864 | 5869 | ||
5865 | igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); | 5870 | igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); |
5866 | } | 5871 | } |
5872 | |||
5873 | static void igb_rx_vlan(struct igb_ring *ring, | ||
5874 | union e1000_adv_rx_desc *rx_desc, | ||
5875 | struct sk_buff *skb) | ||
5876 | { | ||
5877 | if (igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { | ||
5878 | u16 vid; | ||
5879 | if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) && | ||
5880 | test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags)) | ||
5881 | vid = be16_to_cpu(rx_desc->wb.upper.vlan); | ||
5882 | else | ||
5883 | vid = le16_to_cpu(rx_desc->wb.upper.vlan); | ||
5884 | |||
5885 | __vlan_hwaccel_put_tag(skb, vid); | ||
5886 | } | ||
5887 | } | ||
5888 | |||
5867 | static inline u16 igb_get_hlen(union e1000_adv_rx_desc *rx_desc) | 5889 | static inline u16 igb_get_hlen(union e1000_adv_rx_desc *rx_desc) |
5868 | { | 5890 | { |
5869 | /* HW will not DMA in data larger than the given buffer, even if it | 5891 | /* HW will not DMA in data larger than the given buffer, even if it |
@@ -5960,12 +5982,7 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget) | |||
5960 | igb_rx_hwtstamp(q_vector, rx_desc, skb); | 5982 | igb_rx_hwtstamp(q_vector, rx_desc, skb); |
5961 | igb_rx_hash(rx_ring, rx_desc, skb); | 5983 | igb_rx_hash(rx_ring, rx_desc, skb); |
5962 | igb_rx_checksum(rx_ring, rx_desc, skb); | 5984 | igb_rx_checksum(rx_ring, rx_desc, skb); |
5963 | 5985 | igb_rx_vlan(rx_ring, rx_desc, skb); | |
5964 | if (igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { | ||
5965 | u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan); | ||
5966 | |||
5967 | __vlan_hwaccel_put_tag(skb, vid); | ||
5968 | } | ||
5969 | 5986 | ||
5970 | total_bytes += skb->len; | 5987 | total_bytes += skb->len; |
5971 | total_packets++; | 5988 | total_packets++; |