diff options
Diffstat (limited to 'drivers')
-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 01dd3c5..88bb1f1 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -235,6 +235,8 @@ struct tx_desc { #define GEN_IP_V4_CHECKSUM 0x00040000 #define GEN_TCP_UDP_CHECKSUM 0x00020000 #define UDP_FRAME 0x00010000 +#define MAC_HDR_EXTRA_4_BYTES 0x00008000 +#define MAC_HDR_EXTRA_8_BYTES 0x00000200 #define TX_IHL_SHIFT 11 @@ -757,12 +759,36 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); if (skb->ip_summed == CHECKSUM_PARTIAL) { - BUG_ON(skb->protocol != htons(ETH_P_IP)); + int mac_hdr_len; + + BUG_ON(skb->protocol != htons(ETH_P_IP) && + skb->protocol != htons(ETH_P_8021Q)); cmd_sts |= GEN_TCP_UDP_CHECKSUM | GEN_IP_V4_CHECKSUM | ip_hdr(skb)->ihl << TX_IHL_SHIFT; + mac_hdr_len = (void *)ip_hdr(skb) - (void *)skb->data; + switch (mac_hdr_len - ETH_HLEN) { + case 0: + break; + case 4: + cmd_sts |= MAC_HDR_EXTRA_4_BYTES; + break; + case 8: + cmd_sts |= MAC_HDR_EXTRA_8_BYTES; + break; + case 12: + cmd_sts |= MAC_HDR_EXTRA_4_BYTES; + cmd_sts |= MAC_HDR_EXTRA_8_BYTES; + break; + default: + if (net_ratelimit()) + dev_printk(KERN_ERR, &txq_to_mp(txq)->dev->dev, + "mac header length is %d?!\n", mac_hdr_len); + break; + } + switch (ip_hdr(skb)->protocol) { case IPPROTO_UDP: cmd_sts |= UDP_FRAME; @@ -2565,6 +2591,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) * have to map the buffers to ISA memory which is only 16 MB */ dev->features = NETIF_F_SG | NETIF_F_IP_CSUM; + dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM; #endif SET_NETDEV_DEV(dev, &pdev->dev); |