]> git.proxmox.com Git - pve-kernel-jessie.git/blob - 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
1 From: Alex Williamson <alex.williamson@redhat.com>
2 Subject: [PATCH 2/2] PCI: Quirk PCH root port ACS for Sunrise Point
3
4 As noted in the comments, these root ports attempted to implement ACS
5 but used dwords for the capability and control registers, putting the
6 control register at the wrong offset. We use quirks to enable and
7 test ACS for these devices, which match the standard functions modulo
8 the broken control register offset.
9
10 Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
11 ---
12 drivers/pci/quirks.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++
13 1 file changed, 78 insertions(+)
14
15 diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
16 index 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