diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_osm_pci.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index c62ce41f279..66f0259edb6 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -50,6 +50,8 @@ static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, u_long *bus_addr, uint8_t __iomem **maddr); +static int ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg); +static int ahd_linux_pci_dev_resume(struct pci_dev *pdev); static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); /* Define the macro locally since it's different for different class of chips. @@ -86,10 +88,58 @@ MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); static struct pci_driver aic79xx_pci_driver = { .name = "aic79xx", .probe = ahd_linux_pci_dev_probe, +#ifdef CONFIG_PM + .suspend = ahd_linux_pci_dev_suspend, + .resume = ahd_linux_pci_dev_resume, +#endif .remove = ahd_linux_pci_dev_remove, .id_table = ahd_linux_pci_id_table }; +static int +ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ahd_softc *ahd = pci_get_drvdata(pdev); + int rc; + + if ((rc = ahd_suspend(ahd))) + return rc; + + ahd_pci_suspend(ahd); + + pci_save_state(pdev); + pci_disable_device(pdev); + + if (mesg.event == PM_EVENT_SUSPEND) + pci_set_power_state(pdev, PCI_D3hot); + + return rc; +} + +static int +ahd_linux_pci_dev_resume(struct pci_dev *pdev) +{ + struct ahd_softc *ahd = pci_get_drvdata(pdev); + int rc; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if ((rc = pci_enable_device(pdev))) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to enable device after resume (%d)\n", rc); + return rc; + } + + pci_set_master(pdev); + + ahd_pci_resume(ahd); + + ahd_resume(ahd); + + return rc; +} + static void ahd_linux_pci_dev_remove(struct pci_dev *pdev) { |