igbvf: work around i350 erratum
authorMitch A Williams <mitch.a.williams@intel.com>
Sat, 17 Nov 2012 07:10:16 +0000 (07:10 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Wed, 28 Nov 2012 11:57:23 +0000 (03:57 -0800)
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>
drivers/net/ethernet/intel/igbvf/defines.h
drivers/net/ethernet/intel/igbvf/igbvf.h
drivers/net/ethernet/intel/igbvf/netdev.c

index 3e18045d8f89f69d5e374d246f49a91320399a0c..d9fa999b16856e41f79a750c92d94223dfaa6d98 100644 (file)
@@ -46,6 +46,7 @@
 #define E1000_RXD_ERR_SE        0x02    /* Symbol Error */
 #define E1000_RXD_SPC_VLAN_MASK 0x0FFF  /* VLAN ID is in lower 12 bits */
 
+#define E1000_RXDEXT_STATERR_LB    0x00040000
 #define E1000_RXDEXT_STATERR_CE    0x01000000
 #define E1000_RXDEXT_STATERR_SE    0x02000000
 #define E1000_RXDEXT_STATERR_SEQ   0x04000000
index a895e2f7b34d99b4afa870cfaab801b1061ab9db..fdca7b6727764fb574ffc88a85f47ee81fdc5f23 100644 (file)
@@ -295,7 +295,7 @@ struct igbvf_info {
 
 /* hardware capability, feature, and workaround flags */
 #define IGBVF_FLAG_RX_CSUM_DISABLED             (1 << 0)
-
+#define IGBVF_FLAG_RX_LB_VLAN_BSWAP            (1 << 1)
 #define IGBVF_RX_DESC_ADV(R, i)     \
        (&((((R).desc))[i].rx_desc))
 #define IGBVF_TX_DESC_ADV(R, i)     \
index 4051ec404613c4788485f58125f9d76888a1dc69..b44b9d3d07f47c5478efe9b811db22cda073ad2c 100644 (file)
@@ -107,12 +107,19 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
                               struct sk_buff *skb,
                               u32 status, u16 vlan)
 {
+       u16 vid;
+
        if (status & E1000_RXD_STAT_VP) {
-               u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+               if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) &&
+                   (status & E1000_RXDEXT_STATERR_LB))
+                       vid = be16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+               else
+                       vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
                if (test_bit(vid, adapter->active_vlans))
                        __vlan_hwaccel_put_tag(skb, vid);
        }
-       netif_receive_skb(skb);
+
+       napi_gro_receive(&adapter->rx_ring->napi, skb);
 }
 
 static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
@@ -2767,6 +2774,10 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
        /* reset the hardware with the new settings */
        igbvf_reset(adapter);
 
+       /* set hardware-specific flags */
+       if (adapter->hw.mac.type == e1000_vfadapt_i350)
+               adapter->flags |= IGBVF_FLAG_RX_LB_VLAN_BSWAP;
+
        strcpy(netdev->name, "eth%d");
        err = register_netdev(netdev);
        if (err)