e1000e: Support RXFCS feature flag.

This enables enabling/disabling reception of the Ethernet
FCS.  This can be useful when sniffing packets.

For e1000e, enabling RXFCS can change the default
behaviour for how the NIC handles CRC.  Disabling RXFCS
will take the NIC back to defaults, which can be configured
as part of the module options.

Signed-off-by: Ben Greear <greearb@candelatech.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
Ben Greear 2012-02-11 15:39:25 +00:00 committed by Jeff Kirsher
parent 36eabda3d0
commit 0184039a4b
3 changed files with 39 additions and 8 deletions

View File

@ -461,6 +461,7 @@ struct e1000_info {
#define FLAG2_CHECK_PHY_HANG (1 << 9)
#define FLAG2_NO_DISABLE_RX (1 << 10)
#define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11)
#define FLAG2_DFLT_CRC_STRIPPING (1 << 12)
#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))

View File

@ -933,8 +933,16 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
}
/* adjust length to remove Ethernet CRC */
if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
length -= 4;
if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
/* If configured to store CRC, don't subtract FCS,
* but keep the FCS bytes out of the total_rx_bytes
* counter
*/
if (netdev->features & NETIF_F_RXFCS)
total_rx_bytes -= 4;
else
length -= 4;
}
total_rx_bytes += length;
total_rx_packets++;
@ -1301,8 +1309,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
DMA_FROM_DEVICE);
/* remove the CRC */
if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
l1 -= 4;
if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
if (!(netdev->features & NETIF_F_RXFCS))
l1 -= 4;
}
skb_put(skb, l1);
goto copydone;
@ -1328,8 +1338,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
/* strip the ethernet crc, problem is we're using pages now so
* this whole operation can get a little cpu intensive
*/
if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
pskb_trim(skb, skb->len - 4);
if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
if (!(netdev->features & NETIF_F_RXFCS))
pskb_trim(skb, skb->len - 4);
}
copydone:
total_rx_bytes += skb->len;
@ -5982,7 +5994,7 @@ static int e1000_set_features(struct net_device *netdev,
adapter->flags |= FLAG_TSO_FORCE;
if (!(changed & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX |
NETIF_F_RXCSUM | NETIF_F_RXHASH)))
NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_RXFCS)))
return 0;
/*
@ -5996,6 +6008,20 @@ static int e1000_set_features(struct net_device *netdev,
return -EINVAL;
}
if (changed & NETIF_F_RXFCS) {
if (features & NETIF_F_RXFCS) {
adapter->flags2 &= ~FLAG2_CRC_STRIPPING;
} else {
/* We need to take it back to defaults, which might mean
* stripping is still disabled at the adapter level.
*/
if (adapter->flags2 & FLAG2_DFLT_CRC_STRIPPING)
adapter->flags2 |= FLAG2_CRC_STRIPPING;
else
adapter->flags2 &= ~FLAG2_CRC_STRIPPING;
}
}
netdev->features = features;
if (netif_running(netdev))
@ -6194,6 +6220,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
/* Set user-changeable features (subset of all device features) */
netdev->hw_features = netdev->features;
netdev->hw_features |= NETIF_F_RXFCS;
if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
netdev->features |= NETIF_F_HW_VLAN_FILTER;

View File

@ -463,10 +463,13 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
if (num_CrcStripping > bd) {
unsigned int crc_stripping = CrcStripping[bd];
e1000_validate_option(&crc_stripping, &opt, adapter);
if (crc_stripping == OPTION_ENABLED)
if (crc_stripping == OPTION_ENABLED) {
adapter->flags2 |= FLAG2_CRC_STRIPPING;
adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
}
} else {
adapter->flags2 |= FLAG2_CRC_STRIPPING;
adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
}
}
{ /* Kumeran Lock Loss Workaround */