diff --git a/doc/guides/nics/cxgbe.rst b/doc/guides/nics/cxgbe.rst
index 4b9913669..4a8fef07b 100644
--- a/doc/guides/nics/cxgbe.rst
+++ b/doc/guides/nics/cxgbe.rst
@@ -70,7 +70,7 @@ in :ref:`t5-nics` and :ref:`t6-nics`.
 Prerequisites
 -------------
 
-- Requires firmware version **1.24.17.0** and higher. Visit
+- Requires firmware version **1.25.4.0** and higher. Visit
   `Chelsio Download Center <http://service.chelsio.com>`_ to get latest firmware
   bundled with the latest Chelsio Unified Wire package.
 
@@ -404,7 +404,7 @@ Unified Wire package for Linux operating system are as follows:
 
    .. code-block:: console
 
-      firmware-version: 1.24.17.0, TP 0.1.23.2
+      firmware-version: 1.25.4.0, TP 0.1.23.2
 
 Running testpmd
 ~~~~~~~~~~~~~~~
@@ -462,7 +462,7 @@ devices managed by librte_net_cxgbe in Linux operating system.
       EAL:   PCI memory mapped at 0x7fd7c0200000
       EAL:   PCI memory mapped at 0x7fd77cdfd000
       EAL:   PCI memory mapped at 0x7fd7c10b7000
-      PMD: rte_cxgbe_pmd: fw: 1.24.17.0, TP: 0.1.23.2
+      PMD: rte_cxgbe_pmd: fw: 1.25.4.0, TP: 0.1.23.2
       PMD: rte_cxgbe_pmd: Coming up as MASTER: Initializing adapter
       Interactive-mode selected
       Configuring Port 0 (socket 0)
@@ -568,7 +568,7 @@ virtual functions.
       [...]
       EAL: PCI device 0000:02:01.0 on NUMA socket 0
       EAL:   probe driver: 1425:5803 net_cxgbevf
-      PMD: rte_cxgbe_pmd: Firmware version: 1.24.17.0
+      PMD: rte_cxgbe_pmd: Firmware version: 1.25.4.0
       PMD: rte_cxgbe_pmd: TP Microcode version: 0.1.23.2
       PMD: rte_cxgbe_pmd: Chelsio rev 0
       PMD: rte_cxgbe_pmd: No bootstrap loaded
@@ -576,7 +576,7 @@ virtual functions.
       PMD: rte_cxgbe_pmd:  0000:02:01.0 Chelsio rev 0 1G/10GBASE-SFP
       EAL: PCI device 0000:02:01.1 on NUMA socket 0
       EAL:   probe driver: 1425:5803 net_cxgbevf
-      PMD: rte_cxgbe_pmd: Firmware version: 1.24.17.0
+      PMD: rte_cxgbe_pmd: Firmware version: 1.25.4.0
       PMD: rte_cxgbe_pmd: TP Microcode version: 0.1.23.2
       PMD: rte_cxgbe_pmd: Chelsio rev 0
       PMD: rte_cxgbe_pmd: No bootstrap loaded
@@ -654,7 +654,7 @@ Unified Wire package for FreeBSD operating system are as follows:
 
    .. code-block:: console
 
-      dev.t5nex.0.firmware_version: 1.24.17.0
+      dev.t5nex.0.firmware_version: 1.25.4.0
 
 Running testpmd
 ~~~~~~~~~~~~~~~
@@ -772,7 +772,7 @@ devices managed by librte_net_cxgbe in FreeBSD operating system.
       EAL:   PCI memory mapped at 0x8007ec000
       EAL:   PCI memory mapped at 0x842800000
       EAL:   PCI memory mapped at 0x80086c000
-      PMD: rte_cxgbe_pmd: fw: 1.24.17.0, TP: 0.1.23.2
+      PMD: rte_cxgbe_pmd: fw: 1.25.4.0, TP: 0.1.23.2
       PMD: rte_cxgbe_pmd: Coming up as MASTER: Initializing adapter
       Interactive-mode selected
       Configuring Port 0 (socket 0)
diff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h
index a5a3313c2..01a2a9d14 100644
--- a/drivers/net/cxgbe/base/adapter.h
+++ b/drivers/net/cxgbe/base/adapter.h
@@ -58,6 +58,9 @@ struct port_info {
 	 */
 	u8 vin;
 	u8 vivld;
+
+	u8 vi_en_rx; /* Enable/disable VI Rx */
+	u8 vi_en_tx; /* Enable/disable VI Tx */
 };
 
 enum {                                 /* adapter flags */
@@ -792,6 +795,7 @@ void t4_free_mem(void *addr);
 #define t4_os_free(_ptr)       t4_free_mem((_ptr))
 
 void t4_os_portmod_changed(const struct adapter *adap, int port_id);
+void t4_os_link_changed(struct adapter *adap, int port_id);
 
 void reclaim_completed_tx(struct sge_txq *q);
 void t4_free_sge_resources(struct adapter *adap);
diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h
index 202a2f4ba..8225717ae 100644
--- a/drivers/net/cxgbe/base/common.h
+++ b/drivers/net/cxgbe/base/common.h
@@ -265,6 +265,7 @@ struct adapter_params {
 	u8 filter2_wr_support;            /* FW support for FILTER2_WR */
 	u32 viid_smt_extn_support:1;	  /* FW returns vin and smt index */
 	u32 max_tx_coalesce_num; /* Max # of Tx packets that can be coalesced */
+	u8 vi_enable_rx; /* FW support for enable/disable VI Rx at runtime */
 };
 
 /* Firmware Port Capabilities types.
diff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c
index 0e3033b55..7ebf4a9a7 100644
--- a/drivers/net/cxgbe/base/t4_hw.c
+++ b/drivers/net/cxgbe/base/t4_hw.c
@@ -4595,6 +4595,7 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 		lc->link_ok = link_ok;
 		lc->acaps = acaps;
 		lc->link_caps = link_caps;
+		t4_os_link_changed(adapter, pi->pidx);
 	}
 
 	if (mod_changed) {
diff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h
index 240e0ee49..0310a7ce8 100644
--- a/drivers/net/cxgbe/base/t4fw_interface.h
+++ b/drivers/net/cxgbe/base/t4fw_interface.h
@@ -702,6 +702,7 @@ enum fw_params_param_dev {
 	FW_PARAMS_PARAM_DEV_OPAQUE_VIID_SMT_EXTN = 0x27,
 	FW_PARAMS_PARAM_DEV_HASHFILTER_WITH_OFLD = 0x28,
 	FW_PARAMS_PARAM_DEV_FILTER      = 0x2E,
+	FW_PARAMS_PARAM_DEV_VI_ENABLE_INGRESS_AFTER_LINKUP = 0x32,
 };
 
 /*
diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
index 83ad758e8..c759d97f8 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -1496,6 +1496,10 @@ static int adap_init0(struct adapter *adap)
 	else
 		adap->params.max_tx_coalesce_num = ETH_COALESCE_PKT_NUM;
 
+	params[0] = CXGBE_FW_PARAM_DEV(VI_ENABLE_INGRESS_AFTER_LINKUP);
+	ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, params, val);
+	adap->params.vi_enable_rx = (ret == 0 && val[0] != 0);
+
 	/*
 	 * The MTU/MSS Table is initialized by now, so load their values.  If
 	 * we're initializing the adapter, then we'll make any modifications
@@ -1594,6 +1598,33 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id)
 			 pi->port_id, pi->link_cfg.mod_type);
 }
 
+void t4_os_link_changed(struct adapter *adap, int port_id)
+{
+	struct port_info *pi = adap2pinfo(adap, port_id);
+
+	/* If link status has not changed or if firmware doesn't
+	 * support enabling/disabling VI's Rx path during runtime,
+	 * then return.
+	 */
+	if (adap->params.vi_enable_rx == 0 ||
+	    pi->vi_en_rx == pi->link_cfg.link_ok)
+		return;
+
+	/* Don't enable VI Rx path, if link has been administratively
+	 * turned off.
+	 */
+	if (pi->vi_en_tx == 0 && pi->vi_en_rx == 0)
+		return;
+
+	/* When link goes down, disable the port's Rx path to drop
+	 * Rx traffic closer to the wire, instead of processing it
+	 * further in the Rx pipeline. The Rx path will be re-enabled
+	 * once the link up message comes in firmware event queue.
+	 */
+	pi->vi_en_rx = pi->link_cfg.link_ok;
+	t4_enable_vi(adap, adap->mbox, pi->viid, pi->vi_en_rx, pi->vi_en_tx);
+}
+
 bool cxgbe_force_linkup(struct adapter *adap)
 {
 	if (is_pf4(adap))
@@ -1638,15 +1669,14 @@ int cxgbe_link_start(struct port_info *pi)
 	if (ret == 0 && is_pf4(adapter))
 		ret = t4_link_l1cfg(pi, pi->link_cfg.admin_caps);
 	if (ret == 0) {
-		/*
-		 * Enabling a Virtual Interface can result in an interrupt
-		 * during the processing of the VI Enable command and, in some
-		 * paths, result in an attempt to issue another command in the
-		 * interrupt context.  Thus, we disable interrupts during the
-		 * course of the VI Enable command ...
+		/* Disable VI Rx until link up message is received in
+		 * firmware event queue, if firmware supports enabling/
+		 * disabling VI Rx at runtime.
 		 */
+		pi->vi_en_rx = adapter->params.vi_enable_rx ? 0 : 1;
+		pi->vi_en_tx = 1;
 		ret = t4_enable_vi_params(adapter, adapter->mbox, pi->viid,
-					  true, true, false);
+					  pi->vi_en_rx, pi->vi_en_tx, false);
 	}
 
 	if (ret == 0 && cxgbe_force_linkup(adapter))
@@ -1923,7 +1953,13 @@ int cxgbe_set_link_status(struct port_info *pi, bool status)
 	struct adapter *adapter = pi->adapter;
 	int err = 0;
 
-	err = t4_enable_vi(adapter, adapter->mbox, pi->viid, status, status);
+	/* Wait for link up message from firmware to enable Rx path,
+	 * if firmware supports enabling/disabling VI Rx at runtime.
+	 */
+	pi->vi_en_rx = adapter->params.vi_enable_rx ? 0 : status;
+	pi->vi_en_tx = status;
+	err = t4_enable_vi(adapter, adapter->mbox, pi->viid, pi->vi_en_rx,
+			   pi->vi_en_tx);
 	if (err) {
 		dev_err(adapter, "%s: disable_vi failed: %d\n", __func__, err);
 		return err;
