aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c70
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
1658static 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
1706add_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
1654static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev) 1719static 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) {