diff options
author | Dmitry Bezrukov <dmitry.bezrukov@aquantia.com> | 2018-11-26 09:33:21 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-11-27 15:46:07 -0800 |
commit | 0203146646be831de832e7fd2dc4ef1f32958f51 (patch) | |
tree | a911fe6bd6fa9b4017de209fac7269e12189be8a /drivers/net/usb/aqc111.c | |
parent | 361459cd9642631f048719169da9ef14cbf4a932 (diff) | |
download | linux-0203146646be831de832e7fd2dc4ef1f32958f51.tar.gz linux-0203146646be831de832e7fd2dc4ef1f32958f51.tar.bz2 linux-0203146646be831de832e7fd2dc4ef1f32958f51.zip |
net: usb: aqc111: Add checksum offload support
Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb/aqc111.c')
-rw-r--r-- | drivers/net/usb/aqc111.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c index 7a1976ecf294..1c8812e082bf 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, ®8); + + 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, ®8); +} + 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, ®16); + aqc111_configure_csum_offload(dev); + aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 2, ®16); @@ -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; @@ -660,6 +697,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 = SKB_TRUESIZE(new_skb->len); + aqc111_rx_checksum(new_skb, pkt_desc); usbnet_skb_return(dev, new_skb); if (pkt_count == 0) |