|
@@ -1118,40 +1118,54 @@ struct pci_dev *alloc_pci_dev(void)
|
|
|
}
|
|
|
EXPORT_SYMBOL(alloc_pci_dev);
|
|
|
|
|
|
-/*
|
|
|
- * Read the config data for a PCI device, sanity-check it
|
|
|
- * and fill in the dev structure...
|
|
|
- */
|
|
|
-static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
|
|
|
+bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
|
|
|
+ int crs_timeout)
|
|
|
{
|
|
|
- struct pci_dev *dev;
|
|
|
- u32 l;
|
|
|
int delay = 1;
|
|
|
|
|
|
- if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
|
|
|
- return NULL;
|
|
|
+ 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 NULL;
|
|
|
+ if (*l == 0xffffffff || *l == 0x00000000 ||
|
|
|
+ *l == 0x0000ffff || *l == 0xffff0000)
|
|
|
+ return false;
|
|
|
|
|
|
/* Configuration request Retry Status */
|
|
|
- while (l == 0xffff0001) {
|
|
|
+ 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 NULL;
|
|
|
+ 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 > 60 * 1000) {
|
|
|
+ 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 NULL;
|
|
|
+ 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...
|
|
|
+ */
|
|
|
+static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
|
|
|
+{
|
|
|
+ struct pci_dev *dev;
|
|
|
+ u32 l;
|
|
|
+
|
|
|
+ if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
dev = alloc_pci_dev();
|
|
|
if (!dev)
|
|
|
return NULL;
|