diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2009-04-27 18:36:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-04-28 04:53:14 -0400 |
commit | b9473560c6d882e0fbd3a8817e906c847b11c722 (patch) | |
tree | e183dd56fc93e201c92e596b5603e6ebb99776a1 /drivers/net/igb/igb_main.c | |
parent | 8dc92f7e2ecfd93f5c57da78594a7a5482e2c15e (diff) |
igb: Enable SCTP checksum offloading
Originally from: Vlad Yasevich <vladislav.yasevich@hp.com>
This patch, both the driver portion and the sctp code was
modified by Jesse Brandeburg and is
Copyright(c) 2009 Intel Corporation.
Thanks go to Vlad for starting this work.
Intel 82576 chipset supports SCTP checksum offloading. This
patch enables this functionality in the driver. A new NETIF
feature is introduced for SCTP checksum offload. If the driver
supports CRC32c checksum, it can set this feature flag. The
hardware can offload both transmit and receive.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/igb/igb_main.c')
-rw-r--r-- | drivers/net/igb/igb_main.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index f7f861215242..bca7e9f76be4 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -1345,6 +1345,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
1345 | if (pci_using_dac) | 1345 | if (pci_using_dac) |
1346 | netdev->features |= NETIF_F_HIGHDMA; | 1346 | netdev->features |= NETIF_F_HIGHDMA; |
1347 | 1347 | ||
1348 | if (adapter->hw.mac.type == e1000_82576) | ||
1349 | netdev->features |= NETIF_F_SCTP_CSUM; | ||
1350 | |||
1348 | adapter->en_mng_pt = igb_enable_mng_pass_thru(&adapter->hw); | 1351 | adapter->en_mng_pt = igb_enable_mng_pass_thru(&adapter->hw); |
1349 | 1352 | ||
1350 | /* before reading the NVM, reset the controller to put the device in a | 1353 | /* before reading the NVM, reset the controller to put the device in a |
@@ -2249,6 +2252,10 @@ static void igb_configure_rx(struct igb_adapter *adapter) | |||
2249 | /* Don't need to set TUOFL or IPOFL, they default to 1 */ | 2252 | /* Don't need to set TUOFL or IPOFL, they default to 1 */ |
2250 | if (!adapter->rx_csum) | 2253 | if (!adapter->rx_csum) |
2251 | rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL); | 2254 | rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL); |
2255 | else if (adapter->hw.mac.type == e1000_82576) | ||
2256 | /* Enable Receive Checksum Offload for SCTP */ | ||
2257 | rxcsum |= E1000_RXCSUM_CRCOFL; | ||
2258 | |||
2252 | wr32(E1000_RXCSUM, rxcsum); | 2259 | wr32(E1000_RXCSUM, rxcsum); |
2253 | 2260 | ||
2254 | /* Set the default pool for the PF's first queue */ | 2261 | /* Set the default pool for the PF's first queue */ |
@@ -3064,11 +3071,15 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter, | |||
3064 | tu_cmd |= E1000_ADVTXD_TUCMD_IPV4; | 3071 | tu_cmd |= E1000_ADVTXD_TUCMD_IPV4; |
3065 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) | 3072 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) |
3066 | tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; | 3073 | tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; |
3074 | else if (ip_hdr(skb)->protocol == IPPROTO_SCTP) | ||
3075 | tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP; | ||
3067 | break; | 3076 | break; |
3068 | case cpu_to_be16(ETH_P_IPV6): | 3077 | case cpu_to_be16(ETH_P_IPV6): |
3069 | /* XXX what about other V6 headers?? */ | 3078 | /* XXX what about other V6 headers?? */ |
3070 | if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) | 3079 | if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) |
3071 | tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; | 3080 | tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; |
3081 | else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP) | ||
3082 | tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP; | ||
3072 | break; | 3083 | break; |
3073 | default: | 3084 | default: |
3074 | if (unlikely(net_ratelimit())) | 3085 | if (unlikely(net_ratelimit())) |
@@ -4449,14 +4460,22 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter, | |||
4449 | /* TCP/UDP checksum error bit is set */ | 4460 | /* TCP/UDP checksum error bit is set */ |
4450 | if (status_err & | 4461 | if (status_err & |
4451 | (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) { | 4462 | (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) { |
4463 | /* | ||
4464 | * work around errata with sctp packets where the TCPE aka | ||
4465 | * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) | ||
4466 | * packets, (aka let the stack check the crc32c) | ||
4467 | */ | ||
4468 | if (!((adapter->hw.mac.type == e1000_82576) && | ||
4469 | (skb->len == 60))) | ||
4470 | adapter->hw_csum_err++; | ||
4452 | /* let the stack verify checksum errors */ | 4471 | /* let the stack verify checksum errors */ |
4453 | adapter->hw_csum_err++; | ||
4454 | return; | 4472 | return; |
4455 | } | 4473 | } |
4456 | /* It must be a TCP or UDP packet with a valid checksum */ | 4474 | /* It must be a TCP or UDP packet with a valid checksum */ |
4457 | if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) | 4475 | if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) |
4458 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 4476 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
4459 | 4477 | ||
4478 | dev_dbg(&adapter->pdev->dev, "cksum success: bits %08X\n", status_err); | ||
4460 | adapter->hw_csum_good++; | 4479 | adapter->hw_csum_good++; |
4461 | } | 4480 | } |
4462 | 4481 | ||