PCI: Separate pci_bus_read_dev_vendor_id from pci_scan_device
authorYinghai Lu <yinghai@kernel.org>
Fri, 27 Jan 2012 18:55:10 +0000 (10:55 -0800)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Tue, 14 Feb 2012 16:44:59 +0000 (08:44 -0800)
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>
drivers/pci/pci.h
drivers/pci/probe.c

index 1009a5e..aaf7ff8 100644 (file)
@@ -207,6 +207,8 @@ enum pci_bar_type {
        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);
index aad7d0f..9f2ff8c 100644 (file)
@@ -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;