Merge "[qca-nss-drv] Add H2N component of nss-host test"
diff --git a/exports/arch/nss_fsm9010.h b/exports/arch/nss_fsm9010.h
new file mode 100644
index 0000000..b135bd5
--- /dev/null
+++ b/exports/arch/nss_fsm9010.h
@@ -0,0 +1,35 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/**
+ * @file nss_fsm9010.h
+ *	Architecture dependent parameters.
+ */
+#ifndef __NSS_FSM9010_H
+#define __NSS_FSM9010_H
+
+/**
+ * @addtogroup nss_fsm9010_subsystem
+ * @{
+ */
+
+#define NSS_MAX_NUM_PRI 1		/**< Maximum number of priority queues in NSS. */
+
+/**
+ * @}
+ */
+
+#endif /** __NSS_FSM9010_H */
diff --git a/exports/arch/nss_ipq40xx.h b/exports/arch/nss_ipq40xx.h
new file mode 100644
index 0000000..f02e263
--- /dev/null
+++ b/exports/arch/nss_ipq40xx.h
@@ -0,0 +1,35 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/**
+ * @file nss_ipq40xx.h
+ *	Architecture dependent parameters.
+ */
+#ifndef __NSS_IPQ40XX_H
+#define __NSS_IPQ40XX_H
+
+/**
+ * @addtogroup nss_ipq40xx_subsystem
+ * @{
+ */
+
+#define NSS_MAX_NUM_PRI 1		/**< Maximum number of priority queues in NSS. */
+
+/**
+ * @}
+ */
+
+#endif /** __NSS_IPQ40XX_H */
diff --git a/exports/arch/nss_ipq806x.h b/exports/arch/nss_ipq806x.h
new file mode 100644
index 0000000..be08896
--- /dev/null
+++ b/exports/arch/nss_ipq806x.h
@@ -0,0 +1,35 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/**
+ * @file nss_ipq806x.h
+ *	Architecture dependent parameters.
+ */
+#ifndef __NSS_IPQ806X_H
+#define __NSS_IPQ806X_H
+
+/**
+ * @addtogroup nss_ipq806x_subsystem
+ * @{
+ */
+
+#define NSS_MAX_NUM_PRI 1		/**< Maximum number of priority queues in NSS. */
+
+/**
+ * @}
+ */
+
+#endif /** __NSS_IPQ806X_H */
diff --git a/exports/arch/nss_ipq807x.h b/exports/arch/nss_ipq807x.h
new file mode 100644
index 0000000..dc50d54
--- /dev/null
+++ b/exports/arch/nss_ipq807x.h
@@ -0,0 +1,35 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/**
+ * @file nss_ipq807x.h
+ *	Architecture dependent parameters.
+ */
+#ifndef __NSS_IPQ807X_H
+#define __NSS_IPQ807X_H
+
+/**
+ * @addtogroup nss_ipq807x_subsystem
+ * @{
+ */
+
+#define NSS_MAX_NUM_PRI 4		/**< Maximum number of priority queues in NSS. */
+
+/**
+ * @}
+ */
+
+#endif /** __NSS_IPQ807X_H */
diff --git a/exports/arch/nss_ipq807x_64.h b/exports/arch/nss_ipq807x_64.h
new file mode 100644
index 0000000..b9887d1
--- /dev/null
+++ b/exports/arch/nss_ipq807x_64.h
@@ -0,0 +1,35 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/**
+ * @file nss_ipq807x_64.h
+ *	Architecture dependent parameters.
+ */
+#ifndef __NSS_IPQ807x_64_H
+#define __NSS_IPQ807x_64_H
+
+/**
+ * @addtogroup nss_ipq807x_subsystem
+ * @{
+ */
+
+#define NSS_MAX_NUM_PRI 4		/**< Maximum number of priority queues in NSS. */
+
+/**
+ * @}
+ */
+
+#endif /** __NSS_IPQ807x_64_H */
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 9f58580..5330f2d 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -28,6 +28,7 @@
 #include <linux/if_ether.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include "nss_arch.h"
 #include "nss_def.h"
 #include "nss_cmn.h"
 #include "nss_tun6rd.h"
diff --git a/exports/nss_cmn.h b/exports/nss_cmn.h
index 017c6cf..fcad572 100644
--- a/exports/nss_cmn.h
+++ b/exports/nss_cmn.h
@@ -166,11 +166,11 @@
  *	Common per-node statistics.
  */
 struct nss_cmn_node_stats {
-	uint32_t rx_packets;	/**< Number of packets received. */
-	uint32_t rx_bytes;	/**< Number of bytes received. */
-	uint32_t rx_dropped;	/**< Dropped packets received because the queue is full. */
-	uint32_t tx_packets;	/**< Number of packets transmitted. */
-	uint32_t tx_bytes;	/**< Number of bytes transmitted. */
+	uint32_t rx_packets;			/**< Number of packets received. */
+	uint32_t rx_bytes;			/**< Number of bytes received. */
+	uint32_t tx_packets;			/**< Number of packets transmitted. */
+	uint32_t tx_bytes;			/**< Number of bytes transmitted. */
+	uint32_t rx_dropped[NSS_MAX_NUM_PRI];	/**< Packets dropped on receive due to queue full. */
 };
 
 /**
@@ -344,6 +344,20 @@
  */
 extern bool nss_cmn_get_nss_enabled(void);
 
+/**
+ * nss_cmn_rx_dropped_sum
+ *	Sums dropped packet count of all NSS pnode queues.
+ *
+ * @datatypes
+ * nss_cmn_node_stats \n
+ *
+ * @param[in] node_stats  Pointer to node statistics.
+ *
+ * @return
+ * Total dropped packets count.
+ */
+extern uint32_t nss_cmn_rx_dropped_sum(struct nss_cmn_node_stats *node_stats);
+
 #endif /* __KERNEL__ */
 
 /**
diff --git a/exports/nss_n2h.h b/exports/nss_n2h.h
index 3feb76b..bf28312 100644
--- a/exports/nss_n2h.h
+++ b/exports/nss_n2h.h
@@ -29,9 +29,6 @@
 
 #define MAX_PAGES_PER_MSG 32	/**< Maximum number of pages per message. */
 
-#define NSS_MAX_NUM_PRI 4		/**< Maximum number of pnode ingress priorities. */
-#define NSS_DEFAULT_QUEUE_LIMIT 256	/**< Default NSS packet queue limit. */
-
 /**
  * nss_n2h_payload_info
  *	Payload configuration based on the watermark.
diff --git a/nss_cmn.c b/nss_cmn.c
index 9a7b9f4..bd6766c 100644
--- a/nss_cmn.c
+++ b/nss_cmn.c
@@ -164,6 +164,20 @@
 }
 
 /*
+ * nss_cmn_rx_dropped_sum()
+ *	Sum rx_dropped count.
+ */
+uint32_t nss_cmn_rx_dropped_sum(struct nss_cmn_node_stats *node_stats)
+{
+	uint32_t sum = 0;
+	int i;
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		sum += node_stats->rx_dropped[i];
+	}
+	return sum;
+}
+
+/*
  * nss_cmn_register_queue_decongestion()
  *	Register for queue decongestion event
  */
@@ -247,8 +261,8 @@
 EXPORT_SYMBOL(nss_cmn_interface_is_redirect);
 EXPORT_SYMBOL(nss_cmn_msg_init);
 EXPORT_SYMBOL(nss_cmn_get_interface_number_by_dev);
+EXPORT_SYMBOL(nss_cmn_rx_dropped_sum);
 
 EXPORT_SYMBOL(nss_cmn_register_queue_decongestion);
 EXPORT_SYMBOL(nss_cmn_unregister_queue_decongestion);
 EXPORT_SYMBOL(nss_cmn_get_nss_enabled);
-
diff --git a/nss_core.c b/nss_core.c
index cfcfe27..cab289d 100644
--- a/nss_core.c
+++ b/nss_core.c
@@ -31,6 +31,8 @@
 
 #define NSS_CORE_JUMBO_LINEAR_BUF_SIZE 128
 
+#define NSS_DEFAULT_QUEUE_LIMIT 256	/* Default NSS packet queue limit. */
+
 #if (NSS_SKB_RECYCLE_SUPPORT == 1)
 /*
  * We have validated the skb recycling code within the NSS for the
@@ -61,8 +63,7 @@
 module_param(pn_mq_en, bool, S_IRUGO);
 MODULE_PARM_DESC(pn_mq_en, "Enable pnode ingress QoS");
 
-uint16_t pn_qlimits[NSS_MAX_NUM_PRI] = { NSS_DEFAULT_QUEUE_LIMIT, NSS_DEFAULT_QUEUE_LIMIT,
-					       NSS_DEFAULT_QUEUE_LIMIT, NSS_DEFAULT_QUEUE_LIMIT};
+uint16_t pn_qlimits[NSS_MAX_NUM_PRI] = {[0 ... NSS_MAX_NUM_PRI - 1] = NSS_DEFAULT_QUEUE_LIMIT};
 module_param_array(pn_qlimits, short, NULL, 0);
 MODULE_PARM_DESC(pn_qlimits, "Queue limit per queue");
 
@@ -547,6 +548,7 @@
 	printk("\tbuffer_len = %d\n", desc->buffer_len);
 	printk("\tpayload_offs = %d\n", desc->payload_offs);
 	printk("\tpayload_len = %d\n", desc->payload_len);
+	printk("\tpri = %d\n", desc->pri);
 }
 
 /*
@@ -935,6 +937,7 @@
 		 */
 		nbuf->data_len = payload_len;
 		nbuf->len = payload_len;
+		nbuf->priority = desc->pri;
 		goto pull;
 	}
 
@@ -964,6 +967,7 @@
 		__skb_fill_page_desc(nbuf, 0, skb_frag_page(&skb_shinfo(nbuf)->frags[0]), payload_offs, payload_len);
 		nbuf->data_len = payload_len;
 		nbuf->len = payload_len;
+		nbuf->priority = desc->pri;
 
 		/*
 		 * Set jumbo pointer to nbuf
@@ -1065,6 +1069,8 @@
 			*head_ptr = NULL;
 		}
 
+		nbuf->priority = desc->pri;
+
 		/*
 		 * TODO: Check if there is any issue wrt map and unmap,
 		 * NSS should playaround with data area and should not
@@ -1111,6 +1117,7 @@
 		skb_frag_list_init(nbuf);
 		nbuf->data_len = 0;
 		nbuf->truesize = desc->payload_len;
+		nbuf->priority = desc->pri;
 
 		*head_ptr = nbuf;
 
diff --git a/nss_core.h b/nss_core.h
index b25bb37..4f2aa1d 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -495,12 +495,18 @@
 					/* Accelerated node RX packets */
 	NSS_STATS_NODE_RX_BYTES,
 					/* Accelerated node RX bytes */
-	NSS_STATS_NODE_RX_DROPPED,
-					/* Accelerated node RX dropped */
 	NSS_STATS_NODE_TX_PKTS,
 					/* Accelerated node TX packets */
 	NSS_STATS_NODE_TX_BYTES,
 					/* Accelerated node TX bytes */
+	NSS_STATS_NODE_RX_QUEUE_0_DROPPED,
+					/* Accelerated node RX Queue 0 dropped */
+	NSS_STATS_NODE_RX_QUEUE_1_DROPPED,
+					/* Accelerated node RX Queue 1 dropped */
+	NSS_STATS_NODE_RX_QUEUE_2_DROPPED,
+					/* Accelerated node RX Queue 2 dropped */
+	NSS_STATS_NODE_RX_QUEUE_3_DROPPED,
+					/* Accelerated node RX Queue 3 dropped */
 	NSS_STATS_NODE_MAX,
 };
 
@@ -562,7 +568,10 @@
  */
 enum nss_stats_wifi {
 	NSS_STATS_WIFI_RX_PKTS,				/* Number of packets enqueud to wifi */
-	NSS_STATS_WIFI_RX_DROPPED,			/* Number of packet dropped during enqueue to wifi */
+	NSS_STATS_WIFI_RX_QUEUE_0_DROPPED,		/* Number of packet dropped during enqueue to wifi queue 0 */
+	NSS_STATS_WIFI_RX_QUEUE_1_DROPPED,		/* Number of packet dropped during enqueue to wifi queue 1 */
+	NSS_STATS_WIFI_RX_QUEUE_2_DROPPED,		/* Number of packet dropped during enqueue to wifi queue 2 */
+	NSS_STATS_WIFI_RX_QUEUE_3_DROPPED,		/* Number of packet dropped during enqueue to wifi queue 3 */
 	NSS_STATS_WIFI_TX_PKTS,				/* Number of packets transmited out to wifi */
 	NSS_STATS_WIFI_TX_DROPPED,			/* Number of packets dropped during transmission */
 	NSS_STATS_WIFI_TX_COMPLETED,			/* Number of packets for which transmission completion received */
@@ -765,12 +774,18 @@
 	NSS_STATS_PPTP_ENCAP_RX_BYTES,
 	NSS_STATS_PPTP_ENCAP_TX_PACKETS,
 	NSS_STATS_PPTP_ENCAP_TX_BYTES,
-	NSS_STATS_PPTP_ENCAP_RX_DROP,
+	NSS_STATS_PPTP_ENCAP_RX_QUEUE_0_DROP,
+	NSS_STATS_PPTP_ENCAP_RX_QUEUE_1_DROP,
+	NSS_STATS_PPTP_ENCAP_RX_QUEUE_2_DROP,
+	NSS_STATS_PPTP_ENCAP_RX_QUEUE_3_DROP,
 	NSS_STATS_PPTP_DECAP_RX_PACKETS,
 	NSS_STATS_PPTP_DECAP_RX_BYTES,
 	NSS_STATS_PPTP_DECAP_TX_PACKETS,
 	NSS_STATS_PPTP_DECAP_TX_BYTES,
-	NSS_STATS_PPTP_DECAP_RX_DROP,
+	NSS_STATS_PPTP_DECAP_RX_QUEUE_0_DROP,
+	NSS_STATS_PPTP_DECAP_RX_QUEUE_1_DROP,
+	NSS_STATS_PPTP_DECAP_RX_QUEUE_2_DROP,
+	NSS_STATS_PPTP_DECAP_RX_QUEUE_3_DROP,
 	NSS_STATS_PPTP_SESSION_ENCAP_HEADROOM_ERR,
 	NSS_STATS_PPTP_SESSION_ENCAP_SMALL_SIZE,
 	NSS_STATS_PPTP_SESSION_ENCAP_PNODE_ENQUEUE_FAIL,
@@ -1963,7 +1978,6 @@
 extern int32_t nss_core_send_buffer(struct nss_ctx_instance *nss_ctx, uint32_t if_num,
 					struct sk_buff *nbuf, uint16_t qid,
 					uint8_t buffer_type, uint16_t flags);
-extern void nss_wq_function( struct work_struct *work);
 extern uint32_t nss_core_register_handler(struct nss_ctx_instance *nss_ctx, uint32_t interface, nss_core_rx_callback_t cb, void *app_data);
 extern uint32_t nss_core_unregister_handler(struct nss_ctx_instance *nss_ctx, uint32_t interface);
 void nss_core_update_max_ipv4_conn(int conn);
diff --git a/nss_dtls.c b/nss_dtls.c
index 8c22983..6fcd88b 100644
--- a/nss_dtls.c
+++ b/nss_dtls.c
@@ -82,7 +82,9 @@
 
 	s->stats[NSS_STATS_DTLS_SESSION_RX_PKTS] += stats_msg->node_stats.rx_packets;
 	s->stats[NSS_STATS_DTLS_SESSION_TX_PKTS] += stats_msg->node_stats.tx_packets;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_DROPPED] += stats_msg->node_stats.rx_dropped;
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		s->stats[NSS_STATS_DTLS_SESSION_RX_QUEUE_0_DROPPED + i] += stats_msg->node_stats.rx_dropped[i];
+	}
 	s->stats[NSS_STATS_DTLS_SESSION_RX_AUTH_DONE] += stats_msg->rx_auth_done;
 	s->stats[NSS_STATS_DTLS_SESSION_TX_AUTH_DONE] += stats_msg->tx_auth_done;
 	s->stats[NSS_STATS_DTLS_SESSION_RX_CIPHER_DONE] += stats_msg->rx_cipher_done;
diff --git a/nss_dtls_stats.h b/nss_dtls_stats.h
index 94b2da5..e8da83a 100644
--- a/nss_dtls_stats.h
+++ b/nss_dtls_stats.h
@@ -22,7 +22,10 @@
 			/* Rx packets */
 	NSS_STATS_DTLS_SESSION_TX_PKTS,
 			/* Tx packets */
-	NSS_STATS_DTLS_SESSION_RX_DROPPED,
+	NSS_STATS_DTLS_SESSION_RX_QUEUE_0_DROPPED,
+	NSS_STATS_DTLS_SESSION_RX_QUEUE_1_DROPPED,
+	NSS_STATS_DTLS_SESSION_RX_QUEUE_2_DROPPED,
+	NSS_STATS_DTLS_SESSION_RX_QUEUE_3_DROPPED,
 			/* Rx dropped */
 	NSS_STATS_DTLS_SESSION_RX_AUTH_DONE,
 			/* Rx successful authentication */
@@ -101,4 +104,3 @@
  * Stats APIs provided by nss_dtls.c
  */
 extern void nss_dtls_session_debug_stats_get(struct nss_stats_dtls_session_debug *s);
-
diff --git a/nss_edma.c b/nss_edma.c
index ed63365..bfcca62 100644
--- a/nss_edma.c
+++ b/nss_edma.c
@@ -33,7 +33,7 @@
  */
 static void nss_edma_metadata_port_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_port_stats_sync *nepss)
 {
-	uint16_t i, j = 0;
+	int i;
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 
 	spin_lock_bh(&nss_top->stats_lock);
@@ -43,16 +43,20 @@
 	 * We process a subset of port stats since msg payload is not enough to hold all ports at once.
 	 */
 	for (i = nepss->start_port; i < nepss->end_port; i++) {
-		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_RX_PKTS] += nepss->port_stats[j].node_stats.rx_packets;
-		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_RX_BYTES] += nepss->port_stats[j].node_stats.rx_bytes;
-		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_RX_DROPPED] += nepss->port_stats[j].node_stats.rx_dropped;
-		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_TX_PKTS] += nepss->port_stats[j].node_stats.tx_packets;
-		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_TX_BYTES] += nepss->port_stats[j].node_stats.tx_bytes;
+		int k;
 
-		nss_top->stats_edma.port[i].port_type = nepss->port_stats[j].port_type;
-		nss_top->stats_edma.port[i].port_ring_map[NSS_EDMA_PORT_RX_RING] = nepss->port_stats[j].edma_rx_ring;
-		nss_top->stats_edma.port[i].port_ring_map[NSS_EDMA_PORT_TX_RING] = nepss->port_stats[j].edma_tx_ring;
-		j++;
+		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_RX_PKTS] += nepss->port_stats[i].node_stats.rx_packets;
+		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_RX_BYTES] += nepss->port_stats[i].node_stats.rx_bytes;
+		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_TX_PKTS] += nepss->port_stats[i].node_stats.tx_packets;
+		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_TX_BYTES] += nepss->port_stats[i].node_stats.tx_bytes;
+
+		for (k = 0; k < NSS_MAX_NUM_PRI; k++) {
+			nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_RX_QUEUE_0_DROPPED + k] += nepss->port_stats[i].node_stats.rx_dropped[k];
+		}
+
+		nss_top->stats_edma.port[i].port_type = nepss->port_stats[i].port_type;
+		nss_top->stats_edma.port[i].port_ring_map[NSS_EDMA_PORT_RX_RING] = nepss->port_stats[i].edma_rx_ring;
+		nss_top->stats_edma.port[i].port_ring_map[NSS_EDMA_PORT_TX_RING] = nepss->port_stats[i].edma_tx_ring;
 	}
 
 	spin_unlock_bh(&nss_top->stats_lock);
@@ -64,7 +68,7 @@
  */
 static void nss_edma_metadata_ring_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_ring_stats_sync *nerss)
 {
-	int32_t i;
+	int i;
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 
 	spin_lock_bh(&nss_top->stats_lock);
diff --git a/nss_eth_rx.c b/nss_eth_rx.c
index 17a30fd..2ac5687 100644
--- a/nss_eth_rx.c
+++ b/nss_eth_rx.c
@@ -33,17 +33,20 @@
  */
 static void nss_eth_rx_metadata_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_eth_rx_node_sync *nens)
 {
-	int32_t i;
+	int i;
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 
 	spin_lock_bh(&nss_top->stats_lock);
 
 	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nens->node_stats.rx_packets;
 	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nens->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nens->node_stats.rx_dropped;
 	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nens->node_stats.tx_packets;
 	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nens->node_stats.tx_bytes;
 
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nens->node_stats.rx_dropped[i];
+	}
+
 	nss_top->stats_eth_rx[NSS_STATS_ETH_RX_TOTAL_TICKS] += nens->total_ticks;
 	nss_top->stats_eth_rx[NSS_STATS_ETH_RX_WORST_CASE_TICKS] += nens->worst_case_ticks;
 	nss_top->stats_eth_rx[NSS_STATS_ETH_RX_ITERATIONS] += nens->iterations;
diff --git a/nss_freq.c b/nss_freq.c
index 9990076..d21903a 100644
--- a/nss_freq.c
+++ b/nss_freq.c
@@ -292,7 +292,7 @@
 		return false;
 	}
 
-	INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
+	INIT_WORK((struct work_struct *)nss_work, nss_hal_wq_function);
 
 	nss_work->frequency = nss_runtime_samples.freq_scale[index].frequency;
 
diff --git a/nss_gre_redir.c b/nss_gre_redir.c
index 3ad469a..1ff3106 100644
--- a/nss_gre_redir.c
+++ b/nss_gre_redir.c
@@ -32,7 +32,7 @@
  */
 static void nss_gre_redir_tunnel_update_stats(struct nss_ctx_instance *nss_ctx, int if_num, struct nss_gre_redir_stats_sync_msg *ngss)
 {
-	int i;
+	int i, j;
 
 	spin_lock_bh(&nss_gre_redir_stats_lock);
 	for (i = 0; i < NSS_GRE_REDIR_MAX_INTERFACES; i++) {
@@ -42,7 +42,9 @@
 			tun_stats[i].node_stats.rx_bytes += ngss->node_stats.rx_bytes;
 			tun_stats[i].node_stats.tx_packets += ngss->node_stats.tx_packets;
 			tun_stats[i].node_stats.tx_bytes += ngss->node_stats.tx_bytes;
-			tun_stats[i].node_stats.rx_dropped += ngss->node_stats.rx_dropped;
+			for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+				tun_stats[i].node_stats.rx_dropped[j] += ngss->node_stats.rx_dropped[j];
+			}
 			tun_stats[i].tx_dropped += ngss->tx_dropped;
 
 			break;
@@ -51,7 +53,6 @@
 	spin_unlock_bh(&nss_gre_redir_stats_lock);
 }
 
-
 /*
  * nss_gre_redir_handler()
  * 	Handle NSS -> HLOS messages for gre tunnel
diff --git a/nss_gre_tunnel.c b/nss_gre_tunnel.c
index cdff637..e515fcc 100644
--- a/nss_gre_tunnel.c
+++ b/nss_gre_tunnel.c
@@ -79,7 +79,9 @@
 
 	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_PKTS] += stats_msg->node_stats.rx_packets;
 	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_TX_PKTS] += stats_msg->node_stats.tx_packets;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_DROPPED] += stats_msg->node_stats.rx_dropped;
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_0_DROPPED + i] += stats_msg->node_stats.rx_dropped[i];
+	}
 	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_MALFORMED] += stats_msg->rx_malformed;
 	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_INVALID_PROT] += stats_msg->rx_invalid_prot;
 	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_DECAP_QUEUE_FULL] += stats_msg->decap_queue_full;
diff --git a/nss_gre_tunnel_stats.h b/nss_gre_tunnel_stats.h
index eca49e2..623f11d 100644
--- a/nss_gre_tunnel_stats.h
+++ b/nss_gre_tunnel_stats.h
@@ -20,7 +20,10 @@
 enum nss_stats_gre_tunnel_session {
 	NSS_STATS_GRE_TUNNEL_SESSION_RX_PKTS,
 	NSS_STATS_GRE_TUNNEL_SESSION_TX_PKTS,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_DROPPED,
+	NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_0_DROPPED,
+	NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_1_DROPPED,
+	NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_2_DROPPED,
+	NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_3_DROPPED,
 	NSS_STATS_GRE_TUNNEL_SESSION_RX_MALFORMED,
 	NSS_STATS_GRE_TUNNEL_SESSION_RX_INVALID_PROT,
 	NSS_STATS_GRE_TUNNEL_SESSION_DECAP_QUEUE_FULL,
diff --git a/nss_hal/fsm9010/nss_hal_pvt.c b/nss_hal/fsm9010/nss_hal_pvt.c
index acb80e2..d5f2b33 100644
--- a/nss_hal/fsm9010/nss_hal_pvt.c
+++ b/nss_hal/fsm9010/nss_hal_pvt.c
@@ -41,6 +41,18 @@
 				(1 << NSS_H2N_INTR_TRIGGER_COREDUMP_BIT)};
 
 /*
+ * nss_hal_wq_function()
+ *	Added to Handle BH requests to kernel
+ */
+void nss_hal_wq_function(struct work_struct *work)
+{
+	/*
+	 * Not supported in FSM9010
+	 */
+	kfree((void *)work);
+}
+
+/*
  * nss_hal_get_num_irqs()
  *	get number of irqs from interrupt resource of device tree
  */
diff --git a/nss_hal/include/nss_hal.h b/nss_hal/include/nss_hal.h
index 6484919..e16f975 100644
--- a/nss_hal/include/nss_hal.h
+++ b/nss_hal/include/nss_hal.h
@@ -32,6 +32,7 @@
 extern struct nss_runtime_sampling nss_runtime_samples;
 extern struct clk *nss_fab0_clk;
 extern struct clk *nss_fab1_clk;
+extern void nss_hal_wq_function(struct work_struct *work);
 
 #if defined(NSS_HAL_IPQ806X_SUPPORT)
 extern struct nss_hal_ops nss_hal_ipq806x_ops;
diff --git a/nss_hal/ipq806x/nss_hal_pvt.c b/nss_hal/ipq806x/nss_hal_pvt.c
index 0bbf49c..e49364d 100644
--- a/nss_hal/ipq806x/nss_hal_pvt.c
+++ b/nss_hal/ipq806x/nss_hal_pvt.c
@@ -59,6 +59,10 @@
 				(1 << NSS_H2N_INTR_TRIGGER_COREDUMP_BIT),
 				(1 << NSS_H2N_INTR_EMPTY_PAGED_BUFFER_QUEUE_BIT)};
 
+#if (NSS_DT_SUPPORT == 1)
+bool nss_crypto_is_scaled = false;
+#endif
+
 #if (NSS_FW_DBG_SUPPORT == 1)
 /*
  * NSS debug pins configuration
@@ -180,6 +184,121 @@
 #endif /* NSS_FW_DBG_SUPPORT */
 
 /*
+ * nss_hal_scale_fabric()
+ *	DT supported fabric scaling
+ */
+void nss_hal_scale_fabric(uint32_t work_frequency)
+{
+#if (NSS_DT_SUPPORT == 1)
+	nss_crypto_pm_event_callback_t crypto_pm_cb;
+	bool auto_scale;
+	bool turbo;
+
+#if (NSS_FABRIC_SCALING_SUPPORT == 1)
+	/*
+	 * PM framework
+	 */
+	scale_fabrics();
+#endif
+	if ((nss_fab0_clk != NULL) && (nss_fab1_clk != NULL)) {
+		if (work_frequency >= NSS_FREQ_733) {
+			clk_set_rate(nss_fab0_clk, NSS_FABRIC0_TURBO);
+			clk_set_rate(nss_fab1_clk, NSS_FABRIC1_TURBO);
+		} else if (work_frequency > NSS_FREQ_110) {
+			clk_set_rate(nss_fab0_clk, NSS_FABRIC0_NOMINAL);
+			clk_set_rate(nss_fab1_clk, NSS_FABRIC1_NOMINAL);
+		} else {
+			clk_set_rate(nss_fab0_clk, NSS_FABRIC0_IDLE);
+			clk_set_rate(nss_fab1_clk, NSS_FABRIC1_IDLE);
+		}
+
+		/*
+		 * notify crypto about the clock change
+		 */
+		crypto_pm_cb = nss_top_main.crypto_pm_callback;
+		if (crypto_pm_cb) {
+			turbo = (work_frequency >= NSS_FREQ_733);
+			auto_scale = nss_cmd_buf.auto_scale;
+			nss_crypto_is_scaled = crypto_pm_cb(nss_top_main.crypto_pm_ctx, turbo, auto_scale);
+		}
+	}
+#endif
+}
+
+/*
+ * nss_hal_pm_support()
+ *	Supported in 3.4
+ */
+void nss_hal_pm_support(uint32_t work_frequency)
+{
+#if (NSS_PM_SUPPORT == 1)
+	if (!pm_client) {
+		return;
+	}
+
+	if (work_frequency >= NSS_FREQ_733) {
+		nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
+	} else if (work_frequency > NSS_FREQ_110) {
+		nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
+	} else {
+		nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
+	}
+#endif
+}
+
+/*
+ * nss_hal_freq_change()
+ *	Send frequency change message, and clock adjustment
+ */
+void nss_hal_freq_change(nss_work_t *my_work)
+{
+	nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 0);
+	if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
+		nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 0);
+	}
+	clk_set_rate(nss_core0_clk, my_work->frequency);
+
+	nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 1);
+	if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
+		nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 1);
+	}
+}
+
+/*
+ * nss_hal_wq_function()
+ *	Added to Handle BH requests to kernel
+ */
+void nss_hal_wq_function(struct work_struct *work)
+{
+	nss_work_t *my_work = (nss_work_t *)work;
+
+	mutex_lock(&nss_top_main.wq_lock);
+#if (NSS_DT_SUPPORT == 1)
+	/*
+	 * If crypto clock is in Turbo, disable scaling for other
+	 * NSS subsystem components and retain them at turbo
+	 */
+	if (nss_crypto_is_scaled) {
+		nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency;
+		mutex_unlock(&nss_top_main.wq_lock);
+		return;
+	}
+#endif
+
+	nss_hal_freq_change(my_work);
+
+	/*
+	 * Supported in 3.4
+	 */
+	nss_hal_pm_support(my_work->frequency);
+
+	nss_hal_scale_fabric(my_work->frequency);
+
+	mutex_unlock(&nss_top_main.wq_lock);
+	kfree((void *)work);
+}
+
+/*
  * nss_hal_handle_irq()
  *	HLOS interrupt handler for nss interrupts
  */
diff --git a/nss_hal/ipq807x/nss_hal_pvt.c b/nss_hal/ipq807x/nss_hal_pvt.c
index 5d80e9e..b81ef1b 100644
--- a/nss_hal/ipq807x/nss_hal_pvt.c
+++ b/nss_hal/ipq807x/nss_hal_pvt.c
@@ -26,6 +26,7 @@
 #include <linux/of_net.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
+#include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 #include "nss_hal.h"
 #include "nss_core.h"
@@ -63,6 +64,17 @@
 #define NSS_NC_AXI_CLK "nss-nc-axi-clk"
 
 /*
+ * Voltage values
+ */
+#define NOMINAL_VOLTAGE 1
+#define TURBO_VOLTAGE 2
+
+/*
+ * Voltage regulator
+ */
+struct regulator *npu_reg;
+
+/*
  * Purpose of each interrupt index: This should match the order defined in the NSS firmware
  */
 enum nss_hal_n2h_intr_purpose {
@@ -97,6 +109,40 @@
 };
 
 /*
+ * nss_hal_wq_function()
+ *	Added to Handle BH requests to kernel
+ */
+void nss_hal_wq_function(struct work_struct *work)
+{
+	nss_work_t *my_work = (nss_work_t *)work;
+
+	mutex_lock(&nss_top_main.wq_lock);
+
+	if (my_work->frequency > NSS_FREQ_1497) {
+		regulator_set_voltage(npu_reg, TURBO_VOLTAGE, TURBO_VOLTAGE);
+	}
+
+	nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 0);
+	if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
+		nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 0);
+	}
+	clk_set_rate(nss_core0_clk, my_work->frequency);
+
+	nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 1);
+	if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
+		nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 1);
+	}
+
+	clk_set_rate(nss_core1_clk, my_work->frequency);
+	if (my_work->frequency <= NSS_FREQ_1497) {
+		regulator_set_voltage(npu_reg, NOMINAL_VOLTAGE, NOMINAL_VOLTAGE);
+	}
+
+	mutex_unlock(&nss_top_main.wq_lock);
+	kfree((void *)work);
+}
+
+/*
  * nss_hal_handle_irq()
  */
 static irqreturn_t nss_hal_handle_irq(int irq, void *ctx)
@@ -423,6 +469,23 @@
 		return -EFAULT;
 	}
 
+
+	/*
+	 * For IPQ807x, any rate above 1497 is Turbo Voltage
+	 * Temporary set the voltage to turbo till we start scaling frequenices.
+	 * This is to ensure probing is safe and autoscaling will correct the voltage.
+	 */
+	if (!nss_ctx->id) {
+		npu_reg = devm_regulator_get(&nss_dev->dev, "npu");
+		if (IS_ERR(npu_reg)) {
+			return PTR_ERR(npu_reg);
+		}
+		if (regulator_enable(npu_reg)) {
+			return -EFAULT;
+		}
+		regulator_set_voltage(npu_reg, TURBO_VOLTAGE, TURBO_VOLTAGE);
+	}
+
 	/*
 	 * No entries, then just load default
 	 */
@@ -432,6 +495,7 @@
 		nss_runtime_samples.freq_scale[NSS_FREQ_LOW_SCALE].frequency = NSS_FREQ_187;
 		nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency = NSS_FREQ_748;
 		nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency = NSS_FREQ_1497;
+		nss_info_always("Running default frequencies\n");
 	}
 
 	/*
@@ -460,7 +524,7 @@
 			nss_runtime_samples.freq_scale[i].minimum = NSS_FREQ_1689_MIN;
 			nss_runtime_samples.freq_scale[i].maximum = NSS_FREQ_1689_MAX;
 		} else {
-			nss_info_always("Frequency not found %d", nss_runtime_samples.freq_scale[i].frequency);
+			nss_info_always("Frequency not found %d\n", nss_runtime_samples.freq_scale[i].frequency);
 			return -EFAULT;
 		}
 
@@ -483,7 +547,7 @@
 		} else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_1689) {
 			nss_info_always("1.689 GHz ");
 		} else {
-			nss_info_always("Error\nNo Table/Invalid Frequency Found");
+			nss_info_always("Error\nNo Table/Invalid Frequency Found\n");
 			return -EFAULT;
 		}
 	}
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index ad0766d..401f12e 100644
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -393,7 +393,8 @@
 	uint16_t bit_flags;	/* Bit flags associated with the buffer */
 	uint8_t buffer_type;	/* Type of buffer */
 	uint8_t response_type;	/* Response type if the buffer is a command response */
-	uint16_t reserved[3];	/* Reserved for future use */
+	uint8_t pri;		/* Packet priority */
+	uint8_t reserved[5];	/* Reserved for future use */
 	nss_ptr_t opaque;	/* 32 or 64-bit value provided by the HLOS to associate with the buffer. The cookie has no meaning to the NSS */
 #ifndef __LP64__
 	uint32_t padding;	/* Pad to fit 64 bits, do not reuse */
diff --git a/nss_init.c b/nss_init.c
index 046c592..82dbbf4 100644
--- a/nss_init.c
+++ b/nss_init.c
@@ -81,7 +81,6 @@
 #if (NSS_DT_SUPPORT == 1)
 struct clk *nss_fab0_clk;
 struct clk *nss_fab1_clk;
-bool nss_crypto_is_scaled = false;
 #endif
 
 /*
@@ -151,7 +150,7 @@
  * nss_reset_frequency_stats_samples()
  *	Reset all frequency sampling state when auto scaling is turned off.
  */
-static void nss_reset_frequency_stats_samples (void)
+static void nss_reset_frequency_stats_samples(void)
 {
 	nss_runtime_samples.buffer_index = 0;
 	nss_runtime_samples.sum = 0;
@@ -162,104 +161,6 @@
 }
 
 /*
- ***************************************************************************************************
- * nss_wq_function() is used to queue up requests to change NSS frequencies.
- * The function will take care of NSS notices and also control clock.
- * The auto rate algorithmn will queue up requests or the procfs may also queue up these requests.
- ***************************************************************************************************
- */
-
-/*
- * nss_wq_function()
- *	Added to Handle BH requests to kernel
- */
-void nss_wq_function (struct work_struct *work)
-{
-	nss_work_t *my_work = (nss_work_t *)work;
-#if (NSS_DT_SUPPORT == 1)
-	nss_crypto_pm_event_callback_t crypto_pm_cb;
-	bool auto_scale;
-	bool turbo;
-
-	mutex_lock(&nss_top_main.wq_lock);
-	/*
-	 * If crypto clock is in Turbo, disable scaling for other
-	 * NSS subsystem components and retain them at turbo
-	 */
-	if (nss_crypto_is_scaled) {
-		nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency;
-		mutex_unlock(&nss_top_main.wq_lock);
-		return;
-	}
-#endif
-
-	nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 0);
-	if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
-		nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 0);
-	}
-	clk_set_rate(nss_core0_clk, my_work->frequency);
-
-	nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 1);
-	if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
-		nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 1);
-	}
-#if defined(NSS_HAL_IPQ807x_SUPPORT)
-	clk_set_rate(nss_core1_clk, my_work->frequency);
-#endif
-
-/*
- * If we are running NSS_PM_SUPPORT, we are on banana
- * otherwise, we check if we are are on new kernel by checking if the
- * fabric lookups are not NULL (success in init()))
- */
-#if (NSS_PM_SUPPORT == 1)
-	if (!pm_client) {
-		goto out;
-	}
-
-	if (my_work->frequency >= NSS_FREQ_733) {
-		nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
-	} else if (my_work->frequency > NSS_FREQ_110) {
-		nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
-	} else {
-		nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
-	}
-
-out:
-#else
-#if (NSS_DT_SUPPORT == 1)
-#if (NSS_FABRIC_SCALING_SUPPORT == 1)
-	scale_fabrics();
-#endif
-	if ((nss_fab0_clk != NULL) && (nss_fab1_clk != NULL)) {
-		if (my_work->frequency >= NSS_FREQ_733) {
-			clk_set_rate(nss_fab0_clk, NSS_FABRIC0_TURBO);
-			clk_set_rate(nss_fab1_clk, NSS_FABRIC1_TURBO);
-		} else if (my_work->frequency > NSS_FREQ_110) {
-			clk_set_rate(nss_fab0_clk, NSS_FABRIC0_NOMINAL);
-			clk_set_rate(nss_fab1_clk, NSS_FABRIC1_NOMINAL);
-		} else {
-			clk_set_rate(nss_fab0_clk, NSS_FABRIC0_IDLE);
-			clk_set_rate(nss_fab1_clk, NSS_FABRIC1_IDLE);
-		}
-
-		/*
-		 * notify crypto about the clock change
-		 */
-		crypto_pm_cb = nss_top_main.crypto_pm_callback;
-		if (crypto_pm_cb) {
-			turbo = (my_work->frequency >= NSS_FREQ_733);
-			auto_scale = nss_cmd_buf.auto_scale;
-			nss_crypto_is_scaled = crypto_pm_cb(nss_top_main.crypto_pm_ctx, turbo, auto_scale);
-		}
-	}
-#endif
-#endif
-	mutex_unlock(&nss_top_main.wq_lock);
-	kfree((void *)work);
-}
-
-/*
  * nss_current_freq_handler()
  *	Handle Userspace Frequency Change Requests
  */
@@ -305,7 +206,7 @@
 		nss_info("NSS Freq WQ kmalloc fail");
 		return ret;
 	}
-	INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
+	INIT_WORK((struct work_struct *)nss_work, nss_hal_wq_function);
 	nss_work->frequency = nss_cmd_buf.current_freq;
 	nss_work->stats_enable = 0;
 
@@ -345,7 +246,7 @@
 				nss_info("NSS Freq WQ kmalloc fail");
 				return ret;
 			}
-			INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
+			INIT_WORK((struct work_struct *)nss_work, nss_hal_wq_function);
 			nss_work->frequency = nss_cmd_buf.current_freq;
 			nss_work->stats_enable = 0;
 			queue_work(nss_wq, (struct work_struct *)nss_work);
@@ -378,7 +279,7 @@
 		nss_info("NSS Freq WQ kmalloc fail");
 		return ret;
 	}
-	INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
+	INIT_WORK((struct work_struct *)nss_work, nss_hal_wq_function);
 	nss_work->frequency = nss_cmd_buf.current_freq;
 	nss_work->stats_enable = 1;
 	queue_work(nss_wq, (struct work_struct *)nss_work);
diff --git a/nss_ipv4.c b/nss_ipv4.c
index 8b0e5cb..c655a35 100644
--- a/nss_ipv4.c
+++ b/nss_ipv4.c
@@ -141,7 +141,7 @@
 static void nss_ipv4_driver_node_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_node_sync *nins)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	uint32_t i;
+	int i;
 
 	/*
 	 * Update statistics maintained by NSS driver
@@ -149,10 +149,13 @@
 	spin_lock_bh(&nss_top->stats_lock);
 	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets;
 	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nins->node_stats.rx_dropped;
 	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets;
 	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes;
 
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nins->node_stats.rx_dropped[i];
+	}
+
 	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_REQUESTS] += nins->ipv4_connection_create_requests;
 	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_COLLISIONS] += nins->ipv4_connection_create_collisions;
 	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv4_connection_create_invalid_interface;
@@ -715,7 +718,6 @@
 	{ }
 };
 
-
 static struct ctl_table nss_ipv4_root_dir[] = {
 	{
 		.procname		= "nss",
diff --git a/nss_ipv4_reasm.c b/nss_ipv4_reasm.c
index 043dcc2..80a230f 100644
--- a/nss_ipv4_reasm.c
+++ b/nss_ipv4_reasm.c
@@ -26,6 +26,7 @@
  */
 static void nss_ipv4_reasm_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_reasm_stats_sync *nirs)
 {
+	int i;
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 
 	spin_lock_bh(&nss_top->stats_lock);
@@ -35,10 +36,13 @@
 	 */
 	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nirs->node_stats.rx_packets;
 	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nirs->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nirs->node_stats.rx_dropped;
 	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nirs->node_stats.tx_packets;
 	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nirs->node_stats.tx_bytes;
 
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nirs->node_stats.rx_dropped[0];
+	}
+
 	/*
 	 * IPv4 reasm node stats
 	 */
diff --git a/nss_ipv6.c b/nss_ipv6.c
index 44920ea..5273dca 100644
--- a/nss_ipv6.c
+++ b/nss_ipv6.c
@@ -140,7 +140,7 @@
 static void nss_ipv6_driver_node_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_node_sync *nins)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	uint32_t i;
+	int i;
 
 	/*
 	 * Update statistics maintained by NSS driver
@@ -148,10 +148,13 @@
 	spin_lock_bh(&nss_top->stats_lock);
 	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets;
 	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nins->node_stats.rx_dropped;
 	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets;
 	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes;
 
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nins->node_stats.rx_dropped[i];
+	}
+
 	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_CREATE_REQUESTS] += nins->ipv6_connection_create_requests;
 	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_CREATE_COLLISIONS] += nins->ipv6_connection_create_collisions;
 	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv6_connection_create_invalid_interface;
diff --git a/nss_ipv6_reasm.c b/nss_ipv6_reasm.c
index 002bb82..b818be3 100644
--- a/nss_ipv6_reasm.c
+++ b/nss_ipv6_reasm.c
@@ -27,6 +27,7 @@
 static void nss_ipv6_reasm_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_reasm_stats_sync *nirs)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
 
 	spin_lock_bh(&nss_top->stats_lock);
 
@@ -35,10 +36,13 @@
 	 */
 	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nirs->node_stats.rx_packets;
 	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nirs->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nirs->node_stats.rx_dropped;
 	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nirs->node_stats.tx_packets;
 	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nirs->node_stats.tx_bytes;
 
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nirs->node_stats.rx_dropped[j];
+	}
+
 	/*
 	 * IPv6 reasm node stats
 	 */
diff --git a/nss_lso_rx.c b/nss_lso_rx.c
index 5d3b012..fb961ae 100644
--- a/nss_lso_rx.c
+++ b/nss_lso_rx.c
@@ -28,6 +28,7 @@
 static void nss_rx_lso_rx_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_lso_rx_stats_sync *nlrss)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
 
 	spin_lock_bh(&nss_top->stats_lock);
 
@@ -36,10 +37,13 @@
 	 */
 	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nlrss->node_stats.rx_packets;
 	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nlrss->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nlrss->node_stats.rx_dropped;
 	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nlrss->node_stats.tx_packets;
 	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nlrss->node_stats.tx_bytes;
 
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nlrss->node_stats.rx_dropped[j];
+	}
+
 	/*
 	 * General LSO_RX stats
 	 */
diff --git a/nss_n2h.c b/nss_n2h.c
index 6acf338..3d6d303 100644
--- a/nss_n2h.c
+++ b/nss_n2h.c
@@ -58,6 +58,7 @@
 static void nss_n2h_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_n2h_stats_sync *nnss)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
 
 	spin_lock_bh(&nss_top->stats_lock);
 
@@ -66,10 +67,13 @@
 	 */
 	nss_ctx->stats_n2h[NSS_STATS_NODE_RX_PKTS] += nnss->node_stats.rx_packets;
 	nss_ctx->stats_n2h[NSS_STATS_NODE_RX_BYTES] += nnss->node_stats.rx_bytes;
-	nss_ctx->stats_n2h[NSS_STATS_NODE_RX_DROPPED] += nnss->node_stats.rx_dropped;
 	nss_ctx->stats_n2h[NSS_STATS_NODE_TX_PKTS] += nnss->node_stats.tx_packets;
 	nss_ctx->stats_n2h[NSS_STATS_NODE_TX_BYTES] += nnss->node_stats.tx_bytes;
 
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_ctx->stats_n2h[NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nnss->node_stats.rx_dropped[j];
+	}
+
 	/*
 	 * General N2H stats
 	 */
@@ -1099,6 +1103,14 @@
 		return NSS_TX_SUCCESS;
 	}
 
+	/*
+	 * MQ mode doesnot make any sense if number of priority queues in NSS
+	 * is 1
+	 */
+	if (NSS_MAX_NUM_PRI <= 1) {
+		return NSS_TX_SUCCESS;
+	}
+
 	memset(&nnm, 0, sizeof(struct nss_n2h_msg));
 
 	nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
@@ -1141,6 +1153,14 @@
 		return NSS_TX_SUCCESS;
 	}
 
+	/*
+	 * MQ mode doesnot make any sense if number of priority queues in NSS
+	 * is 1
+	 */
+	if (NSS_MAX_NUM_PRI <= 1) {
+		return NSS_TX_SUCCESS;
+	}
+
 	memset(&nnm, 0, sizeof(struct nss_n2h_msg));
 
 	nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
diff --git a/nss_portid.c b/nss_portid.c
index 2ad46d5..3476a44 100644
--- a/nss_portid.c
+++ b/nss_portid.c
@@ -49,6 +49,7 @@
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 	struct nss_portid_handle *hdl;
+	int j;
 
 	if (npsm->port_id == NSS_PORTID_MAX_SWITCH_PORT) {
 		/*
@@ -57,9 +58,13 @@
 		spin_lock_bh(&nss_top->stats_lock);
 		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_PKTS] += npsm->node_stats.rx_packets;
 		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_BYTES] += npsm->node_stats.rx_bytes;
-		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += npsm->node_stats.rx_dropped;
 		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_TX_PKTS] += npsm->node_stats.tx_packets;
 		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_TX_BYTES] += npsm->node_stats.tx_bytes;
+
+		for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+			nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += npsm->node_stats.rx_dropped[j];
+		}
+
 		nss_top->stats_portid[NSS_STATS_PORTID_RX_INVALID_HEADER] += npsm->rx_invalid_header;
 		spin_unlock_bh(&nss_top->stats_lock);
 		return;
@@ -82,7 +87,7 @@
 	}
 	hdl->stats.rx_packets += npsm->node_stats.rx_packets;
 	hdl->stats.rx_bytes += npsm->node_stats.rx_bytes;
-	hdl->stats.rx_dropped += npsm->node_stats.rx_dropped;
+	hdl->stats.rx_dropped += nss_cmn_rx_dropped_sum(&npsm->node_stats);
 	hdl->stats.tx_packets += npsm->node_stats.tx_packets;
 	hdl->stats.tx_bytes += npsm->node_stats.tx_bytes;
 	spin_unlock_bh(&nss_portid_spinlock);
@@ -118,7 +123,6 @@
 	 */
 	nss_core_log_msg_failures(nss_ctx, ncm);
 
-
 	switch (ncm->type) {
 	case NSS_PORTID_STATS_SYNC_MSG:
 		/*
diff --git a/nss_pppoe.c b/nss_pppoe.c
index d8b4398..43a1946 100644
--- a/nss_pppoe.c
+++ b/nss_pppoe.c
@@ -147,15 +147,19 @@
 static void nss_pppoe_node_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_node_stats_sync_msg *npess)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
 
 	spin_lock_bh(&nss_top->stats_lock);
 
 	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += npess->node_stats.rx_packets;
 	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += npess->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += npess->node_stats.rx_dropped;
 	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += npess->node_stats.tx_packets;
 	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += npess->node_stats.tx_bytes;
 
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += npess->node_stats.rx_dropped[j];
+	}
+
 	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_REQUESTS] += npess->pppoe_session_create_requests;
 	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_FAILURES] += npess->pppoe_session_create_failures;
 	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
@@ -228,4 +232,3 @@
 {
 	nss_cmn_msg_init(&npm->cm, if_num, type, len, (void *)cb, app_data);
 }
-
diff --git a/nss_pptp.c b/nss_pptp.c
index cade98d..dc66b14 100644
--- a/nss_pptp.c
+++ b/nss_pptp.c
@@ -42,7 +42,7 @@
  */
 void nss_pptp_session_debug_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pptp_sync_session_stats_msg *stats_msg, uint16_t if_num)
 {
-	int i;
+	int i, j;
 	spin_lock_bh(&nss_pptp_session_debug_stats_lock);
 	for (i = 0; i < NSS_MAX_PPTP_DYNAMIC_INTERFACES; i++) {
 		if (nss_pptp_session_debug_stats[i].if_num == if_num) {
@@ -50,12 +50,16 @@
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_RX_BYTES] += stats_msg->encap_stats.rx_bytes;
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_TX_PACKETS] += stats_msg->encap_stats.tx_packets;
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_TX_BYTES] += stats_msg->encap_stats.tx_bytes;
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_RX_DROP] += stats_msg->encap_stats.rx_dropped;
+			for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+				nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_RX_QUEUE_0_DROP + j] += stats_msg->encap_stats.rx_dropped[j];
+			}
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_RX_PACKETS] += stats_msg->decap_stats.rx_packets;
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_RX_BYTES] += stats_msg->decap_stats.rx_bytes;
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_TX_PACKETS] += stats_msg->decap_stats.tx_packets;
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_TX_BYTES] += stats_msg->decap_stats.tx_bytes;
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_RX_DROP] += stats_msg->decap_stats.rx_dropped;
+			for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+				nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_RX_QUEUE_0_DROP + j] += stats_msg->decap_stats.rx_dropped[j];
+			}
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_ENCAP_HEADROOM_ERR] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_ENCAP_HEADROOM_ERR];
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_ENCAP_SMALL_SIZE] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_ENCAP_SMALL_SIZE];
 			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_ENCAP_PNODE_ENQUEUE_FAIL] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_ENCAP_PNODE_ENQUEUE_FAIL];
diff --git a/nss_sjack.c b/nss_sjack.c
index d2eceab..84b5f92 100644
--- a/nss_sjack.c
+++ b/nss_sjack.c
@@ -23,6 +23,7 @@
 static void nss_sjack_node_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_sjack_stats_sync_msg *nins)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
 
 	/*
 	 * Update SJACK node stats.
@@ -30,9 +31,13 @@
 	spin_lock_bh(&nss_top->stats_lock);
 	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets;
 	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nins->node_stats.rx_dropped;
 	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets;
 	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes;
+
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nins->node_stats.rx_dropped[j];
+	}
+
 	spin_unlock_bh(&nss_top->stats_lock);
 }
 
@@ -100,7 +105,6 @@
 	cb(ctx, ncm);
 }
 
-
 /*
  * nss_sjack_tx_msg()
  * 	Transmit a sjack message to NSSFW
diff --git a/nss_stats.c b/nss_stats.c
index 90f2e68..6d4ea03 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -23,6 +23,7 @@
 #include "nss_core.h"
 #include "nss_dtls_stats.h"
 #include "nss_gre_tunnel_stats.h"
+#include "nss_tx_rx_common.h"
 
 /*
  * Maximum string length:
@@ -296,9 +297,12 @@
 static int8_t *nss_stats_str_node[NSS_STATS_NODE_MAX] = {
 	"rx_packets",
 	"rx_bytes",
-	"rx_dropped",
 	"tx_packets",
-	"tx_bytes"
+	"tx_bytes",
+	"rx_queue_0_dropped",
+	"rx_queue_1_dropped",
+	"rx_queue_2_dropped",
+	"rx_queue_3_dropped",
 };
 
 /*
@@ -482,7 +486,10 @@
  */
 static int8_t *nss_stats_str_wifi[NSS_STATS_WIFI_MAX] = {
 	"RX_PACKETS",
-	"RX_DROPPED",
+	"RX_QUEUE_0_DROPPED",
+	"RX_QUEUE_1_DROPPED",
+	"RX_QUEUE_2_DROPPED",
+	"RX_QUEUE_3_DROPPED",
 	"TX_PACKETS",
 	"TX_DROPPED",
 	"TX_TRANSMIT_COMPLETED",
@@ -672,7 +679,10 @@
 static int8_t *nss_stats_str_dtls_session_debug_stats[NSS_STATS_DTLS_SESSION_MAX] = {
 	"RX_PKTS",
 	"TX_PKTS",
-	"RX_DROPPED",
+	"RX_QUEUE_0_DROPPED",
+	"RX_QUEUE_1_DROPPED",
+	"RX_QUEUE_2_DROPPED",
+	"RX_QUEUE_3_DROPPED",
 	"RX_AUTH_DONE",
 	"TX_AUTH_DONE",
 	"RX_CIPHER_DONE",
@@ -712,7 +722,10 @@
 static int8_t *nss_stats_str_gre_tunnel_session_debug_stats[NSS_STATS_GRE_TUNNEL_SESSION_MAX] = {
 	"RX_PKTS",
 	"TX_PKTS",
-	"RX_DROPPED",
+	"RX_QUEUE_0_DROPPED",
+	"RX_QUEUE_1_DROPPED",
+	"RX_QUEUE_2_DROPPED",
+	"RX_QUEUE_3_DROPPED",
 	"RX_MALFORMED",
 	"RX_INVALID_PROT",
 	"DECAP_QUEUE_FULL",
@@ -1178,12 +1191,18 @@
 	"ENCAP_RX_BYTES",
 	"ENCAP_TX_PACKETS",
 	"ENCAP_TX_BYTES",
-	"ENCAP_RX_DROP",
+	"ENCAP_RX_QUEUE_0_DROP",
+	"ENCAP_RX_QUEUE_1_DROP",
+	"ENCAP_RX_QUEUE_2_DROP",
+	"ENCAP_RX_QUEUE_3_DROP",
 	"DECAP_RX_PACKETS",
 	"DECAP_RX_BYTES",
 	"DECAP_TX_PACKETS",
 	"DECAP_TX_BYTES",
-	"DECAP_RX_DROP",
+	"DECAP_RX_QUEUE_0_DROP",
+	"DECAP_RX_QUEUE_1_DROP",
+	"DECAP_RX_QUEUE_2_DROP",
+	"DECAP_RX_QUEUE_3_DROP",
 	"ENCAP_HEADROOM_ERR",
 	"ENCAP_SMALL_SIZE",
 	"ENCAP_PNODE_ENQUEUE_FAIL",
@@ -3799,33 +3818,33 @@
  */
 static ssize_t nss_stats_gre_redir(char *line, int len, int i, struct nss_gre_redir_tunnel_stats *s)
 {
-	char *header[] = { "TX Packets", "TX Bytes", "TX Drops", "RX Packets", "RX Bytes", "Rx Drops" };
+	char *header[] = { "TX Packets", "TX Bytes", "TX Drops", "RX Packets", "RX Bytes" };
+	char name[20];
 	uint64_t tcnt = 0;
+	int j = 0;
 
 	switch (i) {
 	case 0:
-		tcnt = s->node_stats.tx_packets;
-		break;
+		return snprintf(line, len, "%s = %u\n", header[i], s->node_stats.tx_packets);
 	case 1:
-		tcnt = s->node_stats.tx_bytes;
-		break;
+		return snprintf(line, len, "%s = %u\n", header[i], s->node_stats.tx_bytes);
 	case 2:
-		tcnt = s->tx_dropped;
-		break;
+		return snprintf(line, len, "%s = %u\n", header[i], s->tx_dropped);
 	case 3:
-		tcnt = s->node_stats.rx_packets;
-		break;
+		return snprintf(line, len, "%s = %u\n", header[i], s->node_stats.rx_packets);
 	case 4:
-		tcnt = s->node_stats.rx_bytes;
-		break;
+		return snprintf(line, len, "%s = %u\n", header[i], s->node_stats.rx_bytes);
 	case 5:
-		tcnt = s->node_stats.rx_dropped;
-		break;
+		for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+			scnprintf(name, 20, "Rx Queue %d Drops", j);
+			tcnt += snprintf(line, len, "%s = %u\n", name, s->node_stats.rx_dropped[j]);
+		}
+		return tcnt;
+
 	default:
 		return 0;
 	}
 
-	return (snprintf(line, len, "%s = %llu\n", header[i], tcnt));
 }
 
 /*
@@ -3838,7 +3857,7 @@
 	ssize_t bytes_read = 0;
 	struct nss_gre_redir_tunnel_stats stats;
 	size_t bytes;
-	char line[80];
+	char line[80 * NSS_MAX_NUM_PRI];
 	int start, end;
 	int index = 0;
 
@@ -4557,7 +4576,6 @@
 	struct dentry *core_dentry = NULL;
 	struct dentry *wt_dentry = NULL;
 
-
 	char file_name[10];
 
 	/*
diff --git a/nss_trustsec_tx.c b/nss_trustsec_tx.c
index 348eb1b..f9f181b 100644
--- a/nss_trustsec_tx.c
+++ b/nss_trustsec_tx.c
@@ -34,6 +34,7 @@
 static void nss_trustsec_tx_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_trustsec_tx_stats_sync_msg *ntsm)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
 
 	/*
 	 * Update common node stats
@@ -41,10 +42,13 @@
 	spin_lock_bh(&nss_top->stats_lock);
 	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += ntsm->node_stats.rx_packets;
 	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += ntsm->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += ntsm->node_stats.rx_dropped;
 	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += ntsm->node_stats.tx_packets;
 	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += ntsm->node_stats.tx_bytes;
 
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += ntsm->node_stats.rx_dropped[j];
+	}
+
 	/*
 	 * Update trustsec node stats
 	 */
@@ -84,7 +88,6 @@
 	 */
 	nss_core_log_msg_failures(nss_ctx, ncm);
 
-
 	switch (ncm->type) {
 	case NSS_TRUSTSEC_TX_STATS_SYNC_MSG:
 		/*
diff --git a/nss_wifi.c b/nss_wifi.c
index 970a9a6..fab4c7c 100644
--- a/nss_wifi.c
+++ b/nss_wifi.c
@@ -25,7 +25,7 @@
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 	uint32_t radio_id = interface - NSS_WIFI_INTERFACE0;
-	uint8_t i = 0;
+	int i = 0;
 
 	if (radio_id >= NSS_MAX_WIFI_RADIO_INTERFACES) {
 		nss_warning("%p: invalid interface: %d", nss_ctx, interface);
@@ -38,7 +38,9 @@
 	 * Tx/Rx stats
 	 */
 	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_PKTS] += stats->node_stats.rx_packets;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_DROPPED] += stats->node_stats.rx_dropped;
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_QUEUE_0_DROPPED + i] += stats->node_stats.rx_dropped[i];
+	}
 	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TX_PKTS] += stats->node_stats.tx_packets;
 	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TX_DROPPED] += stats->tx_transmit_dropped;
 	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TX_COMPLETED] += stats->tx_transmit_completions;