diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fcd8191..f12cb58 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -376,11 +376,18 @@ struct pci_dev_reset_methods {

  #ifdef CONFIG_PCI_QUIRKS
  int pci_dev_specific_reset(struct pci_dev *dev, int probe);
+int pci_dev_specific_fixup_acs_quirk(struct pci_bus *bus , int devfn,
+                               int enable, bool found);
  #else
  static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
  {
  	return -ENOTTY;
  }
+static inline int pci_dev_specific_fixup_acs_quirk(struct pc_bus *bus,
+                                       int devfn, int enable, bool found)
+{
+       return -ENOTTY;
+}
  #endif

  #if defined(CONFIG_PCI_QUIRKS) && defined(CONFIG_ARM64)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ef53774..9497d33 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2041,18 +2041,26 @@ static bool pci_bus_wait_crs(struct pci_bus 
*bus, int de
vfn, u32 *l,
  bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
  				int timeout)
  {
+	bool found = false;
+	int enable = -1;
+
+	enable = pci_dev_specific_fixup_acs_quirk(bus, devfn, false, found);
  	if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
-		return false;
+		goto out;

  	/* Some broken boards return 0 or ~0 if a slot is empty: */
  	if (*l == 0xffffffff || *l == 0x00000000 ||
  	    *l == 0x0000ffff || *l == 0xffff0000)
-		return false;
+		goto out;

+	found = true;
  	if (pci_bus_crs_vendor_id(*l))
-		return pci_bus_wait_crs(bus, devfn, l, timeout);
+		found = pci_bus_wait_crs(bus, devfn, l, timeout);

-	return true;
+out:
+	if (enable > 0)
+		pci_dev_specific_fixup_acs_quirk(bus, devfn, enable, found);
+	return found;
  }
  EXPORT_SYMBOL(pci_bus_read_dev_vendor_id);

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 8b14bd3..7222853 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -4839,3 +4839,98 @@ static void quirk_fsl_no_msi(struct pci_dev *pdev)
  		pdev->no_msi = 1;
  }
  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, 
quirk_fsl_no_msi);
+
+
+
+/*
+ * Some IDT switches flag an ACS violation for config reads even though 
the
+ * PCI spec allows for it (PCIe 3.1, 6.1.12.1). It flags it because the 
bus
+ * number is not properly set in the completion. The workaround is to do a
+ * dummy write to properly latch number once the device is ready for 
config
+ * operations.
+ *
+ * So, the caller would disable ACS source validation, wait for the device
+ * hanging off this switch to be ready for config operations, and then
+ * call this routine again to enable it (if it was eabled to begin with)
+ */
+static int pci_idt_acs_quirk(struct pci_bus *bus, int devfn, int enable,
+                               bool found)
+{
+	int pos;
+	u16 cap;
+	u16 ctrl;
+	int retval;
+	struct pci_dev *dev = bus->self;
+
+
+	/* Write 0 to the devfn device under the PCIE switch (bus->self)
+ 	* as part of forcing the devfn number to latch with the device below
+ 	*/
+	if (found)
+        	pci_bus_write_config_word(bus, devfn, PCI_VENDOR_ID, 0);
+
+
+	/* Enable/disable ACS SV feature (based on enable flag) */
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
+	if (!pos)
+		return -ENODEV;
+
+	pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
+
+	if (!(cap & PCI_ACS_SV))
+		return -ENODEV;
+
+	pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
+
+	retval = !!(ctrl & cap & PCI_ACS_SV);
+	if (enable)
+		ctrl |= (cap & PCI_ACS_SV);
+	else
+		ctrl &= ~(cap & PCI_ACS_SV);
+
+	pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+	return retval;
+}
+
+static const struct pci_dev_acs_quirk{
+        u16 vendor;
+        u16 device;
+        int (*fixup_acs)(struct pci_bus *bus, int devfn, int enable, 
bool found
);
+} pci_dev_acs_quirks[] = {
+        { PCI_VENDOR_ID_IDT, 0x80b5, pci_idt_acs_quirk},
+        {0}
+};
+
+int pci_dev_specific_fixup_acs_quirk(struct pci_bus *bus, int devfn, 
int enable
,
+                                       bool found)
+{
+	const struct pci_dev_acs_quirk *i;
+	struct pci_dev *dev;
+	int ret;
+
+	if (!bus || !bus->self)
+		return -ENOTTY;
+
+	dev = bus->self;
+
+	 /*
+	  * Allow devices that do not expose standard PCIe ACS capabilities
+	  * or control to indicate their support here.  Multi-function express
+	  * devices which do not allow internal peer-to-peer between functions,
+	  * but do not implement PCIe ACS may wish to return true here.
+	  */
+	 for (i = pci_dev_acs_quirks; i->fixup_acs; i++) {
+		if ((i->vendor == dev->vendor ||
+		      i->vendor == (u16)PCI_ANY_ID) &&
+		     (i->device == dev->device ||
+		      i->device == (u16)PCI_ANY_ID)) {
+			 ret = i->fixup_acs(bus, devfn, enable, found);
+			 if (ret >= 0)
