diff options
-rw-r--r-- | drivers/pci/search.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 45f2b20ef513..fab381ed853c 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -193,6 +193,18 @@ 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))) { + printk(KERN_INFO "pci_find_subsys() called while pci_devices " + "is still empty\n"); + return NULL; + } down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next; @@ -259,6 +271,18 @@ 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))) { + printk(KERN_NOTICE "pci_get_subsys() called while pci_devices " + "is still empty\n"); + return NULL; + } down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next; |