From: Dmitry Bezrukov <dmitry.bezru...@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezru...@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russk...@aquantia.com>
---
 drivers/net/usb/aqc111.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 16 ++++++++++++++--
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 2ad8b3100e2e..2a322391896c 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -439,6 +439,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)
 {
        struct aqc111_data *aqc111_data = dev->driver_priv;
@@ -482,6 +502,8 @@ static int aqc111_link_reset(struct usbnet *dev)
                aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
                                   2, &reg16);
 
+               aqc111_configure_csum_offload(dev);
+
                aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
                                  2, &reg16);
 
@@ -583,6 +605,21 @@ static int aqc111_stop(struct usbnet *dev)
        return 0;
 }
 
+static void aqc111_rx_checksum(struct sk_buff *skb, u64 *pkt_desc)
+{
+       u32 pkt_type = 0;
+
+       skb->ip_summed = CHECKSUM_NONE;
+       /* checksum error bit is set */
+       if (*pkt_desc & AQ_RX_PD_L4_ERR || *pkt_desc & AQ_RX_PD_L3_ERR)
+               return;
+
+       pkt_type = *pkt_desc & AQ_RX_PD_L4_TYPE_MASK;
+       /* It must be a TCP or UDP packet with a valid checksum */
+       if (pkt_type == AQ_RX_PD_L4_TCP || pkt_type == AQ_RX_PD_L4_UDP)
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
 static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
        struct sk_buff *new_skb = NULL;
@@ -661,6 +698,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 c5785f890022..ff43443bfd72 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -21,8 +21,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. ********************************************/
 
@@ -162,6 +165,15 @@ struct aqc111_data {
 #define AQ_RX_HW_PAD                   0x02
 
 /* RX Packet Descriptor */
+#define AQ_RX_PD_L4_ERR                BIT(0)
+#define AQ_RX_PD_L3_ERR                BIT(1)
+#define AQ_RX_PD_L4_TYPE_MASK  0x1C
+#define AQ_RX_PD_L4_UDP                0x04
+#define AQ_RX_PD_L4_TCP                0x10
+#define AQ_RX_PD_L3_TYPE_MASK  0x60
+#define AQ_RX_PD_L3_IP         0x20
+#define AQ_RX_PD_L3_IP6                0x40
+
 #define AQ_RX_PD_RX_OK         BIT(11)
 #define AQ_RX_PD_DROP          BIT(31)
 #define AQ_RX_PD_LEN_MASK      0x7FFF0000
-- 
2.17.1

Reply via email to