diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2008-07-24 00:22:59 -0400 |
---|---|---|
committer | Lennert Buytenhek <buytenh@marvell.com> | 2008-07-24 00:22:59 -0400 |
commit | e32b66175072d75bde1ddca4227a6723ca17e0af (patch) | |
tree | bdbd3342dd0575976f15114759a95c6ff07e95d2 /drivers/net/mv643xx_eth.c | |
parent | 2f7eb47a7b9f703d4f7dfdab358df6ff1f2a2204 (diff) |
mv643xx_eth: enable hardware TX checksumming with vlan tags
Although mv643xx_eth has no hardware support for inserting a vlan
tag by twiddling some bits in the TX descriptor, it does support
hardware TX checksumming on packets where the IP header starts {a
limited set of values other than 14} bytes into the packet.
This patch sets mv643xx_eth's ->vlan_features to NETIF_F_SG |
NETIF_F_IP_CSUM, which prevents the stack from checksumming vlan'ed
packets in software, and if vlan tags are present on a transmitted
packet, notifies the hardware of this fact by toggling the right
bits in the TX descriptor.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 01dd3c505d25..88bb1f1e8065 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -235,6 +235,8 @@ struct tx_desc { | |||
235 | #define GEN_IP_V4_CHECKSUM 0x00040000 | 235 | #define GEN_IP_V4_CHECKSUM 0x00040000 |
236 | #define GEN_TCP_UDP_CHECKSUM 0x00020000 | 236 | #define GEN_TCP_UDP_CHECKSUM 0x00020000 |
237 | #define UDP_FRAME 0x00010000 | 237 | #define UDP_FRAME 0x00010000 |
238 | #define MAC_HDR_EXTRA_4_BYTES 0x00008000 | ||
239 | #define MAC_HDR_EXTRA_8_BYTES 0x00000200 | ||
238 | 240 | ||
239 | #define TX_IHL_SHIFT 11 | 241 | #define TX_IHL_SHIFT 11 |
240 | 242 | ||
@@ -757,12 +759,36 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) | |||
757 | desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); | 759 | desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); |
758 | 760 | ||
759 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 761 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
760 | BUG_ON(skb->protocol != htons(ETH_P_IP)); | 762 | int mac_hdr_len; |
763 | |||
764 | BUG_ON(skb->protocol != htons(ETH_P_IP) && | ||
765 | skb->protocol != htons(ETH_P_8021Q)); | ||
761 | 766 | ||
762 | cmd_sts |= GEN_TCP_UDP_CHECKSUM | | 767 | cmd_sts |= GEN_TCP_UDP_CHECKSUM | |
763 | GEN_IP_V4_CHECKSUM | | 768 | GEN_IP_V4_CHECKSUM | |
764 | ip_hdr(skb)->ihl << TX_IHL_SHIFT; | 769 | ip_hdr(skb)->ihl << TX_IHL_SHIFT; |
765 | 770 | ||
771 | mac_hdr_len = (void *)ip_hdr(skb) - (void *)skb->data; | ||
772 | switch (mac_hdr_len - ETH_HLEN) { | ||
773 | case 0: | ||
774 | break; | ||
775 | case 4: | ||
776 | cmd_sts |= MAC_HDR_EXTRA_4_BYTES; | ||
777 | break; | ||
778 | case 8: | ||
779 | cmd_sts |= MAC_HDR_EXTRA_8_BYTES; | ||
780 | break; | ||
781 | case 12: | ||
782 | cmd_sts |= MAC_HDR_EXTRA_4_BYTES; | ||
783 | cmd_sts |= MAC_HDR_EXTRA_8_BYTES; | ||
784 | break; | ||
785 | default: | ||
786 | if (net_ratelimit()) | ||
787 | dev_printk(KERN_ERR, &txq_to_mp(txq)->dev->dev, | ||
788 | "mac header length is %d?!\n", mac_hdr_len); | ||
789 | break; | ||
790 | } | ||
791 | |||
766 | switch (ip_hdr(skb)->protocol) { | 792 | switch (ip_hdr(skb)->protocol) { |
767 | case IPPROTO_UDP: | 793 | case IPPROTO_UDP: |
768 | cmd_sts |= UDP_FRAME; | 794 | cmd_sts |= UDP_FRAME; |
@@ -2565,6 +2591,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
2565 | * have to map the buffers to ISA memory which is only 16 MB | 2591 | * have to map the buffers to ISA memory which is only 16 MB |
2566 | */ | 2592 | */ |
2567 | dev->features = NETIF_F_SG | NETIF_F_IP_CSUM; | 2593 | dev->features = NETIF_F_SG | NETIF_F_IP_CSUM; |
2594 | dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM; | ||
2568 | #endif | 2595 | #endif |
2569 | 2596 | ||
2570 | SET_NETDEV_DEV(dev, &pdev->dev); | 2597 | SET_NETDEV_DEV(dev, &pdev->dev); |