[qca-nss-sfe] Use HW csum in TX if possible.

Change-Id: I7857b24e1fa0e240a41109b6c4ce0625293a8154
Signed-off-by: Ratheesh Kannoth <quic_rkannoth@quicinc.com>
diff --git a/sfe_ipv4_tcp.c b/sfe_ipv4_tcp.c
index df8df0c..b9dcdce 100644
--- a/sfe_ipv4_tcp.c
+++ b/sfe_ipv4_tcp.c
@@ -127,6 +127,7 @@
 	u32 flags;
 	struct net_device *xmit_dev;
 	bool ret;
+	bool hw_csum;
 
 	/*
 	 * Is our packet too short to contain a valid UDP header?
@@ -496,6 +497,13 @@
 	iph->ttl = ttl - 1;
 
 	/*
+	 * Enable HW csum if rx checksum is verified and xmit interface is CSUM offload capable.
+	 * Note: If L4 csum at Rx was found to be incorrect, we (router) should use incremental L4 checksum here
+	 * so that HW does not re-calculate/replace the L4 csum
+	 */
+	hw_csum = !!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_CSUM_OFFLOAD) && (skb->ip_summed == CHECKSUM_UNNECESSARY);
+
+	/*
 	 * Do we have to perform translations of the source address/port?
 	 */
 	if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) {
@@ -505,19 +513,17 @@
 		iph->saddr = cm->xlate_src_ip;
 		tcph->source = cm->xlate_src_port;
 
-		/*
-		 * Do we have a non-zero UDP checksum?  If we do then we need
-		 * to update it.
-		 */
-		tcp_csum = tcph->check;
-		if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) {
-			sum = tcp_csum + cm->xlate_src_partial_csum_adjustment;
-		} else {
-			sum = tcp_csum + cm->xlate_src_csum_adjustment;
-		}
+		if (unlikely(!hw_csum)) {
+			tcp_csum = tcph->check;
+			if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+				sum = tcp_csum + cm->xlate_src_partial_csum_adjustment;
+			} else {
+				sum = tcp_csum + cm->xlate_src_csum_adjustment;
+			}
 
-		sum = (sum & 0xffff) + (sum >> 16);
-		tcph->check = (u16)sum;
+			sum = (sum & 0xffff) + (sum >> 16);
+			tcph->check = (u16)sum;
+		}
 	}
 
 	/*
@@ -530,25 +536,30 @@
 		iph->daddr = cm->xlate_dest_ip;
 		tcph->dest = cm->xlate_dest_port;
 
-		/*
-		 * Do we have a non-zero UDP checksum?  If we do then we need
-		 * to update it.
-		 */
-		tcp_csum = tcph->check;
-		if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) {
-			sum = tcp_csum + cm->xlate_dest_partial_csum_adjustment;
-		} else {
-			sum = tcp_csum + cm->xlate_dest_csum_adjustment;
-		}
+		if (unlikely(!hw_csum)) {
+			tcp_csum = tcph->check;
+			if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+				sum = tcp_csum + cm->xlate_dest_partial_csum_adjustment;
+			} else {
+				sum = tcp_csum + cm->xlate_dest_csum_adjustment;
+			}
 
-		sum = (sum & 0xffff) + (sum >> 16);
-		tcph->check = (u16)sum;
+			sum = (sum & 0xffff) + (sum >> 16);
+			tcph->check = (u16)sum;
+		}
 	}
 
 	/*
-	 * Replace the IP checksum.
+	 * If HW checksum offload is not possible, full L3 checksum and incremental L4 checksum
+	 * are used to update the packet. Setting ip_summed to CHECKSUM_UNNECESSARY ensures checksum is
+	 * not recalculated further in packet path.
 	 */
-	iph->check = sfe_ipv4_gen_ip_csum(iph);
+	if (likely(hw_csum)) {
+		skb->ip_summed = CHECKSUM_PARTIAL;
+	} else {
+		iph->check = sfe_ipv4_gen_ip_csum(iph);
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	}
 
 	/*
 	 * Update traffic stats.