diff options
-rw-r--r-- | drivers/pci/pci-driver.c | 3 | ||||
-rw-r--r-- | drivers/pci/pci.c | 41 | ||||
-rw-r--r-- | drivers/pci/pci.h | 1 |
3 files changed, 34 insertions, 11 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 1ec546d3d53c..dd2da9b6b119 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -324,8 +324,7 @@ static int pci_default_resume(struct pci_dev *pci_dev) | |||
324 | /* restore the PCI config space */ | 324 | /* restore the PCI config space */ |
325 | pci_restore_state(pci_dev); | 325 | pci_restore_state(pci_dev); |
326 | /* if the device was enabled before suspend, reenable */ | 326 | /* if the device was enabled before suspend, reenable */ |
327 | if (atomic_read(&pci_dev->enable_cnt)) | 327 | retval = __pci_reenable_device(pci_dev); |
328 | retval = pci_enable_device(pci_dev); | ||
329 | /* if the device was busmaster before the suspend, make it busmaster again */ | 328 | /* if the device was busmaster before the suspend, make it busmaster again */ |
330 | if (pci_dev->is_busmaster) | 329 | if (pci_dev->is_busmaster) |
331 | pci_set_master(pci_dev); | 330 | pci_set_master(pci_dev); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 212acd2e1a84..287b685aaa5c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -676,6 +676,36 @@ pci_restore_state(struct pci_dev *dev) | |||
676 | return 0; | 676 | return 0; |
677 | } | 677 | } |
678 | 678 | ||
679 | static int do_pci_enable_device(struct pci_dev *dev, int bars) | ||
680 | { | ||
681 | int err; | ||
682 | |||
683 | err = pci_set_power_state(dev, PCI_D0); | ||
684 | if (err < 0 && err != -EIO) | ||
685 | return err; | ||
686 | err = pcibios_enable_device(dev, bars); | ||
687 | if (err < 0) | ||
688 | return err; | ||
689 | pci_fixup_device(pci_fixup_enable, dev); | ||
690 | |||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * __pci_reenable_device - Resume abandoned device | ||
696 | * @dev: PCI device to be resumed | ||
697 | * | ||
698 | * Note this function is a backend of pci_default_resume and is not supposed | ||
699 | * to be called by normal code, write proper resume handler and use it instead. | ||
700 | */ | ||
701 | int | ||
702 | __pci_reenable_device(struct pci_dev *dev) | ||
703 | { | ||
704 | if (atomic_read(&dev->enable_cnt)) | ||
705 | return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1); | ||
706 | return 0; | ||
707 | } | ||
708 | |||
679 | /** | 709 | /** |
680 | * pci_enable_device_bars - Initialize some of a device for use | 710 | * pci_enable_device_bars - Initialize some of a device for use |
681 | * @dev: PCI device to be initialized | 711 | * @dev: PCI device to be initialized |
@@ -693,16 +723,9 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) | |||
693 | if (atomic_add_return(1, &dev->enable_cnt) > 1) | 723 | if (atomic_add_return(1, &dev->enable_cnt) > 1) |
694 | return 0; /* already enabled */ | 724 | return 0; /* already enabled */ |
695 | 725 | ||
696 | err = pci_set_power_state(dev, PCI_D0); | 726 | err = do_pci_enable_device(dev, bars); |
697 | if (err < 0 && err != -EIO) | ||
698 | goto err_out; | ||
699 | err = pcibios_enable_device(dev, bars); | ||
700 | if (err < 0) | 727 | if (err < 0) |
701 | goto err_out; | 728 | atomic_dec(&dev->enable_cnt); |
702 | pci_fixup_device(pci_fixup_enable, dev); | ||
703 | |||
704 | err_out: | ||
705 | atomic_dec(&dev->enable_cnt); | ||
706 | return err; | 729 | return err; |
707 | } | 730 | } |
708 | 731 | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 6bf327db5c5e..783e81f81f58 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* Functions internal to the PCI core code */ | 1 | /* Functions internal to the PCI core code */ |
2 | 2 | ||
3 | extern int __must_check __pci_reenable_device(struct pci_dev *); | ||
3 | extern int pci_uevent(struct device *dev, char **envp, int num_envp, | 4 | extern int pci_uevent(struct device *dev, char **envp, int num_envp, |
4 | char *buffer, int buffer_size); | 5 | char *buffer, int buffer_size); |
5 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); | 6 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); |