Commit f3dbd802 authored by Rajat Jain's avatar Rajat Jain Committed by Bjorn Helgaas

PCI: Enable CRS Software Visibility for root port if it is supported

Per PCIe r3.0, sec 2.3.2, an endpoint may respond to a Configuration
Request with a Completion with Configuration Request Retry Status (CRS).
This terminates the Configuration Request.

When the CRS Software Visibility feature is disabled (as it is by default),
a Root Complex must handle a CRS Completion by re-issuing the Configuration
Request.  This is invisible to software.  From the CPU's point of view, an
endpoint that always responds with CRS causes a hang because the Root
Complex never supplies data to complete the CPU read.

When CRS Software Visibility is enabled, a Root Complex that receives a CRS
Completion for a read of the Vendor ID must return data of 0x0001.  The
Vendor ID of 0x0001 indicates to software that the endpoint is not ready.

We now have more devices that require CRS Software Visibility.  For
example, a PLX 8713 NT bridge may respond with CRS until it has been
configured via I2C, and the I2C configuration is completely independent of
PCI enumeration.

Enable CRS Software Visibility if it is supported.  This allows a system
with such a device to work (though the PCI core times out waiting for it to
become ready, and we have to rescan the bus after it is ready).

This essentially reverts ad7edfe0 ("[PCI] Do not enable CRS Software
Visibility by default").  The failures that led to ad7edfe0 should be
addressed by 89665a6a ("PCI: Check only the Vendor ID to identify
Configuration Request Retry").

[bhelgaas: changelog]
Link: http://lkml.kernel.org/r/20071029061532.5d10dfc6@snowcone
Link: http://lkml.kernel.org/r/alpine.LFD.0.9999.0712271023090.21557@woody.linux-foundation.orgSigned-off-by: default avatarRajat Jain <rajatxjain@gmail.com>
Signed-off-by: default avatarRajat Jain <rajatjain@juniper.net>
Signed-off-by: default avatarGuenter Roeck <groeck@juniper.net>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent 89665a6a
...@@ -740,6 +740,17 @@ struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, ...@@ -740,6 +740,17 @@ struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
} }
EXPORT_SYMBOL(pci_add_new_bus); EXPORT_SYMBOL(pci_add_new_bus);
static void pci_enable_crs(struct pci_dev *pdev)
{
u16 root_cap = 0;
/* Enable CRS Software Visibility if supported */
pcie_capability_read_word(pdev, PCI_EXP_RTCAP, &root_cap);
if (root_cap & PCI_EXP_RTCAP_CRSVIS)
pcie_capability_set_word(pdev, PCI_EXP_RTCTL,
PCI_EXP_RTCTL_CRSSVE);
}
/* /*
* If it's a bridge, configure it and scan the bus behind it. * If it's a bridge, configure it and scan the bus behind it.
* For CardBus bridges, we don't scan behind as the devices will * For CardBus bridges, we don't scan behind as the devices will
...@@ -787,6 +798,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) ...@@ -787,6 +798,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, pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
pci_enable_crs(dev);
if ((secondary || subordinate) && !pcibios_assign_all_busses() && if ((secondary || subordinate) && !pcibios_assign_all_busses() &&
!is_cardbus && !broken) { !is_cardbus && !broken) {
unsigned int cmax; unsigned int cmax;
......
...@@ -552,6 +552,7 @@ ...@@ -552,6 +552,7 @@
#define PCI_EXP_RTCTL_PMEIE 0x0008 /* PME Interrupt Enable */ #define PCI_EXP_RTCTL_PMEIE 0x0008 /* PME Interrupt Enable */
#define PCI_EXP_RTCTL_CRSSVE 0x0010 /* CRS Software Visibility Enable */ #define PCI_EXP_RTCTL_CRSSVE 0x0010 /* CRS Software Visibility Enable */
#define PCI_EXP_RTCAP 30 /* Root Capabilities */ #define PCI_EXP_RTCAP 30 /* Root Capabilities */
#define PCI_EXP_RTCAP_CRSVIS 0x0001 /* CRS Software Visibility capability */
#define PCI_EXP_RTSTA 32 /* Root Status */ #define PCI_EXP_RTSTA 32 /* Root Status */
#define PCI_EXP_RTSTA_PME 0x00010000 /* PME status */ #define PCI_EXP_RTSTA_PME 0x00010000 /* PME status */
#define PCI_EXP_RTSTA_PENDING 0x00020000 /* PME pending */ #define PCI_EXP_RTSTA_PENDING 0x00020000 /* PME pending */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment