aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mv643xx_eth.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2008-07-24 00:22:59 -0400
committerLennert Buytenhek <buytenh@marvell.com>2008-07-24 00:22:59 -0400
commite32b66175072d75bde1ddca4227a6723ca17e0af (patch)
treebdbd3342dd0575976f15114759a95c6ff07e95d2 /drivers/net/mv643xx_eth.c
parent2f7eb47a7b9f703d4f7dfdab358df6ff1f2a2204 (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.c29
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);