diff options
author | hayeswang <hayeswang@realtek.com> | 2014-03-07 11:04:38 +0800 |
---|---|---|
committer | Seema Khowala <seemaj@nvidia.com> | 2014-04-23 14:07:37 -0700 |
commit | 812785b849ae574318639c7c505dc62cf221afa4 (patch) | |
tree | b5486e44daed6e56185a73419d28505c88474fb1 /drivers/net | |
parent | 6148892b7c3a81541b472771e923cf265f999035 (diff) |
r8152: support rx checksum
Support hw rx checksum for TCP and UDP packets.
Change-Id: I3bb3cefe4d9dbd98996fa975256545f35f393eae
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Aly Hirani <ahirani@nvidia.com>
Reviewed-on: http://git-master/r/390296
(cherry picked from commit 930a7af20283f78e3f5e5e4c70615c84c1ee29f6)
Reviewed-on: http://git-master/r/396898
Reviewed-by: Preetham Chandru <pchandru@nvidia.com>
Tested-by: Preetham Chandru <pchandru@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/usb/r8152.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 9c3ca4c38d16..571a2af3cdd4 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -465,8 +465,17 @@ enum rtl8152_flags { struct rx_desc { __le32 opts1; #define RX_LEN_MASK 0x7fff + __le32 opts2; +#define RD_UDP_CS (1 << 23) +#define RD_TCP_CS (1 << 22) +#define RD_IPV4_CS (1 << 19) + __le32 opts3; +#define IPF (1 << 23) /* IP checksum fail */ +#define UDPF (1 << 22) /* UDP checksum fail */ +#define TCPF (1 << 21) /* TCP checksum fail */ + __le32 opts4; __le32 opts5; __le32 opts6; @@ -1402,6 +1411,32 @@ out_tx_fill: return ret; } +static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc) +{ + u8 checksum = CHECKSUM_NONE; + u32 opts2, opts3; + + if (tp->version == RTL_VER_01) + goto return_result; + + opts2 = le32_to_cpu(rx_desc->opts2); + opts3 = le32_to_cpu(rx_desc->opts3); + + if (opts2 & RD_IPV4_CS) { + if (opts3 & IPF) + checksum = CHECKSUM_NONE; + else if ((opts2 & RD_UDP_CS) && (opts3 & UDPF)) + checksum = CHECKSUM_NONE; + else if ((opts2 & RD_TCP_CS) && (opts3 & TCPF)) + checksum = CHECKSUM_NONE; + else + checksum = CHECKSUM_UNNECESSARY; + } + +return_result: + return checksum; +} + static void rx_bottom(struct r8152 *tp) { unsigned long flags; @@ -1456,6 +1491,8 @@ static void rx_bottom(struct r8152 *tp) stats->rx_dropped++; goto find_next_rx; } + + skb->ip_summed = r8152_rx_csum(tp, rx_desc); memcpy(skb->data, rx_data, pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, netdev); @@ -3106,8 +3143,8 @@ static int rtl8152_probe(struct usb_interface *intf, netdev->netdev_ops = &rtl8152_netdev_ops; netdev->watchdog_timeo = RTL8152_TX_TIMEOUT; - netdev->features |= NETIF_F_IP_CSUM; - netdev->hw_features = NETIF_F_IP_CSUM; + netdev->features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM; + netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM; SET_ETHTOOL_OPS(netdev, &ops); |