Loading drivers/net/usb/r8152.c +59 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <linux/if_vlan.h> #include <linux/uaccess.h> #include <linux/list.h> #include <linux/ip.h> #include <linux/ipv6.h> /* Version Information */ #define DRIVER_VERSION "v1.01.0 (2013/08/12)" Loading Loading @@ -314,8 +316,13 @@ struct tx_desc { u32 opts1; #define TX_FS (1 << 31) /* First segment of a packet */ #define TX_LS (1 << 30) /* Final segment of a packet */ #define TX_LEN_MASK 0xffff #define TX_LEN_MASK 0x3ffff u32 opts2; #define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */ #define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */ #define IPV4_CS (1 << 29) /* Calculate IPv4 checksum */ #define IPV6_CS (1 << 28) /* Calculate IPv6 checksum */ }; struct rx_agg { Loading Loading @@ -968,6 +975,52 @@ static int alloc_all_mem(struct r8152 *tp) return -ENOMEM; } static void r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb) { memset(desc, 0, sizeof(*desc)); desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS); if (skb->ip_summed == CHECKSUM_PARTIAL) { __be16 protocol; u8 ip_protocol; u32 opts2 = 0; if (skb->protocol == htons(ETH_P_8021Q)) protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; else protocol = skb->protocol; switch (protocol) { case htons(ETH_P_IP): opts2 |= IPV4_CS; ip_protocol = ip_hdr(skb)->protocol; break; case htons(ETH_P_IPV6): opts2 |= IPV6_CS; ip_protocol = ipv6_hdr(skb)->nexthdr; break; default: ip_protocol = IPPROTO_RAW; break; } if (ip_protocol == IPPROTO_TCP) { opts2 |= TCP_CS; opts2 |= (skb_transport_offset(skb) & 0x7fff) << 17; } else if (ip_protocol == IPPROTO_UDP) { opts2 |= UDP_CS; } else { WARN_ON_ONCE(1); } desc->opts2 = cpu_to_le32(opts2); } } static void rx_bottom(struct r8152 *tp) { struct net_device_stats *stats; Loading Loading @@ -1097,8 +1150,7 @@ static void tx_bottom(struct r8152 *tp) tx_desc = (struct tx_desc *)tx_data; tx_data += sizeof(*tx_desc); tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS); r8152_tx_csum(tp, tx_desc, skb); memcpy(tx_data, skb->data, len); agg->skb_num++; agg->skb_len += len; Loading Loading @@ -1256,7 +1308,7 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, agg->skb_num = agg->skb_len = 0; len = skb->len; tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS); r8152_tx_csum(tp, tx_desc, skb); memcpy(tx_data, skb->data, len); dev_kfree_skb_any(skb); agg->skb_num++; Loading Loading @@ -1977,7 +2029,9 @@ static int rtl8152_probe(struct usb_interface *intf, tp->netdev = netdev; netdev->netdev_ops = &rtl8152_netdev_ops; netdev->watchdog_timeo = RTL8152_TX_TIMEOUT; netdev->features &= ~NETIF_F_IP_CSUM; netdev->features |= NETIF_F_IP_CSUM; netdev->hw_features = NETIF_F_IP_CSUM; SET_ETHTOOL_OPS(netdev, &ops); tp->speed = 0; Loading Loading
drivers/net/usb/r8152.c +59 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <linux/if_vlan.h> #include <linux/uaccess.h> #include <linux/list.h> #include <linux/ip.h> #include <linux/ipv6.h> /* Version Information */ #define DRIVER_VERSION "v1.01.0 (2013/08/12)" Loading Loading @@ -314,8 +316,13 @@ struct tx_desc { u32 opts1; #define TX_FS (1 << 31) /* First segment of a packet */ #define TX_LS (1 << 30) /* Final segment of a packet */ #define TX_LEN_MASK 0xffff #define TX_LEN_MASK 0x3ffff u32 opts2; #define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */ #define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */ #define IPV4_CS (1 << 29) /* Calculate IPv4 checksum */ #define IPV6_CS (1 << 28) /* Calculate IPv6 checksum */ }; struct rx_agg { Loading Loading @@ -968,6 +975,52 @@ static int alloc_all_mem(struct r8152 *tp) return -ENOMEM; } static void r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb) { memset(desc, 0, sizeof(*desc)); desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS); if (skb->ip_summed == CHECKSUM_PARTIAL) { __be16 protocol; u8 ip_protocol; u32 opts2 = 0; if (skb->protocol == htons(ETH_P_8021Q)) protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; else protocol = skb->protocol; switch (protocol) { case htons(ETH_P_IP): opts2 |= IPV4_CS; ip_protocol = ip_hdr(skb)->protocol; break; case htons(ETH_P_IPV6): opts2 |= IPV6_CS; ip_protocol = ipv6_hdr(skb)->nexthdr; break; default: ip_protocol = IPPROTO_RAW; break; } if (ip_protocol == IPPROTO_TCP) { opts2 |= TCP_CS; opts2 |= (skb_transport_offset(skb) & 0x7fff) << 17; } else if (ip_protocol == IPPROTO_UDP) { opts2 |= UDP_CS; } else { WARN_ON_ONCE(1); } desc->opts2 = cpu_to_le32(opts2); } } static void rx_bottom(struct r8152 *tp) { struct net_device_stats *stats; Loading Loading @@ -1097,8 +1150,7 @@ static void tx_bottom(struct r8152 *tp) tx_desc = (struct tx_desc *)tx_data; tx_data += sizeof(*tx_desc); tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS); r8152_tx_csum(tp, tx_desc, skb); memcpy(tx_data, skb->data, len); agg->skb_num++; agg->skb_len += len; Loading Loading @@ -1256,7 +1308,7 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, agg->skb_num = agg->skb_len = 0; len = skb->len; tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS); r8152_tx_csum(tp, tx_desc, skb); memcpy(tx_data, skb->data, len); dev_kfree_skb_any(skb); agg->skb_num++; Loading Loading @@ -1977,7 +2029,9 @@ static int rtl8152_probe(struct usb_interface *intf, tp->netdev = netdev; netdev->netdev_ops = &rtl8152_netdev_ops; netdev->watchdog_timeo = RTL8152_TX_TIMEOUT; netdev->features &= ~NETIF_F_IP_CSUM; netdev->features |= NETIF_F_IP_CSUM; netdev->hw_features = NETIF_F_IP_CSUM; SET_ETHTOOL_OPS(netdev, &ops); tp->speed = 0; Loading