Commit a7cf3d24 authored by Subash Abhinov Kasiviswanathan's avatar Subash Abhinov Kasiviswanathan Committed by David S. Miller

net: qualcomm: rmnet: Fix incorrect UL checksum offload logic

The udp_ip4_ind bit is set only for IPv4 UDP non-fragmented packets
so that the hardware can flip the checksum to 0xFFFF if the computed
checksum is 0 per RFC768.

However, this bit had to be set for IPv6 UDP non fragmented packets
as well per hardware requirements. Otherwise, IPv6 UDP packets
with computed checksum as 0 were transmitted by hardware and were
dropped in the network.

In addition to setting this bit for IPv6 UDP, the field is also
appropriately renamed to udp_ind as part of this change.

Fixes: 5eb5f860 ("net: qualcomm: rmnet: Add support for TX checksum offload")
Cc: Sean Tranchetti <stranche@codeaurora.org>
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 01f5bffa
...@@ -206,9 +206,9 @@ rmnet_map_ipv4_ul_csum_header(void *iphdr, ...@@ -206,9 +206,9 @@ rmnet_map_ipv4_ul_csum_header(void *iphdr,
ul_header->csum_insert_offset = skb->csum_offset; ul_header->csum_insert_offset = skb->csum_offset;
ul_header->csum_enabled = 1; ul_header->csum_enabled = 1;
if (ip4h->protocol == IPPROTO_UDP) if (ip4h->protocol == IPPROTO_UDP)
ul_header->udp_ip4_ind = 1; ul_header->udp_ind = 1;
else else
ul_header->udp_ip4_ind = 0; ul_header->udp_ind = 0;
/* Changing remaining fields to network order */ /* Changing remaining fields to network order */
hdr++; hdr++;
...@@ -239,6 +239,7 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr, ...@@ -239,6 +239,7 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
struct rmnet_map_ul_csum_header *ul_header, struct rmnet_map_ul_csum_header *ul_header,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ipv6hdr *ip6h = (struct ipv6hdr *)ip6hdr;
__be16 *hdr = (__be16 *)ul_header, offset; __be16 *hdr = (__be16 *)ul_header, offset;
offset = htons((__force u16)(skb_transport_header(skb) - offset = htons((__force u16)(skb_transport_header(skb) -
...@@ -246,7 +247,11 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr, ...@@ -246,7 +247,11 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
ul_header->csum_start_offset = offset; ul_header->csum_start_offset = offset;
ul_header->csum_insert_offset = skb->csum_offset; ul_header->csum_insert_offset = skb->csum_offset;
ul_header->csum_enabled = 1; ul_header->csum_enabled = 1;
ul_header->udp_ip4_ind = 0;
if (ip6h->nexthdr == IPPROTO_UDP)
ul_header->udp_ind = 1;
else
ul_header->udp_ind = 0;
/* Changing remaining fields to network order */ /* Changing remaining fields to network order */
hdr++; hdr++;
...@@ -419,7 +424,7 @@ void rmnet_map_checksum_uplink_packet(struct sk_buff *skb, ...@@ -419,7 +424,7 @@ void rmnet_map_checksum_uplink_packet(struct sk_buff *skb,
ul_header->csum_start_offset = 0; ul_header->csum_start_offset = 0;
ul_header->csum_insert_offset = 0; ul_header->csum_insert_offset = 0;
ul_header->csum_enabled = 0; ul_header->csum_enabled = 0;
ul_header->udp_ip4_ind = 0; ul_header->udp_ind = 0;
priv->stats.csum_sw++; priv->stats.csum_sw++;
} }
...@@ -41,11 +41,11 @@ struct rmnet_map_ul_csum_header { ...@@ -41,11 +41,11 @@ struct rmnet_map_ul_csum_header {
__be16 csum_start_offset; __be16 csum_start_offset;
#if defined(__LITTLE_ENDIAN_BITFIELD) #if defined(__LITTLE_ENDIAN_BITFIELD)
u16 csum_insert_offset:14; u16 csum_insert_offset:14;
u16 udp_ip4_ind:1; u16 udp_ind:1;
u16 csum_enabled:1; u16 csum_enabled:1;
#elif defined (__BIG_ENDIAN_BITFIELD) #elif defined (__BIG_ENDIAN_BITFIELD)
u16 csum_enabled:1; u16 csum_enabled:1;
u16 udp_ip4_ind:1; u16 udp_ind:1;
u16 csum_insert_offset:14; u16 csum_insert_offset:14;
#else #else
#error "Please fix <asm/byteorder.h>" #error "Please fix <asm/byteorder.h>"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment