mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Hayes Wang <hayeswang@realtek.com>
To: <netdev@vger.kernel.org>
Cc: <nic_swsd@realtek.com>, <linux-kernel@vger.kernel.org>,
	<linux-usb@vger.kernel.org>, Hayes Wang <hayeswang@realtek.com>
Subject: [PATCH net-next 09/12] r8152: support IPv6
Date: Tue, 4 Mar 2014 20:01:01 +0800	[thread overview]
Message-ID: <1393934464-23675-10-git-send-email-hayeswang@realtek.com> (raw)
In-Reply-To: <1393934464-23675-1-git-send-email-hayeswang@realtek.com>

Support hw IPv6 checksum for TCP and UDP packets.

Note that the hw has the limitation of the range of the transport
offset. Besides, the TCP Pseudo Header of the IPv6 TSO of the hw
bases on the Microsoft document which excludes the packet length.

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
 drivers/net/usb/r8152.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 104 insertions(+), 3 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 774a19a..72cbab1 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -21,6 +21,7 @@
 #include <linux/list.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
+#include <net/ip6_checksum.h>
 
 /* Version Information */
 #define DRIVER_VERSION "v1.06.0 (2014/03/03)"
@@ -474,6 +475,7 @@ struct rx_desc {
 	__le32 opts2;
 #define RD_UDP_CS			(1 << 23)
 #define RD_TCP_CS			(1 << 22)
+#define RD_IPV6_CS			(1 << 20)
 #define RD_IPV4_CS			(1 << 19)
 
 	__le32 opts3;
@@ -491,7 +493,9 @@ struct tx_desc {
 #define TX_FS			(1 << 31) /* First segment of a packet */
 #define TX_LS			(1 << 30) /* Final segment of a packet */
 #define GTSENDV4		(1 << 28)
+#define GTSENDV6		(1 << 27)
 #define GTTCPHO_SHIFT		18
+#define GTTCPHO_MAX		0x7fU
 #define TX_LEN_MAX		0x3ffffU
 
 	__le32 opts2;
@@ -502,6 +506,7 @@ struct tx_desc {
 #define MSS_SHIFT		17
 #define MSS_MAX			0x7ffU
 #define TCPHO_SHIFT		17
+#define TCPHO_MAX		0x7ffU
 };
 
 struct r8152;
@@ -1321,6 +1326,65 @@ static inline __be16 get_protocol(struct sk_buff *skb)
 	return protocol;
 }
 
+/*
+ * r8152_csum_workaround()
+ * The hw limites the value the transport offset. When the offset is out of the
+ * range, calculate the checksum by sw.
+ */
+static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb,
+				  struct sk_buff_head *list)
+{
+	if (skb_shinfo(skb)->gso_size) {
+		netdev_features_t features = tp->netdev->features;
+		struct sk_buff *segs, *nskb;
+
+		features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO);
+		segs = skb_gso_segment(skb, features);
+		if (IS_ERR(segs) || !segs)
+			goto drop;
+
+		do {
+			nskb = segs;
+			segs = segs->next;
+			nskb->next = NULL;
+			__skb_queue_head(list, nskb);
+		} while (segs);
+
+		dev_kfree_skb(skb);
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		if (skb_checksum_help(skb) < 0)
+			goto drop;
+
+		__skb_queue_head(list, skb);
+	} else {
+		struct net_device_stats *stats;
+
+drop:
+		stats = &tp->netdev->stats;
+		stats->tx_dropped++;
+		dev_kfree_skb(skb);
+	}
+}
+
+/*
+ * msdn_giant_send_check()
+ * According to the document of microsoft, the TCP Pseudo Header excludes the
+ * packet length for IPv6 TCP large packets.
+ */
+static int msdn_giant_send_check(struct sk_buff *skb)
+{
+	const struct ipv6hdr *ipv6h;
+	struct tcphdr *th;
+
+	ipv6h = ipv6_hdr(skb);
+	th = tcp_hdr(skb);
+
+	th->check = 0;
+	th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0);
+
+	return 0;
+}
+
 static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
 			 struct sk_buff *skb, u32 len, u32 transport_offset)
 {
@@ -1333,11 +1397,24 @@ static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
 	opts1 = len | TX_FS | TX_LS;
 
 	if (mss) {
+		if (transport_offset > GTTCPHO_MAX) {
+			netif_warn(tp, tx_err, tp->netdev,
+				   "Invalid transport offset 0x%x for TSO\n",
+				   transport_offset);
+			ret = TX_CSUM_TSO;
+			goto unavailable;
+		}
+
 		switch (get_protocol(skb)) {
 		case htons(ETH_P_IP):
 			opts1 |= GTSENDV4;
 			break;
 
+		case htons(ETH_P_IPV6):
+			opts1 |= GTSENDV6;
+			msdn_giant_send_check(skb);
+			break;
+
 		default:
 			WARN_ON_ONCE(1);
 			break;
@@ -1348,6 +1425,14 @@ static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		u8 ip_protocol;
 
+		if (transport_offset > TCPHO_MAX) {
+			netif_warn(tp, tx_err, tp->netdev,
+				   "Invalid transport offset 0x%x\n",
+				   transport_offset);
+			ret = TX_CSUM_NONE;
+			goto unavailable;
+		}
+
 		switch (get_protocol(skb)) {
 		case htons(ETH_P_IP):
 			opts2 |= IPV4_CS;
@@ -1377,6 +1462,7 @@ static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
 	desc->opts2 = cpu_to_le32(opts2);
 	desc->opts1 = cpu_to_le32(opts1);
 
+unavailable:
 	return ret;
 }
 
@@ -1441,7 +1527,10 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 
 		offset = (u32)skb_transport_offset(skb);
 
-		r8152_tx_csum(tp, tx_desc, skb, skb->len, offset);
+		if (r8152_tx_csum(tp, tx_desc, skb, skb->len, offset)) {
+			r8152_csum_workaround(tp, skb, &skb_head);
+			continue;
+		}
 
 		tx_data += sizeof(*tx_desc);
 
@@ -1505,6 +1594,18 @@ static int r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
 			checksum = RTL_CHECKSUM_FAIL;
 		else
 			checksum = CHECKSUM_UNNECESSARY;
+	} else if (RD_IPV6_CS) {
+		if (opts2 & RD_UDP_CS) {
+			if (opts3 & UDPF)
+				checksum = RTL_CHECKSUM_FAIL;
+			else
+				checksum = CHECKSUM_UNNECESSARY;
+		} else if (opts2 & RD_TCP_CS) {
+			if (opts3 & TCPF)
+				checksum = RTL_CHECKSUM_FAIL;
+			else
+				checksum = CHECKSUM_UNNECESSARY;
+		}
 	}
 
 return_result:
@@ -3220,9 +3321,9 @@ static int rtl8152_probe(struct usb_interface *intf,
 	netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
 
 	netdev->features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
-			    NETIF_F_TSO;
+			    NETIF_F_TSO | NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
 	netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
-			      NETIF_F_TSO;
+			      NETIF_F_TSO | NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
 
 	SET_ETHTOOL_OPS(netdev, &ops);
 	netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
-- 
1.8.4.2


  parent reply	other threads:[~2014-03-04 12:02 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-04 12:00 [PATCH net-next 00/12] r8152: new features Hayes Wang
2014-03-04 12:00 ` [PATCH net-next 01/12] r8152: deal with the empty line and space Hayes Wang
2014-03-04 12:00 ` [PATCH net-next 02/12] r8152: replace tp->netdev with netdev Hayes Wang
2014-03-04 12:00 ` [PATCH net-next 03/12] r8152: remove rtl8152_get_stats Hayes Wang
2014-03-04 12:00 ` [PATCH net-next 04/12] r8152: replace spin_lock_irqsave and spin_unlock_irqrestore Hayes Wang
2014-03-04 12:00 ` [PATCH net-next 05/12] r8152: check tx agg list before spin lock Hayes Wang
2014-03-04 12:00 ` [PATCH net-next 06/12] r8152: up the priority of the transmission Hayes Wang
2014-03-04 12:00 ` [PATCH net-next 07/12] r8152: support rx checksum Hayes Wang
2014-03-04 21:32   ` David Miller
2014-03-04 12:01 ` [PATCH net-next 08/12] r8152: support TSO Hayes Wang
2014-03-04 12:11   ` David Laight
2014-03-04 13:11     ` hayeswang
2014-03-04 14:35       ` David Laight
2014-03-04 15:02         ` Eric Dumazet
2014-03-04 15:14           ` David Laight
2014-03-04 16:11   ` Eric Dumazet
2014-03-04 16:52   ` Eric Dumazet
2014-03-04 12:01 ` Hayes Wang [this message]
2014-03-04 16:58   ` [PATCH net-next 09/12] r8152: support IPv6 Eric Dumazet
2014-03-04 12:01 ` [PATCH net-next 10/12] r8152: reduce the numbers of the bulks Hayes Wang
2014-03-04 12:01 ` [PATCH net-next 11/12] r8152: add additional parameter for non x86 platform Hayes Wang
2014-03-04 12:01 ` [PATCH net-next 12/12] r8152: modify the tx timeout funcfion Hayes Wang
2014-03-25 20:12   ` Grant Grundler
2014-03-26  9:54     ` hayeswang
2014-03-05  6:49 ` [PATCH net-next v2 00/13] r8152: new features Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 01/13] r8152: deal with the empty line and space Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 02/13] r8152: replace tp->netdev with netdev Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 03/13] r8152: remove rtl8152_get_stats Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 04/13] r8152: replace spin_lock_irqsave and spin_unlock_irqrestore Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 05/13] r8152: check tx agg list before spin lock Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 06/13] r8152: up the priority of the transmission Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 07/13] r8152: calculate the dropped packets for rx Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 08/13] r8152: support rx checksum Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 09/13] r8152: support TSO Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 10/13] r8152: support IPv6 Hayes Wang
2014-03-09 19:47     ` Ben Hutchings
2014-03-09 22:56       ` David Miller
2014-03-05  6:49   ` [PATCH net-next v2 11/13] r8152: reduce the numbers of the bulks Hayes Wang
2014-03-05  6:49   ` [PATCH net-next v2 12/13] r8152: add additional parameter for non x86 platform Hayes Wang
2014-03-06  5:05     ` David Miller
2014-03-05  6:49   ` [PATCH net-next v2 13/13] r8152: modify the tx timeout funcfion Hayes Wang
2014-03-06  7:07 ` [PATCH net-next 0/3] r8152: cleanups Hayes Wang
2014-03-06  7:07   ` [PATCH net-next 1/3] r8152: deal with the empty line and space Hayes Wang
2014-03-06  7:07   ` [PATCH net-next 2/3] r8152: replace tp->netdev with netdev Hayes Wang
2014-03-06  7:07   ` [PATCH net-next 3/3] r8152: remove rtl8152_get_stats Hayes Wang
2014-03-06 18:17   ` [PATCH net-next 0/3] r8152: cleanups David Miller
2014-03-07  3:04 ` [PATCH net-next 0/7] r8152: tx/rx improvement Hayes Wang
2014-03-07  3:04   ` [PATCH net-next 1/7] r8152: replace spin_lock_irqsave and spin_unlock_irqrestore Hayes Wang
2014-03-07  3:04   ` [PATCH net-next 2/7] r8152: check tx agg list before spin lock Hayes Wang
2014-03-07  3:04   ` [PATCH net-next 3/7] r8152: up the priority of the transmission Hayes Wang
2014-03-07  3:04   ` [PATCH net-next 4/7] r8152: calculate the dropped packets for rx Hayes Wang
2014-03-07  3:04   ` [PATCH net-next 5/7] r8152: support rx checksum Hayes Wang
2014-03-07  3:04   ` [PATCH net-next 6/7] r8152: support TSO Hayes Wang
2014-03-07  3:04   ` [PATCH net-next 7/7] r8152: support IPv6 Hayes Wang
2014-03-07 21:27   ` [PATCH net-next 0/7] r8152: tx/rx improvement David Miller
2014-03-10  3:45     ` hayeswang
2014-03-10  6:22 ` [PATCH net-next] r8152: add skb_cow_head Hayes Wang
2014-03-10 20:31   ` David Miller
2014-03-11  2:20 ` [PATCH net-next v2] " Hayes Wang
2014-03-11  2:25   ` David Miller
2014-03-12 12:39 ` [PATCH net-next 0/2] parameter modification Hayes Wang
2014-03-12 12:39   ` [PATCH net-next 1/2] r8152: add CONFIG_RTL8152_EARLY_AGG_SUPER Hayes Wang
2014-03-12 13:40     ` Bjørn Mork
2014-03-12 12:39   ` [PATCH net-next 2/2] r8152: reduce the numbers of the bulks Hayes Wang
2014-03-13  3:34 ` [PATCH net-next v2 0/2] parameter modification Hayes Wang
2014-03-13  3:34   ` [PATCH net-next v2 1/2] r8152: add RTL8152_EARLY_AGG_TIMEOUT_SUPER Hayes Wang
2014-03-13  9:28     ` David Laight
2014-03-13  3:34   ` [PATCH net-next v2 2/2] r8152: reduce the numbers of the bulks Hayes Wang
2014-03-13 12:05 ` [PATCH net-next v3 0/2] parameter modification Hayes Wang
2014-03-13 12:05   ` [PATCH net-next v3 1/2] r8152: add RTL8152_EARLY_AGG_TIMEOUT_SUPER Hayes Wang
2014-03-13 13:12     ` David Laight
2014-03-13 17:22       ` David Miller
2014-03-14  2:37         ` [PATCH net-next v3 1/2] r8152: addRTL8152_EARLY_AGG_TIMEOUT_SUPER hayeswang
2014-03-14  4:07           ` David Miller
2014-03-14  7:24             ` [PATCH net-next v3 1/2] r8152:addRTL8152_EARLY_AGG_TIMEOUT_SUPER hayeswang
2014-03-14 18:43               ` David Miller
2014-03-17  6:01                 ` [PATCH net-next v3 1/2]r8152:addRTL8152_EARLY_AGG_TIMEOUT_SUPER hayeswang
2014-03-14 23:42               ` [PATCH net-next v3 1/2] r8152:addRTL8152_EARLY_AGG_TIMEOUT_SUPER Francois Romieu
2014-03-17  6:03                 ` hayeswang
2014-03-13 12:05   ` [PATCH net-next v3 2/2] r8152: reduce the numbers of the bulks Hayes Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1393934464-23675-10-git-send-email-hayeswang@realtek.com \
    --to=hayeswang@realtek.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=nic_swsd@realtek.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®