aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/igb
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2009-04-27 18:36:13 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-28 04:53:14 -0400
commitb9473560c6d882e0fbd3a8817e906c847b11c722 (patch)
treee183dd56fc93e201c92e596b5603e6ebb99776a1 /drivers/net/igb
parent8dc92f7e2ecfd93f5c57da78594a7a5482e2c15e (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')
-rw-r--r--drivers/net/igb/e1000_82575.h1
-rw-r--r--drivers/net/igb/e1000_defines.h1
-rw-r--r--drivers/net/igb/igb_ethtool.c12
-rw-r--r--drivers/net/igb/igb_main.c21
4 files changed, 31 insertions, 4 deletions
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index eaf977050368..0f16abab2565 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -130,6 +130,7 @@ struct e1000_adv_tx_context_desc {
130#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ 130#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
131#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ 131#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
132#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ 132#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
133#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
133/* IPSec Encrypt Enable for ESP */ 134/* IPSec Encrypt Enable for ESP */
134#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ 135#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
135#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ 136#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index 65acbbaca2d5..3bda3db73f1f 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -291,6 +291,7 @@
291/* Receive Checksum Control */ 291/* Receive Checksum Control */
292#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ 292#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */
293#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ 293#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
294#define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
294#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ 295#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
295 296
296/* Header split receive */ 297/* Header split receive */
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 27eae49e79c2..b1367ce6586e 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -293,10 +293,16 @@ static u32 igb_get_tx_csum(struct net_device *netdev)
293 293
294static int igb_set_tx_csum(struct net_device *netdev, u32 data) 294static int igb_set_tx_csum(struct net_device *netdev, u32 data)
295{ 295{
296 if (data) 296 struct igb_adapter *adapter = netdev_priv(netdev);
297
298 if (data) {
297 netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); 299 netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
298 else 300 if (adapter->hw.mac.type == e1000_82576)
299 netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); 301 netdev->features |= NETIF_F_SCTP_CSUM;
302 } else {
303 netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
304 NETIF_F_SCTP_CSUM);
305 }
300 306
301 return 0; 307 return 0;
302} 308}
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