diff options
-rw-r--r-- | drivers/net/ethernet/cadence/macb_main.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 332b19c645b4..dc09f9a8a49b 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
12 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
13 | #include <linux/crc32.h> | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
@@ -1565,6 +1566,9 @@ static unsigned int macb_tx_map(struct macb *bp, | |||
1565 | if (i == queue->tx_head) { | 1566 | if (i == queue->tx_head) { |
1566 | ctrl |= MACB_BF(TX_LSO, lso_ctrl); | 1567 | ctrl |= MACB_BF(TX_LSO, lso_ctrl); |
1567 | ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl); | 1568 | ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl); |
1569 | if ((bp->dev->features & NETIF_F_HW_CSUM) && | ||
1570 | skb->ip_summed != CHECKSUM_PARTIAL && !lso_ctrl) | ||
1571 | ctrl |= MACB_BIT(TX_NOCRC); | ||
1568 | } else | 1572 | } else |
1569 | /* Only set MSS/MFS on payload descriptors | 1573 | /* Only set MSS/MFS on payload descriptors |
1570 | * (second or later descriptor) | 1574 | * (second or later descriptor) |
@@ -1651,6 +1655,67 @@ static inline int macb_clear_csum(struct sk_buff *skb) | |||
1651 | return 0; | 1655 | return 0; |
1652 | } | 1656 | } |
1653 | 1657 | ||
1658 | static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev) | ||
1659 | { | ||
1660 | bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb); | ||
1661 | int padlen = ETH_ZLEN - (*skb)->len; | ||
1662 | int headroom = skb_headroom(*skb); | ||
1663 | int tailroom = skb_tailroom(*skb); | ||
1664 | struct sk_buff *nskb; | ||
1665 | u32 fcs; | ||
1666 | |||
1667 | if (!(ndev->features & NETIF_F_HW_CSUM) || | ||
1668 | !((*skb)->ip_summed != CHECKSUM_PARTIAL) || | ||
1669 | skb_shinfo(*skb)->gso_size) /* Not available for GSO */ | ||
1670 | return 0; | ||
1671 | |||
1672 | if (padlen <= 0) { | ||
1673 | /* FCS could be appeded to tailroom. */ | ||
1674 | if (tailroom >= ETH_FCS_LEN) | ||
1675 | goto add_fcs; | ||
1676 | /* FCS could be appeded by moving data to headroom. */ | ||
1677 | else if (!cloned && headroom + tailroom >= ETH_FCS_LEN) | ||
1678 | padlen = 0; | ||
1679 | /* No room for FCS, need to reallocate skb. */ | ||
1680 | else | ||
1681 | padlen = ETH_FCS_LEN - tailroom; | ||
1682 | } else { | ||
1683 | /* Add room for FCS. */ | ||
1684 | padlen += ETH_FCS_LEN; | ||
1685 | } | ||
1686 | |||
1687 | if (!cloned && headroom + tailroom >= padlen) { | ||
1688 | (*skb)->data = memmove((*skb)->head, (*skb)->data, (*skb)->len); | ||
1689 | skb_set_tail_pointer(*skb, (*skb)->len); | ||
1690 | } else { | ||
1691 | nskb = skb_copy_expand(*skb, 0, padlen, GFP_ATOMIC); | ||
1692 | if (!nskb) | ||
1693 | return -ENOMEM; | ||
1694 | |||
1695 | dev_kfree_skb_any(*skb); | ||
1696 | *skb = nskb; | ||
1697 | } | ||
1698 | |||
1699 | if (padlen) { | ||
1700 | if (padlen >= ETH_FCS_LEN) | ||
1701 | skb_put_zero(*skb, padlen - ETH_FCS_LEN); | ||
1702 | else | ||
1703 | skb_trim(*skb, ETH_FCS_LEN - padlen); | ||
1704 | } | ||
1705 | |||
1706 | add_fcs: | ||
1707 | /* set FCS to packet */ | ||
1708 | fcs = crc32_le(~0, (*skb)->data, (*skb)->len); | ||
1709 | fcs = ~fcs; | ||
1710 | |||
1711 | skb_put_u8(*skb, fcs & 0xff); | ||
1712 | skb_put_u8(*skb, (fcs >> 8) & 0xff); | ||
1713 | skb_put_u8(*skb, (fcs >> 16) & 0xff); | ||
1714 | skb_put_u8(*skb, (fcs >> 24) & 0xff); | ||
1715 | |||
1716 | return 0; | ||
1717 | } | ||
1718 | |||
1654 | static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev) | 1719 | static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev) |
1655 | { | 1720 | { |
1656 | u16 queue_index = skb_get_queue_mapping(skb); | 1721 | u16 queue_index = skb_get_queue_mapping(skb); |
@@ -1667,6 +1732,11 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1667 | return ret; | 1732 | return ret; |
1668 | } | 1733 | } |
1669 | 1734 | ||
1735 | if (macb_pad_and_fcs(&skb, dev)) { | ||
1736 | dev_kfree_skb_any(skb); | ||
1737 | return ret; | ||
1738 | } | ||
1739 | |||
1670 | is_lso = (skb_shinfo(skb)->gso_size != 0); | 1740 | is_lso = (skb_shinfo(skb)->gso_size != 0); |
1671 | 1741 | ||
1672 | if (is_lso) { | 1742 | if (is_lso) { |