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:
Родитель
36eabda3d0
Коммит
0184039a4b
|
@ -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]))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче