diff mbox series

[net-next,10/19] net: usb: aqc111: Add checksum offload support

Message ID 8252f068582078a8c56789d9cff72fc151c4723c.1538734658.git.igor.russkikh@aquantia.com
State Changes Requested, archived
Delegated to: David Miller
Headers show
Series Add support for Aquantia AQtion USB to 5/2.5GbE devices | expand

Commit Message

Igor Russkikh Oct. 5, 2018, 10:25 a.m. UTC
From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 23 +++++++++++++++++++++--
 2 files changed, 59 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index fc068e731335..5967f7adeab4 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -537,6 +537,26 @@  static void aqc111_configure_rx(struct usbnet *dev,
 	netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host);
 }
 
+static void aqc111_configure_csum_offload(struct usbnet *dev)
+{
+	u8 reg8 = 0;
+
+	if (dev->net->features & NETIF_F_RXCSUM) {
+		reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP |
+			SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6;
+	}
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, &reg8);
+
+	reg8 = 0;
+	if (dev->net->features & NETIF_F_IP_CSUM)
+		reg8 |= SFR_TXCOE_IP | SFR_TXCOE_TCP | SFR_TXCOE_UDP;
+
+	if (dev->net->features & NETIF_F_IPV6_CSUM)
+		reg8 |= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6;
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
+}
+
 static int aqc111_link_reset(struct usbnet *dev)
 {
 	u8 reg8 = 0;
@@ -580,6 +600,8 @@  static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				 2, 2, &reg16);
 
+		aqc111_configure_csum_offload(dev);
+
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				2, 2, &reg16);
 
@@ -713,6 +735,21 @@  static int aqc111_stop(struct usbnet *dev)
 	return 0;
 }
 
+static void aqc111_rx_checksum(struct sk_buff *skb, void *pkt_hdr)
+{
+	struct aq_rx_packet_desc *hdr = (struct aq_rx_packet_desc *)pkt_hdr;
+
+	skb->ip_summed = CHECKSUM_NONE;
+	/* checksum error bit is set */
+	if (hdr->l4_err || hdr->l3_err)
+		return;
+
+	/* It must be a TCP or UDP packet with a valid checksum */
+	if (hdr->l4_pkt_type == AQ_RXHDR_L4_TYPE_TCP ||
+	    hdr->l4_pkt_type == AQ_RXHDR_L4_TYPE_UDP)
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
 static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
 	struct sk_buff *new_skb = NULL;
@@ -788,6 +825,7 @@  static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 		skb_set_tail_pointer(new_skb, new_skb->len);
 
 		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
+		aqc111_rx_checksum(new_skb, &pkt_desc);
 
 		usbnet_skb_return(dev, new_skb);
 		if (pkt_count == 0)
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 679ca9f992f7..1632e78ebe9b 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -63,8 +63,11 @@ 
 #define AQ_USB_SET_TIMEOUT		4000
 
 /* Feature. ********************************************/
-#define AQ_SUPPORT_FEATURE	(NETIF_F_SG)
-#define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG)
+#define AQ_SUPPORT_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
+
+#define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
 
 /* SFR Reg. ********************************************/
 
@@ -230,6 +233,22 @@  struct aqc111_int_data {
 #define AQ_INT_SPEED_1G		0x11
 #define AQ_INT_SPEED_100M	0x13
 
+#define AQ_RXHDR_L4_ERR		BIT(8)
+#define AQ_RXHDR_L3_ERR		BIT(9)
+
+#define AQ_RXHDR_L4_TYPE_ICMP		0x02
+#define AQ_RXHDR_L4_TYPE_IGMP		0x03
+#define AQ_RXHDR_L4_TYPE_TCMPV6		0x05
+
+#define AQ_RXHDR_L3_TYPE_IP		0x01
+#define AQ_RXHDR_L3_TYPE_IPV6		0x02
+
+#define AQ_RXHDR_L4_TYPE_MASK		0x1c
+#define AQ_RXHDR_L4_TYPE_UDP		0x04
+#define AQ_RXHDR_L4_TYPE_TCP		0x10
+#define AQ_RXHDR_L3CSUM_ERR		0x02
+#define AQ_RXHDR_L4CSUM_ERR		0x01
+
 #define AQ_RX_HW_PAD			0x02
 
 struct aq_tx_packet_desc {