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>
This commit is contained in:
parent
03f52a0a55
commit
2c1a101965
3 changed files with 15 additions and 3 deletions
|
@ -46,6 +46,7 @@
|
||||||
#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
|
#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
|
||||||
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
|
#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_CE 0x01000000
|
||||||
#define E1000_RXDEXT_STATERR_SE 0x02000000
|
#define E1000_RXDEXT_STATERR_SE 0x02000000
|
||||||
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
|
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
|
||||||
|
|
|
@ -295,7 +295,7 @@ struct igbvf_info {
|
||||||
|
|
||||||
/* hardware capability, feature, and workaround flags */
|
/* hardware capability, feature, and workaround flags */
|
||||||
#define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0)
|
#define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0)
|
||||||
|
#define IGBVF_FLAG_RX_LB_VLAN_BSWAP (1 << 1)
|
||||||
#define IGBVF_RX_DESC_ADV(R, i) \
|
#define IGBVF_RX_DESC_ADV(R, i) \
|
||||||
(&((((R).desc))[i].rx_desc))
|
(&((((R).desc))[i].rx_desc))
|
||||||
#define IGBVF_TX_DESC_ADV(R, i) \
|
#define IGBVF_TX_DESC_ADV(R, i) \
|
||||||
|
|
|
@ -107,12 +107,19 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
u32 status, u16 vlan)
|
u32 status, u16 vlan)
|
||||||
{
|
{
|
||||||
|
u16 vid;
|
||||||
|
|
||||||
if (status & E1000_RXD_STAT_VP) {
|
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))
|
if (test_bit(vid, adapter->active_vlans))
|
||||||
__vlan_hwaccel_put_tag(skb, vid);
|
__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,
|
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 */
|
/* reset the hardware with the new settings */
|
||||||
igbvf_reset(adapter);
|
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");
|
strcpy(netdev->name, "eth%d");
|
||||||
err = register_netdev(netdev);
|
err = register_netdev(netdev);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
Loading…
Add table
Reference in a new issue