Commit c842b00a authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Greg Kroah-Hartman

[PATCH] PCI: Software visible configuration request retry status

PCI Express allows cards to return "Configuration Request Retry" if they're
not ready to handle accesses to configuration space.  The PCI Express 1.0a
specification says that the Root Complex should retry the access.  ECN 27
http://www.pcisig.com/specifications/pciexpress/ECN_CRS_Software_Visibility_No27.pdf
allows software to handle the CRS.
Signed-off-by: default avatarMatthew Wilcox <matthew@wil.cx>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 05bbd08a
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* probe.c - PCI detection and setup code * probe.c - PCI detection and setup code
*/ */
#include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -336,6 +337,22 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de ...@@ -336,6 +337,22 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
return child; return child;
} }
static void pci_enable_crs(struct pci_dev *dev)
{
u16 cap, rpctl;
int rpcap = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (!rpcap)
return;
pci_read_config_word(dev, rpcap + PCI_CAP_FLAGS, &cap);
if (((cap & PCI_EXP_FLAGS_TYPE) >> 4) != PCI_EXP_TYPE_ROOT_PORT)
return;
pci_read_config_word(dev, rpcap + PCI_EXP_RTCTL, &rpctl);
rpctl |= PCI_EXP_RTCTL_CRSSVE;
pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl);
}
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
/* /*
...@@ -366,6 +383,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max ...@@ -366,6 +383,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
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 ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) {
unsigned int cmax, busnr; unsigned int cmax, busnr;
/* /*
...@@ -614,9 +633,7 @@ pci_scan_device(struct pci_bus *bus, int devfn) ...@@ -614,9 +633,7 @@ pci_scan_device(struct pci_bus *bus, int devfn)
struct pci_dev *dev; struct pci_dev *dev;
u32 l; u32 l;
u8 hdr_type; u8 hdr_type;
int delay = 1;
if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
return NULL;
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l)) if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
return NULL; return NULL;
...@@ -626,6 +643,25 @@ pci_scan_device(struct pci_bus *bus, int devfn) ...@@ -626,6 +643,25 @@ pci_scan_device(struct pci_bus *bus, int devfn)
l == 0x0000ffff || l == 0xffff0000) l == 0x0000ffff || l == 0xffff0000)
return NULL; return NULL;
/* Configuration request Retry Status */
while (l == 0xffff0001) {
msleep(delay);
delay *= 2;
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
return NULL;
/* Card hasn't responded in 60 seconds? Must be stuck. */
if (delay > 60 * 1000) {
printk(KERN_WARNING "Device %04x:%02x:%02x.%d not "
"responding\n", pci_domain_nr(bus),
bus->number, PCI_SLOT(devfn),
PCI_FUNC(devfn));
return NULL;
}
}
if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
return NULL;
dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
if (!dev) if (!dev)
return NULL; return NULL;
......
...@@ -364,6 +364,20 @@ ...@@ -364,6 +364,20 @@
#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */ #define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */
#define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */ #define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */
#define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */ #define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */
#define PCI_EXP_LNKCAP 12 /* Link Capabilities */
#define PCI_EXP_LNKCTL 16 /* Link Control */
#define PCI_EXP_LNKSTA 18 /* Link Status */
#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
#define PCI_EXP_SLTCTL 24 /* Slot Control */
#define PCI_EXP_SLTSTA 26 /* Slot Status */
#define PCI_EXP_RTCTL 28 /* Root Control */
#define PCI_EXP_RTCTL_SECEE 0x01 /* System Error on Correctable Error */
#define PCI_EXP_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Error */
#define PCI_EXP_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */
#define PCI_EXP_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */
#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */
#define PCI_EXP_RTCAP 30 /* Root Capabilities */
#define PCI_EXP_RTSTA 32 /* Root Status */
/* Extended Capabilities (PCI-X 2.0 and Express) */ /* Extended Capabilities (PCI-X 2.0 and Express) */
#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) #define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
......
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