aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2012-02-11 10:39:25 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-02-24 04:23:06 -0500
commit0184039a4b6727d6efd545919c773ef141090ae7 (patch)
treea6e7d4acc061300c694dc2f6155eadbf88136268
parent36eabda3d094dae30a74350c6289c163349b744d (diff)
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>
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h1
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c41
-rw-r--r--drivers/net/ethernet/intel/e1000e/param.c5
3 files changed, 39 insertions, 8 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 45e5ae8a9fb7..04a21fcb827e 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -461,6 +461,7 @@ struct e1000_info {
461#define FLAG2_CHECK_PHY_HANG (1 << 9) 461#define FLAG2_CHECK_PHY_HANG (1 << 9)
462#define FLAG2_NO_DISABLE_RX (1 << 10) 462#define FLAG2_NO_DISABLE_RX (1 << 10)
463#define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11) 463#define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11)
464#define FLAG2_DFLT_CRC_STRIPPING (1 << 12)
464 465
465#define E1000_RX_DESC_PS(R, i) \ 466#define E1000_RX_DESC_PS(R, i) \
466 (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) 467 (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index c079b9b0810d..30c8c15d0396 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -933,8 +933,16 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
933 } 933 }
934 934
935 /* adjust length to remove Ethernet CRC */ 935 /* adjust length to remove Ethernet CRC */
936 if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) 936 if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
937 length -= 4; 937 /* If configured to store CRC, don't subtract FCS,
938 * but keep the FCS bytes out of the total_rx_bytes
939 * counter
940 */
941 if (netdev->features & NETIF_F_RXFCS)
942 total_rx_bytes -= 4;
943 else
944 length -= 4;
945 }
938 946
939 total_rx_bytes += length; 947 total_rx_bytes += length;
940 total_rx_packets++; 948 total_rx_packets++;
@@ -1301,8 +1309,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
1301 DMA_FROM_DEVICE); 1309 DMA_FROM_DEVICE);
1302 1310
1303 /* remove the CRC */ 1311 /* remove the CRC */
1304 if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) 1312 if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
1305 l1 -= 4; 1313 if (!(netdev->features & NETIF_F_RXFCS))
1314 l1 -= 4;
1315 }
1306 1316
1307 skb_put(skb, l1); 1317 skb_put(skb, l1);
1308 goto copydone; 1318 goto copydone;
@@ -1328,8 +1338,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
1328 /* strip the ethernet crc, problem is we're using pages now so 1338 /* strip the ethernet crc, problem is we're using pages now so
1329 * this whole operation can get a little cpu intensive 1339 * this whole operation can get a little cpu intensive
1330 */ 1340 */
1331 if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) 1341 if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
1332 pskb_trim(skb, skb->len - 4); 1342 if (!(netdev->features & NETIF_F_RXFCS))
1343 pskb_trim(skb, skb->len - 4);
1344 }
1333 1345
1334copydone: 1346copydone:
1335 total_rx_bytes += skb->len; 1347 total_rx_bytes += skb->len;
@@ -5982,7 +5994,7 @@ static int e1000_set_features(struct net_device *netdev,
5982 adapter->flags |= FLAG_TSO_FORCE; 5994 adapter->flags |= FLAG_TSO_FORCE;
5983 5995
5984 if (!(changed & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | 5996 if (!(changed & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX |
5985 NETIF_F_RXCSUM | NETIF_F_RXHASH))) 5997 NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_RXFCS)))
5986 return 0; 5998 return 0;
5987 5999
5988 /* 6000 /*
@@ -5996,6 +6008,20 @@ static int e1000_set_features(struct net_device *netdev,
5996 return -EINVAL; 6008 return -EINVAL;
5997 } 6009 }
5998 6010
6011 if (changed & NETIF_F_RXFCS) {
6012 if (features & NETIF_F_RXFCS) {
6013 adapter->flags2 &= ~FLAG2_CRC_STRIPPING;
6014 } else {
6015 /* We need to take it back to defaults, which might mean
6016 * stripping is still disabled at the adapter level.
6017 */
6018 if (adapter->flags2 & FLAG2_DFLT_CRC_STRIPPING)
6019 adapter->flags2 |= FLAG2_CRC_STRIPPING;
6020 else
6021 adapter->flags2 &= ~FLAG2_CRC_STRIPPING;
6022 }
6023 }
6024
5999 netdev->features = features; 6025 netdev->features = features;
6000 6026
6001 if (netif_running(netdev)) 6027 if (netif_running(netdev))
@@ -6194,6 +6220,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
6194 6220
6195 /* Set user-changeable features (subset of all device features) */ 6221 /* Set user-changeable features (subset of all device features) */
6196 netdev->hw_features = netdev->features; 6222 netdev->hw_features = netdev->features;
6223 netdev->hw_features |= NETIF_F_RXFCS;
6197 6224
6198 if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) 6225 if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
6199 netdev->features |= NETIF_F_HW_VLAN_FILTER; 6226 netdev->features |= NETIF_F_HW_VLAN_FILTER;
diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c
index 9c6a56d804a4..ff796e42c3eb 100644
--- a/drivers/net/ethernet/intel/e1000e/param.c
+++ b/drivers/net/ethernet/intel/e1000e/param.c
@@ -463,10 +463,13 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
463 if (num_CrcStripping > bd) { 463 if (num_CrcStripping > bd) {
464 unsigned int crc_stripping = CrcStripping[bd]; 464 unsigned int crc_stripping = CrcStripping[bd];
465 e1000_validate_option(&crc_stripping, &opt, adapter); 465 e1000_validate_option(&crc_stripping, &opt, adapter);
466 if (crc_stripping == OPTION_ENABLED) 466 if (crc_stripping == OPTION_ENABLED) {
467 adapter->flags2 |= FLAG2_CRC_STRIPPING; 467 adapter->flags2 |= FLAG2_CRC_STRIPPING;
468 adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
469 }
468 } else { 470 } else {
469 adapter->flags2 |= FLAG2_CRC_STRIPPING; 471 adapter->flags2 |= FLAG2_CRC_STRIPPING;
472 adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
470 } 473 }
471 } 474 }
472 { /* Kumeran Lock Loss Workaround */ 475 { /* Kumeran Lock Loss Workaround */