PCI: Enable ATS at the device state restore
authorHao, Xudong <xudong.hao@intel.com>
Sat, 17 Dec 2011 13:24:40 +0000 (21:24 +0800)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 6 Jan 2012 20:11:18 +0000 (12:11 -0800)
During S3 or S4 resume or PCI reset, ATS regs aren't restored correctly.
This patch enables ATS at the device state restore if PCI device has ATS
capability.

Signed-off-by: Xudong Hao <xudong.hao@intel.com>
Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
drivers/pci/ats.c
drivers/pci/pci.c
drivers/pci/pci.h

index e11ebafaf7749883a9632cd1e99a36cbce6821f0..a4a1b369853b7bf5d112fd93fc738d8224b4cbb1 100644 (file)
@@ -128,6 +128,23 @@ void pci_disable_ats(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_disable_ats);
 
+void pci_restore_ats_state(struct pci_dev *dev)
+{
+       u16 ctrl;
+
+       if (!pci_ats_enabled(dev))
+               return;
+       if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS))
+               BUG();
+
+       ctrl = PCI_ATS_CTRL_ENABLE;
+       if (!dev->is_virtfn)
+               ctrl |= PCI_ATS_CTRL_STU(dev->ats->stu - PCI_ATS_MIN_STU);
+
+       pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
+}
+EXPORT_SYMBOL_GPL(pci_restore_ats_state);
+
 /**
  * pci_ats_queue_depth - query the ATS Invalidate Queue Depth
  * @dev: the PCI device
index 54343aa5b30a548f11e66f266373e53e07fcc323..97fff785e97e7027f7d54563186db969075a2558 100644 (file)
@@ -965,6 +965,7 @@ void pci_restore_state(struct pci_dev *dev)
 
        /* PCI Express register must be restored first */
        pci_restore_pcie_state(dev);
+       pci_restore_ats_state(dev);
 
        /*
         * The Base Address register should be programmed before the command
index 3b6e4ed306b636cbbea2146e56a9c506fb7d89ea..1009a5e88e533f37736710895ffc6ba5194f0498 100644 (file)
@@ -251,6 +251,14 @@ struct pci_sriov {
        u8 __iomem *mstate;     /* VF Migration State Array */
 };
 
+#ifdef CONFIG_PCI_ATS
+extern void pci_restore_ats_state(struct pci_dev *dev);
+#else
+static inline void pci_restore_ats_state(struct pci_dev *dev)
+{
+}
+#endif /* CONFIG_PCI_ATS */
+
 #ifdef CONFIG_PCI_IOV
 extern int pci_iov_init(struct pci_dev *dev);
 extern void pci_iov_release(struct pci_dev *dev);