]> Pileus Git - ~andy/linux/blobdiff - drivers/pci/search.c
devres: release resources on device_del()
[~andy/linux] / drivers / pci / search.c
index 45f2b20ef513d39612dcfd64cc838a65d85973d9..ff98eaddaa73868777ae19564122c5bff4d0cd3e 100644 (file)
@@ -193,6 +193,15 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor,
        struct pci_dev *dev;
 
        WARN_ON(in_interrupt());
+
+       /*
+        * pci_find_subsys() can be called on the ide_setup() path, super-early
+        * in boot.  But the down_read() will enable local interrupts, which
+        * can cause some machines to crash.  So here we detect and flag that
+        * situation and bail out early.
+        */
+       if (unlikely(list_empty(&pci_devices)))
+               return NULL;
        down_read(&pci_bus_sem);
        n = from ? from->global_list.next : pci_devices.next;
 
@@ -259,6 +268,15 @@ pci_get_subsys(unsigned int vendor, unsigned int device,
        struct pci_dev *dev;
 
        WARN_ON(in_interrupt());
+
+       /*
+        * pci_get_subsys() can potentially be called by drivers super-early
+        * in boot.  But the down_read() will enable local interrupts, which
+        * can cause some machines to crash.  So here we detect and flag that
+        * situation and bail out early.
+        */
+       if (unlikely(list_empty(&pci_devices)))
+               return NULL;
        down_read(&pci_bus_sem);
        n = from ? from->global_list.next : pci_devices.next;
 
@@ -339,43 +357,6 @@ exit:
        return dev;
 }
 
-/**
- * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id
- * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
- * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
- * @from: Previous PCI device found in search, or %NULL for new search.
- *
- * Iterates through the list of known PCI devices in the reverse order of
- * pci_find_device().
- * If a PCI device is found with a matching @vendor and @device, a pointer to
- * its device structure is returned.  Otherwise, %NULL is returned.
- * A new search is initiated by passing %NULL as the @from argument.
- * Otherwise if @from is not %NULL, searches continue from previous device
- * on the global list.
- */
-struct pci_dev *
-pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from)
-{
-       struct list_head *n;
-       struct pci_dev *dev;
-
-       WARN_ON(in_interrupt());
-       down_read(&pci_bus_sem);
-       n = from ? from->global_list.prev : pci_devices.prev;
-
-       while (n && (n != &pci_devices)) {
-               dev = pci_dev_g(n);
-               if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
-                   (device == PCI_ANY_ID || dev->device == device))
-                       goto exit;
-               n = n->prev;
-       }
-       dev = NULL;
-exit:
-       up_read(&pci_bus_sem);
-       return dev;
-}
-
 /**
  * pci_get_class - begin or continue searching for a PCI device by class
  * @class: search for a PCI device with this class designation
@@ -451,7 +432,6 @@ EXPORT_SYMBOL(pci_dev_present);
 EXPORT_SYMBOL(pci_find_present);
 
 EXPORT_SYMBOL(pci_find_device);
-EXPORT_SYMBOL(pci_find_device_reverse);
 EXPORT_SYMBOL(pci_find_slot);
 /* For boot time work */
 EXPORT_SYMBOL(pci_find_bus);