diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index b761c1f72f67..e2ea9083f30f 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -28,6 +28,9 @@ void pci_ats_init(struct pci_dev *dev)
 		return;
 
 	dev->ats_cap = pos;
+
+	dev->ats_enabled = 1; /* To avoid WARN_ON from pci_disable_ats() */
+	pci_disable_ats(dev);
 }
 
 /**
@@ -82,6 +85,7 @@ int pci_enable_ats(struct pci_dev *dev, int ps)
 	}
 	pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
 
+	pci_disable_acs_trans_blocking(dev);
 	dev->ats_enabled = 1;
 	return 0;
 }
@@ -102,6 +106,7 @@ void pci_disable_ats(struct pci_dev *dev)
 	ctrl &= ~PCI_ATS_CTRL_ENABLE;
 	pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
 
+	pci_enable_acs_trans_blocking(dev);
 	dev->ats_enabled = 0;
 }
 EXPORT_SYMBOL_GPL(pci_disable_ats);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 73a862782214..614e3c1e8c56 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -876,6 +876,9 @@ static void pci_std_enable_acs(struct pci_dev *dev)
 	/* Upstream Forwarding */
 	ctrl |= (cap & PCI_ACS_UF);
 
+	/* Translation Blocking */
+	ctrl |= (cap & PCI_ACS_TB);
+
 	pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
 }
 
@@ -904,6 +907,60 @@ static void pci_enable_acs(struct pci_dev *dev)
 	pci_disable_acs_redir(dev);
 }
 
+void pci_disable_acs_trans_blocking(struct pci_dev *pdev)
+{
+	u16 cap, ctrl, pos;
+	struct pci_dev *dev;
+
+	if (!pci_acs_enable)
+		return;
+
+	for (dev = pdev; dev; dev = pci_upstream_bridge(pdev)) {
+
+		pos = dev->acs_cap;
+		if (!pos)
+			continue;
+
+		/*
+		 * Disable translation blocking when first downstream
+		 * device that needs it (for ATS) wants to enable ATS
+		 */
+		if (++dev->ats_dependencies == 1) {
+			pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
+			pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
+			ctrl &= ~(cap & PCI_ACS_TB);
+			pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+		}
+	}
+}
+
+void pci_enable_acs_trans_blocking(struct pci_dev *pdev)
+{
+	u16 cap, ctrl, pos;
+	struct pci_dev *dev;
+
+	if (!pci_acs_enable)
+		return;
+
+	for (dev = pdev; dev; dev = pci_upstream_bridge(pdev)) {
+
+		pos = dev->acs_cap;
+		if (!pos)
+			continue;
+
+		/*
+		 * Enable translation blocking when last downstream device
+		 * that depends on it (for ATS), doesn't need ATS anymore
+		 */
+		if (--dev->ats_dependencies == 0) {
+			pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
+			pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
+			ctrl |= (cap & PCI_ACS_TB);
+			pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+		}
+	}
+}
+
 /**
  * pci_restore_bars - restore a device's BAR values (e.g. after wake-up)
  * @dev: PCI device to have its BARs restored
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 12fb79fbe29d..f5d8ecb6ba96 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -552,6 +552,8 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
 	return -ENOTTY;
 }
 #endif
+void pci_disable_acs_trans_blocking(struct pci_dev *dev);
+void pci_enable_acs_trans_blocking(struct pci_dev *dev);
 
 /* PCI error reporting and recovery */
 pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 8c40c00413e7..e2ff3a94e621 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2387,10 +2387,10 @@ static void pci_init_capabilities(struct pci_dev *dev)
 	pci_vpd_init(dev);		/* Vital Product Data */
 	pci_configure_ari(dev);		/* Alternative Routing-ID Forwarding */
 	pci_iov_init(dev);		/* Single Root I/O Virtualization */
+	pci_acs_init(dev);		/* Access Control Services */
 	pci_ats_init(dev);		/* Address Translation Services */
 	pci_pri_init(dev);		/* Page Request Interface */
 	pci_pasid_init(dev);		/* Process Address Space ID */
-	pci_acs_init(dev);		/* Access Control Services */
 	pci_ptm_init(dev);		/* Precision Time Measurement */
 	pci_aer_init(dev);		/* Advanced Error Reporting */
 	pci_dpc_init(dev);		/* Downstream Port Containment */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7a40cd5caed0..31da4355f0fd 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -480,6 +480,8 @@ struct pci_dev {
 	u16		ats_cap;	/* ATS Capability offset */
 	u8		ats_stu;	/* ATS Smallest Translation Unit */
 #endif
+	/* Total number of downstream devices below a bridge that need ATS */
+	u8		ats_dependencies;
 #ifdef CONFIG_PCI_PRI
 	u16		pri_cap;	/* PRI Capability offset */
 	u32		pri_reqs_alloc; /* Number of PRI requests allocated */
