PCI: Separate pci_bus_read_dev_vendor_id from pci_scan_device
We can reuse it for pciehp probing.
-v2: according to Kenji, fix crs timeout checking, and export the function
for later use when pciehp is compiled as a module.
Suggested-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 1009a5e..aaf7ff8 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -207,6 +207,8 @@
pci_bar_mem64, /* A 64-bit memory BAR */
};
+bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl,
+ int crs_timeout);
extern int pci_setup_device(struct pci_dev *dev);
extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
struct resource *res, unsigned int reg);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index aad7d0f..9f2ff8c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1118,6 +1118,42 @@
}
EXPORT_SYMBOL(alloc_pci_dev);
+bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
+ int crs_timeout)
+{
+ int delay = 1;
+
+ if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
+ return false;
+
+ /* some broken boards return 0 or ~0 if a slot is empty: */
+ if (*l == 0xffffffff || *l == 0x00000000 ||
+ *l == 0x0000ffff || *l == 0xffff0000)
+ return false;
+
+ /* Configuration request Retry Status */
+ while (*l == 0xffff0001) {
+ if (!crs_timeout)
+ return false;
+
+ msleep(delay);
+ delay *= 2;
+ if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
+ return false;
+ /* Card hasn't responded in 60 seconds? Must be stuck. */
+ if (delay > crs_timeout) {
+ printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not "
+ "responding\n", pci_domain_nr(bus),
+ bus->number, PCI_SLOT(devfn),
+ PCI_FUNC(devfn));
+ return false;
+ }
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(pci_bus_read_dev_vendor_id);
+
/*
* Read the config data for a PCI device, sanity-check it
* and fill in the dev structure...
@@ -1126,32 +1162,10 @@
{
struct pci_dev *dev;
u32 l;
- int delay = 1;
- if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
+ if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
return NULL;
- /* some broken boards return 0 or ~0 if a slot is empty: */
- if (l == 0xffffffff || l == 0x00000000 ||
- l == 0x0000ffff || l == 0xffff0000)
- 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 "pci %04x:%02x:%02x.%d: not "
- "responding\n", pci_domain_nr(bus),
- bus->number, PCI_SLOT(devfn),
- PCI_FUNC(devfn));
- return NULL;
- }
- }
-
dev = alloc_pci_dev();
if (!dev)
return NULL;