aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2007-05-03 16:22:28 -0400
committerDavid S. Miller <davem@davemloft.net>2007-05-03 16:22:28 -0400
commit4666f87a82cf74b63737a7f55a8b3b057a7b83df (patch)
tree67cc362f70fa70bb8218e91e46e82d3bd5f7b57e /drivers/net/bnx2.c
parent874bb672fdd939aec37ad3a06b50be4ff8b4feac (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>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r--drivers/net/bnx2.c91
1 files changed, 63 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)
5233static int 5247static int
5234bnx2_set_tso(struct net_device *dev, u32 data) 5248bnx2_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
5556static int
5557bnx2_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
5537static const struct ethtool_ops bnx2_ethtool_ops = { 5567static 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");