diff --git a/QDMA/DPDK/RELEASE b/QDMA/DPDK/RELEASE
index d300616eb412fb453b2a7fff2af9dc9e7696643d..806779b5eea6e3270e8f1354a401e05d34ccc456 100755
--- a/QDMA/DPDK/RELEASE
+++ b/QDMA/DPDK/RELEASE
@@ -1,4 +1,4 @@
-RELEASE: 2023.2.0
+RELEASE: 2023.2.1
 =================
 
 This release is based on DPDK v20.11, v21.11 and v22.11 and
@@ -132,6 +132,10 @@ CPM5
 - Added support for Tx and Rx queue statistics to enhance debugging capabilities
 - Added support for latency measurements in Tx and Rx data path to enhance debugging capabilities
 
+2023.2.1 Updates
+----------------
+- Added support for latency measurements in Tx and Rx data path for VF
+
 KNOWN ISSUE:
 ============
 - CPM4:
diff --git a/QDMA/DPDK/drivers/net/qdma/qdma_access/qdma_access_version.h b/QDMA/DPDK/drivers/net/qdma/qdma_access/qdma_access_version.h
index 9503e5abda6dd9a578ff020413b46c7061d35f97..652a5550ffa966500aa816fe479d6876830b792c 100755
--- a/QDMA/DPDK/drivers/net/qdma/qdma_access/qdma_access_version.h
+++ b/QDMA/DPDK/drivers/net/qdma/qdma_access/qdma_access_version.h
@@ -37,7 +37,7 @@
 
 #define QDMA_VERSION_MAJOR	2023
 #define QDMA_VERSION_MINOR	2
-#define QDMA_VERSION_PATCH	0
+#define QDMA_VERSION_PATCH	1
 
 #define QDMA_VERSION_STR	\
 	__stringify(QDMA_VERSION_MAJOR) "." \
diff --git a/QDMA/DPDK/drivers/net/qdma/qdma_ethdev.c b/QDMA/DPDK/drivers/net/qdma/qdma_ethdev.c
index 21b83a8499da76054e280682d5ebc7e6dfc3be2f..6bd6147f7a531ed9fead5b9c11bcdb87f793ce60 100755
--- a/QDMA/DPDK/drivers/net/qdma/qdma_ethdev.c
+++ b/QDMA/DPDK/drivers/net/qdma/qdma_ethdev.c
@@ -772,31 +772,40 @@ int qdma_eth_dev_init(struct rte_eth_dev *dev)
 	}
 
 #ifdef LATENCY_MEASUREMENT
-	/* Create a shared memory zone for the txq latency buffer */
-	txq_lat_buf_mz = rte_memzone_reserve("TXQ_LAT_BUFFER_ZONE",
-		LATENCY_MAX_QUEUES * LATENCY_CNT * sizeof(double),
-		rte_socket_id(), 0);
-	if (txq_lat_buf_mz == NULL) {
-		PMD_DRV_LOG(ERR, "Failed to allocate txq latency buffer memzone\n");
-		return -1;
+	/* Create txq and rxq latency measurement shared memory
+	 * if not already created by the VF
+	 */
+	if (!h2c_pidx_to_hw_cidx_lat) {
+		/* Create a shared memory zone for the txq latency buffer */
+		txq_lat_buf_mz = rte_memzone_reserve("TXQ_LAT_BUFFER_ZONE",
+			LATENCY_MAX_QUEUES * LATENCY_CNT * sizeof(double),
+			rte_socket_id(), 0);
+		if (txq_lat_buf_mz == NULL) {
+			PMD_DRV_LOG(ERR,
+				"Failed to allocate txq latency buffer memzone\n");
+			return -1;
+		}
+
+		/* Get the virtual address of the txq latency buffer */
+		h2c_pidx_to_hw_cidx_lat =
+			(double(*)[LATENCY_CNT])txq_lat_buf_mz->addr;
 	}
 
-	/* Get the virtual address of the txq latency buffer */
-	h2c_pidx_to_hw_cidx_lat =
-		(double(*)[LATENCY_CNT])txq_lat_buf_mz->addr;
+	if (!c2h_pidx_to_cmpt_pidx_lat) {
+		/* Create a shared memory zone for the rxq latency buffer */
+		rxq_lat_buf_mz = rte_memzone_reserve("RXQ_LAT_BUFFER_ZONE",
+			LATENCY_MAX_QUEUES * LATENCY_CNT * sizeof(double),
+			rte_socket_id(), 0);
+		if (rxq_lat_buf_mz == NULL) {
+			PMD_DRV_LOG(ERR,
+				"Failed to allocate rxq latency buffer memzone\n");
+			return -1;
+		}
 
-	/* Create a shared memory zone for the rxq latency buffer */
-	rxq_lat_buf_mz = rte_memzone_reserve("RXQ_LAT_BUFFER_ZONE",
-		LATENCY_MAX_QUEUES * LATENCY_CNT * sizeof(double),
-		rte_socket_id(), 0);
-	if (rxq_lat_buf_mz == NULL) {
-		PMD_DRV_LOG(ERR, "Failed to allocate rxq latency buffer memzone\n");
-		return -1;
+		/* Get the virtual address of the rxq latency buffer */
+		c2h_pidx_to_cmpt_pidx_lat =
+			(double(*)[LATENCY_CNT])rxq_lat_buf_mz->addr;
 	}
-
-	/* Get the virtual address of the rxq latency buffer */
-	c2h_pidx_to_cmpt_pidx_lat =
-		(double(*)[LATENCY_CNT])rxq_lat_buf_mz->addr;
 #endif
 
 	dma_priv->reset_in_progress = 0;
diff --git a/QDMA/DPDK/drivers/net/qdma/qdma_vf_ethdev.c b/QDMA/DPDK/drivers/net/qdma/qdma_vf_ethdev.c
index f055e6d51279ddeb80068ce1edac198f2bfc9d5a..219af04e1c7bb41c837b0bee14c5bc5277b6c632 100755
--- a/QDMA/DPDK/drivers/net/qdma/qdma_vf_ethdev.c
+++ b/QDMA/DPDK/drivers/net/qdma/qdma_vf_ethdev.c
@@ -1144,6 +1144,43 @@ static int eth_qdma_vf_dev_init(struct rte_eth_dev *dev)
 
 	dma_priv->reset_state = RESET_STATE_IDLE;
 
+#ifdef LATENCY_MEASUREMENT
+	/* Create txq and rxq latency measurement shared memory
+	 * if not already created by the PF
+	 */
+	if (!h2c_pidx_to_hw_cidx_lat) {
+		/* Create a shared memory zone for the txq latency buffer */
+		txq_lat_buf_mz = rte_memzone_reserve("TXQ_LAT_BUFFER_ZONE",
+			LATENCY_MAX_QUEUES * LATENCY_CNT * sizeof(double),
+			rte_socket_id(), 0);
+		if (txq_lat_buf_mz == NULL) {
+			PMD_DRV_LOG(ERR,
+				"Failed to allocate txq latency buffer memzone\n");
+			return -1;
+		}
+
+		/* Get the virtual address of the txq latency buffer */
+		h2c_pidx_to_hw_cidx_lat =
+			(double(*)[LATENCY_CNT])txq_lat_buf_mz->addr;
+	}
+
+	if (!c2h_pidx_to_cmpt_pidx_lat) {
+		/* Create a shared memory zone for the rxq latency buffer */
+		rxq_lat_buf_mz = rte_memzone_reserve("RXQ_LAT_BUFFER_ZONE",
+			LATENCY_MAX_QUEUES * LATENCY_CNT * sizeof(double),
+			rte_socket_id(), 0);
+		if (rxq_lat_buf_mz == NULL) {
+			PMD_DRV_LOG(ERR,
+				"Failed to allocate rxq latency buffer memzone\n");
+			return -1;
+		}
+
+		/* Get the virtual address of the rxq latency buffer */
+		c2h_pidx_to_cmpt_pidx_lat =
+			(double(*)[LATENCY_CNT])rxq_lat_buf_mz->addr;
+	}
+#endif
+
 	PMD_DRV_LOG(INFO, "VF-%d(DEVFN) QDMA device driver probe:",
 				dma_priv->func_id);
 
diff --git a/QDMA/DPDK/drivers/net/qdma/qdma_xdebug.c b/QDMA/DPDK/drivers/net/qdma/qdma_xdebug.c
index 1811f21c061311549a4209bff417827fadae9edf..4cade046ed04520c5a5c758919608acf4d9054ee 100755
--- a/QDMA/DPDK/drivers/net/qdma/qdma_xdebug.c
+++ b/QDMA/DPDK/drivers/net/qdma/qdma_xdebug.c
@@ -1283,6 +1283,9 @@ int qdma_tx_qstats_clear(struct rte_eth_dev *dev, uint16_t queue)
 {
 	struct qdma_tx_queue *txq;
 	int ret;
+#ifdef LATENCY_MEASUREMENT
+	int i;
+#endif
 
 	if (queue >= dev->data->nb_tx_queues) {
 		xdebug_info("TX queue_id=%d not configured\n", queue);
@@ -1297,6 +1300,11 @@ int qdma_tx_qstats_clear(struct rte_eth_dev *dev, uint16_t queue)
 
 	memset(&txq->qstats, 0, sizeof(struct qdma_txq_stats));
 
+#ifdef LATENCY_MEASUREMENT
+	for (i = 0; i < LATENCY_CNT; i++)
+		h2c_pidx_to_hw_cidx_lat[queue][i] = 0;
+#endif
+
 	xdebug_info("\nCleared Tx queue stats for  qid: %d\n",
 		queue);
 
@@ -1314,6 +1322,9 @@ int qdma_rx_qstats_clear(struct rte_eth_dev *dev, uint16_t queue)
 {
 	struct qdma_rx_queue *rxq;
 	int ret;
+#ifdef LATENCY_MEASUREMENT
+	int i;
+#endif
 
 	if (queue >= dev->data->nb_rx_queues) {
 		xdebug_info("RX queue_id=%d not configured\n", queue);
@@ -1328,6 +1339,11 @@ int qdma_rx_qstats_clear(struct rte_eth_dev *dev, uint16_t queue)
 
 	memset(&rxq->qstats, 0, sizeof(struct qdma_rxq_stats));
 
+#ifdef LATENCY_MEASUREMENT
+	for (i = 0; i < LATENCY_CNT; i++)
+		c2h_pidx_to_cmpt_pidx_lat[queue][i] = 0;
+#endif
+
 	xdebug_info("\nCleared Rx queue stats for  qid: %d\n",
 		queue);
 
diff --git a/QDMA/DPDK/drivers/net/qdma/version.h b/QDMA/DPDK/drivers/net/qdma/version.h
index e17690d5850feb4707c17d1eaee1985f1fd0b985..8e44e3a2742b8aee437eb6623299c8508d155988 100755
--- a/QDMA/DPDK/drivers/net/qdma/version.h
+++ b/QDMA/DPDK/drivers/net/qdma/version.h
@@ -39,7 +39,7 @@
 
 #define QDMA_PMD_MAJOR		2023
 #define QDMA_PMD_MINOR		2
-#define QDMA_PMD_PATCHLEVEL	0
+#define QDMA_PMD_PATCHLEVEL	1
 
 #define QDMA_PMD_VERSION      \
 	qdma_stringify(QDMA_PMD_MAJOR) "." \
diff --git a/QDMA/DPDK/examples/qdma_testapp/commands.c b/QDMA/DPDK/examples/qdma_testapp/commands.c
index c87bb9bef8b652a11ae4636fa3eef325726af5ba..20e8af7f5d7d1ac363c0636844178ba42e378b6c 100755
--- a/QDMA/DPDK/examples/qdma_testapp/commands.c
+++ b/QDMA/DPDK/examples/qdma_testapp/commands.c
@@ -170,6 +170,10 @@ static void cmd_help_parsed(__attribute__((unused)) void *parsed_result,
 			":Reads the field info for the specified number of registers\n"
 			"\tqueue_dump           <port-id> <queue-id>  "
 			":To dump the queue-context of a queue-number\n"
+			"\tqstats               <port-id> <queue-id>  "
+			":To dump the queue-stats of a queue-number\n"
+			"\tqstats_clr               <port-id> <queue-id>  "
+			":To clear the queue-stats of a queue-number\n"
 			"\tdesc_dump            <port-id> <queue-id>  "
 			":To dump the descriptor-fields of a "
 			"queue-number\n"
@@ -1233,6 +1237,144 @@ cmdline_parse_inst_t cmd_obj_queue_dump = {
 
 };
 
+/*Command queue-stats dump*/
+
+struct cmd_obj_qstats_result {
+	cmdline_fixed_string_t action;
+	cmdline_fixed_string_t port_id;
+	cmdline_fixed_string_t queue_id;
+};
+
+static void cmd_obj_qstats_parsed(void *parsed_result,
+			       struct cmdline *cl,
+			       __attribute__((unused)) void *data)
+{
+	struct cmd_obj_qstats_result *res = parsed_result;
+
+	cmdline_printf(cl, "queue-dump on Port:%s, queue-id:%s\n\n",
+						res->port_id, res->queue_id);
+
+	{
+		int port_id = atoi(res->port_id);
+		int qid = atoi(res->queue_id);
+		int bar_id = 0x0;
+
+		bar_id = pinfo[port_id].config_bar_idx;
+		if (bar_id < 0) {
+			cmdline_printf(cl, "Error: fetching QDMA config BAR-id "
+					"on port-id:%d not supported\n Please "
+					"enter valid port-id\n", port_id);
+			return;
+		}
+		if (port_id >= num_ports) {
+			cmdline_printf(cl, "Error: port-id:%d not supported\n "
+					"Please enter valid port-id\n",
+					port_id);
+			return;
+		}
+		if ((unsigned int)qid >= pinfo[port_id].num_queues) {
+			cmdline_printf(cl, "Error: queue-id:%d is greater than "
+					"the number of confgiured queues in "
+					"the port\n Please enter valid "
+					"queue-id\n", qid);
+			return;
+		}
+		rte_pmd_qdma_qstats(port_id, qid);
+	}
+}
+
+cmdline_parse_token_string_t cmd_obj_action_qstats =
+	TOKEN_STRING_INITIALIZER(struct cmd_obj_qstats_result, action,
+								"qstats");
+cmdline_parse_token_string_t cmd_obj_qstats_port_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_obj_qstats_result, port_id,
+									NULL);
+cmdline_parse_token_string_t cmd_obj_qstats_queue_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_obj_qstats_result, queue_id,
+									NULL);
+
+cmdline_parse_inst_t cmd_obj_qstats = {
+	.f = cmd_obj_qstats_parsed,  /* function to call */
+	.data = NULL,      /* 2nd arg of func */
+	.help_str = "qstats port-id queue_id",
+	.tokens = {        /* token list, NULL terminated */
+		(void *)&cmd_obj_action_qstats,
+		(void *)&cmd_obj_qstats_port_id,
+		(void *)&cmd_obj_qstats_queue_id,
+		NULL,
+	},
+
+};
+
+/*Command queue-stats-cleaar dump*/
+
+struct cmd_obj_qstats_clr_result {
+	cmdline_fixed_string_t action;
+	cmdline_fixed_string_t port_id;
+	cmdline_fixed_string_t queue_id;
+};
+
+static void cmd_obj_qstats_clr_parsed(void *parsed_result,
+			       struct cmdline *cl,
+			       __attribute__((unused)) void *data)
+{
+	struct cmd_obj_qstats_clr_result *res = parsed_result;
+
+	cmdline_printf(cl, "queue-dump on Port:%s, queue-id:%s\n\n",
+						res->port_id, res->queue_id);
+
+	{
+		int port_id = atoi(res->port_id);
+		int qid = atoi(res->queue_id);
+		int bar_id = 0x0;
+
+		bar_id = pinfo[port_id].config_bar_idx;
+		if (bar_id < 0) {
+			cmdline_printf(cl, "Error: fetching QDMA config BAR-id "
+					"on port-id:%d not supported\n Please "
+					"enter valid port-id\n", port_id);
+			return;
+		}
+		if (port_id >= num_ports) {
+			cmdline_printf(cl, "Error: port-id:%d not supported\n "
+					"Please enter valid port-id\n",
+					port_id);
+			return;
+		}
+		if ((unsigned int)qid >= pinfo[port_id].num_queues) {
+			cmdline_printf(cl, "Error: queue-id:%d is greater than "
+					"the number of confgiured queues in "
+					"the port\n Please enter valid "
+					"queue-id\n", qid);
+			return;
+		}
+		rte_pmd_qdma_qstats_clear(port_id, qid);
+	}
+}
+
+cmdline_parse_token_string_t cmd_obj_action_qstats_clr =
+	TOKEN_STRING_INITIALIZER(struct cmd_obj_qstats_clr_result, action,
+								"qstats_clr");
+cmdline_parse_token_string_t cmd_obj_qstats_clr_port_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_obj_qstats_clr_result, port_id,
+									NULL);
+cmdline_parse_token_string_t cmd_obj_qstats_clr_queue_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_obj_qstats_clr_result, queue_id,
+									NULL);
+
+cmdline_parse_inst_t cmd_obj_qstats_clr = {
+	.f = cmd_obj_qstats_clr_parsed,  /* function to call */
+	.data = NULL,      /* 2nd arg of func */
+	.help_str = "qstats_clr port-id queue_id",
+	.tokens = {        /* token list, NULL terminated */
+		(void *)&cmd_obj_action_qstats_clr,
+		(void *)&cmd_obj_qstats_clr_port_id,
+		(void *)&cmd_obj_qstats_clr_queue_id,
+		NULL,
+	},
+
+};
+
 /* Command descriptor dump */
 
 struct cmd_obj_desc_dump_result {
@@ -1375,6 +1517,8 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_obj_reg_dump,
 	(cmdline_parse_inst_t *)&cmd_obj_reg_info_read,
 	(cmdline_parse_inst_t *)&cmd_obj_queue_dump,
+	(cmdline_parse_inst_t *)&cmd_obj_qstats,
+	(cmdline_parse_inst_t *)&cmd_obj_qstats_clr,
 	(cmdline_parse_inst_t *)&cmd_obj_desc_dump,
 	(cmdline_parse_inst_t *)&cmd_obj_load_cmds,
 	(cmdline_parse_inst_t *)&cmd_help,