Re: [PATCH net-next 09/10] net: qualcomm: rmnet: Add support for TX checksum offload

2017-12-27 Thread kbuild test robot
Hi Subash,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]

url:
https://github.com/0day-ci/linux/commits/Subash-Abhinov-Kasiviswanathan/net-qualcomm-rmnet-Enable-csum-offloads/20171228-041216
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)


vim +187 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c

   106  
   107  #if IS_ENABLED(CONFIG_IPV6)
   108  static int
   109  rmnet_map_ipv6_dl_csum_trailer(struct sk_buff *skb,
   110 struct rmnet_map_dl_csum_trailer 
*csum_trailer)
   111  {
   112  u16 ip_pseudo_payload_csum, pseudo_csum, ip6_hdr_csum, 
*csum_field;
   113  u16 csum_value, ip6_payload_csum, csum_value_final;
   114  struct ipv6hdr *ip6h;
   115  void *txporthdr;
   116  u32 length;
   117  
   118  ip6h = (struct ipv6hdr *)(skb->data);
   119  
   120  txporthdr = skb->data + sizeof(struct ipv6hdr);
   121  csum_field = rmnet_map_get_csum_field(ip6h->nexthdr, txporthdr);
   122  
   123  if (!csum_field)
   124  return -EPROTONOSUPPORT;
   125  
   126  csum_value = ~ntohs(csum_trailer->csum_value);
   127  ip6_hdr_csum = ~ntohs(ip_compute_csum(ip6h,
   128(int)(txporthdr - (void *)(skb->data;
   129  ip6_payload_csum = csum16_sub(csum_value, ip6_hdr_csum);
   130  
   131  length = (ip6h->nexthdr == IPPROTO_UDP) ?
   132   ntohs(((struct udphdr *)txporthdr)->len) :
   133   ntohs(ip6h->payload_len);
   134  pseudo_csum = ~ntohs(csum_ipv6_magic(>saddr, >daddr,
   135   length, ip6h->nexthdr, 0));
   136  ip_pseudo_payload_csum = csum16_add(ip6_payload_csum, 
pseudo_csum);
   137  
 > 138  csum_value_final = ~csum16_sub(ip_pseudo_payload_csum,
 > 139 ntohs(*csum_field));
   140  
   141  if (unlikely(csum_value_final == 0)) {
   142  switch (ip6h->nexthdr) {
   143  case IPPROTO_UDP:
   144  /* RFC 2460 section 8.1
   145   * DL6 One's complement rule for UDP checksum 0
   146   */
   147  csum_value_final = ~csum_value_final;
   148  break;
   149  
   150  case IPPROTO_TCP:
   151  /* DL6 Non-RFC compliant TCP checksum found */
   152  if (*csum_field == 0x)
   153  csum_value_final = ~csum_value_final;
   154  break;
   155  }
   156  }
   157  
   158  if (csum_value_final == ntohs(*csum_field))
   159  return 0;
   160  else
   161  return -EINVAL;
   162  }
   163  #endif
   164  
   165  static void rmnet_map_complement_ipv4_txporthdr_csum_field(void *iphdr)
   166  {
   167  struct iphdr *ip4h = (struct iphdr *)iphdr;
   168  void *txphdr;
   169  u16 *csum;
   170  
   171  txphdr = iphdr + ip4h->ihl * 4;
   172  
   173  if (ip4h->protocol == IPPROTO_TCP || ip4h->protocol == 
IPPROTO_UDP) {
   174  csum = (u16 *)rmnet_map_get_csum_field(ip4h->protocol, 
txphdr);
   175  *csum = ~(*csum);
   176  }
   177  }
   178  
   179  static void
   180  rmnet_map_ipv4_ul_csum_header(void *iphdr,
   181struct rmnet_map_ul_csum_header 
*ul_header,
   182struct sk_buff *skb)
   183  {
   184  struct iphdr *ip4h = (struct iphdr *)iphdr;
   185  u16 *hdr = (u16 *)ul_header;
   186  
 > 187  ul_header->csum_start_offset = 
 > htons((u16)(skb_transport_header(skb) -
   188 (unsigned char 
*)iphdr));
   189  ul_header->csum_insert_offset = skb->csum_offset;
   190  ul_header->csum_enabled = 1;
   191  if (ip4h->protocol == IPPROTO_UDP)
   192  ul_header->udp_ip4_ind = 1;
   193  else
   194  ul_header->udp_ip4_ind = 0;
   195  
   196  /* Changing remaining fields to network order */
   197  hdr++;
 > 198  *hdr = htons(*hdr);
   199  
   200  skb->ip_summed = CHECKSUM_NONE;
   201  
   202  rmnet_map_complement_ipv4_txporthdr_csum_field(iphdr);
   203  }
   204  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


[PATCH net-next 09/10] net: qualcomm: rmnet: Add support for TX checksum offload

2017-12-26 Thread Subash Abhinov Kasiviswanathan
TX checksum offload applies to TCP / UDP packets which are not
fragmented using the MAPv4 checksum header. The following needs to be
done to have checksum computed in hardware -

1. Set the checksum start offset and inset offset.
2. Set the csum_enabled bit
3. Compute and set 1's complement of partial checksum field in
   transport header.

If TX checksum offload is disabled, all the fields in the checksum
header are set 0 and hardware will not perform any computation.

Signed-off-by: Subash Abhinov Kasiviswanathan 
---
 .../net/ethernet/qualcomm/rmnet/rmnet_handlers.c   |   8 ++
 drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h|   2 +
 .../net/ethernet/qualcomm/rmnet/rmnet_map_data.c   | 118 +
 drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c|   1 +
 4 files changed, 129 insertions(+)

diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c 
b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
index 3409458..601edec 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
@@ -141,11 +141,19 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
additional_header_len = 0;
required_headroom = sizeof(struct rmnet_map_header);
 
+   if (port->data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV4) {
+   additional_header_len = sizeof(struct rmnet_map_ul_csum_header);
+   required_headroom += additional_header_len;
+   }
+
if (skb_headroom(skb) < required_headroom) {
if (pskb_expand_head(skb, required_headroom, 0, GFP_KERNEL))
goto fail;
}
 
+   if (port->data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV4)
+   rmnet_map_checksum_uplink_packet(skb, orig_dev);
+
map_header = rmnet_map_add_map_header(skb, additional_header_len, 0);
if (!map_header)
goto fail;
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h 
b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
index 0539d99..c635dd7 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
@@ -89,5 +89,7 @@ struct rmnet_map_header *rmnet_map_add_map_header(struct 
sk_buff *skb,
  int hdrlen, int pad);
 void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port);
 int rmnet_map_checksum_downlink_packet(struct sk_buff *skb, u16 len);
+void rmnet_map_checksum_uplink_packet(struct sk_buff *skb,
+ struct net_device *orig_dev);
 
 #endif /* _RMNET_MAP_H_ */
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c 
b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
index 543e423..56923a5 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
@@ -162,6 +162,84 @@ static u16 *rmnet_map_get_csum_field(unsigned char 
protocol,
 }
 #endif
 
+static void rmnet_map_complement_ipv4_txporthdr_csum_field(void *iphdr)
+{
+   struct iphdr *ip4h = (struct iphdr *)iphdr;
+   void *txphdr;
+   u16 *csum;
+
+   txphdr = iphdr + ip4h->ihl * 4;
+
+   if (ip4h->protocol == IPPROTO_TCP || ip4h->protocol == IPPROTO_UDP) {
+   csum = (u16 *)rmnet_map_get_csum_field(ip4h->protocol, txphdr);
+   *csum = ~(*csum);
+   }
+}
+
+static void
+rmnet_map_ipv4_ul_csum_header(void *iphdr,
+ struct rmnet_map_ul_csum_header *ul_header,
+ struct sk_buff *skb)
+{
+   struct iphdr *ip4h = (struct iphdr *)iphdr;
+   u16 *hdr = (u16 *)ul_header;
+
+   ul_header->csum_start_offset = htons((u16)(skb_transport_header(skb) -
+  (unsigned char *)iphdr));
+   ul_header->csum_insert_offset = skb->csum_offset;
+   ul_header->csum_enabled = 1;
+   if (ip4h->protocol == IPPROTO_UDP)
+   ul_header->udp_ip4_ind = 1;
+   else
+   ul_header->udp_ip4_ind = 0;
+
+   /* Changing remaining fields to network order */
+   hdr++;
+   *hdr = htons(*hdr);
+
+   skb->ip_summed = CHECKSUM_NONE;
+
+   rmnet_map_complement_ipv4_txporthdr_csum_field(iphdr);
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static void rmnet_map_complement_ipv6_txporthdr_csum_field(void *ip6hdr)
+{
+   struct ipv6hdr *ip6h = (struct ipv6hdr *)ip6hdr;
+   void *txphdr;
+   u16 *csum;
+
+   txphdr = ip6hdr + sizeof(struct ipv6hdr);
+
+   if (ip6h->nexthdr == IPPROTO_TCP || ip6h->nexthdr == IPPROTO_UDP) {
+   csum = (u16 *)rmnet_map_get_csum_field(ip6h->nexthdr, txphdr);
+   *csum = ~(*csum);
+   }
+}
+
+static void
+rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
+ struct rmnet_map_ul_csum_header *ul_header,
+ struct sk_buff *skb)
+{
+   u16