Skip to content

Commit

Permalink
e1000e: Support RXFCS feature flag.
Browse files Browse the repository at this point in the history
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 <[email protected]>
Tested-by: Aaron Brown <[email protected]>
Signed-off-by: Jeff Kirsher <[email protected]>
  • Loading branch information
greearb authored and Jeff Kirsher committed Feb 24, 2012
1 parent 36eabda commit 0184039
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 8 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/e1000e/e1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand Down
41 changes: 34 additions & 7 deletions drivers/net/ethernet/intel/e1000e/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;

/*
Expand All @@ -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))
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion drivers/net/ethernet/intel/e1000e/param.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 0184039

Please sign in to comment.