aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/cadence/macb_main.c
diff options
context:
space:
mode:
authorClaudiu Beznea <claudiu.beznea@microchip.com>2018-08-07 05:25:14 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-07 16:18:49 -0400
commit653e92a9175ea7ed67efe209c725222051a3713d (patch)
tree8f5fce8d1c80755b83aaf2823372162f023c0726 /drivers/net/ethernet/cadence/macb_main.c
parent33729f25a31e84e665b5441181bf98a514740fcf (diff)
net: macb: add support for padding and fcs computation
For packets with computed IP/TCP/UDP checksum there is no need to tell hardware to recompute it. For such kind of packets hardware expects the packet to be at least 64 bytes and FCS to be computed. Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/cadence/macb_main.c')
-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) {