diff --git a/hw/phb4.c b/hw/phb4.c
index f17625bb..60e797cf 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -809,6 +809,33 @@ static int64_t phb4_pcicfg_no_dstate(void *dev __unused,
 	return OPAL_PARTIAL;
 }
 
+void phb4_pec2_dma_engine_realloc(struct phb4 *p)
+{
+	uint64_t reg;
+
+	/*
+	 * Allocate 16 extra dma read engines to stack 0, to boost dma
+	 * performance for devices on stack 0 of PEC2, i.e PHB3.
+	 * It comes at a price of reduced read engine allocation for
+	 * devices on stack 1 and 2. The engine allocation becomes
+	 * 48/8/8 instead of the default 32/16/16.
+	 *
+	 * The reallocation magic value should be 0xffff0000ff008000,
+	 * but per the PCI designers, dma engine 32 (bit 0) has a
+	 * quirk, and 0x7fff80007F008000 has the same effect (engine
+	 * 32 goes to PHB4).
+	 */
+	if (p->index != 3) /* shared slot on PEC2 */
+		return;
+
+	PHBINF(p, "Allocating an extra 16 dma read engines on PEC2 stack0\n");
+	reg = 0x7fff80007F008000ULL;
+	xscom_write(p->chip_id,
+		    p->pci_xscom + XPEC_PCI_PRDSTKOVR, reg);
+	xscom_write(p->chip_id,
+		    p->pe_xscom  + XPEC_NEST_READ_STACK_OVERRIDE, reg);
+}
+
 static void phb4_check_device_quirks(struct pci_device *dev)
 {
 	/* Some special adapter tweaks for devices directly under the PHB */
@@ -4415,30 +4442,8 @@ static int64_t enable_capi_mode(struct phb4 *p, uint64_t pe_number,
 	 * dma-read engines allocations to maximize the DMA read performance
 	 */
 	if ((p->index == CAPP1_PHB_INDEX) &&
-	    (capp_eng & CAPP_MAX_DMA_READ_ENGINES)) {
-
-		/*
-		 * Allocate Additional 16/8 dma read engines to stack0/stack1
-		 * respectively. Read engines 0:31 are anyways always assigned
-		 * to stack0. Also skip allocating DMA Read Engine-32 by
-		 * enabling Bit[0] in XPEC_NEST_READ_STACK_OVERRIDE register.
-		 * Enabling this bit seems cause a parity error reported in
-		 * NFIR[1]-nonbar_pe.
-		 */
-		reg = 0x7fff80007F008000ULL;
-
-		xscom_write(p->chip_id, p->pci_xscom + XPEC_PCI_PRDSTKOVR, reg);
-		xscom_write(p->chip_id, p->pe_xscom +
-			    XPEC_NEST_READ_STACK_OVERRIDE, reg);
-
-		/* Log this reallocation as it may impact dma performance of
-		 * other slots connected to PEC2
-		 */
-		PHBINF(p, "CAPP: Set %d dma-read engines for PEC2/stack-0\n",
-		      32 + __builtin_popcountll(reg & PPC_BITMASK(0, 31)));
-		PHBDBG(p, "CAPP: XPEC_NEST_READ_STACK_OVERRIDE: %016llx\n",
-		       reg);
-	}
+	    (capp_eng & CAPP_MAX_DMA_READ_ENGINES))
+		phb4_pec2_dma_engine_realloc(p);
 
 	/* PCI to PB data movement ignores the PB init signal. */
 	xscom_write_mask(p->chip_id, p->pe_xscom + XPEC_NEST_PBCQ_HW_CONFIG,
diff --git a/include/phb4.h b/include/phb4.h
index 6d5fd510..abba2d9c 100644
--- a/include/phb4.h
+++ b/include/phb4.h
@@ -257,4 +257,6 @@ static inline int phb4_get_opal_id(unsigned int chip_id, unsigned int index)
 		return chip_id * PHB4_MAX_PHBS_PER_CHIP_P9P + index;
 }
 
+void phb4_pec2_dma_engine_realloc(struct phb4 *p);
+
 #endif /* __PHB4_H */
diff --git a/platforms/astbmc/witherspoon.c b/platforms/astbmc/witherspoon.c
index 6387af48..39c3f161 100644
--- a/platforms/astbmc/witherspoon.c
+++ b/platforms/astbmc/witherspoon.c
@@ -192,6 +192,52 @@ static void witherspoon_shared_slot_fixup(void)
 	}
 }
 
+static int check_mlx_cards(struct phb *phb __unused, struct pci_device *dev,
+			   void *userdata __unused)
+{
+	uint16_t mlx_cards[] = {
+		0x1017, /* ConnectX-5 */
+		0x1019, /* ConnectX-5 Ex */
+		0x101b, /* ConnectX-6 */
+		0x101d, /* ConnectX-6 Dx */
+		0x101f, /* ConnectX-6 Lx */
+		0x1021, /* ConnectX-7 */
+	};
+
+	if (PCI_VENDOR_ID(dev->vdid) == 0x15b3) { /* Mellanox */
+		for (int i = 0; i < ARRAY_SIZE(mlx_cards); i++) {
+			if (mlx_cards[i] == PCI_DEVICE_ID(dev->vdid))
+				return 1;
+		}
+	}
+	return 0;
+}
+
+static void witherspoon_pci_probe_complete(void)
+{
+	struct pci_device *dev;
+	struct phb *phb;
+	struct phb4 *p;
+
+	/*
+	 * Reallocate dma engines between stacks in PEC2 if a Mellanox
+	 * card is found on the shared slot, as it is required to get
+	 * good GPU direct performance.
+	 */
+	for_each_phb(phb) {
+		/* skip the virtual PHBs */
+		if (phb->phb_type != phb_type_pcie_v4)
+			continue;
+		p = phb_to_phb4(phb);
+		/* Keep only the first PHB on PEC2 */
+		if (p->index != 3)
+			continue;
+		dev = pci_walk_dev(phb, NULL, check_mlx_cards, NULL);
+		if (dev)
+			phb4_pec2_dma_engine_realloc(p);
+	}
+}
+
 static void set_link_details(struct npu2 *npu, uint32_t link_index,
 			     uint32_t brick_index, enum npu2_dev_type type)
 {
@@ -533,6 +579,7 @@ DECLARE_PLATFORM(witherspoon) = {
 	.probe			= witherspoon_probe,
 	.init			= astbmc_init,
 	.pre_pci_fixup		= witherspoon_shared_slot_fixup,
+	.pci_probe_complete	= witherspoon_pci_probe_complete,
 	.start_preload_resource	= flash_start_preload_resource,
 	.resource_loaded	= flash_resource_loaded,
 	.bmc			= &bmc_plat_ast2500_openbmc,
