]> git.proxmox.com Git - pve-kernel-jessie.git/blame - 981-2-PCI-Quirk-PCH-root-port-ACS-for-Sunrise-Point.patch
add scheduler fix for ceph on numa hosts
[pve-kernel-jessie.git] / 981-2-PCI-Quirk-PCH-root-port-ACS-for-Sunrise-Point.patch
CommitLineData
4e52de75
FG
1From: Alex Williamson <alex.williamson@redhat.com>
2Subject: [PATCH 2/2] PCI: Quirk PCH root port ACS for Sunrise Point
3
4As noted in the comments, these root ports attempted to implement ACS
5but used dwords for the capability and control registers, putting the
6control register at the wrong offset. We use quirks to enable and
7test ACS for these devices, which match the standard functions modulo
8the broken control register offset.
9
10Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
11---
12 drivers/pci/quirks.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++
13 1 file changed, 78 insertions(+)
14
15diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
16index 701fad6..d6606e4 100644
17--- a/drivers/pci/quirks.c
18+++ b/drivers/pci/quirks.c
19@@ -3992,6 +3992,55 @@ static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
20 return acs_flags & ~flags ? 0 : 1;
21 }
22
23+/*
24+ * Sunrise Point PCH root ports implement ACS, but unfortunately as shown in
25+ * the datasheet (Intel 100 Series Chipset Family PCH Datasheet, Vol. 2,
26+ * 12.1.46, 12.1.47)[1] this chipset uses dwords for the ACS capability and
27+ * control registers whereas the PCIe spec packs them into words (Rev 3.0,
28+ * 7.16 ACS Extended Capability). The bit definitions are correct, but the
29+ * control register is at offset 8 instead of 6 and we should probably use
30+ * dword accesses to them. This applies to the following PCI Device IDs, as
31+ * found in volume 1 of the datasheet[2]:
32+ *
33+ * 0xa110-0xa11f Sunrise Point-H PCI Express Root Port #{0-16}
34+ * 0xa167-0xa16a Sunrise Point-H PCI Express Root Port #{17-20}
35+ *
36+ * NB. This doesn't fix what lspci shows.
37+ *
38+ * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html
39+ * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html
40+ */
41+static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev)
42+{
43+ return pci_is_pcie(dev) &&
44+ pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT &&
45+ ((dev->device & ~0xf) == 0xa110 ||
46+ (dev->device >= 0xa167 && dev->device <= 0xa16a));
47+}
48+
49+#define INTEL_SPT_ACS_CTRL (PCI_ACS_CAP + 4)
50+
51+static int pci_quirk_intel_spt_pch_acs(struct pci_dev *dev, u16 acs_flags)
52+{
53+ int pos;
54+ u32 cap, ctrl;
55+
56+ if (!pci_quirk_intel_spt_pch_acs_match(dev))
57+ return -ENOTTY;
58+
59+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
60+ if (!pos)
61+ return -ENOTTY;
62+
63+ /* see pci_acs_flags_enabled() */
64+ pci_read_config_dword(dev, pos + PCI_ACS_CAP, &cap);
65+ acs_flags &= (cap | PCI_ACS_EC);
66+
67+ pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl);
68+
69+ return acs_flags & ~ctrl ? 0 : 1;
70+}
71+
72 static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags)
73 {
74 /*
75@@ -4024,6 +4073,7 @@ static const struct pci_dev_acs_enabled {
76 { PCI_VENDOR_ID_INTEL, 0x15b8, pci_quirk_mf_endpoint_acs },
77 /* Intel PCH root ports */
78 { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
79+ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_spt_pch_acs },
80 { 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */
81 { 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */
82 /* Cavium ThunderX */
83@@ -4159,12 +4209,40 @@ static int pci_quirk_enable_intel_pch_acs(struct pci_dev *dev)
84 return 0;
85 }
86
87+static int pci_quirk_enable_intel_spt_pch_acs(struct pci_dev *dev)
88+{
89+ int pos;
90+ u32 cap, ctrl;
91+
92+ if (!pci_quirk_intel_spt_pch_acs_match(dev))
93+ return -ENOTTY;
94+
95+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
96+ if (!pos)
97+ return -ENOTTY;
98+
99+ pci_read_config_dword(dev, pos + PCI_ACS_CAP, &cap);
100+ pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl);
101+
102+ ctrl |= (cap & PCI_ACS_SV);
103+ ctrl |= (cap & PCI_ACS_RR);
104+ ctrl |= (cap & PCI_ACS_CR);
105+ ctrl |= (cap & PCI_ACS_UF);
106+
107+ pci_write_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, ctrl);
108+
109+ dev_info(&dev->dev, "Intel SPT PCH root port ACS workaround enabled\n");
110+
111+ return 0;
112+}
113+
114 static const struct pci_dev_enable_acs {
115 u16 vendor;
116 u16 device;
117 int (*enable_acs)(struct pci_dev *dev);
118 } pci_dev_enable_acs[] = {
119 { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs },
120+ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_spt_pch_acs },
121 { 0 }
122 };
123