diff options
| author | Michael Chan <mchan@broadcom.com> | 2007-05-03 16:22:28 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2007-05-03 16:22:28 -0400 |
| commit | 4666f87a82cf74b63737a7f55a8b3b057a7b83df (patch) | |
| tree | 67cc362f70fa70bb8218e91e46e82d3bd5f7b57e | |
| parent | 874bb672fdd939aec37ad3a06b50be4ff8b4feac (diff) | |
[BNX2]: Add ipv6 TSO and checksum for 5709.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/bnx2.c | 91 | ||||
| -rw-r--r-- | drivers/net/bnx2.h | 4 |
2 files changed, 67 insertions, 28 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 89681b30b890..01977de759d8 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
| @@ -4537,35 +4537,49 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 4537 | u32 tcp_opt_len, ip_tcp_len; | 4537 | u32 tcp_opt_len, ip_tcp_len; |
| 4538 | struct iphdr *iph; | 4538 | struct iphdr *iph; |
| 4539 | 4539 | ||
| 4540 | if (skb_header_cloned(skb) && | ||
| 4541 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { | ||
| 4542 | dev_kfree_skb(skb); | ||
| 4543 | return NETDEV_TX_OK; | ||
| 4544 | } | ||
| 4545 | |||
| 4546 | vlan_tag_flags |= TX_BD_FLAGS_SW_LSO; | 4540 | vlan_tag_flags |= TX_BD_FLAGS_SW_LSO; |
| 4547 | 4541 | ||
| 4548 | tcp_opt_len = 0; | 4542 | tcp_opt_len = tcp_optlen(skb); |
| 4549 | if (tcp_hdr(skb)->doff > 5) | 4543 | |
| 4550 | tcp_opt_len = tcp_optlen(skb); | 4544 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { |
| 4545 | u32 tcp_off = skb_transport_offset(skb) - | ||
| 4546 | sizeof(struct ipv6hdr) - ETH_HLEN; | ||
| 4551 | 4547 | ||
| 4552 | ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr); | 4548 | vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) | |
| 4549 | TX_BD_FLAGS_SW_FLAGS; | ||
| 4550 | if (likely(tcp_off == 0)) | ||
| 4551 | vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK; | ||
| 4552 | else { | ||
| 4553 | tcp_off >>= 3; | ||
| 4554 | vlan_tag_flags |= ((tcp_off & 0x3) << | ||
| 4555 | TX_BD_FLAGS_TCP6_OFF0_SHL) | | ||
| 4556 | ((tcp_off & 0x10) << | ||
| 4557 | TX_BD_FLAGS_TCP6_OFF4_SHL); | ||
| 4558 | mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL; | ||
| 4559 | } | ||
| 4560 | } else { | ||
| 4561 | if (skb_header_cloned(skb) && | ||
| 4562 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { | ||
| 4563 | dev_kfree_skb(skb); | ||
| 4564 | return NETDEV_TX_OK; | ||
| 4565 | } | ||
| 4553 | 4566 | ||
| 4554 | iph = ip_hdr(skb); | 4567 | ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr); |
| 4555 | iph->check = 0; | 4568 | |
| 4556 | iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); | 4569 | iph = ip_hdr(skb); |
| 4557 | tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, | 4570 | iph->check = 0; |
| 4558 | iph->daddr, 0, | 4571 | iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); |
| 4559 | IPPROTO_TCP, 0); | 4572 | tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, |
| 4560 | if (tcp_opt_len || (iph->ihl > 5)) { | 4573 | iph->daddr, 0, |
| 4561 | vlan_tag_flags |= ((iph->ihl - 5) + | 4574 | IPPROTO_TCP, |
| 4562 | (tcp_opt_len >> 2)) << 8; | 4575 | 0); |
| 4576 | if (tcp_opt_len || (iph->ihl > 5)) { | ||
| 4577 | vlan_tag_flags |= ((iph->ihl - 5) + | ||
| 4578 | (tcp_opt_len >> 2)) << 8; | ||
| 4579 | } | ||
| 4563 | } | 4580 | } |
| 4564 | } | 4581 | } else |
| 4565 | else | ||
| 4566 | { | ||
| 4567 | mss = 0; | 4582 | mss = 0; |
| 4568 | } | ||
| 4569 | 4583 | ||
| 4570 | mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); | 4584 | mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); |
| 4571 | 4585 | ||
| @@ -5233,10 +5247,15 @@ bnx2_set_rx_csum(struct net_device *dev, u32 data) | |||
| 5233 | static int | 5247 | static int |
| 5234 | bnx2_set_tso(struct net_device *dev, u32 data) | 5248 | bnx2_set_tso(struct net_device *dev, u32 data) |
| 5235 | { | 5249 | { |
| 5236 | if (data) | 5250 | struct bnx2 *bp = netdev_priv(dev); |
| 5251 | |||
| 5252 | if (data) { | ||
| 5237 | dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; | 5253 | dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; |
| 5238 | else | 5254 | if (CHIP_NUM(bp) == CHIP_NUM_5709) |
| 5239 | dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN); | 5255 | dev->features |= NETIF_F_TSO6; |
| 5256 | } else | ||
| 5257 | dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6 | | ||
| 5258 | NETIF_F_TSO_ECN); | ||
| 5240 | return 0; | 5259 | return 0; |
| 5241 | } | 5260 | } |
| 5242 | 5261 | ||
| @@ -5534,6 +5553,17 @@ bnx2_phys_id(struct net_device *dev, u32 data) | |||
| 5534 | return 0; | 5553 | return 0; |
| 5535 | } | 5554 | } |
| 5536 | 5555 | ||
| 5556 | static int | ||
| 5557 | bnx2_set_tx_csum(struct net_device *dev, u32 data) | ||
| 5558 | { | ||
| 5559 | struct bnx2 *bp = netdev_priv(dev); | ||
| 5560 | |||
| 5561 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
| 5562 | return (ethtool_op_set_tx_hw_csum(dev, data)); | ||
| 5563 | else | ||
| 5564 | return (ethtool_op_set_tx_csum(dev, data)); | ||
| 5565 | } | ||
| 5566 | |||
| 5537 | static const struct ethtool_ops bnx2_ethtool_ops = { | 5567 | static const struct ethtool_ops bnx2_ethtool_ops = { |
| 5538 | .get_settings = bnx2_get_settings, | 5568 | .get_settings = bnx2_get_settings, |
| 5539 | .set_settings = bnx2_set_settings, | 5569 | .set_settings = bnx2_set_settings, |
| @@ -5556,7 +5586,7 @@ static const struct ethtool_ops bnx2_ethtool_ops = { | |||
| 5556 | .get_rx_csum = bnx2_get_rx_csum, | 5586 | .get_rx_csum = bnx2_get_rx_csum, |
| 5557 | .set_rx_csum = bnx2_set_rx_csum, | 5587 | .set_rx_csum = bnx2_set_rx_csum, |
| 5558 | .get_tx_csum = ethtool_op_get_tx_csum, | 5588 | .get_tx_csum = ethtool_op_get_tx_csum, |
| 5559 | .set_tx_csum = ethtool_op_set_tx_csum, | 5589 | .set_tx_csum = bnx2_set_tx_csum, |
| 5560 | .get_sg = ethtool_op_get_sg, | 5590 | .get_sg = ethtool_op_get_sg, |
| 5561 | .set_sg = ethtool_op_set_sg, | 5591 | .set_sg = ethtool_op_set_sg, |
| 5562 | .get_tso = ethtool_op_get_tso, | 5592 | .get_tso = ethtool_op_get_tso, |
| @@ -6094,11 +6124,16 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 6094 | memcpy(dev->perm_addr, bp->mac_addr, 6); | 6124 | memcpy(dev->perm_addr, bp->mac_addr, 6); |
| 6095 | bp->name = board_info[ent->driver_data].name; | 6125 | bp->name = board_info[ent->driver_data].name; |
| 6096 | 6126 | ||
| 6097 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | 6127 | if (CHIP_NUM(bp) == CHIP_NUM_5709) |
| 6128 | dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; | ||
| 6129 | else | ||
| 6130 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | ||
| 6098 | #ifdef BCM_VLAN | 6131 | #ifdef BCM_VLAN |
| 6099 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 6132 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; |
| 6100 | #endif | 6133 | #endif |
| 6101 | dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; | 6134 | dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; |
| 6135 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||
| 6136 | dev->features |= NETIF_F_TSO6; | ||
| 6102 | 6137 | ||
| 6103 | if ((rc = register_netdev(dev))) { | 6138 | if ((rc = register_netdev(dev))) { |
| 6104 | dev_err(&pdev->dev, "Cannot register net device\n"); | 6139 | dev_err(&pdev->dev, "Cannot register net device\n"); |
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 8e7b29a3f930..70fb639b6f52 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h | |||
| @@ -24,8 +24,11 @@ struct tx_bd { | |||
| 24 | u32 tx_bd_haddr_hi; | 24 | u32 tx_bd_haddr_hi; |
| 25 | u32 tx_bd_haddr_lo; | 25 | u32 tx_bd_haddr_lo; |
| 26 | u32 tx_bd_mss_nbytes; | 26 | u32 tx_bd_mss_nbytes; |
| 27 | #define TX_BD_TCP6_OFF2_SHL (14) | ||
| 27 | u32 tx_bd_vlan_tag_flags; | 28 | u32 tx_bd_vlan_tag_flags; |
| 28 | #define TX_BD_FLAGS_CONN_FAULT (1<<0) | 29 | #define TX_BD_FLAGS_CONN_FAULT (1<<0) |
| 30 | #define TX_BD_FLAGS_TCP6_OFF0_MSK (3<<1) | ||
| 31 | #define TX_BD_FLAGS_TCP6_OFF0_SHL (1) | ||
| 29 | #define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1) | 32 | #define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1) |
| 30 | #define TX_BD_FLAGS_IP_CKSUM (1<<2) | 33 | #define TX_BD_FLAGS_IP_CKSUM (1<<2) |
| 31 | #define TX_BD_FLAGS_VLAN_TAG (1<<3) | 34 | #define TX_BD_FLAGS_VLAN_TAG (1<<3) |
| @@ -34,6 +37,7 @@ struct tx_bd { | |||
| 34 | #define TX_BD_FLAGS_END (1<<6) | 37 | #define TX_BD_FLAGS_END (1<<6) |
| 35 | #define TX_BD_FLAGS_START (1<<7) | 38 | #define TX_BD_FLAGS_START (1<<7) |
| 36 | #define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8) | 39 | #define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8) |
| 40 | #define TX_BD_FLAGS_TCP6_OFF4_SHL (12) | ||
| 37 | #define TX_BD_FLAGS_SW_FLAGS (1<<13) | 41 | #define TX_BD_FLAGS_SW_FLAGS (1<<13) |
| 38 | #define TX_BD_FLAGS_SW_SNAP (1<<14) | 42 | #define TX_BD_FLAGS_SW_SNAP (1<<14) |
| 39 | #define TX_BD_FLAGS_SW_LSO (1<<15) | 43 | #define TX_BD_FLAGS_SW_LSO (1<<15) |
