summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorhayeswang <hayeswang@realtek.com>2014-03-07 11:04:38 +0800
committerSeema Khowala <seemaj@nvidia.com>2014-04-23 14:07:37 -0700
commit812785b849ae574318639c7c505dc62cf221afa4 (patch)
treeb5486e44daed6e56185a73419d28505c88474fb1 /drivers/net
parent6148892b7c3a81541b472771e923cf265f999035 (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.c41
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);