[qca-edma] Add stats support for per-precedence stats

Add support for per-precedence counters for ingress/egress packets

Change-Id: I230a5e1cee5ea17ae57ade48d1f8984a3e583147
Signed-off-by: Rakesh Nair <ranair@codeaurora.org>
diff --git a/edma.c b/edma.c
index 4e83c2e..3932454 100644
--- a/edma.c
+++ b/edma.c
@@ -15,12 +15,15 @@
 
 #include <linux/platform_device.h>
 #include <linux/if_vlan.h>
+#include <linux/kernel.h>
 #include "ess_edma.h"
 #include "edma.h"
 
 extern struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED];
 bool edma_stp_rstp;
 u16 edma_ath_eth_type;
+extern u8 edma_dscp2ac_tbl[EDMA_PRECEDENCE_MAX];
+extern u8 edma_per_prec_stats_enable;
 
 /* edma_skb_priority_offset()
  *	get edma skb priority
@@ -795,6 +798,14 @@
 				erdr->pending_fill = ret_count;
 			}
 
+			/*
+			 * We increment per-precedence counters for the rx packets
+			 */
+			if (edma_per_prec_stats_enable) {
+				edma_cinfo->edma_ethstats.rx_prec[priority]++;
+				edma_cinfo->edma_ethstats.rx_ac[edma_dscp2ac_tbl[priority]]++;
+			}
+
 			/* At this point skb should go to stack */
 			napi_gro_receive(napi, skb);
 		}
@@ -1372,6 +1383,37 @@
 		}
 	}
 
+	/* If sysctl support for per-precedence stats are enabled */
+	if (edma_per_prec_stats_enable) {
+		struct iphdr *ip_hdr = NULL;
+		struct ipv6hdr *ip6_hdr = NULL;
+		uint8_t precedence = 0xff;
+
+		if (likely(htons(ETH_P_IP) == skb->protocol)) {
+			ip_hdr = (struct iphdr *)skb_network_header(skb);
+			if (ip_hdr && ((ip_hdr->protocol == IPPROTO_UDP) || (ip_hdr->protocol == IPPROTO_TCP)))
+				 precedence = ip_hdr->tos >> EDMA_DSCP_PREC_SHIFT;
+
+			/* Increment per-precedence counters for tx packets
+			 * and set the precedence in the TPD.
+			 */
+			edma_cinfo->edma_ethstats.tx_prec[precedence]++;
+			edma_cinfo->edma_ethstats.tx_ac[edma_dscp2ac_tbl[precedence]]++;
+			tpd->word3 |= precedence << EDMA_TPD_PRIO_SHIFT;
+		} else if (htons(ETH_P_IPV6) == skb->protocol) {
+			ip6_hdr = (struct ipv6hdr *)skb_network_header(skb);
+			if (ip6_hdr && ((ip6_hdr->nexthdr == IPPROTO_UDP) || (ip6_hdr->nexthdr == IPPROTO_TCP)))
+				precedence = ip6_hdr->priority >> EDMA_DSCP6_PREC_SHIFT;
+
+			/* Increment per-precedence counters for tx packets
+			 * and set the precedence in the TPD for v6 packets.
+			 */
+			edma_cinfo->edma_ethstats.tx_prec[precedence]++;
+			edma_cinfo->edma_ethstats.tx_ac[edma_dscp2ac_tbl[precedence]]++;
+			tpd->word3 |= precedence << EDMA_TPD_PRIO_SHIFT;
+		}
+	}
+
 	/* If tpd or sw_desc is still unitiialized then we need to return */
 	if ((!tpd) || (!sw_desc))
 		return -EINVAL;