diff options
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r-- | drivers/pci/pci-driver.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index b1c0c707d96..e5ae3a0c13b 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -265,6 +265,13 @@ static int pci_device_remove(struct device * dev) } /* + * If the device is still on, set the power state as "unknown", + * since it might change by the next time we load the driver. + */ + if (pci_dev->current_state == PCI_D0) + pci_dev->current_state = PCI_UNKNOWN; + + /* * We would love to complain here if pci_dev->is_enabled is set, that * the driver should have called pci_disable_device(), but the * unfortunate fact is there are too many odd BIOS and bridge setups @@ -288,6 +295,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state) suspend_report_result(drv->suspend, i); } else { pci_save_state(pci_dev); + /* + * mark its power state as "unknown", since we don't know if + * e.g. the BIOS will change its device state when we suspend. + */ + if (pci_dev->current_state == PCI_D0) + pci_dev->current_state = PCI_UNKNOWN; } return i; } @@ -316,8 +329,8 @@ static int pci_default_resume(struct pci_dev *pci_dev) /* restore the PCI config space */ pci_restore_state(pci_dev); /* if the device was enabled before suspend, reenable */ - if (pci_dev->is_enabled) - retval = pci_enable_device(pci_dev); + if (atomic_read(&pci_dev->enable_cnt)) + retval = __pci_enable_device(pci_dev); /* if the device was busmaster before the suspend, make it busmaster again */ if (pci_dev->is_busmaster) pci_set_master(pci_dev); @@ -432,9 +445,12 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner) /* register with core */ error = driver_register(&drv->driver); + if (error) + return error; - if (!error) - error = pci_create_newid_file(drv); + error = pci_create_newid_file(drv); + if (error) + driver_unregister(&drv->driver); return error; } |