@@ -634,6 +634,24 @@ char * __init pcibios_setup(char *str)
return str;
}
+static const struct pci_device_id crs_whitelist[] = {
+ { PCI_VDEVICE(INTEL, 0x2f00), },
+ { PCI_VDEVICE(INTEL, 0x2f02), },
+ { },
+};
+
+void pcibios_enable_crs(struct pci_dev *dev)
+{
+ if (!pci_is_pcie(dev) ||
+ pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
+ return;
+
+ /* Enable CRS Software visibility only for whitelisted systems */
+ if (pci_match_id(crs_whitelist, dev))
+ pcie_capability_set_word(dev, PCI_EXP_RTCTL,
+ PCI_EXP_RTCTL_CRSSVE);
+}
+
unsigned int pcibios_assign_all_busses(void)
{
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
@@ -2685,6 +2685,11 @@ char * __weak __init pcibios_setup(char *str)
return str;
}
+void __weak pcibios_enable_crs(struct pci_dev *dev)
+{
+ /* Do nothing by default, and let platforms decide for themselves */
+}
+
/**
* pcibios_set_master - enable PCI bus-mastering for device dev
* @dev: the PCI device to enable
@@ -801,6 +801,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
+ pcibios_enable_crs(dev);
+
if ((secondary || subordinate) && !pcibios_assign_all_busses() &&
!is_cardbus && !broken) {
unsigned int cmax;
@@ -723,6 +723,7 @@ void pcibios_fixup_bus(struct pci_bus *);
int __must_check pcibios_enable_device(struct pci_dev *, int mask);
/* Architecture-specific versions may override this (weak) */
char *pcibios_setup(char *str);
+void pcibios_enable_crs(struct pci_dev *dev);
/* Used only when drivers/pci/setup.c is used */
resource_size_t pcibios_align_resource(void *, const struct resource *,