aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-07-11 17:33:31 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-11 17:33:31 -0400
commit19278cab62add209beda861696ac5f905485444f (patch)
tree8a0b41a5cc8db77b424ee30a8efbb472c08d4fb0
parenta2f983f83b0f66a74a045d36eb84e2f01bb950c7 (diff)
parente974604b453e87f8d864371786375d3d511fdf56 (diff)
Merge branch 'r8169_tso_ipv6'
Hayes Wang says: ==================== r8169: support IPv6 The RTL8168C and the later chips support the hardware checksum for IPv6. Adjust some code and add the relative code. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/realtek/r8169.c220
1 files changed, 181 insertions, 39 deletions
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index be425ad5e824..51c78ce27b37 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -27,6 +27,8 @@
27#include <linux/firmware.h> 27#include <linux/firmware.h>
28#include <linux/pci-aspm.h> 28#include <linux/pci-aspm.h>
29#include <linux/prefetch.h> 29#include <linux/prefetch.h>
30#include <linux/ipv6.h>
31#include <net/ip6_checksum.h>
30 32
31#include <asm/io.h> 33#include <asm/io.h>
32#include <asm/irq.h> 34#include <asm/irq.h>
@@ -626,39 +628,22 @@ enum rtl_tx_desc_bit_0 {
626 628
627/* 8102e, 8168c and beyond. */ 629/* 8102e, 8168c and beyond. */
628enum rtl_tx_desc_bit_1 { 630enum rtl_tx_desc_bit_1 {
631 /* First doubleword. */
632 TD1_GTSENV4 = (1 << 26), /* Giant Send for IPv4 */
633 TD1_GTSENV6 = (1 << 25), /* Giant Send for IPv6 */
634#define GTTCPHO_SHIFT 18
635#define GTTCPHO_MAX 0x7fU
636
629 /* Second doubleword. */ 637 /* Second doubleword. */
638#define TCPHO_SHIFT 18
639#define TCPHO_MAX 0x3ffU
630#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */ 640#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
631 TD1_IP_CS = (1 << 29), /* Calculate IP checksum */ 641 TD1_IPv6_CS = (1 << 28), /* Calculate IPv6 checksum */
642 TD1_IPv4_CS = (1 << 29), /* Calculate IPv4 checksum */
632 TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */ 643 TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
633 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */ 644 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
634}; 645};
635 646
636static const struct rtl_tx_desc_info {
637 struct {
638 u32 udp;
639 u32 tcp;
640 } checksum;
641 u16 mss_shift;
642 u16 opts_offset;
643} tx_desc_info [] = {
644 [RTL_TD_0] = {
645 .checksum = {
646 .udp = TD0_IP_CS | TD0_UDP_CS,
647 .tcp = TD0_IP_CS | TD0_TCP_CS
648 },
649 .mss_shift = TD0_MSS_SHIFT,
650 .opts_offset = 0
651 },
652 [RTL_TD_1] = {
653 .checksum = {
654 .udp = TD1_IP_CS | TD1_UDP_CS,
655 .tcp = TD1_IP_CS | TD1_TCP_CS
656 },
657 .mss_shift = TD1_MSS_SHIFT,
658 .opts_offset = 1
659 }
660};
661
662enum rtl_rx_desc_bit { 647enum rtl_rx_desc_bit {
663 /* Rx private */ 648 /* Rx private */
664 PID1 = (1 << 18), /* Protocol ID bit 1/2 */ 649 PID1 = (1 << 18), /* Protocol ID bit 1/2 */
@@ -782,6 +767,7 @@ struct rtl8169_private {
782 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp); 767 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
783 unsigned int (*link_ok)(void __iomem *); 768 unsigned int (*link_ok)(void __iomem *);
784 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); 769 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
770 bool (*tso_csum)(struct rtl8169_private *, struct sk_buff *, u32 *);
785 771
786 struct { 772 struct {
787 DECLARE_BITMAP(flags, RTL_FLAG_MAX); 773 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
@@ -5941,32 +5927,179 @@ static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb)
5941 return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34; 5927 return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34;
5942} 5928}
5943 5929
5944static inline bool rtl8169_tso_csum(struct rtl8169_private *tp, 5930static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5945 struct sk_buff *skb, u32 *opts) 5931 struct net_device *dev);
5932/* r8169_csum_workaround()
5933 * The hw limites the value the transport offset. When the offset is out of the
5934 * range, calculate the checksum by sw.
5935 */
5936static void r8169_csum_workaround(struct rtl8169_private *tp,
5937 struct sk_buff *skb)
5938{
5939 if (skb_shinfo(skb)->gso_size) {
5940 netdev_features_t features = tp->dev->features;
5941 struct sk_buff *segs, *nskb;
5942
5943 features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
5944 segs = skb_gso_segment(skb, features);
5945 if (IS_ERR(segs) || !segs)
5946 goto drop;
5947
5948 do {
5949 nskb = segs;
5950 segs = segs->next;
5951 nskb->next = NULL;
5952 rtl8169_start_xmit(nskb, tp->dev);
5953 } while (segs);
5954
5955 dev_kfree_skb(skb);
5956 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
5957 if (skb_checksum_help(skb) < 0)
5958 goto drop;
5959
5960 rtl8169_start_xmit(skb, tp->dev);
5961 } else {
5962 struct net_device_stats *stats;
5963
5964drop:
5965 stats = &tp->dev->stats;
5966 stats->tx_dropped++;
5967 dev_kfree_skb(skb);
5968 }
5969}
5970
5971/* msdn_giant_send_check()
5972 * According to the document of microsoft, the TCP Pseudo Header excludes the
5973 * packet length for IPv6 TCP large packets.
5974 */
5975static int msdn_giant_send_check(struct sk_buff *skb)
5976{
5977 const struct ipv6hdr *ipv6h;
5978 struct tcphdr *th;
5979 int ret;
5980
5981 ret = skb_cow_head(skb, 0);
5982 if (ret)
5983 return ret;
5984
5985 ipv6h = ipv6_hdr(skb);
5986 th = tcp_hdr(skb);
5987
5988 th->check = 0;
5989 th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0);
5990
5991 return ret;
5992}
5993
5994static inline __be16 get_protocol(struct sk_buff *skb)
5995{
5996 __be16 protocol;
5997
5998 if (skb->protocol == htons(ETH_P_8021Q))
5999 protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
6000 else
6001 protocol = skb->protocol;
6002
6003 return protocol;
6004}
6005
6006static bool rtl8169_tso_csum_v1(struct rtl8169_private *tp,
6007 struct sk_buff *skb, u32 *opts)
5946{ 6008{
5947 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
5948 u32 mss = skb_shinfo(skb)->gso_size; 6009 u32 mss = skb_shinfo(skb)->gso_size;
5949 int offset = info->opts_offset;
5950 6010
5951 if (mss) { 6011 if (mss) {
5952 opts[0] |= TD_LSO; 6012 opts[0] |= TD_LSO;
5953 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift; 6013 opts[0] |= min(mss, TD_MSS_MAX) << TD0_MSS_SHIFT;
5954 } else if (skb->ip_summed == CHECKSUM_PARTIAL) { 6014 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
5955 const struct iphdr *ip = ip_hdr(skb); 6015 const struct iphdr *ip = ip_hdr(skb);
5956 6016
6017 if (ip->protocol == IPPROTO_TCP)
6018 opts[0] |= TD0_IP_CS | TD0_TCP_CS;
6019 else if (ip->protocol == IPPROTO_UDP)
6020 opts[0] |= TD0_IP_CS | TD0_UDP_CS;
6021 else
6022 WARN_ON_ONCE(1);
6023 }
6024
6025 return true;
6026}
6027
6028static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
6029 struct sk_buff *skb, u32 *opts)
6030{
6031 u32 transport_offset = (u32)skb_transport_offset(skb);
6032 u32 mss = skb_shinfo(skb)->gso_size;
6033
6034 if (mss) {
6035 if (transport_offset > GTTCPHO_MAX) {
6036 netif_warn(tp, tx_err, tp->dev,
6037 "Invalid transport offset 0x%x for TSO\n",
6038 transport_offset);
6039 return false;
6040 }
6041
6042 switch (get_protocol(skb)) {
6043 case htons(ETH_P_IP):
6044 opts[0] |= TD1_GTSENV4;
6045 break;
6046
6047 case htons(ETH_P_IPV6):
6048 if (msdn_giant_send_check(skb))
6049 return false;
6050
6051 opts[0] |= TD1_GTSENV6;
6052 break;
6053
6054 default:
6055 WARN_ON_ONCE(1);
6056 break;
6057 }
6058
6059 opts[0] |= transport_offset << GTTCPHO_SHIFT;
6060 opts[1] |= min(mss, TD_MSS_MAX) << TD1_MSS_SHIFT;
6061 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
6062 u8 ip_protocol;
6063
5957 if (unlikely(rtl_test_hw_pad_bug(tp, skb))) 6064 if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
5958 return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb); 6065 return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb);
5959 6066
5960 if (ip->protocol == IPPROTO_TCP) 6067 if (transport_offset > TCPHO_MAX) {
5961 opts[offset] |= info->checksum.tcp; 6068 netif_warn(tp, tx_err, tp->dev,
5962 else if (ip->protocol == IPPROTO_UDP) 6069 "Invalid transport offset 0x%x\n",
5963 opts[offset] |= info->checksum.udp; 6070 transport_offset);
6071 return false;
6072 }
6073
6074 switch (get_protocol(skb)) {
6075 case htons(ETH_P_IP):
6076 opts[1] |= TD1_IPv4_CS;
6077 ip_protocol = ip_hdr(skb)->protocol;
6078 break;
6079
6080 case htons(ETH_P_IPV6):
6081 opts[1] |= TD1_IPv6_CS;
6082 ip_protocol = ipv6_hdr(skb)->nexthdr;
6083 break;
6084
6085 default:
6086 ip_protocol = IPPROTO_RAW;
6087 break;
6088 }
6089
6090 if (ip_protocol == IPPROTO_TCP)
6091 opts[1] |= TD1_TCP_CS;
6092 else if (ip_protocol == IPPROTO_UDP)
6093 opts[1] |= TD1_UDP_CS;
5964 else 6094 else
5965 WARN_ON_ONCE(1); 6095 WARN_ON_ONCE(1);
6096
6097 opts[1] |= transport_offset << TCPHO_SHIFT;
5966 } else { 6098 } else {
5967 if (unlikely(rtl_test_hw_pad_bug(tp, skb))) 6099 if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
5968 return rtl_skb_pad(skb); 6100 return rtl_skb_pad(skb);
5969 } 6101 }
6102
5970 return true; 6103 return true;
5971} 6104}
5972 6105
@@ -5994,8 +6127,10 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5994 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb)); 6127 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
5995 opts[0] = DescOwn; 6128 opts[0] = DescOwn;
5996 6129
5997 if (!rtl8169_tso_csum(tp, skb, opts)) 6130 if (!tp->tso_csum(tp, skb, opts)) {
5998 goto err_update_stats; 6131 r8169_csum_workaround(tp, skb);
6132 return NETDEV_TX_OK;
6133 }
5999 6134
6000 len = skb_headlen(skb); 6135 len = skb_headlen(skb);
6001 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE); 6136 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
@@ -6060,7 +6195,6 @@ err_dma_1:
6060 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd); 6195 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
6061err_dma_0: 6196err_dma_0:
6062 dev_kfree_skb_any(skb); 6197 dev_kfree_skb_any(skb);
6063err_update_stats:
6064 dev->stats.tx_dropped++; 6198 dev->stats.tx_dropped++;
6065 return NETDEV_TX_OK; 6199 return NETDEV_TX_OK;
6066 6200
@@ -7145,6 +7279,14 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
7145 /* 8110SCd requires hardware Rx VLAN - disallow toggling */ 7279 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
7146 dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX; 7280 dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
7147 7281
7282 if (tp->txd_version == RTL_TD_0)
7283 tp->tso_csum = rtl8169_tso_csum_v1;
7284 else if (tp->txd_version == RTL_TD_1) {
7285 tp->tso_csum = rtl8169_tso_csum_v2;
7286 dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
7287 } else
7288 WARN_ON_ONCE(1);
7289
7148 dev->hw_features |= NETIF_F_RXALL; 7290 dev->hw_features |= NETIF_F_RXALL;
7149 dev->hw_features |= NETIF_F_RXFCS; 7291 dev->hw_features |= NETIF_F_RXFCS;
7150 7292